Fix problem loading gif files using subset of the original color map (fix #729)

There are gif files that use a subset of the original color map remapping
used entries into first indexes. E.g. the main palette contains 256 colors,
but then a frame can use 4-bit per pixel to reference 16 colors from the
original 256 color palette.
This commit is contained in:
David Capello 2015-07-15 15:42:54 -03:00
parent 008dceb55d
commit 37478688c0

View File

@ -165,6 +165,7 @@ bool GifFormat::onLoad(FileOp* fop)
UniquePtr<Palette> current_palette(new Palette(frame_t(0), 256)); UniquePtr<Palette> current_palette(new Palette(frame_t(0), 256));
UniquePtr<Palette> previous_palette(new Palette(frame_t(0), 256)); UniquePtr<Palette> previous_palette(new Palette(frame_t(0), 256));
Remap remap(256);
// If the GIF image has a global palette, it has a valid // If the GIF image has a global palette, it has a valid
// background color (so the GIF is not transparent). // background color (so the GIF is not transparent).
@ -223,15 +224,42 @@ bool GifFormat::onLoad(FileOp* fop)
if (frame_delay >= 0) if (frame_delay >= 0)
data->frames[frame_num].duration = frame_delay*10; data->frames[frame_num].duration = frame_delay*10;
for (int i=0; i<256; ++i)
remap.map(i, i);
// Update palette for this frame (the first frame always need a palette). // Update palette for this frame (the first frame always need a palette).
if (gif_file->Image.ColorMap) { if (gif_file->Image.ColorMap) {
ColorMapObject* colormap = gif_file->Image.ColorMap; ColorMapObject* colormap = gif_file->Image.ColorMap;
bool createPal = false;
// Here we try to find all colors in the existent color map.
// In this way we can remap the local color map to the
// global color map (or the previous frame color map).
for (int i=0; i<colormap->ColorCount; ++i) { for (int i=0; i<colormap->ColorCount; ++i) {
current_palette->setEntry(i, int j =
rgba( current_palette->findExactMatch(
colormap->Colors[i].Red, colormap->Colors[i].Red,
colormap->Colors[i].Green, colormap->Colors[i].Green,
colormap->Colors[i].Blue, 255)); colormap->Colors[i].Blue, 255);
// If some entry is not found in the palette, we have to
// replace the whole palette.
if (j < 0) {
createPal = true;
break;
}
remap.map(i, j);
}
if (createPal) {
for (int i=0; i<colormap->ColorCount; ++i) {
remap.map(i, i);
current_palette->setEntry(
i,
rgba(
colormap->Colors[i].Red,
colormap->Colors[i].Green,
colormap->Colors[i].Blue, 255));
}
} }
} }
@ -271,6 +299,8 @@ bool GifFormat::onLoad(FileOp* fop)
} }
} }
remap_image(frame_image.get(), remap);
// Detach the pointer of the frame-image and put it in the list of frames. // Detach the pointer of the frame-image and put it in the list of frames.
data->frames[frame_num].image = frame_image.release(); data->frames[frame_num].image = frame_image.release();
data->frames[frame_num].disposal_method = disposal_method; data->frames[frame_num].disposal_method = disposal_method;