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 };
37
38 static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
39
GetDeviceConfig()40 SkBitmap::Config SkImageDecoder::GetDeviceConfig()
41 {
42 return gDeviceConfig;
43 }
44
SetDeviceConfig(SkBitmap::Config config)45 void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
46 {
47 gDeviceConfig = config;
48 }
49
50 ///////////////////////////////////////////////////////////////////////////////
51
SkImageDecoder()52 SkImageDecoder::SkImageDecoder()
53 : fReporter(NULL), fPeeker(NULL), fChooser(NULL), fAllocator(NULL),
54 fSampleSize(1), fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
55 fUsePrefTable(false) {
56 }
57
~SkImageDecoder()58 SkImageDecoder::~SkImageDecoder() {
59 fPeeker->safeUnref();
60 fChooser->safeUnref();
61 fAllocator->safeUnref();
62 fReporter->safeUnref();
63 }
64
getFormat() const65 SkImageDecoder::Format SkImageDecoder::getFormat() const {
66 return kUnknown_Format;
67 }
68
setPeeker(Peeker * peeker)69 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
70 SkRefCnt_SafeAssign(fPeeker, peeker);
71 return peeker;
72 }
73
setChooser(Chooser * chooser)74 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
75 SkRefCnt_SafeAssign(fChooser, chooser);
76 return chooser;
77 }
78
setAllocator(SkBitmap::Allocator * alloc)79 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
80 SkRefCnt_SafeAssign(fAllocator, alloc);
81 return alloc;
82 }
83
setReporter(SkVMMemoryReporter * reporter)84 SkVMMemoryReporter* SkImageDecoder::setReporter(SkVMMemoryReporter* reporter) {
85 SkRefCnt_SafeAssign(fReporter, reporter);
86 return reporter;
87 }
88
setSampleSize(int size)89 void SkImageDecoder::setSampleSize(int size) {
90 if (size < 1) {
91 size = 1;
92 }
93 fSampleSize = size;
94 }
95
chooseFromOneChoice(SkBitmap::Config config,int width,int height) const96 bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
97 int height) const {
98 Chooser* chooser = fChooser;
99
100 if (NULL == chooser) { // no chooser, we just say YES to decoding :)
101 return true;
102 }
103 chooser->begin(1);
104 chooser->inspect(0, config, width, height);
105 return chooser->choose() == 0;
106 }
107
allocPixelRef(SkBitmap * bitmap,SkColorTable * ctable) const108 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
109 SkColorTable* ctable) const {
110 return bitmap->allocPixels(fAllocator, ctable);
111 }
112
113 ///////////////////////////////////////////////////////////////////////////////
114
setPrefConfigTable(const SkBitmap::Config pref[6])115 void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
116 if (NULL == pref) {
117 fUsePrefTable = false;
118 } else {
119 fUsePrefTable = true;
120 memcpy(fPrefTable, pref, sizeof(fPrefTable));
121 }
122 }
123
getPrefConfig(SrcDepth srcDepth,bool srcHasAlpha) const124 SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
125 bool srcHasAlpha) const {
126 SkBitmap::Config config;
127
128 if (fUsePrefTable) {
129 int index = 0;
130 switch (srcDepth) {
131 case kIndex_SrcDepth:
132 index = 0;
133 break;
134 case k16Bit_SrcDepth:
135 index = 2;
136 break;
137 case k32Bit_SrcDepth:
138 index = 4;
139 break;
140 }
141 if (srcHasAlpha) {
142 index += 1;
143 }
144 config = fPrefTable[index];
145 } else {
146 config = fDefaultPref;
147 }
148
149 if (SkBitmap::kNo_Config == config) {
150 config = SkImageDecoder::GetDeviceConfig();
151 }
152 return config;
153 }
154
decode(SkStream * stream,SkBitmap * bm,SkBitmap::Config pref,Mode mode)155 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
156 SkBitmap::Config pref, Mode mode) {
157 // pass a temporary bitmap, so that if we return false, we are assured of
158 // leaving the caller's bitmap untouched.
159 SkBitmap tmp;
160
161 // we reset this to false before calling onDecode
162 fShouldCancelDecode = false;
163 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
164 fDefaultPref = pref;
165
166 if (!this->onDecode(stream, &tmp, mode)) {
167 return false;
168 }
169 bm->swap(tmp);
170 return true;
171 }
172
decodeRegion(SkBitmap * bm,SkIRect rect,SkBitmap::Config pref)173 bool SkImageDecoder::decodeRegion(SkBitmap* bm, SkIRect rect,
174 SkBitmap::Config pref) {
175 // pass a temporary bitmap, so that if we return false, we are assured of
176 // leaving the caller's bitmap untouched.
177 SkBitmap tmp;
178
179 // we reset this to false before calling onDecodeRegion
180 fShouldCancelDecode = false;
181 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
182 fDefaultPref = pref;
183
184 if (!this->onDecodeRegion(&tmp, rect)) {
185 return false;
186 }
187 bm->swap(tmp);
188 return true;
189 }
190
buildTileIndex(SkStream * stream,int * width,int * height)191 bool SkImageDecoder::buildTileIndex(SkStream* stream,
192 int *width, int *height) {
193 // we reset this to false before calling onBuildTileIndex
194 fShouldCancelDecode = false;
195
196 return this->onBuildTileIndex(stream, width, height);
197 }
198
cropBitmap(SkBitmap * dest,SkBitmap * src,int sampleSize,int destX,int destY,int width,int height,int srcX,int srcY)199 void SkImageDecoder::cropBitmap(SkBitmap *dest, SkBitmap *src,
200 int sampleSize, int destX, int destY,
201 int width, int height, int srcX, int srcY) {
202 int w = width / sampleSize;
203 int h = height / sampleSize;
204 if (w == src->width() && h == src->height() &&
205 (srcX - destX) / sampleSize == 0 && (srcY - destY) / sampleSize == 0) {
206 // The output rect is the same as the decode result
207 dest->swap(*src);
208 return;
209 }
210 dest->setConfig(src->getConfig(), w, h);
211 dest->setIsOpaque(src->isOpaque());
212 this->allocPixelRef(dest, NULL);
213
214 SkCanvas canvas(*dest);
215 canvas.drawBitmap(*src, (srcX - destX) / sampleSize,
216 (srcY - destY) / sampleSize);
217 }
218
219 ///////////////////////////////////////////////////////////////////////////////
220
DecodeFile(const char file[],SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)221 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
222 SkBitmap::Config pref, Mode mode, Format* format) {
223 SkASSERT(file);
224 SkASSERT(bm);
225
226 SkFILEStream stream(file);
227 if (stream.isValid()) {
228 if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) {
229 bm->pixelRef()->setURI(file);
230 }
231 return true;
232 }
233 return false;
234 }
235
DecodeMemory(const void * buffer,size_t size,SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)236 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
237 SkBitmap::Config pref, Mode mode, Format* format) {
238 if (0 == size) {
239 return false;
240 }
241 SkASSERT(buffer);
242
243 SkMemoryStream stream(buffer, size);
244 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
245 }
246
DecodeStream(SkStream * stream,SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)247 bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
248 SkBitmap::Config pref, Mode mode, Format* format) {
249 SkASSERT(stream);
250 SkASSERT(bm);
251
252 bool success = false;
253 SkImageDecoder* codec = SkImageDecoder::Factory(stream);
254
255 if (NULL != codec) {
256 success = codec->decode(stream, bm, pref, mode);
257 if (success && format) {
258 *format = codec->getFormat();
259 }
260 delete codec;
261 }
262 return success;
263 }
264