summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp')
-rw-r--r--Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp57
1 files changed, 39 insertions, 18 deletions
diff --git a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
index 060c62a..eacfd29 100644
--- a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -38,6 +38,8 @@ namespace WebCore {
WEBPImageDecoder::WEBPImageDecoder(ImageSource::AlphaOption alphaOption,
ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
: ImageDecoder(alphaOption, gammaAndColorProfileOption)
+ , m_decoder(0)
+ , m_lastVisibleRow(0)
{
}
@@ -79,12 +81,13 @@ bool WEBPImageDecoder::decode(bool onlySize)
if (failed())
return false;
+
const size_t dataSize = m_data->size();
- const uint8_t* dataBytes =
- reinterpret_cast<const uint8_t*>(m_data->data());
- int width, height;
if (dataSize < sizeOfHeader)
return true;
+
+ int width, height;
+ const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data());
if (!WebPGetInfo(dataBytes, dataSize, &width, &height))
return setFailed();
if (!ImageDecoder::isSizeAvailable() && !setSize(width, height))
@@ -92,9 +95,8 @@ bool WEBPImageDecoder::decode(bool onlySize)
if (onlySize)
return true;
- // FIXME: Add support for progressive decoding.
- if (!isAllDataReceived())
- return true;
+ bool allDataReceived = isAllDataReceived();
+ int stride = width * bytesPerPixel;
ASSERT(!m_frameBufferCache.isEmpty());
ImageFrame& buffer = m_frameBufferCache[0];
if (buffer.status() == ImageFrame::FrameEmpty) {
@@ -102,22 +104,41 @@ bool WEBPImageDecoder::decode(bool onlySize)
ASSERT(height == size().height());
if (!buffer.setSize(width, height))
return setFailed();
+ buffer.setStatus(allDataReceived ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
+ // FIXME: We currently hard code false below because libwebp doesn't support alpha yet.
+ buffer.setHasAlpha(false);
+ buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
+ m_rgbOutput.resize(height * stride);
+ }
+ int newLastVisibleRow = 0; // Last completed row.
+ if (allDataReceived) {
+ if (!WebPDecodeRGBInto(dataBytes, dataSize, m_rgbOutput.data(), m_rgbOutput.size(), stride))
+ return setFailed();
+ newLastVisibleRow = height;
+ } else {
+ if (!m_decoder) {
+ m_decoder = WebPINewRGB(MODE_RGB, m_rgbOutput.data(), m_rgbOutput.size(), stride);
+ if (!m_decoder)
+ return setFailed();
+ }
+ const VP8StatusCode status = WebPIUpdate(m_decoder, dataBytes, dataSize);
+ if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED)
+ return setFailed();
+ if (!WebPIDecGetRGB(m_decoder, &newLastVisibleRow, 0, 0, 0))
+ return setFailed();
+ ASSERT(newLastVisibleRow >= 0);
+ ASSERT(newLastVisibleRow <= height);
}
- const int stride = width * bytesPerPixel;
- Vector<uint8_t> rgb;
- rgb.resize(height * stride);
- if (!WebPDecodeBGRInto(dataBytes, dataSize, rgb.data(), rgb.size(), stride))
- return setFailed();
// FIXME: remove this data copy.
- for (int y = 0; y < height; ++y) {
- const uint8_t* const src = &rgb[y * stride];
+ for (int y = m_lastVisibleRow; y < newLastVisibleRow; ++y) {
+ const uint8_t* const src = &m_rgbOutput[y * stride];
for (int x = 0; x < width; ++x)
- buffer.setRGBA(x, y, src[bytesPerPixel * x + 2], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 0], 0xff);
+ buffer.setRGBA(x, y, src[bytesPerPixel * x + 0], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 2], 0xff);
}
- buffer.setStatus(ImageFrame::FrameComplete);
- buffer.setHasAlpha(false);
- buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
- return true;
+ m_lastVisibleRow = newLastVisibleRow;
+ if (m_lastVisibleRow == height)
+ buffer.setStatus(ImageFrame::FrameComplete);
+ return m_lastVisibleRow == height;
}
}