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