1
2 /*
3 * Copyright 2006 The Android Open Source Project
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
9
10 #include "SkImageDecoder.h"
11 #include "SkBitmap.h"
12 #include "SkPixelRef.h"
13 #include "SkStream.h"
14 #include "SkTemplates.h"
15 #include "SkCanvas.h"
16
~SkVMMemoryReporter()17 SkVMMemoryReporter::~SkVMMemoryReporter() {
18 }
19
20 const char *SkImageDecoder::kFormatName[] = {
21 "Unknown Format",
22 "BMP",
23 "GIF",
24 "ICO",
25 "JPEG",
26 "PNG",
27 "WBMP",
28 "WEBP",
29 };
30
31 static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
32
GetDeviceConfig()33 SkBitmap::Config SkImageDecoder::GetDeviceConfig()
34 {
35 return gDeviceConfig;
36 }
37
SetDeviceConfig(SkBitmap::Config config)38 void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
39 {
40 gDeviceConfig = config;
41 }
42
43 ///////////////////////////////////////////////////////////////////////////////
44
SkImageDecoder()45 SkImageDecoder::SkImageDecoder()
46 : fReporter(NULL), fPeeker(NULL), fChooser(NULL), fAllocator(NULL),
47 fSampleSize(1), fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
48 fUsePrefTable(false),fPreferQualityOverSpeed(false) {
49 }
50
~SkImageDecoder()51 SkImageDecoder::~SkImageDecoder() {
52 SkSafeUnref(fPeeker);
53 SkSafeUnref(fChooser);
54 SkSafeUnref(fAllocator);
55 SkSafeUnref(fReporter);
56 }
57
getFormat() const58 SkImageDecoder::Format SkImageDecoder::getFormat() const {
59 return kUnknown_Format;
60 }
61
setPeeker(Peeker * peeker)62 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
63 SkRefCnt_SafeAssign(fPeeker, peeker);
64 return peeker;
65 }
66
setChooser(Chooser * chooser)67 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
68 SkRefCnt_SafeAssign(fChooser, chooser);
69 return chooser;
70 }
71
setAllocator(SkBitmap::Allocator * alloc)72 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
73 SkRefCnt_SafeAssign(fAllocator, alloc);
74 return alloc;
75 }
76
setReporter(SkVMMemoryReporter * reporter)77 SkVMMemoryReporter* SkImageDecoder::setReporter(SkVMMemoryReporter* reporter) {
78 SkRefCnt_SafeAssign(fReporter, reporter);
79 return reporter;
80 }
81
setSampleSize(int size)82 void SkImageDecoder::setSampleSize(int size) {
83 if (size < 1) {
84 size = 1;
85 }
86 fSampleSize = size;
87 }
88
chooseFromOneChoice(SkBitmap::Config config,int width,int height) const89 bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
90 int height) const {
91 Chooser* chooser = fChooser;
92
93 if (NULL == chooser) { // no chooser, we just say YES to decoding :)
94 return true;
95 }
96 chooser->begin(1);
97 chooser->inspect(0, config, width, height);
98 return chooser->choose() == 0;
99 }
100
allocPixelRef(SkBitmap * bitmap,SkColorTable * ctable) const101 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
102 SkColorTable* ctable) const {
103 return bitmap->allocPixels(fAllocator, ctable);
104 }
105
106 ///////////////////////////////////////////////////////////////////////////////
107
setPrefConfigTable(const SkBitmap::Config pref[6])108 void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
109 if (NULL == pref) {
110 fUsePrefTable = false;
111 } else {
112 fUsePrefTable = true;
113 memcpy(fPrefTable, pref, sizeof(fPrefTable));
114 }
115 }
116
getPrefConfig(SrcDepth srcDepth,bool srcHasAlpha) const117 SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
118 bool srcHasAlpha) const {
119 SkBitmap::Config config;
120
121 if (fUsePrefTable) {
122 int index = 0;
123 switch (srcDepth) {
124 case kIndex_SrcDepth:
125 index = 0;
126 break;
127 case k16Bit_SrcDepth:
128 index = 2;
129 break;
130 case k32Bit_SrcDepth:
131 index = 4;
132 break;
133 }
134 if (srcHasAlpha) {
135 index += 1;
136 }
137 config = fPrefTable[index];
138 } else {
139 config = fDefaultPref;
140 }
141
142 if (SkBitmap::kNo_Config == config) {
143 config = SkImageDecoder::GetDeviceConfig();
144 }
145 return config;
146 }
147
decode(SkStream * stream,SkBitmap * bm,SkBitmap::Config pref,Mode mode,bool reuseBitmap)148 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
149 SkBitmap::Config pref, Mode mode, bool reuseBitmap) {
150 // pass a temporary bitmap, so that if we return false, we are assured of
151 // leaving the caller's bitmap untouched.
152 SkBitmap tmp;
153
154 // we reset this to false before calling onDecode
155 fShouldCancelDecode = false;
156 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
157 fDefaultPref = pref;
158
159 if (reuseBitmap) {
160 SkAutoLockPixels alp(*bm);
161 if (bm->getPixels() != NULL) {
162 return this->onDecode(stream, bm, mode);
163 }
164 }
165 if (!this->onDecode(stream, &tmp, mode)) {
166 return false;
167 }
168 bm->swap(tmp);
169 return true;
170 }
171
decodeRegion(SkBitmap * bm,SkIRect rect,SkBitmap::Config pref)172 bool SkImageDecoder::decodeRegion(SkBitmap* bm, SkIRect rect,
173 SkBitmap::Config pref) {
174 // we reset this to false before calling onDecodeRegion
175 fShouldCancelDecode = false;
176 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
177 fDefaultPref = pref;
178
179 if (!this->onDecodeRegion(bm, rect)) {
180 return false;
181 }
182 return true;
183 }
184
buildTileIndex(SkStream * stream,int * width,int * height)185 bool SkImageDecoder::buildTileIndex(SkStream* stream,
186 int *width, int *height) {
187 // we reset this to false before calling onBuildTileIndex
188 fShouldCancelDecode = false;
189
190 return this->onBuildTileIndex(stream, width, height);
191 }
192
cropBitmap(SkBitmap * dest,SkBitmap * src,int sampleSize,int destX,int destY,int width,int height,int srcX,int srcY)193 void SkImageDecoder::cropBitmap(SkBitmap *dest, SkBitmap *src,
194 int sampleSize, int destX, int destY,
195 int width, int height, int srcX, int srcY) {
196 int w = width / sampleSize;
197 int h = height / sampleSize;
198 // if the destination has no pixels then we must allocate them.
199 if (dest->isNull()) {
200 dest->setConfig(src->getConfig(), w, h);
201 dest->setIsOpaque(src->isOpaque());
202
203 if (!this->allocPixelRef(dest, NULL)) {
204 SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
205 return;
206 }
207 }
208 // check to see if the destination is large enough to decode the desired
209 // region. If this assert fails we will just draw as much of the source
210 // into the destination that we can.
211 SkASSERT(dest->width() >= w && dest->height() >= h);
212
213 // Set the Src_Mode for the paint to prevent transparency issue in the
214 // dest in the event that the dest was being re-used.
215 SkPaint paint;
216 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
217
218 SkCanvas canvas(*dest);
219 canvas.drawSprite(*src, (srcX - destX) / sampleSize,
220 (srcY - destY) / sampleSize,
221 &paint);
222 }
223
224 ///////////////////////////////////////////////////////////////////////////////
225
DecodeFile(const char file[],SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)226 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
227 SkBitmap::Config pref, Mode mode, Format* format) {
228 SkASSERT(file);
229 SkASSERT(bm);
230
231 SkFILEStream stream(file);
232 if (stream.isValid()) {
233 if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) {
234 bm->pixelRef()->setURI(file);
235 return true;
236 }
237 }
238 return false;
239 }
240
DecodeMemory(const void * buffer,size_t size,SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)241 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
242 SkBitmap::Config pref, Mode mode, Format* format) {
243 if (0 == size) {
244 return false;
245 }
246 SkASSERT(buffer);
247
248 SkMemoryStream stream(buffer, size);
249 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
250 }
251
DecodeStream(SkStream * stream,SkBitmap * bm,SkBitmap::Config pref,Mode mode,Format * format)252 bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
253 SkBitmap::Config pref, Mode mode, Format* format) {
254 SkASSERT(stream);
255 SkASSERT(bm);
256
257 bool success = false;
258 SkImageDecoder* codec = SkImageDecoder::Factory(stream);
259
260 if (NULL != codec) {
261 success = codec->decode(stream, bm, pref, mode);
262 if (success && format) {
263 *format = codec->getFormat();
264 }
265 delete codec;
266 }
267 return success;
268 }
269