OLD | NEW |
(Empty) | |
| 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::noDecodedImag
eByteLimit; |
| 60 |
| 61 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColo
rProfileOption 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 chan
nel. |
| 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 animat
ed 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 decod
ed. |
| 149 virtual unsigned frameBytesAtIndex(size_t) const; |
| 150 |
| 151 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile
= flag; } |
| 152 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfi
le; } |
| 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 >= iccColorProfileHeaderLengt
h); |
| 161 |
| 162 return !memcmp(&profileData[16], "RGB ", 4); |
| 163 } |
| 164 |
| 165 static bool inputDeviceColorProfile(const char* profileData, unsigned profil
eLength) |
| 166 { |
| 167 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLengt
h); |
| 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, CGDisplayCopyC
olorSpace(CGMainDisplayID())); |
| 183 CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpace.ge
t())); |
| 184 if (iccProfile) { |
| 185 size_t length = CFDataGetLength(iccProfile); |
| 186 const unsigned char* systemProfile = CFDataGetBytePtr(iccProfile
); |
| 187 outputDeviceProfile = qcms_profile_from_memory(systemProfile, le
ngth); |
| 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(), p
rofile.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 cleare
d. |
| 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 |
OLD | NEW |