Home | History | Annotate | Download | only in images
      1 #include "SkImageRef.h"
      2 #include "SkBitmap.h"
      3 #include "SkFlattenable.h"
      4 #include "SkImageDecoder.h"
      5 #include "SkStream.h"
      6 #include "SkTemplates.h"
      7 #include "SkThread.h"
      8 
      9 //#define DUMP_IMAGEREF_LIFECYCLE
     10 
     11 // can't be static, as SkImageRef_Pool needs to see it
     12 SkMutex gImageRefMutex;
     13 
     14 ///////////////////////////////////////////////////////////////////////////////
     15 
     16 SkImageRef::SkImageRef(SkStream* stream, SkBitmap::Config config,
     17                        int sampleSize)
     18         : SkPixelRef(&gImageRefMutex), fErrorInDecoding(false) {
     19     SkASSERT(stream);
     20     stream->ref();
     21     fStream = stream;
     22     fConfig = config;
     23     fSampleSize = sampleSize;
     24     fDoDither = true;
     25     fPrev = fNext = NULL;
     26     fFactory = NULL;
     27 
     28 #ifdef DUMP_IMAGEREF_LIFECYCLE
     29     SkDebugf("add ImageRef %p [%d] data=%d\n",
     30               this, config, (int)stream->getLength());
     31 #endif
     32 }
     33 
     34 SkImageRef::~SkImageRef() {
     35     SkASSERT(&gImageRefMutex == this->mutex());
     36 
     37 #ifdef DUMP_IMAGEREF_LIFECYCLE
     38     SkDebugf("delete ImageRef %p [%d] data=%d\n",
     39               this, fConfig, (int)fStream->getLength());
     40 #endif
     41 
     42     fStream->unref();
     43     fFactory->safeUnref();
     44 }
     45 
     46 bool SkImageRef::getInfo(SkBitmap* bitmap) {
     47     SkAutoMutexAcquire ac(gImageRefMutex);
     48 
     49     if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) {
     50         return false;
     51     }
     52 
     53     SkASSERT(SkBitmap::kNo_Config != fBitmap.config());
     54     if (bitmap) {
     55         bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height());
     56     }
     57     return true;
     58 }
     59 
     60 bool SkImageRef::isOpaque(SkBitmap* bitmap) {
     61     if (bitmap && bitmap->pixelRef() == this) {
     62         bitmap->lockPixels();
     63         bitmap->setIsOpaque(fBitmap.isOpaque());
     64         bitmap->unlockPixels();
     65         return true;
     66     }
     67     return false;
     68 }
     69 
     70 SkImageDecoderFactory* SkImageRef::setDecoderFactory(
     71                                                 SkImageDecoderFactory* fact) {
     72     SkRefCnt_SafeAssign(fFactory, fact);
     73     return fact;
     74 }
     75 
     76 ///////////////////////////////////////////////////////////////////////////////
     77 
     78 bool SkImageRef::onDecode(SkImageDecoder* codec, SkStream* stream,
     79                           SkBitmap* bitmap, SkBitmap::Config config,
     80                           SkImageDecoder::Mode mode) {
     81     return codec->decode(stream, bitmap, config, mode);
     82 }
     83 
     84 bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
     85     SkASSERT(&gImageRefMutex == this->mutex());
     86 
     87     if (fErrorInDecoding) {
     88         return false;
     89     }
     90 
     91     /*  As soon as we really know our config, we record it, so that on
     92         subsequent calls to the codec, we are sure we will always get the same
     93         result.
     94     */
     95     if (SkBitmap::kNo_Config != fBitmap.config()) {
     96         fConfig = fBitmap.config();
     97     }
     98 
     99     if (NULL != fBitmap.getPixels() ||
    100             (SkBitmap::kNo_Config != fBitmap.config() &&
    101              SkImageDecoder::kDecodeBounds_Mode == mode)) {
    102         return true;
    103     }
    104 
    105     SkASSERT(fBitmap.getPixels() == NULL);
    106 
    107     fStream->rewind();
    108 
    109     SkImageDecoder* codec;
    110     if (fFactory) {
    111         codec = fFactory->newDecoder(fStream);
    112     } else {
    113         codec = SkImageDecoder::Factory(fStream);
    114     }
    115 
    116     if (codec) {
    117         SkAutoTDelete<SkImageDecoder> ad(codec);
    118 
    119         codec->setSampleSize(fSampleSize);
    120         codec->setDitherImage(fDoDither);
    121         if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) {
    122             return true;
    123         }
    124     }
    125 
    126 #ifdef DUMP_IMAGEREF_LIFECYCLE
    127     if (NULL == codec) {
    128         SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI());
    129     } else {
    130         SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n",
    131                  this->getURI(), mode);
    132     }
    133 #endif
    134     fErrorInDecoding = true;
    135     fBitmap.reset();
    136     return false;
    137 }
    138 
    139 void* SkImageRef::onLockPixels(SkColorTable** ct) {
    140     SkASSERT(&gImageRefMutex == this->mutex());
    141 
    142     if (NULL == fBitmap.getPixels()) {
    143         (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
    144     }
    145 
    146     if (ct) {
    147         *ct = fBitmap.getColorTable();
    148     }
    149     return fBitmap.getPixels();
    150 }
    151 
    152 void SkImageRef::onUnlockPixels() {
    153     // we're already have the mutex locked
    154     SkASSERT(&gImageRefMutex == this->mutex());
    155 }
    156 
    157 size_t SkImageRef::ramUsed() const {
    158     size_t size = 0;
    159 
    160     if (fBitmap.getPixels()) {
    161         size = fBitmap.getSize();
    162         if (fBitmap.getColorTable()) {
    163             size += fBitmap.getColorTable()->count() * sizeof(SkPMColor);
    164         }
    165     }
    166     return size;
    167 }
    168 
    169 ///////////////////////////////////////////////////////////////////////////////
    170 
    171 SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer)
    172         : INHERITED(buffer, &gImageRefMutex), fErrorInDecoding(false) {
    173     fConfig = (SkBitmap::Config)buffer.readU8();
    174     fSampleSize = buffer.readU8();
    175     fDoDither = buffer.readBool();
    176 
    177     size_t length = buffer.readU32();
    178     fStream = SkNEW_ARGS(SkMemoryStream, (length));
    179     buffer.read((void*)fStream->getMemoryBase(), length);
    180 
    181     fPrev = fNext = NULL;
    182     fFactory = NULL;
    183 }
    184 
    185 void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
    186     this->INHERITED::flatten(buffer);
    187 
    188     buffer.write8(fConfig);
    189     buffer.write8(fSampleSize);
    190     buffer.writeBool(fDoDither);
    191     size_t length = fStream->getLength();
    192     buffer.write32(length);
    193     fStream->rewind();
    194     buffer.readFromStream(fStream, length);
    195 }
    196 
    197