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 ImageFrame_h 28 #define ImageFrame_h 29 30 #include "platform/PlatformExport.h" 31 #include "platform/geometry/IntRect.h" 32 #include "platform/graphics/skia/NativeImageSkia.h" 33 #include "wtf/Assertions.h" 34 #include "wtf/PassRefPtr.h" 35 36 namespace blink { 37 38 // ImageFrame represents the decoded image data. This buffer is what all 39 // decoders write a single frame into. 40 class PLATFORM_EXPORT ImageFrame { 41 public: 42 enum Status { FrameEmpty, FramePartial, FrameComplete }; 43 enum DisposalMethod { 44 // If you change the numeric values of these, make sure you audit 45 // all users, as some users may cast raw values to/from these 46 // constants. 47 DisposeNotSpecified, // Leave frame in framebuffer 48 DisposeKeep, // Leave frame in framebuffer 49 DisposeOverwriteBgcolor, // Clear frame to fully transparent 50 DisposeOverwritePrevious // Clear frame to previous framebuffer contents 51 }; 52 // Indicates how non-opaque pixels in the current frame rectangle 53 // are blended with those in the previous frame. 54 // Notes: 55 // * GIF always uses 'BlendAtopPreviousFrame'. 56 // * WebP also uses the 'BlendAtopBgcolor' option. This is useful for 57 // cases where one wants to transform a few opaque pixels of the 58 // previous frame into non-opaque pixels in the current frame. 59 enum AlphaBlendSource { 60 // Blend non-opaque pixels atop the corresponding pixels in the 61 // initial buffer state (i.e. any previous frame buffer after having 62 // been properly disposed). 63 BlendAtopPreviousFrame, 64 65 // Blend non-opaque pixels against fully transparent (i.e. simply 66 // overwrite the corresponding pixels). 67 BlendAtopBgcolor, 68 }; 69 typedef uint32_t PixelData; 70 71 ImageFrame(); 72 ImageFrame(const ImageFrame & other)73 ImageFrame(const ImageFrame& other) { operator=(other); } 74 75 // For backends which refcount their data, this operator doesn't need to 76 // create a new copy of the image data, only increase the ref count. 77 ImageFrame& operator=(const ImageFrame& other); 78 79 // These do not touch other metadata, only the raw pixel data. 80 void clearPixelData(); 81 void zeroFillPixelData(); 82 void zeroFillFrameRect(const IntRect&); 83 84 // Makes this frame have an independent copy of the provided image's 85 // pixel data, so that modifications in one frame are not reflected in 86 // the other. Returns whether the copy succeeded. 87 bool copyBitmapData(const ImageFrame&); 88 89 // Copies the pixel data at [(startX, startY), (endX, startY)) to the 90 // same X-coordinates on each subsequent row up to but not including 91 // endY. copyRowNTimes(int startX,int endX,int startY,int endY)92 void copyRowNTimes(int startX, int endX, int startY, int endY) 93 { 94 ASSERT(startX < width()); 95 ASSERT(endX <= width()); 96 ASSERT(startY < height()); 97 ASSERT(endY <= height()); 98 const int rowBytes = (endX - startX) * sizeof(PixelData); 99 const PixelData* const startAddr = getAddr(startX, startY); 100 for (int destY = startY + 1; destY < endY; ++destY) 101 memcpy(getAddr(startX, destY), startAddr, rowBytes); 102 } 103 104 // Allocates space for the pixel data. Must be called before any pixels 105 // are written. Must only be called once. Returns whether allocation 106 // succeeded. 107 bool setSize(int newWidth, int newHeight); 108 109 // Returns a caller-owned pointer to the underlying native image data. 110 // (Actual use: This pointer will be owned by BitmapImage and freed in 111 // FrameData::clear()). 112 PassRefPtr<NativeImageSkia> asNewNativeImage() const; 113 114 bool hasAlpha() const; originalFrameRect()115 const IntRect& originalFrameRect() const { return m_originalFrameRect; } status()116 Status status() const { return m_status; } duration()117 unsigned duration() const { return m_duration; } disposalMethod()118 DisposalMethod disposalMethod() const { return m_disposalMethod; } alphaBlendSource()119 AlphaBlendSource alphaBlendSource() const { return m_alphaBlendSource; } premultiplyAlpha()120 bool premultiplyAlpha() const { return m_premultiplyAlpha; } allocator()121 SkBitmap::Allocator* allocator() const { return m_allocator; } getSkBitmap()122 const SkBitmap& getSkBitmap() const { return m_bitmap; } 123 // Returns true if the pixels changed, but the bitmap has not yet been notified. pixelsChanged()124 bool pixelsChanged() const { return m_pixelsChanged; } 125 requiredPreviousFrameIndex()126 size_t requiredPreviousFrameIndex() const 127 { 128 ASSERT(m_requiredPreviousFrameIndexValid); 129 return m_requiredPreviousFrameIndex; 130 } 131 #if ENABLE(ASSERT) requiredPreviousFrameIndexValid()132 bool requiredPreviousFrameIndexValid() const { return m_requiredPreviousFrameIndexValid; } 133 #endif 134 void setHasAlpha(bool alpha); setOriginalFrameRect(const IntRect & r)135 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; } 136 void setStatus(Status); setDuration(unsigned duration)137 void setDuration(unsigned duration) { m_duration = duration; } setDisposalMethod(DisposalMethod disposalMethod)138 void setDisposalMethod(DisposalMethod disposalMethod) { m_disposalMethod = disposalMethod; } setAlphaBlendSource(AlphaBlendSource alphaBlendSource)139 void setAlphaBlendSource(AlphaBlendSource alphaBlendSource) { m_alphaBlendSource = alphaBlendSource; } setPremultiplyAlpha(bool premultiplyAlpha)140 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; } setMemoryAllocator(SkBitmap::Allocator * allocator)141 void setMemoryAllocator(SkBitmap::Allocator* allocator) { m_allocator = allocator; } setSkBitmap(const SkBitmap & bitmap)142 void setSkBitmap(const SkBitmap& bitmap) { m_bitmap = bitmap; } 143 // The pixelsChanged flag needs to be set when the raw pixel data was directly modified 144 // (e.g. through a pointer or setRGBA). The flag is usually set after a batch of changes was made. setPixelsChanged(bool pixelsChanged)145 void setPixelsChanged(bool pixelsChanged) { m_pixelsChanged = pixelsChanged; } 146 setRequiredPreviousFrameIndex(size_t previousFrameIndex)147 void setRequiredPreviousFrameIndex(size_t previousFrameIndex) 148 { 149 m_requiredPreviousFrameIndex = previousFrameIndex; 150 #if ENABLE(ASSERT) 151 m_requiredPreviousFrameIndexValid = true; 152 #endif 153 } 154 getAddr(int x,int y)155 inline PixelData* getAddr(int x, int y) 156 { 157 return m_bitmap.getAddr32(x, y); 158 } 159 setRGBA(int x,int y,unsigned r,unsigned g,unsigned b,unsigned a)160 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a) 161 { 162 setRGBA(getAddr(x, y), r, g, b, a); 163 } 164 setRGBA(PixelData * dest,unsigned r,unsigned g,unsigned b,unsigned a)165 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 166 { 167 if (m_premultiplyAlpha) 168 setRGBAPremultiply(dest, r, g, b, a); 169 else 170 *dest = SkPackARGB32NoCheck(a, r, g, b); 171 } 172 173 static const unsigned div255 = static_cast<unsigned>(1.0 / 255 * (1 << 24)) + 1; 174 setRGBAPremultiply(PixelData * dest,unsigned r,unsigned g,unsigned b,unsigned a)175 static inline void setRGBAPremultiply(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 176 { 177 if (a < 255) { 178 if (!a) { 179 *dest = 0; 180 return; 181 } 182 183 unsigned alpha = a * div255; 184 r = (r * alpha) >> 24; 185 g = (g * alpha) >> 24; 186 b = (b * alpha) >> 24; 187 } 188 189 // Call the "NoCheck" version since we may deliberately pass non-premultiplied 190 // values, and we don't want an assert. 191 *dest = SkPackARGB32NoCheck(a, r, g, b); 192 } 193 setRGBARaw(PixelData * dest,unsigned r,unsigned g,unsigned b,unsigned a)194 static inline void setRGBARaw(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 195 { 196 *dest = SkPackARGB32NoCheck(a, r, g, b); 197 } 198 199 // Notifies the SkBitmap if any pixels changed and resets the flag. notifyBitmapIfPixelsChanged()200 inline void notifyBitmapIfPixelsChanged() 201 { 202 if (m_pixelsChanged) 203 m_bitmap.notifyPixelsChanged(); 204 m_pixelsChanged = false; 205 } 206 207 private: width()208 int width() const 209 { 210 return m_bitmap.width(); 211 } 212 height()213 int height() const 214 { 215 return m_bitmap.height(); 216 } 217 218 SkBitmap m_bitmap; 219 SkBitmap::Allocator* m_allocator; 220 bool m_hasAlpha; 221 // This will always just be the entire buffer except for GIF or WebP 222 // frames whose original rect was smaller than the overall image size. 223 IntRect m_originalFrameRect; 224 Status m_status; 225 unsigned m_duration; 226 DisposalMethod m_disposalMethod; 227 AlphaBlendSource m_alphaBlendSource; 228 bool m_premultiplyAlpha; 229 // True if the pixels changed, but the bitmap has not yet been notified. 230 bool m_pixelsChanged; 231 232 // The frame that must be decoded before this frame can be decoded. 233 // WTF::kNotFound if this frame doesn't require any previous frame. 234 // This is used by ImageDecoder::clearCacheExceptFrame(), and will never 235 // be read for image formats that do not have multiple frames. 236 size_t m_requiredPreviousFrameIndex; 237 #if ENABLE(ASSERT) 238 bool m_requiredPreviousFrameIndexValid; 239 #endif 240 }; 241 242 } // namespace blink 243 244 #endif 245