• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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