GDI+ and 16-bit grayscale images

I'm trying load a 16-bit grayscale image into a Bitmap object of GDI+.
My input is a BYTE array containing the raw image data. I create the Bitmap object by mean of the following code:

Bitmap * outputImg = new Bitmap(columns, rows, (columns*2), PixelFormat16bppGrayScale, pixelBuffer);

The problem is that when I try to display or print this image, it is always ALL WHITE. I also tried to fill pixelBuffer with fixed values, in order to be sure that the actual pixel values did not represent WHITE pixels, but nothing changed.

I think there is some problem with the "PixelFormat16bppGrayScale" format, since everything works fine with other formats (for instance, PixelFormat24bppRGB).

BTW, the only way of creating an 8-bit GDI+ grayscale image (starting from a raw BYTE buffer) is to convert it to an 8-bit-per-channel RGB image?

Any help/suggestion would be greatly appreciated.

Regards,

Marco.
[970 byte] By [micu] at [2007-11-18 3:49:00]
# 1 Re: GDI+ and 16-bit grayscale images
I am not sure that I can help you, since I use GDI++ through CImage class which doesn't support 16 bit. However, I read this:
--------------
Remarks
PixelFormat48bppRGB, PixelFormat64bppARGB, and PixelFormat64bppPARGB use 16 bits per color component (channel). GDI+ version 1.0 can read 16-bits-per-channel images, but such images are converted to an 8-bits-per-channel format for processing, displaying, and saving.
--------------

White should be 65535 but maybe there is no automatic conversion from [0,65535] to [0,255] for display and printing. As an experiment, try loading the bitmap with values 0, 128, and 255 and see whether it displays properly.
aruzinsky at 2007-11-11 3:39:37 >
# 2 Re: GDI+ and 16-bit grayscale images
First of all, thanks for your answer.
I report below the entire test code I'm using:

***********************************
const int imageHeight = 512;
const int imageWidth = 512;

// ---- 16-bit Grayscale test ----
BYTE pixelBuffer[imageHeight * imageWidth * 2];
unsigned short constPixelVal = 0;
unsigned int offset = 0;

for (int i = 0; i < (imageHeight * imageWidth); i++)
{
// Should I store the 16-bit value as Big Endian ?
pixelBuffer[offset++] = (constPixelVal >> 8) & 0x00FF;
pixelBuffer[offset++] = (constPixelVal & 0x00FF);
}

Bitmap myBitmap(imageWidth, imageHeight, (imageWidth * 2), PixelFormat16bppGrayScale, pixelBuffer);
// --------------

graphics.DrawImage(&myBitmap, 0, 0);
***********************************

Whatever value I give to "constPixelVal", my image is displayed as ALL-WHITE.
If I try a similar sample code, but with pixel format "PixelFormat24bppRGB", everything is displayed properly.

Any help / suggestion?

Thanks a lot.

Marco.
micu at 2007-11-11 3:40:31 >
# 3 Re: GDI+ and 16-bit grayscale images
As I explained, I am not familiar with the GDI+ functions because I use MFC class CImage which encapsulates GDI+ functions. However, I have written image processing programs for 48 bit color and I would not do things your way even if I did use GDI+ directly.

First, I don't understand why you have a BYTE buffer instead of an unsigned short int buffer and why you want to screw around big versus little endian values.

Second, I don't know why you want to use a 16 bit bitmap unless you have separate code for reading, processing, and writing 16 bit image files. Again, I call your attention to "but such images are converted to an 8-bits-per-channel format for processing, displaying, and saving."

This implies that there is little point in NOT doing the conversion yourself before displaying on a monitor or printing. I would do my processing in an unsigned short int buffer and then transfer to an 8 bit bitmap for displaying on a monitor or printing.

Often it is easier to reinvent the wheel than follow instructions for someone else's wheel.
aruzinsky at 2007-11-11 3:41:36 >
# 4 Re: GDI+ and 16-bit grayscale images
Thanks again for your answer.

I try to clarify a little bit my needs: first of all, I would like to work with 16-bit Bitmaps because I have input images that are 16-bit-per-pixel grayscale.

I'm using a BYTE buffer and I'm concerned with Big vs. Little endian because the Bitmap constructor requires a BYTE buffer even if you specify "PixelFormat16bppGrayScale" or "PixelFormat48bppRGB", which are 16-bit-per-pixel formats.

I agree with you when you say that it is convenient to make the convertion to 8-bit-per-pixel myself, given that it would be performed anyway before displaying or printing. The only point that leaves me some doubts is that the "Remarks" you quoted in your previous message only talks about PixelFormat48bppRGB, PixelFormat64bppARGB, and PixelFormat64bppPARGB, but it doesn't say anything about PixelFormat16bppGrayScale... Probably it is the same also for this format...

Thanks again,

Marco.
micu at 2007-11-11 3:42:40 >
# 5 Re: GDI+ and 16-bit grayscale images
I just tried using CImage::Load to read 8 bit greyscale JPEG and TIFF image files (which were not blank). In both cases, the bitmaps were filled with zeros.
aruzinsky at 2007-11-11 3:43:36 >