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 d.loopCount = -1
228
229 err := d.readHeaderAndScreenDescriptor()
230 if err != nil {
231 return err
232 }
233 if configOnly {
234 return nil
235 }
236
237 for {
238 c, err := readByte(d.r)
239 if err != nil {
240 return fmt.Errorf("gif: reading frames: %v", err)
241 }
242 switch c {
243 case sExtension:
244 if err = d.readExtension(); err != nil {
245 return err
246 }
247
248 case sImageDescriptor:
249 if err = d.readImageDescriptor(keepAllFrames); err != nil {
250 return err
251 }
252
253 case sTrailer:
254 if len(d.image) == 0 {
255 return fmt.Errorf("gif: missing image data")
256 }
257 return nil
258
259 default:
260 return fmt.Errorf("gif: unknown block type: 0x%.2x", c)
261 }
262 }
263 }
264
265 func (d *decoder) readHeaderAndScreenDescriptor() error {
266 err := readFull(d.r, d.tmp[:13])
267 if err != nil {
268 return fmt.Errorf("gif: reading header: %v", err)
269 }
270 d.vers = string(d.tmp[:6])
271 if d.vers != "GIF87a" && d.vers != "GIF89a" {
272 return fmt.Errorf("gif: can't recognize format %q", d.vers)
273 }
274 d.width = int(d.tmp[6]) + int(d.tmp[7])<<8
275 d.height = int(d.tmp[8]) + int(d.tmp[9])<<8
276 if fields := d.tmp[10]; fields&fColorTable != 0 {
277 d.backgroundIndex = d.tmp[11]
278
279 if d.globalColorTable, err = d.readColorTable(fields); err != nil {
280 return err
281 }
282 }
283
284 return nil
285 }
286
287 func (d *decoder) readColorTable(fields byte) (color.Palette, error) {
288 n := 1 << (1 + uint(fields&fColorTableBitsMask))
289 err := readFull(d.r, d.tmp[:3*n])
290 if err != nil {
291 return nil, fmt.Errorf("gif: reading color table: %s", err)
292 }
293 j, p := 0, make(color.Palette, n)
294 for i := range p {
295 p[i] = color.RGBA{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
296 j += 3
297 }
298 return p, nil
299 }
300
301 func (d *decoder) readExtension() error {
302 extension, err := readByte(d.r)
303 if err != nil {
304 return fmt.Errorf("gif: reading extension: %v", err)
305 }
306 size := 0
307 switch extension {
308 case eText:
309 size = 13
310 case eGraphicControl:
311 return d.readGraphicControl()
312 case eComment:
313
314 case eApplication:
315 b, err := readByte(d.r)
316 if err != nil {
317 return fmt.Errorf("gif: reading extension: %v", err)
318 }
319
320 size = int(b)
321 default:
322 return fmt.Errorf("gif: unknown extension 0x%.2x", extension)
323 }
324 if size > 0 {
325 if err := readFull(d.r, d.tmp[:size]); err != nil {
326 return fmt.Errorf("gif: reading extension: %v", err)
327 }
328 }
329
330
331
332 if extension == eApplication && string(d.tmp[:size]) == "NETSCAPE2.0" {
333 n, err := d.readBlock()
334 if err != nil {
335 return fmt.Errorf("gif: reading extension: %v", err)
336 }
337 if n == 0 {
338 return nil
339 }
340 if n == 3 && d.tmp[0] == 1 {
341 d.loopCount = int(d.tmp[1]) | int(d.tmp[2])<<8
342 }
343 }
344 for {
345 n, err := d.readBlock()
346 if err != nil {
347 return fmt.Errorf("gif: reading extension: %v", err)
348 }
349 if n == 0 {
350 return nil
351 }
352 }
353 }
354
355 func (d *decoder) readGraphicControl() error {
356 if err := readFull(d.r, d.tmp[:6]); err != nil {
357 return fmt.Errorf("gif: can't read graphic control: %s", err)
358 }
359 if d.tmp[0] != 4 {
360 return fmt.Errorf("gif: invalid graphic control extension block size: %d", d.tmp[0])
361 }
362 flags := d.tmp[1]
363 d.disposalMethod = (flags & gcDisposalMethodMask) >> 2
364 d.delayTime = int(d.tmp[2]) | int(d.tmp[3])<<8
365 if flags&gcTransparentColorSet != 0 {
366 d.transparentIndex = d.tmp[4]
367 d.hasTransparentIndex = true
368 }
369 if d.tmp[5] != 0 {
370 return fmt.Errorf("gif: invalid graphic control extension block terminator: %d", d.tmp[5])
371 }
372 return nil
373 }
374
375 func (d *decoder) readImageDescriptor(keepAllFrames bool) error {
376 m, err := d.newImageFromDescriptor()
377 if err != nil {
378 return err
379 }
380 useLocalColorTable := d.imageFields&fColorTable != 0
381 if useLocalColorTable {
382 m.Palette, err = d.readColorTable(d.imageFields)
383 if err != nil {
384 return err
385 }
386 } else {
387 if d.globalColorTable == nil {
388 return errors.New("gif: no color table")
389 }
390 m.Palette = d.globalColorTable
391 }
392 if d.hasTransparentIndex {
393 if !useLocalColorTable {
394
395 m.Palette = append(color.Palette(nil), d.globalColorTable...)
396 }
397 if ti := int(d.transparentIndex); ti < len(m.Palette) {
398 m.Palette[ti] = color.RGBA{}
399 } else {
400
401
402
403
404 p := make(color.Palette, ti+1)
405 copy(p, m.Palette)
406 for i := len(m.Palette); i < len(p); i++ {
407 p[i] = color.RGBA{}
408 }
409 m.Palette = p
410 }
411 }
412 litWidth, err := readByte(d.r)
413 if err != nil {
414 return fmt.Errorf("gif: reading image data: %v", err)
415 }
416 if litWidth < 2 || litWidth > 8 {
417 return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
418 }
419
420 br := &blockReader{d: d}
421 lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
422 defer lzwr.Close()
423 if err = readFull(lzwr, m.Pix); err != nil {
424 if err != io.ErrUnexpectedEOF {
425 return fmt.Errorf("gif: reading image data: %v", err)
426 }
427 return errNotEnough
428 }
429
430
431
432
433
434
435
436
437
438
439
440 if n, err := lzwr.Read(d.tmp[256:257]); n != 0 || (err != io.EOF && err != io.ErrUnexpectedEOF) {
441 if err != nil {
442 return fmt.Errorf("gif: reading image data: %v", err)
443 }
444 return errTooMuch
445 }
446
447
448
449 if err := br.close(); err == errTooMuch {
450 return errTooMuch
451 } else if err != nil {
452 return fmt.Errorf("gif: reading image data: %v", err)
453 }
454
455
456 if len(m.Palette) < 256 {
457 for _, pixel := range m.Pix {
458 if int(pixel) >= len(m.Palette) {
459 return errBadPixel
460 }
461 }
462 }
463
464
465 if d.imageFields&fInterlace != 0 {
466 uninterlace(m)
467 }
468
469 if keepAllFrames || len(d.image) == 0 {
470 d.image = append(d.image, m)
471 d.delay = append(d.delay, d.delayTime)
472 d.disposal = append(d.disposal, d.disposalMethod)
473 }
474
475
476
477 d.delayTime = 0
478 d.hasTransparentIndex = false
479 return nil
480 }
481
482 func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
483 if err := readFull(d.r, d.tmp[:9]); err != nil {
484 return nil, fmt.Errorf("gif: can't read image descriptor: %s", err)
485 }
486 left := int(d.tmp[0]) + int(d.tmp[1])<<8
487 top := int(d.tmp[2]) + int(d.tmp[3])<<8
488 width := int(d.tmp[4]) + int(d.tmp[5])<<8
489 height := int(d.tmp[6]) + int(d.tmp[7])<<8
490 d.imageFields = d.tmp[8]
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508 if left+width > d.width || top+height > d.height {
509 return nil, errors.New("gif: frame bounds larger than image bounds")
510 }
511 return image.NewPaletted(image.Rectangle{
512 Min: image.Point{left, top},
513 Max: image.Point{left + width, top + height},
514 }, nil), nil
515 }
516
517 func (d *decoder) readBlock() (int, error) {
518 n, err := readByte(d.r)
519 if n == 0 || err != nil {
520 return 0, err
521 }
522 if err := readFull(d.r, d.tmp[:n]); err != nil {
523 return 0, err
524 }
525 return int(n), nil
526 }
527
528
529 type interlaceScan struct {
530 skip, start int
531 }
532
533
534 var interlacing = []interlaceScan{
535 {8, 0},
536 {8, 4},
537 {4, 2},
538 {2, 1},
539 }
540
541
542 func uninterlace(m *image.Paletted) {
543 var nPix []uint8
544 dx := m.Bounds().Dx()
545 dy := m.Bounds().Dy()
546 nPix = make([]uint8, dx*dy)
547 offset := 0
548 for _, pass := range interlacing {
549 nOffset := pass.start * dx
550 for y := pass.start; y < dy; y += pass.skip {
551 copy(nPix[nOffset:nOffset+dx], m.Pix[offset:offset+dx])
552 offset += dx
553 nOffset += dx * pass.skip
554 }
555 }
556 m.Pix = nPix
557 }
558
559
560
561 func Decode(r io.Reader) (image.Image, error) {
562 var d decoder
563 if err := d.decode(r, false, false); err != nil {
564 return nil, err
565 }
566 return d.image[0], nil
567 }
568
569
570 type GIF struct {
571 Image []*image.Paletted
572 Delay []int
573
574
575
576
577
578 LoopCount int
579
580
581
582
583 Disposal []byte
584
585
586
587
588
589
590
591
592
593 Config image.Config
594
595
596 BackgroundIndex byte
597 }
598
599
600
601 func DecodeAll(r io.Reader) (*GIF, error) {
602 var d decoder
603 if err := d.decode(r, false, true); err != nil {
604 return nil, err
605 }
606 gif := &GIF{
607 Image: d.image,
608 LoopCount: d.loopCount,
609 Delay: d.delay,
610 Disposal: d.disposal,
611 Config: image.Config{
612 ColorModel: d.globalColorTable,
613 Width: d.width,
614 Height: d.height,
615 },
616 BackgroundIndex: d.backgroundIndex,
617 }
618 return gif, nil
619 }
620
621
622
623 func DecodeConfig(r io.Reader) (image.Config, error) {
624 var d decoder
625 if err := d.decode(r, true, false); err != nil {
626 return image.Config{}, err
627 }
628 return image.Config{
629 ColorModel: d.globalColorTable,
630 Width: d.width,
631 Height: d.height,
632 }, nil
633 }
634
635 func init() {
636 image.RegisterFormat("gif", "GIF8?a", Decode, DecodeConfig)
637 }
638
View as plain text