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