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

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

Powered by Google App Engine
This is Rietveld 408576698