michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #ifndef SkImageDecoder_DEFINED michael@0: #define SkImageDecoder_DEFINED michael@0: michael@0: #include "SkBitmap.h" michael@0: #include "SkImage.h" michael@0: #include "SkRect.h" michael@0: #include "SkRefCnt.h" michael@0: #include "SkTRegistry.h" michael@0: #include "SkTypes.h" michael@0: michael@0: class SkStream; michael@0: class SkStreamRewindable; michael@0: michael@0: /** \class SkImageDecoder michael@0: michael@0: Base class for decoding compressed images into a SkBitmap michael@0: */ michael@0: class SkImageDecoder : public SkNoncopyable { michael@0: public: michael@0: virtual ~SkImageDecoder(); michael@0: michael@0: enum Format { michael@0: kUnknown_Format, michael@0: kBMP_Format, michael@0: kGIF_Format, michael@0: kICO_Format, michael@0: kJPEG_Format, michael@0: kPNG_Format, michael@0: kWBMP_Format, michael@0: kWEBP_Format, michael@0: michael@0: kLastKnownFormat = kWEBP_Format, michael@0: }; michael@0: michael@0: /** Return the format of image this decoder can decode. If this decoder can decode multiple michael@0: formats, kUnknown_Format will be returned. michael@0: */ michael@0: virtual Format getFormat() const; michael@0: michael@0: /** Return the format of the SkStreamRewindable or kUnknown_Format if it cannot be determined. michael@0: Rewinds the stream before returning. michael@0: */ michael@0: static Format GetStreamFormat(SkStreamRewindable*); michael@0: michael@0: /** Return a readable string of the Format provided. michael@0: */ michael@0: static const char* GetFormatName(Format); michael@0: michael@0: /** Return a readable string of the value returned by getFormat(). michael@0: */ michael@0: const char* getFormatName() const; michael@0: michael@0: /** Whether the decoder should skip writing zeroes to output if possible. michael@0: */ michael@0: bool getSkipWritingZeroes() const { return fSkipWritingZeroes; } michael@0: michael@0: /** Set to true if the decoder should skip writing any zeroes when michael@0: creating the output image. michael@0: This is a hint that may not be respected by the decoder. michael@0: It should only be used if it is known that the memory to write michael@0: to has already been set to 0; otherwise the resulting image will michael@0: have garbage. michael@0: This is ideal for images that contain a lot of completely transparent michael@0: pixels, but may be a performance hit for an image that has only a michael@0: few transparent pixels. michael@0: The default is false. michael@0: */ michael@0: void setSkipWritingZeroes(bool skip) { fSkipWritingZeroes = skip; } michael@0: michael@0: /** Returns true if the decoder should try to dither the resulting image. michael@0: The default setting is true. michael@0: */ michael@0: bool getDitherImage() const { return fDitherImage; } michael@0: michael@0: /** Set to true if the the decoder should try to dither the resulting image. michael@0: The default setting is true. michael@0: */ michael@0: void setDitherImage(bool dither) { fDitherImage = dither; } michael@0: michael@0: /** Returns true if the decoder should try to decode the michael@0: resulting image to a higher quality even at the expense of michael@0: the decoding speed. michael@0: */ michael@0: bool getPreferQualityOverSpeed() const { return fPreferQualityOverSpeed; } michael@0: michael@0: /** Set to true if the the decoder should try to decode the michael@0: resulting image to a higher quality even at the expense of michael@0: the decoding speed. michael@0: */ michael@0: void setPreferQualityOverSpeed(bool qualityOverSpeed) { michael@0: fPreferQualityOverSpeed = qualityOverSpeed; michael@0: } michael@0: michael@0: /** Set to true to require the decoder to return a bitmap with unpremultiplied michael@0: colors. The default is false, meaning the resulting bitmap will have its michael@0: colors premultiplied. michael@0: NOTE: Passing true to this function may result in a bitmap which cannot michael@0: be properly used by Skia. michael@0: */ michael@0: void setRequireUnpremultipliedColors(bool request) { michael@0: fRequireUnpremultipliedColors = request; michael@0: } michael@0: michael@0: /** Returns true if the decoder will only return bitmaps with unpremultiplied michael@0: colors. michael@0: */ michael@0: bool getRequireUnpremultipliedColors() const { return fRequireUnpremultipliedColors; } michael@0: michael@0: /** \class Peeker michael@0: michael@0: Base class for optional callbacks to retrieve meta/chunk data out of michael@0: an image as it is being decoded. michael@0: */ michael@0: class Peeker : public SkRefCnt { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(Peeker) michael@0: michael@0: /** Return true to continue decoding, or false to indicate an error, which michael@0: will cause the decoder to not return the image. michael@0: */ michael@0: virtual bool peek(const char tag[], const void* data, size_t length) = 0; michael@0: private: michael@0: typedef SkRefCnt INHERITED; michael@0: }; michael@0: michael@0: Peeker* getPeeker() const { return fPeeker; } michael@0: Peeker* setPeeker(Peeker*); michael@0: michael@0: /** \class Chooser michael@0: michael@0: Base class for optional callbacks to choose an image from a format that michael@0: contains multiple images. michael@0: */ michael@0: class Chooser : public SkRefCnt { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(Chooser) michael@0: michael@0: virtual void begin(int count) {} michael@0: virtual void inspect(int index, SkBitmap::Config config, int width, int height) {} michael@0: /** Return the index of the subimage you want, or -1 to choose none of them. michael@0: */ michael@0: virtual int choose() = 0; michael@0: michael@0: private: michael@0: typedef SkRefCnt INHERITED; michael@0: }; michael@0: michael@0: Chooser* getChooser() const { return fChooser; } michael@0: Chooser* setChooser(Chooser*); michael@0: michael@0: /** michael@0: * Optional table describing the caller's preferred config based on michael@0: * information about the src data. Each field should be set to the michael@0: * preferred config for a src described in the name of the field. The michael@0: * src attributes are described in terms of depth (8-index, michael@0: * 8bit-grayscale, or 8-bits/component) and whether there is per-pixel michael@0: * alpha (does not apply to grayscale). If the caller has no preference michael@0: * for a particular src type, its slot should be set to kNo_Config. michael@0: * michael@0: * NOTE ABOUT PREFERRED CONFIGS: michael@0: * If a config is preferred, either using a pref table or as a parameter michael@0: * to some flavor of decode, it is still at the discretion of the codec michael@0: * as to what output config is actually returned, as it may not be able michael@0: * to support the caller's preference. michael@0: * michael@0: * If a bitmap is decoded into SkBitmap::A8_Config, the resulting bitmap michael@0: * will either be a conversion of the grayscale in the case of a michael@0: * grayscale source or the alpha channel in the case of a source with michael@0: * an alpha channel. michael@0: */ michael@0: struct PrefConfigTable { michael@0: SkBitmap::Config fPrefFor_8Index_NoAlpha_src; michael@0: SkBitmap::Config fPrefFor_8Index_YesAlpha_src; michael@0: SkBitmap::Config fPrefFor_8Gray_src; michael@0: SkBitmap::Config fPrefFor_8bpc_NoAlpha_src; michael@0: SkBitmap::Config fPrefFor_8bpc_YesAlpha_src; michael@0: }; michael@0: michael@0: /** michael@0: * Set an optional table for specifying the caller's preferred config michael@0: * based on information about the src data. michael@0: * michael@0: * The default is no preference, which will assume the config set by michael@0: * decode is preferred. michael@0: */ michael@0: void setPrefConfigTable(const PrefConfigTable&); michael@0: michael@0: /** michael@0: * Do not use a PrefConfigTable to determine the output config. This michael@0: * is the default, so there is no need to call unless a PrefConfigTable michael@0: * was previously set. michael@0: */ michael@0: void resetPrefConfigTable() { fUsePrefTable = false; } michael@0: michael@0: SkBitmap::Allocator* getAllocator() const { return fAllocator; } michael@0: SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*); michael@0: michael@0: // sample-size, if set to > 1, tells the decoder to return a smaller than michael@0: // original bitmap, sampling 1 pixel for every size pixels. e.g. if sample michael@0: // size is set to 3, then the returned bitmap will be 1/3 as wide and high, michael@0: // and will contain 1/9 as many pixels as the original. michael@0: // Note: this is a hint, and the codec may choose to ignore this, or only michael@0: // approximate the sample size. michael@0: int getSampleSize() const { return fSampleSize; } michael@0: void setSampleSize(int size); michael@0: michael@0: /** Reset the sampleSize to its default of 1 michael@0: */ michael@0: void resetSampleSize() { this->setSampleSize(1); } michael@0: michael@0: /** Decoding is synchronous, but for long decodes, a different thread can michael@0: call this method safely. This sets a state that the decoders will michael@0: periodically check, and if they see it changed to cancel, they will michael@0: cancel. This will result in decode() returning false. However, there is michael@0: no guarantee that the decoder will see the state change in time, so michael@0: it is possible that cancelDecode() will be called, but will be ignored michael@0: and decode() will return true (assuming no other problems were michael@0: encountered). michael@0: michael@0: This state is automatically reset at the beginning of decode(). michael@0: */ michael@0: void cancelDecode() { michael@0: // now the subclass must query shouldCancelDecode() to be informed michael@0: // of the request michael@0: fShouldCancelDecode = true; michael@0: } michael@0: michael@0: /** Passed to the decode method. If kDecodeBounds_Mode is passed, then michael@0: only the bitmap's width/height/config need be set. If kDecodePixels_Mode michael@0: is passed, then the bitmap must have pixels or a pixelRef. michael@0: */ michael@0: enum Mode { michael@0: kDecodeBounds_Mode, //!< only return width/height/config in bitmap michael@0: kDecodePixels_Mode //!< return entire bitmap (including pixels) michael@0: }; michael@0: michael@0: /** Given a stream, decode it into the specified bitmap. michael@0: If the decoder can decompress the image, it calls bitmap.setConfig(), michael@0: and then if the Mode is kDecodePixels_Mode, call allocPixelRef(), michael@0: which will allocated a pixelRef. To access the pixel memory, the codec michael@0: needs to call lockPixels/unlockPixels on the michael@0: bitmap. It can then set the pixels with the decompressed image. michael@0: * If the image cannot be decompressed, return false. After the michael@0: * decoding, the function converts the decoded config in bitmap michael@0: * to pref if possible. Whether a conversion is feasible is michael@0: * tested by Bitmap::canCopyTo(pref). michael@0: michael@0: If an SkBitmap::Allocator is installed via setAllocator, it will be michael@0: used to allocate the pixel memory. A clever allocator can be used michael@0: to allocate the memory from a cache, volatile memory, or even from michael@0: an existing bitmap's memory. michael@0: michael@0: If a Peeker is installed via setPeeker, it may be used to peek into michael@0: meta data during the decode. michael@0: michael@0: If a Chooser is installed via setChooser, it may be used to select michael@0: which image to return from a format that contains multiple images. michael@0: */ michael@0: bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode); michael@0: bool decode(SkStream* stream, SkBitmap* bitmap, Mode mode) { michael@0: return this->decode(stream, bitmap, SkBitmap::kNo_Config, mode); michael@0: } michael@0: michael@0: /** michael@0: * Given a stream, build an index for doing tile-based decode. michael@0: * The built index will be saved in the decoder, and the image size will michael@0: * be returned in width and height. michael@0: * michael@0: * Return true for success or false on failure. michael@0: */ michael@0: bool buildTileIndex(SkStreamRewindable*, int *width, int *height); michael@0: michael@0: /** michael@0: * Decode a rectangle subset in the image. michael@0: * The method can only be called after buildTileIndex(). michael@0: * michael@0: * Return true for success. michael@0: * Return false if the index is never built or failing in decoding. michael@0: */ michael@0: bool decodeSubset(SkBitmap* bm, const SkIRect& subset, SkBitmap::Config pref); michael@0: michael@0: SK_ATTR_DEPRECATED("use decodeSubset() instead") michael@0: bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect, SkBitmap::Config pref) { michael@0: return this->decodeSubset(bitmap, rect, pref); michael@0: } michael@0: michael@0: /** Given a stream, this will try to find an appropriate decoder object. michael@0: If none is found, the method returns NULL. michael@0: */ michael@0: static SkImageDecoder* Factory(SkStreamRewindable*); michael@0: michael@0: /** Decode the image stored in the specified file, and store the result michael@0: in bitmap. Return true for success or false on failure. michael@0: michael@0: @param prefConfig If the PrefConfigTable is not set, prefer this config. michael@0: See NOTE ABOUT PREFERRED CONFIGS. michael@0: michael@0: @param format On success, if format is non-null, it is set to the format michael@0: of the decoded file. On failure it is ignored. michael@0: */ michael@0: static bool DecodeFile(const char file[], SkBitmap* bitmap, michael@0: SkBitmap::Config prefConfig, Mode, michael@0: Format* format = NULL); michael@0: static bool DecodeFile(const char file[], SkBitmap* bitmap) { michael@0: return DecodeFile(file, bitmap, SkBitmap::kNo_Config, michael@0: kDecodePixels_Mode, NULL); michael@0: } michael@0: /** Decode the image stored in the specified memory buffer, and store the michael@0: result in bitmap. Return true for success or false on failure. michael@0: michael@0: @param prefConfig If the PrefConfigTable is not set, prefer this config. michael@0: See NOTE ABOUT PREFERRED CONFIGS. michael@0: michael@0: @param format On success, if format is non-null, it is set to the format michael@0: of the decoded buffer. On failure it is ignored. michael@0: */ michael@0: static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap, michael@0: SkBitmap::Config prefConfig, Mode, michael@0: Format* format = NULL); michael@0: static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap){ michael@0: return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config, michael@0: kDecodePixels_Mode, NULL); michael@0: } michael@0: michael@0: /** michael@0: * Struct containing information about a pixel destination. michael@0: */ michael@0: struct Target { michael@0: /** michael@0: * Pre-allocated memory. michael@0: */ michael@0: void* fAddr; michael@0: michael@0: /** michael@0: * Rowbytes of the allocated memory. michael@0: */ michael@0: size_t fRowBytes; michael@0: }; michael@0: michael@0: /** Decode the image stored in the specified SkStreamRewindable, and store the result michael@0: in bitmap. Return true for success or false on failure. michael@0: michael@0: @param prefConfig If the PrefConfigTable is not set, prefer this config. michael@0: See NOTE ABOUT PREFERRED CONFIGS. michael@0: michael@0: @param format On success, if format is non-null, it is set to the format michael@0: of the decoded stream. On failure it is ignored. michael@0: */ michael@0: static bool DecodeStream(SkStreamRewindable* stream, SkBitmap* bitmap, michael@0: SkBitmap::Config prefConfig, Mode, michael@0: Format* format = NULL); michael@0: static bool DecodeStream(SkStreamRewindable* stream, SkBitmap* bitmap) { michael@0: return DecodeStream(stream, bitmap, SkBitmap::kNo_Config, michael@0: kDecodePixels_Mode, NULL); michael@0: } michael@0: michael@0: /** Return the default config for the running device. michael@0: Currently this used as a suggestion to image decoders that need to guess michael@0: what config they should decode into. michael@0: Default is kNo_Config, but this can be changed with SetDeviceConfig() michael@0: */ michael@0: static SkBitmap::Config GetDeviceConfig(); michael@0: /** Set the default config for the running device. michael@0: Currently this used as a suggestion to image decoders that need to guess michael@0: what config they should decode into. michael@0: Default is kNo_Config. michael@0: This can be queried with GetDeviceConfig() michael@0: */ michael@0: static void SetDeviceConfig(SkBitmap::Config); michael@0: michael@0: protected: michael@0: // must be overridden in subclasses. This guy is called by decode(...) michael@0: virtual bool onDecode(SkStream*, SkBitmap* bitmap, Mode) = 0; michael@0: michael@0: // If the decoder wants to support tiled based decoding, michael@0: // this method must be overridden. This guy is called by buildTileIndex(...) michael@0: virtual bool onBuildTileIndex(SkStreamRewindable*, int *width, int *height) { michael@0: return false; michael@0: } michael@0: michael@0: // If the decoder wants to support tiled based decoding, michael@0: // this method must be overridden. This guy is called by decodeRegion(...) michael@0: virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) { michael@0: return false; michael@0: } michael@0: michael@0: /* michael@0: * Crop a rectangle from the src Bitmap to the dest Bitmap. src and dst are michael@0: * both sampled by sampleSize from an original Bitmap. michael@0: * michael@0: * @param dst the destination bitmap. michael@0: * @param src the source bitmap that is sampled by sampleSize from the michael@0: * original bitmap. michael@0: * @param sampleSize the sample size that src is sampled from the original bitmap. michael@0: * @param (dstX, dstY) the upper-left point of the dest bitmap in terms of michael@0: * the coordinate in the original bitmap. michael@0: * @param (width, height) the width and height of the unsampled dst. michael@0: * @param (srcX, srcY) the upper-left point of the src bitmap in terms of michael@0: * the coordinate in the original bitmap. michael@0: * @return bool Whether or not it succeeded. michael@0: */ michael@0: bool cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, michael@0: int dstX, int dstY, int width, int height, michael@0: int srcX, int srcY); michael@0: michael@0: /** michael@0: * Copy all fields on this decoder to the other decoder. Used by subclasses michael@0: * to decode a subimage using a different decoder, but with the same settings. michael@0: */ michael@0: void copyFieldsToOther(SkImageDecoder* other); michael@0: michael@0: /** michael@0: * Return the default preference being used by the current or latest call to michael@0: * decode. michael@0: */ michael@0: SkBitmap::Config getDefaultPref() { return fDefaultPref; } michael@0: michael@0: /** Can be queried from within onDecode, to see if the user (possibly in michael@0: a different thread) has requested the decode to cancel. If this returns michael@0: true, your onDecode() should stop and return false. michael@0: Each subclass needs to decide how often it can query this, to balance michael@0: responsiveness with performance. michael@0: michael@0: Calling this outside of onDecode() may return undefined values. michael@0: */ michael@0: michael@0: public: michael@0: bool shouldCancelDecode() const { return fShouldCancelDecode; } michael@0: michael@0: protected: michael@0: SkImageDecoder(); michael@0: michael@0: // helper function for decoders to handle the (common) case where there is only michael@0: // once choice available in the image file. michael@0: bool chooseFromOneChoice(SkBitmap::Config config, int width, int height) const; michael@0: michael@0: /* Helper for subclasses. Call this to allocate the pixel memory given the bitmap's michael@0: width/height/rowbytes/config. Returns true on success. This method handles checking michael@0: for an optional Allocator. michael@0: */ michael@0: bool allocPixelRef(SkBitmap*, SkColorTable*) const; michael@0: michael@0: /** michael@0: * The raw data of the src image. michael@0: */ michael@0: enum SrcDepth { michael@0: // Color-indexed. michael@0: kIndex_SrcDepth, michael@0: // Grayscale in 8 bits. michael@0: k8BitGray_SrcDepth, michael@0: // 8 bits per component. Used for 24 bit if there is no alpha. michael@0: k32Bit_SrcDepth, michael@0: }; michael@0: /** The subclass, inside onDecode(), calls this to determine the config of michael@0: the returned bitmap. SrcDepth and hasAlpha reflect the raw data of the michael@0: src image. This routine returns the caller's preference given michael@0: srcDepth and hasAlpha, or kNo_Config if there is no preference. michael@0: michael@0: Note: this also takes into account GetDeviceConfig(), so the subclass michael@0: need not call that. michael@0: */ michael@0: SkBitmap::Config getPrefConfig(SrcDepth, bool hasAlpha) const; michael@0: michael@0: private: michael@0: Peeker* fPeeker; michael@0: Chooser* fChooser; michael@0: SkBitmap::Allocator* fAllocator; michael@0: int fSampleSize; michael@0: SkBitmap::Config fDefaultPref; // use if fUsePrefTable is false michael@0: PrefConfigTable fPrefTable; // use if fUsePrefTable is true michael@0: bool fDitherImage; michael@0: bool fUsePrefTable; michael@0: bool fSkipWritingZeroes; michael@0: mutable bool fShouldCancelDecode; michael@0: bool fPreferQualityOverSpeed; michael@0: bool fRequireUnpremultipliedColors; michael@0: }; michael@0: michael@0: /** Calling newDecoder with a stream returns a new matching imagedecoder michael@0: instance, or NULL if none can be found. The caller must manage its ownership michael@0: of the stream as usual, calling unref() when it is done, as the returned michael@0: decoder may have called ref() (and if so, the decoder is responsible for michael@0: balancing its ownership when it is destroyed). michael@0: */ michael@0: class SkImageDecoderFactory : public SkRefCnt { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(SkImageDecoderFactory) michael@0: michael@0: virtual SkImageDecoder* newDecoder(SkStreamRewindable*) = 0; michael@0: michael@0: private: michael@0: typedef SkRefCnt INHERITED; michael@0: }; michael@0: michael@0: class SkDefaultImageDecoderFactory : SkImageDecoderFactory { michael@0: public: michael@0: // calls SkImageDecoder::Factory(stream) michael@0: virtual SkImageDecoder* newDecoder(SkStreamRewindable* stream) { michael@0: return SkImageDecoder::Factory(stream); michael@0: } michael@0: }; michael@0: michael@0: // This macro declares a global (i.e., non-class owned) creation entry point michael@0: // for each decoder (e.g., CreateJPEGImageDecoder) michael@0: #define DECLARE_DECODER_CREATOR(codec) \ michael@0: SkImageDecoder *Create ## codec (); michael@0: michael@0: // This macro defines the global creation entry point for each decoder. Each michael@0: // decoder implementation that registers with the decoder factory must call it. michael@0: #define DEFINE_DECODER_CREATOR(codec) \ michael@0: SkImageDecoder *Create ## codec () { \ michael@0: return SkNEW( Sk ## codec ); \ michael@0: } michael@0: michael@0: // All the decoders known by Skia. Note that, depending on the compiler settings, michael@0: // not all of these will be available michael@0: DECLARE_DECODER_CREATOR(BMPImageDecoder); michael@0: DECLARE_DECODER_CREATOR(GIFImageDecoder); michael@0: DECLARE_DECODER_CREATOR(ICOImageDecoder); michael@0: DECLARE_DECODER_CREATOR(JPEGImageDecoder); michael@0: DECLARE_DECODER_CREATOR(PNGImageDecoder); michael@0: DECLARE_DECODER_CREATOR(WBMPImageDecoder); michael@0: DECLARE_DECODER_CREATOR(WEBPImageDecoder); michael@0: michael@0: michael@0: // Typedefs to make registering decoder and formatter callbacks easier. michael@0: // These have to be defined outside SkImageDecoder. :( michael@0: typedef SkTRegistry SkImageDecoder_DecodeReg; michael@0: typedef SkTRegistry SkImageDecoder_FormatReg; michael@0: michael@0: #endif