blob: 544ba1369524a82ed0599d55b96422ecd7753ae0 [file] [log] [blame]
msarett8c8f22a2015-04-01 06:58:48 -07001/*
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"
scroggo19b91532016-10-24 09:03:26 -07009#include "SkCodecAnimation.h"
msarettad8bcfe2016-03-07 07:09:03 -080010#include "SkColorSpace.h"
msarett10522ff2015-09-07 08:54:01 -070011#include "SkColorTable.h"
msarett8c8f22a2015-04-01 06:58:48 -070012#include "SkImageInfo.h"
msarett10522ff2015-09-07 08:54:01 -070013#include "SkSwizzler.h"
msarett8c8f22a2015-04-01 06:58:48 -070014
scroggo19b91532016-10-24 09:03:26 -070015#include "GIFImageReader.h"
msarett8c8f22a2015-04-01 06:58:48 -070016
17/*
18 *
19 * This class implements the decoding for gif images
20 *
21 */
22class SkGifCodec : public SkCodec {
23public:
scroggodb30be22015-12-08 18:54:13 -080024 static bool IsGif(const void*, size_t);
msarett8c8f22a2015-04-01 06:58:48 -070025
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*);
msarett10522ff2015-09-07 08:54:01 -070032
scroggo19b91532016-10-24 09:03:26 -070033 // Callback for GIFImageReader when a row is available.
34 bool haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin,
35 size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels);
msarett8c8f22a2015-04-01 06:58:48 -070036protected:
msarett438b2ad2015-04-09 12:43:10 -070037 /*
msarett10522ff2015-09-07 08:54:01 -070038 * Performs the full gif decode
msarett8c8f22a2015-04-01 06:58:48 -070039 */
40 Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
msarette6dd0042015-10-09 11:07:34 -070041 SkPMColor*, int*, int*) override;
msarett8c8f22a2015-04-01 06:58:48 -070042
43 SkEncodedFormat onGetEncodedFormat() const override {
44 return kGIF_SkEncodedFormat;
45 }
46
scroggob427db12015-08-12 07:24:13 -070047 bool onRewind() override;
48
msarettf7eb6fc2016-09-13 09:04:11 -070049 uint64_t onGetFillValue(const SkImageInfo&) const override;
msarette6dd0042015-10-09 11:07:34 -070050
scroggo19b91532016-10-24 09:03:26 -070051 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;
msarette6dd0042015-10-09 11:07:34 -070057
msarett8c8f22a2015-04-01 06:58:48 -070058private:
59
60 /*
msarett10522ff2015-09-07 08:54:01 -070061 * Initializes the color table that we will use for decoding.
62 *
63 * @param dstInfo Contains the requested dst color type.
scroggo19b91532016-10-24 09:03:26 -070064 * @param frameIndex Frame whose color table to use.
msarett10522ff2015-09-07 08:54:01 -070065 * @param inputColorPtr Copies the encoded color table to the client's
66 * input color table if the client requests kIndex8.
scroggo19b91532016-10-24 09:03:26 -070067 * @param inputColorCount If the client requests kIndex8, this will be set
68 * to the number of colors in the array that
69 * inputColorPtr now points to. This will typically
70 * be 256. Since gifs may have up to 8-bit indices,
71 * using a 256-entry table means a pixel will never
72 * be out of range. This will be set to 1 if there
73 * is no color table, since that will be a
74 * transparent frame.
msarett10522ff2015-09-07 08:54:01 -070075 */
scroggo19b91532016-10-24 09:03:26 -070076 void initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex,
77 SkPMColor* colorPtr, int* inputColorCount);
msarett10522ff2015-09-07 08:54:01 -070078
79 /*
scroggo19b91532016-10-24 09:03:26 -070080 * Does necessary setup, including setting up the color table and swizzler,
81 * and reports color info to the client.
msarett10522ff2015-09-07 08:54:01 -070082 */
scroggo46c57472015-09-30 08:57:13 -070083 Result prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
msarett10522ff2015-09-07 08:54:01 -070084 int* inputColorCount, const Options& opts);
85
86 /*
87 * Initializes the swizzler.
88 *
scroggo19b91532016-10-24 09:03:26 -070089 * @param dstInfo Output image information. Dimensions may have been
90 * adjusted if the image frame size does not match the size
91 * indicated in the header.
92 * @param frameIndex Which frame we are decoding. This determines the frameRect
93 * to use.
msarett10522ff2015-09-07 08:54:01 -070094 */
scroggo19b91532016-10-24 09:03:26 -070095 void initializeSwizzler(const SkImageInfo& dstInfo, size_t frameIndex);
msarett10522ff2015-09-07 08:54:01 -070096
msarette6dd0042015-10-09 11:07:34 -070097 SkSampler* getSampler(bool createIfNecessary) override {
98 SkASSERT(fSwizzler);
scroggo19b91532016-10-24 09:03:26 -070099 return fSwizzler.get();
msarette6dd0042015-10-09 11:07:34 -0700100 }
scroggoe7fc14b2015-10-02 13:14:46 -0700101
msarett10522ff2015-09-07 08:54:01 -0700102 /*
scroggo19b91532016-10-24 09:03:26 -0700103 * Recursive function to decode a frame.
msarett72261c02015-11-19 15:29:26 -0800104 *
scroggo19b91532016-10-24 09:03:26 -0700105 * @param firstAttempt Whether this is the first call to decodeFrame since
106 * starting. e.g. true in onGetPixels, and true in the
107 * first call to onIncrementalDecode after calling
108 * onStartIncrementalDecode.
109 * When true, this method may have to initialize the
110 * frame, for example by filling or decoding the prior
111 * frame.
112 * @param opts Options for decoding. May be different from
113 * this->options() for decoding prior frames. Specifies
114 * the frame to decode and whether the prior frame has
115 * already been decoded to fDst. If not, and the frame
116 * is not independent, this method will recursively
117 * decode the frame it depends on.
118 * @param rowsDecoded Out-parameter to report the total number of rows
119 * that have been decoded (or at least written to, if
120 * it had to fill), including rows decoded by prior
121 * calls to onIncrementalDecode.
122 * @return kSuccess if the frame is complete, kIncompleteInput
123 * otherwise.
msarett72261c02015-11-19 15:29:26 -0800124 */
scroggo19b91532016-10-24 09:03:26 -0700125 Result decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded);
msarett8c8f22a2015-04-01 06:58:48 -0700126
127 /*
128 * Creates an instance of the decoder
129 * Called only by NewFromStream
scroggo19b91532016-10-24 09:03:26 -0700130 * Takes ownership of the GIFImageReader
msarett8c8f22a2015-04-01 06:58:48 -0700131 */
scroggo19b91532016-10-24 09:03:26 -0700132 SkGifCodec(const SkEncodedInfo&, const SkImageInfo&, GIFImageReader*);
msarett8c8f22a2015-04-01 06:58:48 -0700133
scroggo19b91532016-10-24 09:03:26 -0700134 std::unique_ptr<GIFImageReader> fReader;
135 std::unique_ptr<uint8_t[]> fTmpBuffer;
136 std::unique_ptr<SkSwizzler> fSwizzler;
137 sk_sp<SkColorTable> fCurrColorTable;
138 // We may create a dummy table if there is not a Map in the input data. In
139 // that case, we set this value to false, and we can skip a lot of decoding
140 // work (which would not be meaningful anyway). We create a "fake"/"dummy"
141 // one in that case, so the client and the swizzler have something to draw.
142 bool fCurrColorTableIsReal;
143 // Whether the background was filled.
144 bool fFilledBackground;
145 // True on the first call to onIncrementalDecode. This value is passed to
146 // decodeFrame.
147 bool fFirstCallToIncrementalDecode;
148
149 void* fDst;
150 size_t fDstRowBytes;
151
152 // Updated inside haveDecodedRow when rows are decoded, unless we filled
153 // the background, in which case it is set once and left alone.
154 int fRowsDecoded;
msarett10522ff2015-09-07 08:54:01 -0700155
msarett8c8f22a2015-04-01 06:58:48 -0700156 typedef SkCodec INHERITED;
157};