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