Code and Decode a CGContextRef

  • Hi!

    I have an object with a member variable that is a CGContextRef. I'm
    trying to implement the NSCoding protocol in my object. What is the
    best/easiest way to code and decode this CGContextRef?

    Thanks,
    Jason
  • On Nov 27, 2007, at 5:17 AM, Jason Barker wrote:

    > I have an object with a member variable that is a CGContextRef. I'm
    > trying to implement the NSCoding protocol in my object. What is the
    > best/easiest way to code and decode this CGContextRef?

    There isn't one easy way to do it, it depends on how you obtained the
    context in the first place. A bitmap context you would probably encode
    by describing its properties and maybe saving an image from its
    current contents. A PDF context may be described by the PDF data
    itself or a location where the PDF should be saved to. Other kinds of
    contexts are probably best not archived at all.

    What kind of context are you working with and where does it come from?
    Answering that question will probably tell you what you want to know
    to encode it well.
    --
    David Duncan
    Apple DTS Animation and Printing
    <david.duncan...>
  • Uh, could both of you type slower so that I can understand you? :)

    The image data in the CGContextRef is bitmap data. If I save out the
    properties of the context individually, how should I handle the data?
    Can that be converted to an NSData object?

    Thanks,
    Jason

    >
    >> I have an object with a member variable that is a CGContextRef. I'm
    >> trying to implement the NSCoding protocol in my object. What is the
    >> best/easiest way to code and decode this CGContextRef?
    >
    >
    > Don't. CGContextRefs (like NSGraphicsContextes) are, under the scenes,
    > references to IPC communication channels with the graphics
    > infrastructure (I believe). What I know for sure is that they have no
    > support for coding.
    >
    > Recreate a new CGContextRef in initWithCoder: from scratch using the
    > appropriate CGContext... function. If you need the contents of the
    > context, save them as image data (there should be CGImage... functions
    > equivalent to NSImage's -TIFFRepresentation, which returns NSData
    > objects which are encodable).
    >
    > - $B!g(B
    >

    >
    > There isn't one easy way to do it, it depends on how you obtained the
    > context in the first place. A bitmap context you would probably encode
    > by describing its properties and maybe saving an image from its
    > current contents. A PDF context may be described by the PDF data
    > itself or a location where the PDF should be saved to. Other kinds of
    > contexts are probably best not archived at all.
    >
    > What kind of context are you working with and where does it come from?
    > Answering that question will probably tell you what you want to know
    > to encode it well.
    > --
    > David Duncan
  • On 28 Nov 2007, at 05:57, Jason Barker wrote:

    > Uh, could both of you type slower so that I can understand you? :)
    >
    > The image data in the CGContextRef is bitmap data. If I save out the
    > properties of the context individually, how should I handle the data?
    > Can that be converted to an NSData object?

    The CGContextRef isn't a container for bitmap data, it's just a
    reference; a handle, if you will (if you're a Windows programmer, it's
    similar to an HDC; if you're an X11 programmer, it's like a GC).  As
    such, encoding or decoding it doesn't make any sense (in the same way
    that you wouldn't encode or decode a file handle or a socket or
    anything like that).

    However, if the context in question is one of the types that holds
    data of some sort (e.g. a bitmap context holds image data; a PDF
    context holds PDF data) then you could save the data, then in your
    decode routine create a new context with similar properties and load
    the data into it.

    My guess is that you *probably* want to use
    CGBitmapContextCreateImage() to get a CGImageRef, then
    CGImageDestinationCreateWithData() or
    CGImageDestinationCreateWithURL() to turn it into a bitmap file of
    some sort.  I wouldn't go trying to store the data manually (e.g. via
    CGBitmapContextGetData()) since there are a large number of possible
    bitmap formats and supporting all of them in your own code would be
    tedious, not to mention hard to test.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • Actually, I knew that it was a reference and not a "container". I've just
    not done much with C-style functions and structs, and so Quartz makes my
    head swim a bit, trying to change from Objective-C style syntax to C-style
    syntax.

    Anyway, I just wasn't sure if I had to code/decode each property from the
    CGContextRef (width, height, bitsPerComponent, bytesPerRow, dataSize,
    colorspace, data, etc.) or if there was an Objective-C type that could just
    do it all for me.

    With regards to the function CGImageDestinationCreateWithData(), I think I
    understand what to pass in for the last three parameters it takes (namely
    'type', 'count' and 'options') but I don't know how to go from a CGImageRef
    to a CFMutableDataRef. Is this what I'm supposed to do? And then once I have
    a CGImageDestinationRef, how do I code/decode that?

    Thanks for your help,
    Jason

    >

    On Nov 28, 2007 3:43 AM, Alastair Houghton <alastair...>
    wrote:

    > On 28 Nov 2007, at 05:57, Jason Barker wrote:
    >
    >> Uh, could both of you type slower so that I can understand you? :)
    >>
    >> The image data in the CGContextRef is bitmap data. If I save out the
    >> properties of the context individually, how should I handle the data?
    >> Can that be converted to an NSData object?
    >
    > The CGContextRef isn't a container for bitmap data, it's just a
    > reference; a handle, if you will (if you're a Windows programmer, it's
    > similar to an HDC; if you're an X11 programmer, it's like a GC).  As
    > such, encoding or decoding it doesn't make any sense (in the same way
    > that you wouldn't encode or decode a file handle or a socket or
    > anything like that).
    >
    > However, if the context in question is one of the types that holds
    > data of some sort (e.g. a bitmap context holds image data; a PDF
    > context holds PDF data) then you could save the data, then in your
    > decode routine create a new context with similar properties and load
    > the data into it.
    >
    > My guess is that you *probably* want to use
    > CGBitmapContextCreateImage() to get a CGImageRef, then
    > CGImageDestinationCreateWithData() or
    > CGImageDestinationCreateWithURL() to turn it into a bitmap file of
    > some sort.  I wouldn't go trying to store the data manually (e.g. via
    > CGBitmapContextGetData()) since there are a large number of possible
    > bitmap formats and supporting all of them in your own code would be
    > tedious, not to mention hard to test.
    >
    > Kind regards,
    >
    > Alastair.
    >
    > --
    > http://alastairs-place.net
    >
    >
    >
  • On 28 Nov 2007, at 16:57, Jason Barker wrote:

    > Anyway, I just wasn't sure if I had to code/decode each property
    > from the CGContextRef (width, height, bitsPerComponent, bytesPerRow,
    > dataSize, colorspace, data, etc.) or if there was an Objective-C
    > type that could just do it all for me.

    No no, that's the crazy way to do it :-)... essentially you'd be
    inventing your own binary image file format.  Since there are a number
    of good ones already, and since many of them are supported by the
    system, you might as well use one of those.

    > With regards to the function CGImageDestinationCreateWithData(), I
    > think I understand what to pass in for the last three parameters it
    > takes (namely 'type', 'count' and 'options') but I don't know how to
    > go from a CGImageRef to a CFMutableDataRef. Is this what I'm
    > supposed to do? And then once I have a CGImageDestinationRef, how do
    > I code/decode that?

    The steps are as follows:

    1. Use CGBitmapContextCreateImage() to create a CGImage.

    2. Create an NSMutableData object.  (NSMutableData is toll-free
    bridged to CFMutableData, so you can pass an NSMutableData pointer
    everywhere you see a CFMutableDataRef argument.  Many of the CFxxx
    types that have equivalents with similar NSxxx names are toll-free
    bridged; it usually notes this fact in the documentation for both
    types.)

    3. Create a CGImageDestination using
    CGImageDestinationCreateWithData().  For instance:

        NSMutableData *data = [NSMutableData data];
        CGImageDestinationRef myDestination;

        myDestination = CGImageDestinationCreateWithData
    ((CFMutableDataRef)data,

    CFSTR("public.tiff"), 1, NULL);

    (You could pass an NSString instead of using CFSTR, but you'd have to
    cast to CFStringRef)

    4. Add the image to the image destination using
    CGImageDestinationAddImage().  You can release the CGImage at this
    point.

    5. Call CGImageDestinationFinalize() to make Quartz generate the
    data.  You can then release the CGImageDestination.

    6. The NSMutableData object you created now contains image data in the
    format you chose.  If you used the code above, that means it contains
    a TIFF format image.

    Note that, if you're saving your data in a bundled format, you may
    prefer to save the data into a separate file in the bundle and then to
    save a reference to that file in your normal data file.  Depending on
    how you're storing your other data, this can avoid various performance
    and/or memory usage problems.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • Le 28 nov. 07 à 17:57, Jason Barker a écrit :

    > Actually, I knew that it was a reference and not a "container".
    > I've just
    > not done much with C-style functions and structs, and so Quartz
    > makes my
    > head swim a bit, trying to change from Objective-C style syntax to
    > C-style
    > syntax.
    >
    > Anyway, I just wasn't sure if I had to code/decode each property
    > from the
    > CGContextRef (width, height, bitsPerComponent, bytesPerRow, dataSize,
    > colorspace, data, etc.) or if there was an Objective-C type that
    > could just
    > do it all for me.
    >
    > With regards to the function CGImageDestinationCreateWithData(), I
    > think I
    > understand what to pass in for the last three parameters it takes
    > (namely
    > 'type', 'count' and 'options') but I don't know how to go from a
    > CGImageRef
    > to a CFMutableDataRef. Is this what I'm supposed to do? And then
    > once I have
    > a CGImageDestinationRef, how do I code/decode that?
    >
    > Thanks for your help,
    > Jason

    The CFMutableDataRef is the destination buffer where it will store
    your image data.
    NSMutableData *imgData = [NSMutableData data];
    CGImageDestinationRef dest = CGImageDestinationCreateWithData
    (imgData, ...);
    CGImageDestinationAddImage(dest, myCGImageRef, NULL);
    CGImageDestinationFinalize(dest);
    CFRelease(dest);

    Now, imgData should contains your image data and you can encode it.

    Your image can contains a lots of properties (width, height,
    resolution, colorspace, etc...) so you don't have to archive
    additional meta-data.

    To restore the context, you probably can use CGImageSource to create
    a CGImageRef, creating your context as needed, and then draw the
    image on your new context.
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today