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