Fix gif encoder, blended indexed images could be selected to preserve palette orders, but it is not possible.

Before this fix, multi layer blended indexed images (into the gif options dialog), could be checked in the preserve palette orders check box, but actually it is not possible.
In addition, we bypass large code blocks when we have to preserve palette order.
This commit is contained in:
Gaspar Capello 2020-04-22 11:23:16 -03:00
parent 8d7020a063
commit af7e85313a

View File

@ -934,7 +934,8 @@ public:
, m_hasBackground(m_sprite->isOpaque())
, m_bitsPerPixel(1)
, m_globalColormap(nullptr)
, m_globalColormapPalette(*m_sprite->palette(0)) {
, m_globalColormapPalette(*m_sprite->palette(0))
, m_preservePaletteOrder(false) {
const auto gifOptions = std::static_pointer_cast<GifOptions>(fop->formatOptions());
@ -943,26 +944,6 @@ public:
m_interlaced = gifOptions->interlaced();
m_loop = (gifOptions->loop() ? 0: -1);
if (m_sprite->pixelFormat() == PixelFormat::IMAGE_INDEXED) {
// For indexed and opaque sprite, we can preserve the exact
// palette order without lossing compression rate.
if (m_hasBackground) {
m_preservePaletteOrder = true;
}
// Only for transparent indexed images the user can choose to
// preserve or not the palette order.
else {
m_preservePaletteOrder = gifOptions->preservePaletteOrder();
}
}
// For RGB images we don't preserve the palette order (palettes
// will be generated as they are needed to optimize the file
// size).
else {
m_preservePaletteOrder = false;
}
m_lastFrameBounds = m_spriteBounds;
m_lastDisposal = DisposalMethod::NONE;
@ -995,6 +976,14 @@ public:
if (!quantizeColormaps) {
m_globalColormap = createColorMap(&m_globalColormapPalette);
m_bgIndex = m_sprite->transparentColor();
// For indexed and opaque sprite, we can preserve the exact
// palette order without lossing compression rate.
if (m_hasBackground)
m_preservePaletteOrder = true;
// Only for transparent indexed images the user can choose to
// preserve or not the palette order.
else
m_preservePaletteOrder = gifOptions->preservePaletteOrder();
}
else
m_bgIndex = 0;
@ -1071,7 +1060,7 @@ public:
// Create the 3 temporary images (previous/current/next) to
// compare pixels between them.
for (int i=0; i<3; ++i)
m_images[i].reset(Image::create(IMAGE_RGB,
m_images[i].reset(Image::create((m_preservePaletteOrder)? IMAGE_INDEXED : IMAGE_RGB,
m_spriteBounds.w,
m_spriteBounds.h));
}
@ -1152,7 +1141,7 @@ private:
// we must change disposal to RESTORE_BGCOLOR.
// "Pixel clearing" detection:
if (!m_hasBackground) {
if (!m_hasBackground && !m_preservePaletteOrder) {
const LockImageBits<RgbTraits> bits2(m_currentImage);
const LockImageBits<RgbTraits> bits3(m_nextImage);
typename LockImageBits<RgbTraits>::const_iterator it2, it3, end2, end3;
@ -1165,12 +1154,16 @@ private:
}
}
}
else if (m_preservePaletteOrder)
disposal = DisposalMethod::RESTORE_BGCOLOR;
}
else {
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
if (!m_preservePaletteOrder) {
// When m_lastDisposal was RESTORE_BGBOLOR it implies
// we will have to cover with colors the entire previous frameBounds plus
// the current frameBounds due to color changes, so we must start with
@ -1223,10 +1216,10 @@ private:
disposal = DisposalMethod::RESTORE_BGCOLOR;
}
}
if (m_preservePaletteOrder)
disposal = DisposalMethod::RESTORE_BGCOLOR;
frameBounds = gfx::Rect(x1, y1, x2-x1+1, y2-y1+1);
}
else
disposal = DisposalMethod::RESTORE_BGCOLOR;
// We need to conditionate the deltaImage to the next step: 'writeImage()'
// To do it, we need to crop deltaImage in frameBounds.
@ -1368,7 +1361,11 @@ private:
// will be used in each processed frame.
PalettePicks usedColors(framePalette.size());
{
int localTransparent = m_transparentIndex;
ColorMapObject* colormap = m_globalColormap;
Remap remap(256);
if (!m_preservePaletteOrder) {
const LockImageBits<RgbTraits> srcBits(m_deltaImage.get());
LockImageBits<IndexedTraits> dstBits(frameImage.get());
@ -1414,16 +1411,12 @@ private:
*dstIt = i;
}
}
}
int usedNColors = usedColors.picks();
Remap remap(256);
for (int i=0; i<remap.size(); ++i)
remap.map(i, i);
int localTransparent = m_transparentIndex;
ColorMapObject* colormap = m_globalColormap;
if (!colormap) {
Palette reducedPalette(0, usedNColors);
@ -1442,6 +1435,12 @@ private:
if (localTransparent >= 0 && m_transparentIndex != localTransparent)
remap.map(m_transparentIndex, localTransparent);
}
else {
frameImage.reset(Image::createCopy(m_deltaImage.get()));
for (int i=0; i<colormap->ColorCount; ++i)
remap.map(i, i);
}
// Write extension record.
writeExtension(gifFrame, frame, localTransparent,
@ -1664,6 +1663,9 @@ private:
render.setNewBlend(m_fop->newBlend());
render.setBgType(render::BgType::NONE);
if (m_preservePaletteOrder)
clear_image(dst, m_bgIndex);
else
clear_image(dst, 0);
render.renderSprite(dst, m_sprite, frame);
}