blob: 2980896ddbb365b754c41e057f0b90ea611b1773 [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
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000016SK_DEFINE_INST_COUNT(SkImageDecoder::Peeker)
17SK_DEFINE_INST_COUNT(SkImageDecoder::Chooser)
18SK_DEFINE_INST_COUNT(SkImageDecoderFactory)
19
reed@android.com8a1c16f2008-12-17 15:59:43 +000020static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
21
22SkBitmap::Config SkImageDecoder::GetDeviceConfig()
23{
24 return gDeviceConfig;
25}
26
27void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
28{
29 gDeviceConfig = config;
30}
31
32///////////////////////////////////////////////////////////////////////////////
33
34SkImageDecoder::SkImageDecoder()
35 : fPeeker(NULL), fChooser(NULL), fAllocator(NULL), fSampleSize(1),
reed@android.com3f1f06a2010-03-03 21:04:12 +000036 fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
37 fUsePrefTable(false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000038}
39
40SkImageDecoder::~SkImageDecoder() {
reed@google.com82065d62011-02-07 15:30:46 +000041 SkSafeUnref(fPeeker);
42 SkSafeUnref(fChooser);
43 SkSafeUnref(fAllocator);
reed@android.com8a1c16f2008-12-17 15:59:43 +000044}
45
46SkImageDecoder::Format SkImageDecoder::getFormat() const {
47 return kUnknown_Format;
48}
49
50SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
51 SkRefCnt_SafeAssign(fPeeker, peeker);
52 return peeker;
53}
54
55SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
56 SkRefCnt_SafeAssign(fChooser, chooser);
57 return chooser;
58}
59
60SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
61 SkRefCnt_SafeAssign(fAllocator, alloc);
62 return alloc;
63}
64
65void SkImageDecoder::setSampleSize(int size) {
66 if (size < 1) {
67 size = 1;
68 }
69 fSampleSize = size;
70}
71
72bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
73 int height) const {
74 Chooser* chooser = fChooser;
75
76 if (NULL == chooser) { // no chooser, we just say YES to decoding :)
77 return true;
78 }
79 chooser->begin(1);
80 chooser->inspect(0, config, width, height);
81 return chooser->choose() == 0;
82}
83
84bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
85 SkColorTable* ctable) const {
86 return bitmap->allocPixels(fAllocator, ctable);
87}
88
89///////////////////////////////////////////////////////////////////////////////
reed@android.comb6137c32009-07-29 20:56:52 +000090
reed@android.com3f1f06a2010-03-03 21:04:12 +000091void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
92 if (NULL == pref) {
93 fUsePrefTable = false;
94 } else {
95 fUsePrefTable = true;
96 memcpy(fPrefTable, pref, sizeof(fPrefTable));
97 }
98}
99
100SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
101 bool srcHasAlpha) const {
102 SkBitmap::Config config;
103
104 if (fUsePrefTable) {
105 int index = 0;
106 switch (srcDepth) {
107 case kIndex_SrcDepth:
108 index = 0;
109 break;
110 case k16Bit_SrcDepth:
111 index = 2;
112 break;
113 case k32Bit_SrcDepth:
114 index = 4;
115 break;
116 }
117 if (srcHasAlpha) {
118 index += 1;
119 }
120 config = fPrefTable[index];
121 } else {
122 config = fDefaultPref;
123 }
124
125 if (SkBitmap::kNo_Config == config) {
126 config = SkImageDecoder::GetDeviceConfig();
127 }
128 return config;
129}
130
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
132 SkBitmap::Config pref, Mode mode) {
reed@android.com62900b42009-02-11 15:07:19 +0000133 // pass a temporary bitmap, so that if we return false, we are assured of
134 // leaving the caller's bitmap untouched.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135 SkBitmap tmp;
136
137 // we reset this to false before calling onDecode
138 fShouldCancelDecode = false;
reed@android.com3f1f06a2010-03-03 21:04:12 +0000139 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
140 fDefaultPref = pref;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141
reed@android.com3f1f06a2010-03-03 21:04:12 +0000142 if (!this->onDecode(stream, &tmp, mode)) {
reed@android.com62900b42009-02-11 15:07:19 +0000143 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144 }
reed@android.com62900b42009-02-11 15:07:19 +0000145 bm->swap(tmp);
146 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147}
148
149///////////////////////////////////////////////////////////////////////////////
150
151bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000152 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153 SkASSERT(file);
154 SkASSERT(bm);
155
156 SkFILEStream stream(file);
157 if (stream.isValid()) {
reed@android.comb3ade9d2009-06-15 13:04:45 +0000158 if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000159 bm->pixelRef()->setURI(file);
tomhudson@google.com1a366212012-01-03 14:42:08 +0000160 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000161 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162 }
163 return false;
164}
165
166bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000167 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 if (0 == size) {
169 return false;
170 }
171 SkASSERT(buffer);
172
173 SkMemoryStream stream(buffer, size);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000174 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175}
176
177bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000178 SkBitmap::Config pref, Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 SkASSERT(stream);
180 SkASSERT(bm);
181
182 bool success = false;
183 SkImageDecoder* codec = SkImageDecoder::Factory(stream);
184
185 if (NULL != codec) {
186 success = codec->decode(stream, bm, pref, mode);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000187 if (success && format) {
188 *format = codec->getFormat();
189 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190 delete codec;
191 }
192 return success;
193}
194