2011-04-18 Pascal Massimino <pascal.massimino@gmail.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Apr 2011 03:43:24 +0000 (03:43 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Apr 2011 03:43:24 +0000 (03:43 +0000)
        Reviewed by Adam Barth.

        Add incremental decoding to WebP decoder
        https://bugs.webkit.org/show_bug.cgi?id=58851

        No new tests, as it's not possible for the layout test framework to
        force the decoders to decode incrementally.

        * platform/image-decoders/webp/WEBPImageDecoder.cpp:
        (WebCore::WEBPImageDecoder::WEBPImageDecoder):
        (WebCore::WEBPImageDecoder::decode):
        * platform/image-decoders/webp/WEBPImageDecoder.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@84219 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h

index 939277e..e7a9cd5 100644 (file)
@@ -1,3 +1,18 @@
+2011-04-18  Pascal Massimino  <pascal.massimino@gmail.com>
+
+        Reviewed by Adam Barth.
+
+        Add incremental decoding to WebP decoder
+        https://bugs.webkit.org/show_bug.cgi?id=58851
+
+        No new tests, as it's not possible for the layout test framework to
+        force the decoders to decode incrementally.
+
+        * platform/image-decoders/webp/WEBPImageDecoder.cpp:
+        (WebCore::WEBPImageDecoder::WEBPImageDecoder):
+        (WebCore::WEBPImageDecoder::decode):
+        * platform/image-decoders/webp/WEBPImageDecoder.h:
+
 2011-04-18  Daniel Bates  <dbates@rim.com>
 
         Reviewed by Adam Roben.
index 060c62a..eacfd29 100644 (file)
@@ -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;
 }
 
 }
index c32e047..53da91f 100644 (file)
@@ -33,6 +33,9 @@
 
 #if USE(WEBP)
 
+// Forward declaration of libwebp's structure. Must be outside the WebCore scope.
+typedef struct WebPIDecoder WebPIDecoder;
+
 namespace WebCore {
 
 class WEBPImageDecoder : public ImageDecoder {
@@ -46,6 +49,10 @@ public:
 private:
     // Returns false in case of decoding failure.
     bool decode(bool onlySize);
+
+    WebPIDecoder* m_decoder; // This is only used when we want to decode() but not all data is available yet.
+    int m_lastVisibleRow;
+    Vector<uint8_t> m_rgbOutput;
 };
 
 } // namespace WebCore