1/* 2 * Copyright (C) 2006 Apple 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) 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. 27 */ 28 29#ifndef ImageDecoder_h 30#define ImageDecoder_h 31 32#include "IntRect.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> 40 41#if USE(QCMSLIB) 42#include "qcms.h" 43#if OS(DARWIN) 44#include "GraphicsContextCG.h" 45#include <ApplicationServices/ApplicationServices.h> 46#include <wtf/RetainPtr.h> 47#endif 48#endif 49 50namespace 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 unsigned 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 PassNativeImagePtr 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 119 void setHasAlpha(bool alpha); 120 void setColorProfile(const ColorProfile&); 121 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; } 122 void setStatus(FrameStatus status); 123 void setDuration(unsigned duration) { m_duration = duration; } 124 void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; } 125 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; } 126 127 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a) 128 { 129 setRGBA(getAddr(x, y), r, g, b, a); 130 } 131 132 inline PixelData* getAddr(int x, int y) 133 { 134 return m_bytes + (y * width()) + x; 135 } 136 137 inline bool hasPixelData() const 138 { 139 return m_bytes; 140 } 141 142 // Use fix point multiplier instead of integer division or floating point math. 143 // This multipler produces exactly the same result for all values in range 0 - 255. 144 static const unsigned fixPointShift = 24; 145 static const unsigned fixPointMult = static_cast<unsigned>(1.0 / 255.0 * (1 << fixPointShift)) + 1; 146 // Multiplies unsigned value by fixpoint value and converts back to unsigned. 147 static unsigned fixPointUnsignedMultiply(unsigned fixed, unsigned v) 148 { 149 return (fixed * v) >> fixPointShift; 150 } 151 152 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 153 { 154 if (m_premultiplyAlpha && a < 255) { 155 if (!a) { 156 *dest = 0; 157 return; 158 } 159 160 unsigned alphaMult = a * fixPointMult; 161 r = fixPointUnsignedMultiply(r, alphaMult); 162 g = fixPointUnsignedMultiply(g, alphaMult); 163 b = fixPointUnsignedMultiply(b, alphaMult); 164 } 165 *dest = (a << 24 | r << 16 | g << 8 | b); 166 } 167 168 private: 169 int width() const 170 { 171 return m_size.width(); 172 } 173 174 int height() const 175 { 176 return m_size.height(); 177 } 178 179 Vector<PixelData> m_backingStore; 180 PixelData* m_bytes; // The memory is backed by m_backingStore. 181 IntSize m_size; 182 // FIXME: Do we need m_colorProfile anymore? 183 ColorProfile m_colorProfile; 184 bool m_hasAlpha; 185 IntRect m_originalFrameRect; // This will always just be the entire 186 // buffer except for GIF frames whose 187 // original rect was smaller than the 188 // overall image size. 189 FrameStatus m_status; 190 unsigned m_duration; 191 FrameDisposalMethod m_disposalMethod; 192 bool m_premultiplyAlpha; 193 }; 194 195 // ImageDecoder is a base for all format-specific decoders 196 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache. 197 // 198 // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample 199 // at decode time. Image decoders will downsample any images larger than 200 // |m_maxNumPixels|. FIXME: Not yet supported by all decoders. 201 class ImageDecoder { 202 WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED; 203 public: 204 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) 205 : m_scaled(false) 206 , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied) 207 , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored) 208 , m_sizeAvailable(false) 209 , m_maxNumPixels(-1) 210 , m_isAllDataReceived(false) 211 , m_failed(false) { } 212 213 virtual ~ImageDecoder() { } 214 215 // Returns a caller-owned decoder of the appropriate type. Returns 0 if 216 // we can't sniff a supported type from the provided data (possibly 217 // because there isn't enough data yet). 218 static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); 219 220 virtual String filenameExtension() const = 0; 221 222 bool isAllDataReceived() const { return m_isAllDataReceived; } 223 224 virtual void setData(SharedBuffer* data, bool allDataReceived) 225 { 226 if (m_failed) 227 return; 228 m_data = data; 229 m_isAllDataReceived = allDataReceived; 230 } 231 232 // Lazily-decodes enough of the image to get the size (if possible). 233 // FIXME: Right now that has to be done by each subclass; factor the 234 // decode call out and use it here. 235 virtual bool isSizeAvailable() 236 { 237 return !m_failed && m_sizeAvailable; 238 } 239 240 virtual IntSize size() const { return m_size; } 241 242 IntSize scaledSize() const 243 { 244 return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size(); 245 } 246 247 // This will only differ from size() for ICO (where each frame is a 248 // different icon) or other formats where different frames are different 249 // sizes. This does NOT differ from size() for GIF, since decoding GIFs 250 // composites any smaller frames against previous frames to create full- 251 // size frames. 252 virtual IntSize frameSizeAtIndex(size_t) const 253 { 254 return size(); 255 } 256 257 // Returns whether the size is legal (i.e. not going to result in 258 // overflow elsewhere). If not, marks decoding as failed. 259 virtual bool setSize(unsigned width, unsigned height) 260 { 261 if (isOverSize(width, height)) 262 return setFailed(); 263 m_size = IntSize(width, height); 264 m_sizeAvailable = true; 265 return true; 266 } 267 268 // Lazily-decodes enough of the image to get the frame count (if 269 // possible), without decoding the individual frames. 270 // FIXME: Right now that has to be done by each subclass; factor the 271 // decode call out and use it here. 272 virtual size_t frameCount() { return 1; } 273 274 virtual int repetitionCount() const { return cAnimationNone; } 275 276 // Decodes as much of the requested frame as possible, and returns an 277 // ImageDecoder-owned pointer. 278 virtual ImageFrame* frameBufferAtIndex(size_t) = 0; 279 280 // Make the best effort guess to check if the requested frame has alpha channel. 281 virtual bool frameHasAlphaAtIndex(size_t) const; 282 283 // Number of bytes in the decoded frame requested. Return 0 if not yet decoded. 284 virtual unsigned frameBytesAtIndex(size_t) const; 285 286 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; } 287 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; } 288 289 ImageOrientation orientation() const { return m_orientation; } 290 291 enum { iccColorProfileHeaderLength = 128 }; 292 293 static bool rgbColorProfile(const char* profileData, unsigned profileLength) 294 { 295 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength); 296 297 return !memcmp(&profileData[16], "RGB ", 4); 298 } 299 300 static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength) 301 { 302 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength); 303 304 return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[12], "scnr", 4); 305 } 306 307#if USE(QCMSLIB) 308 static qcms_profile* qcmsOutputDeviceProfile() 309 { 310 static qcms_profile* outputDeviceProfile = 0; 311 312 static bool qcmsInitialized = false; 313 if (!qcmsInitialized) { 314 qcmsInitialized = true; 315 // FIXME: Add optional ICCv4 support. 316#if OS(DARWIN) 317 RetainPtr<CGColorSpaceRef> monitorColorSpace = adoptCF(CGDisplayCopyColorSpace(CGMainDisplayID())); 318 CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpace.get())); 319 if (iccProfile) { 320 size_t length = CFDataGetLength(iccProfile); 321 const unsigned char* systemProfile = CFDataGetBytePtr(iccProfile); 322 outputDeviceProfile = qcms_profile_from_memory(systemProfile, length); 323 CFRelease(iccProfile); 324 } 325#endif 326 if (outputDeviceProfile && qcms_profile_is_bogus(outputDeviceProfile)) { 327 qcms_profile_release(outputDeviceProfile); 328 outputDeviceProfile = 0; 329 } 330 if (!outputDeviceProfile) 331 outputDeviceProfile = qcms_profile_sRGB(); 332 if (outputDeviceProfile) 333 qcms_profile_precache_output_transform(outputDeviceProfile); 334 } 335 return outputDeviceProfile; 336 } 337#endif 338 339 // Sets the "decode failure" flag. For caller convenience (since so 340 // many callers want to return false after calling this), returns false 341 // to enable easy tailcalling. Subclasses may override this to also 342 // clean up any local data. 343 virtual bool setFailed() 344 { 345 m_failed = true; 346 return false; 347 } 348 349 bool failed() const { return m_failed; } 350 351 // Clears decoded pixel data from before the provided frame unless that 352 // data may be needed to decode future frames (e.g. due to GIF frame 353 // compositing). 354 virtual void clearFrameBufferCache(size_t) { } 355 356#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) 357 void setMaxNumPixels(int m) { m_maxNumPixels = m; } 358#endif 359 360 // If the image has a cursor hot-spot, stores it in the argument 361 // and returns true. Otherwise returns false. 362 virtual bool hotSpot(IntPoint&) const { return false; } 363 364 protected: 365 void prepareScaleDataIfNecessary(); 366 int upperBoundScaledX(int origX, int searchStart = 0); 367 int lowerBoundScaledX(int origX, int searchStart = 0); 368 int upperBoundScaledY(int origY, int searchStart = 0); 369 int lowerBoundScaledY(int origY, int searchStart = 0); 370 int scaledY(int origY, int searchStart = 0); 371 372 RefPtr<SharedBuffer> m_data; // The encoded data. 373 Vector<ImageFrame, 1> m_frameBufferCache; 374 // FIXME: Do we need m_colorProfile any more, for any port? 375 ColorProfile m_colorProfile; 376 bool m_scaled; 377 Vector<int> m_scaledColumns; 378 Vector<int> m_scaledRows; 379 bool m_premultiplyAlpha; 380 bool m_ignoreGammaAndColorProfile; 381 ImageOrientation m_orientation; 382 383 private: 384 // Some code paths compute the size of the image as "width * height * 4" 385 // and return it as a (signed) int. Avoid overflow. 386 static bool isOverSize(unsigned width, unsigned height) 387 { 388 unsigned long long total_size = static_cast<unsigned long long>(width) 389 * static_cast<unsigned long long>(height); 390 return total_size > ((1 << 29) - 1); 391 } 392 393 IntSize m_size; 394 bool m_sizeAvailable; 395 int m_maxNumPixels; 396 bool m_isAllDataReceived; 397 bool m_failed; 398 }; 399 400} // namespace WebCore 401 402#endif 403