Home | History | Annotate | Download | only in image-decoders
      1 /*
      2  * Copyright (C) 2008-2009 Torch Mobile, Inc.
      3  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
      4  *
      5  *  This library is free software; you can redistribute it and/or
      6  *  modify it under the terms of the GNU Library General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2 of the License, or (at your option) any later version.
      9  *
     10  *  This library is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Library General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Library General Public License
     16  *  along with this library; see the file COPYING.LIB.  If not, write to
     17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  *  Boston, MA 02110-1301, USA.
     19  *
     20  */
     21 
     22 #include "config.h"
     23 
     24 #include "ImageDecoder.h"
     25 
     26 #include <algorithm>
     27 #include <cmath>
     28 
     29 #include "BMPImageDecoder.h"
     30 #include "GIFImageDecoder.h"
     31 #include "ICOImageDecoder.h"
     32 #include "JPEGImageDecoder.h"
     33 #include "PNGImageDecoder.h"
     34 #include "WEBPImageDecoder.h"
     35 #include "SharedBuffer.h"
     36 
     37 using namespace std;
     38 
     39 namespace WebCore {
     40 
     41 namespace {
     42 
     43 unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
     44 {
     45     unsigned bytesExtracted = 0;
     46     const char* moreData;
     47     while (unsigned moreDataLength = sharedBuffer.getSomeData(moreData, offset)) {
     48         unsigned bytesToCopy = min(bufferLength - bytesExtracted, moreDataLength);
     49         memcpy(buffer + bytesExtracted, moreData, bytesToCopy);
     50         bytesExtracted += bytesToCopy;
     51         if (bytesExtracted == bufferLength)
     52             break;
     53         offset += bytesToCopy;
     54     }
     55     return bytesExtracted;
     56 }
     57 
     58 bool matchesGIFSignature(char* contents)
     59 {
     60     return !memcmp(contents, "GIF8", 4);
     61 }
     62 
     63 bool matchesPNGSignature(char* contents)
     64 {
     65     return !memcmp(contents, "\x89\x50\x4E\x47", 4);
     66 }
     67 
     68 bool matchesJPEGSignature(char* contents)
     69 {
     70     return !memcmp(contents, "\xFF\xD8\xFF", 3);
     71 }
     72 
     73 #if USE(WEBP)
     74 bool matchesWebPSignature(char* contents)
     75 {
     76     return !memcmp(contents, "RIFF", 4) && !memcmp(contents + 8, "WEBPVP", 6);
     77 }
     78 #endif
     79 
     80 bool matchesBMPSignature(char* contents)
     81 {
     82     return !memcmp(contents, "BM", 2);
     83 }
     84 
     85 bool matchesICOSignature(char* contents)
     86 {
     87     return !memcmp(contents, "\x00\x00\x01\x00", 4);
     88 }
     89 
     90 bool matchesCURSignature(char* contents)
     91 {
     92     return !memcmp(contents, "\x00\x00\x02\x00", 4);
     93 }
     94 
     95 }
     96 
     97 #if !OS(ANDROID)
     98 // This method requires BMPImageDecoder, PNGImageDecoder, ICOImageDecoder and
     99 // JPEGDecoder, which aren't used on Android, and which don't all compile.
    100 // TODO: Find a better fix.
    101 ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
    102 {
    103     static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
    104     char contents[lengthOfLongestSignature];
    105     unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
    106     if (length < lengthOfLongestSignature)
    107         return 0;
    108 
    109     if (matchesGIFSignature(contents))
    110         return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption);
    111 
    112     if (matchesPNGSignature(contents))
    113         return new PNGImageDecoder(alphaOption, gammaAndColorProfileOption);
    114 
    115     if (matchesJPEGSignature(contents))
    116         return new JPEGImageDecoder(alphaOption, gammaAndColorProfileOption);
    117 
    118 #if USE(WEBP)
    119     if (matchesWebPSignature(contents))
    120         return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption);
    121 #endif
    122 
    123     if (matchesBMPSignature(contents))
    124         return new BMPImageDecoder(alphaOption, gammaAndColorProfileOption);
    125 
    126     if (matchesICOSignature(contents) || matchesCURSignature(contents))
    127         return new ICOImageDecoder(alphaOption, gammaAndColorProfileOption);
    128 
    129     return 0;
    130 }
    131 #endif // !OS(ANDROID)
    132 
    133 #if !USE(SKIA)
    134 
    135 ImageFrame::ImageFrame()
    136     : m_hasAlpha(false)
    137     , m_status(FrameEmpty)
    138     , m_duration(0)
    139     , m_disposalMethod(DisposeNotSpecified)
    140     , m_premultiplyAlpha(true)
    141 {
    142 }
    143 
    144 ImageFrame& ImageFrame::operator=(const ImageFrame& other)
    145 {
    146     if (this == &other)
    147         return *this;
    148 
    149     copyReferenceToBitmapData(other);
    150     setOriginalFrameRect(other.originalFrameRect());
    151     setStatus(other.status());
    152     setDuration(other.duration());
    153     setDisposalMethod(other.disposalMethod());
    154     setPremultiplyAlpha(other.premultiplyAlpha());
    155     return *this;
    156 }
    157 
    158 void ImageFrame::clearPixelData()
    159 {
    160     m_backingStore.clear();
    161     m_bytes = 0;
    162     m_status = FrameEmpty;
    163     // NOTE: Do not reset other members here; clearFrameBufferCache() calls this
    164     // to free the bitmap data, but other functions like initFrameBuffer() and
    165     // frameComplete() may still need to read other metadata out of this frame
    166     // later.
    167 }
    168 
    169 void ImageFrame::zeroFillPixelData()
    170 {
    171     memset(m_bytes, 0, m_size.width() * m_size.height() * sizeof(PixelData));
    172     m_hasAlpha = true;
    173 }
    174 
    175 #if !USE(CG)
    176 
    177 void ImageFrame::copyReferenceToBitmapData(const ImageFrame& other)
    178 {
    179     ASSERT(this != &other);
    180     copyBitmapData(other);
    181 }
    182 
    183 bool ImageFrame::copyBitmapData(const ImageFrame& other)
    184 {
    185     if (this == &other)
    186         return true;
    187 
    188     m_backingStore = other.m_backingStore;
    189     m_bytes = m_backingStore.data();
    190     m_size = other.m_size;
    191     setHasAlpha(other.m_hasAlpha);
    192     return true;
    193 }
    194 
    195 bool ImageFrame::setSize(int newWidth, int newHeight)
    196 {
    197     // NOTE: This has no way to check for allocation failure if the requested
    198     // size was too big...
    199     m_backingStore.resize(newWidth * newHeight);
    200     m_bytes = m_backingStore.data();
    201     m_size = IntSize(newWidth, newHeight);
    202 
    203     zeroFillPixelData();
    204 
    205     return true;
    206 }
    207 
    208 #endif
    209 
    210 bool ImageFrame::hasAlpha() const
    211 {
    212     return m_hasAlpha;
    213 }
    214 
    215 void ImageFrame::setHasAlpha(bool alpha)
    216 {
    217     m_hasAlpha = alpha;
    218 }
    219 
    220 void ImageFrame::setColorProfile(const ColorProfile& colorProfile)
    221 {
    222     m_colorProfile = colorProfile;
    223 }
    224 
    225 void ImageFrame::setStatus(FrameStatus status)
    226 {
    227     m_status = status;
    228 }
    229 
    230 int ImageFrame::width() const
    231 {
    232     return m_size.width();
    233 }
    234 
    235 int ImageFrame::height() const
    236 {
    237     return m_size.height();
    238 }
    239 
    240 #endif
    241 
    242 namespace {
    243 
    244 enum MatchType {
    245     Exact,
    246     UpperBound,
    247     LowerBound
    248 };
    249 
    250 inline void fillScaledValues(Vector<int>& scaledValues, double scaleRate, int length)
    251 {
    252     double inflateRate = 1. / scaleRate;
    253     scaledValues.reserveCapacity(static_cast<int>(length * scaleRate + 0.5));
    254     for (int scaledIndex = 0; ; ++scaledIndex) {
    255         int index = static_cast<int>(scaledIndex * inflateRate + 0.5);
    256         if (index >= length)
    257             break;
    258         scaledValues.append(index);
    259     }
    260 }
    261 
    262 template <MatchType type> int getScaledValue(const Vector<int>& scaledValues, int valueToMatch, int searchStart)
    263 {
    264     if (scaledValues.isEmpty())
    265         return valueToMatch;
    266 
    267     const int* dataStart = scaledValues.data();
    268     const int* dataEnd = dataStart + scaledValues.size();
    269     const int* matched = std::lower_bound(dataStart + searchStart, dataEnd, valueToMatch);
    270     switch (type) {
    271     case Exact:
    272         return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : -1;
    273     case LowerBound:
    274         return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : matched - dataStart - 1;
    275     case UpperBound:
    276     default:
    277         return matched != dataEnd ? matched - dataStart : -1;
    278     }
    279 }
    280 
    281 }
    282 
    283 void ImageDecoder::prepareScaleDataIfNecessary()
    284 {
    285     m_scaled = false;
    286     m_scaledColumns.clear();
    287     m_scaledRows.clear();
    288 
    289     int width = size().width();
    290     int height = size().height();
    291     int numPixels = height * width;
    292     if (m_maxNumPixels <= 0 || numPixels <= m_maxNumPixels)
    293         return;
    294 
    295     m_scaled = true;
    296     double scale = sqrt(m_maxNumPixels / (double)numPixels);
    297     fillScaledValues(m_scaledColumns, scale, width);
    298     fillScaledValues(m_scaledRows, scale, height);
    299 }
    300 
    301 int ImageDecoder::upperBoundScaledX(int origX, int searchStart)
    302 {
    303     return getScaledValue<UpperBound>(m_scaledColumns, origX, searchStart);
    304 }
    305 
    306 int ImageDecoder::lowerBoundScaledX(int origX, int searchStart)
    307 {
    308     return getScaledValue<LowerBound>(m_scaledColumns, origX, searchStart);
    309 }
    310 
    311 int ImageDecoder::upperBoundScaledY(int origY, int searchStart)
    312 {
    313     return getScaledValue<UpperBound>(m_scaledRows, origY, searchStart);
    314 }
    315 
    316 int ImageDecoder::lowerBoundScaledY(int origY, int searchStart)
    317 {
    318     return getScaledValue<LowerBound>(m_scaledRows, origY, searchStart);
    319 }
    320 
    321 int ImageDecoder::scaledY(int origY, int searchStart)
    322 {
    323     return getScaledValue<Exact>(m_scaledRows, origY, searchStart);
    324 }
    325 
    326 }
    327