ImageDecoder.h 14 KB
Newer Older
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 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (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 30
#ifndef ImageDecoder_h
#define ImageDecoder_h
31

32
#include "IntRect.h"
33
#include "ImageSource.h"
34
#include "PlatformString.h"
35
#include "SharedBuffer.h"
36 37
#include <wtf/Assertions.h>
#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 47
#endif

48 49
namespace WebCore {

50 51 52
    // FIXME: Do we want better encapsulation?
    typedef Vector<char> ColorProfile;

53 54
    // ImageFrame represents the decoded image data.  This buffer is what all
    // decoders write a single frame into.
55
    class ImageFrame {
56 57 58
    public:
        enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
        enum FrameDisposalMethod {
59 60 61 62 63 64
            // If you change the numeric values of these, make sure you audit
            // all users, as some users may cast raw values to/from these
            // constants.
            DisposeNotSpecified,      // Leave frame in framebuffer
            DisposeKeep,              // Leave frame in framebuffer
            DisposeOverwriteBgcolor,  // Clear frame to transparent
65
            DisposeOverwritePrevious  // Clear frame to previous framebuffer
66
                                      // contents
67
        };
68
#if USE(SKIA) || PLATFORM(QT)
69 70
        typedef uint32_t PixelData;
#else
71
        typedef unsigned PixelData;
72
#endif
73

74
        ImageFrame();
75

76
        ImageFrame(const ImageFrame& other) { operator=(other); }
77 78 79

        // For backends which refcount their data, this operator doesn't need to
        // create a new copy of the image data, only increase the ref count.
80
        ImageFrame& operator=(const ImageFrame& other);
81

82 83 84
        // These do not touch other metadata, only the raw pixel data.
        void clearPixelData();
        void zeroFillPixelData();
85

86 87 88
        // Makes this frame have an independent copy of the provided image's
        // pixel data, so that modifications in one frame are not reflected in
        // the other.  Returns whether the copy succeeded.
89
        bool copyBitmapData(const ImageFrame&);
90

91 92
        // Makes this frame reference the provided image's pixel data, so that
        // modifications in one frame are reflected in the other.
93
        void copyReferenceToBitmapData(const ImageFrame&);
94

95 96 97
        // Copies the pixel data at [(startX, startY), (endX, startY)) to the
        // same X-coordinates on each subsequent row up to but not including
        // endY.
98 99 100 101 102 103 104 105 106
        void copyRowNTimes(int startX, int endX, int startY, int endY)
        {
            ASSERT(startX < width());
            ASSERT(endX <= width());
            ASSERT(startY < height());
            ASSERT(endY <= height());
            const int rowBytes = (endX - startX) * sizeof(PixelData);
            const PixelData* const startAddr = getAddr(startX, startY);
            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 112
        // are written.  Must only be called once.  Returns whether allocation
        // succeeded.
113
        bool setSize(int newWidth, int newHeight);
114

115 116 117
        // Returns a caller-owned pointer to the underlying native image data.
        // (Actual use: This pointer will be owned by BitmapImage and freed in
        // FrameData::clear()).
118
        NativeImagePtr asNewNativeImage() const;
119

120
        bool hasAlpha() const;
121
        const IntRect& originalFrameRect() const { return m_originalFrameRect; }
122 123 124
        FrameStatus status() const { return m_status; }
        unsigned duration() const { return m_duration; }
        FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
125
        bool premultiplyAlpha() const { return m_premultiplyAlpha; }
126

127
        void setHasAlpha(bool alpha);
128
        void setColorProfile(const ColorProfile&);
129
        void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
130
        void setStatus(FrameStatus status);
131 132
        void setDuration(unsigned duration) { m_duration = duration; }
        void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
133
        void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
134

135 136 137 138 139
        inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
        {
            setRGBA(getAddr(x, y), r, g, b, a);
        }

140
#if PLATFORM(QT)
141
        void setPixmap(const QPixmap& pixmap);
142 143
#endif

144
    private:
145
#if USE(CG)
146 147 148 149 150
        typedef RetainPtr<CFMutableDataRef> NativeBackingStore;
#else
        typedef Vector<PixelData> NativeBackingStore;
#endif

151 152
        int width() const;
        int height() const;
153

154 155
        inline PixelData* getAddr(int x, int y)
        {
156
#if USE(SKIA)
157
            return m_bitmap.bitmap().getAddr32(x, y);
158
#elif PLATFORM(QT)
159 160
            m_image = m_pixmap.toImage();
            m_pixmap = QPixmap();
161
            return reinterpret_cast_ptr<QRgb*>(m_image.scanLine(y)) + x;
162
#else
163
            return m_bytes + (y * width()) + x;
164 165
#endif
        }
166 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 174 175 176 177
                    float alphaPercent = a / 255.0f;
                    r = static_cast<unsigned>(r * alphaPercent);
                    g = static_cast<unsigned>(g * alphaPercent);
                    b = static_cast<unsigned>(b * alphaPercent);
                }
178
#if USE(SKIA)
179 180 181 182
                // we are sure to call the NoCheck version, since we may
                // deliberately pass non-premultiplied values, and we don't want
                // an assert.
                *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 192 193
#if PLATFORM(CHROMIUM) && OS(DARWIN)
        ColorProfile m_colorProfile;
#endif
194
#elif PLATFORM(QT)
195
        mutable QPixmap m_pixmap;
196
        mutable QImage m_image;
197 198
        bool m_hasAlpha;
        IntSize m_size;
199
#else
200 201
        NativeBackingStore m_backingStore;
        PixelData* m_bytes; // The memory is backed by m_backingStore.
202 203
        IntSize m_size;
        bool m_hasAlpha;
204
        ColorProfile m_colorProfile;
205
#endif
206 207 208 209 210 211 212 213
        IntRect m_originalFrameRect; // This will always just be the entire
                                     // buffer except for GIF frames whose
                                     // original rect was smaller than the
                                     // overall image size.
        FrameStatus m_status;
        unsigned m_duration;
        FrameDisposalMethod m_disposalMethod;
        bool m_premultiplyAlpha;
214 215
    };

216 217
    // ImageDecoder is a base for all format-specific decoders
    // (e.g. JPEGImageDecoder).  This base manages the ImageFrame cache.
218
    //
219 220 221
    // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample
    // at decode time.  Image decoders will downsample any images larger than
    // |m_maxNumPixels|.  FIXME: Not yet supported by all decoders.
222 223
    class ImageDecoder {
        WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
224
    public:
225
        ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
226
            : m_scaled(false)
227 228
            , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
            , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored)
229
            , m_sizeAvailable(false)
230
            , m_maxNumPixels(-1)
231
            , m_isAllDataReceived(false)
232
            , m_failed(false) { }
233

234
        virtual ~ImageDecoder() { }
235

236 237 238
        // Returns a caller-owned decoder of the appropriate type.  Returns 0 if
        // we can't sniff a supported type from the provided data (possibly
        // because there isn't enough data yet).
239
        static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
240

241 242
        virtual String filenameExtension() const = 0;

243
        bool isAllDataReceived() const { return m_isAllDataReceived; }
244

245 246
        virtual void setData(SharedBuffer* data, bool allDataReceived)
        {
247
            if (m_failed)
248
                return;
249 250 251
            m_data = data;
            m_isAllDataReceived = allDataReceived;
        }
252

253 254 255
        // Lazily-decodes enough of the image to get the size (if possible).
        // FIXME: Right now that has to be done by each subclass; factor the
        // decode call out and use it here.
256
        virtual bool isSizeAvailable()
257
        {
258
            return !m_failed && m_sizeAvailable;
259
        }
260

261
        virtual IntSize size() const { return m_size; }
262

263 264 265 266 267
        IntSize scaledSize() const
        {
            return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size();
        }

268 269 270 271 272
        // This will only differ from size() for ICO (where each frame is a
        // different icon) or other formats where different frames are different
        // sizes.  This does NOT differ from size() for GIF, since decoding GIFs
        // composites any smaller frames against previous frames to create full-
        // size frames.
273 274 275 276 277
        virtual IntSize frameSizeAtIndex(size_t) const
        {
            return size();
        }

278 279
        // Returns whether the size is legal (i.e. not going to result in
        // overflow elsewhere).  If not, marks decoding as failed.
280 281
        virtual bool setSize(unsigned width, unsigned height)
        {
282 283
            if (isOverSize(width, height))
                return setFailed();
284 285 286 287 288
            m_size = IntSize(width, height);
            m_sizeAvailable = true;
            return true;
        }

289 290 291 292
        // Lazily-decodes enough of the image to get the frame count (if
        // possible), without decoding the individual frames.
        // FIXME: Right now that has to be done by each subclass; factor the
        // decode call out and use it here.
293
        virtual size_t frameCount() { return 1; }
294 295 296

        virtual int repetitionCount() const { return cAnimationNone; }

297 298
        // Decodes as much of the requested frame as possible, and returns an
        // ImageDecoder-owned pointer.
299
        virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
300

301
        void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
302 303
        bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }

304 305
        // Sets the "decode failure" flag.  For caller convenience (since so
        // many callers want to return false after calling this), returns false
306 307
        // to enable easy tailcalling.  Subclasses may override this to also
        // clean up any local data.
308 309 310 311 312 313
        virtual bool setFailed()
        {
            m_failed = true;
            return false;
        }

314 315
        bool failed() const { return m_failed; }

316 317 318 319
        // Clears decoded pixel data from before the provided frame unless that
        // data may be needed to decode future frames (e.g. due to GIF frame
        // compositing).
        virtual void clearFrameBufferCache(size_t) { }
320

321 322 323 324
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
        void setMaxNumPixels(int m) { m_maxNumPixels = m; }
#endif

325
    protected:
326 327 328
        void prepareScaleDataIfNecessary();
        int upperBoundScaledX(int origX, int searchStart = 0);
        int lowerBoundScaledX(int origX, int searchStart = 0);
329 330
        int upperBoundScaledY(int origY, int searchStart = 0);
        int lowerBoundScaledY(int origY, int searchStart = 0);
331 332
        int scaledY(int origY, int searchStart = 0);

333
        RefPtr<SharedBuffer> m_data; // The encoded data.
334
        Vector<ImageFrame> m_frameBufferCache;
335
        ColorProfile m_colorProfile;
336
        bool m_scaled;
337 338
        Vector<int> m_scaledColumns;
        Vector<int> m_scaledRows;
339
        bool m_premultiplyAlpha;
340
        bool m_ignoreGammaAndColorProfile;
341 342 343 344 345 346 347 348 349 350

    private:
        // Some code paths compute the size of the image as "width * height * 4"
        // and return it as a (signed) int.  Avoid overflow.
        static bool isOverSize(unsigned width, unsigned height)
        {
            unsigned long long total_size = static_cast<unsigned long long>(width)
                                          * static_cast<unsigned long long>(height);
            return total_size > ((1 << 29) - 1);
        }
351 352 353

        IntSize m_size;
        bool m_sizeAvailable;
354
        int m_maxNumPixels;
355
        bool m_isAllDataReceived;
356
        bool m_failed;
357
    };
358

359
} // namespace WebCore
360 361

#endif