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)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
29 #ifndef ImageDecoder_h
30 #define ImageDecoder_h
33 #include "ImageSource.h"
34 #include "PlatformScreen.h"
35 #include "SharedBuffer.h"
36 #include <wtf/Assertions.h>
37 #include <wtf/RefPtr.h>
38 #include <wtf/Vector.h>
39 #include <wtf/text/WTFString.h>
42 #include "NativeImageSkia.h"
43 #include "SkColorPriv.h"
49 #include "GraphicsContextCG.h"
50 #include <ApplicationServices/ApplicationServices.h>
51 #include <wtf/RetainPtr.h>
57 // ImageFrame represents the decoded image data. This buffer is what all
58 // decoders write a single frame into.
61 enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
62 enum FrameDisposalMethod {
63 // If you change the numeric values of these, make sure you audit
64 // all users, as some users may cast raw values to/from these
66 DisposeNotSpecified, // Leave frame in framebuffer
67 DisposeKeep, // Leave frame in framebuffer
68 DisposeOverwriteBgcolor, // Clear frame to transparent
69 DisposeOverwritePrevious // Clear frame to previous framebuffer
73 typedef uint32_t PixelData;
75 typedef unsigned PixelData;
80 ImageFrame(const ImageFrame& other) { operator=(other); }
82 // For backends which refcount their data, this operator doesn't need to
83 // create a new copy of the image data, only increase the ref count.
84 ImageFrame& operator=(const ImageFrame& other);
86 // These do not touch other metadata, only the raw pixel data.
87 void clearPixelData();
88 void zeroFillPixelData();
90 // Makes this frame have an independent copy of the provided image's
91 // pixel data, so that modifications in one frame are not reflected in
92 // the other. Returns whether the copy succeeded.
93 bool copyBitmapData(const ImageFrame&);
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
98 void copyRowNTimes(int startX, int endX, int startY, int endY)
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);
110 // Allocates space for the pixel data. Must be called before any pixels
111 // are written. Must only be called once. Returns whether allocation
113 bool setSize(int newWidth, int newHeight);
115 // Returns a caller-owned pointer to the underlying native image data.
116 // (Actual use: This pointer will be owned by BitmapImage and freed in
117 // FrameData::clear()).
118 PassNativeImagePtr asNewNativeImage() const;
120 bool hasAlpha() const;
121 const IntRect& originalFrameRect() const { return m_originalFrameRect; }
122 FrameStatus status() const { return m_status; }
123 unsigned duration() const { return m_duration; }
124 FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
125 bool premultiplyAlpha() const { return m_premultiplyAlpha; }
127 void setHasAlpha(bool alpha);
128 void setColorProfile(const ColorProfile&);
129 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
130 void setStatus(FrameStatus status);
131 void setDuration(unsigned duration) { m_duration = duration; }
132 void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
133 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
135 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
137 setRGBA(getAddr(x, y), r, g, b, a);
140 inline PixelData* getAddr(int x, int y)
143 return m_bitmap->bitmap().getAddr32(x, y);
145 return m_bytes + (y * width()) + x;
149 // Use fix point multiplier instead of integer division or floating point math.
150 // This multipler produces exactly the same result for all values in range 0 - 255.
151 static const unsigned fixPointShift = 24;
152 static const unsigned fixPointMult = static_cast<unsigned>(1.0 / 255.0 * (1 << fixPointShift)) + 1;
153 // Multiplies unsigned value by fixpoint value and converts back to unsigned.
154 static unsigned fixPointUnsignedMultiply(unsigned fixed, unsigned v)
156 return (fixed * v) >> fixPointShift;
159 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
161 if (m_premultiplyAlpha && a < 255) {
167 unsigned alphaMult = a * fixPointMult;
168 r = fixPointUnsignedMultiply(r, alphaMult);
169 g = fixPointUnsignedMultiply(g, alphaMult);
170 b = fixPointUnsignedMultiply(b, alphaMult);
173 // Call the "NoCheck" version since we may deliberately pass non-premultiplied
174 // values, and we don't want an assert.
175 *dest = SkPackARGB32NoCheck(a, r, g, b);
177 *dest = (a << 24 | r << 16 | g << 8 | b);
185 return m_bitmap->bitmap().width();
187 return m_size.width();
194 return m_bitmap->bitmap().height();
196 return m_size.height();
201 RefPtr<NativeImageSkia> m_bitmap;
202 SkBitmap::Allocator* m_allocator;
204 Vector<PixelData> m_backingStore;
205 PixelData* m_bytes; // The memory is backed by m_backingStore.
207 // FIXME: Do we need m_colorProfile anymore?
208 ColorProfile m_colorProfile;
211 IntRect m_originalFrameRect; // This will always just be the entire
212 // buffer except for GIF frames whose
213 // original rect was smaller than the
214 // overall image size.
215 FrameStatus m_status;
217 FrameDisposalMethod m_disposalMethod;
218 bool m_premultiplyAlpha;
221 // ImageDecoder is a base for all format-specific decoders
222 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache.
224 // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample
225 // at decode time. Image decoders will downsample any images larger than
226 // |m_maxNumPixels|. FIXME: Not yet supported by all decoders.
228 WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
230 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
232 , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
233 , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored)
234 , m_sizeAvailable(false)
236 , m_isAllDataReceived(false)
237 , m_failed(false) { }
239 virtual ~ImageDecoder() { }
241 // Returns a caller-owned decoder of the appropriate type. Returns 0 if
242 // we can't sniff a supported type from the provided data (possibly
243 // because there isn't enough data yet).
244 static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
246 virtual String filenameExtension() const = 0;
248 bool isAllDataReceived() const { return m_isAllDataReceived; }
250 virtual void setData(SharedBuffer* data, bool allDataReceived)
255 m_isAllDataReceived = allDataReceived;
258 // Lazily-decodes enough of the image to get the size (if possible).
259 // FIXME: Right now that has to be done by each subclass; factor the
260 // decode call out and use it here.
261 virtual bool isSizeAvailable()
263 return !m_failed && m_sizeAvailable;
266 virtual IntSize size() const { return m_size; }
268 IntSize scaledSize() const
270 return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size();
273 // This will only differ from size() for ICO (where each frame is a
274 // different icon) or other formats where different frames are different
275 // sizes. This does NOT differ from size() for GIF, since decoding GIFs
276 // composites any smaller frames against previous frames to create full-
278 virtual IntSize frameSizeAtIndex(size_t) const
283 // Returns whether the size is legal (i.e. not going to result in
284 // overflow elsewhere). If not, marks decoding as failed.
285 virtual bool setSize(unsigned width, unsigned height)
287 if (isOverSize(width, height))
289 m_size = IntSize(width, height);
290 m_sizeAvailable = true;
294 // Lazily-decodes enough of the image to get the frame count (if
295 // possible), without decoding the individual frames.
296 // FIXME: Right now that has to be done by each subclass; factor the
297 // decode call out and use it here.
298 virtual size_t frameCount() { return 1; }
300 virtual int repetitionCount() const { return cAnimationNone; }
302 // Decodes as much of the requested frame as possible, and returns an
303 // ImageDecoder-owned pointer.
304 virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
306 // Make the best effort guess to check if the requested frame has alpha channel.
307 virtual bool frameHasAlphaAtIndex(size_t) const;
309 // Number of bytes in the decoded frame requested. Return 0 if not yet decoded.
310 virtual unsigned frameBytesAtIndex(size_t) const;
312 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
313 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
315 ImageOrientation orientation() const { return m_orientation; }
317 enum { iccColorProfileHeaderLength = 128 };
319 static bool rgbColorProfile(const char* profileData, unsigned profileLength)
321 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength);
323 return !memcmp(&profileData[16], "RGB ", 4);
326 static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength)
328 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength);
330 return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[12], "scnr", 4);
334 static qcms_profile* qcmsOutputDeviceProfile()
336 static qcms_profile* outputDeviceProfile = 0;
338 static bool qcmsInitialized = false;
339 if (!qcmsInitialized) {
340 qcmsInitialized = true;
341 // FIXME: Add optional ICCv4 support.
343 RetainPtr<CGColorSpaceRef> monitorColorSpace(AdoptCF, CGDisplayCopyColorSpace(CGMainDisplayID()));
344 CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpace.get()));
346 size_t length = CFDataGetLength(iccProfile);
347 const unsigned char* systemProfile = CFDataGetBytePtr(iccProfile);
348 outputDeviceProfile = qcms_profile_from_memory(systemProfile, length);
351 // FIXME: add support for multiple monitors.
352 ColorProfile profile;
353 screenColorProfile(profile);
354 if (!profile.isEmpty())
355 outputDeviceProfile = qcms_profile_from_memory(profile.data(), profile.size());
357 if (outputDeviceProfile && qcms_profile_is_bogus(outputDeviceProfile)) {
358 qcms_profile_release(outputDeviceProfile);
359 outputDeviceProfile = 0;
361 if (!outputDeviceProfile)
362 outputDeviceProfile = qcms_profile_sRGB();
363 if (outputDeviceProfile)
364 qcms_profile_precache_output_transform(outputDeviceProfile);
366 return outputDeviceProfile;
370 // Sets the "decode failure" flag. For caller convenience (since so
371 // many callers want to return false after calling this), returns false
372 // to enable easy tailcalling. Subclasses may override this to also
373 // clean up any local data.
374 virtual bool setFailed()
380 bool failed() const { return m_failed; }
382 // Clears decoded pixel data from before the provided frame unless that
383 // data may be needed to decode future frames (e.g. due to GIF frame
385 virtual void clearFrameBufferCache(size_t) { }
387 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
388 void setMaxNumPixels(int m) { m_maxNumPixels = m; }
391 // If the image has a cursor hot-spot, stores it in the argument
392 // and returns true. Otherwise returns false.
393 virtual bool hotSpot(IntPoint&) const { return false; }
396 virtual void setMemoryAllocator(SkBitmap::Allocator* allocator)
398 // FIXME: this doesn't work for images with multiple frames.
399 if (m_frameBufferCache.isEmpty())
400 m_frameBufferCache.resize(1);
401 m_frameBufferCache[0].setMemoryAllocator(allocator);
404 virtual bool lockFrameBuffers()
407 for (unsigned i = 0; i < m_frameBufferCache.size(); ++i) {
408 const SkBitmap& bitmap = m_frameBufferCache[i].getSkBitmap();
410 ret = ret && bitmap.getPixels();
415 virtual void unlockFrameBuffers()
417 for (unsigned i = 0; i < m_frameBufferCache.size(); ++i)
418 m_frameBufferCache[i].getSkBitmap().unlockPixels();
422 void prepareScaleDataIfNecessary();
423 int upperBoundScaledX(int origX, int searchStart = 0);
424 int lowerBoundScaledX(int origX, int searchStart = 0);
425 int upperBoundScaledY(int origY, int searchStart = 0);
426 int lowerBoundScaledY(int origY, int searchStart = 0);
427 int scaledY(int origY, int searchStart = 0);
429 RefPtr<SharedBuffer> m_data; // The encoded data.
430 Vector<ImageFrame, 1> m_frameBufferCache;
431 // FIXME: Do we need m_colorProfile any more, for any port?
432 ColorProfile m_colorProfile;
434 Vector<int> m_scaledColumns;
435 Vector<int> m_scaledRows;
436 bool m_premultiplyAlpha;
437 bool m_ignoreGammaAndColorProfile;
438 ImageOrientation m_orientation;
441 // Some code paths compute the size of the image as "width * height * 4"
442 // and return it as a (signed) int. Avoid overflow.
443 static bool isOverSize(unsigned width, unsigned height)
445 unsigned long long total_size = static_cast<unsigned long long>(width)
446 * static_cast<unsigned long long>(height);
447 return total_size > ((1 << 29) - 1);
451 bool m_sizeAvailable;
453 bool m_isAllDataReceived;
457 } // namespace WebCore