• 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     "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