• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #ifndef ImageDecoder_h
28 #define ImageDecoder_h
29 
30 #include "SkColorPriv.h"
31 #include "platform/PlatformExport.h"
32 #include "platform/PlatformScreen.h"
33 #include "platform/SharedBuffer.h"
34 #include "platform/graphics/ImageSource.h"
35 #include "platform/image-decoders/ImageFrame.h"
36 #include "public/platform/Platform.h"
37 #include "wtf/Assertions.h"
38 #include "wtf/RefPtr.h"
39 #include "wtf/Vector.h"
40 #include "wtf/text/WTFString.h"
41 
42 #if USE(QCMSLIB)
43 #include "qcms.h"
44 #endif
45 
46 typedef Vector<char> ColorProfile;
47 
48 namespace blink {
49 
50 // ImagePlanes can be used to decode color components into provided buffers instead of using an ImageFrame.
51 class PLATFORM_EXPORT ImagePlanes {
52 public:
53     ImagePlanes();
54     ImagePlanes(void* planes[3], size_t rowBytes[3]);
55 
56     void* plane(int);
57     size_t rowBytes(int) const;
58 
59 private:
60     void* m_planes[3];
61     size_t m_rowBytes[3];
62 };
63 
64 // ImageDecoder is a base for all format-specific decoders
65 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache.
66 //
67 class PLATFORM_EXPORT ImageDecoder {
68     WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
69 public:
70     enum SizeType { ActualSize, SizeForMemoryAllocation };
71 
72     static const size_t noDecodedImageByteLimit = blink::Platform::noDecodedImageByteLimit;
73 
ImageDecoder(ImageSource::AlphaOption alphaOption,ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption,size_t maxDecodedBytes)74     ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption, size_t maxDecodedBytes)
75         : m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
76         , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored)
77         , m_maxDecodedBytes(maxDecodedBytes)
78         , m_sizeAvailable(false)
79         , m_isAllDataReceived(false)
80         , m_failed(false) { }
81 
~ImageDecoder()82     virtual ~ImageDecoder() { }
83 
84     // Returns a caller-owned decoder of the appropriate type.  Returns 0 if
85     // we can't sniff a supported type from the provided data (possibly
86     // because there isn't enough data yet).
87     // Sets m_maxDecodedBytes to Platform::maxImageDecodedBytes().
88     static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
89 
90     // Returns a decoder with custom maxDecodedSize.
91     static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption, size_t maxDecodedSize);
92 
93     virtual String filenameExtension() const = 0;
94 
isAllDataReceived()95     bool isAllDataReceived() const { return m_isAllDataReceived; }
96 
setData(SharedBuffer * data,bool allDataReceived)97     virtual void setData(SharedBuffer* data, bool allDataReceived)
98     {
99         if (m_failed)
100             return;
101         m_data = data;
102         m_isAllDataReceived = allDataReceived;
103     }
104 
isSizeAvailable()105     virtual bool isSizeAvailable()
106     {
107         return !m_failed && m_sizeAvailable;
108     }
109 
isSizeAvailable()110     bool isSizeAvailable() const
111     {
112         return !m_failed && m_sizeAvailable;
113     }
114 
size()115     virtual IntSize size() const { return m_size; }
116 
117     // Decoders which downsample images should override this method to
118     // return the actual decoded size.
decodedSize()119     virtual IntSize decodedSize() const { return size(); }
120 
121     // Decoders which support YUV decoding can override this to
122     // give potentially different sizes per component.
decodedYUVSize(int component,SizeType)123     virtual IntSize decodedYUVSize(int component, SizeType) const { return decodedSize(); }
124 
125     // This will only differ from size() for ICO (where each frame is a
126     // different icon) or other formats where different frames are different
127     // sizes. This does NOT differ from size() for GIF or WebP, since
128     // decoding GIF or WebP composites any smaller frames against previous
129     // frames to create full-size frames.
frameSizeAtIndex(size_t)130     virtual IntSize frameSizeAtIndex(size_t) const
131     {
132         return size();
133     }
134 
135     // Returns whether the size is legal (i.e. not going to result in
136     // overflow elsewhere).  If not, marks decoding as failed.
setSize(unsigned width,unsigned height)137     virtual bool setSize(unsigned width, unsigned height)
138     {
139         if (sizeCalculationMayOverflow(width, height))
140             return setFailed();
141         m_size = IntSize(width, height);
142         m_sizeAvailable = true;
143         return true;
144     }
145 
146     // Lazily-decodes enough of the image to get the frame count (if
147     // possible), without decoding the individual frames.
148     // FIXME: Right now that has to be done by each subclass; factor the
149     // decode call out and use it here.
frameCount()150     virtual size_t frameCount() { return 1; }
151 
repetitionCount()152     virtual int repetitionCount() const { return cAnimationNone; }
153 
154     // Decodes as much of the requested frame as possible, and returns an
155     // ImageDecoder-owned pointer.
156     virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
157 
158     // Make the best effort guess to check if the requested frame has alpha channel.
159     virtual bool frameHasAlphaAtIndex(size_t) const;
160 
161     // Whether or not the frame is fully received.
162     virtual bool frameIsCompleteAtIndex(size_t) const;
163 
164     // Duration for displaying a frame in seconds. This method is used by animated images only.
frameDurationAtIndex(size_t)165     virtual float frameDurationAtIndex(size_t) const { return 0; }
166 
167     // Number of bytes in the decoded frame requested. Return 0 if not yet decoded.
168     virtual unsigned frameBytesAtIndex(size_t) const;
169 
orientation()170     ImageOrientation orientation() const { return m_orientation; }
171 
172     static bool deferredImageDecodingEnabled();
173 
setIgnoreGammaAndColorProfile(bool flag)174     void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
ignoresGammaAndColorProfile()175     bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
176 
hasColorProfile()177     virtual bool hasColorProfile() const { return false; }
178 
179 #if USE(QCMSLIB)
180     enum { iccColorProfileHeaderLength = 128 };
181 
rgbColorProfile(const char * profileData,unsigned profileLength)182     static bool rgbColorProfile(const char* profileData, unsigned profileLength)
183     {
184         ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength);
185 
186         return !memcmp(&profileData[16], "RGB ", 4);
187     }
188 
inputDeviceColorProfile(const char * profileData,unsigned profileLength)189     static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength)
190     {
191         ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength);
192 
193         return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[12], "scnr", 4);
194     }
195 
196     class OutputDeviceProfile {
197     public:
OutputDeviceProfile()198         OutputDeviceProfile()
199             : m_outputDeviceProfile(0)
200         {
201             ColorProfile profile = screenColorProfile();
202             if (!profile.isEmpty())
203                 m_outputDeviceProfile = qcms_profile_from_memory(profile.data(), profile.size());
204 
205             if (m_outputDeviceProfile && qcms_profile_is_bogus(m_outputDeviceProfile)) {
206                 qcms_profile_release(m_outputDeviceProfile);
207                 m_outputDeviceProfile = 0;
208             }
209 
210             if (!m_outputDeviceProfile)
211                 m_outputDeviceProfile = qcms_profile_sRGB();
212             if (m_outputDeviceProfile)
213                 qcms_profile_precache_output_transform(m_outputDeviceProfile);
214         }
215 
profile()216         qcms_profile* profile() const { return m_outputDeviceProfile; }
217 
218     private:
screenColorProfile()219         static ColorProfile screenColorProfile()
220         {
221             // FIXME: Add optional ICCv4 support and support for multiple monitors.
222             WebVector<char> profile;
223             Platform::current()->screenColorProfile(&profile);
224 
225             ColorProfile colorProfile;
226             colorProfile.append(profile.data(), profile.size());
227             return colorProfile;
228         }
229 
230         qcms_profile* m_outputDeviceProfile;
231     };
232 
qcmsOutputDeviceProfile()233     static qcms_profile* qcmsOutputDeviceProfile()
234     {
235         AtomicallyInitializedStatic(OutputDeviceProfile*, outputDeviceProfile = new OutputDeviceProfile());
236 
237         return outputDeviceProfile->profile();
238     }
239 #endif
240 
241     // Sets the "decode failure" flag.  For caller convenience (since so
242     // many callers want to return false after calling this), returns false
243     // to enable easy tailcalling.  Subclasses may override this to also
244     // clean up any local data.
setFailed()245     virtual bool setFailed()
246     {
247         m_failed = true;
248         return false;
249     }
250 
failed()251     bool failed() const { return m_failed; }
252 
253     // Clears decoded pixel data from all frames except the provided frame.
254     // Callers may pass WTF::kNotFound to clear all frames.
255     // Note: If |m_frameBufferCache| contains only one frame, it won't be cleared.
256     // Returns the number of bytes of frame data actually cleared.
257     virtual size_t clearCacheExceptFrame(size_t);
258 
259     // If the image has a cursor hot-spot, stores it in the argument
260     // and returns true. Otherwise returns false.
hotSpot(IntPoint &)261     virtual bool hotSpot(IntPoint&) const { return false; }
262 
setMemoryAllocator(SkBitmap::Allocator * allocator)263     virtual void setMemoryAllocator(SkBitmap::Allocator* allocator)
264     {
265         // FIXME: this doesn't work for images with multiple frames.
266         if (m_frameBufferCache.isEmpty()) {
267             m_frameBufferCache.resize(1);
268             m_frameBufferCache[0].setRequiredPreviousFrameIndex(
269                 findRequiredPreviousFrame(0, false));
270         }
271         m_frameBufferCache[0].setMemoryAllocator(allocator);
272     }
273 
canDecodeToYUV()274     virtual bool canDecodeToYUV() const { return false; }
decodeToYUV()275     virtual bool decodeToYUV() { return false; }
setImagePlanes(PassOwnPtr<ImagePlanes>)276     virtual void setImagePlanes(PassOwnPtr<ImagePlanes>) { }
277 
278 protected:
279     // Calculates the most recent frame whose image data may be needed in
280     // order to decode frame |frameIndex|, based on frame disposal methods
281     // and |frameRectIsOpaque|, where |frameRectIsOpaque| signifies whether
282     // the rectangle of frame at |frameIndex| is known to be opaque.
283     // If no previous frame's data is required, returns WTF::kNotFound.
284     //
285     // This function requires that the previous frame's
286     // |m_requiredPreviousFrameIndex| member has been set correctly. The
287     // easiest way to ensure this is for subclasses to call this method and
288     // store the result on the frame via setRequiredPreviousFrameIndex()
289     // as soon as the frame has been created and parsed sufficiently to
290     // determine the disposal method; assuming this happens for all frames
291     // in order, the required invariant will hold.
292     //
293     // Image formats which do not use more than one frame do not need to
294     // worry about this; see comments on
295     // ImageFrame::m_requiredPreviousFrameIndex.
296     size_t findRequiredPreviousFrame(size_t frameIndex, bool frameRectIsOpaque);
297 
298     virtual void clearFrameBuffer(size_t frameIndex);
299 
300     RefPtr<SharedBuffer> m_data; // The encoded data.
301     Vector<ImageFrame, 1> m_frameBufferCache;
302     bool m_premultiplyAlpha;
303     bool m_ignoreGammaAndColorProfile;
304     ImageOrientation m_orientation;
305 
306     // The maximum amount of memory a decoded image should require. Ideally,
307     // image decoders should downsample large images to fit under this limit
308     // (and then return the downsampled size from decodedSize()). Ignoring
309     // this limit can cause excessive memory use or even crashes on low-
310     // memory devices.
311     size_t m_maxDecodedBytes;
312 
313 private:
314     // Some code paths compute the size of the image as "width * height * 4"
315     // and return it as a (signed) int.  Avoid overflow.
sizeCalculationMayOverflow(unsigned width,unsigned height)316     static bool sizeCalculationMayOverflow(unsigned width, unsigned height)
317     {
318         unsigned long long total_size = static_cast<unsigned long long>(width)
319                                       * static_cast<unsigned long long>(height);
320         return total_size > ((1 << 29) - 1);
321     }
322 
323     IntSize m_size;
324     bool m_sizeAvailable;
325     bool m_isAllDataReceived;
326     bool m_failed;
327 };
328 
329 } // namespace blink
330 
331 #endif
332