Source file
src/image/gif/reader.go
1
2
3
4
5
6
7
8 package gif
9
10 import (
11 "bufio"
12 "compress/lzw"
13 "errors"
14 "fmt"
15 "image"
16 "image/color"
17 "io"
18 )
19
20 var (
21 errNotEnough = errors.New("gif: not enough image data")
22 errTooMuch = errors.New("gif: too much image data")
23 errBadPixel = errors.New("gif: invalid pixel value")
24 )
25
26
27 type reader interface {
28 io.Reader
29 io.ByteReader
30 }
31
32
33 const (
34
35 fColorTable = 1 << 7
36 fInterlace = 1 << 6
37 fColorTableBitsMask = 7
38
39
40 gcTransparentColorSet = 1 << 0
41 gcDisposalMethodMask = 7 << 2
42 )
43
44
45 const (
46 DisposalNone = 0x01
47 DisposalBackground = 0x02
48 DisposalPrevious = 0x03
49 )
50
51
52 const (
53 sExtension = 0x21
54 sImageDescriptor = 0x2C
55 sTrailer = 0x3B
56 )
57
58
59 const (
60 eText = 0x01
61 eGraphicControl = 0xF9
62 eComment = 0xFE
63 eApplication = 0xFF
64 )
65
66 func readFull(r io.Reader, b []byte) error {
67 _, err := io.ReadFull(r, b)
68 if err == io.EOF {
69 err = io.ErrUnexpectedEOF
70 }
71 return err
72 }
73
74 func readByte(r io.ByteReader) (byte, error) {
75 b, err := r.ReadByte()
76 if err == io.EOF {
77 err = io.ErrUnexpectedEOF
78 }
79 return b, err
80 }
81
82
83 type decoder struct {
84 r reader
85
86
87 vers string
88 width int
89 height int
90 loopCount int
91 delayTime int
92 backgroundIndex byte
93 disposalMethod byte
94
95
96 imageFields byte
97
98
99 transparentIndex byte
100 hasTransparentIndex bool
101
102
103 globalColorTable color.Palette
104
105
106 delay []int
107 disposal []byte
108 image []*image.Paletted
109 tmp [1024]byte
110 }
111
112
113
114
115
116
117
118
119
120 type blockReader struct {
121 d *decoder
122 i, j uint8
123 err error
124 }
125
126 func (b *blockReader) fill() {
127 if b.err != nil {
128 return
129 }
130 b.j, b.err = readByte(b.d.r)
131 if b.j == 0 && b.err == nil {
132 b.err = io.EOF
133 }
134 if b.err != nil {
135 return
136 }
137
138 b.i = 0
139 b.err = readFull(b.d.r, b.d.tmp[:b.j])
140 if b.err != nil {
141 b.j = 0
142 }
143 }
144
145 func (b *blockReader) ReadByte() (byte, error) {
146 if b.i == b.j {
147 b.fill()
148 if b.err != nil {
149 return 0, b.err
150 }
151 }
152
153 c := b.d.tmp[b.i]
154 b.i++
155 return c, nil
156 }
157
158
159
160 func (b *blockReader) Read(p []byte) (int, error) {
161 if len(p) == 0 || b.err != nil {
162 return 0, b.err
163 }
164 if b.i == b.j {
165 b.fill()
166 if b.err != nil {
167 return 0, b.err
168 }
169 }
170
171 n := copy(p, b.d.tmp[b.i:b.j])
172 b.i += uint8(n)
173 return n, nil
174 }
175
176
177
178
179
180
181
182
183
184 func (b *blockReader) close() error {
185 if b.err == io.EOF {
186
187 return nil
188 } else if b.err != nil {
189
190 return b.err
191 }
192
193 if b.i == b.j {
194
195
196 b.fill()
197 if b.err == io.EOF {
198 return nil
199 } else if b.err != nil {
200 return b.err
201 } else if b.j > 1 {
202 return errTooMuch
203 }
204 }
205
206
207
208 b.fill()
209 if b.err == io.EOF {
210 return nil
211 } else if b.err != nil {
212 return b.err
213 }
214
215 return errTooMuch
216 }
217
218
219 func (d *decoder) decode(r io.Reader, configOnly, keepAllFrames bool) error {
220
221 if rr, ok := r.(reader); ok {
222 d.r = rr
223 } else {
224 d.r = bufio.NewReader(r)
225 }
226
227 err := d.readHeaderAndScreenDescriptor()
228 if err != nil {
229 return err
230 }
231 if configOnly {
232 return nil
233 }
234
235 for {
236 c, err := readByte(d.r)
237 if err != nil {
238 return fmt.Errorf("gif: reading frames: %v", err)
239 }
240 switch c {
241 case sExtension:
242 if err = d.readExtension(); err != nil {
243 return err
244 }
245
246 case sImageDescriptor:
247 if err = d.readImageDescriptor(keepAllFrames); err != nil {
248 return err
249 }
250
251 case sTrailer:
252 if len(d.image) == 0 {
253 return fmt.Errorf("gif: missing image data")
254 }
255 return nil
256
257 default:
258 return fmt.Errorf("gif: unknown block type: 0x%.2x", c)
259 }
260 }
261 }
262
263 func (d *decoder) readHeaderAndScreenDescriptor() error {
264 err := readFull(d.r, d.tmp[:13])
265 if err != nil {
266 return fmt.Errorf("gif: reading header: %v", err)
267 }
268 d.vers = string(d.tmp[:6])
269 if d.vers != "GIF87a" && d.vers != "GIF89a" {
270 return fmt.Errorf("gif: can't recognize format %q", d.vers)
271 }
272 d.width = int(d.tmp[6]) + int(d.tmp[7])<<8
273 d.height = int(d.tmp[8]) + int(d.tmp[9])<<8
274 if fields := d.tmp[10]; fields&fColorTable != 0 {
275 d.backgroundIndex = d.tmp[11]
276
277 if d.globalColorTable, err = d.readColorTable(fields); err != nil {
278 return err
279 }
280 }
281
282 return nil
283 }
284
285 func (d *decoder) readColorTable(fields byte) (color.Palette, error) {
286 n := 1 << (1 + uint(fields&fColorTableBitsMask))
287 err := readFull(d.r, d.tmp[:3*n])
288 if err != nil {
289 return nil, fmt.Errorf("gif: reading color table: %s", err)
290 }
291 j, p := 0, make(color.Palette, n)
292 for i := range p {
293 p[i] = color.RGBA{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
294 j += 3
295 }
296 return p, nil
297 }
298
299 func (d *decoder) readExtension() error {
300 extension, err := readByte(d.r)
301 if err != nil {
302 return fmt.Errorf("gif: reading extension: %v", err)
303 }
304 size := 0
305 switch extension {
306 case eText:
307 size = 13
308 case eGraphicControl:
309 return d.readGraphicControl()
310 case eComment:
311
312 case eApplication:
313 b, err := readByte(d.r)
314 if err != nil {
315 return fmt.Errorf("gif: reading extension: %v", err)
316 }
317
318 size = int(b)
319 default:
320 return fmt.Errorf("gif: unknown extension 0x%.2x", extension)
321 }
322 if size > 0 {
323 if err := readFull(d.r, d.tmp[:size]); err != nil {
324 return fmt.Errorf("gif: reading extension: %v", err)
325 }
326 }
327
328
329
330 if extension == eApplication && string(d.tmp[:size]) == "NETSCAPE2.0" {
331 n, err := d.readBlock()
332 if err != nil {
333 return fmt.Errorf("gif: reading extension: %v", err)
334 }
335 if n == 0 {
336 return nil
337 }
338 if n == 3 && d.tmp[0] == 1 {
339 d.loopCount = int(d.tmp[1]) | int(d.tmp[2])<<8
340 }
341 }
342 for {
343 n, err := d.readBlock()
344 if err != nil {
345 return fmt.Errorf("gif: reading extension: %v", err)
346 }
347 if n == 0 {
348 return nil
349 }
350 }
351 }
352
353 func (d *decoder) readGraphicControl() error {
354 if err := readFull(d.r, d.tmp[:6]); err != nil {
355 return fmt.Errorf("gif: can't read graphic control: %s", err)
356 }
357 if d.tmp[0] != 4 {
358 return fmt.Errorf("gif: invalid graphic control extension block size: %d", d.tmp[0])
359 }
360 flags := d.tmp[1]
361 d.disposalMethod = (flags & gcDisposalMethodMask) >> 2
362 d.delayTime = int(d.tmp[2]) | int(d.tmp[3])<<8
363 if flags&gcTransparentColorSet != 0 {
364 d.transparentIndex = d.tmp[4]
365 d.hasTransparentIndex = true
366 }
367 if d.tmp[5] != 0 {
368 return fmt.Errorf("gif: invalid graphic control extension block terminator: %d", d.tmp[5])
369 }
370 return nil
371 }
372
373 func (d *decoder) readImageDescriptor(keepAllFrames bool) error {
374 m, err := d.newImageFromDescriptor()
375 if err != nil {
376 return err
377 }
378 useLocalColorTable := d.imageFields&fColorTable != 0
379 if useLocalColorTable {
380 m.Palette, err = d.readColorTable(d.imageFields)
381 if err != nil {
382 return err
383 }
384 } else {
385 if d.globalColorTable == nil {
386 return errors.New("gif: no color table")
387 }
388 m.Palette = d.globalColorTable
389 }
390 if d.hasTransparentIndex {
391 if !useLocalColorTable {
392
393 m.Palette = append(color.Palette(nil), d.globalColorTable...)
394 }
395 if ti := int(d.transparentIndex); ti < len(m.Palette) {
396 m.Palette[ti] = color.RGBA{}
397 } else {
398
399
400
401
402 p := make(color.Palette, ti+1)
403 copy(p, m.Palette)
404 for i := len(m.Palette); i < len(p); i++ {
405 p[i] = color.RGBA{}
406 }
407 m.Palette = p
408 }
409 }
410 litWidth, err := readByte(d.r)
411 if err != nil {
412 return fmt.Errorf("gif: reading image data: %v", err)
413 }
414 if litWidth < 2 || litWidth > 8 {
415 return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
416 }
417
418 br := &blockReader{d: d}
419 lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
420 defer lzwr.Close()
421 if err = readFull(lzwr, m.Pix); err != nil {
422 if err != io.ErrUnexpectedEOF {
423 return fmt.Errorf("gif: reading image data: %v", err)
424 }
425 return errNotEnough
426 }
427
428
429
430
431
432
433
434
435
436
437
438 if n, err := lzwr.Read(d.tmp[256:257]); n != 0 || (err != io.EOF && err != io.ErrUnexpectedEOF) {
439 if err != nil {
440 return fmt.Errorf("gif: reading image data: %v", err)
441 }
442 return errTooMuch
443 }
444
445
446
447 if err := br.close(); err == errTooMuch {
448 return errTooMuch
449 } else if err != nil {
450 return fmt.Errorf("gif: reading image data: %v", err)
451 }
452
453
454 if len(m.Palette) < 256 {
455 for _, pixel := range m.Pix {
456 if int(pixel) >= len(m.Palette) {
457 return errBadPixel
458 }
459 }
460 }
461
462
463 if d.imageFields&fInterlace != 0 {
464 uninterlace(m)
465 }
466
467 if keepAllFrames || len(d.image) == 0 {
468 d.image = append(d.image, m)
469 d.delay = append(d.delay, d.delayTime)
470 d.disposal = append(d.disposal, d.disposalMethod)
471 }
472
473
474
475 d.delayTime = 0
476 d.hasTransparentIndex = false
477 return nil
478 }
479
480 func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
481 if err := readFull(d.r, d.tmp[:9]); err != nil {
482 return nil, fmt.Errorf("gif: can't read image descriptor: %s", err)
483 }
484 left := int(d.tmp[0]) + int(d.tmp[1])<<8
485 top := int(d.tmp[2]) + int(d.tmp[3])<<8
486 width := int(d.tmp[4]) + int(d.tmp[5])<<8
487 height := int(d.tmp[6]) + int(d.tmp[7])<<8
488 d.imageFields = d.tmp[8]
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506 if left+width > d.width || top+height > d.height {
507 return nil, errors.New("gif: frame bounds larger than image bounds")
508 }
509 return image.NewPaletted(image.Rectangle{
510 Min: image.Point{left, top},
511 Max: image.Point{left + width, top + height},
512 }, nil), nil
513 }
514
515 func (d *decoder) readBlock() (int, error) {
516 n, err := readByte(d.r)
517 if n == 0 || err != nil {
518 return 0, err
519 }
520 if err := readFull(d.r, d.tmp[:n]); err != nil {
521 return 0, err
522 }
523 return int(n), nil
524 }
525
526
527 type interlaceScan struct {
528 skip, start int
529 }
530
531
532 var interlacing = []interlaceScan{
533 {8, 0},
534 {8, 4},
535 {4, 2},
536 {2, 1},
537 }
538
539
540 func uninterlace(m *image.Paletted) {
541 var nPix []uint8
542 dx := m.Bounds().Dx()
543 dy := m.Bounds().Dy()
544 nPix = make([]uint8, dx*dy)
545 offset := 0
546 for _, pass := range interlacing {
547 nOffset := pass.start * dx
548 for y := pass.start; y < dy; y += pass.skip {
549 copy(nPix[nOffset:nOffset+dx], m.Pix[offset:offset+dx])
550 offset += dx
551 nOffset += dx * pass.skip
552 }
553 }
554 m.Pix = nPix
555 }
556
557
558
559 func Decode(r io.Reader) (image.Image, error) {
560 var d decoder
561 if err := d.decode(r, false, false); err != nil {
562 return nil, err
563 }
564 return d.image[0], nil
565 }
566
567
568 type GIF struct {
569 Image []*image.Paletted
570 Delay []int
571 LoopCount int
572
573
574
575
576 Disposal []byte
577
578
579
580
581
582
583
584
585
586 Config image.Config
587
588
589 BackgroundIndex byte
590 }
591
592
593
594 func DecodeAll(r io.Reader) (*GIF, error) {
595 var d decoder
596 if err := d.decode(r, false, true); err != nil {
597 return nil, err
598 }
599 gif := &GIF{
600 Image: d.image,
601 LoopCount: d.loopCount,
602 Delay: d.delay,
603 Disposal: d.disposal,
604 Config: image.Config{
605 ColorModel: d.globalColorTable,
606 Width: d.width,
607 Height: d.height,
608 },
609 BackgroundIndex: d.backgroundIndex,
610 }
611 return gif, nil
612 }
613
614
615
616 func DecodeConfig(r io.Reader) (image.Config, error) {
617 var d decoder
618 if err := d.decode(r, true, false); err != nil {
619 return image.Config{}, err
620 }
621 return image.Config{
622 ColorModel: d.globalColorTable,
623 Width: d.width,
624 Height: d.height,
625 }, nil
626 }
627
628 func init() {
629 image.RegisterFormat("gif", "GIF8?a", Decode, DecodeConfig)
630 }
631
View as plain text