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(const SkImageInfo& info, SkStreamRewindable* stream,
     22                        int sampleSize, SkBaseMutex* mutex)
     23         : SkPixelRef(info, mutex), fErrorInDecoding(false) {
     24     SkASSERT(stream);
     25     stream->ref();
     26     fStream = stream;
     27     fSampleSize = sampleSize;
     28     fDoDither = true;
     29     fPrev = fNext = NULL;
     30     fFactory = NULL;
     31 
     32     // This sets the colortype/alphatype to exactly match our info, so that this
     33     // can get communicated down to the codec.
     34     fBitmap.setConfig(info);
     35 
     36 #ifdef DUMP_IMAGEREF_LIFECYCLE
     37     SkDebugf("add ImageRef %p [%d] data=%d\n",
     38               this, this->info().fColorType, (int)stream->getLength());
     39 #endif
     40 }
     41 
     42 SkImageRef::~SkImageRef() {
     43 
     44 #ifdef DUMP_IMAGEREF_LIFECYCLE
     45     SkDebugf("delete ImageRef %p [%d] data=%d\n",
     46               this, fConfig, (int)fStream->getLength());
     47 #endif
     48 
     49     fStream->unref();
     50     SkSafeUnref(fFactory);
     51 }
     52 
     53 bool SkImageRef::getInfo(SkBitmap* bitmap) {
     54     SkAutoMutexAcquire ac(this->mutex());
     55 
     56     if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) {
     57         return false;
     58     }
     59 
     60     SkASSERT(SkBitmap::kNo_Config != fBitmap.config());
     61     if (bitmap) {
     62         bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height());
     63     }
     64     return true;
     65 }
     66 
     67 bool SkImageRef::isOpaque(SkBitmap* bitmap) {
     68     if (bitmap && bitmap->pixelRef() == this) {
     69         bitmap->lockPixels();
     70         // what about colortables??????
     71         bitmap->setAlphaType(fBitmap.alphaType());
     72         bitmap->unlockPixels();
     73         return true;
     74     }
     75     return false;
     76 }
     77 
     78 SkImageDecoderFactory* SkImageRef::setDecoderFactory(
     79                                                 SkImageDecoderFactory* fact) {
     80     SkRefCnt_SafeAssign(fFactory, fact);
     81     return fact;
     82 }
     83 
     84 ///////////////////////////////////////////////////////////////////////////////
     85 
     86 bool SkImageRef::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
     87                           SkBitmap* bitmap, SkBitmap::Config config,
     88                           SkImageDecoder::Mode mode) {
     89     return codec->decode(stream, bitmap, config, mode);
     90 }
     91 
     92 bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
     93 
     94     if (fErrorInDecoding) {
     95         return false;
     96     }
     97 
     98     if (NULL != fBitmap.getPixels() ||
     99             (SkBitmap::kNo_Config != fBitmap.config() &&
    100              SkImageDecoder::kDecodeBounds_Mode == mode)) {
    101         return true;
    102     }
    103 
    104     SkASSERT(fBitmap.getPixels() == NULL);
    105 
    106     if (!fStream->rewind()) {
    107         SkDEBUGF(("Failed to rewind SkImageRef stream!"));
    108         return false;
    109     }
    110 
    111     SkImageDecoder* codec;
    112     if (fFactory) {
    113         codec = fFactory->newDecoder(fStream);
    114     } else {
    115         codec = SkImageDecoder::Factory(fStream);
    116     }
    117 
    118     if (codec) {
    119         SkAutoTDelete<SkImageDecoder> ad(codec);
    120 
    121         codec->setSampleSize(fSampleSize);
    122         codec->setDitherImage(fDoDither);
    123         if (this->onDecode(codec, fStream, &fBitmap, fBitmap.config(), mode)) {
    124             SkDEBUGCODE(SkImageInfo info;)
    125             SkASSERT(!fBitmap.asImageInfo(&info) || this->info().fColorType == info.fColorType);
    126             SkASSERT(this->info().fWidth == fBitmap.width());
    127             SkASSERT(this->info().fHeight == fBitmap.height());
    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     fSampleSize = buffer.readInt();
    173     fDoDither = buffer.readBool();
    174 
    175     size_t length = buffer.getArrayCount();
    176     fStream = SkNEW_ARGS(SkMemoryStream, (length));
    177     buffer.readByteArray((void*)fStream->getMemoryBase(), length);
    178 
    179     fPrev = fNext = NULL;
    180     fFactory = NULL;
    181 
    182     // This sets the colortype/alphatype to exactly match our info, so that this
    183     // can get communicated down to the codec.
    184     fBitmap.setConfig(this->info());
    185 }
    186 
    187 void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
    188     this->INHERITED::flatten(buffer);
    189 
    190     buffer.writeInt(fSampleSize);
    191     buffer.writeBool(fDoDither);
    192     // FIXME: Consider moving this logic should go into writeStream itself.
    193     // writeStream currently has no other callers, so this may be fine for
    194     // now.
    195     if (!fStream->rewind()) {
    196         SkDEBUGF(("Failed to rewind SkImageRef stream!"));
    197         buffer.write32(0);
    198     } else {
    199         // FIXME: Handle getLength properly here. Perhaps this class should
    200         // take an SkStreamAsset.
    201         buffer.writeStream(fStream, fStream->getLength());
    202     }
    203 }
    204