1 /* libs/graphics/images/SkImageDecoder.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkImageDecoder.h"
19 #include "SkBitmap.h"
20 #include "SkPixelRef.h"
21 #include "SkStream.h"
22 #include "SkTemplates.h"
23 #include "SkCanvas.h"
24
~SkVMMemoryReporter()25 SkVMMemoryReporter::~SkVMMemoryReporter() {
26 }
27
28 const char *SkImageDecoder::kFormatName[] = {
29 "Unknown Format",
30 "BMP",
31 "GIF",
32 "ICO",
33 "JPEG",
34 "PNG",
35 "WBMP",
36 "WEBP",
37 };
38
39 static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
40
GetDeviceConfig()41 SkBitmap::Config SkImageDecoder::GetDeviceConfig()
42 {
43 return gDeviceConfig;
44 }
45
SetDeviceConfig(SkBitmap::Config config)46 void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
47 {
48 gDeviceConfig = config;
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////
52
SkImageDecoder()53 SkImageDecoder::SkImageDecoder()
54 : fReporter(NULL), fPeeker(NULL), fChooser(NULL), fAllocator(NULL),
55 fSampleSize(1), fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
56 fUsePrefTable(false) {
57 }
58
~SkImageDecoder()59 SkImageDecoder::~SkImageDecoder() {
60 SkSafeUnref(fPeeker);
61 SkSafeUnref(fChooser);
62 SkSafeUnref(fAllocator);
63 SkSafeUnref(fReporter);
64 }
65
getFormat() const66 SkImageDecoder::Format SkImageDecoder::getFormat() const {
67 return kUnknown_Format;
68 }
69
setPeeker(Peeker * peeker)70 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
71 SkRefCnt_SafeAssign(fPeeker, peeker);
72 return peeker;
73 }
74
setChooser(Chooser * chooser)75 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
76 SkRefCnt_SafeAssign(fChooser, chooser);
77 return chooser;
78 }
79
setAllocator(SkBitmap::Allocator * alloc)80 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
81 SkRefCnt_SafeAssign(fAllocator, alloc);
82 return alloc;
83 }
84
setReporter(SkVMMemoryReporter * reporter)85 SkVMMemoryReporter* SkImageDecoder::setReporter(SkVMMemoryReporter* reporter) {
86 SkRefCnt_SafeAssign(fReporter, reporter);
87 return reporter;
88 }
89
setSampleSize(int size)90 void SkImageDecoder::setSampleSize(int size) {
91 if (size < 1) {
92 size = 1;
93 }
94 fSampleSize = size;
95 }
96
chooseFromOneChoice(SkBitmap::Config config,int width,int height) const97 bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
98 int height) const {
99 Chooser* chooser = fChooser;
100
101 if (NULL == chooser) { // no chooser, we just say YES to decoding :)
102 return true;
103 }
104 chooser->begin(1);
105 chooser->inspect(0, config, width, height);
106 return chooser->choose() == 0;
107 }
108
allocPixelRef(SkBitmap * bitmap,SkColorTable * ctable) const109 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
110 SkColorTable* ctable) const {
111 return bitmap->allocPixels(fAllocator, ctable);
112 }
113
114 ///////////////////////////////////////////////////////////////////////////////
115
setPrefConfigTable(const SkBitmap::Config pref[6])116 void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
117 if (NULL == pref) {
118 fUsePrefTable = false;
119 } else {
120 fUsePrefTable = true;
121 memcpy(fPrefTable, pref, sizeof(fPrefTable));
122 }
123 }
124
getPrefConfig(SrcDepth srcDepth,bool srcHasAlpha) const125 SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
126 bool srcHasAlpha) const {
127 SkBitmap::Config config;
128
129 if (fUsePrefTable) {
130 int index = 0;
131 switch (srcDepth) {
132 case kIndex_SrcDepth:
133 index = 0;
134 break;
135 case k16Bit_SrcDepth:
136 index = 2;
137 break;
138 case k32Bit_SrcDepth:
139 index = 4;
140 break;
141 }
142 if (srcHasAlpha) {
143 index += 1;
144 }
145 config = fPrefTable[index];
146 } else {
147 config = fDefaultPref;
148 }
149
150 if (SkBitmap::kNo_Config == config) {
151 config = SkImageDecoder::GetDeviceConfig();
152 }
153 return config;
154 }
155
decode(SkStream * stream,SkBitmap * bm,SkBitmap::Config pref,Mode mode,bool reuseBitmap)156 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
157 SkBitmap::Config pref, Mode mode, bool reuseBitmap) {
158 // pass a temporary bitmap, so that if we return false, we are assured of
159 // leaving the caller's bitmap untouched.
160 SkBitmap tmp;
161
162 // we reset this to false before calling onDecode
163 fShouldCancelDecode = false;
164 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
165 fDefaultPref = pref;
166
167 if (reuseBitmap) {
168 SkAutoLockPixels alp(*bm);
169 if (bm->getPixels() != NULL) {
170 return this->onDecode(stream, bm, mode);
171 }
172 }
173 if (!this->onDecode(stream, &tmp, mode)) {
174 return false;
175 }
176 bm->swap(tmp);
177 return true;
178 }
179
decodeRegion(SkBitmap * bm,SkIRect rect,SkBitmap::Config pref)180 bool SkImageDecoder::decodeRegion(SkBitmap* bm, SkIRect rect,
181 SkBitmap::Config pref) {
182 // pass a temporary bitmap, so that if we return false, we are assured of
183 // leaving the caller's bitmap untouched.
184 SkBitmap tmp;
185
186 // we reset this to false before calling onDecodeRegion
187 fShouldCancelDecode = false;
188 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
189 fDefaultPref = pref;
190
191 if (!this->onDecodeRegion(&tmp, rect)) {
192 return false;
193 }
194 bm->swap(tmp);
195 return true;
196 }
197
buildTileIndex(SkStream * stream,int * width,int * height)198 bool SkImageDecoder::buildTileIndex(SkStream* stream,
199 int *width, int *height) {
200 // we reset this to false before calling onBuildTileIndex
201 fShouldCancelDecode = false;
202
203 return this->onBuildTileIndex(stream, width, height);
204 }
205
cropBitmap(SkBitmap * dest,SkBitmap * src,int sampleSize,int destX,int destY,int width,int height,int srcX,int srcY)206 void SkImageDecoder::cropBitmap(SkBitmap *dest, SkBitmap *src,
207 int sampleSize, int destX, int destY,
208 int width, int height, int srcX, int srcY) {
209 int w = width / sampleSize;
210 int h = height / sampleSize;
211 if (w == src->width() && h == src->height() &&
212 (srcX - destX) / sampleSize == 0 && (srcY - destY) / sampleSize == 0) {
213 // The output rect is the same as the decode result
214 dest->swap(*src);
215 return;
216 }
217 dest->setConfig(src->getConfig(), w, h);
218 dest->setIsOpaque(src->isOpaque());
219 this->allocPixelRef(dest, NULL);
220
221 SkCanvas canvas(*dest);
222 canvas.drawBitmap(*src, (srcX - destX) / sampleSize,
223 (srcY - destY) / sampleSize);
224 }
225
226 ///////////////////////////////////////////////////////////////////////////////
227
DecodeFile(const char file[],SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)228 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
229 SkBitmap::Config pref, Mode mode, Format* format) {
230 SkASSERT(file);
231 SkASSERT(bm);
232
233 SkFILEStream stream(file);
234 if (stream.isValid()) {
235 if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) {
236 bm->pixelRef()->setURI(file);
237 }
238 return true;
239 }
240 return false;
241 }
242
DecodeMemory(const void * buffer,size_t size,SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)243 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
244 SkBitmap::Config pref, Mode mode, Format* format) {
245 if (0 == size) {
246 return false;
247 }
248 SkASSERT(buffer);
249
250 SkMemoryStream stream(buffer, size);
251 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
252 }
253
DecodeStream(SkStream * stream,SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)254 bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
255 SkBitmap::Config pref, Mode mode, Format* format) {
256 SkASSERT(stream);
257 SkASSERT(bm);
258
259 bool success = false;
260 SkImageDecoder* codec = SkImageDecoder::Factory(stream);
261
262 if (NULL != codec) {
263 success = codec->decode(stream, bm, pref, mode);
264 if (success && format) {
265 *format = codec->getFormat();
266 }
267 delete codec;
268 }
269 return success;
270 }
271