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 #include "config.h"
     27 #include "BitmapAllocatorAndroid.h"
     28 #include "ImageSource.h"
     29 #include "IntSize.h"
     30 #include "NotImplemented.h"
     31 #include "SharedBuffer.h"
     32 #include "PlatformString.h"
     33 
     34 #include "SkBitmapRef.h"
     35 #include "SkImageDecoder.h"
     36 #include "SkImageRef.h"
     37 #include "SkStream.h"
     38 #include "SkTemplates.h"
     39 
     40 #ifdef ANDROID_ANIMATED_GIF
     41     #include "EmojiFont.h"
     42     #include "GIFImageDecoder.h"
     43 
     44     using namespace android;
     45 #endif
     46 
     47 // TODO: We should make use of some of the common code in platform/graphics/ImageSource.cpp.
     48 
     49 SkPixelRef* SkCreateRLEPixelRef(const SkBitmap& src);
     50 
     51 //#define TRACE_SUBSAMPLE_BITMAPS
     52 //#define TRACE_RLE_BITMAPS
     53 
     54 
     55 // flag to tell us when we're on a large-ram device (e.g. >= 256M)
     56 #ifdef ANDROID_LARGE_MEMORY_DEVICE
     57     // don't use RLE for images smaller than this, since they incur a drawing cost
     58     // (and don't work as patterns yet) we only want to use RLE when we must
     59     #define MIN_RLE_ALLOC_SIZE          (8*1024*1024)
     60 
     61     // see dox for computeMaxBitmapSizeForCache()
     62     #define MAX_SIZE_BEFORE_SUBSAMPLE   (32*1024*1024)
     63 
     64     // preserve quality for 24/32bit src
     65     static const SkBitmap::Config gPrefConfigTable[6] = {
     66         SkBitmap::kIndex8_Config,       // src: index, opaque
     67         SkBitmap::kIndex8_Config,       // src: index, alpha
     68         SkBitmap::kRGB_565_Config,      // src: 16bit, opaque
     69         SkBitmap::kARGB_8888_Config,    // src: 16bit, alpha  (promote to 32bit)
     70         SkBitmap::kARGB_8888_Config,    // src: 32bit, opaque
     71         SkBitmap::kARGB_8888_Config,    // src: 32bit, alpha
     72     };
     73 #else
     74     #define MIN_RLE_ALLOC_SIZE          (2*1024*1024)
     75     #define MAX_SIZE_BEFORE_SUBSAMPLE   (2*1024*1024)
     76 
     77     // tries to minimize memory usage (i.e. demote opaque 32bit -> 16bit)
     78     static const SkBitmap::Config gPrefConfigTable[6] = {
     79         SkBitmap::kIndex8_Config,       // src: index, opaque
     80         SkBitmap::kIndex8_Config,       // src: index, alpha
     81         SkBitmap::kRGB_565_Config,      // src: 16bit, opaque
     82         SkBitmap::kARGB_8888_Config,    // src: 16bit, alpha  (promote to 32bit)
     83         SkBitmap::kRGB_565_Config,      // src: 32bit, opaque (demote to 16bit)
     84         SkBitmap::kARGB_8888_Config,    // src: 32bit, alpha
     85     };
     86 #endif
     87 
     88 /*  Images larger than this should be subsampled. Using ashmem, the decoded
     89     pixels will be purged as needed, so this value can be pretty large. Making
     90     it too small hurts image quality (e.g. abc.com background). 2Meg works for
     91     the sites I've tested, but if we hit important sites that need more, we
     92     should try increasing it and see if it has negative impact on performance
     93     (i.e. we end up thrashing because we need to keep decoding images that have
     94     been purged.
     95 
     96     Perhaps this value should be some fraction of the available RAM...
     97 */
     98 size_t computeMaxBitmapSizeForCache() {
     99     return MAX_SIZE_BEFORE_SUBSAMPLE;
    100 }
    101 
    102 /* 8bit images larger than this should be recompressed in RLE, to reduce
    103     on the imageref cache.
    104 
    105     Downside: performance, since we have to decode/encode
    106     and then rle-decode when we draw.
    107 */
    108 static bool shouldReencodeAsRLE(const SkBitmap& bm) {
    109     const SkBitmap::Config c = bm.config();
    110     return (SkBitmap::kIndex8_Config == c || SkBitmap::kA8_Config == c)
    111             &&
    112             bm.width() >= 64 // narrower than this won't compress well in RLE
    113             &&
    114             bm.getSize() > MIN_RLE_ALLOC_SIZE;
    115 }
    116 
    117 ///////////////////////////////////////////////////////////////////////////////
    118 
    119 class PrivateAndroidImageSourceRec : public SkBitmapRef {
    120 public:
    121     PrivateAndroidImageSourceRec(const SkBitmap& bm, int origWidth,
    122                                  int origHeight, int sampleSize)
    123             : SkBitmapRef(bm), fSampleSize(sampleSize), fAllDataReceived(false) {
    124         this->setOrigSize(origWidth, origHeight);
    125     }
    126 
    127     int  fSampleSize;
    128     bool fAllDataReceived;
    129 };
    130 
    131 namespace WebCore {
    132 
    133 ImageSource::ImageSource(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
    134     : m_alphaOption(alphaOption)
    135     , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
    136 {
    137     m_decoder.m_image = NULL;
    138 #ifdef ANDROID_ANIMATED_GIF
    139     m_decoder.m_gifDecoder = 0;
    140 #endif
    141 }
    142 
    143 ImageSource::~ImageSource() {
    144     delete m_decoder.m_image;
    145 #ifdef ANDROID_ANIMATED_GIF
    146     delete m_decoder.m_gifDecoder;
    147 #endif
    148 }
    149 
    150 bool ImageSource::initialized() const {
    151     return
    152 #ifdef ANDROID_ANIMATED_GIF
    153         m_decoder.m_gifDecoder ||
    154 #endif
    155         m_decoder.m_image != NULL;
    156 }
    157 
    158 static int computeSampleSize(const SkBitmap& bitmap) {
    159     const size_t maxSize = computeMaxBitmapSizeForCache();
    160     size_t size = bitmap.getSize();
    161     int sampleSize = 1;
    162 
    163     while (size > maxSize) {
    164         sampleSize <<= 1;
    165         size >>= 2;
    166     }
    167 
    168 #ifdef TRACE_SUBSAMPLE_BITMAPS
    169     if (sampleSize > 1) {
    170         SkDebugf("------- bitmap [%d %d] config=%d origSize=%d predictSize=%d sampleSize=%d\n",
    171                  bitmap.width(), bitmap.height(), bitmap.config(),
    172                  bitmap.getSize(), size, sampleSize);
    173     }
    174 #endif
    175     return sampleSize;
    176 }
    177 
    178 static SkPixelRef* convertToRLE(SkBitmap* bm, const void* data, size_t len) {
    179     if (!shouldReencodeAsRLE(*bm)) {
    180         return NULL;
    181     }
    182 
    183     SkBitmap tmp;
    184 
    185     if (!SkImageDecoder::DecodeMemory(data, len, &tmp) || !tmp.getPixels()) {
    186         return NULL;
    187     }
    188 
    189     SkPixelRef* ref = SkCreateRLEPixelRef(tmp);
    190     if (NULL == ref) {
    191         return NULL;
    192     }
    193 
    194 #ifdef TRACE_RLE_BITMAPS
    195     SkDebugf("---- reencode bitmap as RLE: [%d %d] encodeSize=%d\n",
    196              tmp.width(), tmp.height(), len);
    197 #endif
    198 
    199     bm->setConfig(SkBitmap::kRLE_Index8_Config, tmp.width(), tmp.height());
    200     return ref;
    201 }
    202 
    203 void ImageSource::clearURL()
    204 {
    205     m_decoder.m_url.reset();
    206 }
    207 
    208 void ImageSource::setURL(const String& url)
    209 {
    210     m_decoder.m_url.setUTF16(url.characters(), url.length());
    211 }
    212 
    213 #ifdef ANDROID_ANIMATED_GIF
    214 // we only animate small GIFs for now, to save memory
    215 // also, we only support this in Japan, hence the Emoji check
    216 static bool should_use_animated_gif(int width, int height) {
    217 #ifdef ANDROID_LARGE_MEMORY_DEVICE
    218     return true;
    219 #else
    220     return EmojiFont::IsAvailable() &&
    221            width <= 32 && height <= 32;
    222 #endif
    223 }
    224 #endif
    225 
    226 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
    227 {
    228 #ifdef ANDROID_ANIMATED_GIF
    229     // This is only necessary if we allow ourselves to partially decode GIF
    230     bool disabledAnimatedGif = false;
    231     if (m_decoder.m_gifDecoder
    232             && !m_decoder.m_gifDecoder->failed()) {
    233         m_decoder.m_gifDecoder->setData(data, allDataReceived);
    234         if (!allDataReceived || m_decoder.m_gifDecoder->frameCount() != 1)
    235             return;
    236         disabledAnimatedGif = true;
    237         delete m_decoder.m_gifDecoder;
    238         m_decoder.m_gifDecoder = 0;
    239     }
    240 #endif
    241     if (NULL == m_decoder.m_image
    242 #ifdef ANDROID_ANIMATED_GIF
    243           && !m_decoder.m_gifDecoder
    244 #endif
    245                                             ) {
    246         SkBitmap tmp;
    247 
    248         SkMemoryStream stream(data->data(), data->size(), false);
    249         SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
    250         if (!codec)
    251             return;
    252 
    253         SkAutoTDelete<SkImageDecoder> ad(codec);
    254         codec->setPrefConfigTable(gPrefConfigTable);
    255         if (!codec->decode(&stream, &tmp, SkImageDecoder::kDecodeBounds_Mode))
    256             return;
    257 
    258         int origW = tmp.width();
    259         int origH = tmp.height();
    260 
    261 #ifdef ANDROID_ANIMATED_GIF
    262         // First, check to see if this is an animated GIF
    263         const char* contents = data->data();
    264         if (data->size() > 3 && strncmp(contents, "GIF8", 4) == 0
    265                 && should_use_animated_gif(origW, origH)
    266                 && !disabledAnimatedGif) {
    267             // This means we are looking at a GIF, so create special
    268             // GIF Decoder
    269             // Need to wait for all data received if we are assigning an
    270             // allocator (which we are not at the moment).
    271             if (!m_decoder.m_gifDecoder /*&& allDataReceived*/)
    272                 m_decoder.m_gifDecoder = new GIFImageDecoder(m_alphaOption, m_gammaAndColorProfileOption);
    273             int frameCount = 0;
    274             if (!m_decoder.m_gifDecoder->failed()) {
    275                 m_decoder.m_gifDecoder->setData(data, allDataReceived);
    276                 if (!allDataReceived)
    277                     return;
    278                 frameCount = m_decoder.m_gifDecoder->frameCount();
    279             }
    280             if (frameCount != 1)
    281                 return;
    282             delete m_decoder.m_gifDecoder;
    283             m_decoder.m_gifDecoder = 0;
    284         }
    285 #endif
    286 
    287         int sampleSize = computeSampleSize(tmp);
    288         if (sampleSize > 1) {
    289             codec->setSampleSize(sampleSize);
    290             stream.rewind();
    291             if (!codec->decode(&stream, &tmp,
    292                                SkImageDecoder::kDecodeBounds_Mode)) {
    293                 return;
    294             }
    295         }
    296 
    297         m_decoder.m_image = new PrivateAndroidImageSourceRec(tmp, origW, origH,
    298                                                      sampleSize);
    299 
    300 //        SkDebugf("----- started: [%d %d] %s\n", origW, origH, m_decoder.m_url.c_str());
    301     }
    302 
    303     PrivateAndroidImageSourceRec* decoder = m_decoder.m_image;
    304     if (allDataReceived && decoder && !decoder->fAllDataReceived) {
    305         decoder->fAllDataReceived = true;
    306 
    307         SkBitmap* bm = &decoder->bitmap();
    308         SkPixelRef* ref = convertToRLE(bm, data->data(), data->size());
    309 
    310         if (ref) {
    311             bm->setPixelRef(ref)->unref();
    312         } else {
    313             BitmapAllocatorAndroid alloc(data, decoder->fSampleSize);
    314             if (!alloc.allocPixelRef(bm, NULL)) {
    315                 return;
    316             }
    317             ref = bm->pixelRef();
    318         }
    319 
    320         // we promise to never change the pixels (makes picture recording fast)
    321         ref->setImmutable();
    322         // give it the URL if we have one
    323         ref->setURI(m_decoder.m_url);
    324     }
    325 }
    326 
    327 bool ImageSource::isSizeAvailable()
    328 {
    329     return
    330 #ifdef ANDROID_ANIMATED_GIF
    331             (m_decoder.m_gifDecoder
    332                     && m_decoder.m_gifDecoder->isSizeAvailable()) ||
    333 #endif
    334             m_decoder.m_image != NULL;
    335 }
    336 
    337 IntSize ImageSource::size() const
    338 {
    339 #ifdef ANDROID_ANIMATED_GIF
    340     if (m_decoder.m_gifDecoder)
    341         return m_decoder.m_gifDecoder->size();
    342 #endif
    343     if (m_decoder.m_image) {
    344         return IntSize(m_decoder.m_image->origWidth(), m_decoder.m_image->origHeight());
    345     }
    346     return IntSize(0, 0);
    347 }
    348 
    349 int ImageSource::repetitionCount()
    350 {
    351 #ifdef ANDROID_ANIMATED_GIF
    352     if (m_decoder.m_gifDecoder)
    353         return m_decoder.m_gifDecoder->repetitionCount();
    354     if (!m_decoder.m_image) return 0;
    355 #endif
    356     return 1;
    357     // A property with value 0 means loop forever.
    358 }
    359 
    360 size_t ImageSource::frameCount() const
    361 {
    362 #ifdef ANDROID_ANIMATED_GIF
    363     if (m_decoder.m_gifDecoder) {
    364         return m_decoder.m_gifDecoder->failed() ? 0
    365                 : m_decoder.m_gifDecoder->frameCount();
    366     }
    367 #endif
    368     // i.e. 0 frames if we're not decoded, or 1 frame if we are
    369     return m_decoder.m_image != NULL;
    370 }
    371 
    372 SkBitmapRef* ImageSource::createFrameAtIndex(size_t index)
    373 {
    374 #ifdef ANDROID_ANIMATED_GIF
    375     if (m_decoder.m_gifDecoder) {
    376         ImageFrame* buffer =
    377                 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
    378         if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
    379             return 0;
    380         SkBitmap& bitmap = buffer->bitmap();
    381         SkPixelRef* pixelRef = bitmap.pixelRef();
    382         if (pixelRef)
    383             pixelRef->setURI(m_decoder.m_url);
    384         return new SkBitmapRef(bitmap);
    385     }
    386 #else
    387     SkASSERT(index == 0);
    388 #endif
    389     SkASSERT(m_decoder.m_image != NULL);
    390     m_decoder.m_image->ref();
    391     return m_decoder.m_image;
    392 }
    393 
    394 float ImageSource::frameDurationAtIndex(size_t index)
    395 {
    396     float duration = 0;
    397 #ifdef ANDROID_ANIMATED_GIF
    398     if (m_decoder.m_gifDecoder) {
    399         ImageFrame* buffer
    400                 = m_decoder.m_gifDecoder->frameBufferAtIndex(index);
    401         if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
    402             return 0;
    403         duration = buffer->duration() / 1000.0f;
    404     }
    405 #else
    406     SkASSERT(index == 0);
    407 #endif
    408 
    409     // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
    410     // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
    411     // a duration of <= 10 ms. See gfxImageFrame::GetTimeout in Gecko or Radar 4051389 for more.
    412     if (duration <= 0.010f)
    413         duration = 0.100f;
    414     return duration;
    415 }
    416 
    417 bool ImageSource::frameHasAlphaAtIndex(size_t index)
    418 {
    419 #ifdef ANDROID_ANIMATED_GIF
    420     if (m_decoder.m_gifDecoder) {
    421         ImageFrame* buffer =
    422                 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
    423         if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
    424             return false;
    425 
    426         return buffer->hasAlpha();
    427     }
    428 #else
    429     SkASSERT(0 == index);
    430 #endif
    431 
    432     if (NULL == m_decoder.m_image)
    433         return true;    // if we're not sure, assume the worse-case
    434     const PrivateAndroidImageSourceRec& decoder = *m_decoder.m_image;
    435     // if we're 16bit, we know even without all the data available
    436     if (decoder.bitmap().getConfig() == SkBitmap::kRGB_565_Config)
    437         return false;
    438 
    439     if (!decoder.fAllDataReceived)
    440         return true;    // if we're not sure, assume the worse-case
    441 
    442     return !decoder.bitmap().isOpaque();
    443 }
    444 
    445 bool ImageSource::frameIsCompleteAtIndex(size_t index)
    446 {
    447 #ifdef ANDROID_ANIMATED_GIF
    448     if (m_decoder.m_gifDecoder) {
    449         ImageFrame* buffer =
    450                 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
    451         return buffer && buffer->status() == ImageFrame::FrameComplete;
    452     }
    453 #else
    454     SkASSERT(0 == index);
    455 #endif
    456 	return m_decoder.m_image && m_decoder.m_image->fAllDataReceived;
    457 }
    458 
    459 void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
    460 {
    461 #ifdef ANDROID_ANIMATED_GIF
    462     if (!destroyAll) {
    463         if (m_decoder.m_gifDecoder)
    464             m_decoder.m_gifDecoder->clearFrameBufferCache(clearBeforeFrame);
    465         return;
    466     }
    467 
    468     delete m_decoder.m_gifDecoder;
    469     m_decoder.m_gifDecoder = 0;
    470     if (data)
    471         setData(data, allDataReceived);
    472 #endif
    473     // do nothing, since the cache is managed elsewhere
    474 }
    475 
    476 IntSize ImageSource::frameSizeAtIndex(size_t index) const
    477 {
    478     // for now, all (1) of our frames are the same size
    479     return this->size();
    480 }
    481 
    482 String ImageSource::filenameExtension() const
    483 {
    484     // FIXME: need to add virtual to our decoders to return "jpg/png/gif/..."
    485 #ifdef ANDROID_ANIMATED_GIF
    486     if (m_decoder.m_gifDecoder)
    487         return m_decoder.m_gifDecoder->filenameExtension();
    488 #endif
    489     return String();
    490 }
    491 
    492 bool ImageSource::getHotSpot(IntPoint&) const
    493 {
    494     return false;
    495 }
    496 
    497 size_t ImageSource::bytesDecodedToDetermineProperties() const
    498 {
    499     return 0;
    500 }
    501 
    502 }
    503