Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright 2007, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #define LOG_TAG "ImageSourceAndroid"
     27 
     28 #include "config.h"
     29 
     30 #include "AndroidLog.h"
     31 #include "BitmapAllocatorAndroid.h"
     32 #include "ImageSource.h"
     33 #include "IntSize.h"
     34 #include "NotImplemented.h"
     35 #include "SharedBuffer.h"
     36 #include "PlatformString.h"
     37 
     38 #include "SkBitmapRef.h"
     39 #include "SkImageDecoder.h"
     40 #include "SkImageRef.h"
     41 #include "SkStream.h"
     42 #include "SkTemplates.h"
     43 
     44 #ifdef ANDROID_ANIMATED_GIF
     45     #include "EmojiFont.h"
     46     #include "GIFImageDecoder.h"
     47 
     48     using namespace android;
     49 #endif
     50 
     51 // TODO: We should make use of some of the common code in platform/graphics/ImageSource.cpp.
     52 
     53 //#define TRACE_SUBSAMPLE_BITMAPS
     54 
     55 
     56 // flag to tell us when we're on a large-ram device (e.g. >= 256M)
     57 #ifdef ANDROID_LARGE_MEMORY_DEVICE
     58     // see dox for computeMaxBitmapSizeForCache()
     59     #define MAX_SIZE_BEFORE_SUBSAMPLE   (32*1024*1024)
     60 
     61     // preserve quality for 24/32bit src
     62     static const SkBitmap::Config gPrefConfigTable[6] = {
     63         SkBitmap::kIndex8_Config,       // src: index, opaque
     64         SkBitmap::kIndex8_Config,       // src: index, alpha
     65         SkBitmap::kRGB_565_Config,      // src: 16bit, opaque
     66         SkBitmap::kARGB_8888_Config,    // src: 16bit, alpha  (promote to 32bit)
     67         SkBitmap::kARGB_8888_Config,    // src: 32bit, opaque
     68         SkBitmap::kARGB_8888_Config,    // src: 32bit, alpha
     69     };
     70 #else
     71     #define MAX_SIZE_BEFORE_SUBSAMPLE   (2*1024*1024)
     72 
     73     // tries to minimize memory usage (i.e. demote opaque 32bit -> 16bit)
     74     static const SkBitmap::Config gPrefConfigTable[6] = {
     75         SkBitmap::kIndex8_Config,       // src: index, opaque
     76         SkBitmap::kIndex8_Config,       // src: index, alpha
     77         SkBitmap::kRGB_565_Config,      // src: 16bit, opaque
     78         SkBitmap::kARGB_8888_Config,    // src: 16bit, alpha  (promote to 32bit)
     79         SkBitmap::kRGB_565_Config,      // src: 32bit, opaque (demote to 16bit)
     80         SkBitmap::kARGB_8888_Config,    // src: 32bit, alpha
     81     };
     82 #endif
     83 
     84 /*  Images larger than this should be subsampled. Using ashmem, the decoded
     85     pixels will be purged as needed, so this value can be pretty large. Making
     86     it too small hurts image quality (e.g. abc.com background). 2Meg works for
     87     the sites I've tested, but if we hit important sites that need more, we
     88     should try increasing it and see if it has negative impact on performance
     89     (i.e. we end up thrashing because we need to keep decoding images that have
     90     been purged.
     91 
     92     Perhaps this value should be some fraction of the available RAM...
     93 */
     94 size_t computeMaxBitmapSizeForCache() {
     95     return MAX_SIZE_BEFORE_SUBSAMPLE;
     96 }
     97 ///////////////////////////////////////////////////////////////////////////////
     98 
     99 class PrivateAndroidImageSourceRec : public SkBitmapRef {
    100 public:
    101     PrivateAndroidImageSourceRec(const SkBitmap& bm, int origWidth,
    102                                  int origHeight, int sampleSize)
    103             : SkBitmapRef(bm), fSampleSize(sampleSize), fAllDataReceived(false) {
    104         this->setOrigSize(origWidth, origHeight);
    105     }
    106 
    107     int  fSampleSize;
    108     bool fAllDataReceived;
    109 };
    110 
    111 namespace WebCore {
    112 
    113 ImageSource::ImageSource(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
    114     : m_alphaOption(alphaOption)
    115     , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
    116 {
    117     m_decoder.m_image = NULL;
    118 #ifdef ANDROID_ANIMATED_GIF
    119     m_decoder.m_gifDecoder = 0;
    120 #endif
    121 }
    122 
    123 ImageSource::~ImageSource() {
    124     delete m_decoder.m_image;
    125 #ifdef ANDROID_ANIMATED_GIF
    126     delete m_decoder.m_gifDecoder;
    127 #endif
    128 }
    129 
    130 bool ImageSource::initialized() const {
    131     return
    132 #ifdef ANDROID_ANIMATED_GIF
    133         m_decoder.m_gifDecoder ||
    134 #endif
    135         m_decoder.m_image != NULL;
    136 }
    137 
    138 static int computeSampleSize(const SkBitmap& bitmap) {
    139     const size_t maxSize = computeMaxBitmapSizeForCache();
    140     size_t size = bitmap.getSize();
    141     int sampleSize = 1;
    142 
    143     while (size > maxSize) {
    144         sampleSize <<= 1;
    145         size >>= 2;
    146     }
    147 
    148 #ifdef TRACE_SUBSAMPLE_BITMAPS
    149     if (sampleSize > 1) {
    150         ALOGD("------- bitmap [%d %d] config=%d origSize=%d predictSize=%d sampleSize=%d\n",
    151                  bitmap.width(), bitmap.height(), bitmap.config(),
    152                  bitmap.getSize(), size, sampleSize);
    153     }
    154 #endif
    155     return sampleSize;
    156 }
    157 
    158 void ImageSource::clearURL()
    159 {
    160     m_decoder.m_url.reset();
    161 }
    162 
    163 void ImageSource::setURL(const String& url)
    164 {
    165     m_decoder.m_url.setUTF16(url.characters(), url.length());
    166 }
    167 
    168 #ifdef ANDROID_ANIMATED_GIF
    169 // we only animate small GIFs for now, to save memory
    170 // also, we only support this in Japan, hence the Emoji check
    171 static bool should_use_animated_gif(int width, int height) {
    172 #ifdef ANDROID_LARGE_MEMORY_DEVICE
    173     return true;
    174 #else
    175     return EmojiFont::IsAvailable() &&
    176            width <= 32 && height <= 32;
    177 #endif
    178 }
    179 #endif
    180 
    181 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
    182 {
    183 #ifdef ANDROID_ANIMATED_GIF
    184     // This is only necessary if we allow ourselves to partially decode GIF
    185     bool disabledAnimatedGif = false;
    186     if (m_decoder.m_gifDecoder
    187             && !m_decoder.m_gifDecoder->failed()) {
    188         m_decoder.m_gifDecoder->setData(data, allDataReceived);
    189         if (!allDataReceived || m_decoder.m_gifDecoder->frameCount() != 1)
    190             return;
    191         disabledAnimatedGif = true;
    192         delete m_decoder.m_gifDecoder;
    193         m_decoder.m_gifDecoder = 0;
    194     }
    195 #endif
    196     if (NULL == m_decoder.m_image
    197 #ifdef ANDROID_ANIMATED_GIF
    198           && !m_decoder.m_gifDecoder
    199 #endif
    200                                             ) {
    201         SkBitmap tmp;
    202 
    203         SkMemoryStream stream(data->data(), data->size(), false);
    204         SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
    205         if (!codec)
    206             return;
    207 
    208         SkAutoTDelete<SkImageDecoder> ad(codec);
    209         codec->setPrefConfigTable(gPrefConfigTable);
    210         if (!codec->decode(&stream, &tmp, SkImageDecoder::kDecodeBounds_Mode))
    211             return;
    212 
    213         int origW = tmp.width();
    214         int origH = tmp.height();
    215 
    216 #ifdef ANDROID_ANIMATED_GIF
    217         // First, check to see if this is an animated GIF
    218         const char* contents = data->data();
    219         if (data->size() > 3 && strncmp(contents, "GIF8", 4) == 0
    220                 && should_use_animated_gif(origW, origH)
    221                 && !disabledAnimatedGif) {
    222             // This means we are looking at a GIF, so create special
    223             // GIF Decoder
    224             // Need to wait for all data received if we are assigning an
    225             // allocator (which we are not at the moment).
    226             if (!m_decoder.m_gifDecoder /*&& allDataReceived*/)
    227                 m_decoder.m_gifDecoder = new GIFImageDecoder(m_alphaOption, m_gammaAndColorProfileOption);
    228             int frameCount = 0;
    229             if (!m_decoder.m_gifDecoder->failed()) {
    230                 m_decoder.m_gifDecoder->setData(data, allDataReceived);
    231                 if (!allDataReceived)
    232                     return;
    233                 frameCount = m_decoder.m_gifDecoder->frameCount();
    234             }
    235             if (frameCount != 1)
    236                 return;
    237             delete m_decoder.m_gifDecoder;
    238             m_decoder.m_gifDecoder = 0;
    239         }
    240 #endif
    241 
    242         int sampleSize = computeSampleSize(tmp);
    243         if (sampleSize > 1) {
    244             codec->setSampleSize(sampleSize);
    245             stream.rewind();
    246             if (!codec->decode(&stream, &tmp,
    247                                SkImageDecoder::kDecodeBounds_Mode)) {
    248                 return;
    249             }
    250         }
    251 
    252         m_decoder.m_image = new PrivateAndroidImageSourceRec(tmp, origW, origH,
    253                                                      sampleSize);
    254 
    255 //        ALOGD("----- started: [%d %d] %s\n", origW, origH, m_decoder.m_url.c_str());
    256     }
    257 
    258     PrivateAndroidImageSourceRec* decoder = m_decoder.m_image;
    259     if (allDataReceived && decoder && !decoder->fAllDataReceived) {
    260         decoder->fAllDataReceived = true;
    261 
    262         SkBitmap* bm = &decoder->bitmap();
    263 
    264         BitmapAllocatorAndroid alloc(data, decoder->fSampleSize);
    265         if (!alloc.allocPixelRef(bm, NULL)) {
    266             return;
    267         }
    268         SkPixelRef* ref = bm->pixelRef();
    269 
    270         // we promise to never change the pixels (makes picture recording fast)
    271         ref->setImmutable();
    272         // give it the URL if we have one
    273         ref->setURI(m_decoder.m_url);
    274     }
    275 }
    276 
    277 bool ImageSource::isSizeAvailable()
    278 {
    279     return
    280 #ifdef ANDROID_ANIMATED_GIF
    281             (m_decoder.m_gifDecoder
    282                     && m_decoder.m_gifDecoder->isSizeAvailable()) ||
    283 #endif
    284             m_decoder.m_image != NULL;
    285 }
    286 
    287 IntSize ImageSource::size() const
    288 {
    289 #ifdef ANDROID_ANIMATED_GIF
    290     if (m_decoder.m_gifDecoder)
    291         return m_decoder.m_gifDecoder->size();
    292 #endif
    293     if (m_decoder.m_image) {
    294         return IntSize(m_decoder.m_image->origWidth(), m_decoder.m_image->origHeight());
    295     }
    296     return IntSize(0, 0);
    297 }
    298 
    299 int ImageSource::repetitionCount()
    300 {
    301 #ifdef ANDROID_ANIMATED_GIF
    302     if (m_decoder.m_gifDecoder)
    303         return m_decoder.m_gifDecoder->repetitionCount();
    304     if (!m_decoder.m_image) return 0;
    305 #endif
    306     return 1;
    307     // A property with value 0 means loop forever.
    308 }
    309 
    310 size_t ImageSource::frameCount() const
    311 {
    312 #ifdef ANDROID_ANIMATED_GIF
    313     if (m_decoder.m_gifDecoder) {
    314         return m_decoder.m_gifDecoder->failed() ? 0
    315                 : m_decoder.m_gifDecoder->frameCount();
    316     }
    317 #endif
    318     // i.e. 0 frames if we're not decoded, or 1 frame if we are
    319     return m_decoder.m_image != NULL;
    320 }
    321 
    322 SkBitmapRef* ImageSource::createFrameAtIndex(size_t index)
    323 {
    324 #ifdef ANDROID_ANIMATED_GIF
    325     if (m_decoder.m_gifDecoder) {
    326         ImageFrame* buffer =
    327                 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
    328         if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
    329             return 0;
    330         SkBitmap& bitmap = buffer->bitmap();
    331         SkPixelRef* pixelRef = bitmap.pixelRef();
    332         if (pixelRef)
    333             pixelRef->setURI(m_decoder.m_url);
    334         return new SkBitmapRef(bitmap);
    335     }
    336 #else
    337     SkASSERT(index == 0);
    338 #endif
    339     SkASSERT(m_decoder.m_image != NULL);
    340     m_decoder.m_image->ref();
    341     return m_decoder.m_image;
    342 }
    343 
    344 float ImageSource::frameDurationAtIndex(size_t index)
    345 {
    346     float duration = 0;
    347 #ifdef ANDROID_ANIMATED_GIF
    348     if (m_decoder.m_gifDecoder) {
    349         ImageFrame* buffer
    350                 = m_decoder.m_gifDecoder->frameBufferAtIndex(index);
    351         if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
    352             return 0;
    353         duration = buffer->duration() / 1000.0f;
    354     }
    355 #else
    356     SkASSERT(index == 0);
    357 #endif
    358 
    359     // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
    360     // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
    361     // a duration of <= 10 ms. See gfxImageFrame::GetTimeout in Gecko or Radar 4051389 for more.
    362     if (duration <= 0.010f)
    363         duration = 0.100f;
    364     return duration;
    365 }
    366 
    367 bool ImageSource::frameHasAlphaAtIndex(size_t index)
    368 {
    369 #ifdef ANDROID_ANIMATED_GIF
    370     if (m_decoder.m_gifDecoder) {
    371         ImageFrame* buffer =
    372                 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
    373         if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
    374             return false;
    375 
    376         return buffer->hasAlpha();
    377     }
    378 #else
    379     SkASSERT(0 == index);
    380 #endif
    381 
    382     if (NULL == m_decoder.m_image)
    383         return true;    // if we're not sure, assume the worse-case
    384     const PrivateAndroidImageSourceRec& decoder = *m_decoder.m_image;
    385     // if we're 16bit, we know even without all the data available
    386     if (decoder.bitmap().getConfig() == SkBitmap::kRGB_565_Config)
    387         return false;
    388 
    389     if (!decoder.fAllDataReceived)
    390         return true;    // if we're not sure, assume the worse-case
    391 
    392     return !decoder.bitmap().isOpaque();
    393 }
    394 
    395 bool ImageSource::frameIsCompleteAtIndex(size_t index)
    396 {
    397 #ifdef ANDROID_ANIMATED_GIF
    398     if (m_decoder.m_gifDecoder) {
    399         ImageFrame* buffer =
    400                 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
    401         return buffer && buffer->status() == ImageFrame::FrameComplete;
    402     }
    403 #else
    404     SkASSERT(0 == index);
    405 #endif
    406 	return m_decoder.m_image && m_decoder.m_image->fAllDataReceived;
    407 }
    408 
    409 void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
    410 {
    411 #ifdef ANDROID_ANIMATED_GIF
    412     if (!destroyAll) {
    413         if (m_decoder.m_gifDecoder)
    414             m_decoder.m_gifDecoder->clearFrameBufferCache(clearBeforeFrame);
    415         return;
    416     }
    417 
    418     delete m_decoder.m_gifDecoder;
    419     m_decoder.m_gifDecoder = 0;
    420     if (data)
    421         setData(data, allDataReceived);
    422 #endif
    423     // do nothing, since the cache is managed elsewhere
    424 }
    425 
    426 IntSize ImageSource::frameSizeAtIndex(size_t index) const
    427 {
    428     // for now, all (1) of our frames are the same size
    429     return this->size();
    430 }
    431 
    432 String ImageSource::filenameExtension() const
    433 {
    434     // FIXME: need to add virtual to our decoders to return "jpg/png/gif/..."
    435 #ifdef ANDROID_ANIMATED_GIF
    436     if (m_decoder.m_gifDecoder)
    437         return m_decoder.m_gifDecoder->filenameExtension();
    438 #endif
    439     return String();
    440 }
    441 
    442 bool ImageSource::getHotSpot(IntPoint&) const
    443 {
    444     return false;
    445 }
    446 
    447 size_t ImageSource::bytesDecodedToDetermineProperties() const
    448 {
    449     return 0;
    450 }
    451 
    452 }
    453