blob: f3962cf98aa4c76e7f9087f16b8da2871e6d704d [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkImageDecoder.h"
11#include "SkBitmap.h"
12#include "SkPixelRef.h"
13#include "SkStream.h"
14#include "SkTemplates.h"
15
16static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
17
18SkBitmap::Config SkImageDecoder::GetDeviceConfig()
19{
20 return gDeviceConfig;
21}
22
23void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
24{
25 gDeviceConfig = config;
26}
27
28///////////////////////////////////////////////////////////////////////////////
29
30SkImageDecoder::SkImageDecoder()
31 : fPeeker(NULL), fChooser(NULL), fAllocator(NULL), fSampleSize(1),
reed@android.com3f1f06a2010-03-03 21:04:12 +000032 fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
33 fUsePrefTable(false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000034}
35
36SkImageDecoder::~SkImageDecoder() {
reed@google.com82065d62011-02-07 15:30:46 +000037 SkSafeUnref(fPeeker);
38 SkSafeUnref(fChooser);
39 SkSafeUnref(fAllocator);
reed@android.com8a1c16f2008-12-17 15:59:43 +000040}
41
42SkImageDecoder::Format SkImageDecoder::getFormat() const {
43 return kUnknown_Format;
44}
45
46SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
47 SkRefCnt_SafeAssign(fPeeker, peeker);
48 return peeker;
49}
50
51SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
52 SkRefCnt_SafeAssign(fChooser, chooser);
53 return chooser;
54}
55
56SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
57 SkRefCnt_SafeAssign(fAllocator, alloc);
58 return alloc;
59}
60
61void SkImageDecoder::setSampleSize(int size) {
62 if (size < 1) {
63 size = 1;
64 }
65 fSampleSize = size;
66}
67
68bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
69 int height) const {
70 Chooser* chooser = fChooser;
71
72 if (NULL == chooser) { // no chooser, we just say YES to decoding :)
73 return true;
74 }
75 chooser->begin(1);
76 chooser->inspect(0, config, width, height);
77 return chooser->choose() == 0;
78}
79
80bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
81 SkColorTable* ctable) const {
82 return bitmap->allocPixels(fAllocator, ctable);
83}
84
85///////////////////////////////////////////////////////////////////////////////
reed@android.comb6137c32009-07-29 20:56:52 +000086
reed@android.com3f1f06a2010-03-03 21:04:12 +000087void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
88 if (NULL == pref) {
89 fUsePrefTable = false;
90 } else {
91 fUsePrefTable = true;
92 memcpy(fPrefTable, pref, sizeof(fPrefTable));
93 }
94}
95
96SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
97 bool srcHasAlpha) const {
98 SkBitmap::Config config;
99
100 if (fUsePrefTable) {
101 int index = 0;
102 switch (srcDepth) {
103 case kIndex_SrcDepth:
104 index = 0;
105 break;
106 case k16Bit_SrcDepth:
107 index = 2;
108 break;
109 case k32Bit_SrcDepth:
110 index = 4;
111 break;
112 }
113 if (srcHasAlpha) {
114 index += 1;
115 }
116 config = fPrefTable[index];
117 } else {
118 config = fDefaultPref;
119 }
120
121 if (SkBitmap::kNo_Config == config) {
122 config = SkImageDecoder::GetDeviceConfig();
123 }
124 return config;
125}
126
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
128 SkBitmap::Config pref, Mode mode) {
reed@android.com62900b42009-02-11 15:07:19 +0000129 // pass a temporary bitmap, so that if we return false, we are assured of
130 // leaving the caller's bitmap untouched.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131 SkBitmap tmp;
132
133 // we reset this to false before calling onDecode
134 fShouldCancelDecode = false;
reed@android.com3f1f06a2010-03-03 21:04:12 +0000135 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
136 fDefaultPref = pref;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137
reed@android.com3f1f06a2010-03-03 21:04:12 +0000138 if (!this->onDecode(stream, &tmp, mode)) {
reed@android.com62900b42009-02-11 15:07:19 +0000139 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140 }
reed@android.com62900b42009-02-11 15:07:19 +0000141 bm->swap(tmp);
142 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143}
144
145///////////////////////////////////////////////////////////////////////////////
146
147bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000148 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149 SkASSERT(file);
150 SkASSERT(bm);
151
152 SkFILEStream stream(file);
153 if (stream.isValid()) {
reed@android.comb3ade9d2009-06-15 13:04:45 +0000154 if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155 bm->pixelRef()->setURI(file);
156 }
157 return true;
158 }
159 return false;
160}
161
162bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000163 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164 if (0 == size) {
165 return false;
166 }
167 SkASSERT(buffer);
168
169 SkMemoryStream stream(buffer, size);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000170 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171}
172
173bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000174 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175 SkASSERT(stream);
176 SkASSERT(bm);
177
178 bool success = false;
179 SkImageDecoder* codec = SkImageDecoder::Factory(stream);
180
181 if (NULL != codec) {
182 success = codec->decode(stream, bm, pref, mode);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000183 if (success && format) {
184 *format = codec->getFormat();
185 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186 delete codec;
187 }
188 return success;
189}
190