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