aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Leon Scroggins III <scroggo@google.com>2016-10-31 14:08:56 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-10-31 19:23:10 +0000
commitfc49b403eb3353fdefe97672017df10b64dee95a (patch)
tree492ff1afa99917513c071e53ba449c2822797573
parent7f650bdfd84aa54bf4fb94a2aef89ad931578e8b (diff)
Use correct color table for prior GIF frames
While investigating skbug.com/5883 I noticed that we use the color table for the current frame even while recursively decoding frames that the current frame depends on. This CL updates fCurrColorTable, fCurrColorTableIsReal and fSwizzler before decoding prior frames, and then sets them back afterwards. Move telling the client about the color table into prepareToDecode, since the other callers do not need to do so. (That is only necessary for decoding to index 8, which is unsupported for frames with dependencies.) Add a test that exposes the bug. colorTables.gif has a local color table in its second frame that does not match the global table used by the first frame. GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4208 Change-Id: Id2dc9e3283adfd92801d2f38726afa74574b1955 Reviewed-on: https://skia-review.googlesource.com/4208 Reviewed-by: Joost Ouwerling <joostouwerling@google.com> Reviewed-by: Matt Sarett <msarett@google.com> Commit-Queue: Leon Scroggins <scroggo@google.com>
-rw-r--r--resources/colorTables.gifbin0 -> 2829 bytes
-rw-r--r--src/codec/SkGifCodec.cpp28
-rw-r--r--src/codec/SkGifCodec.h13
-rw-r--r--tests/CodecAnimTest.cpp3
4 files changed, 21 insertions, 23 deletions
diff --git a/resources/colorTables.gif b/resources/colorTables.gif
new file mode 100644
index 0000000000..f25d13cfaa
--- /dev/null
+++ b/resources/colorTables.gif
Binary files differ
diff --git a/src/codec/SkGifCodec.cpp b/src/codec/SkGifCodec.cpp
index fe0a2b6623..13223960c8 100644
--- a/src/codec/SkGifCodec.cpp
+++ b/src/codec/SkGifCodec.cpp
@@ -139,8 +139,7 @@ std::vector<SkCodec::FrameInfo> SkGifCodec::onGetFrameInfo() {
return result;
}
-void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex,
- SkPMColor* inputColorPtr, int* inputColorCount) {
+void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex) {
fCurrColorTable = fReader->getColorTable(dstInfo.colorType(), frameIndex);
fCurrColorTableIsReal = fCurrColorTable;
if (!fCurrColorTable) {
@@ -148,12 +147,6 @@ void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, size_t frameIn
SkPMColor color = SK_ColorTRANSPARENT;
fCurrColorTable.reset(new SkColorTable(&color, 1));
}
-
- if (inputColorCount) {
- *inputColorCount = fCurrColorTable->count();
- }
-
- copy_color_table(dstInfo, fCurrColorTable.get(), inputColorPtr, inputColorCount);
}
@@ -215,9 +208,15 @@ SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo
fTmpBuffer.reset(new uint8_t[dstInfo.minRowBytes()]);
- // Initialize color table and copy to the client if necessary
- this->initializeColorTable(dstInfo, frameIndex, inputColorPtr, inputColorCount);
+ this->initializeColorTable(dstInfo, frameIndex);
this->initializeSwizzler(dstInfo, frameIndex);
+
+ SkASSERT(fCurrColorTable);
+ if (inputColorCount) {
+ *inputColorCount = fCurrColorTable->count();
+ }
+ copy_color_table(dstInfo, fCurrColorTable.get(), inputColorPtr, inputColorCount);
+
return kSuccess;
}
@@ -337,6 +336,11 @@ SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts,
Options prevFrameOpts(opts);
prevFrameOpts.fFrameIndex = frameContext->getRequiredFrame();
prevFrameOpts.fHasPriorFrame = false;
+ // The prior frame may have a different color table, so update it and the
+ // swizzler.
+ this->initializeColorTable(dstInfo, prevFrameOpts.fFrameIndex);
+ this->initializeSwizzler(dstInfo, prevFrameOpts.fFrameIndex);
+
const Result prevResult = this->decodeFrame(true, prevFrameOpts, nullptr);
switch (prevResult) {
case kSuccess:
@@ -348,6 +352,10 @@ SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts,
default:
return prevResult;
}
+
+ // Go back to using the correct color table for this frame.
+ this->initializeColorTable(dstInfo, frameIndex);
+ this->initializeSwizzler(dstInfo, frameIndex);
}
const auto* prevFrame = fReader->frameContext(frameContext->getRequiredFrame());
if (prevFrame->getDisposalMethod() == SkCodecAnimation::RestoreBGColor_DisposalMethod) {
diff --git a/src/codec/SkGifCodec.h b/src/codec/SkGifCodec.h
index b5f8f7ce0c..9d8e0e46bf 100644
--- a/src/codec/SkGifCodec.h
+++ b/src/codec/SkGifCodec.h
@@ -62,19 +62,8 @@ private:
*
* @param dstInfo Contains the requested dst color type.
* @param frameIndex Frame whose color table to use.
- * @param inputColorPtr Copies the encoded color table to the client's
- * input color table if the client requests kIndex8.
- * @param inputColorCount If the client requests kIndex8, this will be set
- * to the number of colors in the array that
- * inputColorPtr now points to. This will typically
- * be 256. Since gifs may have up to 8-bit indices,
- * using a 256-entry table means a pixel will never
- * be out of range. This will be set to 1 if there
- * is no color table, since that will be a
- * transparent frame.
*/
- void initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex,
- SkPMColor* colorPtr, int* inputColorCount);
+ void initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex);
/*
* Does necessary setup, including setting up the color table and swizzler,
diff --git a/tests/CodecAnimTest.cpp b/tests/CodecAnimTest.cpp
index fee6879a90..de36ce65d0 100644
--- a/tests/CodecAnimTest.cpp
+++ b/tests/CodecAnimTest.cpp
@@ -29,6 +29,7 @@ DEF_TEST(Codec_frames, r) {
{ "box.gif", 1, {}, {} },
{ "color_wheel.gif", 1, {}, {} },
{ "test640x479.gif", 4, { 0, 1, 2 }, { 200, 200, 200, 200 } },
+ { "colorTables.gif", 2, { 0 }, { 1000, 1000 } },
{ "arrow.png", 1, {}, {} },
{ "google_chrome.ico", 1, {}, {} },
@@ -67,7 +68,7 @@ DEF_TEST(Codec_frames, r) {
if (rec.fRequiredFrames.size() + 1 != expected) {
ERRORF(r, "'%s' has wrong number entries in fRequiredFrames; expected: %i\tactual: %i",
- rec.fName, expected, rec.fRequiredFrames.size());
+ rec.fName, expected, rec.fRequiredFrames.size() + 1);
continue;
}