Home | History | Annotate | Download | only in codec
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkCodec.h"
      9 #include "SkColorTable.h"
     10 #include "SkImageInfo.h"
     11 #include "SkSwizzler.h"
     12 
     13 struct GifFileType;
     14 struct SavedImage;
     15 
     16 /*
     17  *
     18  * This class implements the decoding for gif images
     19  *
     20  */
     21 class SkGifCodec : public SkCodec {
     22 public:
     23     static bool IsGif(const void*, size_t);
     24 
     25     /*
     26      * Assumes IsGif was called and returned true
     27      * Creates a gif decoder
     28      * Reads enough of the stream to determine the image format
     29      */
     30     static SkCodec* NewFromStream(SkStream*);
     31 
     32 protected:
     33 
     34     /*
     35      * Read enough of the stream to initialize the SkGifCodec.
     36      * Returns a bool representing success or failure.
     37      *
     38      * @param codecOut
     39      * If it returned true, and codecOut was not nullptr,
     40      * codecOut will be set to a new SkGifCodec.
     41      *
     42      * @param gifOut
     43      * If it returned true, and codecOut was nullptr,
     44      * gifOut must be non-nullptr and gifOut will be set to a new
     45      * GifFileType pointer.
     46      *
     47      * @param stream
     48      * Deleted on failure.
     49      * codecOut will take ownership of it in the case where we created a codec.
     50      * Ownership is unchanged when we returned a gifOut.
     51      *
     52      */
     53     static bool ReadHeader(SkStream* stream, SkCodec** codecOut,
     54             GifFileType** gifOut);
     55 
     56     /*
     57      * Performs the full gif decode
     58      */
     59     Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
     60             SkPMColor*, int*, int*) override;
     61 
     62     SkEncodedFormat onGetEncodedFormat() const override {
     63         return kGIF_SkEncodedFormat;
     64     }
     65 
     66     bool onRewind() override;
     67 
     68     uint32_t onGetFillValue(SkColorType) const override;
     69 
     70     int onOutputScanline(int inputScanline) const override;
     71 
     72 private:
     73 
     74     /*
     75      * A gif can contain multiple image frames.  We will only decode the first
     76      * frame.  This function reads up to the first image frame, processing
     77      * transparency and/or animation information that comes before the image
     78      * data.
     79      *
     80      * @param gif        Pointer to the library type that manages the gif decode
     81      * @param transIndex This call will set the transparent index based on the
     82      *                   extension data.
     83      */
     84      static Result ReadUpToFirstImage(GifFileType* gif, uint32_t* transIndex);
     85 
     86      /*
     87       * A gif may contain many image frames, all of different sizes.
     88       * This function checks if the gif dimensions are valid, based on the frame
     89       * dimensions, and corrects the gif dimensions if necessary.
     90       *
     91       * @param gif       Pointer to the library type that manages the gif decode
     92       * @param size      Size of the image that we will decode.
     93       *                  Will be set by this function if the return value is true.
     94       * @param frameRect Contains the dimenions and offset of the first image frame.
     95       *                  Will be set by this function if the return value is true.
     96       *
     97       * @return true on success, false otherwise
     98       */
     99      static bool GetDimensions(GifFileType* gif, SkISize* size, SkIRect* frameRect);
    100 
    101     /*
    102      * Initializes the color table that we will use for decoding.
    103      *
    104      * @param dstInfo         Contains the requested dst color type.
    105      * @param inputColorPtr   Copies the encoded color table to the client's
    106      *                        input color table if the client requests kIndex8.
    107      * @param inputColorCount If the client requests kIndex8, sets
    108      *                        inputColorCount to 256.  Since gifs always
    109      *                        contain 8-bit indices, we need a 256 entry color
    110      *                        table to ensure that indexing is always in
    111      *                        bounds.
    112      */
    113     void initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* colorPtr,
    114             int* inputColorCount);
    115 
    116    /*
    117     * Checks for invalid inputs and calls setFrameDimensions(), and
    118     * initializeColorTable() in the proper sequence.
    119     */
    120     Result prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
    121             int* inputColorCount, const Options& opts);
    122 
    123     /*
    124      * Initializes the swizzler.
    125      *
    126      * @param dstInfo  Output image information.  Dimensions may have been
    127      *                 adjusted if the image frame size does not match the size
    128      *                 indicated in the header.
    129      * @param options  Informs the swizzler if destination memory is zero initialized.
    130      *                 Contains subset information.
    131      */
    132     void initializeSwizzler(const SkImageInfo& dstInfo,
    133             const Options& options);
    134 
    135     SkSampler* getSampler(bool createIfNecessary) override {
    136         SkASSERT(fSwizzler);
    137         return fSwizzler;
    138     }
    139 
    140     /*
    141      * @return true if the read is successful and false if the read fails.
    142      */
    143     bool readRow();
    144 
    145     Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opts,
    146                    SkPMColor inputColorPtr[], int* inputColorCount) override;
    147 
    148     int onGetScanlines(void* dst, int count, size_t rowBytes) override;
    149 
    150     bool onSkipScanlines(int count) override;
    151 
    152     /*
    153      * For a scanline decode of "count" lines, this function indicates how
    154      * many of the "count" lines should be skipped until we reach the top of
    155      * the image frame and how many of the "count" lines are actually inside
    156      * the image frame.
    157      *
    158      * @param count           The number of scanlines requested.
    159      * @param rowsBeforeFrame Output variable.  The number of lines before
    160      *                        we reach the top of the image frame.
    161      * @param rowsInFrame     Output variable.  The number of lines to decode
    162      *                        inside the image frame.
    163      */
    164     void handleScanlineFrame(int count, int* rowsBeforeFrame, int* rowsInFrame);
    165 
    166     SkScanlineOrder onGetScanlineOrder() const override;
    167 
    168     /*
    169      * This function cleans up the gif object after the decode completes
    170      * It is used in a SkAutoTCallIProc template
    171      */
    172     static void CloseGif(GifFileType* gif);
    173 
    174     /*
    175      * Frees any extension data used in the decode
    176      * Used in a SkAutoTCallVProc
    177      */
    178     static void FreeExtension(SavedImage* image);
    179 
    180     /*
    181      * Creates an instance of the decoder
    182      * Called only by NewFromStream
    183      *
    184      * @param srcInfo contains the source width and height
    185      * @param stream the stream of image data
    186      * @param gif pointer to library type that manages gif decode
    187      *            takes ownership
    188      * @param transIndex  The transparent index.  An invalid value
    189      *            indicates that there is no transparent index.
    190      */
    191     SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream, GifFileType* gif, uint32_t transIndex,
    192             const SkIRect& frameRect, bool frameIsSubset);
    193 
    194     SkAutoTCallVProc<GifFileType, CloseGif> fGif; // owned
    195     SkAutoTDeleteArray<uint8_t>             fSrcBuffer;
    196     const SkIRect                           fFrameRect;
    197     const uint32_t                          fTransIndex;
    198     uint32_t                                fFillIndex;
    199     const bool                              fFrameIsSubset;
    200     SkAutoTDelete<SkSwizzler>               fSwizzler;
    201     SkAutoTUnref<SkColorTable>              fColorTable;
    202 
    203     typedef SkCodec INHERITED;
    204 };
    205