Home | History | Annotate | Download | only in image-decoders
      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 WebCore {
     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 
     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.
     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;
    115     const IntRect& originalFrameRect() const { return m_originalFrameRect; }
    116     Status status() const { return m_status; }
    117     unsigned duration() const { return m_duration; }
    118     DisposalMethod disposalMethod() const { return m_disposalMethod; }
    119     AlphaBlendSource alphaBlendSource() const { return m_alphaBlendSource; }
    120     bool premultiplyAlpha() const { return m_premultiplyAlpha; }
    121     SkBitmap::Allocator* allocator() const { return m_allocator; }
    122     const SkBitmap& getSkBitmap() const { return m_bitmap->bitmap(); }
    123     // Returns true if the pixels changed, but the bitmap has not yet been notified.
    124     bool pixelsChanged() const { return m_pixelsChanged; }
    125 
    126     size_t requiredPreviousFrameIndex() const
    127     {
    128         ASSERT(m_requiredPreviousFrameIndexValid);
    129         return m_requiredPreviousFrameIndex;
    130     }
    131 #if !ASSERT_DISABLED
    132     bool requiredPreviousFrameIndexValid() const { return m_requiredPreviousFrameIndexValid; }
    133 #endif
    134     void setHasAlpha(bool alpha);
    135     void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
    136     void setStatus(Status);
    137     void setDuration(unsigned duration) { m_duration = duration; }
    138     void setDisposalMethod(DisposalMethod disposalMethod) { m_disposalMethod = disposalMethod; }
    139     void setAlphaBlendSource(AlphaBlendSource alphaBlendSource) { m_alphaBlendSource = alphaBlendSource; }
    140     void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
    141     void setMemoryAllocator(SkBitmap::Allocator* allocator) { m_allocator = allocator; }
    142     void setSkBitmap(const SkBitmap& bitmap) { m_bitmap = NativeImageSkia::create(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.
    145     void setPixelsChanged(bool pixelsChanged) { m_pixelsChanged = pixelsChanged; }
    146 
    147     void setRequiredPreviousFrameIndex(size_t previousFrameIndex)
    148     {
    149         m_requiredPreviousFrameIndex = previousFrameIndex;
    150 #if !ASSERT_DISABLED
    151         m_requiredPreviousFrameIndexValid = true;
    152 #endif
    153     }
    154 
    155     inline PixelData* getAddr(int x, int y)
    156     {
    157         return m_bitmap->bitmap().getAddr32(x, y);
    158     }
    159 
    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 
    165     static const unsigned div255 = static_cast<unsigned>(1.0 / 255 * (1 << 24)) + 1;
    166 
    167     inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
    168     {
    169         if (m_premultiplyAlpha && a < 255) {
    170             if (!a) {
    171                 *dest = 0;
    172                 return;
    173             }
    174 
    175             unsigned alpha = a * div255;
    176             r = (r * alpha) >> 24;
    177             g = (g * alpha) >> 24;
    178             b = (b * alpha) >> 24;
    179         }
    180 
    181         // Call the "NoCheck" version since we may deliberately pass non-premultiplied
    182         // values, and we don't want an assert.
    183         *dest = SkPackARGB32NoCheck(a, r, g, b);
    184     }
    185 
    186     inline void setRGBARaw(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
    187     {
    188         *dest = SkPackARGB32NoCheck(a, r, g, b);
    189     }
    190 
    191     // Notifies the SkBitmap if any pixels changed and resets the flag.
    192     inline void notifyBitmapIfPixelsChanged()
    193     {
    194         if (m_pixelsChanged)
    195             m_bitmap->bitmap().notifyPixelsChanged();
    196         m_pixelsChanged = false;
    197     }
    198 
    199 private:
    200     int width() const
    201     {
    202         return m_bitmap->bitmap().width();
    203     }
    204 
    205     int height() const
    206     {
    207         return m_bitmap->bitmap().height();
    208     }
    209 
    210     RefPtr<NativeImageSkia> m_bitmap;
    211     SkBitmap::Allocator* m_allocator;
    212     bool m_hasAlpha;
    213     // This will always just be the entire buffer except for GIF or WebP
    214     // frames whose original rect was smaller than the overall image size.
    215     IntRect m_originalFrameRect;
    216     Status m_status;
    217     unsigned m_duration;
    218     DisposalMethod m_disposalMethod;
    219     AlphaBlendSource m_alphaBlendSource;
    220     bool m_premultiplyAlpha;
    221     // True if the pixels changed, but the bitmap has not yet been notified.
    222     bool m_pixelsChanged;
    223 
    224     // The frame that must be decoded before this frame can be decoded.
    225     // WTF::kNotFound if this frame doesn't require any previous frame.
    226     // This is used by ImageDecoder::clearCacheExceptFrame(), and will never
    227     // be read for image formats that do not have multiple frames.
    228     size_t m_requiredPreviousFrameIndex;
    229 #if !ASSERT_DISABLED
    230     bool m_requiredPreviousFrameIndexValid;
    231 #endif
    232 };
    233 
    234 } // namespace WebCore
    235 
    236 #endif
    237