• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
23 class SkStream;
24 
25 /** \class SkImageDecoder
26 
27     Base class for decoding compressed images into a SkBitmap
28 */
29 class SkImageDecoder {
30 public:
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     */
getDitherImage()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     */
setDitherImage(bool dither)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 
getPeeker()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:
begin(int count)82         virtual void begin(int count) {}
inspect(int index,SkBitmap::Config config,int width,int height)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 
getChooser()89     Chooser* getChooser() const { return fChooser; }
90     Chooser* setChooser(Chooser*);
91 
getAllocator()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.
getSampleSize()101     int getSampleSize() const { return fSampleSize; }
102     void setSampleSize(int size);
103 
104     /** Reset the sampleSize to its default of 1
105      */
resetSampleSize()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      */
cancelDecode()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. After the
141     *   decoding, the function converts the decoded config in bitmap
142     *   to pref if possible. Whether a conversion is feasible is
143     *   tested by Bitmap::canCopyTo(pref).
144 
145         note: document use of Allocator, Peeker and Chooser
146     */
147     bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode);
148 
149     /** Given a stream, this will try to find an appropriate decoder object.
150         If none is found, the method returns NULL.
151     */
152     static SkImageDecoder* Factory(SkStream*);
153 
154     /** Decode the image stored in the specified file, and store the result
155         in bitmap. Return true for success or false on failure.
156 
157         If pref is kNo_Config, then the decoder is free to choose the most natural
158         config given the image data. If pref something other than kNo_Config,
159         the decoder will attempt to decode the image into that format, unless
160         there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
161         config does not support that), in which case the decoder will choose a
162         closest match configuration.
163 
164         @param format On success, if format is non-null, it is set to the format
165                       of the decoded file. On failure it is ignored.
166     */
167     static bool DecodeFile(const char file[], SkBitmap* bitmap,
168                            SkBitmap::Config prefConfig, Mode,
169                            Format* format = NULL);
DecodeFile(const char file[],SkBitmap * bitmap)170     static bool DecodeFile(const char file[], SkBitmap* bitmap) {
171         return DecodeFile(file, bitmap, SkBitmap::kNo_Config,
172                           kDecodePixels_Mode, NULL);
173     }
174     /** Decode the image stored in the specified memory buffer, and store the
175         result in bitmap. Return true for success or false on failure.
176 
177         If pref is kNo_Config, then the decoder is free to choose the most natural
178         config given the image data. If pref something other than kNo_Config,
179         the decoder will attempt to decode the image into that format, unless
180         there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
181         config does not support that), in which case the decoder will choose a
182         closest match configuration.
183 
184         @param format On success, if format is non-null, it is set to the format
185                        of the decoded buffer. On failure it is ignored.
186      */
187     static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap,
188                              SkBitmap::Config prefConfig, Mode,
189                              Format* format = NULL);
DecodeMemory(const void * buffer,size_t size,SkBitmap * bitmap)190     static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap){
191         return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config,
192                             kDecodePixels_Mode, NULL);
193     }
194     /** Decode the image stored in the specified SkStream, and store the result
195         in bitmap. Return true for success or false on failure.
196 
197         If pref is kNo_Config, then the decoder is free to choose the most
198         natural config given the image data. If pref something other than
199         kNo_Config, the decoder will attempt to decode the image into that
200         format, unless there is a conflict (e.g. the image has per-pixel alpha
201         and the bitmap's config does not support that), in which case the
202         decoder will choose a closest match configuration.
203 
204         @param format On success, if format is non-null, it is set to the format
205                       of the decoded stream. On failure it is ignored.
206      */
207     static bool DecodeStream(SkStream* stream, SkBitmap* bitmap,
208                              SkBitmap::Config prefConfig, Mode,
209                              Format* format = NULL);
DecodeStream(SkStream * stream,SkBitmap * bitmap)210     static bool DecodeStream(SkStream* stream, SkBitmap* bitmap) {
211         return DecodeStream(stream, bitmap, SkBitmap::kNo_Config,
212                             kDecodePixels_Mode, NULL);
213     }
214 
215     /** Return the default config for the running device.
216         Currently this used as a suggestion to image decoders that need to guess
217         what config they should decode into.
218         Default is kNo_Config, but this can be changed with SetDeviceConfig()
219     */
220     static SkBitmap::Config GetDeviceConfig();
221     /** Set the default config for the running device.
222         Currently this used as a suggestion to image decoders that need to guess
223         what config they should decode into.
224         Default is kNo_Config.
225         This can be queried with GetDeviceConfig()
226     */
227     static void SetDeviceConfig(SkBitmap::Config);
228 
229   /** @cond UNIT_TEST */
230     SkDEBUGCODE(static void UnitTest();)
231   /** @endcond */
232 
233 protected:
234     // must be overridden in subclasses. This guy is called by decode(...)
235     virtual bool onDecode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref,
236                           Mode) = 0;
237 
238     /** Can be queried from within onDecode, to see if the user (possibly in
239         a different thread) has requested the decode to cancel. If this returns
240         true, your onDecode() should stop and return false.
241         Each subclass needs to decide how often it can query this, to balance
242         responsiveness with performance.
243 
244         Calling this outside of onDecode() may return undefined values.
245      */
246 
247 public:
shouldCancelDecode()248     bool shouldCancelDecode() const { return fShouldCancelDecode; }
249 
250 protected:
251     SkImageDecoder();
252 
253     // helper function for decoders to handle the (common) case where there is only
254     // once choice available in the image file.
255     bool chooseFromOneChoice(SkBitmap::Config config, int width, int height) const;
256 
257     /*  Helper for subclasses. Call this to allocate the pixel memory given the bitmap's
258         width/height/rowbytes/config. Returns true on success. This method handles checking
259         for an optional Allocator.
260     */
261     bool allocPixelRef(SkBitmap*, SkColorTable*) const;
262 
263 private:
264     Peeker*                 fPeeker;
265     Chooser*                fChooser;
266     SkBitmap::Allocator*    fAllocator;
267     int                     fSampleSize;
268     bool                    fDitherImage;
269     mutable bool            fShouldCancelDecode;
270 
271     // illegal
272     SkImageDecoder(const SkImageDecoder&);
273     SkImageDecoder& operator=(const SkImageDecoder&);
274 };
275 
276 /** Calling newDecoder with a stream returns a new matching imagedecoder
277     instance, or NULL if none can be found. The caller must manage its ownership
278     of the stream as usual, calling unref() when it is done, as the returned
279     decoder may have called ref() (and if so, the decoder is responsible for
280     balancing its ownership when it is destroyed).
281  */
282 class SkImageDecoderFactory : public SkRefCnt {
283 public:
284     virtual SkImageDecoder* newDecoder(SkStream*) = 0;
285 };
286 
287 class SkDefaultImageDecoderFactory : SkImageDecoderFactory {
288 public:
289     // calls SkImageDecoder::Factory(stream)
newDecoder(SkStream * stream)290     virtual SkImageDecoder* newDecoder(SkStream* stream) {
291         return SkImageDecoder::Factory(stream);
292     }
293 };
294 
295 
296 #endif
297