开发者

Can't set palette in bitmap

I have been writing a PCX decoder and, so far, the PCX image itself parses fine, but I can't work out how to set the palette of a bitmap.

I have created a bitmap like so:

Bitmap bmp = new Bitmap(width,
                        height,
                        stride2,
                        System.Drawing.Imaging.PixelFormat.Format8bppIndexed,
                        pixels);

But I can't seem to set the palette using the following method:

for (int i = 0; i < 256; i += 3)
{
    Color b = new Color();
    b = Color.FromArgb(palette[i], palette[i + 1], palette[i + 2]);
    bmp.Palette.Entries.SetValue(b, i);
}

In this example, I have read through each byte in the palette of the pcx file and stored them in palette[]. from there, I have used this to set the entries in the palette of开发者_开发技巧 the bitmap. How do I set the colours?


This had me confused too. It seems bitmap.Palette returns a clone of the bitmap's palette. Once you've modified your copy, you need to reset the bitmap's pallete by using bitmap.Palette = palette, e.g.

ColorPalette palette = bitmap.Palette;
palette.Entries[i] = new Color(...);
....
bitmap.Palette = palette; // The crucial statement

See http://www.charlespetzold.com/pwcs/PaletteChange.html


According to Microsoft Reference Source, Palette property of Image class in .net, internally uses GDI+ Flat APIs for handling palettes. GdipGetImagePalette used for initializing ColorPalette object in get method and GdipSetImagePalette used for writing ColorPalette object data back to device is set method.

Each time in your for loop the line bmp.Palette.Entries.SetValue(b, i); forces the Image to call GdipGetImagePalette and data of bmp.Palette reinitialized and therefore you can see no change has been made to bmp.Palette after the loop.

To solve this problem you must do the following:

  1. Assign new alias to bmp.Palette by assigning it to a variable,
  2. Modify it by new alias (this prevents reloading),
  3. And put it back to the bmp.Palette.

Code:

var newAliasForPalette = bmp.Palette; // Palette loaded from graphic device
for (int i = 0; i < 256; i++)
{
    newAliasForPalette.Entries[i] = myColor[i];
}
bmp.Palette = newAliasForPalette; // Palette data wrote back to the graphic device

In my opinion, replacement of definition of Palette as a property with GetPalette() and SetPalette() methods by Microsoft, will be a great help in avoiding confusion.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜