views:

661

answers:

3

So here are the details (I am using C# BTW):

I receive a 32bpp image (JPEG compressed) from a server. At some point, I would like to use the Palette property of a bitmap to color over-saturated pixels (brightness > 240) red. To do so, I need to get the image into an indexed format.

I have tried converting the image to a GIF, but I get quality loss. I have tried creating a new bitmap in an index format by these methods:

// causes a "Parameter not valid" error
Bitmap indexed = new Bitmap(orig.Width, orig.Height, PixelFormat.Indexed)

// no error, but the resulting image is black due to information loss I assume
Bitmap indexed = new Bitmap(orig.Width, orig.Height, PixelFormat.Format8bppIndexed)

I am at a loss now. The data in this image is changed constantly by the user, so I don't want to manually set pixels that have a brightness > 240 if I can avoid it. If I can set the palette once when the image is created, my work is done. If I am going about this the wrong way to begin with please let me know.

EDIT: Thanks guys, here is some more detail on what I am attempting to accomplish.

We are scanning a tissue slide at high resolution (pathology application). I write the interface to the actual scanner. We use a line-scan camera. To test the line rate of the camera, the user scans a very small portion and looks at the image.

The image is displayed next to a track bar. When the user moves the track bar (adjusting line rate), I change the overall intensity of the image in an attempt to model what it would look like at the new line rate. I do this using an ImageAttributes and ColorMatrix object currently.

When the user adjusts the track bar, I adjust the matrix. This does not give me per pixel information, but the performance is very nice. I could use LockBits and some unsafe code here, but I would rather not rewrite it if possible. When the new image is created, I would like for all pixels with a brightness value of > 240 to be colored red. I was thinking that defining a palette for the bitmap up front would be a clean way of doing this.

A: 

Sounds like something you could do easily with a pixel shader. Even very early shader models would support something as easy as this.

The question is however:

Can you include shader support in your application without too much hastle?

Do you know shader programming?

EDIT:

You probably don't have a 3D context where you can do stuff like this =/

I was mostly just airing my thoughts.

Manipulating the picture pixel by pixel should be doable in real-time with a single CPU shouldn't it?

If not, look into GPGPU programming and Open CL.

EDIT AGAIN:

If you gave some more details about what the app actually does we might help a bit more? For example, if you're making a web-app none of my tips would make sense.

Nailer
Thanks, but I think that would be more effort than it is worth for this. I *could* loop through the image pixel by pixel, but I am afraid of performance issues when the user changes the line rate quickly. I added some more detail.
Ed Swangren
+1  A: 

Going from 32bpp to 8bpp indexed will almost always result in quality loss, unless the original image has less than 256 colors total.

Can you create another image that is a overlay with the affected pixels red, then show both of those?

Since you are going for brightness > 240, you can convert the overlay to grayscale first, then to indexed to get the overbright pixels.

You don't specify what you are doing with it once you have tagged the offenders, so I don't know if that will work.

Moose
O.P. says the image starts out as grayscale, so it will be R=G=B already, and fit into 256 colors.
Mark Ransom
I added some more detail, thanks.
Ed Swangren
whoops, missed that, thanks Mark! I'm not seeing why there's quality loss then. The overlay idea is still plausible. Just make anything < 240 transparent, > 240 red.
Moose
The quality loss must be due to the format that I receive the image in. I was misleading; the original image is 10 bit monochrome, but I never see that. I get a 32bpp jpeg. Now, my color theory knowledge is not great, but I am more interested in getting the Palette aproach to work if possible.
Ed Swangren
I cleared up the misleading bit. Think of it as 32bpp to indexed.
Ed Swangren
if you are getting 10 bit mono, then that is where the quality loss comes in. The overlay method may be your best bet at this point. How large are the images?
Moose
I am getting a 32bpp image. I should not have mentioned monochrome. It is a black and white image, but the format is 32bpp. The image is about 640x480. I just tried a brute force method using LockBits and some unsafe code, but it was too slow. If only I could use a Pelette...
Ed Swangren
duplicate the image, convert it to 8bpp indexed. set anything < 240 to transparent, anything >= 240 to red. display both images, the 8bpp on top of the other. maybe?
Moose
The problem I have is that looping through pixels is just too slow because of the rate at which the user will change the image. For every tick on the track bar I would need to do it all over again. Also, the conversion to 8bppIndexed causes the image to go entirely black.
Ed Swangren
A: 

Thanks for the help everyone. It seems that this can be solved using the ImageAttributes class and simply setting a color remap table.

ColorMap[] maps = new ColorMap[someNum]
//  add mappings
imageAttrs.SetRemapTable(maps);

Thanks for the help again, at least I learned something.

Ed Swangren