blob: 347a6da58c21f8e0f0fb4ea829c4ad7e5ccb62e1 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/images/SkImageDecoder.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
weita@google.com25e98342009-05-11 16:06:22 +00005** 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
reed@android.com8a1c16f2008-12-17 15:59:43 +00008**
weita@google.com25e98342009-05-11 16:06:22 +00009** http://www.apache.org/licenses/LICENSE-2.0
reed@android.com8a1c16f2008-12-17 15:59:43 +000010**
weita@google.com25e98342009-05-11 16:06:22 +000011** 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
reed@android.com8a1c16f2008-12-17 15:59:43 +000015** 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
24static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
25
26SkBitmap::Config SkImageDecoder::GetDeviceConfig()
27{
28 return gDeviceConfig;
29}
30
31void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
32{
33 gDeviceConfig = config;
34}
35
36///////////////////////////////////////////////////////////////////////////////
37
38SkImageDecoder::SkImageDecoder()
39 : fPeeker(NULL), fChooser(NULL), fAllocator(NULL), fSampleSize(1),
reed@android.com3f1f06a2010-03-03 21:04:12 +000040 fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
41 fUsePrefTable(false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000042}
43
44SkImageDecoder::~SkImageDecoder() {
reed@google.com82065d62011-02-07 15:30:46 +000045 SkSafeUnref(fPeeker);
46 SkSafeUnref(fChooser);
47 SkSafeUnref(fAllocator);
reed@android.com8a1c16f2008-12-17 15:59:43 +000048}
49
50SkImageDecoder::Format SkImageDecoder::getFormat() const {
51 return kUnknown_Format;
52}
53
54SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
55 SkRefCnt_SafeAssign(fPeeker, peeker);
56 return peeker;
57}
58
59SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
60 SkRefCnt_SafeAssign(fChooser, chooser);
61 return chooser;
62}
63
64SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
65 SkRefCnt_SafeAssign(fAllocator, alloc);
66 return alloc;
67}
68
69void SkImageDecoder::setSampleSize(int size) {
70 if (size < 1) {
71 size = 1;
72 }
73 fSampleSize = size;
74}
75
76bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
77 int height) const {
78 Chooser* chooser = fChooser;
79
80 if (NULL == chooser) { // no chooser, we just say YES to decoding :)
81 return true;
82 }
83 chooser->begin(1);
84 chooser->inspect(0, config, width, height);
85 return chooser->choose() == 0;
86}
87
88bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
89 SkColorTable* ctable) const {
90 return bitmap->allocPixels(fAllocator, ctable);
91}
92
93///////////////////////////////////////////////////////////////////////////////
reed@android.comb6137c32009-07-29 20:56:52 +000094
reed@android.com3f1f06a2010-03-03 21:04:12 +000095void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
96 if (NULL == pref) {
97 fUsePrefTable = false;
98 } else {
99 fUsePrefTable = true;
100 memcpy(fPrefTable, pref, sizeof(fPrefTable));
101 }
102}
103
104SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
105 bool srcHasAlpha) const {
106 SkBitmap::Config config;
107
108 if (fUsePrefTable) {
109 int index = 0;
110 switch (srcDepth) {
111 case kIndex_SrcDepth:
112 index = 0;
113 break;
114 case k16Bit_SrcDepth:
115 index = 2;
116 break;
117 case k32Bit_SrcDepth:
118 index = 4;
119 break;
120 }
121 if (srcHasAlpha) {
122 index += 1;
123 }
124 config = fPrefTable[index];
125 } else {
126 config = fDefaultPref;
127 }
128
129 if (SkBitmap::kNo_Config == config) {
130 config = SkImageDecoder::GetDeviceConfig();
131 }
132 return config;
133}
134
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
136 SkBitmap::Config pref, Mode mode) {
reed@android.com62900b42009-02-11 15:07:19 +0000137 // pass a temporary bitmap, so that if we return false, we are assured of
138 // leaving the caller's bitmap untouched.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 SkBitmap tmp;
140
141 // we reset this to false before calling onDecode
142 fShouldCancelDecode = false;
reed@android.com3f1f06a2010-03-03 21:04:12 +0000143 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
144 fDefaultPref = pref;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145
reed@android.com3f1f06a2010-03-03 21:04:12 +0000146 if (!this->onDecode(stream, &tmp, mode)) {
reed@android.com62900b42009-02-11 15:07:19 +0000147 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000148 }
reed@android.com62900b42009-02-11 15:07:19 +0000149 bm->swap(tmp);
150 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151}
152
153///////////////////////////////////////////////////////////////////////////////
154
155bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000156 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157 SkASSERT(file);
158 SkASSERT(bm);
159
160 SkFILEStream stream(file);
161 if (stream.isValid()) {
reed@android.comb3ade9d2009-06-15 13:04:45 +0000162 if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163 bm->pixelRef()->setURI(file);
164 }
165 return true;
166 }
167 return false;
168}
169
170bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000171 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000172 if (0 == size) {
173 return false;
174 }
175 SkASSERT(buffer);
176
177 SkMemoryStream stream(buffer, size);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000178 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179}
180
181bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000182 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183 SkASSERT(stream);
184 SkASSERT(bm);
185
186 bool success = false;
187 SkImageDecoder* codec = SkImageDecoder::Factory(stream);
188
189 if (NULL != codec) {
190 success = codec->decode(stream, bm, pref, mode);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000191 if (success && format) {
192 *format = codec->getFormat();
193 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194 delete codec;
195 }
196 return success;
197}
198