Groups | Blog | Home
all groups > dotnet drawing api > march 2008 >

dotnet drawing api : Color problems when converting indexed8 to 24 bit


Linus
3/31/2008 3:06:52 AM
Hi,

I'm having a problem converting an indexed8 tiff image to a 24bit
image. When I convert it with DrawImage or for example
DrawImageUnscaledAndClipped it drops the RGB with one. For example
(255,255,255) would become (254,254,254). I've tried the victor image
processing library demo version and with it I've no problems.
Photoshop also converts it to 24bit correctly. Now I'm asking, what
Graphics setting do I need to set to get it to convert the image
correctly? I've included part of the code below. Also, is it possible
to export a reference to a bitmap from a function? How do I dispose of
the bitmap in the function? Or shouldn't I do it? Will it be enough if
the caller disposes of it?

Thanks,
Linus


Function OpenImage(ByVal filename As String) As Bitmap

Dim image As Bitmap
Dim image24 As Bitmap
Dim g As Graphics

Try
image = New Bitmap(filename)
image24 = New Bitmap(image.Width, image.Height,
Imaging.PixelFormat.Format24bppRgb)

g = Graphics.FromImage(image24)

' g.CompositingMode =
Drawing2D.CompositingMode.SourceCopy
' g.CompositingQuality =
Drawing2D.CompositingQuality.AssumeLinear
' g.InterpolationMode =
Drawing2D.InterpolationMode.NearestNeighbor
' g.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
' g.PageUnit = GraphicsUnit.Pixel
' g.SmoothingMode = Drawing2D.SmoothingMode.None
g.DrawImage(image, 0, 0, image.Width, image.Height)
image24.Save(filename & "2.png")
Catch
image24 = Nothing
End Try

If Not (IsNothing(g)) Then g.Dispose()
If Not (IsNothing(image)) Then image.Dispose()
OpenImage = image24
'If Not (IsNothing(image24)) Then image24.Dispose()


Linus
3/31/2008 7:18:27 AM
[quoted text, click to view]

Hi,
I just debugged it to this line. It seems just reading in the tiff
file will mess up the palette. Can there be anything wrong with the
tiff files or is there a bug in the Bitmap class?

[quoted text, click to view]

Regards,
Linus
3/31/2008 8:00:14 AM
Hi,

I can't get Drawimage(image, new point(0,0)) to work. All I get is a
black image. I must use a new Rectangle instead otherwise it just
copies one point). But I think the problem isn't the scaling or using
DrawImage, the problem occurs when I LOAD the image.

Regards,
Linus

On Mar 31, 5:37 pm, "Michael Phillips, Jr."
[quoted text, click to view]
Linus
3/31/2008 8:06:08 AM
Hi,
MSPaint opens it ok but it also messes up the palette. it subtracts 1
from R,G and B. Does MSPaint use the same TIFF loaders as VB.NET? The
3rd party library and Photoshop Elements 4.0 reads the image fine.
Could I send you the picture, if you have the same problem at least
I'll know that there isn't anything wrong with my setup?

Regards,
Linus

On Mar 31, 5:50 pm, "Michael Phillips, Jr."
[quoted text, click to view]
Linus
3/31/2008 9:32:27 AM
Hi,

Here's the link to it: http://web.abo.fi/~lsilvand/SEM.tif
It's an uncompressed 6 Mb TIFF file. Dimensions:3072x2304. 8-bit
indexed. Search for white after you've loaded it in, there should be
plenty of it if everythings ok.
The problem is that I've got thousands of files just like this one and
I'ld hope that there's something wrong with the TIFF loader and not
with the program producing these TIFF images.
Could a problem with the TIFF image also explain why I get a black
image while copying it with DrawImage(image,point()). I always have to
use DrawImage(image,rectangle()) to get it to produce and ok image.

Regards,
Linus


On Mar 31, 6:28=A0pm, "Bob Powell [MVP]" <b...@spamkillerbobpowell.net>
[quoted text, click to view]
Linus
3/31/2008 9:34:44 AM
Just to add one thing. I tested it with Paint.NET v3.2 and it messed
up the palette but Gimp worked ok.


On Mar 31, 6:28=A0pm, "Bob Powell [MVP]" <b...@spamkillerbobpowell.net>
[quoted text, click to view]
Michael Phillips, Jr.
3/31/2008 10:37:54 AM
I suggest that you create a 24bpp image with the same width and height as
the source and set the resolution to match the original source tiff's
resolution.

Use the DrawImage method with the Point argument(i.e., DrawImage(image, new
Point(0,0)).

You should get an unscaled bitblt that unpacks the 8bpp source to a 24bpp
image.


[quoted text, click to view]

Michael Phillips, Jr.
3/31/2008 10:50:58 AM
The tiff specification is complex.

Perhaps there is something wrong with your image.

Does it display with MS Paint?

If you dump the palette after decoding the image, do you get the same
palette when using another 3rd party library or program?

[quoted text, click to view]

Linus
3/31/2008 11:14:30 AM
Ok, that explains a lot, hopefully MS would fix this annoying thing in
net2.0. As I understand it, the palette is 16-bit but the image data
is only 8-bit? I use VS 2005 at work and I've tried out a couple of
things at home with VS Express 2008, but it also seems to use net2.0.
I've tried to add the net3.5 imaging api as a reference but can only
find the net2.0 version. Am I doing something wrong?

On Mar 31, 8:07=A0pm, "Michael Phillips, Jr."
[quoted text, click to view]
Michael Phillips, Jr.
3/31/2008 1:07:15 PM
I downloaded the tiff. The palette is 16bit grayscale. Each of the 768
colors in the color map is in the range 0 - 65535.

The gdi decoder must scale and quantize the color map to create a 256 color
palette with each color in the range 0 - 255 when it decodes it to a 8bpp
indexed bitmap.

If you wish to preserve the color map, use the Net 3.5 media imaging api as
it wraps Microsoft's Windows Imaging Compoment. It has better support for
tiff images.


[quoted text, click to view]

Michael Phillips, Jr.
3/31/2008 3:57:44 PM
16bpp grayscale was never supported. Since it is suppported in Net 3.5, it
is not likely that gdiplus will add this functionality.

You must add references for PresentationCore and WindowsBase.

[quoted text, click to view]
Ok, that explains a lot, hopefully MS would fix this annoying thing in
net2.0. As I understand it, the palette is 16-bit but the image data
is only 8-bit? I use VS 2005 at work and I've tried out a couple of
things at home with VS Express 2008, but it also seems to use net2.0.
I've tried to add the net3.5 imaging api as a reference but can only
find the net2.0 version. Am I doing something wrong?

On Mar 31, 8:07 pm, "Michael Phillips, Jr."
[quoted text, click to view]

Bob Powell [MVP]
3/31/2008 5:28:37 PM
You seem to have chosen the best mode for a simple copy.

Can you post the image that you want to make a copy of?

--
--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.


[quoted text, click to view]
Linus
4/2/2008 11:28:04 AM
I started thinking about this and the palette might be 16 bits but it
can only point to 256 colors in the image data. The image is about 6Mb
uncompressed and 3072x2304x8bits is about 6Mb, so the image data must
be 8 bits. The fact that net2.0 will read in the data and but shift
the palette with 1 in R,G,B would suggest TIFF decoder problem. I also
got around this problem with this small fix below.
The interesting thing is that changing the palette won't fix anything
if I resave it as an indexed picture(indexed_newpalette.png), but if I
first convert it to 24bit it will save it with right palette. Does
anyone know why this is? The new gray palette I create can be in
reverse or even random, it doesn't matter, the picture will have the
correct gray colors when I convert it to 24bit.
Can anyone recommend a good book about VB.NET and GDI+? I bought the
"Programming Microsoft Visual Basic 2005: The Language" by Fransesco
Balena and found it excellent. A similar book about the GDI+ would be
a good thing to have.
Thanks for all the replies I've recieved!

Dim img As Bitmap =3D New Bitmap("d:\test\R017_100x_03.tif")
Dim img24 As Bitmap =3D New Bitmap(3072, 2304,
Imaging.PixelFormat.Format24bppRgb)
Dim g As Graphics =3D Graphics.FromImage(img24)
Dim cp As ColorPalette =3D img.Palette
For i As Integer =3D 0 To 255
cp.Entries(i) =3D Color.FromArgb(i, i, i)
Next
img.Palette =3D cp
img.Save("d:\indexed_newpalette.png", Imaging.ImageFormat.Png)
g.CompositingMode =3D Drawing2D.CompositingMode.SourceCopy
g.CompositingQuality =3D
Drawing2D.CompositingQuality.AssumeLinear
g.InterpolationMode =3D
Drawing2D.InterpolationMode.NearestNeighbor
g.PixelOffsetMode =3D Drawing2D.PixelOffsetMode.Half
g.PageUnit =3D GraphicsUnit.Pixel
g.SmoothingMode =3D Drawing2D.SmoothingMode.None
g.DrawImageUnscaledAndClipped(img, New Rectangle(0, 0,
img.Width, img.Height))
img24.Save("d:\24bit_newpalette.png",
System.Drawing.Imaging.ImageFormat.Png)



On Mar 31, 10:57=A0pm, "Michael Phillips, Jr."
[quoted text, click to view]
Michael Phillips, Jr.
4/2/2008 7:53:44 PM
The palette in your image consists of 768 colors(i.e., rgb) with each color
in the range 0 - 65535.

You image is 8bpp indexed. To convert it to a bitmap, the palette must be
256 colors with each color in the range 0 - 255.

Using the most significant 8 bits of the 16bpp color will give you colors in
the range 0 - 255.

Once you create a grayscale palette, the image must be reindexed. Each
pixel with a color closest to the original 16bpp grayscale color will be
reindexed from the new 256 color grayscale palette.

A color of 65024 will be mapped to 254. So will a color such as 65048. A
color such as 65526 will map to 255 and so on.

You could read the tiff specification to see the recommended way to carry
out the color scaling.

Converting to 24bpp unpacks the image. If you pull each 16bpp rgb color out
of the colormap and scale it by taking the most significant 8 bits and
repack it, you still will have color loss when saving as a bitmap.

If you really want to see exactly how the decoder handles the conversion,
use the Net 3.5 API. You can dump the 768 16bpp colormap and then covert
the image to a 8bpp indexed bitmap and then dump the converted palette.

[quoted text, click to view]
I started thinking about this and the palette might be 16 bits but it
can only point to 256 colors in the image data. The image is about 6Mb
uncompressed and 3072x2304x8bits is about 6Mb, so the image data must
be 8 bits. The fact that net2.0 will read in the data and but shift
the palette with 1 in R,G,B would suggest TIFF decoder problem. I also
got around this problem with this small fix below.
The interesting thing is that changing the palette won't fix anything
if I resave it as an indexed picture(indexed_newpalette.png), but if I
first convert it to 24bit it will save it with right palette. Does
anyone know why this is? The new gray palette I create can be in
reverse or even random, it doesn't matter, the picture will have the
correct gray colors when I convert it to 24bit.
Can anyone recommend a good book about VB.NET and GDI+? I bought the
"Programming Microsoft Visual Basic 2005: The Language" by Fransesco
Balena and found it excellent. A similar book about the GDI+ would be
a good thing to have.
Thanks for all the replies I've recieved!

Dim img As Bitmap = New Bitmap("d:\test\R017_100x_03.tif")
Dim img24 As Bitmap = New Bitmap(3072, 2304,
Imaging.PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(img24)
Dim cp As ColorPalette = img.Palette
For i As Integer = 0 To 255
cp.Entries(i) = Color.FromArgb(i, i, i)
Next
img.Palette = cp
img.Save("d:\indexed_newpalette.png", Imaging.ImageFormat.Png)
g.CompositingMode = Drawing2D.CompositingMode.SourceCopy
g.CompositingQuality =
Drawing2D.CompositingQuality.AssumeLinear
g.InterpolationMode =
Drawing2D.InterpolationMode.NearestNeighbor
g.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
g.PageUnit = GraphicsUnit.Pixel
g.SmoothingMode = Drawing2D.SmoothingMode.None
g.DrawImageUnscaledAndClipped(img, New Rectangle(0, 0,
img.Width, img.Height))
img24.Save("d:\24bit_newpalette.png",
System.Drawing.Imaging.ImageFormat.Png)



On Mar 31, 10:57 pm, "Michael Phillips, Jr."
[quoted text, click to view]

Bob Powell [MVP]
4/4/2008 10:49:56 AM
This image doesn't exist...

--
--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.


[quoted text, click to view]
Hi,

Here's the link to it: http://web.abo.fi/~lsilvand/SEM.tif
It's an uncompressed 6 Mb TIFF file. Dimensions:3072x2304. 8-bit
indexed. Search for white after you've loaded it in, there should be
plenty of it if everythings ok.
The problem is that I've got thousands of files just like this one and
I'ld hope that there's something wrong with the TIFF loader and not
with the program producing these TIFF images.
Could a problem with the TIFF image also explain why I get a black
image while copying it with DrawImage(image,point()). I always have to
use DrawImage(image,rectangle()) to get it to produce and ok image.

Regards,
Linus


On Mar 31, 6:28 pm, "Bob Powell [MVP]" <b...@spamkillerbobpowell.net>
[quoted text, click to view]
AddThis Social Bookmark Button