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