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 // Allocates space for the pixel data. Must be called before any pixels 111 // are written. Must only be called once. Returns whether allocation 112 // succeeded. 113 bool setSize(int newWidth, int newHeight); 114 115 // Returns a caller-owned pointer to the underlying native image data. 116 // (Actual use: This pointer will be owned by BitmapImage and freed in 117 // FrameData::clear()). 118 NativeImagePtr asNewNativeImage() const; 119 120 bool hasAlpha() const; originalFrameRect()121 const IntRect& originalFrameRect() const { return m_originalFrameRect; } status()122 FrameStatus status() const { return m_status; } duration()123 unsigned duration() const { return m_duration; } disposalMethod()124 FrameDisposalMethod disposalMethod() const { return m_disposalMethod; } premultiplyAlpha()125 bool premultiplyAlpha() const { return m_premultiplyAlpha; } 126 127 void setHasAlpha(bool alpha); 128 void setColorProfile(const ColorProfile&); setOriginalFrameRect(const IntRect & r)129 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; } 130 void setStatus(FrameStatus status); setDuration(unsigned duration)131 void setDuration(unsigned duration) { m_duration = duration; } setDisposalMethod(FrameDisposalMethod method)132 void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; } setPremultiplyAlpha(bool premultiplyAlpha)133 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; } 134 setRGBA(int x,int y,unsigned r,unsigned g,unsigned b,unsigned a)135 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a) 136 { 137 setRGBA(getAddr(x, y), r, g, b, a); 138 } 139 140 #if PLATFORM(QT) 141 void setPixmap(const QPixmap& pixmap); 142 #endif 143 144 private: 145 #if USE(CG) 146 typedef RetainPtr<CFMutableDataRef> NativeBackingStore; 147 #else 148 typedef Vector<PixelData> NativeBackingStore; 149 #endif 150 151 int width() const; 152 int height() const; 153 getAddr(int x,int y)154 inline PixelData* getAddr(int x, int y) 155 { 156 #if USE(SKIA) 157 return m_bitmap.getAddr32(x, y); 158 #elif PLATFORM(QT) 159 m_image = m_pixmap.toImage(); 160 m_pixmap = QPixmap(); 161 return reinterpret_cast_ptr<QRgb*>(m_image.scanLine(y)) + x; 162 #else 163 return m_bytes + (y * width()) + x; 164 #endif 165 } 166 setRGBA(PixelData * dest,unsigned r,unsigned g,unsigned b,unsigned a)167 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 168 { 169 if (m_premultiplyAlpha && !a) 170 *dest = 0; 171 else { 172 if (m_premultiplyAlpha && a < 255) { 173 float alphaPercent = a / 255.0f; 174 r = static_cast<unsigned>(r * alphaPercent); 175 g = static_cast<unsigned>(g * alphaPercent); 176 b = static_cast<unsigned>(b * alphaPercent); 177 } 178 #if USE(SKIA) 179 // we are sure to call the NoCheck version, since we may 180 // deliberately pass non-premultiplied values, and we don't want 181 // an assert. 182 *dest = SkPackARGB32NoCheck(a, r, g, b); 183 #else 184 *dest = (a << 24 | r << 16 | g << 8 | b); 185 #endif 186 } 187 } 188 189 #if USE(SKIA) 190 NativeImageSkia m_bitmap; 191 #elif PLATFORM(QT) 192 mutable QPixmap m_pixmap; 193 mutable QImage m_image; 194 bool m_hasAlpha; 195 IntSize m_size; 196 #else 197 NativeBackingStore m_backingStore; 198 PixelData* m_bytes; // The memory is backed by m_backingStore. 199 IntSize m_size; 200 bool m_hasAlpha; 201 ColorProfile m_colorProfile; 202 #endif 203 IntRect m_originalFrameRect; // This will always just be the entire 204 // buffer except for GIF frames whose 205 // original rect was smaller than the 206 // overall image size. 207 FrameStatus m_status; 208 unsigned m_duration; 209 FrameDisposalMethod m_disposalMethod; 210 bool m_premultiplyAlpha; 211 }; 212 213 // ImageDecoder is a base for all format-specific decoders 214 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache. 215 // 216 // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample 217 // at decode time. Image decoders will downsample any images larger than 218 // |m_maxNumPixels|. FIXME: Not yet supported by all decoders. 219 class ImageDecoder { 220 WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED; 221 public: ImageDecoder(ImageSource::AlphaOption alphaOption,ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)222 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) 223 : m_scaled(false) 224 , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied) 225 , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored) 226 , m_sizeAvailable(false) 227 , m_maxNumPixels(-1) 228 , m_isAllDataReceived(false) 229 , m_failed(false) { } 230 ~ImageDecoder()231 virtual ~ImageDecoder() { } 232 233 // Returns a caller-owned decoder of the appropriate type. Returns 0 if 234 // we can't sniff a supported type from the provided data (possibly 235 // because there isn't enough data yet). 236 static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); 237 238 virtual String filenameExtension() const = 0; 239 isAllDataReceived()240 bool isAllDataReceived() const { return m_isAllDataReceived; } 241 setData(SharedBuffer * data,bool allDataReceived)242 virtual void setData(SharedBuffer* data, bool allDataReceived) 243 { 244 if (m_failed) 245 return; 246 m_data = data; 247 m_isAllDataReceived = allDataReceived; 248 } 249 250 // Lazily-decodes enough of the image to get the size (if possible). 251 // FIXME: Right now that has to be done by each subclass; factor the 252 // decode call out and use it here. isSizeAvailable()253 virtual bool isSizeAvailable() 254 { 255 return !m_failed && m_sizeAvailable; 256 } 257 size()258 virtual IntSize size() const { return m_size; } 259 scaledSize()260 IntSize scaledSize() const 261 { 262 return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size(); 263 } 264 265 // This will only differ from size() for ICO (where each frame is a 266 // different icon) or other formats where different frames are different 267 // sizes. This does NOT differ from size() for GIF, since decoding GIFs 268 // composites any smaller frames against previous frames to create full- 269 // size frames. frameSizeAtIndex(size_t)270 virtual IntSize frameSizeAtIndex(size_t) const 271 { 272 return size(); 273 } 274 275 // Returns whether the size is legal (i.e. not going to result in 276 // overflow elsewhere). If not, marks decoding as failed. setSize(unsigned width,unsigned height)277 virtual bool setSize(unsigned width, unsigned height) 278 { 279 if (isOverSize(width, height)) 280 return setFailed(); 281 m_size = IntSize(width, height); 282 m_sizeAvailable = true; 283 return true; 284 } 285 286 // Lazily-decodes enough of the image to get the frame count (if 287 // possible), without decoding the individual frames. 288 // FIXME: Right now that has to be done by each subclass; factor the 289 // decode call out and use it here. frameCount()290 virtual size_t frameCount() { return 1; } 291 repetitionCount()292 virtual int repetitionCount() const { return cAnimationNone; } 293 294 // Decodes as much of the requested frame as possible, and returns an 295 // ImageDecoder-owned pointer. 296 virtual ImageFrame* frameBufferAtIndex(size_t) = 0; 297 setIgnoreGammaAndColorProfile(bool flag)298 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; } ignoresGammaAndColorProfile()299 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; } 300 301 // Sets the "decode failure" flag. For caller convenience (since so 302 // many callers want to return false after calling this), returns false 303 // to enable easy tailcalling. Subclasses may override this to also 304 // clean up any local data. setFailed()305 virtual bool setFailed() 306 { 307 m_failed = true; 308 return false; 309 } 310 failed()311 bool failed() const { return m_failed; } 312 313 // Clears decoded pixel data from before the provided frame unless that 314 // data may be needed to decode future frames (e.g. due to GIF frame 315 // compositing). clearFrameBufferCache(size_t)316 virtual void clearFrameBufferCache(size_t) { } 317 318 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) setMaxNumPixels(int m)319 void setMaxNumPixels(int m) { m_maxNumPixels = m; } 320 #endif 321 322 protected: 323 void prepareScaleDataIfNecessary(); 324 int upperBoundScaledX(int origX, int searchStart = 0); 325 int lowerBoundScaledX(int origX, int searchStart = 0); 326 int upperBoundScaledY(int origY, int searchStart = 0); 327 int lowerBoundScaledY(int origY, int searchStart = 0); 328 int scaledY(int origY, int searchStart = 0); 329 330 RefPtr<SharedBuffer> m_data; // The encoded data. 331 Vector<ImageFrame> m_frameBufferCache; 332 ColorProfile m_colorProfile; 333 bool m_scaled; 334 Vector<int> m_scaledColumns; 335 Vector<int> m_scaledRows; 336 bool m_premultiplyAlpha; 337 bool m_ignoreGammaAndColorProfile; 338 339 private: 340 // Some code paths compute the size of the image as "width * height * 4" 341 // and return it as a (signed) int. Avoid overflow. isOverSize(unsigned width,unsigned height)342 static bool isOverSize(unsigned width, unsigned height) 343 { 344 unsigned long long total_size = static_cast<unsigned long long>(width) 345 * static_cast<unsigned long long>(height); 346 return total_size > ((1 << 29) - 1); 347 } 348 349 IntSize m_size; 350 bool m_sizeAvailable; 351 int m_maxNumPixels; 352 bool m_isAllDataReceived; 353 bool m_failed; 354 }; 355 356 } // namespace WebCore 357 358 #endif 359