aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/codec/SkCodec.cpp63
-rw-r--r--tests/CodecAnimTest.cpp22
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;
+ }
+ }
}
}
}