PDA

View Full Version : Pngimage palette issue



masonwheeler
21-02-2008, 01:06 AM
I'm trying to convert images from a nonstandard format to PNG using the pngimage library. The original format uses a 256-color palette, just like PNG does, so it should be simple. And I can get the image to convert and look exactly like the original. There's only one problem.

The way my program is set up, it checks the image for palette entry #0, and defines that as the mask color. When I'm translating the image to PNG, the original palette has to be preserved in its original order, but I can't find any way to make that work.

My original code tried loading the original image's palette into an array, setting all the pixels of the image, and then using the Windows API function:
windows.SetPaletteEntries(png.Palette, 0, 256, thePalette[0]);
This produced an image that looked correct, but the palette #0 entry was wrong, which screws up masking. It's as if the palette was never set.

Next, I tried calling SetPaletteEntries first, then setting all the image pixels at the end. This produced proper masking, but the colors of the final image were bizarrely munged. Each pixel of the same color in the original came out the same color in the converted version, but they weren't the same two colors, so apparently the palette references were correct but the entries themselves had been corrupted.

Then I tried setting the palette manually. I wrote this:
for I := 0 to 255 do
with TChunkPLTE(png.Chunks.ItemFromClass(TChunkPLTE)).I tem[i] do
begin
rgbRed := thePalette[i].peRed;
rgbBlue := thePalette[i].peBlue;
rgbGreen := thePalette[i].peGreen;
end;

and tried placing it first before and then after the routine that sets the pixels. Both gave me the same results as my original code: Correct image, incorrect palette #0.

I'm about at my wits' end here. Does anyone know how to explicitly set up a the palette entries in a TPngObject and have it come out looking properly AND with the palette in the right order?

User137
21-02-2008, 11:43 AM
Sorry never tried to actually save a PNG. Little i know about 256 palettes with PNG either, most use true colors that don't really take any more space, but is it possible to set pixels alpha value to 0 when color is #0? That would help for the mask problem, assuming you had all colors correctly. I realize this might add extra data to image if you did not have alpha channel previously.

masonwheeler
22-02-2008, 05:00 AM
No, that wouldn't work with the way the program's set up, unfortunately.

andy
26-02-2008, 09:24 PM
Greetings,
I've made a lot of work with 256 bitmap.
And I think is simpler work with a TBitmap then assign it to a PNG when saving.

Var MyPAL: TMaxLogPalette;
TempBitmap:TBitmap;
aPNG: TPNGObject;

MyPAL.palVersion := $300;
MyPAL.palNumEntries := 256;
for i := 0 to 255 do
begin
MyPAL.palPalEntry[i].peRed := thePalette[i].peRed;
MyPAL.palPalEntry[i].peGreen := thePalette[i].peGreen;
MyPAL.palPalEntry[i].peBlue := thePalette[i].peBlue;
end;

TempBitmap:=TBitmap.Create;
TempBitmap.PixelFormat:=pf8bit;
TempBitmap.Palette := CreatePalette(PLogPalette(@MyPal)^);

//set bitmap width and height and fill bitmap with data

aPNG := TPNGObject.Create;
aPNG.Assign(TempBitmap);
aPNG.TransparentColor := 0; //index to transparent color
aPNG.SaveToFile(....

Hope it help.