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

Unified Diff: Source/core/platform/image-decoders/webp/WEBPImageDecoder.cpp

Issue 23068027: Animated WebP: Optimize decoding in case of seeking (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@add_noblend_image
Patch Set: Fix assert fail on debug Created 7 years, 4 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
Index: Source/core/platform/image-decoders/webp/WEBPImageDecoder.cpp
diff --git a/Source/core/platform/image-decoders/webp/WEBPImageDecoder.cpp b/Source/core/platform/image-decoders/webp/WEBPImageDecoder.cpp
index 12c15e1c113a74e61b92076dc565d6f1d7b1958d..3c3ec9c44c489be9a00bc4142038e95b177ead60 100644
--- a/Source/core/platform/image-decoders/webp/WEBPImageDecoder.cpp
+++ b/Source/core/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -127,13 +127,11 @@ ImageFrame* WEBPImageDecoder::frameBufferAtIndex(size_t index)
ASSERT(m_demux);
for (size_t i = framesToDecode.size(); i > 0; --i) {
size_t frameIndex = framesToDecode[i - 1];
+ if ((m_formatFlags & ANIMATION_FLAG) && !initFrameBuffer(frameIndex))
+ return 0;
WebPIterator webpFrame;
if (!WebPDemuxGetFrame(m_demux, frameIndex + 1, &webpFrame))
return 0;
- if ((m_formatFlags & ANIMATION_FLAG) && !initFrameBuffer(webpFrame, frameIndex)) {
- WebPDemuxReleaseIterator(&webpFrame);
- return 0;
- }
PlatformInstrumentation::willDecodeImage("WEBP");
decode(webpFrame.fragment.bytes, webpFrame.fragment.size, false, frameIndex);
PlatformInstrumentation::didDecodeImage();
@@ -247,36 +245,34 @@ bool WEBPImageDecoder::updateDemuxer()
ASSERT(animatedFrame.complete == 1);
m_frameBufferCache[i].setDuration(animatedFrame.duration);
m_frameBufferCache[i].setDisposalMethod(animatedFrame.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? ImageFrame::DisposeOverwriteBgcolor : ImageFrame::DisposeKeep);
+ m_frameBufferCache[i].setAlphaBlendSource(animatedFrame.blend_method == WEBP_MUX_BLEND ? ImageFrame::BlendAtopPreviousFrame : ImageFrame::BlendAtopBgcolor);
+ IntRect frameRect(animatedFrame.x_offset, animatedFrame.y_offset, animatedFrame.width, animatedFrame.height);
+ // Make sure the frameRect doesn't extend outside the buffer.
+ if (frameRect.maxX() > size().width())
+ frameRect.setWidth(size().width() - animatedFrame.x_offset);
+ if (frameRect.maxY() > size().height())
+ frameRect.setHeight(size().height() - animatedFrame.y_offset);
+ m_frameBufferCache[i].setOriginalFrameRect(frameRect);
+ m_frameBufferCache[i].setRequiredPreviousFrameIndex(findRequiredPreviousFrame(i, !animatedFrame.has_alpha));
WebPDemuxReleaseIterator(&animatedFrame);
- m_frameBufferCache[i].setRequiredPreviousFrameIndex(findRequiredPreviousFrame(i));
}
}
return true;
}
-bool WEBPImageDecoder::initFrameBuffer(const WebPIterator& frame, size_t frameIndex)
+bool WEBPImageDecoder::initFrameBuffer(size_t frameIndex)
{
ImageFrame& buffer = m_frameBufferCache[frameIndex];
if (buffer.status() != ImageFrame::FrameEmpty) // Already initialized.
return true;
- // Initialize the frame rect in our buffer.
- IntRect frameRect(frame.x_offset, frame.y_offset, frame.width, frame.height);
-
- // Make sure the frameRect doesn't extend outside the buffer.
- if (frameRect.maxX() > size().width())
- frameRect.setWidth(size().width() - frame.x_offset);
- if (frameRect.maxY() > size().height())
- frameRect.setHeight(size().height() - frame.y_offset);
- buffer.setOriginalFrameRect(frameRect);
-
const size_t requiredPreviousFrameIndex = buffer.requiredPreviousFrameIndex();
if (requiredPreviousFrameIndex == notFound) {
// This frame doesn't rely on any previous data.
if (!buffer.setSize(size().width(), size().height()))
return setFailed();
- m_frameBackgroundHasAlpha = !frameRect.contains(IntRect(IntPoint(), size()));
+ m_frameBackgroundHasAlpha = !buffer.originalFrameRect().contains(IntRect(IntPoint(), size()));
} else {
const ImageFrame& prevBuffer = m_frameBufferCache[requiredPreviousFrameIndex];
ASSERT(prevBuffer.status() == ImageFrame::FrameComplete);
@@ -415,15 +411,15 @@ void WEBPImageDecoder::applyPostProcessing(size_t frameIndex)
// During the decoding of current frame, we may have set some pixels to be transparent (i.e. alpha < 255).
// However, the value of each of these pixels should have been determined by blending it against the value
- // of that pixel in the previous frame. So, we correct these pixels based on disposal method of the previous
- // frame and the previous frame buffer.
+ // of that pixel in the previous frame if alpha blend source was 'BlendAtopPreviousFrame'. So, we correct these
+ // pixels based on disposal method of the previous frame and the previous frame buffer.
// FIXME: This could be avoided if libwebp decoder had an API that used the previous required frame
// to do the alpha-blending by itself.
- if ((m_formatFlags & ANIMATION_FLAG) && frameIndex) {
+ if ((m_formatFlags & ANIMATION_FLAG) && frameIndex && buffer.alphaBlendSource() == ImageFrame::BlendAtopPreviousFrame && buffer.requiredPreviousFrameIndex() != notFound) {
ImageFrame& prevBuffer = m_frameBufferCache[frameIndex - 1];
- ImageFrame::FrameDisposalMethod prevMethod = prevBuffer.disposalMethod();
- if (prevMethod == ImageFrame::DisposeKeep) { // Restore transparent pixels to pixels in previous canvas.
- ASSERT(prevBuffer.status() == ImageFrame::FrameComplete);
+ ASSERT(prevBuffer.status() == ImageFrame::FrameComplete);
+ ImageFrame::DisposalMethod prevDisposalMethod = prevBuffer.disposalMethod();
+ if (prevDisposalMethod == ImageFrame::DisposeKeep) { // Restore transparent pixels to pixels in previous canvas.
for (int y = m_decodedHeight; y < decodedHeight; ++y) {
const int canvasY = top + y;
for (int x = 0; x < width; ++x) {
@@ -437,9 +433,7 @@ void WEBPImageDecoder::applyPostProcessing(size_t frameIndex)
}
}
}
- } else if (prevMethod == ImageFrame::DisposeOverwriteBgcolor && buffer.requiredPreviousFrameIndex() != notFound) {
- // Note: if the requiredPreviousFrameIndex is |notFound|, there's nothing to do.
- ASSERT(prevBuffer.status() == ImageFrame::FrameComplete);
+ } else if (prevDisposalMethod == ImageFrame::DisposeOverwriteBgcolor) {
const IntRect& prevRect = prevBuffer.originalFrameRect();
// We need to restore transparent pixels to as they were just after initFrame() call. That is:
// * Transparent if it belongs to prevRect <-- This is a no-op.

Powered by Google App Engine
This is Rietveld 408576698