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