github.com/vnforks/kid@v5.11.1+incompatible/utils/imgutils/gif.go (about) 1 // Copyright (c) 2011 The Go Authors. 2 // Modified work: Copyright (c) 2019 Mattermost, Inc. All Rights Reserved. 3 // See License.txt for license information. 4 5 package imgutils 6 7 // This contains a portion of Go's image/go library, modified to count the number of frames in a gif without loading 8 // the entire image into memory. 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 ) 24 25 // If the io.Reader does not also have ReadByte, then decode will introduce its own buffering. 26 type reader interface { 27 io.Reader 28 io.ByteReader 29 } 30 31 // Masks etc. 32 const ( 33 // Fields. 34 fColorTable = 1 << 7 35 fInterlace = 1 << 6 36 fColorTableBitsMask = 7 37 38 // Graphic control flags. 39 gcTransparentColorSet = 1 << 0 40 gcDisposalMethodMask = 7 << 2 41 ) 42 43 // Disposal Methods. 44 const ( 45 DisposalNone = 0x01 46 DisposalBackground = 0x02 47 DisposalPrevious = 0x03 48 ) 49 50 // Section indicators. 51 const ( 52 sExtension = 0x21 53 sImageDescriptor = 0x2C 54 sTrailer = 0x3B 55 ) 56 57 // Extensions. 58 const ( 59 eText = 0x01 // Plain Text 60 eGraphicControl = 0xF9 // Graphic Control 61 eComment = 0xFE // Comment 62 eApplication = 0xFF // Application 63 ) 64 65 func readFull(r io.Reader, b []byte) error { 66 _, err := io.ReadFull(r, b) 67 if err == io.EOF { 68 err = io.ErrUnexpectedEOF 69 } 70 return err 71 } 72 73 func readByte(r io.ByteReader) (byte, error) { 74 b, err := r.ReadByte() 75 if err == io.EOF { 76 err = io.ErrUnexpectedEOF 77 } 78 return b, err 79 } 80 81 // decoder is the type used to decode a GIF file. 82 type decoder struct { 83 r reader 84 85 // From header. 86 vers string 87 width int 88 height int 89 loopCount int 90 delayTime int 91 backgroundIndex byte 92 disposalMethod byte 93 94 // From image descriptor. 95 imageFields byte 96 97 // From graphics control. 98 transparentIndex byte 99 hasTransparentIndex bool 100 101 // Computed. 102 globalColorTable color.Palette 103 104 // Used when decoding. 105 imageCount int 106 tmp [1024]byte // must be at least 768 so we can read color table 107 } 108 109 // blockReader parses the block structure of GIF image data, which comprises 110 // (n, (n bytes)) blocks, with 1 <= n <= 255. It is the reader given to the 111 // LZW decoder, which is thus immune to the blocking. After the LZW decoder 112 // completes, there will be a 0-byte block remaining (0, ()), which is 113 // consumed when checking that the blockReader is exhausted. 114 // 115 // To avoid the allocation of a bufio.Reader for the lzw Reader, blockReader 116 // implements io.ReadByte and buffers blocks into the decoder's "tmp" buffer. 117 type blockReader struct { 118 d *decoder 119 i, j uint8 // d.tmp[i:j] contains the buffered bytes 120 err error 121 } 122 123 func (b *blockReader) fill() { 124 if b.err != nil { 125 return 126 } 127 b.j, b.err = readByte(b.d.r) 128 if b.j == 0 && b.err == nil { 129 b.err = io.EOF 130 } 131 if b.err != nil { 132 return 133 } 134 135 b.i = 0 136 b.err = readFull(b.d.r, b.d.tmp[:b.j]) 137 if b.err != nil { 138 b.j = 0 139 } 140 } 141 142 func (b *blockReader) ReadByte() (byte, error) { 143 if b.i == b.j { 144 b.fill() 145 if b.err != nil { 146 return 0, b.err 147 } 148 } 149 150 c := b.d.tmp[b.i] 151 b.i++ 152 return c, nil 153 } 154 155 // blockReader must implement io.Reader, but its Read shouldn't ever actually 156 // be called in practice. The compress/lzw package will only call ReadByte. 157 func (b *blockReader) Read(p []byte) (int, error) { 158 if len(p) == 0 || b.err != nil { 159 return 0, b.err 160 } 161 if b.i == b.j { 162 b.fill() 163 if b.err != nil { 164 return 0, b.err 165 } 166 } 167 168 n := copy(p, b.d.tmp[b.i:b.j]) 169 b.i += uint8(n) 170 return n, nil 171 } 172 173 // close primarily detects whether or not a block terminator was encountered 174 // after reading a sequence of data sub-blocks. It allows at most one trailing 175 // sub-block worth of data. I.e., if some number of bytes exist in one sub-block 176 // following the end of LZW data, the very next sub-block must be the block 177 // terminator. If the very end of LZW data happened to fill one sub-block, at 178 // most one more sub-block of length 1 may exist before the block-terminator. 179 // These accommodations allow us to support GIFs created by less strict encoders. 180 // See https://golang.org/issue/16146. 181 func (b *blockReader) close() error { 182 if b.err == io.EOF { 183 // A clean block-sequence terminator was encountered while reading. 184 return nil 185 } else if b.err != nil { 186 // Some other error was encountered while reading. 187 return b.err 188 } 189 190 if b.i == b.j { 191 // We reached the end of a sub block reading LZW data. We'll allow at 192 // most one more sub block of data with a length of 1 byte. 193 b.fill() 194 if b.err == io.EOF { 195 return nil 196 } else if b.err != nil { 197 return b.err 198 } else if b.j > 1 { 199 return errTooMuch 200 } 201 } 202 203 // Part of a sub-block remains buffered. We expect that the next attempt to 204 // buffer a sub-block will reach the block terminator. 205 b.fill() 206 if b.err == io.EOF { 207 return nil 208 } else if b.err != nil { 209 return b.err 210 } 211 212 return errTooMuch 213 } 214 215 // decode reads a GIF image from r and stores the result in d. 216 func (d *decoder) decode(r io.Reader, configOnly, keepAllFrames bool) error { 217 // Add buffering if r does not provide ReadByte. 218 if rr, ok := r.(reader); ok { 219 d.r = rr 220 } else { 221 d.r = bufio.NewReader(r) 222 } 223 224 d.loopCount = -1 225 226 err := d.readHeaderAndScreenDescriptor() 227 if err != nil { 228 return err 229 } 230 if configOnly { 231 return nil 232 } 233 234 for { 235 c, err := readByte(d.r) 236 if err != nil { 237 return fmt.Errorf("gif: reading frames: %v", err) 238 } 239 switch c { 240 case sExtension: 241 if err = d.readExtension(); err != nil { 242 return err 243 } 244 245 case sImageDescriptor: 246 if err = d.readImageDescriptor(keepAllFrames); err != nil { 247 return err 248 } 249 250 case sTrailer: 251 if d.imageCount == 0 { 252 return fmt.Errorf("gif: missing image data") 253 } 254 return nil 255 256 default: 257 return fmt.Errorf("gif: unknown block type: 0x%.2x", c) 258 } 259 } 260 } 261 262 func (d *decoder) readHeaderAndScreenDescriptor() error { 263 err := readFull(d.r, d.tmp[:13]) 264 if err != nil { 265 return fmt.Errorf("gif: reading header: %v", err) 266 } 267 d.vers = string(d.tmp[:6]) 268 if d.vers != "GIF87a" && d.vers != "GIF89a" { 269 return fmt.Errorf("gif: can't recognize format %q", d.vers) 270 } 271 d.width = int(d.tmp[6]) + int(d.tmp[7])<<8 272 d.height = int(d.tmp[8]) + int(d.tmp[9])<<8 273 if fields := d.tmp[10]; fields&fColorTable != 0 { 274 d.backgroundIndex = d.tmp[11] 275 // readColorTable overwrites the contents of d.tmp, but that's OK. 276 if d.globalColorTable, err = d.readColorTable(fields); err != nil { 277 return err 278 } 279 } 280 // d.tmp[12] is the Pixel Aspect Ratio, which is ignored. 281 return nil 282 } 283 284 func (d *decoder) readColorTable(fields byte) (color.Palette, error) { 285 n := 1 << (1 + uint(fields&fColorTableBitsMask)) 286 err := readFull(d.r, d.tmp[:3*n]) 287 if err != nil { 288 return nil, fmt.Errorf("gif: reading color table: %s", err) 289 } 290 j, p := 0, make(color.Palette, n) 291 for i := range p { 292 p[i] = color.RGBA{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF} 293 j += 3 294 } 295 return p, nil 296 } 297 298 func (d *decoder) readExtension() error { 299 extension, err := readByte(d.r) 300 if err != nil { 301 return fmt.Errorf("gif: reading extension: %v", err) 302 } 303 size := 0 304 switch extension { 305 case eText: 306 size = 13 307 case eGraphicControl: 308 return d.readGraphicControl() 309 case eComment: 310 // nothing to do but read the data. 311 case eApplication: 312 b, err := readByte(d.r) 313 if err != nil { 314 return fmt.Errorf("gif: reading extension: %v", err) 315 } 316 // The spec requires size be 11, but Adobe sometimes uses 10. 317 size = int(b) 318 default: 319 return fmt.Errorf("gif: unknown extension 0x%.2x", extension) 320 } 321 if size > 0 { 322 if err := readFull(d.r, d.tmp[:size]); err != nil { 323 return fmt.Errorf("gif: reading extension: %v", err) 324 } 325 } 326 327 // Application Extension with "NETSCAPE2.0" as string and 1 in data means 328 // this extension defines a loop count. 329 if extension == eApplication && string(d.tmp[:size]) == "NETSCAPE2.0" { 330 n, err := d.readBlock() 331 if err != nil { 332 return fmt.Errorf("gif: reading extension: %v", err) 333 } 334 if n == 0 { 335 return nil 336 } 337 if n == 3 && d.tmp[0] == 1 { 338 d.loopCount = int(d.tmp[1]) | int(d.tmp[2])<<8 339 } 340 } 341 for { 342 n, err := d.readBlock() 343 if err != nil { 344 return fmt.Errorf("gif: reading extension: %v", err) 345 } 346 if n == 0 { 347 return nil 348 } 349 } 350 } 351 352 func (d *decoder) readGraphicControl() error { 353 if err := readFull(d.r, d.tmp[:6]); err != nil { 354 return fmt.Errorf("gif: can't read graphic control: %s", err) 355 } 356 if d.tmp[0] != 4 { 357 return fmt.Errorf("gif: invalid graphic control extension block size: %d", d.tmp[0]) 358 } 359 flags := d.tmp[1] 360 d.disposalMethod = (flags & gcDisposalMethodMask) >> 2 361 d.delayTime = int(d.tmp[2]) | int(d.tmp[3])<<8 362 if flags&gcTransparentColorSet != 0 { 363 d.transparentIndex = d.tmp[4] 364 d.hasTransparentIndex = true 365 } 366 if d.tmp[5] != 0 { 367 return fmt.Errorf("gif: invalid graphic control extension block terminator: %d", d.tmp[5]) 368 } 369 return nil 370 } 371 372 func (d *decoder) readImageDescriptor(keepAllFrames bool) error { 373 m, err := d.newImageFromDescriptor() 374 if err != nil { 375 return err 376 } 377 useLocalColorTable := d.imageFields&fColorTable != 0 378 if useLocalColorTable { 379 m.Palette, err = d.readColorTable(d.imageFields) 380 if err != nil { 381 return err 382 } 383 } else { 384 if d.globalColorTable == nil { 385 return errors.New("gif: no color table") 386 } 387 m.Palette = d.globalColorTable 388 } 389 if d.hasTransparentIndex { 390 if !useLocalColorTable { 391 // Clone the global color table. 392 m.Palette = append(color.Palette(nil), d.globalColorTable...) 393 } 394 if ti := int(d.transparentIndex); ti < len(m.Palette) { 395 m.Palette[ti] = color.RGBA{} 396 } else { 397 // The transparentIndex is out of range, which is an error 398 // according to the spec, but Firefox and Google Chrome 399 // seem OK with this, so we enlarge the palette with 400 // transparent colors. See golang.org/issue/15059. 401 p := make(color.Palette, ti+1) 402 copy(p, m.Palette) 403 for i := len(m.Palette); i < len(p); i++ { 404 p[i] = color.RGBA{} 405 } 406 m.Palette = p 407 } 408 } 409 litWidth, err := readByte(d.r) 410 if err != nil { 411 return fmt.Errorf("gif: reading image data: %v", err) 412 } 413 if litWidth < 2 || litWidth > 8 { 414 return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth) 415 } 416 // A wonderfully Go-like piece of magic. 417 br := &blockReader{d: d} 418 lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth)) 419 defer lzwr.Close() 420 if err = readFull(lzwr, m.Pix); err != nil { 421 if err != io.ErrUnexpectedEOF { 422 return fmt.Errorf("gif: reading image data: %v", err) 423 } 424 return errNotEnough 425 } 426 // In theory, both lzwr and br should be exhausted. Reading from them 427 // should yield (0, io.EOF). 428 // 429 // The spec (Appendix F - Compression), says that "An End of 430 // Information code... must be the last code output by the encoder 431 // for an image". In practice, though, giflib (a widely used C 432 // library) does not enforce this, so we also accept lzwr returning 433 // io.ErrUnexpectedEOF (meaning that the encoded stream hit io.EOF 434 // before the LZW decoder saw an explicit end code), provided that 435 // the io.ReadFull call above successfully read len(m.Pix) bytes. 436 // See https://golang.org/issue/9856 for an example GIF. 437 if n, err := lzwr.Read(d.tmp[256:257]); n != 0 || (err != io.EOF && err != io.ErrUnexpectedEOF) { 438 if err != nil { 439 return fmt.Errorf("gif: reading image data: %v", err) 440 } 441 return errTooMuch 442 } 443 444 // In practice, some GIFs have an extra byte in the data sub-block 445 // stream, which we ignore. See https://golang.org/issue/16146. 446 if err := br.close(); err == errTooMuch { 447 return errTooMuch 448 } else if err != nil { 449 return fmt.Errorf("gif: reading image data: %v", err) 450 } 451 452 d.imageCount += 1 453 454 return nil 455 } 456 457 func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) { 458 if err := readFull(d.r, d.tmp[:9]); err != nil { 459 return nil, fmt.Errorf("gif: can't read image descriptor: %s", err) 460 } 461 left := int(d.tmp[0]) + int(d.tmp[1])<<8 462 top := int(d.tmp[2]) + int(d.tmp[3])<<8 463 width := int(d.tmp[4]) + int(d.tmp[5])<<8 464 height := int(d.tmp[6]) + int(d.tmp[7])<<8 465 d.imageFields = d.tmp[8] 466 467 // The GIF89a spec, Section 20 (Image Descriptor) says: "Each image must 468 // fit within the boundaries of the Logical Screen, as defined in the 469 // Logical Screen Descriptor." 470 // 471 // This is conceptually similar to testing 472 // frameBounds := image.Rect(left, top, left+width, top+height) 473 // imageBounds := image.Rect(0, 0, d.width, d.height) 474 // if !frameBounds.In(imageBounds) { etc } 475 // but the semantics of the Go image.Rectangle type is that r.In(s) is true 476 // whenever r is an empty rectangle, even if r.Min.X > s.Max.X. Here, we 477 // want something stricter. 478 // 479 // Note that, by construction, left >= 0 && top >= 0, so we only have to 480 // explicitly compare frameBounds.Max (left+width, top+height) against 481 // imageBounds.Max (d.width, d.height) and not frameBounds.Min (left, top) 482 // against imageBounds.Min (0, 0). 483 if left+width > d.width || top+height > d.height { 484 return nil, errors.New("gif: frame bounds larger than image bounds") 485 } 486 return image.NewPaletted(image.Rectangle{ 487 Min: image.Point{left, top}, 488 Max: image.Point{left + width, top + height}, 489 }, nil), nil 490 } 491 492 func (d *decoder) readBlock() (int, error) { 493 n, err := readByte(d.r) 494 if n == 0 || err != nil { 495 return 0, err 496 } 497 if err := readFull(d.r, d.tmp[:n]); err != nil { 498 return 0, err 499 } 500 return int(n), nil 501 } 502 503 func CountFrames(r io.Reader) (int, error) { 504 var d decoder 505 if err := d.decode(r, false, true); err != nil { 506 return -1, err 507 } 508 return d.imageCount, nil 509 }