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/text/WTFString.h" 40 #include "wtf/Vector.h" 41 42 #if USE(QCMSLIB) 43 #include "qcms.h" 44 #if OS(MACOSX) 45 #include <ApplicationServices/ApplicationServices.h> 46 #include "platform/graphics/cg/GraphicsContextCG.h" 47 #include "wtf/RetainPtr.h" 48 #endif 49 #endif 50 51 namespace WebCore { 52 53 // ImageDecoder is a base for all format-specific decoders 54 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache. 55 // 56 class PLATFORM_EXPORT ImageDecoder { 57 WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED; 58 public: 59 static const size_t noDecodedImageByteLimit = blink::Platform::noDecodedImageByteLimit; 60 61 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption, size_t maxDecodedBytes) 62 : m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied) 63 , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored) 64 , m_maxDecodedBytes(maxDecodedBytes) 65 , m_sizeAvailable(false) 66 , m_isAllDataReceived(false) 67 , m_failed(false) { } 68 69 virtual ~ImageDecoder() { } 70 71 // Returns a caller-owned decoder of the appropriate type. Returns 0 if 72 // we can't sniff a supported type from the provided data (possibly 73 // because there isn't enough data yet). 74 // Sets m_maxDecodedBytes to Platform::maxImageDecodedBytes(). 75 static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); 76 77 // Returns a decoder with custom maxDecodedSize. 78 static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption, size_t maxDecodedSize); 79 80 virtual String filenameExtension() const = 0; 81 82 bool isAllDataReceived() const { return m_isAllDataReceived; } 83 84 virtual void setData(SharedBuffer* data, bool allDataReceived) 85 { 86 if (m_failed) 87 return; 88 m_data = data; 89 m_isAllDataReceived = allDataReceived; 90 } 91 92 // Lazily-decodes enough of the image to get the size (if possible). 93 // FIXME: Right now that has to be done by each subclass; factor the 94 // decode call out and use it here. 95 virtual bool isSizeAvailable() 96 { 97 return !m_failed && m_sizeAvailable; 98 } 99 100 virtual IntSize size() const { return m_size; } 101 102 // Decoders which downsample images should override this method to 103 // return the actual decoded size. 104 virtual IntSize decodedSize() const { return size(); } 105 106 // This will only differ from size() for ICO (where each frame is a 107 // different icon) or other formats where different frames are different 108 // sizes. This does NOT differ from size() for GIF or WebP, since 109 // decoding GIF or WebP composites any smaller frames against previous 110 // frames to create full-size frames. 111 virtual IntSize frameSizeAtIndex(size_t) const 112 { 113 return size(); 114 } 115 116 // Returns whether the size is legal (i.e. not going to result in 117 // overflow elsewhere). If not, marks decoding as failed. 118 virtual bool setSize(unsigned width, unsigned height) 119 { 120 if (sizeCalculationMayOverflow(width, height)) 121 return setFailed(); 122 m_size = IntSize(width, height); 123 m_sizeAvailable = true; 124 return true; 125 } 126 127 // Lazily-decodes enough of the image to get the frame count (if 128 // possible), without decoding the individual frames. 129 // FIXME: Right now that has to be done by each subclass; factor the 130 // decode call out and use it here. 131 virtual size_t frameCount() { return 1; } 132 133 virtual int repetitionCount() const { return cAnimationNone; } 134 135 // Decodes as much of the requested frame as possible, and returns an 136 // ImageDecoder-owned pointer. 137 virtual ImageFrame* frameBufferAtIndex(size_t) = 0; 138 139 // Make the best effort guess to check if the requested frame has alpha channel. 140 virtual bool frameHasAlphaAtIndex(size_t) const; 141 142 // Whether or not the frame is fully received. 143 virtual bool frameIsCompleteAtIndex(size_t) const; 144 145 // Duration for displaying a frame in seconds. This method is used by animated images only. 146 virtual float frameDurationAtIndex(size_t) const { return 0; } 147 148 // Number of bytes in the decoded frame requested. Return 0 if not yet decoded. 149 virtual unsigned frameBytesAtIndex(size_t) const; 150 151 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; } 152 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; } 153 154 ImageOrientation orientation() const { return m_orientation; } 155 156 enum { iccColorProfileHeaderLength = 128 }; 157 158 static bool rgbColorProfile(const char* profileData, unsigned profileLength) 159 { 160 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength); 161 162 return !memcmp(&profileData[16], "RGB ", 4); 163 } 164 165 static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength) 166 { 167 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength); 168 169 return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[12], "scnr", 4); 170 } 171 172 #if USE(QCMSLIB) 173 static qcms_profile* qcmsOutputDeviceProfile() 174 { 175 static qcms_profile* outputDeviceProfile = 0; 176 177 static bool qcmsInitialized = false; 178 if (!qcmsInitialized) { 179 qcmsInitialized = true; 180 // FIXME: Add optional ICCv4 support. 181 #if OS(MACOSX) 182 RetainPtr<CGColorSpaceRef> monitorColorSpace(AdoptCF, CGDisplayCopyColorSpace(CGMainDisplayID())); 183 CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpace.get())); 184 if (iccProfile) { 185 size_t length = CFDataGetLength(iccProfile); 186 const unsigned char* systemProfile = CFDataGetBytePtr(iccProfile); 187 outputDeviceProfile = qcms_profile_from_memory(systemProfile, length); 188 } 189 #else 190 // FIXME: add support for multiple monitors. 191 ColorProfile profile; 192 screenColorProfile(profile); 193 if (!profile.isEmpty()) 194 outputDeviceProfile = qcms_profile_from_memory(profile.data(), profile.size()); 195 #endif 196 if (outputDeviceProfile && qcms_profile_is_bogus(outputDeviceProfile)) { 197 qcms_profile_release(outputDeviceProfile); 198 outputDeviceProfile = 0; 199 } 200 if (!outputDeviceProfile) 201 outputDeviceProfile = qcms_profile_sRGB(); 202 if (outputDeviceProfile) 203 qcms_profile_precache_output_transform(outputDeviceProfile); 204 } 205 return outputDeviceProfile; 206 } 207 #endif 208 209 // Sets the "decode failure" flag. For caller convenience (since so 210 // many callers want to return false after calling this), returns false 211 // to enable easy tailcalling. Subclasses may override this to also 212 // clean up any local data. 213 virtual bool setFailed() 214 { 215 m_failed = true; 216 return false; 217 } 218 219 bool failed() const { return m_failed; } 220 221 // Clears decoded pixel data from all frames except the provided frame. 222 // Callers may pass WTF::kNotFound to clear all frames. 223 // Note: If |m_frameBufferCache| contains only one frame, it won't be cleared. 224 // Returns the number of bytes of frame data actually cleared. 225 virtual size_t clearCacheExceptFrame(size_t); 226 227 // If the image has a cursor hot-spot, stores it in the argument 228 // and returns true. Otherwise returns false. 229 virtual bool hotSpot(IntPoint&) const { return false; } 230 231 virtual void setMemoryAllocator(SkBitmap::Allocator* allocator) 232 { 233 // FIXME: this doesn't work for images with multiple frames. 234 if (m_frameBufferCache.isEmpty()) { 235 m_frameBufferCache.resize(1); 236 m_frameBufferCache[0].setRequiredPreviousFrameIndex( 237 findRequiredPreviousFrame(0, false)); 238 } 239 m_frameBufferCache[0].setMemoryAllocator(allocator); 240 } 241 242 protected: 243 // Calculates the most recent frame whose image data may be needed in 244 // order to decode frame |frameIndex|, based on frame disposal methods 245 // and |frameRectIsOpaque|, where |frameRectIsOpaque| signifies whether 246 // the rectangle of frame at |frameIndex| is known to be opaque. 247 // If no previous frame's data is required, returns WTF::kNotFound. 248 // 249 // This function requires that the previous frame's 250 // |m_requiredPreviousFrameIndex| member has been set correctly. The 251 // easiest way to ensure this is for subclasses to call this method and 252 // store the result on the frame via setRequiredPreviousFrameIndex() 253 // as soon as the frame has been created and parsed sufficiently to 254 // determine the disposal method; assuming this happens for all frames 255 // in order, the required invariant will hold. 256 // 257 // Image formats which do not use more than one frame do not need to 258 // worry about this; see comments on 259 // ImageFrame::m_requiredPreviousFrameIndex. 260 size_t findRequiredPreviousFrame(size_t frameIndex, bool frameRectIsOpaque); 261 262 virtual void clearFrameBuffer(size_t frameIndex); 263 264 RefPtr<SharedBuffer> m_data; // The encoded data. 265 Vector<ImageFrame, 1> m_frameBufferCache; 266 bool m_premultiplyAlpha; 267 bool m_ignoreGammaAndColorProfile; 268 ImageOrientation m_orientation; 269 270 // The maximum amount of memory a decoded image should require. Ideally, 271 // image decoders should downsample large images to fit under this limit 272 // (and then return the downsampled size from decodedSize()). Ignoring 273 // this limit can cause excessive memory use or even crashes on low- 274 // memory devices. 275 size_t m_maxDecodedBytes; 276 277 private: 278 // Some code paths compute the size of the image as "width * height * 4" 279 // and return it as a (signed) int. Avoid overflow. 280 static bool sizeCalculationMayOverflow(unsigned width, unsigned height) 281 { 282 unsigned long long total_size = static_cast<unsigned long long>(width) 283 * static_cast<unsigned long long>(height); 284 return total_size > ((1 << 29) - 1); 285 } 286 287 IntSize m_size; 288 bool m_sizeAvailable; 289 bool m_isAllDataReceived; 290 bool m_failed; 291 }; 292 293 } // namespace WebCore 294 295 #endif 296