/* * 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" struct GifFileType; struct SavedImage; /* * * 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) 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. */ void 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 fGif; // owned SkAutoTDeleteArray fSrcBuffer; const SkIRect fFrameRect; const uint32_t fTransIndex; uint32_t fFillIndex; const bool fFrameIsSubset; SkAutoTDelete fSwizzler; SkAutoTUnref fColorTable; typedef SkCodec INHERITED; };