|
1 |
|
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 |
|
9 |
|
10 #ifndef SkImageDecoder_DEFINED |
|
11 #define SkImageDecoder_DEFINED |
|
12 |
|
13 #include "SkBitmap.h" |
|
14 #include "SkImage.h" |
|
15 #include "SkRect.h" |
|
16 #include "SkRefCnt.h" |
|
17 #include "SkTRegistry.h" |
|
18 #include "SkTypes.h" |
|
19 |
|
20 class SkStream; |
|
21 class SkStreamRewindable; |
|
22 |
|
23 /** \class SkImageDecoder |
|
24 |
|
25 Base class for decoding compressed images into a SkBitmap |
|
26 */ |
|
27 class SkImageDecoder : public SkNoncopyable { |
|
28 public: |
|
29 virtual ~SkImageDecoder(); |
|
30 |
|
31 enum Format { |
|
32 kUnknown_Format, |
|
33 kBMP_Format, |
|
34 kGIF_Format, |
|
35 kICO_Format, |
|
36 kJPEG_Format, |
|
37 kPNG_Format, |
|
38 kWBMP_Format, |
|
39 kWEBP_Format, |
|
40 |
|
41 kLastKnownFormat = kWEBP_Format, |
|
42 }; |
|
43 |
|
44 /** Return the format of image this decoder can decode. If this decoder can decode multiple |
|
45 formats, kUnknown_Format will be returned. |
|
46 */ |
|
47 virtual Format getFormat() const; |
|
48 |
|
49 /** Return the format of the SkStreamRewindable or kUnknown_Format if it cannot be determined. |
|
50 Rewinds the stream before returning. |
|
51 */ |
|
52 static Format GetStreamFormat(SkStreamRewindable*); |
|
53 |
|
54 /** Return a readable string of the Format provided. |
|
55 */ |
|
56 static const char* GetFormatName(Format); |
|
57 |
|
58 /** Return a readable string of the value returned by getFormat(). |
|
59 */ |
|
60 const char* getFormatName() const; |
|
61 |
|
62 /** Whether the decoder should skip writing zeroes to output if possible. |
|
63 */ |
|
64 bool getSkipWritingZeroes() const { return fSkipWritingZeroes; } |
|
65 |
|
66 /** Set to true if the decoder should skip writing any zeroes when |
|
67 creating the output image. |
|
68 This is a hint that may not be respected by the decoder. |
|
69 It should only be used if it is known that the memory to write |
|
70 to has already been set to 0; otherwise the resulting image will |
|
71 have garbage. |
|
72 This is ideal for images that contain a lot of completely transparent |
|
73 pixels, but may be a performance hit for an image that has only a |
|
74 few transparent pixels. |
|
75 The default is false. |
|
76 */ |
|
77 void setSkipWritingZeroes(bool skip) { fSkipWritingZeroes = skip; } |
|
78 |
|
79 /** Returns true if the decoder should try to dither the resulting image. |
|
80 The default setting is true. |
|
81 */ |
|
82 bool getDitherImage() const { return fDitherImage; } |
|
83 |
|
84 /** Set to true if the the decoder should try to dither the resulting image. |
|
85 The default setting is true. |
|
86 */ |
|
87 void setDitherImage(bool dither) { fDitherImage = dither; } |
|
88 |
|
89 /** Returns true if the decoder should try to decode the |
|
90 resulting image to a higher quality even at the expense of |
|
91 the decoding speed. |
|
92 */ |
|
93 bool getPreferQualityOverSpeed() const { return fPreferQualityOverSpeed; } |
|
94 |
|
95 /** Set to true if the the decoder should try to decode the |
|
96 resulting image to a higher quality even at the expense of |
|
97 the decoding speed. |
|
98 */ |
|
99 void setPreferQualityOverSpeed(bool qualityOverSpeed) { |
|
100 fPreferQualityOverSpeed = qualityOverSpeed; |
|
101 } |
|
102 |
|
103 /** Set to true to require the decoder to return a bitmap with unpremultiplied |
|
104 colors. The default is false, meaning the resulting bitmap will have its |
|
105 colors premultiplied. |
|
106 NOTE: Passing true to this function may result in a bitmap which cannot |
|
107 be properly used by Skia. |
|
108 */ |
|
109 void setRequireUnpremultipliedColors(bool request) { |
|
110 fRequireUnpremultipliedColors = request; |
|
111 } |
|
112 |
|
113 /** Returns true if the decoder will only return bitmaps with unpremultiplied |
|
114 colors. |
|
115 */ |
|
116 bool getRequireUnpremultipliedColors() const { return fRequireUnpremultipliedColors; } |
|
117 |
|
118 /** \class Peeker |
|
119 |
|
120 Base class for optional callbacks to retrieve meta/chunk data out of |
|
121 an image as it is being decoded. |
|
122 */ |
|
123 class Peeker : public SkRefCnt { |
|
124 public: |
|
125 SK_DECLARE_INST_COUNT(Peeker) |
|
126 |
|
127 /** Return true to continue decoding, or false to indicate an error, which |
|
128 will cause the decoder to not return the image. |
|
129 */ |
|
130 virtual bool peek(const char tag[], const void* data, size_t length) = 0; |
|
131 private: |
|
132 typedef SkRefCnt INHERITED; |
|
133 }; |
|
134 |
|
135 Peeker* getPeeker() const { return fPeeker; } |
|
136 Peeker* setPeeker(Peeker*); |
|
137 |
|
138 /** \class Chooser |
|
139 |
|
140 Base class for optional callbacks to choose an image from a format that |
|
141 contains multiple images. |
|
142 */ |
|
143 class Chooser : public SkRefCnt { |
|
144 public: |
|
145 SK_DECLARE_INST_COUNT(Chooser) |
|
146 |
|
147 virtual void begin(int count) {} |
|
148 virtual void inspect(int index, SkBitmap::Config config, int width, int height) {} |
|
149 /** Return the index of the subimage you want, or -1 to choose none of them. |
|
150 */ |
|
151 virtual int choose() = 0; |
|
152 |
|
153 private: |
|
154 typedef SkRefCnt INHERITED; |
|
155 }; |
|
156 |
|
157 Chooser* getChooser() const { return fChooser; } |
|
158 Chooser* setChooser(Chooser*); |
|
159 |
|
160 /** |
|
161 * Optional table describing the caller's preferred config based on |
|
162 * information about the src data. Each field should be set to the |
|
163 * preferred config for a src described in the name of the field. The |
|
164 * src attributes are described in terms of depth (8-index, |
|
165 * 8bit-grayscale, or 8-bits/component) and whether there is per-pixel |
|
166 * alpha (does not apply to grayscale). If the caller has no preference |
|
167 * for a particular src type, its slot should be set to kNo_Config. |
|
168 * |
|
169 * NOTE ABOUT PREFERRED CONFIGS: |
|
170 * If a config is preferred, either using a pref table or as a parameter |
|
171 * to some flavor of decode, it is still at the discretion of the codec |
|
172 * as to what output config is actually returned, as it may not be able |
|
173 * to support the caller's preference. |
|
174 * |
|
175 * If a bitmap is decoded into SkBitmap::A8_Config, the resulting bitmap |
|
176 * will either be a conversion of the grayscale in the case of a |
|
177 * grayscale source or the alpha channel in the case of a source with |
|
178 * an alpha channel. |
|
179 */ |
|
180 struct PrefConfigTable { |
|
181 SkBitmap::Config fPrefFor_8Index_NoAlpha_src; |
|
182 SkBitmap::Config fPrefFor_8Index_YesAlpha_src; |
|
183 SkBitmap::Config fPrefFor_8Gray_src; |
|
184 SkBitmap::Config fPrefFor_8bpc_NoAlpha_src; |
|
185 SkBitmap::Config fPrefFor_8bpc_YesAlpha_src; |
|
186 }; |
|
187 |
|
188 /** |
|
189 * Set an optional table for specifying the caller's preferred config |
|
190 * based on information about the src data. |
|
191 * |
|
192 * The default is no preference, which will assume the config set by |
|
193 * decode is preferred. |
|
194 */ |
|
195 void setPrefConfigTable(const PrefConfigTable&); |
|
196 |
|
197 /** |
|
198 * Do not use a PrefConfigTable to determine the output config. This |
|
199 * is the default, so there is no need to call unless a PrefConfigTable |
|
200 * was previously set. |
|
201 */ |
|
202 void resetPrefConfigTable() { fUsePrefTable = false; } |
|
203 |
|
204 SkBitmap::Allocator* getAllocator() const { return fAllocator; } |
|
205 SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*); |
|
206 |
|
207 // sample-size, if set to > 1, tells the decoder to return a smaller than |
|
208 // original bitmap, sampling 1 pixel for every size pixels. e.g. if sample |
|
209 // size is set to 3, then the returned bitmap will be 1/3 as wide and high, |
|
210 // and will contain 1/9 as many pixels as the original. |
|
211 // Note: this is a hint, and the codec may choose to ignore this, or only |
|
212 // approximate the sample size. |
|
213 int getSampleSize() const { return fSampleSize; } |
|
214 void setSampleSize(int size); |
|
215 |
|
216 /** Reset the sampleSize to its default of 1 |
|
217 */ |
|
218 void resetSampleSize() { this->setSampleSize(1); } |
|
219 |
|
220 /** Decoding is synchronous, but for long decodes, a different thread can |
|
221 call this method safely. This sets a state that the decoders will |
|
222 periodically check, and if they see it changed to cancel, they will |
|
223 cancel. This will result in decode() returning false. However, there is |
|
224 no guarantee that the decoder will see the state change in time, so |
|
225 it is possible that cancelDecode() will be called, but will be ignored |
|
226 and decode() will return true (assuming no other problems were |
|
227 encountered). |
|
228 |
|
229 This state is automatically reset at the beginning of decode(). |
|
230 */ |
|
231 void cancelDecode() { |
|
232 // now the subclass must query shouldCancelDecode() to be informed |
|
233 // of the request |
|
234 fShouldCancelDecode = true; |
|
235 } |
|
236 |
|
237 /** Passed to the decode method. If kDecodeBounds_Mode is passed, then |
|
238 only the bitmap's width/height/config need be set. If kDecodePixels_Mode |
|
239 is passed, then the bitmap must have pixels or a pixelRef. |
|
240 */ |
|
241 enum Mode { |
|
242 kDecodeBounds_Mode, //!< only return width/height/config in bitmap |
|
243 kDecodePixels_Mode //!< return entire bitmap (including pixels) |
|
244 }; |
|
245 |
|
246 /** Given a stream, decode it into the specified bitmap. |
|
247 If the decoder can decompress the image, it calls bitmap.setConfig(), |
|
248 and then if the Mode is kDecodePixels_Mode, call allocPixelRef(), |
|
249 which will allocated a pixelRef. To access the pixel memory, the codec |
|
250 needs to call lockPixels/unlockPixels on the |
|
251 bitmap. It can then set the pixels with the decompressed image. |
|
252 * If the image cannot be decompressed, return false. After the |
|
253 * decoding, the function converts the decoded config in bitmap |
|
254 * to pref if possible. Whether a conversion is feasible is |
|
255 * tested by Bitmap::canCopyTo(pref). |
|
256 |
|
257 If an SkBitmap::Allocator is installed via setAllocator, it will be |
|
258 used to allocate the pixel memory. A clever allocator can be used |
|
259 to allocate the memory from a cache, volatile memory, or even from |
|
260 an existing bitmap's memory. |
|
261 |
|
262 If a Peeker is installed via setPeeker, it may be used to peek into |
|
263 meta data during the decode. |
|
264 |
|
265 If a Chooser is installed via setChooser, it may be used to select |
|
266 which image to return from a format that contains multiple images. |
|
267 */ |
|
268 bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode); |
|
269 bool decode(SkStream* stream, SkBitmap* bitmap, Mode mode) { |
|
270 return this->decode(stream, bitmap, SkBitmap::kNo_Config, mode); |
|
271 } |
|
272 |
|
273 /** |
|
274 * Given a stream, build an index for doing tile-based decode. |
|
275 * The built index will be saved in the decoder, and the image size will |
|
276 * be returned in width and height. |
|
277 * |
|
278 * Return true for success or false on failure. |
|
279 */ |
|
280 bool buildTileIndex(SkStreamRewindable*, int *width, int *height); |
|
281 |
|
282 /** |
|
283 * Decode a rectangle subset in the image. |
|
284 * The method can only be called after buildTileIndex(). |
|
285 * |
|
286 * Return true for success. |
|
287 * Return false if the index is never built or failing in decoding. |
|
288 */ |
|
289 bool decodeSubset(SkBitmap* bm, const SkIRect& subset, SkBitmap::Config pref); |
|
290 |
|
291 SK_ATTR_DEPRECATED("use decodeSubset() instead") |
|
292 bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect, SkBitmap::Config pref) { |
|
293 return this->decodeSubset(bitmap, rect, pref); |
|
294 } |
|
295 |
|
296 /** Given a stream, this will try to find an appropriate decoder object. |
|
297 If none is found, the method returns NULL. |
|
298 */ |
|
299 static SkImageDecoder* Factory(SkStreamRewindable*); |
|
300 |
|
301 /** Decode the image stored in the specified file, and store the result |
|
302 in bitmap. Return true for success or false on failure. |
|
303 |
|
304 @param prefConfig If the PrefConfigTable is not set, prefer this config. |
|
305 See NOTE ABOUT PREFERRED CONFIGS. |
|
306 |
|
307 @param format On success, if format is non-null, it is set to the format |
|
308 of the decoded file. On failure it is ignored. |
|
309 */ |
|
310 static bool DecodeFile(const char file[], SkBitmap* bitmap, |
|
311 SkBitmap::Config prefConfig, Mode, |
|
312 Format* format = NULL); |
|
313 static bool DecodeFile(const char file[], SkBitmap* bitmap) { |
|
314 return DecodeFile(file, bitmap, SkBitmap::kNo_Config, |
|
315 kDecodePixels_Mode, NULL); |
|
316 } |
|
317 /** Decode the image stored in the specified memory buffer, and store the |
|
318 result in bitmap. Return true for success or false on failure. |
|
319 |
|
320 @param prefConfig If the PrefConfigTable is not set, prefer this config. |
|
321 See NOTE ABOUT PREFERRED CONFIGS. |
|
322 |
|
323 @param format On success, if format is non-null, it is set to the format |
|
324 of the decoded buffer. On failure it is ignored. |
|
325 */ |
|
326 static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap, |
|
327 SkBitmap::Config prefConfig, Mode, |
|
328 Format* format = NULL); |
|
329 static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap){ |
|
330 return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config, |
|
331 kDecodePixels_Mode, NULL); |
|
332 } |
|
333 |
|
334 /** |
|
335 * Struct containing information about a pixel destination. |
|
336 */ |
|
337 struct Target { |
|
338 /** |
|
339 * Pre-allocated memory. |
|
340 */ |
|
341 void* fAddr; |
|
342 |
|
343 /** |
|
344 * Rowbytes of the allocated memory. |
|
345 */ |
|
346 size_t fRowBytes; |
|
347 }; |
|
348 |
|
349 /** Decode the image stored in the specified SkStreamRewindable, and store the result |
|
350 in bitmap. Return true for success or false on failure. |
|
351 |
|
352 @param prefConfig If the PrefConfigTable is not set, prefer this config. |
|
353 See NOTE ABOUT PREFERRED CONFIGS. |
|
354 |
|
355 @param format On success, if format is non-null, it is set to the format |
|
356 of the decoded stream. On failure it is ignored. |
|
357 */ |
|
358 static bool DecodeStream(SkStreamRewindable* stream, SkBitmap* bitmap, |
|
359 SkBitmap::Config prefConfig, Mode, |
|
360 Format* format = NULL); |
|
361 static bool DecodeStream(SkStreamRewindable* stream, SkBitmap* bitmap) { |
|
362 return DecodeStream(stream, bitmap, SkBitmap::kNo_Config, |
|
363 kDecodePixels_Mode, NULL); |
|
364 } |
|
365 |
|
366 /** Return the default config for the running device. |
|
367 Currently this used as a suggestion to image decoders that need to guess |
|
368 what config they should decode into. |
|
369 Default is kNo_Config, but this can be changed with SetDeviceConfig() |
|
370 */ |
|
371 static SkBitmap::Config GetDeviceConfig(); |
|
372 /** Set the default config for the running device. |
|
373 Currently this used as a suggestion to image decoders that need to guess |
|
374 what config they should decode into. |
|
375 Default is kNo_Config. |
|
376 This can be queried with GetDeviceConfig() |
|
377 */ |
|
378 static void SetDeviceConfig(SkBitmap::Config); |
|
379 |
|
380 protected: |
|
381 // must be overridden in subclasses. This guy is called by decode(...) |
|
382 virtual bool onDecode(SkStream*, SkBitmap* bitmap, Mode) = 0; |
|
383 |
|
384 // If the decoder wants to support tiled based decoding, |
|
385 // this method must be overridden. This guy is called by buildTileIndex(...) |
|
386 virtual bool onBuildTileIndex(SkStreamRewindable*, int *width, int *height) { |
|
387 return false; |
|
388 } |
|
389 |
|
390 // If the decoder wants to support tiled based decoding, |
|
391 // this method must be overridden. This guy is called by decodeRegion(...) |
|
392 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) { |
|
393 return false; |
|
394 } |
|
395 |
|
396 /* |
|
397 * Crop a rectangle from the src Bitmap to the dest Bitmap. src and dst are |
|
398 * both sampled by sampleSize from an original Bitmap. |
|
399 * |
|
400 * @param dst the destination bitmap. |
|
401 * @param src the source bitmap that is sampled by sampleSize from the |
|
402 * original bitmap. |
|
403 * @param sampleSize the sample size that src is sampled from the original bitmap. |
|
404 * @param (dstX, dstY) the upper-left point of the dest bitmap in terms of |
|
405 * the coordinate in the original bitmap. |
|
406 * @param (width, height) the width and height of the unsampled dst. |
|
407 * @param (srcX, srcY) the upper-left point of the src bitmap in terms of |
|
408 * the coordinate in the original bitmap. |
|
409 * @return bool Whether or not it succeeded. |
|
410 */ |
|
411 bool cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, |
|
412 int dstX, int dstY, int width, int height, |
|
413 int srcX, int srcY); |
|
414 |
|
415 /** |
|
416 * Copy all fields on this decoder to the other decoder. Used by subclasses |
|
417 * to decode a subimage using a different decoder, but with the same settings. |
|
418 */ |
|
419 void copyFieldsToOther(SkImageDecoder* other); |
|
420 |
|
421 /** |
|
422 * Return the default preference being used by the current or latest call to |
|
423 * decode. |
|
424 */ |
|
425 SkBitmap::Config getDefaultPref() { return fDefaultPref; } |
|
426 |
|
427 /** Can be queried from within onDecode, to see if the user (possibly in |
|
428 a different thread) has requested the decode to cancel. If this returns |
|
429 true, your onDecode() should stop and return false. |
|
430 Each subclass needs to decide how often it can query this, to balance |
|
431 responsiveness with performance. |
|
432 |
|
433 Calling this outside of onDecode() may return undefined values. |
|
434 */ |
|
435 |
|
436 public: |
|
437 bool shouldCancelDecode() const { return fShouldCancelDecode; } |
|
438 |
|
439 protected: |
|
440 SkImageDecoder(); |
|
441 |
|
442 // helper function for decoders to handle the (common) case where there is only |
|
443 // once choice available in the image file. |
|
444 bool chooseFromOneChoice(SkBitmap::Config config, int width, int height) const; |
|
445 |
|
446 /* Helper for subclasses. Call this to allocate the pixel memory given the bitmap's |
|
447 width/height/rowbytes/config. Returns true on success. This method handles checking |
|
448 for an optional Allocator. |
|
449 */ |
|
450 bool allocPixelRef(SkBitmap*, SkColorTable*) const; |
|
451 |
|
452 /** |
|
453 * The raw data of the src image. |
|
454 */ |
|
455 enum SrcDepth { |
|
456 // Color-indexed. |
|
457 kIndex_SrcDepth, |
|
458 // Grayscale in 8 bits. |
|
459 k8BitGray_SrcDepth, |
|
460 // 8 bits per component. Used for 24 bit if there is no alpha. |
|
461 k32Bit_SrcDepth, |
|
462 }; |
|
463 /** The subclass, inside onDecode(), calls this to determine the config of |
|
464 the returned bitmap. SrcDepth and hasAlpha reflect the raw data of the |
|
465 src image. This routine returns the caller's preference given |
|
466 srcDepth and hasAlpha, or kNo_Config if there is no preference. |
|
467 |
|
468 Note: this also takes into account GetDeviceConfig(), so the subclass |
|
469 need not call that. |
|
470 */ |
|
471 SkBitmap::Config getPrefConfig(SrcDepth, bool hasAlpha) const; |
|
472 |
|
473 private: |
|
474 Peeker* fPeeker; |
|
475 Chooser* fChooser; |
|
476 SkBitmap::Allocator* fAllocator; |
|
477 int fSampleSize; |
|
478 SkBitmap::Config fDefaultPref; // use if fUsePrefTable is false |
|
479 PrefConfigTable fPrefTable; // use if fUsePrefTable is true |
|
480 bool fDitherImage; |
|
481 bool fUsePrefTable; |
|
482 bool fSkipWritingZeroes; |
|
483 mutable bool fShouldCancelDecode; |
|
484 bool fPreferQualityOverSpeed; |
|
485 bool fRequireUnpremultipliedColors; |
|
486 }; |
|
487 |
|
488 /** Calling newDecoder with a stream returns a new matching imagedecoder |
|
489 instance, or NULL if none can be found. The caller must manage its ownership |
|
490 of the stream as usual, calling unref() when it is done, as the returned |
|
491 decoder may have called ref() (and if so, the decoder is responsible for |
|
492 balancing its ownership when it is destroyed). |
|
493 */ |
|
494 class SkImageDecoderFactory : public SkRefCnt { |
|
495 public: |
|
496 SK_DECLARE_INST_COUNT(SkImageDecoderFactory) |
|
497 |
|
498 virtual SkImageDecoder* newDecoder(SkStreamRewindable*) = 0; |
|
499 |
|
500 private: |
|
501 typedef SkRefCnt INHERITED; |
|
502 }; |
|
503 |
|
504 class SkDefaultImageDecoderFactory : SkImageDecoderFactory { |
|
505 public: |
|
506 // calls SkImageDecoder::Factory(stream) |
|
507 virtual SkImageDecoder* newDecoder(SkStreamRewindable* stream) { |
|
508 return SkImageDecoder::Factory(stream); |
|
509 } |
|
510 }; |
|
511 |
|
512 // This macro declares a global (i.e., non-class owned) creation entry point |
|
513 // for each decoder (e.g., CreateJPEGImageDecoder) |
|
514 #define DECLARE_DECODER_CREATOR(codec) \ |
|
515 SkImageDecoder *Create ## codec (); |
|
516 |
|
517 // This macro defines the global creation entry point for each decoder. Each |
|
518 // decoder implementation that registers with the decoder factory must call it. |
|
519 #define DEFINE_DECODER_CREATOR(codec) \ |
|
520 SkImageDecoder *Create ## codec () { \ |
|
521 return SkNEW( Sk ## codec ); \ |
|
522 } |
|
523 |
|
524 // All the decoders known by Skia. Note that, depending on the compiler settings, |
|
525 // not all of these will be available |
|
526 DECLARE_DECODER_CREATOR(BMPImageDecoder); |
|
527 DECLARE_DECODER_CREATOR(GIFImageDecoder); |
|
528 DECLARE_DECODER_CREATOR(ICOImageDecoder); |
|
529 DECLARE_DECODER_CREATOR(JPEGImageDecoder); |
|
530 DECLARE_DECODER_CREATOR(PNGImageDecoder); |
|
531 DECLARE_DECODER_CREATOR(WBMPImageDecoder); |
|
532 DECLARE_DECODER_CREATOR(WEBPImageDecoder); |
|
533 |
|
534 |
|
535 // Typedefs to make registering decoder and formatter callbacks easier. |
|
536 // These have to be defined outside SkImageDecoder. :( |
|
537 typedef SkTRegistry<SkImageDecoder*(*)(SkStreamRewindable*)> SkImageDecoder_DecodeReg; |
|
538 typedef SkTRegistry<SkImageDecoder::Format(*)(SkStreamRewindable*)> SkImageDecoder_FormatReg; |
|
539 |
|
540 #endif |