1 /* 2 * Copyright (C) 2006 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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 "PlatformString.h" 35 #include "SharedBuffer.h" 36 #include <wtf/Assertions.h> 37 #include <wtf/RefPtr.h> 38 #include <wtf/Vector.h> 39 40 #if USE(SKIA) 41 #include "NativeImageSkia.h" 42 #include "SkColorPriv.h" 43 #elif PLATFORM(QT) 44 #include <QPixmap> 45 #include <QImage> 46 #endif 47 48 namespace WebCore { 49 50 // FIXME: Do we want better encapsulation? 51 typedef Vector<char> ColorProfile; 52 53 // ImageFrame represents the decoded image data. This buffer is what all 54 // decoders write a single frame into. 55 class ImageFrame { 56 public: 57 enum FrameStatus { FrameEmpty, FramePartial, FrameComplete }; 58 enum FrameDisposalMethod { 59 // If you change the numeric values of these, make sure you audit 60 // all users, as some users may cast raw values to/from these 61 // constants. 62 DisposeNotSpecified, // Leave frame in framebuffer 63 DisposeKeep, // Leave frame in framebuffer 64 DisposeOverwriteBgcolor, // Clear frame to transparent 65 DisposeOverwritePrevious // Clear frame to previous framebuffer 66 // contents 67 }; 68 #if USE(SKIA) || PLATFORM(QT) 69 typedef uint32_t PixelData; 70 #else 71 typedef unsigned PixelData; 72 #endif 73 74 ImageFrame(); 75 ImageFrame(const ImageFrame & other)76 ImageFrame(const ImageFrame& other) { operator=(other); } 77 78 // For backends which refcount their data, this operator doesn't need to 79 // create a new copy of the image data, only increase the ref count. 80 ImageFrame& operator=(const ImageFrame& other); 81 82 // These do not touch other metadata, only the raw pixel data. 83 void clearPixelData(); 84 void zeroFillPixelData(); 85 86 // Makes this frame have an independent copy of the provided image's 87 // pixel data, so that modifications in one frame are not reflected in 88 // the other. Returns whether the copy succeeded. 89 bool copyBitmapData(const ImageFrame&); 90 91 // Makes this frame reference the provided image's pixel data, so that 92 // modifications in one frame are reflected in the other. 93 void copyReferenceToBitmapData(const ImageFrame&); 94 95 // Copies the pixel data at [(startX, startY), (endX, startY)) to the 96 // same X-coordinates on each subsequent row up to but not including 97 // endY. copyRowNTimes(int startX,int endX,int startY,int endY)98 void copyRowNTimes(int startX, int endX, int startY, int endY) 99 { 100 ASSERT(startX < width()); 101 ASSERT(endX <= width()); 102 ASSERT(startY < height()); 103 ASSERT(endY <= height()); 104 const int rowBytes = (endX - startX) * sizeof(PixelData); 105 const PixelData* const startAddr = getAddr(startX, startY); 106 for (int destY = startY + 1; destY < endY; ++destY) 107 memcpy(getAddr(startX, destY), startAddr, rowBytes); 108 } 109 110 #if PLATFORM(ANDROID) bitmap()111 NativeImageSkia& bitmap() { return m_bitmap; } bitmap()112 const NativeImageSkia& bitmap() const { return m_bitmap; } 113 #endif 114 115 // Allocates space for the pixel data. Must be called before any pixels 116 // are written. Must only be called once. Returns whether allocation 117 // succeeded. 118 bool setSize(int newWidth, int newHeight); 119 120 // Returns a caller-owned pointer to the underlying native image data. 121 // (Actual use: This pointer will be owned by BitmapImage and freed in 122 // FrameData::clear()). 123 NativeImagePtr asNewNativeImage() const; 124 125 bool hasAlpha() const; originalFrameRect()126 const IntRect& originalFrameRect() const { return m_originalFrameRect; } status()127 FrameStatus status() const { return m_status; } duration()128 unsigned duration() const { return m_duration; } disposalMethod()129 FrameDisposalMethod disposalMethod() const { return m_disposalMethod; } premultiplyAlpha()130 bool premultiplyAlpha() const { return m_premultiplyAlpha; } 131 132 void setHasAlpha(bool alpha); 133 void setColorProfile(const ColorProfile&); setOriginalFrameRect(const IntRect & r)134 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; } 135 void setStatus(FrameStatus status); setDuration(unsigned duration)136 void setDuration(unsigned duration) { m_duration = duration; } setDisposalMethod(FrameDisposalMethod method)137 void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; } setPremultiplyAlpha(bool premultiplyAlpha)138 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; } 139 setRGBA(int x,int y,unsigned r,unsigned g,unsigned b,unsigned a)140 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a) 141 { 142 setRGBA(getAddr(x, y), r, g, b, a); 143 } 144 145 #if PLATFORM(QT) 146 void setPixmap(const QPixmap& pixmap); 147 #endif 148 149 private: 150 #if USE(CG) 151 typedef RetainPtr<CFMutableDataRef> NativeBackingStore; 152 #else 153 typedef Vector<PixelData> NativeBackingStore; 154 #endif 155 156 int width() const; 157 int height() const; 158 getAddr(int x,int y)159 inline PixelData* getAddr(int x, int y) 160 { 161 #if USE(SKIA) 162 return m_bitmap.getAddr32(x, y); 163 #elif PLATFORM(QT) 164 m_image = m_pixmap.toImage(); 165 m_pixmap = QPixmap(); 166 return reinterpret_cast_ptr<QRgb*>(m_image.scanLine(y)) + x; 167 #else 168 return m_bytes + (y * width()) + x; 169 #endif 170 } 171 setRGBA(PixelData * dest,unsigned r,unsigned g,unsigned b,unsigned a)172 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 173 { 174 if (m_premultiplyAlpha && !a) 175 *dest = 0; 176 else { 177 if (m_premultiplyAlpha && a < 255) { 178 float alphaPercent = a / 255.0f; 179 r = static_cast<unsigned>(r * alphaPercent); 180 g = static_cast<unsigned>(g * alphaPercent); 181 b = static_cast<unsigned>(b * alphaPercent); 182 } 183 #if USE(SKIA) 184 // we are sure to call the NoCheck version, since we may 185 // deliberately pass non-premultiplied values, and we don't want 186 // an assert. 187 *dest = SkPackARGB32NoCheck(a, r, g, b); 188 #else 189 *dest = (a << 24 | r << 16 | g << 8 | b); 190 #endif 191 } 192 } 193 194 #if USE(SKIA) 195 NativeImageSkia m_bitmap; 196 #elif PLATFORM(QT) 197 mutable QPixmap m_pixmap; 198 mutable QImage m_image; 199 bool m_hasAlpha; 200 IntSize m_size; 201 #else 202 NativeBackingStore m_backingStore; 203 PixelData* m_bytes; // The memory is backed by m_backingStore. 204 IntSize m_size; 205 bool m_hasAlpha; 206 ColorProfile m_colorProfile; 207 #endif 208 IntRect m_originalFrameRect; // This will always just be the entire 209 // buffer except for GIF frames whose 210 // original rect was smaller than the 211 // overall image size. 212 FrameStatus m_status; 213 unsigned m_duration; 214 FrameDisposalMethod m_disposalMethod; 215 bool m_premultiplyAlpha; 216 }; 217 218 // ImageDecoder is a base for all format-specific decoders 219 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache. 220 // 221 // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample 222 // at decode time. Image decoders will downsample any images larger than 223 // |m_maxNumPixels|. FIXME: Not yet supported by all decoders. 224 class ImageDecoder { 225 WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED; 226 public: ImageDecoder(ImageSource::AlphaOption alphaOption,ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)227 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) 228 : m_scaled(false) 229 , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied) 230 , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored) 231 , m_sizeAvailable(false) 232 , m_maxNumPixels(-1) 233 , m_isAllDataReceived(false) 234 , m_failed(false) { } 235 ~ImageDecoder()236 virtual ~ImageDecoder() { } 237 238 // Returns a caller-owned decoder of the appropriate type. Returns 0 if 239 // we can't sniff a supported type from the provided data (possibly 240 // because there isn't enough data yet). 241 static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); 242 243 virtual String filenameExtension() const = 0; 244 isAllDataReceived()245 bool isAllDataReceived() const { return m_isAllDataReceived; } 246 setData(SharedBuffer * data,bool allDataReceived)247 virtual void setData(SharedBuffer* data, bool allDataReceived) 248 { 249 if (m_failed) 250 return; 251 m_data = data; 252 m_isAllDataReceived = allDataReceived; 253 } 254 255 // Lazily-decodes enough of the image to get the size (if possible). 256 // FIXME: Right now that has to be done by each subclass; factor the 257 // decode call out and use it here. isSizeAvailable()258 virtual bool isSizeAvailable() 259 { 260 return !m_failed && m_sizeAvailable; 261 } 262 size()263 virtual IntSize size() const { return m_size; } 264 scaledSize()265 IntSize scaledSize() const 266 { 267 return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size(); 268 } 269 270 // This will only differ from size() for ICO (where each frame is a 271 // different icon) or other formats where different frames are different 272 // sizes. This does NOT differ from size() for GIF, since decoding GIFs 273 // composites any smaller frames against previous frames to create full- 274 // size frames. frameSizeAtIndex(size_t)275 virtual IntSize frameSizeAtIndex(size_t) const 276 { 277 return size(); 278 } 279 280 // Returns whether the size is legal (i.e. not going to result in 281 // overflow elsewhere). If not, marks decoding as failed. setSize(unsigned width,unsigned height)282 virtual bool setSize(unsigned width, unsigned height) 283 { 284 if (isOverSize(width, height)) 285 return setFailed(); 286 m_size = IntSize(width, height); 287 m_sizeAvailable = true; 288 return true; 289 } 290 291 // Lazily-decodes enough of the image to get the frame count (if 292 // possible), without decoding the individual frames. 293 // FIXME: Right now that has to be done by each subclass; factor the 294 // decode call out and use it here. frameCount()295 virtual size_t frameCount() { return 1; } 296 repetitionCount()297 virtual int repetitionCount() const { return cAnimationNone; } 298 299 // Decodes as much of the requested frame as possible, and returns an 300 // ImageDecoder-owned pointer. 301 virtual ImageFrame* frameBufferAtIndex(size_t) = 0; 302 setIgnoreGammaAndColorProfile(bool flag)303 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; } ignoresGammaAndColorProfile()304 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; } 305 306 // Sets the "decode failure" flag. For caller convenience (since so 307 // many callers want to return false after calling this), returns false 308 // to enable easy tailcalling. Subclasses may override this to also 309 // clean up any local data. setFailed()310 virtual bool setFailed() 311 { 312 m_failed = true; 313 return false; 314 } 315 failed()316 bool failed() const { return m_failed; } 317 318 // Clears decoded pixel data from before the provided frame unless that 319 // data may be needed to decode future frames (e.g. due to GIF frame 320 // compositing). clearFrameBufferCache(size_t)321 virtual void clearFrameBufferCache(size_t) { } 322 323 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) setMaxNumPixels(int m)324 void setMaxNumPixels(int m) { m_maxNumPixels = m; } 325 #endif 326 327 protected: 328 void prepareScaleDataIfNecessary(); 329 int upperBoundScaledX(int origX, int searchStart = 0); 330 int lowerBoundScaledX(int origX, int searchStart = 0); 331 int upperBoundScaledY(int origY, int searchStart = 0); 332 int lowerBoundScaledY(int origY, int searchStart = 0); 333 int scaledY(int origY, int searchStart = 0); 334 335 RefPtr<SharedBuffer> m_data; // The encoded data. 336 Vector<ImageFrame> m_frameBufferCache; 337 ColorProfile m_colorProfile; 338 bool m_scaled; 339 Vector<int> m_scaledColumns; 340 Vector<int> m_scaledRows; 341 bool m_premultiplyAlpha; 342 bool m_ignoreGammaAndColorProfile; 343 344 private: 345 // Some code paths compute the size of the image as "width * height * 4" 346 // and return it as a (signed) int. Avoid overflow. isOverSize(unsigned width,unsigned height)347 static bool isOverSize(unsigned width, unsigned height) 348 { 349 unsigned long long total_size = static_cast<unsigned long long>(width) 350 * static_cast<unsigned long long>(height); 351 return total_size > ((1 << 29) - 1); 352 } 353 354 IntSize m_size; 355 bool m_sizeAvailable; 356 int m_maxNumPixels; 357 bool m_isAllDataReceived; 358 bool m_failed; 359 }; 360 361 } // namespace WebCore 362 363 #endif 364