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 ImageDecoder_h
     28 #define ImageDecoder_h
     29 
     30 #include "SkColorPriv.h"
     31 #include "platform/PlatformExport.h"
     32 #include "platform/PlatformScreen.h"
     33 #include "platform/SharedBuffer.h"
     34 #include "platform/graphics/ImageSource.h"
     35 #include "platform/image-decoders/ImageFrame.h"
     36 #include "public/platform/Platform.h"
     37 #include "wtf/Assertions.h"
     38 #include "wtf/RefPtr.h"
     39 #include "wtf/text/WTFString.h"
     40 #include "wtf/Vector.h"
     41 
     42 #if USE(QCMSLIB)
     43 #include "qcms.h"
     44 #if OS(MACOSX)
     45 #include <ApplicationServices/ApplicationServices.h>
     46 #include "platform/graphics/cg/GraphicsContextCG.h"
     47 #include "wtf/RetainPtr.h"
     48 #endif
     49 #endif
     50 
     51 namespace WebCore {
     52 
     53 // ImageDecoder is a base for all format-specific decoders
     54 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache.
     55 //
     56 class PLATFORM_EXPORT ImageDecoder {
     57     WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
     58 public:
     59     static const size_t noDecodedImageByteLimit = blink::Platform::noDecodedImageByteLimit;
     60 
     61     ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption, size_t maxDecodedBytes)
     62         : m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
     63         , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored)
     64         , m_maxDecodedBytes(maxDecodedBytes)
     65         , m_sizeAvailable(false)
     66         , m_isAllDataReceived(false)
     67         , m_failed(false) { }
     68 
     69     virtual ~ImageDecoder() { }
     70 
     71     // Returns a caller-owned decoder of the appropriate type.  Returns 0 if
     72     // we can't sniff a supported type from the provided data (possibly
     73     // because there isn't enough data yet).
     74     // Sets m_maxDecodedBytes to Platform::maxImageDecodedBytes().
     75     static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
     76 
     77     // Returns a decoder with custom maxDecodedSize.
     78     static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption, size_t maxDecodedSize);
     79 
     80     virtual String filenameExtension() const = 0;
     81 
     82     bool isAllDataReceived() const { return m_isAllDataReceived; }
     83 
     84     virtual void setData(SharedBuffer* data, bool allDataReceived)
     85     {
     86         if (m_failed)
     87             return;
     88         m_data = data;
     89         m_isAllDataReceived = allDataReceived;
     90     }
     91 
     92     // Lazily-decodes enough of the image to get the size (if possible).
     93     // FIXME: Right now that has to be done by each subclass; factor the
     94     // decode call out and use it here.
     95     virtual bool isSizeAvailable()
     96     {
     97         return !m_failed && m_sizeAvailable;
     98     }
     99 
    100     virtual IntSize size() const { return m_size; }
    101 
    102     // Decoders which downsample images should override this method to
    103     // return the actual decoded size.
    104     virtual IntSize decodedSize() const { return size(); }
    105 
    106     // This will only differ from size() for ICO (where each frame is a
    107     // different icon) or other formats where different frames are different
    108     // sizes. This does NOT differ from size() for GIF or WebP, since
    109     // decoding GIF or WebP composites any smaller frames against previous
    110     // frames to create full-size frames.
    111     virtual IntSize frameSizeAtIndex(size_t) const
    112     {
    113         return size();
    114     }
    115 
    116     // Returns whether the size is legal (i.e. not going to result in
    117     // overflow elsewhere).  If not, marks decoding as failed.
    118     virtual bool setSize(unsigned width, unsigned height)
    119     {
    120         if (sizeCalculationMayOverflow(width, height))
    121             return setFailed();
    122         m_size = IntSize(width, height);
    123         m_sizeAvailable = true;
    124         return true;
    125     }
    126 
    127     // Lazily-decodes enough of the image to get the frame count (if
    128     // possible), without decoding the individual frames.
    129     // FIXME: Right now that has to be done by each subclass; factor the
    130     // decode call out and use it here.
    131     virtual size_t frameCount() { return 1; }
    132 
    133     virtual int repetitionCount() const { return cAnimationNone; }
    134 
    135     // Decodes as much of the requested frame as possible, and returns an
    136     // ImageDecoder-owned pointer.
    137     virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
    138 
    139     // Make the best effort guess to check if the requested frame has alpha channel.
    140     virtual bool frameHasAlphaAtIndex(size_t) const;
    141 
    142     // Whether or not the frame is fully received.
    143     virtual bool frameIsCompleteAtIndex(size_t) const;
    144 
    145     // Duration for displaying a frame in seconds. This method is used by animated images only.
    146     virtual float frameDurationAtIndex(size_t) const { return 0; }
    147 
    148     // Number of bytes in the decoded frame requested. Return 0 if not yet decoded.
    149     virtual unsigned frameBytesAtIndex(size_t) const;
    150 
    151     void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
    152     bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
    153 
    154     ImageOrientation orientation() const { return m_orientation; }
    155 
    156     enum { iccColorProfileHeaderLength = 128 };
    157 
    158     static bool rgbColorProfile(const char* profileData, unsigned profileLength)
    159     {
    160         ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength);
    161 
    162         return !memcmp(&profileData[16], "RGB ", 4);
    163     }
    164 
    165     static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength)
    166     {
    167         ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength);
    168 
    169         return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[12], "scnr", 4);
    170     }
    171 
    172 #if USE(QCMSLIB)
    173     static qcms_profile* qcmsOutputDeviceProfile()
    174     {
    175         static qcms_profile* outputDeviceProfile = 0;
    176 
    177         static bool qcmsInitialized = false;
    178         if (!qcmsInitialized) {
    179             qcmsInitialized = true;
    180             // FIXME: Add optional ICCv4 support.
    181 #if OS(MACOSX)
    182             RetainPtr<CGColorSpaceRef> monitorColorSpace(AdoptCF, CGDisplayCopyColorSpace(CGMainDisplayID()));
    183             CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpace.get()));
    184             if (iccProfile) {
    185                 size_t length = CFDataGetLength(iccProfile);
    186                 const unsigned char* systemProfile = CFDataGetBytePtr(iccProfile);
    187                 outputDeviceProfile = qcms_profile_from_memory(systemProfile, length);
    188             }
    189 #else
    190             // FIXME: add support for multiple monitors.
    191             ColorProfile profile;
    192             screenColorProfile(profile);
    193             if (!profile.isEmpty())
    194                 outputDeviceProfile = qcms_profile_from_memory(profile.data(), profile.size());
    195 #endif
    196             if (outputDeviceProfile && qcms_profile_is_bogus(outputDeviceProfile)) {
    197                 qcms_profile_release(outputDeviceProfile);
    198                 outputDeviceProfile = 0;
    199             }
    200             if (!outputDeviceProfile)
    201                 outputDeviceProfile = qcms_profile_sRGB();
    202             if (outputDeviceProfile)
    203                 qcms_profile_precache_output_transform(outputDeviceProfile);
    204         }
    205         return outputDeviceProfile;
    206     }
    207 #endif
    208 
    209     // Sets the "decode failure" flag.  For caller convenience (since so
    210     // many callers want to return false after calling this), returns false
    211     // to enable easy tailcalling.  Subclasses may override this to also
    212     // clean up any local data.
    213     virtual bool setFailed()
    214     {
    215         m_failed = true;
    216         return false;
    217     }
    218 
    219     bool failed() const { return m_failed; }
    220 
    221     // Clears decoded pixel data from all frames except the provided frame.
    222     // Callers may pass WTF::kNotFound to clear all frames.
    223     // Note: If |m_frameBufferCache| contains only one frame, it won't be cleared.
    224     // Returns the number of bytes of frame data actually cleared.
    225     virtual size_t clearCacheExceptFrame(size_t);
    226 
    227     // If the image has a cursor hot-spot, stores it in the argument
    228     // and returns true. Otherwise returns false.
    229     virtual bool hotSpot(IntPoint&) const { return false; }
    230 
    231     virtual void setMemoryAllocator(SkBitmap::Allocator* allocator)
    232     {
    233         // FIXME: this doesn't work for images with multiple frames.
    234         if (m_frameBufferCache.isEmpty()) {
    235             m_frameBufferCache.resize(1);
    236             m_frameBufferCache[0].setRequiredPreviousFrameIndex(
    237                 findRequiredPreviousFrame(0, false));
    238         }
    239         m_frameBufferCache[0].setMemoryAllocator(allocator);
    240     }
    241 
    242 protected:
    243     // Calculates the most recent frame whose image data may be needed in
    244     // order to decode frame |frameIndex|, based on frame disposal methods
    245     // and |frameRectIsOpaque|, where |frameRectIsOpaque| signifies whether
    246     // the rectangle of frame at |frameIndex| is known to be opaque.
    247     // If no previous frame's data is required, returns WTF::kNotFound.
    248     //
    249     // This function requires that the previous frame's
    250     // |m_requiredPreviousFrameIndex| member has been set correctly. The
    251     // easiest way to ensure this is for subclasses to call this method and
    252     // store the result on the frame via setRequiredPreviousFrameIndex()
    253     // as soon as the frame has been created and parsed sufficiently to
    254     // determine the disposal method; assuming this happens for all frames
    255     // in order, the required invariant will hold.
    256     //
    257     // Image formats which do not use more than one frame do not need to
    258     // worry about this; see comments on
    259     // ImageFrame::m_requiredPreviousFrameIndex.
    260     size_t findRequiredPreviousFrame(size_t frameIndex, bool frameRectIsOpaque);
    261 
    262     virtual void clearFrameBuffer(size_t frameIndex);
    263 
    264     RefPtr<SharedBuffer> m_data; // The encoded data.
    265     Vector<ImageFrame, 1> m_frameBufferCache;
    266     bool m_premultiplyAlpha;
    267     bool m_ignoreGammaAndColorProfile;
    268     ImageOrientation m_orientation;
    269 
    270     // The maximum amount of memory a decoded image should require. Ideally,
    271     // image decoders should downsample large images to fit under this limit
    272     // (and then return the downsampled size from decodedSize()). Ignoring
    273     // this limit can cause excessive memory use or even crashes on low-
    274     // memory devices.
    275     size_t m_maxDecodedBytes;
    276 
    277 private:
    278     // Some code paths compute the size of the image as "width * height * 4"
    279     // and return it as a (signed) int.  Avoid overflow.
    280     static bool sizeCalculationMayOverflow(unsigned width, unsigned height)
    281     {
    282         unsigned long long total_size = static_cast<unsigned long long>(width)
    283                                       * static_cast<unsigned long long>(height);
    284         return total_size > ((1 << 29) - 1);
    285     }
    286 
    287     IntSize m_size;
    288     bool m_sizeAvailable;
    289     bool m_isAllDataReceived;
    290     bool m_failed;
    291 };
    292 
    293 } // namespace WebCore
    294 
    295 #endif
    296