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     if (!fStream->rewind()) {
    111         SkDEBUGF(("Failed to rewind SkImageRef stream!"));
    112         return false;
    113     }
    114 
    115     SkImageDecoder* codec;
    116     if (fFactory) {
    117         codec = fFactory->newDecoder(fStream);
    118     } else {
    119         codec = SkImageDecoder::Factory(fStream);
    120     }
    121 
    122     if (codec) {
    123         SkAutoTDelete<SkImageDecoder> ad(codec);
    124 
    125         codec->setSampleSize(fSampleSize);
    126         codec->setDitherImage(fDoDither);
    127         if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) {
    128             return true;
    129         }
    130     }
    131 
    132 #ifdef DUMP_IMAGEREF_LIFECYCLE
    133     if (NULL == codec) {
    134         SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI());
    135     } else {
    136         SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n",
    137                  this->getURI(), mode);
    138     }
    139 #endif
    140     fErrorInDecoding = true;
    141     fBitmap.reset();
    142     return false;
    143 }
    144 
    145 void* SkImageRef::onLockPixels(SkColorTable** ct) {
    146     if (NULL == fBitmap.getPixels()) {
    147         (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
    148     }
    149 
    150     if (ct) {
    151         *ct = fBitmap.getColorTable();
    152     }
    153     return fBitmap.getPixels();
    154 }
    155 
    156 size_t SkImageRef::ramUsed() const {
    157     size_t size = 0;
    158 
    159     if (fBitmap.getPixels()) {
    160         size = fBitmap.getSize();
    161         if (fBitmap.getColorTable()) {
    162             size += fBitmap.getColorTable()->count() * sizeof(SkPMColor);
    163         }
    164     }
    165     return size;
    166 }
    167 
    168 ///////////////////////////////////////////////////////////////////////////////
    169 
    170 SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
    171         : INHERITED(buffer, mutex), fErrorInDecoding(false) {
    172     fConfig = (SkBitmap::Config)buffer.readUInt();
    173     fSampleSize = buffer.readInt();
    174     fDoDither = buffer.readBool();
    175 
    176     size_t length = buffer.getArrayCount();
    177     fStream = SkNEW_ARGS(SkMemoryStream, (length));
    178     buffer.readByteArray((void*)fStream->getMemoryBase());
    179 
    180     fPrev = fNext = NULL;
    181     fFactory = NULL;
    182 }
    183 
    184 void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
    185     this->INHERITED::flatten(buffer);
    186 
    187     buffer.writeUInt(fConfig);
    188     buffer.writeInt(fSampleSize);
    189     buffer.writeBool(fDoDither);
    190     // FIXME: Consider moving this logic should go into writeStream itself.
    191     // writeStream currently has no other callers, so this may be fine for
    192     // now.
    193     if (!fStream->rewind()) {
    194         SkDEBUGF(("Failed to rewind SkImageRef stream!"));
    195         buffer.write32(0);
    196     } else {
    197         // FIXME: Handle getLength properly here. Perhaps this class should
    198         // take an SkStreamAsset.
    199         buffer.writeStream(fStream, fStream->getLength());
    200     }
    201 }
    202