blob: 4a18cab5946332b1caa9774ee72847c7946709c0 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkImageDecoder_DEFINED
18#define SkImageDecoder_DEFINED
19
20#include "SkBitmap.h"
21#include "SkRefCnt.h"
22
23class SkStream;
24
25/** \class SkImageDecoder
26
27 Base class for decoding compressed images into a SkBitmap
28*/
29class SkImageDecoder {
30public:
31 virtual ~SkImageDecoder();
32
33 enum Format {
34 kUnknown_Format,
35 kBMP_Format,
36 kGIF_Format,
37 kICO_Format,
38 kJPEG_Format,
39 kPNG_Format,
40 kWBMP_Format,
41
42 kLastKnownFormat = kWBMP_Format
43 };
44
45 /** Return the compressed data's format (see Format enum)
46 */
47 virtual Format getFormat() const;
48
49 /** Returns true if the decoder should try to dither the resulting image.
50 The default setting is true.
51 */
52 bool getDitherImage() const { return fDitherImage; }
53
54 /** Set to true if the the decoder should try to dither the resulting image.
55 The default setting is true.
56 */
57 void setDitherImage(bool dither) { fDitherImage = dither; }
58
59 /** \class Peeker
60
61 Base class for optional callbacks to retrieve meta/chunk data out of
62 an image as it is being decoded.
63 */
64 class Peeker : public SkRefCnt {
65 public:
66 /** Return true to continue decoding, or false to indicate an error, which
67 will cause the decoder to not return the image.
68 */
69 virtual bool peek(const char tag[], const void* data, size_t length) = 0;
70 };
71
72 Peeker* getPeeker() const { return fPeeker; }
73 Peeker* setPeeker(Peeker*);
74
75 /** \class Peeker
76
77 Base class for optional callbacks to retrieve meta/chunk data out of
78 an image as it is being decoded.
79 */
80 class Chooser : public SkRefCnt {
81 public:
82 virtual void begin(int count) {}
83 virtual void inspect(int index, SkBitmap::Config config, int width, int height) {}
84 /** Return the index of the subimage you want, or -1 to choose none of them.
85 */
86 virtual int choose() = 0;
87 };
88
89 Chooser* getChooser() const { return fChooser; }
90 Chooser* setChooser(Chooser*);
91
92 SkBitmap::Allocator* getAllocator() const { return fAllocator; }
93 SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*);
94
95 // sample-size, if set to > 1, tells the decoder to return a smaller than
96 // original bitmap, sampling 1 pixel for every size pixels. e.g. if sample
97 // size is set to 3, then the returned bitmap will be 1/3 as wide and high,
98 // and will contain 1/9 as many pixels as the original.
99 // Note: this is a hint, and the codec may choose to ignore this, or only
100 // approximate the sample size.
101 int getSampleSize() const { return fSampleSize; }
102 void setSampleSize(int size);
103
104 /** Reset the sampleSize to its default of 1
105 */
106 void resetSampleSize() { this->setSampleSize(1); }
107
108 /** Decoding is synchronous, but for long decodes, a different thread can
109 call this method safely. This sets a state that the decoders will
110 periodically check, and if they see it changed to cancel, they will
111 cancel. This will result in decode() returning false. However, there is
112 no guarantee that the decoder will see the state change in time, so
113 it is possible that cancelDecode() will be called, but will be ignored
114 and decode() will return true (assuming no other problems were
115 encountered).
116
117 This state is automatically reset at the beginning of decode().
118 */
119 void cancelDecode() {
120 // now the subclass must query shouldCancelDecode() to be informed
121 // of the request
122 fShouldCancelDecode = true;
123 }
124
125 /** Passed to the decode method. If kDecodeBounds_Mode is passed, then
126 only the bitmap's width/height/config need be set. If kDecodePixels_Mode
127 is passed, then the bitmap must have pixels or a pixelRef.
128 */
129 enum Mode {
130 kDecodeBounds_Mode, //!< only return width/height/config in bitmap
131 kDecodePixels_Mode //!< return entire bitmap (including pixels)
132 };
133
134 /** Given a stream, decode it into the specified bitmap.
135 If the decoder can decompress the image, it calls bitmap.setConfig(),
136 and then if the Mode is kDecodePixels_Mode, call allocPixelRef(),
137 which will allocated a pixelRef. To access the pixel memory, the codec
138 needs to call lockPixels/unlockPixels on the
139 bitmap. It can then set the pixels with the decompressed image.
140 If the image cannot be decompressed, return false.
141
142 note: document use of Allocator, Peeker and Chooser
143 */
144 bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode);
145
146 /** Given a stream, this will try to find an appropriate decoder object.
147 If none is found, the method returns NULL.
148 */
149 static SkImageDecoder* Factory(SkStream*);
150
151 /** Decode the image stored in the specified file, and store the result
152 in bitmap. Return true for success or false on failure.
153
154 If pref is kNo_Config, then the decoder is free to choose the most natural
155 config given the image data. If pref something other than kNo_Config,
156 the decoder will attempt to decode the image into that format, unless
157 there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
158 config does not support that), in which case the decoder will choose a
159 closest match configuration.
160 */
161 static bool DecodeFile(const char file[], SkBitmap* bitmap,
162 SkBitmap::Config prefConfig, Mode);
163 static bool DecodeFile(const char file[], SkBitmap* bitmap)
164 {
165 return DecodeFile(file, bitmap, SkBitmap::kNo_Config, kDecodePixels_Mode);
166 }
167 /** Decode the image stored in the specified memory buffer, and store the
168 result in bitmap. Return true for success or false on failure.
169
170 If pref is kNo_Config, then the decoder is free to choose the most natural
171 config given the image data. If pref something other than kNo_Config,
172 the decoder will attempt to decode the image into that format, unless
173 there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
174 config does not support that), in which case the decoder will choose a
175 closest match configuration.
176 */
177 static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap,
178 SkBitmap::Config prefConfig, Mode);
179 static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap)
180 {
181 return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config,
182 kDecodePixels_Mode);
183 }
184 /** Decode the image stored in the specified SkStream, and store the result
185 in bitmap. Return true for success or false on failure.
186
187 If pref is kNo_Config, then the decoder is free to choose the most
188 natural config given the image data. If pref something other than
189 kNo_Config, the decoder will attempt to decode the image into that
190 format, unless there is a conflict (e.g. the image has per-pixel alpha
191 and the bitmap's config does not support that), in which case the
192 decoder will choose a closest match configuration.
193 */
194 static bool DecodeStream(SkStream* stream, SkBitmap* bitmap,
195 SkBitmap::Config prefConfig, Mode);
196 static bool DecodeStream(SkStream* stream, SkBitmap* bitmap)
197 {
198 return DecodeStream(stream, bitmap, SkBitmap::kNo_Config,
199 kDecodePixels_Mode);
200 }
201
202 /* Given a format, return true if there is a currently installed decoder
203 for that format. Since a given build may not include all codecs (to save
204 code-size), this may return false.
205 */
206 static bool SupportsFormat(Format);
207
208 /** Return the default config for the running device.
209 Currently this used as a suggestion to image decoders that need to guess
210 what config they should decode into.
211 Default is kNo_Config, but this can be changed with SetDeviceConfig()
212 */
213 static SkBitmap::Config GetDeviceConfig();
214 /** Set the default config for the running device.
215 Currently this used as a suggestion to image decoders that need to guess
216 what config they should decode into.
217 Default is kNo_Config.
218 This can be queried with GetDeviceConfig()
219 */
220 static void SetDeviceConfig(SkBitmap::Config);
221
222 /** @cond UNIT_TEST */
223 SkDEBUGCODE(static void UnitTest();)
224 /** @endcond */
225
226protected:
227 // must be overridden in subclasses. This guy is called by decode(...)
228 virtual bool onDecode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref,
229 Mode) = 0;
230
231 /** Can be queried from within onDecode, to see if the user (possibly in
232 a different thread) has requested the decode to cancel. If this returns
233 true, your onDecode() should stop and return false.
234 Each subclass needs to decide how often it can query this, to balance
235 responsiveness with performance.
236
237 Calling this outside of onDecode() may return undefined values.
238 */
239
240public:
241 bool shouldCancelDecode() const { return fShouldCancelDecode; }
242
243protected:
244 SkImageDecoder();
245
246 // helper function for decoders to handle the (common) case where there is only
247 // once choice available in the image file.
248 bool chooseFromOneChoice(SkBitmap::Config config, int width, int height) const;
249
250 /* Helper for subclasses. Call this to allocate the pixel memory given the bitmap's
251 width/height/rowbytes/config. Returns true on success. This method handles checking
252 for an optional Allocator.
253 */
254 bool allocPixelRef(SkBitmap*, SkColorTable*) const;
255
256private:
257 Peeker* fPeeker;
258 Chooser* fChooser;
259 SkBitmap::Allocator* fAllocator;
260 int fSampleSize;
261 bool fDitherImage;
262 mutable bool fShouldCancelDecode;
263
264 // illegal
265 SkImageDecoder(const SkImageDecoder&);
266 SkImageDecoder& operator=(const SkImageDecoder&);
267};
268
269#ifdef SK_SUPPORT_IMAGE_ENCODE
270
271class SkWStream;
272
273class SkImageEncoder {
274public:
275 enum Type {
276 kJPEG_Type,
277 kPNG_Type
278 };
279 static SkImageEncoder* Create(Type);
280
281 virtual ~SkImageEncoder();
282
283 /* Quality ranges from 0..100 */
284
285 bool encodeFile(const char file[], const SkBitmap&, int quality = 80);
286 bool encodeStream(SkWStream*, const SkBitmap&, int quality = 80);
287
288 static bool EncodeFile(const char file[], const SkBitmap&, Type,
289 int quality = 80);
290 static bool EncodeStream(SkWStream*, const SkBitmap&, Type,
291 int quality = 80);
292
293protected:
294 virtual bool onEncode(SkWStream*, const SkBitmap&, int quality) = 0;
295};
296
297#endif /* SK_SUPPORT_IMAGE_ENCODE */
298
299///////////////////////////////////////////////////////////////////////
300
301#endif