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