Weird behavior (losing data) after saving / loading a 8bpp bitmap as png

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
1. Create a gradient 8bpp bitmap
2. Save as png and bmp
3. Open the files as new bitmaps
4. Look the data
5. png data is corrupted/wrong. I print the first bytes to show it:
string s = "";<br/>
for (int i = 0; i < 20; i++)<br/>
{<br/>
s += buffer.ToString() + " ";<br/>
}<br/>
Console.WriteLine("Image data: " + s);
I get for bmp: Image data: 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5
and for png: Image data: 0 0 0 255 0 0 0 255 0 0 0 255 0 0 128 255 0 0 128 255. it should be the sameeeeee !!!
The code is:

<div style="color:Black;background-color:White; <pre>
<span style="color:Blue; public Class Test
{
<span style="color:Blue; private ColorPaletteHandle palHandle = <span style="color:Blue; new ColorPaletteHandle();

<span style="color:Blue; private <span style="color:Blue; static <span style="color:Blue; void SaveBitmapsTest(ColorPaletteHandle handle, ColorPaletteType type)
{
Bitmap bmp;
bmp = ColorPaletteHandle.CreateGradientBitmap();
<span style="color:Green; //Bitmap bmp = new Bitmap(bmpTemp);
<span style="color:Blue; string name = type.ToString();
handle.SetPallet(<span style="color:Blue; ref bmp, type);
bmp.Save(<span style="color:#A31515; "D:\" + name + ".bmp", ImageFormat.Bmp);
bmp.Save(<span style="color:#A31515; "D:\" + name + ".png", ImageFormat.Png);
bmp.Dispose();
}

<span style="color:Blue; private <span style="color:Blue; void test_Click(<span style="color:Blue; object sender, EventArgs e)
{
SaveBitmapsTest(<span style="color:Blue; this.palHandle, ColorPaletteType.Default);
SaveBitmapsTest(<span style="color:Blue; this.palHandle, ColorPaletteType.GrayScale);
SaveBitmapsTest(<span style="color:Blue; this.palHandle, ColorPaletteType.EdgesHighlightst);
SaveBitmapsTest(<span style="color:Blue; this.palHandle, ColorPaletteType.HeatMap);

<span style="color:Green; //Pra não ter problema com a bitmap após abrir de um arquivo é necessário copia ela
<span style="color:Green; //http://support.microsoft.com/?id=814675
<span style="color:Blue; string name = ColorPaletteType.Default.ToString();
<span style="color:Blue; string ext = <span style="color:#A31515; ".png";
Bitmap bmpTemp = (Bitmap)Bitmap.FromFile("D:\" + name + ext);
Bitmap bmp = <span style="color:Blue; new Bitmap(bmpTemp.Width, bmpTemp.Height, bmpTemp.PixelFormat);
BitmapData data1 = bmpTemp.LockBits(<span style="color:Blue; new Rectangle(0, 0, bmpTemp.Width, bmpTemp.Height), ImageLockMode.ReadOnly, bmpTemp.PixelFormat);
BitmapData data2 = bmp.LockBits(<span style="color:Blue; new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
<span style="color:Blue; byte[] buffer = <span style="color:Blue; new <span style="color:Blue; byte[data1.Stride * data1.Height];

Marshal.Copy(data1.Scan0, buffer, 0, buffer.Length);
<span style="color:Blue; string s = <span style="color:#A31515; "";
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < 20; i++)
{
s += buffer.ToString() + <span style="color:#A31515; " ";
}
Console.WriteLine(<span style="color:#A31515; "Image data: " + s);
Marshal.Copy(buffer, 0, data2.Scan0, buffer.Length);
bmpTemp.UnlockBits(data1);
bmp.UnlockBits(data2);
bmpTemp.Dispose();
GC.Collect();
<span style="color:Blue; this.pcbImage.Image = bmp;
<span style="color:Blue; this.pcbImage.Refresh();
Thread.Sleep(1000);
<span style="color:Blue; this.palHandle.SetPallet(<span style="color:Blue; ref bmp, ColorPaletteType.HeatMap);
<span style="color:Blue; this.pcbImage.Refresh();
}
}

<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Type of color palette.
<span style="color:Gray; /// <span style="color:Gray; </summary>
<span style="color:Blue; public <span style="color:Blue; enum ColorPaletteType
{
<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Default Format8bppIndexed windows palette.
<span style="color:Gray; /// <span style="color:Gray; </summary>
Default = 0,
<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Grayscale
<span style="color:Gray; /// <span style="color:Gray; </summary>
GrayScale = 1,
<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Artificially HeatMap coloured scale
<span style="color:Gray; /// <span style="color:Gray; </summary>
HeatMap = 2,
<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Edges Highlights scale
<span style="color:Gray; ///<span style="color:Green; 0 = Blue
<span style="color:Gray; ///<span style="color:Green; 255 = Red
<span style="color:Gray; /// <span style="color:Gray; </summary>
EdgesHighlightst = 3
}

<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Handles (create and store) different types of color palette.
<span style="color:Gray; /// <span style="color:Gray; </summary>
<span style="color:Blue; public <span style="color:Blue; class ColorPaletteHandle
{
<span style="color:Blue; private ColorPalette pal;
<span style="color:Blue; private ColorPaletteType palType;

<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Creates a new instace of Lma.Image.BitmapPaletteHandle.
<span style="color:Gray; /// <span style="color:Gray; </summary>
<span style="color:Blue; public ColorPaletteHandle()
{
}

<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Creates a bitmap (1024,200) with columns values that range from 0 to 255.
<span style="color:Gray; /// <span style="color:Gray; </summary>
<span style="color:Gray; /// <span style="color:Gray; <returns><span style="color:Green; The image.</returns>
<span style="color:Blue; public <span style="color:Blue; static Bitmap CreateGradientBitmap()
{
Size size = <span style="color:Blue; new Size(1024, 200);
Bitmap bmp = <span style="color:Blue; new Bitmap(size.Width, size.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
BitmapData data = bmp.LockBits(<span style="color:Blue; new Rectangle(0, 0, size.Width, size.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
<span style="color:Blue; byte color = 0;
<span style="color:Blue; int delta = 0;
<span style="color:Blue; int id;
<span style="color:Blue; float colorScale = 255.0f / (<span style="color:Blue; float)size.Width;
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < size.Width; i++)
{
color = Convert.ToByte(i * colorScale);
<span style="color:Blue; for (<span style="color:Blue; int j = 0; j < size.Height; j++)
{
id = j * data.Stride + i;
Marshal.WriteByte(data.Scan0 + id, color);
}
}
bmp.UnlockBits(data);
<span style="color:Blue; return bmp;
}

<span style="color:Blue; public <span style="color:Blue; void SetPallet(<span style="color:Blue; ref Bitmap bmp, ColorPaletteType type)
{
<span style="color:Blue; if (<span style="color:Blue; this.palType != type)
<span style="color:Blue; this.pal = <span style="color:Blue; null;
<span style="color:Blue; if (<span style="color:Blue; this.pal == <span style="color:Blue; null)
{
<span style="color:Blue; this.palType = type;
<span style="color:Blue; this.pal = GetDefaultPalette();
GetPalette(<span style="color:Blue; ref <span style="color:Blue; this.pal, type);
}
bmp.Palette = <span style="color:Blue; this.pal;
}

<span style="color:Blue; public <span style="color:Blue; static <span style="color:Blue; void GetPalette(<span style="color:Blue; ref ColorPalette pal, ColorPaletteType type)
{
<span style="color:Blue; switch (type)
{
<span style="color:Blue; case ColorPaletteType.Default:
pal = GetDefaultPalette();
<span style="color:Blue; break;
<span style="color:Blue; case ColorPaletteType.GrayScale:
GetGrayScalePalette(<span style="color:Blue; ref pal);
<span style="color:Blue; break;
<span style="color:Blue; case ColorPaletteType.HeatMap:
GetHeatMapPalette(<span style="color:Blue; ref pal);
<span style="color:Blue; break;
<span style="color:Blue; case ColorPaletteType.EdgesHighlightst:
GetEdgesHighlightstPalette(<span style="color:Blue; ref pal);
<span style="color:Blue; break;
<span style="color:Blue; default:
<span style="color:Blue; break;
}
}
<span style="color:Blue; public <span style="color:Blue; static ColorPalette GetDefaultPalette()
{
Bitmap bmp = <span style="color:Blue; new Bitmap(1, 1, PixelFormat.Format8bppIndexed);
<span style="color:Blue; return bmp.Palette;
}

<span style="color:Blue; public <span style="color:Blue; static <span style="color:Blue; void GetHeatMapPalette(<span style="color:Blue; ref ColorPalette pal)
{
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < pal.Entries.Length; i++)
{
pal.Entries = ComputeHeatMapColor((<span style="color:Blue; byte)i, <span style="color:Blue; false, Color.Black);
}
}

<span style="color:Blue; public <span style="color:Blue; static <span style="color:Blue; void GetGrayScalePalette(<span style="color:Blue; ref ColorPalette pal)
{
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < 256; i++)
{
pal.Entries = Color.FromArgb(i, i, i);
}
}

<span style="color:Blue; public <span style="color:Blue; static <span style="color:Blue; void GetEdgesHighlightstPalette(<span style="color:Blue; ref ColorPalette pal)
{
GetGrayScalePalette(<span style="color:Blue; ref pal);
pal.Entries[0] = Color.Blue;
pal.Entries[1] = Color.MidnightBlue;
pal.Entries[254] = Color.DarkOrange;
pal.Entries[255] = Color.Red;
}

<span style="color:Gray; /// <span style="color:Gray; <summary>
<span style="color:Gray; ///<span style="color:Green; Calcula cor
<span style="color:Gray; /// <span style="color:Gray; </summary>
<span style="color:Gray; /// <span style="color:Gray; <param name="grayLevel <span style="color:Green; Nivel de cinza</param>
<span style="color:Gray; /// <span style="color:Gray; <returns><span style="color:Green; RGB</returns>
<span style="color:Blue; public <span style="color:Blue; static Color ComputeHeatMapColor(<span style="color:Blue; byte grayLevel, <span style="color:Blue; bool mustUseBackColor, Color backColor)
{
<span style="color:Blue; byte r, g, b;

<span style="color:Blue; if (grayLevel < 128)
{
r = 0;
<span style="color:Blue; if (grayLevel <= 63)
b = 255;
<span style="color:Blue; else
b = (<span style="color:Blue; byte)(255.0 * (1.0 - (<span style="color:Blue; double)(grayLevel - 63) / 64.0));
}
<span style="color:Blue; else
{
b = 0;
<span style="color:Blue; if (grayLevel >= 191)
r = 255;
<span style="color:Blue; else
r = (<span style="color:Blue; byte)(255.0 * (<span style="color:Blue; double)(grayLevel - 127) / 64.0);
}
<span style="color:Blue; if (grayLevel < 63)
g = (<span style="color:Blue; byte)(255 * (<span style="color:Blue; double)grayLevel / 64.0);
<span style="color:Blue; else
{
<span style="color:Blue; if (grayLevel > 191)
g = (<span style="color:Blue; byte)(255.0 * (1.0 - (<span style="color:Blue; double)(grayLevel - 191) / 64.0));
<span style="color:Blue; else
g = 255;
}
<span style="color:Blue; if (mustUseBackColor && r == 0 && g == 0 && b == 0)
<span style="color:Blue; return (backColor);
<span style="color:Blue; return (Color.FromArgb(r, g, b));
}
}
[/code]


View the full article
 
Back
Top