| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkCodec.h" |
| #include "SkColorTable.h" |
| #include "SkImageInfo.h" |
| #include "SkSwizzler.h" |
| |
| #include "gif_lib.h" |
| |
| /* |
| * |
| * This class implements the decoding for gif images |
| * |
| */ |
| class SkGifCodec : public SkCodec { |
| public: |
| static bool IsGif(const void*, size_t); |
| |
| /* |
| * Assumes IsGif was called and returned true |
| * Creates a gif decoder |
| * Reads enough of the stream to determine the image format |
| */ |
| static SkCodec* NewFromStream(SkStream*); |
| |
| protected: |
| |
| /* |
| * Read enough of the stream to initialize the SkGifCodec. |
| * Returns a bool representing success or failure. |
| * |
| * @param codecOut |
| * If it returned true, and codecOut was not nullptr, |
| * codecOut will be set to a new SkGifCodec. |
| * |
| * @param gifOut |
| * If it returned true, and codecOut was nullptr, |
| * gifOut must be non-nullptr and gifOut will be set to a new |
| * GifFileType pointer. |
| * |
| * @param stream |
| * Deleted on failure. |
| * codecOut will take ownership of it in the case where we created a codec. |
| * Ownership is unchanged when we returned a gifOut. |
| * |
| */ |
| static bool ReadHeader(SkStream* stream, SkCodec** codecOut, |
| GifFileType** gifOut); |
| |
| /* |
| * Performs the full gif decode |
| */ |
| Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, |
| SkPMColor*, int*, int*) override; |
| |
| SkEncodedFormat onGetEncodedFormat() const override { |
| return kGIF_SkEncodedFormat; |
| } |
| |
| bool onRewind() override; |
| |
| uint32_t onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const override; |
| |
| int onOutputScanline(int inputScanline) const override; |
| |
| private: |
| |
| /* |
| * A gif can contain multiple image frames. We will only decode the first |
| * frame. This function reads up to the first image frame, processing |
| * transparency and/or animation information that comes before the image |
| * data. |
| * |
| * @param gif Pointer to the library type that manages the gif decode |
| * @param transIndex This call will set the transparent index based on the |
| * extension data. |
| */ |
| static Result ReadUpToFirstImage(GifFileType* gif, uint32_t* transIndex); |
| |
| /* |
| * A gif may contain many image frames, all of different sizes. |
| * This function checks if the gif dimensions are valid, based on the frame |
| * dimensions, and corrects the gif dimensions if necessary. |
| * |
| * @param gif Pointer to the library type that manages the gif decode |
| * @param size Size of the image that we will decode. |
| * Will be set by this function if the return value is true. |
| * @param frameRect Contains the dimenions and offset of the first image frame. |
| * Will be set by this function if the return value is true. |
| * |
| * @return true on success, false otherwise |
| */ |
| static bool GetDimensions(GifFileType* gif, SkISize* size, SkIRect* frameRect); |
| |
| /* |
| * Initializes the color table that we will use for decoding. |
| * |
| * @param dstInfo Contains the requested dst color type. |
| * @param inputColorPtr Copies the encoded color table to the client's |
| * input color table if the client requests kIndex8. |
| * @param inputColorCount If the client requests kIndex8, sets |
| * inputColorCount to 256. Since gifs always |
| * contain 8-bit indices, we need a 256 entry color |
| * table to ensure that indexing is always in |
| * bounds. |
| */ |
| void initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* colorPtr, |
| int* inputColorCount); |
| |
| /* |
| * Checks for invalid inputs and calls setFrameDimensions(), and |
| * initializeColorTable() in the proper sequence. |
| */ |
| Result prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr, |
| int* inputColorCount, const Options& opts); |
| |
| /* |
| * Initializes the swizzler. |
| * |
| * @param dstInfo Output image information. Dimensions may have been |
| * adjusted if the image frame size does not match the size |
| * indicated in the header. |
| * @param options Informs the swizzler if destination memory is zero initialized. |
| * Contains subset information. |
| */ |
| Result initializeSwizzler(const SkImageInfo& dstInfo, |
| const Options& options); |
| |
| SkSampler* getSampler(bool createIfNecessary) override { |
| SkASSERT(fSwizzler); |
| return fSwizzler; |
| } |
| |
| /* |
| * @return true if the read is successful and false if the read fails. |
| */ |
| bool readRow(); |
| |
| Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opts, |
| SkPMColor inputColorPtr[], int* inputColorCount) override; |
| |
| int onGetScanlines(void* dst, int count, size_t rowBytes) override; |
| |
| bool onSkipScanlines(int count) override; |
| |
| /* |
| * For a scanline decode of "count" lines, this function indicates how |
| * many of the "count" lines should be skipped until we reach the top of |
| * the image frame and how many of the "count" lines are actually inside |
| * the image frame. |
| * |
| * @param count The number of scanlines requested. |
| * @param rowsBeforeFrame Output variable. The number of lines before |
| * we reach the top of the image frame. |
| * @param rowsInFrame Output variable. The number of lines to decode |
| * inside the image frame. |
| */ |
| void handleScanlineFrame(int count, int* rowsBeforeFrame, int* rowsInFrame); |
| |
| SkScanlineOrder onGetScanlineOrder() const override; |
| |
| /* |
| * This function cleans up the gif object after the decode completes |
| * It is used in a SkAutoTCallIProc template |
| */ |
| static void CloseGif(GifFileType* gif); |
| |
| /* |
| * Frees any extension data used in the decode |
| * Used in a SkAutoTCallVProc |
| */ |
| static void FreeExtension(SavedImage* image); |
| |
| /* |
| * Creates an instance of the decoder |
| * Called only by NewFromStream |
| * |
| * @param srcInfo contains the source width and height |
| * @param stream the stream of image data |
| * @param gif pointer to library type that manages gif decode |
| * takes ownership |
| * @param transIndex The transparent index. An invalid value |
| * indicates that there is no transparent index. |
| */ |
| SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream, GifFileType* gif, uint32_t transIndex, |
| const SkIRect& frameRect, bool frameIsSubset); |
| |
| SkAutoTCallVProc<GifFileType, CloseGif> fGif; // owned |
| SkAutoTDeleteArray<uint8_t> fSrcBuffer; |
| const SkIRect fFrameRect; |
| const uint32_t fTransIndex; |
| uint32_t fFillIndex; |
| const bool fFrameIsSubset; |
| SkAutoTDelete<SkSwizzler> fSwizzler; |
| SkAutoTUnref<SkColorTable> fColorTable; |
| |
| typedef SkCodec INHERITED; |
| }; |