SkImageRef.cpp revision 4f1dae40e24d57d647db01443b8bf2410514b8b5
11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc. 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkImageRef.h" 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmap.h" 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFlattenable.h" 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkImageDecoder.h" 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStream.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTemplates.h" 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkThread.h" 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1624fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed//#define DUMP_IMAGEREF_LIFECYCLE 1724fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// can't be static, as SkImageRef_Pool needs to see it 194f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSK_DECLARE_GLOBAL_MUTEX(gImageRefMutex); 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkImageRef::SkImageRef(SkStream* stream, SkBitmap::Config config, 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int sampleSize) 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project : SkPixelRef(&gImageRefMutex), fErrorInDecoding(false) { 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(stream); 27af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project stream->ref(); 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStream = stream; 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fConfig = config; 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSampleSize = sampleSize; 3147f2621859e1e6fa9a5ed53e7ca66bc395999242Mike Reed fDoDither = true; 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrev = fNext = NULL; 33af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project fFactory = NULL; 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef DUMP_IMAGEREF_LIFECYCLE 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("add ImageRef %p [%d] data=%d\n", 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this, config, (int)stream->getLength()); 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkImageRef::~SkImageRef() { 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&gImageRefMutex == this->mutex()); 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef DUMP_IMAGEREF_LIFECYCLE 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("delete ImageRef %p [%d] data=%d\n", 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this, fConfig, (int)fStream->getLength()); 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 49af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project fStream->unref(); 5040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkSafeUnref(fFactory); 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkImageRef::getInfo(SkBitmap* bitmap) { 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMutexAcquire ac(gImageRefMutex); 5540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) { 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(SkBitmap::kNo_Config != fBitmap.config()); 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bitmap) { 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height()); 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6799d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guybool SkImageRef::isOpaque(SkBitmap* bitmap) { 6899d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy if (bitmap && bitmap->pixelRef() == this) { 6999d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy bitmap->lockPixels(); 7099d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy bitmap->setIsOpaque(fBitmap.isOpaque()); 7199d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy bitmap->unlockPixels(); 7299d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy return true; 7399d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy } 7499d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy return false; 7599d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy} 7699d118f65a9d99c610396ea78b27faadb8d0b9cdRomain Guy 77af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source ProjectSkImageDecoderFactory* SkImageRef::setDecoderFactory( 78af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project SkImageDecoderFactory* fact) { 79af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project SkRefCnt_SafeAssign(fFactory, fact); 80af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project return fact; 81af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project} 82af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkImageRef::onDecode(SkImageDecoder* codec, SkStream* stream, 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBitmap* bitmap, SkBitmap::Config config, 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkImageDecoder::Mode mode) { 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return codec->decode(stream, bitmap, config, mode); 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) { 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&gImageRefMutex == this->mutex()); 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fErrorInDecoding) { 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* As soon as we really know our config, we record it, so that on 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subsequent calls to the codec, we are sure we will always get the same 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result. 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkBitmap::kNo_Config != fBitmap.config()) { 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fConfig = fBitmap.config(); 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != fBitmap.getPixels() || 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkBitmap::kNo_Config != fBitmap.config() && 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkImageDecoder::kDecodeBounds_Mode == mode)) { 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fBitmap.getPixels() == NULL); 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStream->rewind(); 115af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project 116af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project SkImageDecoder* codec; 117af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project if (fFactory) { 118af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project codec = fFactory->newDecoder(fStream); 119af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project } else { 120af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project codec = SkImageDecoder::Factory(fStream); 121af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project } 122af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (codec) { 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoTDelete<SkImageDecoder> ad(codec); 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project codec->setSampleSize(fSampleSize); 12747f2621859e1e6fa9a5ed53e7ca66bc395999242Mike Reed codec->setDitherImage(fDoDither); 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) { 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef DUMP_IMAGEREF_LIFECYCLE 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL == codec) { 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI()); 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n", 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getURI(), mode); 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fErrorInDecoding = true; 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fBitmap.reset(); 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid* SkImageRef::onLockPixels(SkColorTable** ct) { 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&gImageRefMutex == this->mutex()); 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL == fBitmap.getPixels()) { 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode); 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (ct) { 1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *ct = fBitmap.getColorTable(); 1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fBitmap.getPixels(); 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkImageRef::onUnlockPixels() { 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // we're already have the mutex locked 1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&gImageRefMutex == this->mutex()); 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectsize_t SkImageRef::ramUsed() const { 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t size = 0; 1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBitmap.getPixels()) { 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size = fBitmap.getSize(); 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBitmap.getColorTable()) { 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size += fBitmap.getColorTable()->count() * sizeof(SkPMColor); 1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return size; 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer) 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project : INHERITED(buffer, &gImageRefMutex), fErrorInDecoding(false) { 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fConfig = (SkBitmap::Config)buffer.readU8(); 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSampleSize = buffer.readU8(); 18224fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed fDoDither = buffer.readBool(); 18324fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t length = buffer.readU32(); 1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStream = SkNEW_ARGS(SkMemoryStream, (length)); 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.read((void*)fStream->getMemoryBase(), length); 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrev = fNext = NULL; 189bf62c4a8cf34acfad56af81e7f8cb059ef554f74Mike Reed fFactory = NULL; 1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const { 1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->INHERITED::flatten(buffer); 1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.write8(fConfig); 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.write8(fSampleSize); 19724fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed buffer.writeBool(fDoDither); 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t length = fStream->getLength(); 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.write32(length); 2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStream->rewind(); 2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.readFromStream(fStream, length); 2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 204