• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  #ifndef SkGifCodec_DEFINED
8  #define SkGifCodec_DEFINED
9  
10  #include "SkCodec.h"
11  #include "SkCodecAnimation.h"
12  #include "SkColorSpace.h"
13  #include "SkColorTable.h"
14  #include "SkImageInfo.h"
15  #include "SkSwizzler.h"
16  
17  #include "SkGifImageReader.h"
18  
19  /*
20   *
21   * This class implements the decoding for gif images
22   *
23   */
24  class SkGifCodec : public SkCodec {
25  public:
26      static bool IsGif(const void*, size_t);
27  
28      /*
29       * Assumes IsGif was called and returned true
30       * Reads enough of the stream to determine the image format
31       */
32      static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*);
33  
34      // Callback for SkGifImageReader when a row is available.
35      void haveDecodedRow(int frameIndex, const unsigned char* rowBegin,
36                          int rowNumber, int repeatCount, bool writeTransparentPixels);
37  protected:
38      /*
39       * Performs the full gif decode
40       */
41      Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
42              int*) override;
43  
onGetEncodedFormat()44      SkEncodedImageFormat onGetEncodedFormat() const override {
45          return SkEncodedImageFormat::kGIF;
46      }
47  
48      bool onRewind() override;
49  
50      int onGetFrameCount() override;
51      bool onGetFrameInfo(int, FrameInfo*) const override;
52      int onGetRepetitionCount() override;
53  
54      Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
55              const SkCodec::Options&) override;
56  
57      Result onIncrementalDecode(int*) override;
58  
getFrameHolder()59      const SkFrameHolder* getFrameHolder() const override {
60          return fReader.get();
61      }
62  
63  private:
64  
65      /*
66       * Initializes the color table that we will use for decoding.
67       *
68       * @param dstInfo         Contains the requested dst color type.
69       * @param frameIndex      Frame whose color table to use.
70       */
71      void initializeColorTable(const SkImageInfo& dstInfo, int frameIndex);
72  
73     /*
74      * Does necessary setup, including setting up the color table and swizzler.
75      */
76      Result prepareToDecode(const SkImageInfo& dstInfo, const Options& opts);
77  
78      /*
79       * Initializes the swizzler.
80       *
81       * @param dstInfo    Output image information.  Dimensions may have been
82       *                   adjusted if the image frame size does not match the size
83       *                   indicated in the header.
84       * @param frameIndex Which frame we are decoding. This determines the frameRect
85       *                   to use.
86       */
87      void initializeSwizzler(const SkImageInfo& dstInfo, int frameIndex);
88  
getSampler(bool createIfNecessary)89      SkSampler* getSampler(bool createIfNecessary) override {
90          SkASSERT(fSwizzler);
91          return fSwizzler.get();
92      }
93  
94      /*
95       * Recursive function to decode a frame.
96       *
97       * @param firstAttempt Whether this is the first call to decodeFrame since
98       *                     starting. e.g. true in onGetPixels, and true in the
99       *                     first call to onIncrementalDecode after calling
100       *                     onStartIncrementalDecode.
101       *                     When true, this method may have to initialize the
102       *                     frame, for example by filling or decoding the prior
103       *                     frame.
104       * @param opts         Options for decoding. May be different from
105       *                     this->options() for decoding prior frames. Specifies
106       *                     the frame to decode and whether the prior frame has
107       *                     already been decoded to fDst. If not, and the frame
108       *                     is not independent, this method will recursively
109       *                     decode the frame it depends on.
110       * @param rowsDecoded  Out-parameter to report the total number of rows
111       *                     that have been decoded (or at least written to, if
112       *                     it had to fill), including rows decoded by prior
113       *                     calls to onIncrementalDecode.
114       * @return             kSuccess if the frame is complete, kIncompleteInput
115       *                     otherwise.
116       */
117      Result decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded);
118  
119      /*
120       *  Swizzles and color xforms (if necessary) into dst.
121       */
122      void applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint8_t* src) const;
123  
124      /*
125       * Creates an instance of the decoder
126       * Called only by NewFromStream
127       * Takes ownership of the SkGifImageReader
128       */
129      SkGifCodec(SkEncodedInfo&&, SkGifImageReader*);
130  
131      std::unique_ptr<SkGifImageReader>   fReader;
132      std::unique_ptr<uint8_t[]>          fTmpBuffer;
133      std::unique_ptr<SkSwizzler>         fSwizzler;
134      sk_sp<SkColorTable>                 fCurrColorTable;
135      // We may create a dummy table if there is not a Map in the input data. In
136      // that case, we set this value to false, and we can skip a lot of decoding
137      // work (which would not be meaningful anyway). We create a "fake"/"dummy"
138      // one in that case, so the client and the swizzler have something to draw.
139      bool                                fCurrColorTableIsReal;
140      // Whether the background was filled.
141      bool                                fFilledBackground;
142      // True on the first call to onIncrementalDecode. This value is passed to
143      // decodeFrame.
144      bool                                fFirstCallToIncrementalDecode;
145  
146      void*                               fDst;
147      size_t                              fDstRowBytes;
148  
149      // Updated inside haveDecodedRow when rows are decoded, unless we filled
150      // the background, in which case it is set once and left alone.
151      int                                 fRowsDecoded;
152      std::unique_ptr<uint32_t[]>         fXformBuffer;
153  
154      typedef SkCodec INHERITED;
155  };
156  #endif  // SkGifCodec_DEFINED
157