blob: cbae8b1721f8cac15a61edf44b36cef306b88850 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkImageDecoder_DEFINED
11#define SkImageDecoder_DEFINED
12
13#include "SkBitmap.h"
14#include "SkRefCnt.h"
15
16class SkStream;
17
18/** \class SkImageDecoder
19
20 Base class for decoding compressed images into a SkBitmap
21*/
22class SkImageDecoder {
23public:
24 virtual ~SkImageDecoder();
weita@google.com25e98342009-05-11 16:06:22 +000025
reed@android.com8a1c16f2008-12-17 15:59:43 +000026 enum Format {
27 kUnknown_Format,
28 kBMP_Format,
29 kGIF_Format,
30 kICO_Format,
31 kJPEG_Format,
32 kPNG_Format,
33 kWBMP_Format,
weita@google.com25e98342009-05-11 16:06:22 +000034
reed@android.com8a1c16f2008-12-17 15:59:43 +000035 kLastKnownFormat = kWBMP_Format
36 };
weita@google.com25e98342009-05-11 16:06:22 +000037
reed@android.com8a1c16f2008-12-17 15:59:43 +000038 /** Return the compressed data's format (see Format enum)
39 */
40 virtual Format getFormat() const;
41
42 /** Returns true if the decoder should try to dither the resulting image.
43 The default setting is true.
44 */
45 bool getDitherImage() const { return fDitherImage; }
weita@google.com25e98342009-05-11 16:06:22 +000046
reed@android.com8a1c16f2008-12-17 15:59:43 +000047 /** Set to true if the the decoder should try to dither the resulting image.
48 The default setting is true.
49 */
50 void setDitherImage(bool dither) { fDitherImage = dither; }
51
52 /** \class Peeker
weita@google.com25e98342009-05-11 16:06:22 +000053
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 Base class for optional callbacks to retrieve meta/chunk data out of
55 an image as it is being decoded.
56 */
57 class Peeker : public SkRefCnt {
58 public:
59 /** Return true to continue decoding, or false to indicate an error, which
60 will cause the decoder to not return the image.
61 */
62 virtual bool peek(const char tag[], const void* data, size_t length) = 0;
63 };
64
65 Peeker* getPeeker() const { return fPeeker; }
66 Peeker* setPeeker(Peeker*);
weita@google.com25e98342009-05-11 16:06:22 +000067
reed@android.com8a1c16f2008-12-17 15:59:43 +000068 /** \class Peeker
weita@google.com25e98342009-05-11 16:06:22 +000069
reed@android.com8a1c16f2008-12-17 15:59:43 +000070 Base class for optional callbacks to retrieve meta/chunk data out of
71 an image as it is being decoded.
72 */
73 class Chooser : public SkRefCnt {
74 public:
75 virtual void begin(int count) {}
76 virtual void inspect(int index, SkBitmap::Config config, int width, int height) {}
77 /** Return the index of the subimage you want, or -1 to choose none of them.
78 */
79 virtual int choose() = 0;
80 };
81
82 Chooser* getChooser() const { return fChooser; }
83 Chooser* setChooser(Chooser*);
84
reed@android.com3f1f06a2010-03-03 21:04:12 +000085 /** This optional table describes the caller's preferred config based on
86 information about the src data. For this table, the src attributes are
87 described in terms of depth (index (8), 16, 32/24) and if there is
88 per-pixel alpha. These inputs combine to create an index into the
89 pref[] table, which contains the caller's preferred config for that
90 input, or kNo_Config if there is no preference.
91
92 To specify no preferrence, call setPrefConfigTable(NULL), which is
93 the default.
94
95 Note, it is still at the discretion of the codec as to what output
96 config is actually returned, as it may not be able to support the
97 caller's preference.
98
99 Here is how the index into the table is computed from the src:
100 depth [8, 16, 32/24] -> 0, 2, 4
101 alpha [no, yes] -> 0, 1
102 The two index values are OR'd together.
103 src: 8-index, no-alpha -> 0
104 src: 8-index, yes-alpha -> 1
105 src: 16bit, no-alpha -> 2 // e.g. 565
106 src: 16bit, yes-alpha -> 3 // e.g. 1555
107 src: 32/24, no-alpha -> 4
108 src: 32/24, yes-alpha -> 5
109 */
110 void setPrefConfigTable(const SkBitmap::Config pref[6]);
111
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112 SkBitmap::Allocator* getAllocator() const { return fAllocator; }
113 SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*);
114
115 // sample-size, if set to > 1, tells the decoder to return a smaller than
116 // original bitmap, sampling 1 pixel for every size pixels. e.g. if sample
117 // size is set to 3, then the returned bitmap will be 1/3 as wide and high,
118 // and will contain 1/9 as many pixels as the original.
119 // Note: this is a hint, and the codec may choose to ignore this, or only
120 // approximate the sample size.
121 int getSampleSize() const { return fSampleSize; }
122 void setSampleSize(int size);
weita@google.com25e98342009-05-11 16:06:22 +0000123
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 /** Reset the sampleSize to its default of 1
125 */
126 void resetSampleSize() { this->setSampleSize(1); }
127
128 /** Decoding is synchronous, but for long decodes, a different thread can
129 call this method safely. This sets a state that the decoders will
130 periodically check, and if they see it changed to cancel, they will
131 cancel. This will result in decode() returning false. However, there is
132 no guarantee that the decoder will see the state change in time, so
133 it is possible that cancelDecode() will be called, but will be ignored
134 and decode() will return true (assuming no other problems were
135 encountered).
weita@google.com25e98342009-05-11 16:06:22 +0000136
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137 This state is automatically reset at the beginning of decode().
138 */
139 void cancelDecode() {
140 // now the subclass must query shouldCancelDecode() to be informed
141 // of the request
142 fShouldCancelDecode = true;
143 }
144
145 /** Passed to the decode method. If kDecodeBounds_Mode is passed, then
146 only the bitmap's width/height/config need be set. If kDecodePixels_Mode
147 is passed, then the bitmap must have pixels or a pixelRef.
148 */
149 enum Mode {
150 kDecodeBounds_Mode, //!< only return width/height/config in bitmap
151 kDecodePixels_Mode //!< return entire bitmap (including pixels)
152 };
weita@google.com25e98342009-05-11 16:06:22 +0000153
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154 /** Given a stream, decode it into the specified bitmap.
155 If the decoder can decompress the image, it calls bitmap.setConfig(),
156 and then if the Mode is kDecodePixels_Mode, call allocPixelRef(),
157 which will allocated a pixelRef. To access the pixel memory, the codec
158 needs to call lockPixels/unlockPixels on the
159 bitmap. It can then set the pixels with the decompressed image.
weita@google.com25e98342009-05-11 16:06:22 +0000160 * If the image cannot be decompressed, return false. After the
161 * decoding, the function converts the decoded config in bitmap
162 * to pref if possible. Whether a conversion is feasible is
163 * tested by Bitmap::canCopyTo(pref).
164
165 note: document use of Allocator, Peeker and Chooser
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166 */
167 bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode);
reed@android.com3f1f06a2010-03-03 21:04:12 +0000168 bool decode(SkStream* stream, SkBitmap* bitmap, Mode mode) {
169 return this->decode(stream, bitmap, SkBitmap::kNo_Config, mode);
170 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171
172 /** Given a stream, this will try to find an appropriate decoder object.
173 If none is found, the method returns NULL.
174 */
175 static SkImageDecoder* Factory(SkStream*);
reed@android.coma14ea0e2009-03-17 17:59:53 +0000176
reed@android.com8a1c16f2008-12-17 15:59:43 +0000177 /** Decode the image stored in the specified file, and store the result
178 in bitmap. Return true for success or false on failure.
179
180 If pref is kNo_Config, then the decoder is free to choose the most natural
181 config given the image data. If pref something other than kNo_Config,
182 the decoder will attempt to decode the image into that format, unless
183 there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
184 config does not support that), in which case the decoder will choose a
185 closest match configuration.
reed@android.com31d1c642009-06-15 18:45:19 +0000186
reed@android.comb3ade9d2009-06-15 13:04:45 +0000187 @param format On success, if format is non-null, it is set to the format
188 of the decoded file. On failure it is ignored.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189 */
190 static bool DecodeFile(const char file[], SkBitmap* bitmap,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000191 SkBitmap::Config prefConfig, Mode,
reed@android.com31d1c642009-06-15 18:45:19 +0000192 Format* format = NULL);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000193 static bool DecodeFile(const char file[], SkBitmap* bitmap) {
194 return DecodeFile(file, bitmap, SkBitmap::kNo_Config,
195 kDecodePixels_Mode, NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196 }
197 /** Decode the image stored in the specified memory buffer, and store the
198 result in bitmap. Return true for success or false on failure.
199
200 If pref is kNo_Config, then the decoder is free to choose the most natural
201 config given the image data. If pref something other than kNo_Config,
202 the decoder will attempt to decode the image into that format, unless
203 there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
204 config does not support that), in which case the decoder will choose a
205 closest match configuration.
reed@android.com31d1c642009-06-15 18:45:19 +0000206
207 @param format On success, if format is non-null, it is set to the format
reed@android.comb3ade9d2009-06-15 13:04:45 +0000208 of the decoded buffer. On failure it is ignored.
209 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000211 SkBitmap::Config prefConfig, Mode,
reed@android.com31d1c642009-06-15 18:45:19 +0000212 Format* format = NULL);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000213 static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap){
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214 return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000215 kDecodePixels_Mode, NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216 }
217 /** Decode the image stored in the specified SkStream, and store the result
218 in bitmap. Return true for success or false on failure.
219
220 If pref is kNo_Config, then the decoder is free to choose the most
221 natural config given the image data. If pref something other than
222 kNo_Config, the decoder will attempt to decode the image into that
223 format, unless there is a conflict (e.g. the image has per-pixel alpha
224 and the bitmap's config does not support that), in which case the
225 decoder will choose a closest match configuration.
reed@android.com31d1c642009-06-15 18:45:19 +0000226
reed@android.comb3ade9d2009-06-15 13:04:45 +0000227 @param format On success, if format is non-null, it is set to the format
228 of the decoded stream. On failure it is ignored.
229 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230 static bool DecodeStream(SkStream* stream, SkBitmap* bitmap,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000231 SkBitmap::Config prefConfig, Mode,
reed@android.com31d1c642009-06-15 18:45:19 +0000232 Format* format = NULL);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000233 static bool DecodeStream(SkStream* stream, SkBitmap* bitmap) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234 return DecodeStream(stream, bitmap, SkBitmap::kNo_Config,
reed@android.comb3ade9d2009-06-15 13:04:45 +0000235 kDecodePixels_Mode, NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 }
weita@google.com25e98342009-05-11 16:06:22 +0000237
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238 /** Return the default config for the running device.
239 Currently this used as a suggestion to image decoders that need to guess
240 what config they should decode into.
241 Default is kNo_Config, but this can be changed with SetDeviceConfig()
242 */
243 static SkBitmap::Config GetDeviceConfig();
244 /** Set the default config for the running device.
245 Currently this used as a suggestion to image decoders that need to guess
246 what config they should decode into.
247 Default is kNo_Config.
248 This can be queried with GetDeviceConfig()
249 */
250 static void SetDeviceConfig(SkBitmap::Config);
251
252 /** @cond UNIT_TEST */
253 SkDEBUGCODE(static void UnitTest();)
254 /** @endcond */
255
256protected:
257 // must be overridden in subclasses. This guy is called by decode(...)
reed@android.com3f1f06a2010-03-03 21:04:12 +0000258 virtual bool onDecode(SkStream*, SkBitmap* bitmap, Mode) = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259
260 /** Can be queried from within onDecode, to see if the user (possibly in
261 a different thread) has requested the decode to cancel. If this returns
262 true, your onDecode() should stop and return false.
263 Each subclass needs to decide how often it can query this, to balance
264 responsiveness with performance.
weita@google.com25e98342009-05-11 16:06:22 +0000265
reed@android.com8a1c16f2008-12-17 15:59:43 +0000266 Calling this outside of onDecode() may return undefined values.
267 */
268
269public:
270 bool shouldCancelDecode() const { return fShouldCancelDecode; }
271
weita@google.com25e98342009-05-11 16:06:22 +0000272protected:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000273 SkImageDecoder();
274
275 // helper function for decoders to handle the (common) case where there is only
276 // once choice available in the image file.
277 bool chooseFromOneChoice(SkBitmap::Config config, int width, int height) const;
278
279 /* Helper for subclasses. Call this to allocate the pixel memory given the bitmap's
280 width/height/rowbytes/config. Returns true on success. This method handles checking
281 for an optional Allocator.
282 */
283 bool allocPixelRef(SkBitmap*, SkColorTable*) const;
284
reed@android.com3f1f06a2010-03-03 21:04:12 +0000285 enum SrcDepth {
286 kIndex_SrcDepth,
287 k16Bit_SrcDepth,
288 k32Bit_SrcDepth
289 };
290 /** The subclass, inside onDecode(), calls this to determine the config of
291 the returned bitmap. SrcDepth and hasAlpha reflect the raw data of the
292 src image. This routine returns the caller's preference given
293 srcDepth and hasAlpha, or kNo_Config if there is no preference.
294
295 Note: this also takes into account GetDeviceConfig(), so the subclass
296 need not call that.
297 */
298 SkBitmap::Config getPrefConfig(SrcDepth, bool hasAlpha) const;
299
reed@android.com8a1c16f2008-12-17 15:59:43 +0000300private:
301 Peeker* fPeeker;
302 Chooser* fChooser;
303 SkBitmap::Allocator* fAllocator;
304 int fSampleSize;
reed@android.com3f1f06a2010-03-03 21:04:12 +0000305 SkBitmap::Config fDefaultPref; // use if fUsePrefTable is false
306 SkBitmap::Config fPrefTable[6]; // use if fUsePrefTable is true
reed@android.com8a1c16f2008-12-17 15:59:43 +0000307 bool fDitherImage;
reed@android.com3f1f06a2010-03-03 21:04:12 +0000308 bool fUsePrefTable;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309 mutable bool fShouldCancelDecode;
310
311 // illegal
312 SkImageDecoder(const SkImageDecoder&);
313 SkImageDecoder& operator=(const SkImageDecoder&);
314};
315
reed@android.coma14ea0e2009-03-17 17:59:53 +0000316/** Calling newDecoder with a stream returns a new matching imagedecoder
317 instance, or NULL if none can be found. The caller must manage its ownership
318 of the stream as usual, calling unref() when it is done, as the returned
319 decoder may have called ref() (and if so, the decoder is responsible for
320 balancing its ownership when it is destroyed).
321 */
322class SkImageDecoderFactory : public SkRefCnt {
323public:
324 virtual SkImageDecoder* newDecoder(SkStream*) = 0;
325};
326
327class SkDefaultImageDecoderFactory : SkImageDecoderFactory {
328public:
329 // calls SkImageDecoder::Factory(stream)
330 virtual SkImageDecoder* newDecoder(SkStream* stream) {
331 return SkImageDecoder::Factory(stream);
332 }
333};
334
335
reed@android.com8a1c16f2008-12-17 15:59:43 +0000336#endif