Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / images / SkImageDecoder.cpp
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8
9 #include "SkImageDecoder.h"
10 #include "SkBitmap.h"
11 #include "SkImagePriv.h"
12 #include "SkPixelRef.h"
13 #include "SkStream.h"
14 #include "SkTemplates.h"
15 #include "SkCanvas.h"
16
17 static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
18
19 SkBitmap::Config SkImageDecoder::GetDeviceConfig()
20 {
21     return gDeviceConfig;
22 }
23
24 void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
25 {
26     gDeviceConfig = config;
27 }
28
29 ///////////////////////////////////////////////////////////////////////////////
30
31 SkImageDecoder::SkImageDecoder()
32     : fPeeker(NULL)
33     , fChooser(NULL)
34     , fAllocator(NULL)
35     , fSampleSize(1)
36     , fDefaultPref(SkBitmap::kNo_Config)
37     , fDitherImage(true)
38     , fUsePrefTable(false)
39     , fSkipWritingZeroes(false)
40     , fPreferQualityOverSpeed(false)
41     , fRequireUnpremultipliedColors(false) {
42 }
43
44 SkImageDecoder::~SkImageDecoder() {
45     SkSafeUnref(fPeeker);
46     SkSafeUnref(fChooser);
47     SkSafeUnref(fAllocator);
48 }
49
50 void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
51     if (NULL == other) {
52         return;
53     }
54     other->setPeeker(fPeeker);
55     other->setChooser(fChooser);
56     other->setAllocator(fAllocator);
57     other->setSampleSize(fSampleSize);
58     if (fUsePrefTable) {
59         other->setPrefConfigTable(fPrefTable);
60     } else {
61         other->fDefaultPref = fDefaultPref;
62     }
63     other->setDitherImage(fDitherImage);
64     other->setSkipWritingZeroes(fSkipWritingZeroes);
65     other->setPreferQualityOverSpeed(fPreferQualityOverSpeed);
66     other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors);
67 }
68
69 SkImageDecoder::Format SkImageDecoder::getFormat() const {
70     return kUnknown_Format;
71 }
72
73 const char* SkImageDecoder::getFormatName() const {
74     return GetFormatName(this->getFormat());
75 }
76
77 const char* SkImageDecoder::GetFormatName(Format format) {
78     switch (format) {
79         case kUnknown_Format:
80             return "Unknown Format";
81         case kBMP_Format:
82             return "BMP";
83         case kGIF_Format:
84             return "GIF";
85         case kICO_Format:
86             return "ICO";
87         case kJPEG_Format:
88             return "JPEG";
89         case kPNG_Format:
90             return "PNG";
91         case kWBMP_Format:
92             return "WBMP";
93         case kWEBP_Format:
94             return "WEBP";
95         default:
96             SkDEBUGFAIL("Invalid format type!");
97     }
98     return "Unknown Format";
99 }
100
101 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
102     SkRefCnt_SafeAssign(fPeeker, peeker);
103     return peeker;
104 }
105
106 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
107     SkRefCnt_SafeAssign(fChooser, chooser);
108     return chooser;
109 }
110
111 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
112     SkRefCnt_SafeAssign(fAllocator, alloc);
113     return alloc;
114 }
115
116 void SkImageDecoder::setSampleSize(int size) {
117     if (size < 1) {
118         size = 1;
119     }
120     fSampleSize = size;
121 }
122
123 bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
124                                          int height) const {
125     Chooser* chooser = fChooser;
126
127     if (NULL == chooser) {    // no chooser, we just say YES to decoding :)
128         return true;
129     }
130     chooser->begin(1);
131     chooser->inspect(0, config, width, height);
132     return chooser->choose() == 0;
133 }
134
135 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
136                                    SkColorTable* ctable) const {
137     return bitmap->allocPixels(fAllocator, ctable);
138 }
139
140 ///////////////////////////////////////////////////////////////////////////////
141
142 void SkImageDecoder::setPrefConfigTable(const PrefConfigTable& prefTable) {
143     fUsePrefTable = true;
144     fPrefTable = prefTable;
145 }
146
147 SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
148                                                bool srcHasAlpha) const {
149     SkBitmap::Config config = SkBitmap::kNo_Config;
150
151     if (fUsePrefTable) {
152         switch (srcDepth) {
153             case kIndex_SrcDepth:
154                 config = srcHasAlpha ? fPrefTable.fPrefFor_8Index_YesAlpha_src
155                                      : fPrefTable.fPrefFor_8Index_NoAlpha_src;
156                 break;
157             case k8BitGray_SrcDepth:
158                 config = fPrefTable.fPrefFor_8Gray_src;
159                 break;
160             case k32Bit_SrcDepth:
161                 config = srcHasAlpha ? fPrefTable.fPrefFor_8bpc_YesAlpha_src
162                                      : fPrefTable.fPrefFor_8bpc_NoAlpha_src;
163                 break;
164         }
165     } else {
166         config = fDefaultPref;
167     }
168
169     if (SkBitmap::kNo_Config == config) {
170         config = SkImageDecoder::GetDeviceConfig();
171     }
172     return config;
173 }
174
175 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
176                             SkBitmap::Config pref, Mode mode) {
177     // we reset this to false before calling onDecode
178     fShouldCancelDecode = false;
179     // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
180     fDefaultPref = pref;
181
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     if (!this->onDecode(stream, &tmp, mode)) {
186         return false;
187     }
188     bm->swap(tmp);
189     return true;
190 }
191
192 bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect,
193                                   SkBitmap::Config pref) {
194     // we reset this to false before calling onDecodeSubset
195     fShouldCancelDecode = false;
196     // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
197     fDefaultPref = pref;
198
199     return this->onDecodeSubset(bm, rect);
200 }
201
202 bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream,
203                                     int *width, int *height) {
204     // we reset this to false before calling onBuildTileIndex
205     fShouldCancelDecode = false;
206
207     return this->onBuildTileIndex(stream, width, height);
208 }
209
210 bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
211                                 int dstX, int dstY, int width, int height,
212                                 int srcX, int srcY) {
213     int w = width / sampleSize;
214     int h = height / sampleSize;
215     if (src->config() == SkBitmap::kIndex8_Config) {
216         // kIndex8 does not allow drawing via an SkCanvas, as is done below.
217         // Instead, use extractSubset. Note that this shares the SkPixelRef and
218         // SkColorTable.
219         // FIXME: Since src is discarded in practice, this holds on to more
220         // pixels than is strictly necessary. Switch to a copy if memory
221         // savings are more important than speed here. This also means
222         // that the pixels in dst can not be reused (though there is no
223         // allocation, which was already done on src).
224         int x = (dstX - srcX) / sampleSize;
225         int y = (dstY - srcY) / sampleSize;
226         SkIRect subset = SkIRect::MakeXYWH(x, y, w, h);
227         return src->extractSubset(dst, subset);
228     }
229     // if the destination has no pixels then we must allocate them.
230     if (dst->isNull()) {
231         dst->setConfig(src->config(), w, h, 0, src->alphaType());
232
233         if (!this->allocPixelRef(dst, NULL)) {
234             SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
235             return false;
236         }
237     }
238     // check to see if the destination is large enough to decode the desired
239     // region. If this assert fails we will just draw as much of the source
240     // into the destination that we can.
241     if (dst->width() < w || dst->height() < h) {
242         SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n"));
243     }
244
245     // Set the Src_Mode for the paint to prevent transparency issue in the
246     // dest in the event that the dest was being re-used.
247     SkPaint paint;
248     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
249
250     SkCanvas canvas(*dst);
251     canvas.drawSprite(*src, (srcX - dstX) / sampleSize,
252                             (srcY - dstY) / sampleSize,
253                             &paint);
254     return true;
255 }
256
257 ///////////////////////////////////////////////////////////////////////////////
258
259 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
260                             SkBitmap::Config pref,  Mode mode, Format* format) {
261     SkASSERT(file);
262     SkASSERT(bm);
263
264     SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file));
265     if (stream.get()) {
266         if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
267             bm->pixelRef()->setURI(file);
268             return true;
269         }
270     }
271     return false;
272 }
273
274 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
275                           SkBitmap::Config pref, Mode mode, Format* format) {
276     if (0 == size) {
277         return false;
278     }
279     SkASSERT(buffer);
280
281     SkMemoryStream  stream(buffer, size);
282     return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
283 }
284
285 bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm,
286                                   SkBitmap::Config pref, Mode mode,
287                                   Format* format) {
288     SkASSERT(stream);
289     SkASSERT(bm);
290
291     bool success = false;
292     SkImageDecoder* codec = SkImageDecoder::Factory(stream);
293
294     if (NULL != codec) {
295         success = codec->decode(stream, bm, pref, mode);
296         if (success && format) {
297             *format = codec->getFormat();
298             if (kUnknown_Format == *format) {
299                 if (stream->rewind()) {
300                     *format = GetStreamFormat(stream);
301                 }
302             }
303         }
304         delete codec;
305     }
306     return success;
307 }