• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 Apple Computer, 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  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef ImageDecoder_h
30 #define ImageDecoder_h
31 
32 #include "IntRect.h"
33 #include "ImageSource.h"
34 #include "PlatformString.h"
35 #include "SharedBuffer.h"
36 #include <wtf/Assertions.h>
37 #include <wtf/RefPtr.h>
38 #include <wtf/Vector.h>
39 
40 #if USE(SKIA)
41 #include "NativeImageSkia.h"
42 #include "SkColorPriv.h"
43 #elif PLATFORM(QT)
44 #include <QPixmap>
45 #include <QImage>
46 #endif
47 
48 namespace WebCore {
49 
50     // FIXME: Do we want better encapsulation?
51     typedef Vector<char> ColorProfile;
52 
53     // ImageFrame represents the decoded image data.  This buffer is what all
54     // decoders write a single frame into.
55     class ImageFrame {
56     public:
57         enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
58         enum FrameDisposalMethod {
59             // If you change the numeric values of these, make sure you audit
60             // all users, as some users may cast raw values to/from these
61             // constants.
62             DisposeNotSpecified,      // Leave frame in framebuffer
63             DisposeKeep,              // Leave frame in framebuffer
64             DisposeOverwriteBgcolor,  // Clear frame to transparent
65             DisposeOverwritePrevious  // Clear frame to previous framebuffer
66                                       // contents
67         };
68 #if USE(SKIA) || PLATFORM(QT)
69         typedef uint32_t PixelData;
70 #else
71         typedef unsigned PixelData;
72 #endif
73 
74         ImageFrame();
75 
ImageFrame(const ImageFrame & other)76         ImageFrame(const ImageFrame& other) { operator=(other); }
77 
78         // For backends which refcount their data, this operator doesn't need to
79         // create a new copy of the image data, only increase the ref count.
80         ImageFrame& operator=(const ImageFrame& other);
81 
82         // These do not touch other metadata, only the raw pixel data.
83         void clearPixelData();
84         void zeroFillPixelData();
85 
86         // Makes this frame have an independent copy of the provided image's
87         // pixel data, so that modifications in one frame are not reflected in
88         // the other.  Returns whether the copy succeeded.
89         bool copyBitmapData(const ImageFrame&);
90 
91         // Makes this frame reference the provided image's pixel data, so that
92         // modifications in one frame are reflected in the other.
93         void copyReferenceToBitmapData(const ImageFrame&);
94 
95         // Copies the pixel data at [(startX, startY), (endX, startY)) to the
96         // same X-coordinates on each subsequent row up to but not including
97         // endY.
copyRowNTimes(int startX,int endX,int startY,int endY)98         void copyRowNTimes(int startX, int endX, int startY, int endY)
99         {
100             ASSERT(startX < width());
101             ASSERT(endX <= width());
102             ASSERT(startY < height());
103             ASSERT(endY <= height());
104             const int rowBytes = (endX - startX) * sizeof(PixelData);
105             const PixelData* const startAddr = getAddr(startX, startY);
106             for (int destY = startY + 1; destY < endY; ++destY)
107                 memcpy(getAddr(startX, destY), startAddr, rowBytes);
108         }
109 
110 #if PLATFORM(ANDROID)
bitmap()111         NativeImageSkia& bitmap() { return m_bitmap; }
bitmap()112         const NativeImageSkia& bitmap() const { return m_bitmap; }
113 #endif
114 
115         // Allocates space for the pixel data.  Must be called before any pixels
116         // are written.  Must only be called once.  Returns whether allocation
117         // succeeded.
118         bool setSize(int newWidth, int newHeight);
119 
120         // Returns a caller-owned pointer to the underlying native image data.
121         // (Actual use: This pointer will be owned by BitmapImage and freed in
122         // FrameData::clear()).
123         NativeImagePtr asNewNativeImage() const;
124 
125         bool hasAlpha() const;
originalFrameRect()126         const IntRect& originalFrameRect() const { return m_originalFrameRect; }
status()127         FrameStatus status() const { return m_status; }
duration()128         unsigned duration() const { return m_duration; }
disposalMethod()129         FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
premultiplyAlpha()130         bool premultiplyAlpha() const { return m_premultiplyAlpha; }
131 
132         void setHasAlpha(bool alpha);
133         void setColorProfile(const ColorProfile&);
setOriginalFrameRect(const IntRect & r)134         void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
135         void setStatus(FrameStatus status);
setDuration(unsigned duration)136         void setDuration(unsigned duration) { m_duration = duration; }
setDisposalMethod(FrameDisposalMethod method)137         void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
setPremultiplyAlpha(bool premultiplyAlpha)138         void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
139 
setRGBA(int x,int y,unsigned r,unsigned g,unsigned b,unsigned a)140         inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
141         {
142             setRGBA(getAddr(x, y), r, g, b, a);
143         }
144 
145 #if PLATFORM(QT)
146         void setPixmap(const QPixmap& pixmap);
147 #endif
148 
149     private:
150 #if USE(CG)
151         typedef RetainPtr<CFMutableDataRef> NativeBackingStore;
152 #else
153         typedef Vector<PixelData> NativeBackingStore;
154 #endif
155 
156         int width() const;
157         int height() const;
158 
getAddr(int x,int y)159         inline PixelData* getAddr(int x, int y)
160         {
161 #if USE(SKIA)
162             return m_bitmap.getAddr32(x, y);
163 #elif PLATFORM(QT)
164             m_image = m_pixmap.toImage();
165             m_pixmap = QPixmap();
166             return reinterpret_cast_ptr<QRgb*>(m_image.scanLine(y)) + x;
167 #else
168             return m_bytes + (y * width()) + x;
169 #endif
170         }
171 
setRGBA(PixelData * dest,unsigned r,unsigned g,unsigned b,unsigned a)172         inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
173         {
174             if (m_premultiplyAlpha && !a)
175                 *dest = 0;
176             else {
177                 if (m_premultiplyAlpha && a < 255) {
178                     float alphaPercent = a / 255.0f;
179                     r = static_cast<unsigned>(r * alphaPercent);
180                     g = static_cast<unsigned>(g * alphaPercent);
181                     b = static_cast<unsigned>(b * alphaPercent);
182                 }
183 #if USE(SKIA)
184                 // we are sure to call the NoCheck version, since we may
185                 // deliberately pass non-premultiplied values, and we don't want
186                 // an assert.
187                 *dest = SkPackARGB32NoCheck(a, r, g, b);
188 #else
189                 *dest = (a << 24 | r << 16 | g << 8 | b);
190 #endif
191             }
192         }
193 
194 #if USE(SKIA)
195         NativeImageSkia m_bitmap;
196 #elif PLATFORM(QT)
197         mutable QPixmap m_pixmap;
198         mutable QImage m_image;
199         bool m_hasAlpha;
200         IntSize m_size;
201 #else
202         NativeBackingStore m_backingStore;
203         PixelData* m_bytes; // The memory is backed by m_backingStore.
204         IntSize m_size;
205         bool m_hasAlpha;
206         ColorProfile m_colorProfile;
207 #endif
208         IntRect m_originalFrameRect; // This will always just be the entire
209                                      // buffer except for GIF frames whose
210                                      // original rect was smaller than the
211                                      // overall image size.
212         FrameStatus m_status;
213         unsigned m_duration;
214         FrameDisposalMethod m_disposalMethod;
215         bool m_premultiplyAlpha;
216     };
217 
218     // ImageDecoder is a base for all format-specific decoders
219     // (e.g. JPEGImageDecoder).  This base manages the ImageFrame cache.
220     //
221     // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample
222     // at decode time.  Image decoders will downsample any images larger than
223     // |m_maxNumPixels|.  FIXME: Not yet supported by all decoders.
224     class ImageDecoder {
225         WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
226     public:
ImageDecoder(ImageSource::AlphaOption alphaOption,ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)227         ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
228             : m_scaled(false)
229             , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
230             , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored)
231             , m_sizeAvailable(false)
232             , m_maxNumPixels(-1)
233             , m_isAllDataReceived(false)
234             , m_failed(false) { }
235 
~ImageDecoder()236         virtual ~ImageDecoder() { }
237 
238         // Returns a caller-owned decoder of the appropriate type.  Returns 0 if
239         // we can't sniff a supported type from the provided data (possibly
240         // because there isn't enough data yet).
241         static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
242 
243         virtual String filenameExtension() const = 0;
244 
isAllDataReceived()245         bool isAllDataReceived() const { return m_isAllDataReceived; }
246 
setData(SharedBuffer * data,bool allDataReceived)247         virtual void setData(SharedBuffer* data, bool allDataReceived)
248         {
249             if (m_failed)
250                 return;
251             m_data = data;
252             m_isAllDataReceived = allDataReceived;
253         }
254 
255         // Lazily-decodes enough of the image to get the size (if possible).
256         // FIXME: Right now that has to be done by each subclass; factor the
257         // decode call out and use it here.
isSizeAvailable()258         virtual bool isSizeAvailable()
259         {
260             return !m_failed && m_sizeAvailable;
261         }
262 
size()263         virtual IntSize size() const { return m_size; }
264 
scaledSize()265         IntSize scaledSize() const
266         {
267             return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size();
268         }
269 
270         // This will only differ from size() for ICO (where each frame is a
271         // different icon) or other formats where different frames are different
272         // sizes.  This does NOT differ from size() for GIF, since decoding GIFs
273         // composites any smaller frames against previous frames to create full-
274         // size frames.
frameSizeAtIndex(size_t)275         virtual IntSize frameSizeAtIndex(size_t) const
276         {
277             return size();
278         }
279 
280         // Returns whether the size is legal (i.e. not going to result in
281         // overflow elsewhere).  If not, marks decoding as failed.
setSize(unsigned width,unsigned height)282         virtual bool setSize(unsigned width, unsigned height)
283         {
284             if (isOverSize(width, height))
285                 return setFailed();
286             m_size = IntSize(width, height);
287             m_sizeAvailable = true;
288             return true;
289         }
290 
291         // Lazily-decodes enough of the image to get the frame count (if
292         // possible), without decoding the individual frames.
293         // FIXME: Right now that has to be done by each subclass; factor the
294         // decode call out and use it here.
frameCount()295         virtual size_t frameCount() { return 1; }
296 
repetitionCount()297         virtual int repetitionCount() const { return cAnimationNone; }
298 
299         // Decodes as much of the requested frame as possible, and returns an
300         // ImageDecoder-owned pointer.
301         virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
302 
setIgnoreGammaAndColorProfile(bool flag)303         void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
ignoresGammaAndColorProfile()304         bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
305 
306         // Sets the "decode failure" flag.  For caller convenience (since so
307         // many callers want to return false after calling this), returns false
308         // to enable easy tailcalling.  Subclasses may override this to also
309         // clean up any local data.
setFailed()310         virtual bool setFailed()
311         {
312             m_failed = true;
313             return false;
314         }
315 
failed()316         bool failed() const { return m_failed; }
317 
318         // Clears decoded pixel data from before the provided frame unless that
319         // data may be needed to decode future frames (e.g. due to GIF frame
320         // compositing).
clearFrameBufferCache(size_t)321         virtual void clearFrameBufferCache(size_t) { }
322 
323 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
setMaxNumPixels(int m)324         void setMaxNumPixels(int m) { m_maxNumPixels = m; }
325 #endif
326 
327     protected:
328         void prepareScaleDataIfNecessary();
329         int upperBoundScaledX(int origX, int searchStart = 0);
330         int lowerBoundScaledX(int origX, int searchStart = 0);
331         int upperBoundScaledY(int origY, int searchStart = 0);
332         int lowerBoundScaledY(int origY, int searchStart = 0);
333         int scaledY(int origY, int searchStart = 0);
334 
335         RefPtr<SharedBuffer> m_data; // The encoded data.
336         Vector<ImageFrame> m_frameBufferCache;
337         ColorProfile m_colorProfile;
338         bool m_scaled;
339         Vector<int> m_scaledColumns;
340         Vector<int> m_scaledRows;
341         bool m_premultiplyAlpha;
342         bool m_ignoreGammaAndColorProfile;
343 
344     private:
345         // Some code paths compute the size of the image as "width * height * 4"
346         // and return it as a (signed) int.  Avoid overflow.
isOverSize(unsigned width,unsigned height)347         static bool isOverSize(unsigned width, unsigned height)
348         {
349             unsigned long long total_size = static_cast<unsigned long long>(width)
350                                           * static_cast<unsigned long long>(height);
351             return total_size > ((1 << 29) - 1);
352         }
353 
354         IntSize m_size;
355         bool m_sizeAvailable;
356         int m_maxNumPixels;
357         bool m_isAllDataReceived;
358         bool m_failed;
359     };
360 
361 } // namespace WebCore
362 
363 #endif
364