github.com/larkox/mattermost-server@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  }