diff options
-rw-r--r-- | src/codec/SkCodec.cpp | 63 | ||||
-rw-r--r-- | tests/CodecAnimTest.cpp | 22 |
2 files changed, 54 insertions, 31 deletions
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp index bf12ad2625..d9992c0cd9 100644 --- a/src/codec/SkCodec.cpp +++ b/src/codec/SkCodec.cpp @@ -208,16 +208,37 @@ bool SkCodec::rewindIfNeeded() { return this->onRewind(); } -static void zero_rect(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes, - SkIRect frameRect) { - if (!frameRect.intersect(dstInfo.bounds())) { - return; +bool zero_rect(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes, + SkISize srcDimensions, SkIRect prevRect) { + const auto dimensions = dstInfo.dimensions(); + if (dimensions != srcDimensions) { + SkRect src = SkRect::Make(srcDimensions); + SkRect dst = SkRect::Make(dimensions); + SkMatrix map = SkMatrix::MakeRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit); + SkRect asRect = SkRect::Make(prevRect); + if (!map.mapRect(&asRect)) { + return false; + } + asRect.roundIn(&prevRect); + if (prevRect.isEmpty()) { + // Down-scaling shrank the empty portion to nothing, + // so nothing to zero. + return true; + } } - const auto info = dstInfo.makeWH(frameRect.width(), frameRect.height()); + + if (!prevRect.intersect(dstInfo.bounds())) { + SkCodecPrintf("rectangles do not intersect!"); + SkASSERT(false); + return true; + } + + const SkImageInfo info = dstInfo.makeWH(prevRect.width(), prevRect.height()); const size_t bpp = dstInfo.bytesPerPixel(); - const size_t offset = frameRect.x() * bpp + frameRect.y() * rowBytes; - auto* eraseDst = SkTAddOffset<void>(pixels, offset); + const size_t offset = prevRect.x() * bpp + prevRect.y() * rowBytes; + void* eraseDst = SkTAddOffset<void>(pixels, offset); SkSampler::Fill(info, eraseDst, rowBytes, 0, SkCodec::kNo_ZeroInitialized); + return true; } SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, size_t rowBytes, @@ -276,28 +297,9 @@ SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, // need to clear, since it must be covered by the desired frame. if (options.fPriorFrame == requiredFrame) { SkIRect prevRect = prevFrame->frameRect(); - if (info.dimensions() != fSrcInfo.dimensions()) { - auto src = SkRect::Make(fSrcInfo.dimensions()); - auto dst = SkRect::Make(info.dimensions()); - SkMatrix map = SkMatrix::MakeRectToRect(src, dst, - SkMatrix::kCenter_ScaleToFit); - SkRect asRect = SkRect::Make(prevRect); - if (!map.mapRect(&asRect)) { - return kInternalError; - } - asRect.roundIn(&prevRect); - if (prevRect.isEmpty()) { - // Down-scaling shrank the empty portion to nothing, - // so nothing to zero. - break; - } - if (!prevRect.intersect(SkIRect::MakeSize(info.dimensions()))) { - SkCodecPrintf("rectangles do not intersect!"); - SkASSERT(false); - break; - } + if (!zero_rect(info, pixels, rowBytes, fSrcInfo.dimensions(), prevRect)) { + return kInternalError; } - zero_rect(info, pixels, rowBytes, prevRect); } break; default: @@ -314,7 +316,10 @@ SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, const auto* prevFrame = frameHolder->getFrame(requiredFrame); const auto disposalMethod = prevFrame->getDisposalMethod(); if (disposalMethod == SkCodecAnimation::DisposalMethod::kRestoreBGColor) { - zero_rect(info, pixels, rowBytes, prevFrame->frameRect()); + auto prevRect = prevFrame->frameRect(); + if (!zero_rect(info, pixels, rowBytes, fSrcInfo.dimensions(), prevRect)) { + return kInternalError; + } } } } diff --git a/tests/CodecAnimTest.cpp b/tests/CodecAnimTest.cpp index a3e16c6aa5..4e069c17fb 100644 --- a/tests/CodecAnimTest.cpp +++ b/tests/CodecAnimTest.cpp @@ -422,9 +422,27 @@ DEF_TEST(AndroidCodec_animated, r) { options.fPriorFrame = i - 1; info = info.makeAlphaType(frameInfo.fAlphaType); - const auto result = codec->codec()->getPixels(info, bm.getPixels(), bm.rowBytes(), - &options); + auto result = codec->codec()->getPixels(info, bm.getPixels(), bm.rowBytes(), + &options); REPORTER_ASSERT(r, result == SkCodec::kSuccess); + + // Now compare to not using prior frame. + SkBitmap bm2; + bm2.allocPixels(info); + + options.fPriorFrame = SkCodec::kNone; + result = codec->codec()->getPixels(info, bm2.getPixels(), bm2.rowBytes(), + &options); + REPORTER_ASSERT(r, result == SkCodec::kSuccess); + + for (int y = 0; y < info.height(); ++y) { + if (memcmp(bm.getAddr32(0, y), bm2.getAddr32(0, y), info.minRowBytes())) { + ERRORF(r, "pixel mismatch for sample size %i, frame %i resulting in " + "dimensions %i x %i line %i\n", + sampleSize, i, info.width(), info.height(), y); + break; + } + } } } } |