SkImageRef.cpp revision 24fb8c7cc7b76134a25914d8f6346c89c359c621
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkImageRef.h" 20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmap.h" 30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFlattenable.h" 40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkImageDecoder.h" 50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStream.h" 60910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTemplates.h" 70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkThread.h" 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 924fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed//#define DUMP_IMAGEREF_LIFECYCLE 1024fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// can't be static, as SkImageRef_Pool needs to see it 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkMutex gImageRefMutex; 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkImageRef::SkImageRef(SkStream* stream, SkBitmap::Config config, 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int sampleSize) 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project : SkPixelRef(&gImageRefMutex), fErrorInDecoding(false) { 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(stream); 20af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project stream->ref(); 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStream = stream; 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fConfig = config; 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSampleSize = sampleSize; 2447f2621859e1e6fa9a5ed53e7ca66bc395999242Mike Reed fDoDither = true; 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrev = fNext = NULL; 26af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project fFactory = NULL; 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef DUMP_IMAGEREF_LIFECYCLE 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("add ImageRef %p [%d] data=%d\n", 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this, config, (int)stream->getLength()); 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkImageRef::~SkImageRef() { 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&gImageRefMutex == this->mutex()); 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef DUMP_IMAGEREF_LIFECYCLE 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("delete ImageRef %p [%d] data=%d\n", 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this, fConfig, (int)fStream->getLength()); 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 42af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project fStream->unref(); 43af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project fFactory->safeUnref(); 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkImageRef::getInfo(SkBitmap* bitmap) { 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMutexAcquire ac(gImageRefMutex); 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) { 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(SkBitmap::kNo_Config != fBitmap.config()); 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bitmap) { 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height()); 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 60af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source ProjectSkImageDecoderFactory* SkImageRef::setDecoderFactory( 61af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project SkImageDecoderFactory* fact) { 62af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project SkRefCnt_SafeAssign(fFactory, fact); 63af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project return fact; 64af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project} 65af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkImageRef::onDecode(SkImageDecoder* codec, SkStream* stream, 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBitmap* bitmap, SkBitmap::Config config, 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkImageDecoder::Mode mode) { 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return codec->decode(stream, bitmap, config, mode); 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) { 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&gImageRefMutex == this->mutex()); 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fErrorInDecoding) { 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* As soon as we really know our config, we record it, so that on 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subsequent calls to the codec, we are sure we will always get the same 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result. 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkBitmap::kNo_Config != fBitmap.config()) { 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fConfig = fBitmap.config(); 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != fBitmap.getPixels() || 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkBitmap::kNo_Config != fBitmap.config() && 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkImageDecoder::kDecodeBounds_Mode == mode)) { 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fBitmap.getPixels() == NULL); 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStream->rewind(); 98af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project 99af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project SkImageDecoder* codec; 100af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project if (fFactory) { 101af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project codec = fFactory->newDecoder(fStream); 102af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project } else { 103af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project codec = SkImageDecoder::Factory(fStream); 104af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project } 105af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (codec) { 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoTDelete<SkImageDecoder> ad(codec); 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project codec->setSampleSize(fSampleSize); 11047f2621859e1e6fa9a5ed53e7ca66bc395999242Mike Reed codec->setDitherImage(fDoDither); 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) { 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef DUMP_IMAGEREF_LIFECYCLE 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL == codec) { 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI()); 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n", 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getURI(), mode); 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fErrorInDecoding = true; 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fBitmap.reset(); 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid* SkImageRef::onLockPixels(SkColorTable** ct) { 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&gImageRefMutex == this->mutex()); 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL == fBitmap.getPixels()) { 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode); 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (ct) { 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *ct = fBitmap.getColorTable(); 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fBitmap.getPixels(); 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkImageRef::onUnlockPixels() { 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // we're already have the mutex locked 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&gImageRefMutex == this->mutex()); 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectsize_t SkImageRef::ramUsed() const { 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t size = 0; 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBitmap.getPixels()) { 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size = fBitmap.getSize(); 1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBitmap.getColorTable()) { 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size += fBitmap.getColorTable()->count() * sizeof(SkPMColor); 1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return size; 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer) 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project : INHERITED(buffer, &gImageRefMutex), fErrorInDecoding(false) { 1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fConfig = (SkBitmap::Config)buffer.readU8(); 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSampleSize = buffer.readU8(); 16524fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed fDoDither = buffer.readBool(); 16624fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t length = buffer.readU32(); 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStream = SkNEW_ARGS(SkMemoryStream, (length)); 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.read((void*)fStream->getMemoryBase(), length); 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrev = fNext = NULL; 172bf62c4a8cf34acfad56af81e7f8cb059ef554f74Mike Reed fFactory = NULL; 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const { 1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->INHERITED::flatten(buffer); 1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.write8(fConfig); 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.write8(fSampleSize); 18024fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed buffer.writeBool(fDoDither); 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t length = fStream->getLength(); 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.write32(length); 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStream->rewind(); 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.readFromStream(fStream, length); 1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 187