Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.h

Issue 2565323003: Move gif image decoder to SkCodec (Closed)
Patch Set: Only include SkCodec for non-iOS targets Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /* -*- 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
38 #ifndef GIFImageReader_h
39 #define GIFImageReader_h
40
41 // Define ourselves as the clientPtr. Mozilla just hacked their C++ callback
42 // class into this old C decoder, so we will too.
43 #include <memory>
44 #include "platform/image-decoders/FastSharedBufferReader.h"
45 #include "platform/image-decoders/gif/GIFImageDecoder.h"
46 #include "platform/wtf/Allocator.h"
47 #include "platform/wtf/Noncopyable.h"
48 #include "platform/wtf/Vector.h"
49
50 namespace blink {
51
52 const int kCLoopCountNotSeen = -2;
53
54 // List of possible parsing states.
55 enum GIFState {
56 kGIFType,
57 kGIFGlobalHeader,
58 kGIFGlobalColormap,
59 kGIFImageStart,
60 kGIFImageHeader,
61 kGIFImageColormap,
62 kGIFImageBody,
63 kGIFLZWStart,
64 GIFLZW,
65 kGIFSubBlock,
66 kGIFExtension,
67 kGIFControlExtension,
68 kGIFConsumeBlock,
69 kGIFSkipBlock,
70 kGIFDone,
71 kGIFCommentExtension,
72 kGIFApplicationExtension,
73 kGIFNetscapeExtensionBlock,
74 kGIFConsumeNetscapeExtension,
75 kGIFConsumeComment
76 };
77
78 struct GIFFrameContext;
79
80 // LZW decoder state machine.
81 class GIFLZWContext final {
82 USING_FAST_MALLOC(GIFLZWContext);
83 WTF_MAKE_NONCOPYABLE(GIFLZWContext);
84
85 public:
86 GIFLZWContext(blink::GIFImageDecoder* client,
87 const GIFFrameContext* frame_context)
88 : codesize(0),
89 codemask(0),
90 clear_code(0),
91 avail(0),
92 oldcode(0),
93 firstchar(0),
94 bits(0),
95 datum(0),
96 ipass(0),
97 irow(0),
98 rows_remaining(0),
99 row_iter(0),
100 client_(client),
101 frame_context_(frame_context) {}
102
103 bool PrepareToDecode();
104 bool OutputRow(GIFRow::const_iterator row_begin);
105 bool DoLZW(const unsigned char* block, size_t bytes_in_block);
106 bool HasRemainingRows() { return rows_remaining; }
107
108 private:
109 enum {
110 kMaxDictionaryEntryBits = 12,
111 // 2^kMaxDictionaryEntryBits
112 kMaxDictionaryEntries = 4096,
113 };
114
115 // LZW decoding states and output states.
116 int codesize;
117 int codemask;
118 int clear_code; // Codeword used to trigger dictionary reset.
119 int avail; // Index of next available slot in dictionary.
120 int oldcode;
121 unsigned char firstchar;
122 int bits; // Number of unread bits in "datum".
123 int datum; // 32-bit input buffer.
124 int ipass; // Interlace pass; Ranges 1-4 if interlaced.
125 size_t irow; // Current output row, starting at zero.
126 size_t rows_remaining; // Rows remaining to be output.
127
128 unsigned short prefix[kMaxDictionaryEntries];
129 unsigned char suffix[kMaxDictionaryEntries];
130 unsigned short suffix_length[kMaxDictionaryEntries];
131 GIFRow row_buffer; // Single scanline temporary buffer.
132 GIFRow::iterator row_iter;
133
134 // Initialized during construction and read-only.
135 blink::GIFImageDecoder* client_;
136 const GIFFrameContext* frame_context_;
137 };
138
139 // Data structure for one LZW block.
140 struct GIFLZWBlock {
141 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
142
143 public:
144 GIFLZWBlock(size_t position, size_t size)
145 : block_position(position), block_size(size) {}
146
147 size_t block_position;
148 size_t block_size;
149 };
150
151 class GIFColorMap final {
152 DISALLOW_NEW();
153
154 public:
155 typedef Vector<blink::ImageFrame::PixelData> Table;
156
157 GIFColorMap() : is_defined_(false), position_(0), colors_(0) {}
158
159 // Set position and number of colors for the RGB table in the data stream.
160 void SetTablePositionAndSize(size_t position, size_t colors) {
161 position_ = position;
162 colors_ = colors;
163 }
164 void SetDefined() { is_defined_ = true; }
165 bool IsDefined() const { return is_defined_; }
166
167 // Build RGBA table using the data stream.
168 void BuildTable(blink::FastSharedBufferReader*);
169 const Table& GetTable() const { return table_; }
170
171 private:
172 bool is_defined_;
173 size_t position_;
174 size_t colors_;
175 Table table_;
176 };
177
178 // LocalFrame output state machine.
179 struct GIFFrameContext {
180 USING_FAST_MALLOC(GIFFrameContext);
181 WTF_MAKE_NONCOPYABLE(GIFFrameContext);
182
183 public:
184 GIFFrameContext(int id)
185 : frame_id_(id),
186 x_offset_(0),
187 y_offset_(0),
188 width_(0),
189 height_(0),
190 transparent_pixel_(kNotFound),
191 disposal_method_(blink::ImageFrame::kDisposeNotSpecified),
192 data_size_(0),
193 progressive_display_(false),
194 interlaced_(false),
195 delay_time_(0),
196 current_lzw_block_(0),
197 is_complete_(false),
198 is_header_defined_(false),
199 is_data_size_defined_(false) {}
200
201 ~GIFFrameContext() {}
202
203 void AddLzwBlock(size_t position, size_t size) {
204 lzw_blocks_.push_back(GIFLZWBlock(position, size));
205 }
206
207 bool Decode(blink::FastSharedBufferReader*,
208 blink::GIFImageDecoder* client,
209 bool* frame_decoded);
210
211 int FrameId() const { return frame_id_; }
212 void SetRect(unsigned x, unsigned y, unsigned width, unsigned height) {
213 x_offset_ = x;
214 y_offset_ = y;
215 width_ = width;
216 height_ = height;
217 }
218 blink::IntRect FrameRect() const {
219 return blink::IntRect(x_offset_, y_offset_, width_, height_);
220 }
221 unsigned XOffset() const { return x_offset_; }
222 unsigned YOffset() const { return y_offset_; }
223 unsigned Width() const { return width_; }
224 unsigned Height() const { return height_; }
225 size_t TransparentPixel() const { return transparent_pixel_; }
226 void SetTransparentPixel(size_t pixel) { transparent_pixel_ = pixel; }
227 blink::ImageFrame::DisposalMethod GetDisposalMethod() const {
228 return disposal_method_;
229 }
230 void SetDisposalMethod(blink::ImageFrame::DisposalMethod disposal_method) {
231 disposal_method_ = disposal_method;
232 }
233 unsigned DelayTime() const { return delay_time_; }
234 void SetDelayTime(unsigned delay) { delay_time_ = delay; }
235 bool IsComplete() const { return is_complete_; }
236 void SetComplete() { is_complete_ = true; }
237 bool IsHeaderDefined() const { return is_header_defined_; }
238 void SetHeaderDefined() { is_header_defined_ = true; }
239 bool IsDataSizeDefined() const { return is_data_size_defined_; }
240 int DataSize() const { return data_size_; }
241 void SetDataSize(int size) {
242 data_size_ = size;
243 is_data_size_defined_ = true;
244 }
245 bool ProgressiveDisplay() const { return progressive_display_; }
246 void SetProgressiveDisplay(bool progressive_display) {
247 progressive_display_ = progressive_display;
248 }
249 bool Interlaced() const { return interlaced_; }
250 void SetInterlaced(bool interlaced) { interlaced_ = interlaced; }
251
252 void ClearDecodeState() { lzw_context_.reset(); }
253 const GIFColorMap& LocalColorMap() const { return local_color_map_; }
254 GIFColorMap& LocalColorMap() { return local_color_map_; }
255
256 private:
257 int frame_id_;
258 unsigned x_offset_;
259 unsigned y_offset_; // With respect to "screen" origin.
260 unsigned width_;
261 unsigned height_;
262 size_t transparent_pixel_; // Index of transparent pixel. Value is kNotFound
263 // if there is no transparent pixel.
264 blink::ImageFrame::DisposalMethod
265 disposal_method_; // Restore to background, leave in place, etc.
266 int data_size_;
267
268 bool progressive_display_; // If true, do Haeberli interlace hack.
269 bool interlaced_; // True, if scanlines arrive interlaced order.
270
271 unsigned delay_time_; // Display time, in milliseconds, for this image in a
272 // multi-image GIF.
273
274 std::unique_ptr<GIFLZWContext> lzw_context_;
275 Vector<GIFLZWBlock> lzw_blocks_; // LZW blocks for this frame.
276 GIFColorMap local_color_map_;
277
278 size_t current_lzw_block_;
279 bool is_complete_;
280 bool is_header_defined_;
281 bool is_data_size_defined_;
282 };
283
284 class PLATFORM_EXPORT GIFImageReader final {
285 USING_FAST_MALLOC(GIFImageReader);
286 WTF_MAKE_NONCOPYABLE(GIFImageReader);
287
288 public:
289 GIFImageReader(blink::GIFImageDecoder* client = 0)
290 : client_(client),
291 state_(kGIFType),
292 // Number of bytes for GIF type, either "GIF87a" or "GIF89a".
293 bytes_to_consume_(6),
294 bytes_read_(0),
295 version_(0),
296 screen_width_(0),
297 screen_height_(0),
298 sent_size_to_client_(false),
299 loop_count_(kCLoopCountNotSeen),
300 parse_completed_(false) {}
301
302 ~GIFImageReader() {}
303
304 void SetData(PassRefPtr<blink::SegmentReader> data) {
305 data_ = std::move(data);
306 }
307 bool Parse(blink::GIFImageDecoder::GIFParseQuery);
308 bool Decode(size_t frame_index);
309
310 size_t ImagesCount() const {
311 if (frames_.IsEmpty())
312 return 0;
313
314 // This avoids counting an empty frame when the file is truncated right
315 // after GIFControlExtension but before GIFImageHeader.
316 // FIXME: This extra complexity is not necessary and we should just report
317 // m_frames.size().
318 return frames_.back()->IsHeaderDefined() ? frames_.size()
319 : frames_.size() - 1;
320 }
321 int LoopCount() const { return loop_count_; }
322
323 const GIFColorMap& GlobalColorMap() const { return global_color_map_; }
324
325 const GIFFrameContext* FrameContext(size_t index) const {
326 return index < frames_.size() ? frames_[index].get() : 0;
327 }
328
329 bool ParseCompleted() const { return parse_completed_; }
330
331 void ClearDecodeState(size_t index) { frames_[index]->ClearDecodeState(); }
332
333 private:
334 bool ParseData(size_t data_position,
335 size_t len,
336 blink::GIFImageDecoder::GIFParseQuery);
337 void SetRemainingBytes(size_t);
338
339 void AddFrameIfNecessary();
340 bool CurrentFrameIsFirstFrame() const {
341 return frames_.IsEmpty() ||
342 (frames_.size() == 1u && !frames_[0]->IsComplete());
343 }
344
345 blink::GIFImageDecoder* client_;
346
347 // Parsing state machine.
348 GIFState state_; // Current decoder master state.
349 size_t bytes_to_consume_; // Number of bytes to consume for next stage of
350 // parsing.
351 size_t bytes_read_; // Number of bytes processed.
352
353 // Global (multi-image) state.
354 int version_; // Either 89 for GIF89 or 87 for GIF87.
355 unsigned screen_width_; // Logical screen width & height.
356 unsigned screen_height_;
357 bool sent_size_to_client_;
358 GIFColorMap global_color_map_;
359 int loop_count_; // Netscape specific extension block to control the number
360 // of animation loops a GIF renders.
361
362 Vector<std::unique_ptr<GIFFrameContext>> frames_;
363
364 RefPtr<blink::SegmentReader> data_;
365 bool parse_completed_;
366 };
367
368 } // namespace blink
369
370 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698