Create NSImage from array of integers

  • I need some help creating an NSBitmapImageRep or an NSImage from a
    proprietary file. I have figured out how to load the data from the
    file into an array of integers.  I'm not sure what to do from there.
    The image is a greyscale image with 16 bit integers (unsigned int).
    Separately, I have the dimensions of the image (640 x 480).

    Any thoughts?

    Thanks,

    - Jason
  • Hi Jason,

    This is a job for Quartz i believe.

    If you know the exact pixel layout and such I'd think you could create a bitmap context and then get the image from that;

            void* bitmapData = load your array of ints;
            CGContextRef context = CGBitmapContextCreate(bitmapData, size.width, size.height, bitsPerComponent,  bytesPerRow, CGColorSpaceCreateWithName(kCGColorSpaceGenericGray), kCGImageAlphaNone);
            image = CGBitmapContextCreateImage(context);

    I think this will work. You might have to tweak some of the args to the context create to get it to draw properly.

    Good Luck,

    -bd-
    http://bill.dudney.net/roller/objc

    On Wednesday, October 31, 2007, at 03:13PM, "Jason Horn" <jason...> wrote:
    > I need some help creating an NSBitmapImageRep or an NSImage from a
    > proprietary file. I have figured out how to load the data from the
    > file into an array of integers.  I'm not sure what to do from there.
    > The image is a greyscale image with 16 bit integers (unsigned int).
    > Separately, I have the dimensions of the image (640 x 480).
    >
    > Any thoughts?
    >
    > Thanks,
    >
    > - Jason
    >
    >
  • Wouldn't a more direct approach be to create an NSBitmapImageRep from
    the bitmapData using -initWithBitmapDataPlanes:... and then use
    NSImage -initWithSize: and -addRepresentation:?

    dave

    On 31-Oct-07, at 4:14 PM, Bill Dudney wrote:

    > Hi Jason,
    >
    > This is a job for Quartz i believe.
    >
    > If you know the exact pixel layout and such I'd think you could
    > create a bitmap context and then get the image from that;
    >
    > void* bitmapData = load your array of ints;
    > CGContextRef context = CGBitmapContextCreate(bitmapData,
    > size.width, size.height, bitsPerComponent,  bytesPerRow,
    > CGColorSpaceCreateWithName(kCGColorSpaceGenericGray),
    > kCGImageAlphaNone);
    > image = CGBitmapContextCreateImage(context);
    >
    > I think this will work. You might have to tweak some of the args to
    > the context create to get it to draw properly.
    >
    > Good Luck,
    >
    > -bd-
    > http://bill.dudney.net/roller/objc
    >
    > On Wednesday, October 31, 2007, at 03:13PM, "Jason Horn" <jason...>
    >> wrote:
    >> I need some help creating an NSBitmapImageRep or an NSImage from a
    >> proprietary file. I have figured out how to load the data from the
    >> file into an array of integers.  I'm not sure what to do from there.
    >> The image is a greyscale image with 16 bit integers (unsigned int).
    >> Separately, I have the dimensions of the image (640 x 480).
    >>
    >> Any thoughts?
    >>
    >> Thanks,
    >>
    >> - Jason
    >>
    >>

    >
  • Yes, NSBitmapImageRep supports this pixel data format as well, so one
    could create an NSBitmapImageRep directly:

            unsigned char *planes[1];
            planes[0] = (unsigned char *)bitmapData;
            NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
    initWithBitmapDataPlanes:planes pixelsWide:pixelsWide
    pixelsHigh:pixelsHigh bitsPerSample:16 samplesPerPixel:1 hasAlpha:NO
    isPlanar:NO colorSpaceName:NSCalibratedWhiteColorSpace bitmapFormat:0
    bytesPerRow:0 bitsPerPixel:0];

    Note that this creates an NSBitmapImageRep instance that references
    the "bitmapData" you've pointed it to, but has no way to insure that
    the data sticks around.  So you must either insure that the bitmapData
    pointer remains valid for the lifetime of the NSBitmapImageRep (i.e.
    don't free or reuse the bitmapData buffer), or, if that's
    inconvenient, you can pass NULL for the "planes" parameter to the
    NSBItmapImageRep initializer to let the NSBitmapImageRep allocate its
    own buffer, then you can get a pointer to that buffer using the "-
    bitmapData" method and copy your pixel data into it.

    In any case, if you then need to wrap the NSBitmapImageRep in an
    NSImage for handoff to other API, that's simple too:

                image = [[NSImage alloc] initWithSize:[bitmap size]];
                [image addRepresentation:bitmap];

    Troy

    --
    Troy Stephens
    Cocoa Frameworks
    Apple, Inc.

    On Oct 31, 2007, at 4:16 PM, David Spooner wrote:

    >
    > Wouldn't a more direct approach be to create an NSBitmapImageRep
    > from the bitmapData using -initWithBitmapDataPlanes:... and then use
    > NSImage -initWithSize: and -addRepresentation:?
    >
    > dave
    >
    >
    > On 31-Oct-07, at 4:14 PM, Bill Dudney wrote:
    >
    >> Hi Jason,
    >>
    >> This is a job for Quartz i believe.
    >>
    >> If you know the exact pixel layout and such I'd think you could
    >> create a bitmap context and then get the image from that;
    >>
    >> void* bitmapData = load your array of ints;
    >> CGContextRef context = CGBitmapContextCreate(bitmapData,
    >> size.width, size.height, bitsPerComponent,  bytesPerRow,
    >> CGColorSpaceCreateWithName(kCGColorSpaceGenericGray),
    >> kCGImageAlphaNone);
    >> image = CGBitmapContextCreateImage(context);
    >>
    >> I think this will work. You might have to tweak some of the args to
    >> the context create to get it to draw properly.
    >>
    >> Good Luck,
    >>
    >> -bd-
    >> http://bill.dudney.net/roller/objc
    >>
    >> On Wednesday, October 31, 2007, at 03:13PM, "Jason Horn" <jason...>
    >>> wrote:
    >>> I need some help creating an NSBitmapImageRep or an NSImage from a
    >>> proprietary file. I have figured out how to load the data from the
    >>> file into an array of integers.  I'm not sure what to do from there.
    >>> The image is a greyscale image with 16 bit integers (unsigned int).
    >>> Separately, I have the dimensions of the image (640 x 480).
    >>>
    >>> Any thoughts?
    >>>
    >>> Thanks,
    >>>
    >>> - Jason
    >>>
    >>>

    >>

  • Thank you Troy for the head start - I'm new to Mac development.  One
    thing I don't understand:  when you call [bitmap bitmapData], what is
    the pointer that it returns pointing to?  How do I fill it with an
    array of ints?

    Thanks,

    - Jason

    On Oct 31, 2007, at 7:29 PM, Troy Stephens wrote:

    > Yes, NSBitmapImageRep supports this pixel data format as well, so
    > one could create an NSBitmapImageRep directly:
    >
    > unsigned char *planes[1];
    > planes[0] = (unsigned char *)bitmapData;
    > NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
    > initWithBitmapDataPlanes:planes pixelsWide:pixelsWide
    > pixelsHigh:pixelsHigh bitsPerSample:16 samplesPerPixel:1 hasAlpha:NO
    > isPlanar:NO colorSpaceName:NSCalibratedWhiteColorSpace bitmapFormat:
    > 0 bytesPerRow:0 bitsPerPixel:0];
    >
    > Note that this creates an NSBitmapImageRep instance that references
    > the "bitmapData" you've pointed it to, but has no way to insure that
    > the data sticks around.  So you must either insure that the
    > bitmapData pointer remains valid for the lifetime of the
    > NSBitmapImageRep (i.e. don't free or reuse the bitmapData buffer),
    > or, if that's inconvenient, you can pass NULL for the "planes"
    > parameter to the NSBItmapImageRep initializer to let the
    > NSBitmapImageRep allocate its own buffer, then you can get a pointer
    > to that buffer using the "-bitmapData" method and copy your pixel
    > data into it.
    >
    > In any case, if you then need to wrap the NSBitmapImageRep in an
    > NSImage for handoff to other API, that's simple too:
    >
    > image = [[NSImage alloc] initWithSize:[bitmap size]];
    > [image addRepresentation:bitmap];
    >
    > Troy
    >
    >
    > --
    > Troy Stephens
    > Cocoa Frameworks
    > Apple, Inc.
    >
    > On Oct 31, 2007, at 4:16 PM, David Spooner wrote:
    >
    >>
    >> Wouldn't a more direct approach be to create an NSBitmapImageRep
    >> from the bitmapData using -initWithBitmapDataPlanes:... and then
    >> use NSImage -initWithSize: and -addRepresentation:?
    >>
    >> dave
    >>
    >>
    >> On 31-Oct-07, at 4:14 PM, Bill Dudney wrote:
    >>
    >>> Hi Jason,
    >>>
    >>> This is a job for Quartz i believe.
    >>>
    >>> If you know the exact pixel layout and such I'd think you could
    >>> create a bitmap context and then get the image from that;
    >>>
    >>> void* bitmapData = load your array of ints;
    >>> CGContextRef context = CGBitmapContextCreate(bitmapData,
    >>> size.width, size.height, bitsPerComponent,  bytesPerRow,
    >>> CGColorSpaceCreateWithName(kCGColorSpaceGenericGray),
    >>> kCGImageAlphaNone);
    >>> image = CGBitmapContextCreateImage(context);
    >>>
    >>> I think this will work. You might have to tweak some of the args
    >>> to the context create to get it to draw properly.
    >>>
    >>> Good Luck,
    >>>
    >>> -bd-
    >>> http://bill.dudney.net/roller/objc
    >>>
    >>> On Wednesday, October 31, 2007, at 03:13PM, "Jason Horn" <jason...>
    >>>> wrote:
    >>>> I need some help creating an NSBitmapImageRep or an NSImage from a
    >>>> proprietary file. I have figured out how to load the data from the
    >>>> file into an array of integers.  I'm not sure what to do from
    >>>> there.
    >>>> The image is a greyscale image with 16 bit integers (unsigned int).
    >>>> Separately, I have the dimensions of the image (640 x 480).
    >>>>
    >>>> Any thoughts?
    >>>>
    >>>> Thanks,
    >>>>
    >>>> - Jason
    >>>>
    >>>>

    >>>

    >
    >
    >
    >
    >
  • On Nov 1, 2007, at 12:38 PM, Jason Horn wrote:
    > Thank you Troy for the head start - I'm new to Mac development.  One
    > thing I don't understand:  when you call [bitmap bitmapData], what
    > is the pointer that it returns pointing to?  How do I fill it with
    > an array of ints?

    The pointer returned from -bitmapData points to the raw pixel data
    (a.k.a. sample data).  This may be a buffer that the NSBitmapImageRep
    allocated itself (if you passed NULL as the first argument to -
    initWithBitmapDataPlanes:...), or the buffer you provided to -
    initWithBitmapDataPlanes:...

    The data is arranged as [bitmapImageRep pixelsHigh] rows of
    [bitmapImageRep bytesPerRow] bytes each.  Each row may contain padding
    on the end for alignment (so bytesPerRow may be slightly greater than
    pixelsWide * bytesPerPixel).  The [bitmapImageRep bitmapFormat] flags
    specify the order and interpretation of the sample values for each
    pixel (position of alpha value, and alpha premultiplied or not, if
    alpha is present, as well as float or integer for the sample values),
    and each row contains data for [bitmapImageRep pixelsWide] pixels,
    packed together left to right.

    This is assuming a nonplanar bitmap by the way ([bitmapImageRep
    isPlanar] == NO).  When dealing with planar bitmap data, you'll need
    to use -getBitmapDataPlanes: instead of -bitmapData to retrieve the
    pointers to the separate planes.

    In your case, you're dealing with 16-bit-per-sample grayscale values,
    so you'd find (or store) the value for a pixel at a given (x,y)
    position like so:

        unsigned char *bitmapData = [bitmapImageRep bitmapData];
        uint16_t *pixel = bitmapData + y * [bitmapImageRep bytesPerRow] +
    2 * x; // (2 bytes per pixel)
        *pixel = 65535; // set pixel to desired value

    If your data is already prepared in a buffer of exactly the same
    layout, you can simply do:

        memcpy(bitmapData, yourBuffer, [bitmapImageRep bytesPerRow] *
    [bitmapImageRep pixelsHigh]);

    If the bitmapImageRep uses different row padding than your buffer,
    however, (i.e. bytesPerRow is different from that for your source
    buffer), you'll need to memcpy the rows one at a time, finding the
    start of each destination row as:

        unsigned char *bitmapData = [bitmapImageRep bitmapData];
        uint16_t *destRow = bitmapData + y * [bitmapImageRep bytesPerRow];

    Troy
previous month october 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 31        
Go to today