Not reviewed, build fix.
[WebKit-https.git] / Source / WebCore / platform / image-decoders / webp / WEBPImageDecoder.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "WEBPImageDecoder.h"
31
32 #if USE(WEBP)
33
34 #include "webp/decode.h"
35
36 namespace WebCore {
37
38 WEBPImageDecoder::WEBPImageDecoder(ImageSource::AlphaOption alphaOption,
39                                    ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
40     : ImageDecoder(alphaOption, gammaAndColorProfileOption)
41 {
42 }
43
44 WEBPImageDecoder::~WEBPImageDecoder()
45 {
46 }
47
48 bool WEBPImageDecoder::isSizeAvailable()
49 {
50     if (!ImageDecoder::isSizeAvailable())
51          decode(true);
52
53     return ImageDecoder::isSizeAvailable();
54 }
55
56 ImageFrame* WEBPImageDecoder::frameBufferAtIndex(size_t index)
57 {
58     if (index)
59         return 0;
60
61     if (m_frameBufferCache.isEmpty()) {
62         m_frameBufferCache.resize(1);
63         m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
64     }
65
66     ImageFrame& frame = m_frameBufferCache[0];
67     if (frame.status() != ImageFrame::FrameComplete)
68         decode(false);
69     return &frame;
70 }
71
72
73 bool WEBPImageDecoder::decode(bool onlySize)
74 {
75     // Minimum number of bytes needed to ensure one can parse size information.
76     static const size_t sizeOfHeader = 30;
77     // Number of bytes per pixel.
78     static const int bytesPerPixel = 3;
79
80     if (failed())
81         return false;
82     const size_t dataSize = m_data->buffer().size();
83     const uint8_t* dataBytes =
84         reinterpret_cast<const uint8_t*>(m_data->buffer().data());
85     int width, height;
86     if (dataSize < sizeOfHeader)
87         return true;
88     if (!WebPGetInfo(dataBytes, dataSize, &width, &height))
89         return setFailed();
90     if (!ImageDecoder::isSizeAvailable() && !setSize(width, height))
91         return setFailed();
92     if (onlySize)
93         return true;
94
95     // FIXME: Add support for progressive decoding.
96     if (!isAllDataReceived())
97         return true;
98     ASSERT(!m_frameBufferCache.isEmpty());
99     ImageFrame& buffer = m_frameBufferCache[0];
100     if (buffer.status() == ImageFrame::FrameEmpty) {
101         ASSERT(width == size().width());
102         ASSERT(height == size().height());
103         if (!buffer.setSize(width, height))
104             return setFailed();
105     }
106     const int stride = width * bytesPerPixel;
107     Vector<uint8_t> rgb;
108     rgb.resize(height * stride);
109     if (!WebPDecodeBGRInto(dataBytes, dataSize, rgb.data(), rgb.size(), stride))
110         return setFailed();
111     // FIXME: remove this data copy.
112     for (int y = 0; y < height; ++y) {
113         const uint8_t* const src = &rgb[y * stride];
114         for (int x = 0; x < width; ++x)
115             buffer.setRGBA(x, y, src[bytesPerPixel * x + 2], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 0], 0xff);
116     }
117     buffer.setStatus(ImageFrame::FrameComplete);
118     buffer.setHasAlpha(false);
119     buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
120     return true;
121 }
122
123 }
124
125 #endif