Click here to Skip to main content
15,867,308 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I'm trying to draw a grayscales image of type 48bppRBG pixel format.
I have an array/list of ushort values. These values are the pixels values. So each color(R, G ans B) will have the same pixel value, since it's a grayscale image. In an 24bpp type, these values are scanned then converted to <b>byte </b> then assigned to the bitmap image.

My question is how can I scan these values (using Scan0 and Stride), of type ushort,and draw an image of 48bppRBG?
Posted
Comments
BillWoodruff 1-Dec-13 4:13am    
You might start by reviewing if GDI+ color facilities are really adequate for 48bpp work: try this CodeProject article:

http://www.codeproject.com/Articles/482727/GDIplus-Deep-Color-Workaround

And:

http://stackoverflow.com/questions/15301890/how-can-i-load-the-raw-data-of-a-48bpp-image-into-a-bitmap

http://stackoverflow.com/questions/7276212/reading-preserving-a-pixelformat-format48bpprgb-png-bitmap-in-net

A question I would ask is whether you really need 48bpp for grey-scale images, given the limitations of most eyeballs, and monitors, but don't let that stop you :)

good luck !

First some background:

You wrote:

"In an 24bpp type, these values are scanned then converted to byte then assigned to the bitmap image."

Every scanner I have seen in a previous job, which included scanners by Canon, HP, Konica Minolta, Toshiba, and more, all scanned color images that were subsequently converted to grayscale images with a grayscale palette.

The conversion is:

GrayColor = 0.299 Red + 0.587 Green + 0.114 Blue.

(Note that 0.299 + 0.587 + 0.114) add up to 1.0).

For the BMP image format, the GrayColor value would be used an index into a color palette associated with the BMP image format, where each (RGB) color in the palette has the same R, G, and B value, and each of these values at a particular index is the same value as the index.

In other words, Grayscale is implemented as a color image with a color palette, just all the colors in the palette are grayscale colors. The colors, in order, and skipping most central colors, are (0, 0, 0), (1, 1, 1), (2, 2, 2,), ... (254, 254, 254), (255, 255, 255).

------------------------------------------------------------

In the case you pose, you can create a BMP image with a palette that has 65536 RGB entries that range from (0, 0, 0) to (65535, 65535, 65535). Then each color entry would be a 16-bit index into the palette. Microsoft supports this image format. I don't know if this is supported in C#, but it would be easy to check that.

.NET 4.5 (and earlier versions?) provides an easy way to make a 16-bit palette - see:

http://msdn.microsoft.com/en-us/library/system.drawing.graphics.gethalftonepalette%28v=vs.110%29.aspx

However, WPF will only display values in the range of 0 to 255 regardless of the source. So, you can store the image data in high-resolution, but I do not know how to view the image at full luminance resolution.

Like Bill Woodruff, I question the need for that amount of luminance precision in an image. Most advanced sensors in scanners typically produce 12-bits or less of color accuracy, so 16 bits is probably overkill. Most displays don't allows rendering such fine shade differences, and even if they did, I don't think adjacent colors in the palette would be discernably different to the human eye. However, your case might be unique - but if it isn't, I'd go with an 8-bit palettized image - that format takes up a lot less space.


To write the code you want, find the standard 8-bit grayscale case and convert the values to 16-bit. The palette will go from being 256 32-bit RGB values (one byte is unused) to a palette of 65536 32-bit RGB values. (Palette entries are always 32-bit in the BMP image format - the most significant byte can be set to 0 - or ignored. Then change the byte value to be short values and adjust all the loop indexing accordingly. I hope that helps.
 
Share this answer
 
v3
Comments
BillWoodruff 1-Dec-13 20:26pm    
+5 Excellent answer !
Afnan_ 2-Dec-13 0:36am    
First, thank you and BillWoodfuff for your replies.
I totally understand the "grayscale" concept and regarding the first part of your answer, what I meant by "scanned" as in read from the BMP.

I agree that 16 bits is overkill and that's what I'm trying to explain to my client but he is insisting on first displaying it as a 16-bit (48bpp) then convert it to a 8-bit.
I've succeeded in converting it to 8-bit but now I want to draw it as 16-bit (48bpp).

In the last part of your answer, you said that "entries are always 32-bit in the BMP image format" you mean BMP doesn't support 48-bit? How can I know what number of bits supported in each image type( jpg, png ...etc?
Afnan_ 2-Dec-13 0:48am    
This is a snapshot of the code, that I'm having a problem with:
Note:
pixels16 is of type List<ushort>

private void CreateBitmap()
{
bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format48bppRgb);
BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, width, height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

// This 'unsafe' part of the code populates the bitmap bmp with data stored in pixel16.
// It does so using pointers, and therefore the need for 'unsafe'.
unsafe
{
int pixelSize = 3;
int i, j, j1, i1;
ushort b;
ushort sVal;
double lPixval;

for (i = 0; i < bmd.Height; ++i)
{
ushort* row = (ushort*)bmd.Scan0 + (i * bmd.Stride);
i1 = i * bmd.Height;

for (j = 0; j < bmd.Width; ++j)
{
sVal = (ushort)(pixels16[i1 + j]);

b = (ushort)(sVal);
j1 = j * pixelSize;
row[j1] = b; // Red
row[j1 + 1] = b; // Green
row[j1 + 2] = b; // Blue
}
}
}
bmp.UnlockBits(bmd);
}
The 32-bit entries mentioned are for pallete entries for images that take a palette.

Because you are specifying Red, Green, and Blue separately for each pixel, you don't need a pallete.

I don't know if the BMP format, which is a file format (BITMAPINFO structure in C++) supports more than 32 bits-per-pixel. If C# has a PixelFormat.Format48bppRgb format, then it must support that image format - this is probably for images taken with modern cameras that have more than 8 bits per color component.

However, WPF, and the vast majority of graphics cards (all of them?) don't support more than 16,777,216 colors, that is 24-bit color with 8-bit color components.

-------------------------------------------

I have a question for you. You stated what you are trying to do, but you didn't state what wasn't working. Does anything display? Does the program crash? What happens?

Did you try what is at the link in Bill Woodruff's message?
 
Share this answer
 
v5

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900