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*/ 94size_t computeMaxBitmapSizeForCache() { 95 return MAX_SIZE_BEFORE_SUBSAMPLE; 96} 97/////////////////////////////////////////////////////////////////////////////// 98 99class PrivateAndroidImageSourceRec : public SkBitmapRef { 100public: 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 111namespace WebCore { 112 113ImageSource::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 123ImageSource::~ImageSource() { 124 delete m_decoder.m_image; 125#ifdef ANDROID_ANIMATED_GIF 126 delete m_decoder.m_gifDecoder; 127#endif 128} 129 130bool 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 138static 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 158void ImageSource::clearURL() 159{ 160 m_decoder.m_url.reset(); 161} 162 163void 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 171static 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 181void 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 277bool 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 287IntSize 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 299int 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 310size_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 322SkBitmapRef* 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 344float 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 367bool 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 395bool 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 409void 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 426IntSize 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 432String 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 442bool ImageSource::getHotSpot(IntPoint&) const 443{ 444 return false; 445} 446 447size_t ImageSource::bytesDecodedToDetermineProperties() const 448{ 449 return 0; 450} 451 452} 453