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 #ifdef DUMP_IMAGEREF_LIFECYCLE
     33     SkDebugf("add ImageRef %p [%d] data=%d\n",
     34               this, this->info().fColorType, (int)stream->getLength());
     35 #endif
     36 }
     37 
     38 SkImageRef::~SkImageRef() {
     39 
     40 #ifdef DUMP_IMAGEREF_LIFECYCLE
     41     SkDebugf("delete ImageRef %p [%d] data=%d\n",
     42               this, fConfig, (int)fStream->getLength());
     43 #endif
     44 
     45     fStream->unref();
     46     SkSafeUnref(fFactory);
     47 }
     48 
     49 bool SkImageRef::getInfo(SkBitmap* bitmap) {
     50     SkAutoMutexAcquire ac(this->mutex());
     51 
     52     if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) {
     53         return false;
     54     }
     55 
     56     SkASSERT(SkBitmap::kNo_Config != fBitmap.config());
     57     if (bitmap) {
     58         bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height());
     59     }
     60     return true;
     61 }
     62 
     63 bool SkImageRef::isOpaque(SkBitmap* bitmap) {
     64     if (bitmap && bitmap->pixelRef() == this) {
     65         bitmap->lockPixels();
     66         // what about colortables??????
     67         bitmap->setAlphaType(fBitmap.alphaType());
     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, SkStreamRewindable* 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     if (NULL != fBitmap.getPixels() ||
     95             (SkBitmap::kNo_Config != fBitmap.config() &&
     96              SkImageDecoder::kDecodeBounds_Mode == mode)) {
     97         return true;
     98     }
     99 
    100     SkASSERT(fBitmap.getPixels() == NULL);
    101 
    102     if (!fStream->rewind()) {
    103         SkDEBUGF(("Failed to rewind SkImageRef stream!"));
    104         return false;
    105     }
    106 
    107     SkImageDecoder* codec;
    108     if (fFactory) {
    109         codec = fFactory->newDecoder(fStream);
    110     } else {
    111         codec = SkImageDecoder::Factory(fStream);
    112     }
    113 
    114     if (codec) {
    115         SkAutoTDelete<SkImageDecoder> ad(codec);
    116 
    117         codec->setSampleSize(fSampleSize);
    118         codec->setDitherImage(fDoDither);
    119         if (this->onDecode(codec, fStream, &fBitmap, fBitmap.config(), mode)) {
    120             return true;
    121         }
    122     }
    123 
    124 #ifdef DUMP_IMAGEREF_LIFECYCLE
    125     if (NULL == codec) {
    126         SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI());
    127     } else {
    128         SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n",
    129                  this->getURI(), mode);
    130     }
    131 #endif
    132     fErrorInDecoding = true;
    133     fBitmap.reset();
    134     return false;
    135 }
    136 
    137 void* SkImageRef::onLockPixels(SkColorTable** ct) {
    138     if (NULL == fBitmap.getPixels()) {
    139         (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
    140     }
    141 
    142     if (ct) {
    143         *ct = fBitmap.getColorTable();
    144     }
    145     return fBitmap.getPixels();
    146 }
    147 
    148 size_t SkImageRef::ramUsed() const {
    149     size_t size = 0;
    150 
    151     if (fBitmap.getPixels()) {
    152         size = fBitmap.getSize();
    153         if (fBitmap.getColorTable()) {
    154             size += fBitmap.getColorTable()->count() * sizeof(SkPMColor);
    155         }
    156     }
    157     return size;
    158 }
    159 
    160 ///////////////////////////////////////////////////////////////////////////////
    161 
    162 SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
    163         : INHERITED(buffer, mutex), fErrorInDecoding(false) {
    164     fSampleSize = buffer.readInt();
    165     fDoDither = buffer.readBool();
    166 
    167     size_t length = buffer.getArrayCount();
    168     fStream = SkNEW_ARGS(SkMemoryStream, (length));
    169     buffer.readByteArray((void*)fStream->getMemoryBase(), length);
    170 
    171     fPrev = fNext = NULL;
    172     fFactory = NULL;
    173 }
    174 
    175 void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
    176     this->INHERITED::flatten(buffer);
    177 
    178     buffer.writeInt(fSampleSize);
    179     buffer.writeBool(fDoDither);
    180     // FIXME: Consider moving this logic should go into writeStream itself.
    181     // writeStream currently has no other callers, so this may be fine for
    182     // now.
    183     if (!fStream->rewind()) {
    184         SkDEBUGF(("Failed to rewind SkImageRef stream!"));
    185         buffer.write32(0);
    186     } else {
    187         // FIXME: Handle getLength properly here. Perhaps this class should
    188         // take an SkStreamAsset.
    189         buffer.writeStream(fStream, fStream->getLength());
    190     }
    191 }
    192