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 "core/platform/PlatformScreen.h" 32 #include "core/platform/SharedBuffer.h" 33 #include "core/platform/graphics/ImageSource.h" 34 #include "core/platform/graphics/IntRect.h" 35 #include "core/platform/graphics/skia/NativeImageSkia.h" 36 #include "wtf/Assertions.h" 37 #include "wtf/RefPtr.h" 38 #include "wtf/text/WTFString.h" 39 #include "wtf/Vector.h" 40 41 #if USE(QCMSLIB) 42 #include "qcms.h" 43 #if OS(DARWIN) 44 #include <ApplicationServices/ApplicationServices.h> 45 #include "core/platform/graphics/cg/GraphicsContextCG.h" 46 #include "wtf/RetainPtr.h" 47 #endif 48 #endif 49 50 namespace WebCore { 51 52 // ImageFrame represents the decoded image data. This buffer is what all 53 // decoders write a single frame into. 54 class ImageFrame { 55 public: 56 enum FrameStatus { FrameEmpty, FramePartial, FrameComplete }; 57 enum FrameDisposalMethod { 58 // If you change the numeric values of these, make sure you audit 59 // all users, as some users may cast raw values to/from these 60 // constants. 61 DisposeNotSpecified, // Leave frame in framebuffer 62 DisposeKeep, // Leave frame in framebuffer 63 DisposeOverwriteBgcolor, // Clear frame to transparent 64 DisposeOverwritePrevious // Clear frame to previous framebuffer 65 // contents 66 }; 67 typedef uint32_t PixelData; 68 69 ImageFrame(); 70 71 ImageFrame(const ImageFrame& other) { operator=(other); } 72 73 // For backends which refcount their data, this operator doesn't need to 74 // create a new copy of the image data, only increase the ref count. 75 ImageFrame& operator=(const ImageFrame& other); 76 77 // These do not touch other metadata, only the raw pixel data. 78 void clearPixelData(); 79 void zeroFillPixelData(); 80 void zeroFillFrameRect(const IntRect&); 81 82 // Makes this frame have an independent copy of the provided image's 83 // pixel data, so that modifications in one frame are not reflected in 84 // the other. Returns whether the copy succeeded. 85 bool copyBitmapData(const ImageFrame&); 86 87 // Copies the pixel data at [(startX, startY), (endX, startY)) to the 88 // same X-coordinates on each subsequent row up to but not including 89 // endY. 90 void copyRowNTimes(int startX, int endX, int startY, int endY) 91 { 92 ASSERT(startX < width()); 93 ASSERT(endX <= width()); 94 ASSERT(startY < height()); 95 ASSERT(endY <= height()); 96 const int rowBytes = (endX - startX) * sizeof(PixelData); 97 const PixelData* const startAddr = getAddr(startX, startY); 98 for (int destY = startY + 1; destY < endY; ++destY) 99 memcpy(getAddr(startX, destY), startAddr, rowBytes); 100 } 101 102 // Allocates space for the pixel data. Must be called before any pixels 103 // are written. Must only be called once. Returns whether allocation 104 // succeeded. 105 bool setSize(int newWidth, int newHeight); 106 107 // Returns a caller-owned pointer to the underlying native image data. 108 // (Actual use: This pointer will be owned by BitmapImage and freed in 109 // FrameData::clear()). 110 PassRefPtr<NativeImageSkia> asNewNativeImage() const; 111 112 bool hasAlpha() const; 113 const IntRect& originalFrameRect() const { return m_originalFrameRect; } 114 FrameStatus status() const { return m_status; } 115 unsigned duration() const { return m_duration; } 116 FrameDisposalMethod disposalMethod() const { return m_disposalMethod; } 117 bool premultiplyAlpha() const { return m_premultiplyAlpha; } 118 SkBitmap::Allocator* allocator() const { return m_allocator; } 119 const SkBitmap& getSkBitmap() const { return m_bitmap->bitmap(); } 120 121 size_t requiredPreviousFrameIndex() const 122 { 123 ASSERT(m_requiredPreviousFrameIndexValid); 124 return m_requiredPreviousFrameIndex; 125 } 126 #if !ASSERT_DISABLED 127 bool requiredPreviousFrameIndexValid() const { return m_requiredPreviousFrameIndexValid; } 128 #endif 129 void setHasAlpha(bool alpha); 130 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; } 131 void setStatus(FrameStatus status); 132 void setDuration(unsigned duration) { m_duration = duration; } 133 void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; } 134 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; } 135 void setMemoryAllocator(SkBitmap::Allocator* allocator) { m_allocator = allocator; } 136 void setSkBitmap(const SkBitmap& bitmap) { m_bitmap = NativeImageSkia::create(bitmap); } 137 138 void setRequiredPreviousFrameIndex(size_t previousFrameIndex) 139 { 140 m_requiredPreviousFrameIndex = previousFrameIndex; 141 #if !ASSERT_DISABLED 142 m_requiredPreviousFrameIndexValid = true; 143 #endif 144 } 145 146 inline PixelData* getAddr(int x, int y) 147 { 148 return m_bitmap->bitmap().getAddr32(x, y); 149 } 150 151 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a) 152 { 153 setRGBA(getAddr(x, y), r, g, b, a); 154 } 155 156 static const unsigned div255 = static_cast<unsigned>(1.0 / 255 * (1 << 24)) + 1; 157 158 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 159 { 160 if (m_premultiplyAlpha && a < 255) { 161 if (!a) { 162 *dest = 0; 163 return; 164 } 165 166 unsigned alpha = a * div255; 167 r = (r * alpha) >> 24; 168 g = (g * alpha) >> 24; 169 b = (b * alpha) >> 24; 170 } 171 172 // Call the "NoCheck" version since we may deliberately pass non-premultiplied 173 // values, and we don't want an assert. 174 *dest = SkPackARGB32NoCheck(a, r, g, b); 175 } 176 177 inline void setRGBARaw(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 178 { 179 *dest = SkPackARGB32NoCheck(a, r, g, b); 180 } 181 182 private: 183 int width() const 184 { 185 return m_bitmap->bitmap().width(); 186 } 187 188 int height() const 189 { 190 return m_bitmap->bitmap().height(); 191 } 192 193 RefPtr<NativeImageSkia> m_bitmap; 194 SkBitmap::Allocator* m_allocator; 195 bool m_hasAlpha; 196 // This will always just be the entire buffer except for GIF or WebP 197 // frames whose original rect was smaller than the overall image size. 198 IntRect m_originalFrameRect; 199 FrameStatus m_status; 200 unsigned m_duration; 201 FrameDisposalMethod m_disposalMethod; 202 bool m_premultiplyAlpha; 203 204 // The frame that must be decoded before this frame can be decoded. 205 // WTF::notFound if this frame doesn't require any previous frame. 206 // This is used by ImageDecoder::clearCacheExceptFrame(), and will never 207 // be read for image formats that do not have multiple frames. 208 size_t m_requiredPreviousFrameIndex; 209 #if !ASSERT_DISABLED 210 bool m_requiredPreviousFrameIndexValid; 211 #endif 212 }; 213 214 // ImageDecoder is a base for all format-specific decoders 215 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache. 216 class ImageDecoder { 217 WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED; 218 public: 219 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) 220 : m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied) 221 , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored) 222 , m_sizeAvailable(false) 223 , m_isAllDataReceived(false) 224 , m_failed(false) { } 225 226 virtual ~ImageDecoder() { } 227 228 // Returns a caller-owned decoder of the appropriate type. Returns 0 if 229 // we can't sniff a supported type from the provided data (possibly 230 // because there isn't enough data yet). 231 static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); 232 233 virtual String filenameExtension() const = 0; 234 235 bool isAllDataReceived() const { return m_isAllDataReceived; } 236 237 virtual void setData(SharedBuffer* data, bool allDataReceived) 238 { 239 if (m_failed) 240 return; 241 m_data = data; 242 m_isAllDataReceived = allDataReceived; 243 } 244 245 // Lazily-decodes enough of the image to get the size (if possible). 246 // FIXME: Right now that has to be done by each subclass; factor the 247 // decode call out and use it here. 248 virtual bool isSizeAvailable() 249 { 250 return !m_failed && m_sizeAvailable; 251 } 252 253 virtual IntSize size() const { return m_size; } 254 255 // This will only differ from size() for ICO (where each frame is a 256 // different icon) or other formats where different frames are different 257 // sizes. This does NOT differ from size() for GIF or WebP, since 258 // decoding GIF or WebP composites any smaller frames against previous 259 // frames to create full-size frames. 260 virtual IntSize frameSizeAtIndex(size_t) const 261 { 262 return size(); 263 } 264 265 // Returns whether the size is legal (i.e. not going to result in 266 // overflow elsewhere). If not, marks decoding as failed. 267 virtual bool setSize(unsigned width, unsigned height) 268 { 269 if (isOverSize(width, height)) 270 return setFailed(); 271 m_size = IntSize(width, height); 272 m_sizeAvailable = true; 273 return true; 274 } 275 276 // Lazily-decodes enough of the image to get the frame count (if 277 // possible), without decoding the individual frames. 278 // FIXME: Right now that has to be done by each subclass; factor the 279 // decode call out and use it here. 280 virtual size_t frameCount() { return 1; } 281 282 virtual int repetitionCount() const { return cAnimationNone; } 283 284 // Decodes as much of the requested frame as possible, and returns an 285 // ImageDecoder-owned pointer. 286 virtual ImageFrame* frameBufferAtIndex(size_t) = 0; 287 288 // Make the best effort guess to check if the requested frame has alpha channel. 289 virtual bool frameHasAlphaAtIndex(size_t) const; 290 291 // Whether or not the frame is fully received. 292 virtual bool frameIsCompleteAtIndex(size_t) const; 293 294 // Duration for displaying a frame in seconds. This method is used by animated images only. 295 virtual float frameDurationAtIndex(size_t) const { return 0; } 296 297 // Number of bytes in the decoded frame requested. Return 0 if not yet decoded. 298 virtual unsigned frameBytesAtIndex(size_t) const; 299 300 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; } 301 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; } 302 303 ImageOrientation orientation() const { return m_orientation; } 304 305 enum { iccColorProfileHeaderLength = 128 }; 306 307 static bool rgbColorProfile(const char* profileData, unsigned profileLength) 308 { 309 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength); 310 311 return !memcmp(&profileData[16], "RGB ", 4); 312 } 313 314 static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength) 315 { 316 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength); 317 318 return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[12], "scnr", 4); 319 } 320 321 #if USE(QCMSLIB) 322 static qcms_profile* qcmsOutputDeviceProfile() 323 { 324 static qcms_profile* outputDeviceProfile = 0; 325 326 static bool qcmsInitialized = false; 327 if (!qcmsInitialized) { 328 qcmsInitialized = true; 329 // FIXME: Add optional ICCv4 support. 330 #if OS(DARWIN) 331 RetainPtr<CGColorSpaceRef> monitorColorSpace(AdoptCF, CGDisplayCopyColorSpace(CGMainDisplayID())); 332 CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpace.get())); 333 if (iccProfile) { 334 size_t length = CFDataGetLength(iccProfile); 335 const unsigned char* systemProfile = CFDataGetBytePtr(iccProfile); 336 outputDeviceProfile = qcms_profile_from_memory(systemProfile, length); 337 } 338 #else 339 // FIXME: add support for multiple monitors. 340 ColorProfile profile; 341 screenColorProfile(profile); 342 if (!profile.isEmpty()) 343 outputDeviceProfile = qcms_profile_from_memory(profile.data(), profile.size()); 344 #endif 345 if (outputDeviceProfile && qcms_profile_is_bogus(outputDeviceProfile)) { 346 qcms_profile_release(outputDeviceProfile); 347 outputDeviceProfile = 0; 348 } 349 if (!outputDeviceProfile) 350 outputDeviceProfile = qcms_profile_sRGB(); 351 if (outputDeviceProfile) 352 qcms_profile_precache_output_transform(outputDeviceProfile); 353 } 354 return outputDeviceProfile; 355 } 356 #endif 357 358 // Sets the "decode failure" flag. For caller convenience (since so 359 // many callers want to return false after calling this), returns false 360 // to enable easy tailcalling. Subclasses may override this to also 361 // clean up any local data. 362 virtual bool setFailed() 363 { 364 m_failed = true; 365 return false; 366 } 367 368 bool failed() const { return m_failed; } 369 370 // Clears decoded pixel data from all frames except the provided frame. 371 // Callers may pass WTF::notFound to clear all frames. 372 // Note: If |m_frameBufferCache| contains only one frame, it won't be cleared. 373 // Returns the number of bytes of frame data actually cleared. 374 virtual size_t clearCacheExceptFrame(size_t); 375 376 // If the image has a cursor hot-spot, stores it in the argument 377 // and returns true. Otherwise returns false. 378 virtual bool hotSpot(IntPoint&) const { return false; } 379 380 virtual void setMemoryAllocator(SkBitmap::Allocator* allocator) 381 { 382 // FIXME: this doesn't work for images with multiple frames. 383 if (m_frameBufferCache.isEmpty()) { 384 m_frameBufferCache.resize(1); 385 m_frameBufferCache[0].setRequiredPreviousFrameIndex( 386 findRequiredPreviousFrame(0)); 387 } 388 m_frameBufferCache[0].setMemoryAllocator(allocator); 389 } 390 391 protected: 392 // Calculates the most recent frame whose image data may be needed in 393 // order to decode frame |frameIndex|, based on frame disposal methods. 394 // If no previous frame's data is required, returns WTF::notFound. 395 // 396 // This function requires that the previous frame's 397 // |m_requiredPreviousFrameIndex| member has been set correctly. The 398 // easiest way to ensure this is for subclasses to call this method and 399 // store the result on the frame via setRequiredPreviousFrameIndex() 400 // as soon as the frame has been created and parsed sufficiently to 401 // determine the disposal method; assuming this happens for all frames 402 // in order, the required invariant will hold. 403 // 404 // Image formats which do not use more than one frame do not need to 405 // worry about this; see comments on 406 // ImageFrame::m_requiredPreviousFrameIndex. 407 size_t findRequiredPreviousFrame(size_t frameIndex); 408 409 virtual void clearFrameBuffer(size_t frameIndex); 410 411 RefPtr<SharedBuffer> m_data; // The encoded data. 412 Vector<ImageFrame, 1> m_frameBufferCache; 413 bool m_premultiplyAlpha; 414 bool m_ignoreGammaAndColorProfile; 415 ImageOrientation m_orientation; 416 417 private: 418 // Some code paths compute the size of the image as "width * height * 4" 419 // and return it as a (signed) int. Avoid overflow. 420 static bool isOverSize(unsigned width, unsigned height) 421 { 422 unsigned long long total_size = static_cast<unsigned long long>(width) 423 * static_cast<unsigned long long>(height); 424 return total_size > ((1 << 29) - 1); 425 } 426 427 IntSize m_size; 428 bool m_sizeAvailable; 429 bool m_isAllDataReceived; 430 bool m_failed; 431 }; 432 433 } // namespace WebCore 434 435 #endif 436