You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.8 KiB
154 lines
5.8 KiB
// 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
|