REGRESSION(r198782, r201043): [image-decoders] Flickering with some animated gif
[WebKit-https.git] / Source / WebCore / platform / image-decoders / ImageDecoder.cpp
1 /*
2  * Copyright (C) 2016 Apple Inc.  All rights reserved.
3  * Copyright (C) 2008-2009 Torch Mobile, Inc.
4  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "ImageDecoder.h"
25
26 #include "BMPImageDecoder.h"
27 #include "GIFImageDecoder.h"
28 #include "ICOImageDecoder.h"
29 #include "JPEGImageDecoder.h"
30 #include "PNGImageDecoder.h"
31 #include "SharedBuffer.h"
32 #if USE(WEBP)
33 #include "WEBPImageDecoder.h"
34 #endif
35
36 #include <algorithm>
37 #include <cmath>
38
39 using namespace std;
40
41 namespace WebCore {
42
43 namespace {
44
45 unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
46 {
47     unsigned bytesExtracted = 0;
48     const char* moreData;
49     while (unsigned moreDataLength = sharedBuffer.getSomeData(moreData, offset)) {
50         unsigned bytesToCopy = min(bufferLength - bytesExtracted, moreDataLength);
51         memcpy(buffer + bytesExtracted, moreData, bytesToCopy);
52         bytesExtracted += bytesToCopy;
53         if (bytesExtracted == bufferLength)
54             break;
55         offset += bytesToCopy;
56     }
57     return bytesExtracted;
58 }
59
60 bool matchesGIFSignature(char* contents)
61 {
62     return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6);
63 }
64
65 bool matchesPNGSignature(char* contents)
66 {
67     return !memcmp(contents, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8);
68 }
69
70 bool matchesJPEGSignature(char* contents)
71 {
72     return !memcmp(contents, "\xFF\xD8\xFF", 3);
73 }
74
75 #if USE(WEBP)
76 bool matchesWebPSignature(char* contents)
77 {
78     return !memcmp(contents, "RIFF", 4) && !memcmp(contents + 8, "WEBPVP", 6);
79 }
80 #endif
81
82 bool matchesBMPSignature(char* contents)
83 {
84     return !memcmp(contents, "BM", 2);
85 }
86
87 bool matchesICOSignature(char* contents)
88 {
89     return !memcmp(contents, "\x00\x00\x01\x00", 4);
90 }
91
92 bool matchesCURSignature(char* contents)
93 {
94     return !memcmp(contents, "\x00\x00\x02\x00", 4);
95 }
96
97 }
98
99 std::unique_ptr<ImageDecoder> ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
100 {
101     static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
102     char contents[lengthOfLongestSignature];
103     unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
104     if (length < lengthOfLongestSignature)
105         return nullptr;
106
107     if (matchesGIFSignature(contents))
108         return std::unique_ptr<ImageDecoder> { std::make_unique<GIFImageDecoder>(alphaOption, gammaAndColorProfileOption) };
109
110     if (matchesPNGSignature(contents))
111         return std::unique_ptr<ImageDecoder> { std::make_unique<PNGImageDecoder>(alphaOption, gammaAndColorProfileOption) };
112
113     if (matchesICOSignature(contents) || matchesCURSignature(contents))
114         return std::unique_ptr<ImageDecoder> { std::make_unique<ICOImageDecoder>(alphaOption, gammaAndColorProfileOption) };
115
116     if (matchesJPEGSignature(contents))
117         return std::unique_ptr<ImageDecoder> { std::make_unique<JPEGImageDecoder>(alphaOption, gammaAndColorProfileOption) };
118
119 #if USE(WEBP)
120     if (matchesWebPSignature(contents))
121         return std::unique_ptr<ImageDecoder> { std::make_unique<WEBPImageDecoder>(alphaOption, gammaAndColorProfileOption) };
122 #endif
123
124     if (matchesBMPSignature(contents))
125         return std::unique_ptr<ImageDecoder> { std::make_unique<BMPImageDecoder>(alphaOption, gammaAndColorProfileOption) };
126
127     return nullptr;
128 }
129
130 ImageFrame::ImageFrame()
131     : m_hasAlpha(false)
132     , m_status(FrameEmpty)
133     , m_duration(0)
134     , m_disposalMethod(DisposeNotSpecified)
135     , m_premultiplyAlpha(true)
136 {
137
138
139 ImageFrame& ImageFrame::operator=(const ImageFrame& other)
140 {
141     if (this == &other)
142         return *this;
143
144     copyBitmapData(other);
145     setOriginalFrameRect(other.originalFrameRect());
146     setStatus(other.status());
147     setDuration(other.duration());
148     setDisposalMethod(other.disposalMethod());
149     setPremultiplyAlpha(other.premultiplyAlpha());
150     return *this;
151 }
152
153 void ImageFrame::clearPixelData()
154 {
155     m_backingStore.clear();
156     m_bytes = 0;
157     m_status = FrameEmpty;
158     // NOTE: Do not reset other members here; clearFrameBufferCache() calls this
159     // to free the bitmap data, but other functions like initFrameBuffer() and
160     // frameComplete() may still need to read other metadata out of this frame
161     // later.
162 }
163
164 void ImageFrame::zeroFillPixelData()
165 {
166     memset(m_bytes, 0, m_size.width() * m_size.height() * sizeof(PixelData));
167     m_hasAlpha = true;
168 }
169
170 void ImageFrame::zeroFillFrameRect(const IntRect& rect)
171 {
172     ASSERT(IntRect(IntPoint(), m_size).contains(rect));
173
174     if (rect.isEmpty())
175         return;
176
177     size_t rectWidthInBytes = rect.width() * sizeof(PixelData);
178     PixelData* start = m_bytes + (rect.y() * width()) + rect.x();
179     for (int i = 0; i < rect.height(); ++i) {
180         memset(start, 0, rectWidthInBytes);
181         start += width();
182     }
183
184     setHasAlpha(true);
185 }
186
187 bool ImageFrame::copyBitmapData(const ImageFrame& other)
188 {
189     if (this == &other)
190         return true;
191
192     m_backingStore = other.m_backingStore;
193     m_bytes = m_backingStore.data();
194     m_size = other.m_size;
195     setHasAlpha(other.m_hasAlpha);
196     return true;
197 }
198
199 bool ImageFrame::setSize(int newWidth, int newHeight)
200 {
201     ASSERT(!width() && !height());
202     size_t backingStoreSize = newWidth * newHeight;
203     if (!m_backingStore.tryReserveCapacity(backingStoreSize))
204         return false;
205     m_backingStore.resize(backingStoreSize);
206     m_bytes = m_backingStore.data();
207     m_size = IntSize(newWidth, newHeight);
208
209     zeroFillPixelData();
210     return true;
211 }
212
213 bool ImageFrame::hasAlpha() const
214 {
215     return m_hasAlpha;
216 }
217
218 void ImageFrame::setHasAlpha(bool alpha)
219 {
220     m_hasAlpha = alpha;
221 }
222
223 void ImageFrame::setColorProfile(const ColorProfile& colorProfile)
224 {
225     m_colorProfile = colorProfile;
226 }
227
228 void ImageFrame::setStatus(FrameStatus status)
229 {
230     m_status = status;
231 }
232
233 namespace {
234
235 enum MatchType {
236     Exact,
237     UpperBound,
238     LowerBound
239 };
240
241 inline void fillScaledValues(Vector<int>& scaledValues, double scaleRate, int length)
242 {
243     double inflateRate = 1. / scaleRate;
244     scaledValues.reserveCapacity(static_cast<int>(length * scaleRate + 0.5));
245     for (int scaledIndex = 0; ; ++scaledIndex) {
246         int index = static_cast<int>(scaledIndex * inflateRate + 0.5);
247         if (index >= length)
248             break;
249         scaledValues.append(index);
250     }
251 }
252
253 template <MatchType type> int getScaledValue(const Vector<int>& scaledValues, int valueToMatch, int searchStart)
254 {
255     if (scaledValues.isEmpty())
256         return valueToMatch;
257
258     const int* dataStart = scaledValues.data();
259     const int* dataEnd = dataStart + scaledValues.size();
260     const int* matched = std::lower_bound(dataStart + searchStart, dataEnd, valueToMatch);
261     switch (type) {
262     case Exact:
263         return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : -1;
264     case LowerBound:
265         return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : matched - dataStart - 1;
266     case UpperBound:
267     default:
268         return matched != dataEnd ? matched - dataStart : -1;
269     }
270 }
271
272 }
273
274 bool ImageDecoder::frameIsCompleteAtIndex(size_t index)
275 {
276     ImageFrame* buffer = frameBufferAtIndex(index);
277     return buffer && buffer->status() == ImageFrame::FrameComplete;
278 }
279
280 bool ImageDecoder::frameHasAlphaAtIndex(size_t index) const
281 {
282     if (m_frameBufferCache.size() <= index)
283         return true;
284     if (m_frameBufferCache[index].status() == ImageFrame::FrameComplete)
285         return m_frameBufferCache[index].hasAlpha();
286     return true;
287 }
288
289 unsigned ImageDecoder::frameBytesAtIndex(size_t index) const
290 {
291     if (m_frameBufferCache.size() <= index)
292         return 0;
293     // FIXME: Use the dimension of the requested frame.
294     return m_size.area() * sizeof(ImageFrame::PixelData);
295 }
296
297 float ImageDecoder::frameDurationAtIndex(size_t index)
298 {
299     ImageFrame* buffer = frameBufferAtIndex(index);
300     if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
301         return 0;
302     
303     // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
304     // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
305     // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
306     // for more information.
307     const float duration = buffer->duration() / 1000.0f;
308     if (duration < 0.011f)
309         return 0.100f;
310     return duration;
311 }
312
313 NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel)
314 {
315     ImageFrame* buffer = frameBufferAtIndex(index);
316     // Zero-height images can cause problems for some ports. If we have an empty image dimension, just bail.
317     // It's important to check the size after calling frameBufferAtIndex() to ensure the decoder has updated the size.
318     // See https://bugs.webkit.org/show_bug.cgi?id=159089.
319     if (!buffer || buffer->status() == ImageFrame::FrameEmpty || size().isEmpty())
320         return nullptr;
321
322     // Return the buffer contents as a native image. For some ports, the data
323     // is already in a native container, and this just increments its refcount.
324     return buffer->asNewNativeImage();
325 }
326
327 void ImageDecoder::prepareScaleDataIfNecessary()
328 {
329     m_scaled = false;
330     m_scaledColumns.clear();
331     m_scaledRows.clear();
332
333     int width = size().width();
334     int height = size().height();
335     int numPixels = height * width;
336     if (m_maxNumPixels <= 0 || numPixels <= m_maxNumPixels)
337         return;
338
339     m_scaled = true;
340     double scale = sqrt(m_maxNumPixels / (double)numPixels);
341     fillScaledValues(m_scaledColumns, scale, width);
342     fillScaledValues(m_scaledRows, scale, height);
343 }
344
345 int ImageDecoder::upperBoundScaledX(int origX, int searchStart)
346 {
347     return getScaledValue<UpperBound>(m_scaledColumns, origX, searchStart);
348 }
349
350 int ImageDecoder::lowerBoundScaledX(int origX, int searchStart)
351 {
352     return getScaledValue<LowerBound>(m_scaledColumns, origX, searchStart);
353 }
354
355 int ImageDecoder::upperBoundScaledY(int origY, int searchStart)
356 {
357     return getScaledValue<UpperBound>(m_scaledRows, origY, searchStart);
358 }
359
360 int ImageDecoder::lowerBoundScaledY(int origY, int searchStart)
361 {
362     return getScaledValue<LowerBound>(m_scaledRows, origY, searchStart);
363 }
364
365 int ImageDecoder::scaledY(int origY, int searchStart)
366 {
367     return getScaledValue<Exact>(m_scaledRows, origY, searchStart);
368 }
369
370 }