• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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