Problem with creating a negative (inverted) image

M

moss

Hi people,
I have a weird problem with creating a negative image. I'm working on
this image viewer application in VS 2008 on Windows 7 64-bit and when
I try to create a negative from the original image, my negative image
ends up being totally black, every pixel is RGB(0,0,0). This is the
code I'm using for this purpose:

ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();
cm.Matrix00 =
cm.Matrix11 =
cm.Matrix22 = -1;
ia.SetColorMatrix(cm);

Graphics g = Graphics.FromImage(MyBitmap);
g.DrawImage(MyBitmap, new Rectangle(0, 0, MyBitmap.Width,
MyBitmap.Height), 0, 0, MyBitmap.Width, MyBitmap.Height,
GraphicsUnit.Pixel, ia);
g.Dispose();

When I run the program on Windows XP 32-bit and Vista 32-bit there is
no problem at all, the negative image looks fine, and I'm able to
invert it back to the original one. Then I read this article:
http://www.bobpowell.net/negativeimage.htm

I used Bob Powell's solution to shift the colors a little bit before
inverting the image, but I get the same blackened result on my 64-bit
machine. So I'm guessing this is some sort of 64-bit issue, because
the numbers are probably represented in a different way and there is
some zero multiplication going on between matrices to produce this
result. (I'm a novice programmer, don't know much about the 64-bit
architecture). Any ideas on how to fix this without having to use the
slow SetPixel method?
 
P

Peter Duniho

moss said:
Hi people,
I have a weird problem with creating a negative image. I'm working on
this image viewer application in VS 2008 on Windows 7 64-bit and when
I try to create a negative from the original image, my negative image
ends up being totally black, every pixel is RGB(0,0,0). This is the
code I'm using for this purpose:

ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();
cm.Matrix00 =
cm.Matrix11 =
cm.Matrix22 = -1;
ia.SetColorMatrix(cm);

Graphics g = Graphics.FromImage(MyBitmap);
g.DrawImage(MyBitmap, new Rectangle(0, 0, MyBitmap.Width,
MyBitmap.Height), 0, 0, MyBitmap.Width, MyBitmap.Height,
GraphicsUnit.Pixel, ia);
g.Dispose();

When I run the program on Windows XP 32-bit and Vista 32-bit there is
no problem at all, the negative image looks fine, and I'm able to
invert it back to the original one. Then I read this article:
http://www.bobpowell.net/negativeimage.htm [...]

I'm not sure I buy Bob's explanation about why the inversion fails, nor
his suggestion that you have to modify (shift) the colors in order to
get it to work. At the very least, if he believes this to be a bug in
Windows, he should say so explicitly, rather than implying this is a
problem inherent in using a ColorMatrix.

I haven't spent much time thinking about this, never mind done any
testing myself. But the first thing I would check is to make sure that
the ColorMatrix is indeed by default the identity matrix, through _all_
the color value components. In particular, make sure that the element
at (3,3) is in fact 1. A 0 in that position would cause all the pixels
to be transparent, and when drawn into an uninitialized bitmap, would
result in an all-black bitmap (since the uninitialized bitmap starts out
all black).

You may be able to gain some better understanding of the problem by
initializing the destination bitmap to something other than black before
drawing into it. Either some graphic, or perhaps just some color other
than black.

It's entirely possible that there's some bug in GDI+, and that Bob's
explanation is accurate. Having a 64-bit OS _shouldn't_ affect drawing
code, but if some Microsoft developer used a platform-dependent type for
a variable instead of a fixed 32-bit int for something, I suppose
something like this could come up. But you should rule out more mundane
causes first.

Finally, if indeed you can't rely on using a ColorMatrix to do this, I
wouldn't use Get/SetPixel(). Instead, use Bitmap.LockBits() to get the
actual bitmap data and invert the colors directly. Of course, doing
this you'll have to worry about pixel format issues, but the performance
will be acceptable, whereas with Get/SetPixel() it definitely won't be.

Pete
 
M

moss

I'm not sure I buy Bob's explanation about why the inversion fails, nor
his suggestion that you have to modify (shift) the colors in order to
get it to work. At the very least, if he believes this to be a bug in
Windows, he should say so explicitly, rather than implying this is a
problem inherent in using a ColorMatrix.

I haven't spent much time thinking about this, never mind done any
testing myself. But the first thing I would check is to make sure that
the ColorMatrix is indeed by default the identity matrix, through _all_
the color value components. In particular, make sure that the element
at (3,3) is in fact 1. A 0 in that position would cause all the pixels
to be transparent, and when drawn into an uninitialized bitmap, would
result in an all-black bitmap (since the uninitialized bitmap starts out
all black).

You may be able to gain some better understanding of the problem by
initializing the destination bitmap to something other than black before
drawing into it. Either some graphic, or perhaps just some color other
than black.

It's entirely possible that there's some bug in GDI+, and that Bob's
explanation is accurate. Having a 64-bit OS _shouldn't_ affect drawing
code, but if some Microsoft developer used a platform-dependent type for
a variable instead of a fixed 32-bit int for something, I suppose
something like this could come up. But you should rule out more mundane
causes first.

Finally, if indeed you can't rely on using a ColorMatrix to do this, I
wouldn't use Get/SetPixel(). Instead, use Bitmap.LockBits() to get the
actual bitmap data and invert the colors directly. Of course, doing
this you'll have to worry about pixel format issues, but the performance
will be acceptable, whereas with Get/SetPixel() it definitely won't be.

Pete

Thanks for this explanation and advice, but in the mean time I've
managed to find a great open source image processing framework
(AForge.NET), which has the Invert filter that does the job, without
any issues.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top