Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3537)

Unified Diff: dm/DMSrcSink.cpp

Issue 2045293002: Add support for multiple frames in SkCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Various fixes Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dm/DMSrcSink.h ('k') | fuzz/fuzz.cpp » ('j') | gyp/codec.gyp » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dm/DMSrcSink.cpp
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 585a51d7fdf28df03783002819f7f3bce6998e5e..73702b56d4b03656422449d69906b914a421e1a4 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -410,7 +410,8 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
const int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
const size_t rowBytes = size.width() * bpp;
- SkAutoMalloc pixels(decodeInfo.getSafeSize(rowBytes));
+ const size_t safeSize = decodeInfo.getSafeSize(rowBytes);
+ SkAutoMalloc pixels(safeSize);
SkPMColor colorPtr[256];
int colorCount = 256;
@@ -427,6 +428,58 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
}
switch (fMode) {
+ case kAnimated_Mode: {
+ std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
+ if (frameInfos.size() <= 1) {
+ return SkStringPrintf("%s is not an animated image.", fPath.c_str());
+ }
+
+ SkAutoCanvasRestore acr(canvas, true);
+ // Used to cache a frame that future frames will depend on.
+ SkAutoMalloc priorFramePixels;
+ size_t cachedFrame = SkCodec::kIndependentFrame;
+ SkCodec::MultiFrameOptions multiOptions;
+ options.fFrameOptions = &multiOptions;
+ for (size_t i = 0; i < frameInfos.size(); i++) {
+ multiOptions.fIndex = i;
+ // Check for a prior frame
+ const size_t reqFrame = frameInfos[i].fRequiredFrame;
+ if (reqFrame != SkCodec::kIndependentFrame && reqFrame == cachedFrame
cblume 2016/10/14 16:52:35 I wonder if we can find a better name than kIndepe
scroggo_chromium 2016/10/14 19:55:59 I understand your confusion, and I'm not opposed t
cblume 2016/10/18 21:57:32 I agree that I'm not a fan of kNotFound. It wasn't
scroggo_chromium 2016/10/20 17:57:12 Done.
+ && priorFramePixels.get()) {
+ // Copy into pixels
+ memcpy(pixels.get(), priorFramePixels.get(), safeSize);
+ multiOptions.fHasPriorFrame = true;
+ } else {
+ multiOptions.fHasPriorFrame = false;
+ }
+ const SkCodec::Result result = codec->getPixels(decodeInfo, pixels.get(),
+ rowBytes, &options,
+ colorPtr, &colorCount);
+ switch (result) {
+ case SkCodec::kSuccess:
+ case SkCodec::kIncompleteInput:
+ draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes,
+ colorPtr, colorCount, fDstColorType);
+ if (result == SkCodec::kIncompleteInput) {
+ return "";
+ }
+ break;
+ default:
+ return SkStringPrintf("Couldn't getPixels for frame %i in %s.",
+ i, fPath.c_str());
+ }
+
+ // If a future frame depends on this one, store it in priorFrame.
+ // (Note that if i+1 does *not* depend on i, then no future frame can.)
+ if (i+1 < frameInfos.size() && frameInfos[i+1].fRequiredFrame == i) {
+ memcpy(priorFramePixels.reset(safeSize), pixels.get(), safeSize);
+ cachedFrame = i;
+ }
cblume 2016/10/14 16:52:35 I like this way of dealing with DisposeOverwritePr
+
+ canvas->translate(SkIntToScalar(0), SkIntToScalar(decodeInfo.height()));
+ }
+ break;
+ }
case kCodecZeroInit_Mode:
case kCodec_Mode: {
switch (codec->getPixels(decodeInfo, pixels.get(), rowBytes, &options,
@@ -448,10 +501,12 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
case kScanline_Mode: {
void* dst = pixels.get();
uint32_t height = decodeInfo.height();
- const bool png = fPath.endsWith("png");
+ const bool useIncremental = fPath.endsWith("png") || fPath.endsWith("gif") || fPath.endsWith("GIF");
msarett 2016/10/14 14:58:50 nit: 100 chars nit: Should we defensively add PNG
cblume 2016/10/14 16:52:35 or just toLower
scroggo_chromium 2016/10/14 19:55:59 done
+ // ico may use the old scanline method or the new one, depending on whether it
+ // internally holds a bmp or a png.
const bool ico = fPath.endsWith("ico");
- bool useOldScanlineMethod = !png && !ico;
- if (png || ico) {
+ bool useOldScanlineMethod = !useIncremental && !ico;
+ if (useIncremental || ico) {
if (SkCodec::kSuccess == codec->startIncrementalDecode(decodeInfo, dst,
rowBytes, nullptr, colorPtr, &colorCount)) {
int rowsDecoded;
@@ -461,8 +516,8 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
rowsDecoded);
}
} else {
- if (png) {
- // Error: PNG should support incremental decode.
+ if (useIncremental) {
+ // Error: These should support incremental decode.
return "Could not start incremental decode";
}
// Otherwise, this is an ICO. Since incremental failed, it must contain a BMP,
@@ -484,17 +539,6 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
// image, memory will be filled with a default value.
codec->getScanlines(dst, height, rowBytes);
break;
- case SkCodec::kOutOfOrder_SkScanlineOrder: {
- for (int y = 0; y < decodeInfo.height(); y++) {
- int dstY = codec->outputScanline(y);
- void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY);
- // We complete the loop, even if this call begins to fail
- // due to an incomplete image. This ensures any uninitialized
- // memory will be filled with the proper value.
- codec->getScanlines(dstPtr, 1, rowBytes);
- }
- break;
- }
}
}
@@ -660,7 +704,14 @@ SkISize CodecSrc::size() const {
if (nullptr == codec) {
return SkISize::Make(0, 0);
}
- return codec->getScaledDimensions(fScale);
+
+ auto imageSize = codec->getScaledDimensions(fScale);
+ if (fMode == kAnimated_Mode) {
+ // We'll draw one of each frame, so make it big enough to hold them all.
+ const size_t count = codec->getFrameInfo().size();
+ imageSize.fHeight = imageSize.fHeight * count;
+ }
+ return imageSize;
}
Name CodecSrc::name() const {
« no previous file with comments | « dm/DMSrcSink.h ('k') | fuzz/fuzz.cpp » ('j') | gyp/codec.gyp » ('J')

Powered by Google App Engine
This is Rietveld 408576698