blob: a5cb26cc1a1657ba46ca9b250fe80d548291f0d4 [file] [log] [blame]
scroggo19b91532016-10-24 09:03:26 -07001/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is Mozilla Communicator client code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
scroggo3d3a65c2016-10-24 12:28:30 -070038#ifndef SkGifImageReader_h
39#define SkGifImageReader_h
scroggo19b91532016-10-24 09:03:26 -070040
41// Define ourselves as the clientPtr. Mozilla just hacked their C++ callback class into this old C decoder,
42// so we will too.
43class SkGifCodec;
44
45#include "SkCodec.h"
46#include "SkCodecPriv.h"
47#include "SkCodecAnimation.h"
48#include "SkColorTable.h"
49#include "SkData.h"
Leon Scroggins III557fbbe2017-05-23 09:37:21 -040050#include "SkFrameHolder.h"
scroggo19b91532016-10-24 09:03:26 -070051#include "SkImageInfo.h"
52#include "SkStreamBuffer.h"
53#include "../private/SkTArray.h"
54#include <memory>
scroggo19b91532016-10-24 09:03:26 -070055
scroggof9acbe22016-10-25 12:43:21 -070056typedef SkTArray<unsigned char, true> SkGIFRow;
scroggo19b91532016-10-24 09:03:26 -070057
58
scroggof9acbe22016-10-25 12:43:21 -070059#define SK_MAX_DICTIONARY_ENTRY_BITS 12
60#define SK_MAX_DICTIONARY_ENTRIES 4096 // 2^SK_MAX_DICTIONARY_ENTRY_BITS
61#define SK_MAX_COLORS 256
62#define SK_BYTES_PER_COLORMAP_ENTRY 3
scroggo19b91532016-10-24 09:03:26 -070063
64// List of possible parsing states.
scroggof9acbe22016-10-25 12:43:21 -070065enum SkGIFState {
66 SkGIFType,
67 SkGIFGlobalHeader,
68 SkGIFGlobalColormap,
69 SkGIFImageStart,
70 SkGIFImageHeader,
71 SkGIFImageColormap,
72 SkGIFImageBody,
73 SkGIFLZWStart,
74 SkGIFLZW,
75 SkGIFSubBlock,
76 SkGIFExtension,
77 SkGIFControlExtension,
78 SkGIFConsumeBlock,
79 SkGIFSkipBlock,
80 SkGIFDone,
81 SkGIFCommentExtension,
82 SkGIFApplicationExtension,
83 SkGIFNetscapeExtensionBlock,
84 SkGIFConsumeNetscapeExtension,
85 SkGIFConsumeComment
scroggo19b91532016-10-24 09:03:26 -070086};
87
Leon Scroggins III557fbbe2017-05-23 09:37:21 -040088class SkGIFFrameContext;
scroggo53f63b62016-10-27 08:29:13 -070089class SkGIFColorMap;
scroggo19b91532016-10-24 09:03:26 -070090
91// LZW decoder state machine.
scroggof9acbe22016-10-25 12:43:21 -070092class SkGIFLZWContext final : public SkNoncopyable {
scroggo19b91532016-10-24 09:03:26 -070093public:
scroggof9acbe22016-10-25 12:43:21 -070094 SkGIFLZWContext(SkGifCodec* client, const SkGIFFrameContext* frameContext)
scroggo19b91532016-10-24 09:03:26 -070095 : codesize(0)
96 , codemask(0)
97 , clearCode(0)
98 , avail(0)
99 , oldcode(0)
100 , firstchar(0)
101 , bits(0)
102 , datum(0)
103 , ipass(0)
104 , irow(0)
105 , rowsRemaining(0)
Ben Wagnera93a14a2017-08-28 10:34:05 -0400106 , rowIter(nullptr)
scroggo19b91532016-10-24 09:03:26 -0700107 , m_client(client)
108 , m_frameContext(frameContext)
109 { }
110
Leon Scroggins III45565b62016-12-05 14:56:30 -0500111 bool prepareToDecode();
Leon Scroggins III223ec292017-08-22 14:13:15 -0400112 void outputRow(const unsigned char* rowBegin);
scroggo19b91532016-10-24 09:03:26 -0700113 bool doLZW(const unsigned char* block, size_t bytesInBlock);
Jim Van Verth3cfdf6c2016-10-26 09:45:23 -0400114 bool hasRemainingRows() { return SkToBool(rowsRemaining); }
scroggo19b91532016-10-24 09:03:26 -0700115
116private:
117 // LZW decoding states and output states.
118 int codesize;
119 int codemask;
120 int clearCode; // Codeword used to trigger dictionary reset.
121 int avail; // Index of next available slot in dictionary.
122 int oldcode;
123 unsigned char firstchar;
124 int bits; // Number of unread bits in "datum".
125 int datum; // 32-bit input buffer.
126 int ipass; // Interlace pass; Ranges 1-4 if interlaced.
127 size_t irow; // Current output row, starting at zero.
128 size_t rowsRemaining; // Rows remaining to be output.
129
scroggof9acbe22016-10-25 12:43:21 -0700130 unsigned short prefix[SK_MAX_DICTIONARY_ENTRIES];
131 unsigned char suffix[SK_MAX_DICTIONARY_ENTRIES];
132 unsigned short suffixLength[SK_MAX_DICTIONARY_ENTRIES];
133 SkGIFRow rowBuffer; // Single scanline temporary buffer.
scroggo19b91532016-10-24 09:03:26 -0700134 unsigned char* rowIter;
135
136 SkGifCodec* const m_client;
scroggof9acbe22016-10-25 12:43:21 -0700137 const SkGIFFrameContext* m_frameContext;
scroggo19b91532016-10-24 09:03:26 -0700138};
139
Leon Scroggins III932efed2016-12-16 11:39:51 -0500140struct SkGIFLZWBlock {
141 public:
142 SkGIFLZWBlock(size_t position, size_t size)
143 : blockPosition(position), blockSize(size) {}
144
Chris Blumed5c5ed52016-12-20 18:59:39 -0800145 size_t blockPosition;
146 size_t blockSize;
Leon Scroggins III932efed2016-12-16 11:39:51 -0500147};
148
scroggof9acbe22016-10-25 12:43:21 -0700149class SkGIFColorMap final {
scroggo19b91532016-10-24 09:03:26 -0700150public:
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400151 static constexpr int kNotFound = -1;
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500152
scroggof9acbe22016-10-25 12:43:21 -0700153 SkGIFColorMap()
scroggo19b91532016-10-24 09:03:26 -0700154 : m_isDefined(false)
Leon Scroggins III932efed2016-12-16 11:39:51 -0500155 , m_position(0)
scroggo19b91532016-10-24 09:03:26 -0700156 , m_colors(0)
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500157 , m_transPixel(kNotFound)
scroggo19b91532016-10-24 09:03:26 -0700158 , m_packColorProc(nullptr)
159 {
160 }
161
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400162 void setNumColors(int colors) {
Leon Scroggins III932efed2016-12-16 11:39:51 -0500163 SkASSERT(!m_colors);
164 SkASSERT(!m_position);
165
scroggo19b91532016-10-24 09:03:26 -0700166 m_colors = colors;
167 }
168
Leon Scroggins III932efed2016-12-16 11:39:51 -0500169 void setTablePosition(size_t position) {
170 SkASSERT(!m_isDefined);
171
172 m_position = position;
173 m_isDefined = true;
174 }
175
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400176 int numColors() const { return m_colors; }
scroggo19b91532016-10-24 09:03:26 -0700177
scroggo19b91532016-10-24 09:03:26 -0700178 bool isDefined() const { return m_isDefined; }
179
180 // Build RGBA table using the data stream.
Leon Scroggins III932efed2016-12-16 11:39:51 -0500181 sk_sp<SkColorTable> buildTable(SkStreamBuffer*, SkColorType dstColorType,
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400182 int transparentPixel) const;
scroggo19b91532016-10-24 09:03:26 -0700183
184private:
185 bool m_isDefined;
Leon Scroggins III932efed2016-12-16 11:39:51 -0500186 size_t m_position;
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400187 int m_colors;
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500188 // Cached values. If these match on a new request, we can reuse m_table.
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400189 mutable int m_transPixel;
scroggo19b91532016-10-24 09:03:26 -0700190 mutable PackColorProc m_packColorProc;
191 mutable sk_sp<SkColorTable> m_table;
192};
193
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400194class SkGifImageReader;
195
scroggo19b91532016-10-24 09:03:26 -0700196// LocalFrame output state machine.
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400197class SkGIFFrameContext : public SkFrame {
scroggo19b91532016-10-24 09:03:26 -0700198public:
Chris Blume6c08b7b2017-09-28 10:23:26 -0700199 SkGIFFrameContext(int id)
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400200 : INHERITED(id)
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500201 , m_transparentPixel(SkGIFColorMap::kNotFound)
scroggo19b91532016-10-24 09:03:26 -0700202 , m_dataSize(0)
203 , m_progressiveDisplay(false)
204 , m_interlaced(false)
scroggo19b91532016-10-24 09:03:26 -0700205 , m_currentLzwBlock(0)
206 , m_isComplete(false)
207 , m_isHeaderDefined(false)
208 , m_isDataSizeDefined(false)
209 {
210 }
211
Kevin Lubick700a79c2017-05-24 08:34:16 -0400212 ~SkGIFFrameContext() override
scroggo19b91532016-10-24 09:03:26 -0700213 {
214 }
215
Leon Scroggins III932efed2016-12-16 11:39:51 -0500216 void addLzwBlock(size_t position, size_t size)
scroggo19b91532016-10-24 09:03:26 -0700217 {
Leon Scroggins IIIe7503912017-08-30 10:09:42 -0400218 m_lzwBlocks.emplace_back(position, size);
scroggo19b91532016-10-24 09:03:26 -0700219 }
220
Leon Scroggins III932efed2016-12-16 11:39:51 -0500221 bool decode(SkStreamBuffer*, SkGifCodec* client, bool* frameDecoded);
scroggo19b91532016-10-24 09:03:26 -0700222
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400223 int transparentPixel() const { return m_transparentPixel; }
224 void setTransparentPixel(int pixel) { m_transparentPixel = pixel; }
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500225
scroggo19b91532016-10-24 09:03:26 -0700226 bool isComplete() const { return m_isComplete; }
227 void setComplete() { m_isComplete = true; }
228 bool isHeaderDefined() const { return m_isHeaderDefined; }
229 void setHeaderDefined() { m_isHeaderDefined = true; }
230 bool isDataSizeDefined() const { return m_isDataSizeDefined; }
231 int dataSize() const { return m_dataSize; }
232 void setDataSize(int size)
233 {
234 m_dataSize = size;
235 m_isDataSizeDefined = true;
236 }
237 bool progressiveDisplay() const { return m_progressiveDisplay; }
238 void setProgressiveDisplay(bool progressiveDisplay) { m_progressiveDisplay = progressiveDisplay; }
239 bool interlaced() const { return m_interlaced; }
240 void setInterlaced(bool interlaced) { m_interlaced = interlaced; }
241
242 void clearDecodeState() { m_lzwContext.reset(); }
scroggof9acbe22016-10-25 12:43:21 -0700243 const SkGIFColorMap& localColorMap() const { return m_localColorMap; }
244 SkGIFColorMap& localColorMap() { return m_localColorMap; }
scroggo19b91532016-10-24 09:03:26 -0700245
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400246protected:
Leon Scroggins IIIc8037dc2017-12-05 13:55:24 -0500247 SkEncodedInfo::Alpha onReportedAlpha() const override;
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500248
scroggo19b91532016-10-24 09:03:26 -0700249private:
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400250 int m_transparentPixel; // Index of transparent pixel. Value is kNotFound if there is no transparent pixel.
scroggo19b91532016-10-24 09:03:26 -0700251 int m_dataSize;
252
253 bool m_progressiveDisplay; // If true, do Haeberli interlace hack.
254 bool m_interlaced; // True, if scanlines arrive interlaced order.
255
scroggof9acbe22016-10-25 12:43:21 -0700256 std::unique_ptr<SkGIFLZWContext> m_lzwContext;
Leon Scroggins III932efed2016-12-16 11:39:51 -0500257 // LZW blocks for this frame.
Leon Scroggins IIIe7503912017-08-30 10:09:42 -0400258 SkTArray<SkGIFLZWBlock> m_lzwBlocks;
Leon Scroggins III932efed2016-12-16 11:39:51 -0500259
scroggof9acbe22016-10-25 12:43:21 -0700260 SkGIFColorMap m_localColorMap;
scroggo19b91532016-10-24 09:03:26 -0700261
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400262 int m_currentLzwBlock;
scroggo19b91532016-10-24 09:03:26 -0700263 bool m_isComplete;
264 bool m_isHeaderDefined;
265 bool m_isDataSizeDefined;
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400266
267 typedef SkFrame INHERITED;
scroggo19b91532016-10-24 09:03:26 -0700268};
269
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400270class SkGifImageReader final : public SkFrameHolder {
scroggo19b91532016-10-24 09:03:26 -0700271public:
272 // This takes ownership of stream.
Mike Reedede7bac2017-07-23 15:30:02 -0400273 SkGifImageReader(std::unique_ptr<SkStream> stream)
scroggo19b91532016-10-24 09:03:26 -0700274 : m_client(nullptr)
scroggof9acbe22016-10-25 12:43:21 -0700275 , m_state(SkGIFType)
scroggo19b91532016-10-24 09:03:26 -0700276 , m_bytesToConsume(6) // Number of bytes for GIF type, either "GIF87a" or "GIF89a".
277 , m_version(0)
scroggo19b91532016-10-24 09:03:26 -0700278 , m_loopCount(cLoopCountNotSeen)
Mike Reedede7bac2017-07-23 15:30:02 -0400279 , m_streamBuffer(std::move(stream))
scroggo19b91532016-10-24 09:03:26 -0700280 , m_parseCompleted(false)
281 , m_firstFrameHasAlpha(false)
scroggo19b91532016-10-24 09:03:26 -0700282 {
283 }
284
Kevin Lubick700a79c2017-05-24 08:34:16 -0400285 ~SkGifImageReader() override
scroggo19b91532016-10-24 09:03:26 -0700286 {
287 }
288
289 void setClient(SkGifCodec* client) { m_client = client; }
290
scroggo19b91532016-10-24 09:03:26 -0700291 // Option to pass to parse(). All enums are negative, because a non-negative value is used to
292 // indicate that the Reader should parse up to and including the frame indicated.
scroggof9acbe22016-10-25 12:43:21 -0700293 enum SkGIFParseQuery {
scroggo19b91532016-10-24 09:03:26 -0700294 // Parse enough to determine the size. Note that this parses the first frame's header,
295 // since we may decide to expand based on the frame's dimensions.
scroggof9acbe22016-10-25 12:43:21 -0700296 SkGIFSizeQuery = -1,
scroggo19b91532016-10-24 09:03:26 -0700297 // Parse to the end, so we know about all frames.
scroggof9acbe22016-10-25 12:43:21 -0700298 SkGIFFrameCountQuery = -2,
scroggoe71b1a12016-11-01 08:28:28 -0700299 // Parse until we see the loop count.
300 SkGIFLoopCountQuery = -3,
scroggo19b91532016-10-24 09:03:26 -0700301 };
302
303 // Parse incoming GIF data stream into internal data structures.
304 // Non-negative values are used to indicate to parse through that frame.
Leon Scroggins III588fb042017-07-14 16:32:31 -0400305 SkCodec::Result parse(SkGIFParseQuery);
scroggo19b91532016-10-24 09:03:26 -0700306
307 // Decode the frame indicated by frameIndex.
308 // frameComplete will be set to true if the frame is completely decoded.
309 // The method returns false if there is an error.
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400310 bool decode(int frameIndex, bool* frameComplete);
scroggo19b91532016-10-24 09:03:26 -0700311
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400312 int imagesCount() const
scroggo19b91532016-10-24 09:03:26 -0700313 {
Leon Scroggins IIIe7503912017-08-30 10:09:42 -0400314 const int frames = m_frames.count();
Leon Scroggins IIIe726e7c2017-07-18 16:22:52 -0400315 if (!frames) {
316 return 0;
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500317 }
scroggo19b91532016-10-24 09:03:26 -0700318
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500319 // This avoids counting an empty frame when the file is truncated (or
320 // simply not yet complete) after receiving SkGIFControlExtension (and
321 // possibly SkGIFImageHeader) but before reading the color table. This
322 // ensures that we do not count a frame before we know its required
323 // frame.
Leon Scroggins IIIe7503912017-08-30 10:09:42 -0400324 return m_frames.back()->reachedStartOfData() ? frames : frames - 1;
scroggo19b91532016-10-24 09:03:26 -0700325 }
scroggoe71b1a12016-11-01 08:28:28 -0700326 int loopCount() const {
327 if (cLoopCountNotSeen == m_loopCount) {
328 return 0;
329 }
330 return m_loopCount;
331 }
scroggo19b91532016-10-24 09:03:26 -0700332
scroggof9acbe22016-10-25 12:43:21 -0700333 const SkGIFColorMap& globalColorMap() const
scroggo19b91532016-10-24 09:03:26 -0700334 {
335 return m_globalColorMap;
336 }
337
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400338 const SkGIFFrameContext* frameContext(int index) const
scroggo19b91532016-10-24 09:03:26 -0700339 {
Leon Scroggins IIIe7503912017-08-30 10:09:42 -0400340 return index >= 0 && index < m_frames.count()
Ben Wagnera93a14a2017-08-28 10:34:05 -0400341 ? m_frames[index].get() : nullptr;
scroggo19b91532016-10-24 09:03:26 -0700342 }
343
344 void clearDecodeState() {
Leon Scroggins IIIe7503912017-08-30 10:09:42 -0400345 for (int index = 0; index < m_frames.count(); index++) {
scroggo19b91532016-10-24 09:03:26 -0700346 m_frames[index]->clearDecodeState();
347 }
348 }
349
350 // Return the color table for frame index (which may be the global color table).
Leon Scroggins III249b8e32017-04-17 12:46:33 -0400351 sk_sp<SkColorTable> getColorTable(SkColorType dstColorType, int index);
scroggo19b91532016-10-24 09:03:26 -0700352
353 bool firstFrameHasAlpha() const { return m_firstFrameHasAlpha; }
354
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400355protected:
356 const SkFrame* onGetFrame(int i) const override {
357 return static_cast<const SkFrame*>(this->frameContext(i));
358 }
359
scroggo19b91532016-10-24 09:03:26 -0700360private:
361 // Requires that one byte has been buffered into m_streamBuffer.
362 unsigned char getOneByte() const {
363 return reinterpret_cast<const unsigned char*>(m_streamBuffer.get())[0];
364 }
365
366 void addFrameIfNecessary();
367 bool currentFrameIsFirstFrame() const
368 {
Leon Scroggins IIIe7503912017-08-30 10:09:42 -0400369 return m_frames.empty() || (m_frames.count() == 1 && !m_frames[0]->isComplete());
scroggo19b91532016-10-24 09:03:26 -0700370 }
371
372 // Unowned pointer
373 SkGifCodec* m_client;
374
375 // Parsing state machine.
scroggof9acbe22016-10-25 12:43:21 -0700376 SkGIFState m_state; // Current decoder master state.
scroggo19b91532016-10-24 09:03:26 -0700377 size_t m_bytesToConsume; // Number of bytes to consume for next stage of parsing.
378
379 // Global (multi-image) state.
380 int m_version; // Either 89 for GIF89 or 87 for GIF87.
scroggof9acbe22016-10-25 12:43:21 -0700381 SkGIFColorMap m_globalColorMap;
scroggoe71b1a12016-11-01 08:28:28 -0700382
383 static constexpr int cLoopCountNotSeen = -2;
scroggo19b91532016-10-24 09:03:26 -0700384 int m_loopCount; // Netscape specific extension block to control the number of animation loops a GIF renders.
385
Leon Scroggins IIIe7503912017-08-30 10:09:42 -0400386 SkTArray<std::unique_ptr<SkGIFFrameContext>> m_frames;
scroggo19b91532016-10-24 09:03:26 -0700387
388 SkStreamBuffer m_streamBuffer;
389 bool m_parseCompleted;
390
Leon Scroggins571b30f2017-07-11 17:35:31 +0000391 // This value can be computed before we create a SkGIFFrameContext, so we
392 // store it here instead of on m_frames[0].
scroggo19b91532016-10-24 09:03:26 -0700393 bool m_firstFrameHasAlpha;
scroggo19b91532016-10-24 09:03:26 -0700394};
395
396#endif