Creating a color image with NSBitmapImageRep and greyscale data

  • I need to create a color image from greyscale data.  This is because I
    would like to display the image in false color to aid in
    visualization.  I have tried using the CIColorMap core image filter on
    a CIImage created from a 16 bit greyscale NSBitmapImageRep, but this
    does not work (you just get a modified greyscale image, not color).
    Unfortunately, there is nothing in the documentation for CIColorMap
    that says you can only apply this filter to a color image, but I am
    assuming that that is the case.  So, I though I would transform the
    greyscale image data into color RGB data and create a color
    NSBitmapImageRep, but this is not working either.  Here's what I have:

    NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
                   initWithBitmapDataPlanes:NULL
                         pixelsWide:width
                         pixelsHigh:height
                     bitsPerSample:16
                    samplesPerPixel:3
        hasAlpha:NO
        isPlanar:NO
                     colorSpaceName:NSCalibratedRGBColorSpace
                       bitmapFormat:0
                          bytesPerRow:3840
                       bitsPerPixel:48];
    unsigned char *bitmapData = [bitmap bitmapData];
    uint16_t RGBData[921600];
    int pixel, color;
    int numPixels = height*width;
    for (pixel=0; pixel<numPixels; pixel++) {
      for (color=0; color<3; color++) {
      RGBData[pixel+color] = pixels[pixel];
      }
    }
    memcpy(bitmapData, RGBData, [bitmap bytesPerRow] * [bitmap
    pixelsHigh]);

    'pixels' is an array of 16 bit integers that contain the data for the
    16 bit greyscale image that is 640 x 480.  This code actually produces
    a three mini-greyscale images inside the main image.

    Does anyone know hat I'm doing wrong?  Any suggestions for creating a
    color image from greyscale data?

    Thanks!
  • On 27-Nov-07, at 5:38 PM, Jason Horn wrote:

    > I need to create a color image from greyscale data.  This is because
    > I would like to display the image in false color to aid in
    > visualization.  I have tried using the CIColorMap core image filter
    > on a CIImage created from a 16 bit greyscale NSBitmapImageRep, but
    > this does not work (you just get a modified greyscale image, not
    > color).  Unfortunately, there is nothing in the documentation for
    > CIColorMap that says you can only apply this filter to a color
    > image, but I am assuming that that is the case.  So, I though I
    > would transform the greyscale image data into color RGB data and
    > create a color NSBitmapImageRep, but this is not working either.
    > Here's what I have:
    >
    > NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
    > initWithBitmapDataPlanes:NULL
    > pixelsWide:width
    > pixelsHigh:height
    > bitsPerSample:16
    > samplesPerPixel:3
    > hasAlpha:NO
    > isPlanar:NO
    > colorSpaceName:NSCalibratedRGBColorSpace
    > bitmapFormat:0
    > bytesPerRow:3840
    > bitsPerPixel:48];
    > unsigned char *bitmapData = [bitmap bitmapData];
    > uint16_t RGBData[921600];
    > int pixel, color;
    > int numPixels = height*width;
    > for (pixel=0; pixel<numPixels; pixel++) {
    > for (color=0; color<3; color++) {
    > RGBData[pixel+color] = pixels[pixel];

    The preceding line sets the r, g and b components uniformly for each
    output pixel, so you'll always get grey.  You might try distributing
    each input pixel p across r, g and b along the lines of...

    int bpr = [bitmap bytesPerRow];

    for (int i = 0; i < height; ++i) {
      char *row = bitmapData + i * bpr;
      for (int j = 0; j < width; ++j) {
        uint16_t p = pixels[i * width + j];
        unsigned char *rgb = row + j * 3;
        rgb[0] = p & 0x3f;
        rgb[1] = (p >> 6) & 0x3f;
        rgb[2] = (p >> 12);
      }
    }

    > }
    > }
    > memcpy(bitmapData, RGBData, [bitmap bytesPerRow] * [bitmap
    > pixelsHigh]);

    > 'pixels' is an array of 16 bit integers that contain the data for
    > the 16 bit greyscale image that is 640 x 480.  This code actually
    > produces a three mini-greyscale images inside the main image.
    >
    > Does anyone know hat I'm doing wrong?  Any suggestions for creating
    > a color image from greyscale data?
    >
    > Thanks!_______________________________________________

    Cheers,
    dave
  • Sorry,  I meant to also say that an alternative to this quick and
    dirty approach is to consider the input greyscale value as the hue
    component of an HSB (or related) colorspace and perform a standard
    conversion from HSB to RGB (using a fixed saturation and brightness).

    dave

    On 27-Nov-07, at 8:34 PM, David Spooner wrote:

    > The preceding line sets the r, g and b components uniformly for each
    > output pixel, so you'll always get grey.  You might try distributing
    > each input pixel p across r, g and b along the lines of...
    >
    > int bpr = [bitmap bytesPerRow];
    >
    > for (int i = 0; i < height; ++i) {
    > char *row = bitmapData + i * bpr;
    > for (int j = 0; j < width; ++j) {
    > uint16_t p = pixels[i * width + j];
    > unsigned char *rgb = row + j * 3;
    > rgb[0] = p & 0x3f;
    > rgb[1] = (p >> 6) & 0x3f;
    > rgb[2] = (p >> 12);
    > }
    > }
  • Thanks Dave,

    I was aware that the code I gave will still give a grey image.  The
    problem is that the image is also munged somehow.  the resulting image
    was actually a mosaic of three separate grey images within the borders
    of the main image,with the rest of the space being black.  Also, the
    reason that I was attempting this was in hopes that, even though
    technically still grey, CIColorMap would treat the image differently,
    and yield a color image.

    On Nov 27, 2007, at 10:55 PM, David Spooner wrote:

    >
    > Sorry,  I meant to also say that an alternative to this quick and
    > dirty approach is to consider the input greyscale value as the hue
    > component of an HSB (or related) colorspace and perform a standard
    > conversion from HSB to RGB (using a fixed saturation and brightness).
    >
    > dave
    >
    > On 27-Nov-07, at 8:34 PM, David Spooner wrote:
    >
    >> The preceding line sets the r, g and b components uniformly for
    >> each output pixel, so you'll always get grey.  You might try
    >> distributing each input pixel p across r, g and b along the lines
    >> of...
    >>
    >> int bpr = [bitmap bytesPerRow];
    >>
    >> for (int i = 0; i < height; ++i) {
    >> char *row = bitmapData + i * bpr;
    >> for (int j = 0; j < width; ++j) {
    >> uint16_t p = pixels[i * width + j];
    >> unsigned char *rgb = row + j * 3;
    >> rgb[0] = p & 0x3f;
    >> rgb[1] = (p >> 6) & 0x3f;
    >> rgb[2] = (p >> 12);
    >> }
    >> }

  • Dave,

    Actually, there was a bug in my code.  That loop should have been:

    for (pixel=0; pixel<numPixels; pixel++) {
      RGBData[RGBpixel] = pixels[pixel];
      RGBData[RGBpixel+1] = pixels[pixel];
      RGBData[RGBpixel+2] = pixels[pixel];
      RGBpixel += 3;
    }

    So, now I have a color image (that is grey), but CIColorMap still does
    not produce a color image.  Perhaps I don't understand how CIColorMap
    works.

    On Nov 27, 2007, at 10:55 PM, David Spooner wrote:

    >
    > Sorry,  I meant to also say that an alternative to this quick and
    > dirty approach is to consider the input greyscale value as the hue
    > component of an HSB (or related) colorspace and perform a standard
    > conversion from HSB to RGB (using a fixed saturation and brightness).
    >
    > dave
    >
    > On 27-Nov-07, at 8:34 PM, David Spooner wrote:
    >
    >> The preceding line sets the r, g and b components uniformly for
    >> each output pixel, so you'll always get grey.  You might try
    >> distributing each input pixel p across r, g and b along the lines
    >> of...
    >>
    >> int bpr = [bitmap bytesPerRow];
    >>
    >> for (int i = 0; i < height; ++i) {
    >> char *row = bitmapData + i * bpr;
    >> for (int j = 0; j < width; ++j) {
    >> uint16_t p = pixels[i * width + j];
    >> unsigned char *rgb = row + j * 3;
    >> rgb[0] = p & 0x3f;
    >> rgb[1] = (p >> 6) & 0x3f;
    >> rgb[2] = (p >> 12);
    >> }
    >> }

  • Yes, the documentation for the CIColorMap filter is somewhat vague.
    There is a posting on the quartz-dev list which points to an example
    usage in the Core Imager Fun House application and states that the
    gradient image (2nd argument) is a 1xN lookup table mapping greyscale
    values (appropriately scaled?) to rgb values...

    dave

    On 27-Nov-07, at 9:37 PM, Jason Horn wrote:

    > Dave,
    >
    > Actually, there was a bug in my code.  That loop should have been:
    >
    > for (pixel=0; pixel<numPixels; pixel++) {
    > RGBData[RGBpixel] = pixels[pixel];
    > RGBData[RGBpixel+1] = pixels[pixel];
    > RGBData[RGBpixel+2] = pixels[pixel];
    > RGBpixel += 3;
    > }
    >
    > So, now I have a color image (that is grey), but CIColorMap still
    > does not produce a color image.  Perhaps I don't understand how
    > CIColorMap works.
    >
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