summaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/image/tiff
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/image/tiff')
-rw-r--r--vendor/golang.org/x/image/tiff/buffer.go69
-rw-r--r--vendor/golang.org/x/image/tiff/compress.go58
-rw-r--r--vendor/golang.org/x/image/tiff/consts.go149
-rw-r--r--vendor/golang.org/x/image/tiff/fuzz.go30
-rw-r--r--vendor/golang.org/x/image/tiff/lzw/reader.go272
-rw-r--r--vendor/golang.org/x/image/tiff/reader.go709
-rw-r--r--vendor/golang.org/x/image/tiff/writer.go438
7 files changed, 0 insertions, 1725 deletions
diff --git a/vendor/golang.org/x/image/tiff/buffer.go b/vendor/golang.org/x/image/tiff/buffer.go
deleted file mode 100644
index d1801be4..00000000
--- a/vendor/golang.org/x/image/tiff/buffer.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package tiff
-
-import "io"
-
-// buffer buffers an io.Reader to satisfy io.ReaderAt.
-type buffer struct {
- r io.Reader
- buf []byte
-}
-
-// fill reads data from b.r until the buffer contains at least end bytes.
-func (b *buffer) fill(end int) error {
- m := len(b.buf)
- if end > m {
- if end > cap(b.buf) {
- newcap := 1024
- for newcap < end {
- newcap *= 2
- }
- newbuf := make([]byte, end, newcap)
- copy(newbuf, b.buf)
- b.buf = newbuf
- } else {
- b.buf = b.buf[:end]
- }
- if n, err := io.ReadFull(b.r, b.buf[m:end]); err != nil {
- end = m + n
- b.buf = b.buf[:end]
- return err
- }
- }
- return nil
-}
-
-func (b *buffer) ReadAt(p []byte, off int64) (int, error) {
- o := int(off)
- end := o + len(p)
- if int64(end) != off+int64(len(p)) {
- return 0, io.ErrUnexpectedEOF
- }
-
- err := b.fill(end)
- return copy(p, b.buf[o:end]), err
-}
-
-// Slice returns a slice of the underlying buffer. The slice contains
-// n bytes starting at offset off.
-func (b *buffer) Slice(off, n int) ([]byte, error) {
- end := off + n
- if err := b.fill(end); err != nil {
- return nil, err
- }
- return b.buf[off:end], nil
-}
-
-// newReaderAt converts an io.Reader into an io.ReaderAt.
-func newReaderAt(r io.Reader) io.ReaderAt {
- if ra, ok := r.(io.ReaderAt); ok {
- return ra
- }
- return &buffer{
- r: r,
- buf: make([]byte, 0, 1024),
- }
-}
diff --git a/vendor/golang.org/x/image/tiff/compress.go b/vendor/golang.org/x/image/tiff/compress.go
deleted file mode 100644
index 3f176f00..00000000
--- a/vendor/golang.org/x/image/tiff/compress.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package tiff
-
-import (
- "bufio"
- "io"
-)
-
-type byteReader interface {
- io.Reader
- io.ByteReader
-}
-
-// unpackBits decodes the PackBits-compressed data in src and returns the
-// uncompressed data.
-//
-// The PackBits compression format is described in section 9 (p. 42)
-// of the TIFF spec.
-func unpackBits(r io.Reader) ([]byte, error) {
- buf := make([]byte, 128)
- dst := make([]byte, 0, 1024)
- br, ok := r.(byteReader)
- if !ok {
- br = bufio.NewReader(r)
- }
-
- for {
- b, err := br.ReadByte()
- if err != nil {
- if err == io.EOF {
- return dst, nil
- }
- return nil, err
- }
- code := int(int8(b))
- switch {
- case code >= 0:
- n, err := io.ReadFull(br, buf[:code+1])
- if err != nil {
- return nil, err
- }
- dst = append(dst, buf[:n]...)
- case code == -128:
- // No-op.
- default:
- if b, err = br.ReadByte(); err != nil {
- return nil, err
- }
- for j := 0; j < 1-code; j++ {
- buf[j] = b
- }
- dst = append(dst, buf[:1-code]...)
- }
- }
-}
diff --git a/vendor/golang.org/x/image/tiff/consts.go b/vendor/golang.org/x/image/tiff/consts.go
deleted file mode 100644
index 3e5f7f14..00000000
--- a/vendor/golang.org/x/image/tiff/consts.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package tiff
-
-// A tiff image file contains one or more images. The metadata
-// of each image is contained in an Image File Directory (IFD),
-// which contains entries of 12 bytes each and is described
-// on page 14-16 of the specification. An IFD entry consists of
-//
-// - a tag, which describes the signification of the entry,
-// - the data type and length of the entry,
-// - the data itself or a pointer to it if it is more than 4 bytes.
-//
-// The presence of a length means that each IFD is effectively an array.
-
-const (
- leHeader = "II\x2A\x00" // Header for little-endian files.
- beHeader = "MM\x00\x2A" // Header for big-endian files.
-
- ifdLen = 12 // Length of an IFD entry in bytes.
-)
-
-// Data types (p. 14-16 of the spec).
-const (
- dtByte = 1
- dtASCII = 2
- dtShort = 3
- dtLong = 4
- dtRational = 5
-)
-
-// The length of one instance of each data type in bytes.
-var lengths = [...]uint32{0, 1, 1, 2, 4, 8}
-
-// Tags (see p. 28-41 of the spec).
-const (
- tImageWidth = 256
- tImageLength = 257
- tBitsPerSample = 258
- tCompression = 259
- tPhotometricInterpretation = 262
-
- tFillOrder = 266
-
- tStripOffsets = 273
- tSamplesPerPixel = 277
- tRowsPerStrip = 278
- tStripByteCounts = 279
-
- tT4Options = 292 // CCITT Group 3 options, a set of 32 flag bits.
- tT6Options = 293 // CCITT Group 4 options, a set of 32 flag bits.
-
- tTileWidth = 322
- tTileLength = 323
- tTileOffsets = 324
- tTileByteCounts = 325
-
- tXResolution = 282
- tYResolution = 283
- tResolutionUnit = 296
-
- tPredictor = 317
- tColorMap = 320
- tExtraSamples = 338
- tSampleFormat = 339
-)
-
-// Compression types (defined in various places in the spec and supplements).
-const (
- cNone = 1
- cCCITT = 2
- cG3 = 3 // Group 3 Fax.
- cG4 = 4 // Group 4 Fax.
- cLZW = 5
- cJPEGOld = 6 // Superseded by cJPEG.
- cJPEG = 7
- cDeflate = 8 // zlib compression.
- cPackBits = 32773
- cDeflateOld = 32946 // Superseded by cDeflate.
-)
-
-// Photometric interpretation values (see p. 37 of the spec).
-const (
- pWhiteIsZero = 0
- pBlackIsZero = 1
- pRGB = 2
- pPaletted = 3
- pTransMask = 4 // transparency mask
- pCMYK = 5
- pYCbCr = 6
- pCIELab = 8
-)
-
-// Values for the tPredictor tag (page 64-65 of the spec).
-const (
- prNone = 1
- prHorizontal = 2
-)
-
-// Values for the tResolutionUnit tag (page 18).
-const (
- resNone = 1
- resPerInch = 2 // Dots per inch.
- resPerCM = 3 // Dots per centimeter.
-)
-
-// imageMode represents the mode of the image.
-type imageMode int
-
-const (
- mBilevel imageMode = iota
- mPaletted
- mGray
- mGrayInvert
- mRGB
- mRGBA
- mNRGBA
- mCMYK
-)
-
-// CompressionType describes the type of compression used in Options.
-type CompressionType int
-
-// Constants for supported compression types.
-const (
- Uncompressed CompressionType = iota
- Deflate
- LZW
- CCITTGroup3
- CCITTGroup4
-)
-
-// specValue returns the compression type constant from the TIFF spec that
-// is equivalent to c.
-func (c CompressionType) specValue() uint32 {
- switch c {
- case LZW:
- return cLZW
- case Deflate:
- return cDeflate
- case CCITTGroup3:
- return cG3
- case CCITTGroup4:
- return cG4
- }
- return cNone
-}
diff --git a/vendor/golang.org/x/image/tiff/fuzz.go b/vendor/golang.org/x/image/tiff/fuzz.go
deleted file mode 100644
index b27c5400..00000000
--- a/vendor/golang.org/x/image/tiff/fuzz.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build gofuzz
-// +build gofuzz
-
-package tiff
-
-import "bytes"
-
-func Fuzz(data []byte) int {
- cfg, err := DecodeConfig(bytes.NewReader(data))
- if err != nil {
- return 0
- }
- if cfg.Width*cfg.Height > 1e6 {
- return 0
- }
- img, err := Decode(bytes.NewReader(data))
- if err != nil {
- return 0
- }
- var w bytes.Buffer
- err = Encode(&w, img, nil)
- if err != nil {
- panic(err)
- }
- return 1
-}
diff --git a/vendor/golang.org/x/image/tiff/lzw/reader.go b/vendor/golang.org/x/image/tiff/lzw/reader.go
deleted file mode 100644
index 78204ba9..00000000
--- a/vendor/golang.org/x/image/tiff/lzw/reader.go
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package lzw implements the Lempel-Ziv-Welch compressed data format,
-// described in T. A. Welch, ``A Technique for High-Performance Data
-// Compression'', Computer, 17(6) (June 1984), pp 8-19.
-//
-// In particular, it implements LZW as used by the TIFF file format, including
-// an "off by one" algorithmic difference when compared to standard LZW.
-package lzw // import "golang.org/x/image/tiff/lzw"
-
-/*
-This file was branched from src/pkg/compress/lzw/reader.go in the
-standard library. Differences from the original are marked with "NOTE".
-
-The tif_lzw.c file in the libtiff C library has this comment:
-
-----
-The 5.0 spec describes a different algorithm than Aldus
-implements. Specifically, Aldus does code length transitions
-one code earlier than should be done (for real LZW).
-Earlier versions of this library implemented the correct
-LZW algorithm, but emitted codes in a bit order opposite
-to the TIFF spec. Thus, to maintain compatibility w/ Aldus
-we interpret MSB-LSB ordered codes to be images written w/
-old versions of this library, but otherwise adhere to the
-Aldus "off by one" algorithm.
-----
-
-The Go code doesn't read (invalid) TIFF files written by old versions of
-libtiff, but the LZW algorithm in this package still differs from the one in
-Go's standard package library to accomodate this "off by one" in valid TIFFs.
-*/
-
-import (
- "bufio"
- "errors"
- "fmt"
- "io"
-)
-
-// Order specifies the bit ordering in an LZW data stream.
-type Order int
-
-const (
- // LSB means Least Significant Bits first, as used in the GIF file format.
- LSB Order = iota
- // MSB means Most Significant Bits first, as used in the TIFF and PDF
- // file formats.
- MSB
-)
-
-const (
- maxWidth = 12
- decoderInvalidCode = 0xffff
- flushBuffer = 1 << maxWidth
-)
-
-// decoder is the state from which the readXxx method converts a byte
-// stream into a code stream.
-type decoder struct {
- r io.ByteReader
- bits uint32
- nBits uint
- width uint
- read func(*decoder) (uint16, error) // readLSB or readMSB
- litWidth int // width in bits of literal codes
- err error
-
- // The first 1<<litWidth codes are literal codes.
- // The next two codes mean clear and EOF.
- // Other valid codes are in the range [lo, hi] where lo := clear + 2,
- // with the upper bound incrementing on each code seen.
- // overflow is the code at which hi overflows the code width. NOTE: TIFF's LZW is "off by one".
- // last is the most recently seen code, or decoderInvalidCode.
- clear, eof, hi, overflow, last uint16
-
- // Each code c in [lo, hi] expands to two or more bytes. For c != hi:
- // suffix[c] is the last of these bytes.
- // prefix[c] is the code for all but the last byte.
- // This code can either be a literal code or another code in [lo, c).
- // The c == hi case is a special case.
- suffix [1 << maxWidth]uint8
- prefix [1 << maxWidth]uint16
-
- // output is the temporary output buffer.
- // Literal codes are accumulated from the start of the buffer.
- // Non-literal codes decode to a sequence of suffixes that are first
- // written right-to-left from the end of the buffer before being copied
- // to the start of the buffer.
- // It is flushed when it contains >= 1<<maxWidth bytes,
- // so that there is always room to decode an entire code.
- output [2 * 1 << maxWidth]byte
- o int // write index into output
- toRead []byte // bytes to return from Read
-}
-
-// readLSB returns the next code for "Least Significant Bits first" data.
-func (d *decoder) readLSB() (uint16, error) {
- for d.nBits < d.width {
- x, err := d.r.ReadByte()
- if err != nil {
- return 0, err
- }
- d.bits |= uint32(x) << d.nBits
- d.nBits += 8
- }
- code := uint16(d.bits & (1<<d.width - 1))
- d.bits >>= d.width
- d.nBits -= d.width
- return code, nil
-}
-
-// readMSB returns the next code for "Most Significant Bits first" data.
-func (d *decoder) readMSB() (uint16, error) {
- for d.nBits < d.width {
- x, err := d.r.ReadByte()
- if err != nil {
- return 0, err
- }
- d.bits |= uint32(x) << (24 - d.nBits)
- d.nBits += 8
- }
- code := uint16(d.bits >> (32 - d.width))
- d.bits <<= d.width
- d.nBits -= d.width
- return code, nil
-}
-
-func (d *decoder) Read(b []byte) (int, error) {
- for {
- if len(d.toRead) > 0 {
- n := copy(b, d.toRead)
- d.toRead = d.toRead[n:]
- return n, nil
- }
- if d.err != nil {
- return 0, d.err
- }
- d.decode()
- }
-}
-
-// decode decompresses bytes from r and leaves them in d.toRead.
-// read specifies how to decode bytes into codes.
-// litWidth is the width in bits of literal codes.
-func (d *decoder) decode() {
- // Loop over the code stream, converting codes into decompressed bytes.
-loop:
- for {
- code, err := d.read(d)
- if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- d.err = err
- break
- }
- switch {
- case code < d.clear:
- // We have a literal code.
- d.output[d.o] = uint8(code)
- d.o++
- if d.last != decoderInvalidCode {
- // Save what the hi code expands to.
- d.suffix[d.hi] = uint8(code)
- d.prefix[d.hi] = d.last
- }
- case code == d.clear:
- d.width = 1 + uint(d.litWidth)
- d.hi = d.eof
- d.overflow = 1 << d.width
- d.last = decoderInvalidCode
- continue
- case code == d.eof:
- d.err = io.EOF
- break loop
- case code <= d.hi:
- c, i := code, len(d.output)-1
- if code == d.hi && d.last != decoderInvalidCode {
- // code == hi is a special case which expands to the last expansion
- // followed by the head of the last expansion. To find the head, we walk
- // the prefix chain until we find a literal code.
- c = d.last
- for c >= d.clear {
- c = d.prefix[c]
- }
- d.output[i] = uint8(c)
- i--
- c = d.last
- }
- // Copy the suffix chain into output and then write that to w.
- for c >= d.clear {
- d.output[i] = d.suffix[c]
- i--
- c = d.prefix[c]
- }
- d.output[i] = uint8(c)
- d.o += copy(d.output[d.o:], d.output[i:])
- if d.last != decoderInvalidCode {
- // Save what the hi code expands to.
- d.suffix[d.hi] = uint8(c)
- d.prefix[d.hi] = d.last
- }
- default:
- d.err = errors.New("lzw: invalid code")
- break loop
- }
- d.last, d.hi = code, d.hi+1
- if d.hi+1 >= d.overflow { // NOTE: the "+1" is where TIFF's LZW differs from the standard algorithm.
- if d.width == maxWidth {
- d.last = decoderInvalidCode
- } else {
- d.width++
- d.overflow <<= 1
- }
- }
- if d.o >= flushBuffer {
- break
- }
- }
- // Flush pending output.
- d.toRead = d.output[:d.o]
- d.o = 0
-}
-
-var errClosed = errors.New("lzw: reader/writer is closed")
-
-func (d *decoder) Close() error {
- d.err = errClosed // in case any Reads come along
- return nil
-}
-
-// NewReader creates a new io.ReadCloser.
-// Reads from the returned io.ReadCloser read and decompress data from r.
-// If r does not also implement io.ByteReader,
-// the decompressor may read more data than necessary from r.
-// It is the caller's responsibility to call Close on the ReadCloser when
-// finished reading.
-// The number of bits to use for literal codes, litWidth, must be in the
-// range [2,8] and is typically 8. It must equal the litWidth
-// used during compression.
-func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser {
- d := new(decoder)
- switch order {
- case LSB:
- d.read = (*decoder).readLSB
- case MSB:
- d.read = (*decoder).readMSB
- default:
- d.err = errors.New("lzw: unknown order")
- return d
- }
- if litWidth < 2 || 8 < litWidth {
- d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
- return d
- }
- if br, ok := r.(io.ByteReader); ok {
- d.r = br
- } else {
- d.r = bufio.NewReader(r)
- }
- d.litWidth = litWidth
- d.width = 1 + uint(litWidth)
- d.clear = uint16(1) << uint(litWidth)
- d.eof, d.hi = d.clear+1, d.clear+1
- d.overflow = uint16(1) << d.width
- d.last = decoderInvalidCode
-
- return d
-}
diff --git a/vendor/golang.org/x/image/tiff/reader.go b/vendor/golang.org/x/image/tiff/reader.go
deleted file mode 100644
index de73f4b9..00000000
--- a/vendor/golang.org/x/image/tiff/reader.go
+++ /dev/null
@@ -1,709 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package tiff implements a TIFF image decoder and encoder.
-//
-// The TIFF specification is at http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
-package tiff // import "golang.org/x/image/tiff"
-
-import (
- "compress/zlib"
- "encoding/binary"
- "fmt"
- "image"
- "image/color"
- "io"
- "io/ioutil"
- "math"
-
- "golang.org/x/image/ccitt"
- "golang.org/x/image/tiff/lzw"
-)
-
-// A FormatError reports that the input is not a valid TIFF image.
-type FormatError string
-
-func (e FormatError) Error() string {
- return "tiff: invalid format: " + string(e)
-}
-
-// An UnsupportedError reports that the input uses a valid but
-// unimplemented feature.
-type UnsupportedError string
-
-func (e UnsupportedError) Error() string {
- return "tiff: unsupported feature: " + string(e)
-}
-
-var errNoPixels = FormatError("not enough pixel data")
-
-type decoder struct {
- r io.ReaderAt
- byteOrder binary.ByteOrder
- config image.Config
- mode imageMode
- bpp uint
- features map[int][]uint
- palette []color.Color
-
- buf []byte
- off int // Current offset in buf.
- v uint32 // Buffer value for reading with arbitrary bit depths.
- nbits uint // Remaining number of bits in v.
-}
-
-// firstVal returns the first uint of the features entry with the given tag,
-// or 0 if the tag does not exist.
-func (d *decoder) firstVal(tag int) uint {
- f := d.features[tag]
- if len(f) == 0 {
- return 0
- }
- return f[0]
-}
-
-// ifdUint decodes the IFD entry in p, which must be of the Byte, Short
-// or Long type, and returns the decoded uint values.
-func (d *decoder) ifdUint(p []byte) (u []uint, err error) {
- var raw []byte
- if len(p) < ifdLen {
- return nil, FormatError("bad IFD entry")
- }
-
- datatype := d.byteOrder.Uint16(p[2:4])
- if dt := int(datatype); dt <= 0 || dt >= len(lengths) {
- return nil, UnsupportedError("IFD entry datatype")
- }
-
- count := d.byteOrder.Uint32(p[4:8])
- if count > math.MaxInt32/lengths[datatype] {
- return nil, FormatError("IFD data too large")
- }
- if datalen := lengths[datatype] * count; datalen > 4 {
- // The IFD contains a pointer to the real value.
- raw = make([]byte, datalen)
- _, err = d.r.ReadAt(raw, int64(d.byteOrder.Uint32(p[8:12])))
- } else {
- raw = p[8 : 8+datalen]
- }
- if err != nil {
- return nil, err
- }
-
- u = make([]uint, count)
- switch datatype {
- case dtByte:
- for i := uint32(0); i < count; i++ {
- u[i] = uint(raw[i])
- }
- case dtShort:
- for i := uint32(0); i < count; i++ {
- u[i] = uint(d.byteOrder.Uint16(raw[2*i : 2*(i+1)]))
- }
- case dtLong:
- for i := uint32(0); i < count; i++ {
- u[i] = uint(d.byteOrder.Uint32(raw[4*i : 4*(i+1)]))
- }
- default:
- return nil, UnsupportedError("data type")
- }
- return u, nil
-}
-
-// parseIFD decides whether the IFD entry in p is "interesting" and
-// stows away the data in the decoder. It returns the tag number of the
-// entry and an error, if any.
-func (d *decoder) parseIFD(p []byte) (int, error) {
- tag := d.byteOrder.Uint16(p[0:2])
- switch tag {
- case tBitsPerSample,
- tExtraSamples,
- tPhotometricInterpretation,
- tCompression,
- tPredictor,
- tStripOffsets,
- tStripByteCounts,
- tRowsPerStrip,
- tTileWidth,
- tTileLength,
- tTileOffsets,
- tTileByteCounts,
- tImageLength,
- tImageWidth,
- tFillOrder,
- tT4Options,
- tT6Options:
- val, err := d.ifdUint(p)
- if err != nil {
- return 0, err
- }
- d.features[int(tag)] = val
- case tColorMap:
- val, err := d.ifdUint(p)
- if err != nil {
- return 0, err
- }
- numcolors := len(val) / 3
- if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 {
- return 0, FormatError("bad ColorMap length")
- }
- d.palette = make([]color.Color, numcolors)
- for i := 0; i < numcolors; i++ {
- d.palette[i] = color.RGBA64{
- uint16(val[i]),
- uint16(val[i+numcolors]),
- uint16(val[i+2*numcolors]),
- 0xffff,
- }
- }
- case tSampleFormat:
- // Page 27 of the spec: If the SampleFormat is present and
- // the value is not 1 [= unsigned integer data], a Baseline
- // TIFF reader that cannot handle the SampleFormat value
- // must terminate the import process gracefully.
- val, err := d.ifdUint(p)
- if err != nil {
- return 0, err
- }
- for _, v := range val {
- if v != 1 {
- return 0, UnsupportedError("sample format")
- }
- }
- }
- return int(tag), nil
-}
-
-// readBits reads n bits from the internal buffer starting at the current offset.
-func (d *decoder) readBits(n uint) (v uint32, ok bool) {
- for d.nbits < n {
- d.v <<= 8
- if d.off >= len(d.buf) {
- return 0, false
- }
- d.v |= uint32(d.buf[d.off])
- d.off++
- d.nbits += 8
- }
- d.nbits -= n
- rv := d.v >> d.nbits
- d.v &^= rv << d.nbits
- return rv, true
-}
-
-// flushBits discards the unread bits in the buffer used by readBits.
-// It is used at the end of a line.
-func (d *decoder) flushBits() {
- d.v = 0
- d.nbits = 0
-}
-
-// minInt returns the smaller of x or y.
-func minInt(a, b int) int {
- if a <= b {
- return a
- }
- return b
-}
-
-// decode decodes the raw data of an image.
-// It reads from d.buf and writes the strip or tile into dst.
-func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
- d.off = 0
-
- // Apply horizontal predictor if necessary.
- // In this case, p contains the color difference to the preceding pixel.
- // See page 64-65 of the spec.
- if d.firstVal(tPredictor) == prHorizontal {
- switch d.bpp {
- case 16:
- var off int
- n := 2 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
- for y := ymin; y < ymax; y++ {
- off += n
- for x := 0; x < (xmax-xmin-1)*n; x += 2 {
- if off+2 > len(d.buf) {
- return errNoPixels
- }
- v0 := d.byteOrder.Uint16(d.buf[off-n : off-n+2])
- v1 := d.byteOrder.Uint16(d.buf[off : off+2])
- d.byteOrder.PutUint16(d.buf[off:off+2], v1+v0)
- off += 2
- }
- }
- case 8:
- var off int
- n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
- for y := ymin; y < ymax; y++ {
- off += n
- for x := 0; x < (xmax-xmin-1)*n; x++ {
- if off >= len(d.buf) {
- return errNoPixels
- }
- d.buf[off] += d.buf[off-n]
- off++
- }
- }
- case 1:
- return UnsupportedError("horizontal predictor with 1 BitsPerSample")
- }
- }
-
- rMaxX := minInt(xmax, dst.Bounds().Max.X)
- rMaxY := minInt(ymax, dst.Bounds().Max.Y)
- switch d.mode {
- case mGray, mGrayInvert:
- if d.bpp == 16 {
- img := dst.(*image.Gray16)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- if d.off+2 > len(d.buf) {
- return errNoPixels
- }
- v := d.byteOrder.Uint16(d.buf[d.off : d.off+2])
- d.off += 2
- if d.mode == mGrayInvert {
- v = 0xffff - v
- }
- img.SetGray16(x, y, color.Gray16{v})
- }
- if rMaxX == img.Bounds().Max.X {
- d.off += 2 * (xmax - img.Bounds().Max.X)
- }
- }
- } else {
- img := dst.(*image.Gray)
- max := uint32((1 << d.bpp) - 1)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- v, ok := d.readBits(d.bpp)
- if !ok {
- return errNoPixels
- }
- v = v * 0xff / max
- if d.mode == mGrayInvert {
- v = 0xff - v
- }
- img.SetGray(x, y, color.Gray{uint8(v)})
- }
- d.flushBits()
- }
- }
- case mPaletted:
- img := dst.(*image.Paletted)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- v, ok := d.readBits(d.bpp)
- if !ok {
- return errNoPixels
- }
- img.SetColorIndex(x, y, uint8(v))
- }
- d.flushBits()
- }
- case mRGB:
- if d.bpp == 16 {
- img := dst.(*image.RGBA64)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- if d.off+6 > len(d.buf) {
- return errNoPixels
- }
- r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
- g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
- b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
- d.off += 6
- img.SetRGBA64(x, y, color.RGBA64{r, g, b, 0xffff})
- }
- }
- } else {
- img := dst.(*image.RGBA)
- for y := ymin; y < rMaxY; y++ {
- min := img.PixOffset(xmin, y)
- max := img.PixOffset(rMaxX, y)
- off := (y - ymin) * (xmax - xmin) * 3
- for i := min; i < max; i += 4 {
- if off+3 > len(d.buf) {
- return errNoPixels
- }
- img.Pix[i+0] = d.buf[off+0]
- img.Pix[i+1] = d.buf[off+1]
- img.Pix[i+2] = d.buf[off+2]
- img.Pix[i+3] = 0xff
- off += 3
- }
- }
- }
- case mNRGBA:
- if d.bpp == 16 {
- img := dst.(*image.NRGBA64)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- if d.off+8 > len(d.buf) {
- return errNoPixels
- }
- r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
- g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
- b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
- a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8])
- d.off += 8
- img.SetNRGBA64(x, y, color.NRGBA64{r, g, b, a})
- }
- }
- } else {
- img := dst.(*image.NRGBA)
- for y := ymin; y < rMaxY; y++ {
- min := img.PixOffset(xmin, y)
- max := img.PixOffset(rMaxX, y)
- i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
- if i1 > len(d.buf) {
- return errNoPixels
- }
- copy(img.Pix[min:max], d.buf[i0:i1])
- }
- }
- case mRGBA:
- if d.bpp == 16 {
- img := dst.(*image.RGBA64)
- for y := ymin; y < rMaxY; y++ {
- for x := xmin; x < rMaxX; x++ {
- if d.off+8 > len(d.buf) {
- return errNoPixels
- }
- r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
- g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
- b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
- a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8])
- d.off += 8
- img.SetRGBA64(x, y, color.RGBA64{r, g, b, a})
- }
- }
- } else {
- img := dst.(*image.RGBA)
- for y := ymin; y < rMaxY; y++ {
- min := img.PixOffset(xmin, y)
- max := img.PixOffset(rMaxX, y)
- i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
- if i1 > len(d.buf) {
- return errNoPixels
- }
- copy(img.Pix[min:max], d.buf[i0:i1])
- }
- }
- }
-
- return nil
-}
-
-func newDecoder(r io.Reader) (*decoder, error) {
- d := &decoder{
- r: newReaderAt(r),
- features: make(map[int][]uint),
- }
-
- p := make([]byte, 8)
- if _, err := d.r.ReadAt(p, 0); err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return nil, err
- }
- switch string(p[0:4]) {
- case leHeader:
- d.byteOrder = binary.LittleEndian
- case beHeader:
- d.byteOrder = binary.BigEndian
- default:
- return nil, FormatError("malformed header")
- }
-
- ifdOffset := int64(d.byteOrder.Uint32(p[4:8]))
-
- // The first two bytes contain the number of entries (12 bytes each).
- if _, err := d.r.ReadAt(p[0:2], ifdOffset); err != nil {
- return nil, err
- }
- numItems := int(d.byteOrder.Uint16(p[0:2]))
-
- // All IFD entries are read in one chunk.
- p = make([]byte, ifdLen*numItems)
- if _, err := d.r.ReadAt(p, ifdOffset+2); err != nil {
- return nil, err
- }
-
- prevTag := -1
- for i := 0; i < len(p); i += ifdLen {
- tag, err := d.parseIFD(p[i : i+ifdLen])
- if err != nil {
- return nil, err
- }
- if tag <= prevTag {
- return nil, FormatError("tags are not sorted in ascending order")
- }
- prevTag = tag
- }
-
- d.config.Width = int(d.firstVal(tImageWidth))
- d.config.Height = int(d.firstVal(tImageLength))
-
- if _, ok := d.features[tBitsPerSample]; !ok {
- // Default is 1 per specification.
- d.features[tBitsPerSample] = []uint{1}
- }
- d.bpp = d.firstVal(tBitsPerSample)
- switch d.bpp {
- case 0:
- return nil, FormatError("BitsPerSample must not be 0")
- case 1, 8, 16:
- // Nothing to do, these are accepted by this implementation.
- default:
- return nil, UnsupportedError(fmt.Sprintf("BitsPerSample of %v", d.bpp))
- }
-
- // Determine the image mode.
- switch d.firstVal(tPhotometricInterpretation) {
- case pRGB:
- if d.bpp == 16 {
- for _, b := range d.features[tBitsPerSample] {
- if b != 16 {
- return nil, FormatError("wrong number of samples for 16bit RGB")
- }
- }
- } else {
- for _, b := range d.features[tBitsPerSample] {
- if b != 8 {
- return nil, FormatError("wrong number of samples for 8bit RGB")
- }
- }
- }
- // RGB images normally have 3 samples per pixel.
- // If there are more, ExtraSamples (p. 31-32 of the spec)
- // gives their meaning (usually an alpha channel).
- //
- // This implementation does not support extra samples
- // of an unspecified type.
- switch len(d.features[tBitsPerSample]) {
- case 3:
- d.mode = mRGB
- if d.bpp == 16 {
- d.config.ColorModel = color.RGBA64Model
- } else {
- d.config.ColorModel = color.RGBAModel
- }
- case 4:
- switch d.firstVal(tExtraSamples) {
- case 1:
- d.mode = mRGBA
- if d.bpp == 16 {
- d.config.ColorModel = color.RGBA64Model
- } else {
- d.config.ColorModel = color.RGBAModel
- }
- case 2:
- d.mode = mNRGBA
- if d.bpp == 16 {
- d.config.ColorModel = color.NRGBA64Model
- } else {
- d.config.ColorModel = color.NRGBAModel
- }
- default:
- return nil, FormatError("wrong number of samples for RGB")
- }
- default:
- return nil, FormatError("wrong number of samples for RGB")
- }
- case pPaletted:
- d.mode = mPaletted
- d.config.ColorModel = color.Palette(d.palette)
- case pWhiteIsZero:
- d.mode = mGrayInvert
- if d.bpp == 16 {
- d.config.ColorModel = color.Gray16Model
- } else {
- d.config.ColorModel = color.GrayModel
- }
- case pBlackIsZero:
- d.mode = mGray
- if d.bpp == 16 {
- d.config.ColorModel = color.Gray16Model
- } else {
- d.config.ColorModel = color.GrayModel
- }
- default:
- return nil, UnsupportedError("color model")
- }
-
- return d, nil
-}
-
-// DecodeConfig returns the color model and dimensions of a TIFF image without
-// decoding the entire image.
-func DecodeConfig(r io.Reader) (image.Config, error) {
- d, err := newDecoder(r)
- if err != nil {
- return image.Config{}, err
- }
- return d.config, nil
-}
-
-func ccittFillOrder(tiffFillOrder uint) ccitt.Order {
- if tiffFillOrder == 2 {
- return ccitt.LSB
- }
- return ccitt.MSB
-}
-
-// Decode reads a TIFF image from r and returns it as an image.Image.
-// The type of Image returned depends on the contents of the TIFF.
-func Decode(r io.Reader) (img image.Image, err error) {
- d, err := newDecoder(r)
- if err != nil {
- return
- }
-
- blockPadding := false
- blockWidth := d.config.Width
- blockHeight := d.config.Height
- blocksAcross := 1
- blocksDown := 1
-
- if d.config.Width == 0 {
- blocksAcross = 0
- }
- if d.config.Height == 0 {
- blocksDown = 0
- }
-
- var blockOffsets, blockCounts []uint
-
- if int(d.firstVal(tTileWidth)) != 0 {
- blockPadding = true
-
- blockWidth = int(d.firstVal(tTileWidth))
- blockHeight = int(d.firstVal(tTileLength))
-
- if blockWidth != 0 {
- blocksAcross = (d.config.Width + blockWidth - 1) / blockWidth
- }
- if blockHeight != 0 {
- blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
- }
-
- blockCounts = d.features[tTileByteCounts]
- blockOffsets = d.features[tTileOffsets]
-
- } else {
- if int(d.firstVal(tRowsPerStrip)) != 0 {
- blockHeight = int(d.firstVal(tRowsPerStrip))
- }
-
- if blockHeight != 0 {
- blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
- }
-
- blockOffsets = d.features[tStripOffsets]
- blockCounts = d.features[tStripByteCounts]
- }
-
- // Check if we have the right number of strips/tiles, offsets and counts.
- if n := blocksAcross * blocksDown; len(blockOffsets) < n || len(blockCounts) < n {
- return nil, FormatError("inconsistent header")
- }
-
- imgRect := image.Rect(0, 0, d.config.Width, d.config.Height)
- switch d.mode {
- case mGray, mGrayInvert:
- if d.bpp == 16 {
- img = image.NewGray16(imgRect)
- } else {
- img = image.NewGray(imgRect)
- }
- case mPaletted:
- img = image.NewPaletted(imgRect, d.palette)
- case mNRGBA:
- if d.bpp == 16 {
- img = image.NewNRGBA64(imgRect)
- } else {
- img = image.NewNRGBA(imgRect)
- }
- case mRGB, mRGBA:
- if d.bpp == 16 {
- img = image.NewRGBA64(imgRect)
- } else {
- img = image.NewRGBA(imgRect)
- }
- }
-
- for i := 0; i < blocksAcross; i++ {
- blkW := blockWidth
- if !blockPadding && i == blocksAcross-1 && d.config.Width%blockWidth != 0 {
- blkW = d.config.Width % blockWidth
- }
- for j := 0; j < blocksDown; j++ {
- blkH := blockHeight
- if !blockPadding && j == blocksDown-1 && d.config.Height%blockHeight != 0 {
- blkH = d.config.Height % blockHeight
- }
- offset := int64(blockOffsets[j*blocksAcross+i])
- n := int64(blockCounts[j*blocksAcross+i])
- switch d.firstVal(tCompression) {
-
- // According to the spec, Compression does not have a default value,
- // but some tools interpret a missing Compression value as none so we do
- // the same.
- case cNone, 0:
- if b, ok := d.r.(*buffer); ok {
- d.buf, err = b.Slice(int(offset), int(n))
- } else {
- d.buf = make([]byte, n)
- _, err = d.r.ReadAt(d.buf, offset)
- }
- case cG3:
- inv := d.firstVal(tPhotometricInterpretation) == pWhiteIsZero
- order := ccittFillOrder(d.firstVal(tFillOrder))
- r := ccitt.NewReader(io.NewSectionReader(d.r, offset, n), order, ccitt.Group3, blkW, blkH, &ccitt.Options{Invert: inv, Align: false})
- d.buf, err = ioutil.ReadAll(r)
- case cG4:
- inv := d.firstVal(tPhotometricInterpretation) == pWhiteIsZero
- order := ccittFillOrder(d.firstVal(tFillOrder))
- r := ccitt.NewReader(io.NewSectionReader(d.r, offset, n), order, ccitt.Group4, blkW, blkH, &ccitt.Options{Invert: inv, Align: false})
- d.buf, err = ioutil.ReadAll(r)
- case cLZW:
- r := lzw.NewReader(io.NewSectionReader(d.r, offset, n), lzw.MSB, 8)
- d.buf, err = ioutil.ReadAll(r)
- r.Close()
- case cDeflate, cDeflateOld:
- var r io.ReadCloser
- r, err = zlib.NewReader(io.NewSectionReader(d.r, offset, n))
- if err != nil {
- return nil, err
- }
- d.buf, err = ioutil.ReadAll(r)
- r.Close()
- case cPackBits:
- d.buf, err = unpackBits(io.NewSectionReader(d.r, offset, n))
- default:
- err = UnsupportedError(fmt.Sprintf("compression value %d", d.firstVal(tCompression)))
- }
- if err != nil {
- return nil, err
- }
-
- xmin := i * blockWidth
- ymin := j * blockHeight
- xmax := xmin + blkW
- ymax := ymin + blkH
- err = d.decode(img, xmin, ymin, xmax, ymax)
- if err != nil {
- return nil, err
- }
- }
- }
- return
-}
-
-func init() {
- image.RegisterFormat("tiff", leHeader, Decode, DecodeConfig)
- image.RegisterFormat("tiff", beHeader, Decode, DecodeConfig)
-}
diff --git a/vendor/golang.org/x/image/tiff/writer.go b/vendor/golang.org/x/image/tiff/writer.go
deleted file mode 100644
index c8a01cea..00000000
--- a/vendor/golang.org/x/image/tiff/writer.go
+++ /dev/null
@@ -1,438 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package tiff
-
-import (
- "bytes"
- "compress/zlib"
- "encoding/binary"
- "image"
- "io"
- "sort"
-)
-
-// The TIFF format allows to choose the order of the different elements freely.
-// The basic structure of a TIFF file written by this package is:
-//
-// 1. Header (8 bytes).
-// 2. Image data.
-// 3. Image File Directory (IFD).
-// 4. "Pointer area" for larger entries in the IFD.
-
-// We only write little-endian TIFF files.
-var enc = binary.LittleEndian
-
-// An ifdEntry is a single entry in an Image File Directory.
-// A value of type dtRational is composed of two 32-bit values,
-// thus data contains two uints (numerator and denominator) for a single number.
-type ifdEntry struct {
- tag int
- datatype int
- data []uint32
-}
-
-func (e ifdEntry) putData(p []byte) {
- for _, d := range e.data {
- switch e.datatype {
- case dtByte, dtASCII:
- p[0] = byte(d)
- p = p[1:]
- case dtShort:
- enc.PutUint16(p, uint16(d))
- p = p[2:]
- case dtLong, dtRational:
- enc.PutUint32(p, uint32(d))
- p = p[4:]
- }
- }
-}
-
-type byTag []ifdEntry
-
-func (d byTag) Len() int { return len(d) }
-func (d byTag) Less(i, j int) bool { return d[i].tag < d[j].tag }
-func (d byTag) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
-
-func encodeGray(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
- if !predictor {
- return writePix(w, pix, dy, dx, stride)
- }
- buf := make([]byte, dx)
- for y := 0; y < dy; y++ {
- min := y*stride + 0
- max := y*stride + dx
- off := 0
- var v0 uint8
- for i := min; i < max; i++ {
- v1 := pix[i]
- buf[off] = v1 - v0
- v0 = v1
- off++
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encodeGray16(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
- buf := make([]byte, dx*2)
- for y := 0; y < dy; y++ {
- min := y*stride + 0
- max := y*stride + dx*2
- off := 0
- var v0 uint16
- for i := min; i < max; i += 2 {
- // An image.Gray16's Pix is in big-endian order.
- v1 := uint16(pix[i])<<8 | uint16(pix[i+1])
- if predictor {
- v0, v1 = v1, v1-v0
- }
- // We only write little-endian TIFF files.
- buf[off+0] = byte(v1)
- buf[off+1] = byte(v1 >> 8)
- off += 2
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
- if !predictor {
- return writePix(w, pix, dy, dx*4, stride)
- }
- buf := make([]byte, dx*4)
- for y := 0; y < dy; y++ {
- min := y*stride + 0
- max := y*stride + dx*4
- off := 0
- var r0, g0, b0, a0 uint8
- for i := min; i < max; i += 4 {
- r1, g1, b1, a1 := pix[i+0], pix[i+1], pix[i+2], pix[i+3]
- buf[off+0] = r1 - r0
- buf[off+1] = g1 - g0
- buf[off+2] = b1 - b0
- buf[off+3] = a1 - a0
- off += 4
- r0, g0, b0, a0 = r1, g1, b1, a1
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encodeRGBA64(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
- buf := make([]byte, dx*8)
- for y := 0; y < dy; y++ {
- min := y*stride + 0
- max := y*stride + dx*8
- off := 0
- var r0, g0, b0, a0 uint16
- for i := min; i < max; i += 8 {
- // An image.RGBA64's Pix is in big-endian order.
- r1 := uint16(pix[i+0])<<8 | uint16(pix[i+1])
- g1 := uint16(pix[i+2])<<8 | uint16(pix[i+3])
- b1 := uint16(pix[i+4])<<8 | uint16(pix[i+5])
- a1 := uint16(pix[i+6])<<8 | uint16(pix[i+7])
- if predictor {
- r0, r1 = r1, r1-r0
- g0, g1 = g1, g1-g0
- b0, b1 = b1, b1-b0
- a0, a1 = a1, a1-a0
- }
- // We only write little-endian TIFF files.
- buf[off+0] = byte(r1)
- buf[off+1] = byte(r1 >> 8)
- buf[off+2] = byte(g1)
- buf[off+3] = byte(g1 >> 8)
- buf[off+4] = byte(b1)
- buf[off+5] = byte(b1 >> 8)
- buf[off+6] = byte(a1)
- buf[off+7] = byte(a1 >> 8)
- off += 8
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encode(w io.Writer, m image.Image, predictor bool) error {
- bounds := m.Bounds()
- buf := make([]byte, 4*bounds.Dx())
- for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
- off := 0
- if predictor {
- var r0, g0, b0, a0 uint8
- for x := bounds.Min.X; x < bounds.Max.X; x++ {
- r, g, b, a := m.At(x, y).RGBA()
- r1 := uint8(r >> 8)
- g1 := uint8(g >> 8)
- b1 := uint8(b >> 8)
- a1 := uint8(a >> 8)
- buf[off+0] = r1 - r0
- buf[off+1] = g1 - g0
- buf[off+2] = b1 - b0
- buf[off+3] = a1 - a0
- off += 4
- r0, g0, b0, a0 = r1, g1, b1, a1
- }
- } else {
- for x := bounds.Min.X; x < bounds.Max.X; x++ {
- r, g, b, a := m.At(x, y).RGBA()
- buf[off+0] = uint8(r >> 8)
- buf[off+1] = uint8(g >> 8)
- buf[off+2] = uint8(b >> 8)
- buf[off+3] = uint8(a >> 8)
- off += 4
- }
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-// writePix writes the internal byte array of an image to w. It is less general
-// but much faster then encode. writePix is used when pix directly
-// corresponds to one of the TIFF image types.
-func writePix(w io.Writer, pix []byte, nrows, length, stride int) error {
- if length == stride {
- _, err := w.Write(pix[:nrows*length])
- return err
- }
- for ; nrows > 0; nrows-- {
- if _, err := w.Write(pix[:length]); err != nil {
- return err
- }
- pix = pix[stride:]
- }
- return nil
-}
-
-func writeIFD(w io.Writer, ifdOffset int, d []ifdEntry) error {
- var buf [ifdLen]byte
- // Make space for "pointer area" containing IFD entry data
- // longer than 4 bytes.
- parea := make([]byte, 1024)
- pstart := ifdOffset + ifdLen*len(d) + 6
- var o int // Current offset in parea.
-
- // The IFD has to be written with the tags in ascending order.
- sort.Sort(byTag(d))
-
- // Write the number of entries in this IFD.
- if err := binary.Write(w, enc, uint16(len(d))); err != nil {
- return err
- }
- for _, ent := range d {
- enc.PutUint16(buf[0:2], uint16(ent.tag))
- enc.PutUint16(buf[2:4], uint16(ent.datatype))
- count := uint32(len(ent.data))
- if ent.datatype == dtRational {
- count /= 2
- }
- enc.PutUint32(buf[4:8], count)
- datalen := int(count * lengths[ent.datatype])
- if datalen <= 4 {
- ent.putData(buf[8:12])
- } else {
- if (o + datalen) > len(parea) {
- newlen := len(parea) + 1024
- for (o + datalen) > newlen {
- newlen += 1024
- }
- newarea := make([]byte, newlen)
- copy(newarea, parea)
- parea = newarea
- }
- ent.putData(parea[o : o+datalen])
- enc.PutUint32(buf[8:12], uint32(pstart+o))
- o += datalen
- }
- if _, err := w.Write(buf[:]); err != nil {
- return err
- }
- }
- // The IFD ends with the offset of the next IFD in the file,
- // or zero if it is the last one (page 14).
- if err := binary.Write(w, enc, uint32(0)); err != nil {
- return err
- }
- _, err := w.Write(parea[:o])
- return err
-}
-
-// Options are the encoding parameters.
-type Options struct {
- // Compression is the type of compression used.
- Compression CompressionType
- // Predictor determines whether a differencing predictor is used;
- // if true, instead of each pixel's color, the color difference to the
- // preceding one is saved. This improves the compression for certain
- // types of images and compressors. For example, it works well for
- // photos with Deflate compression.
- Predictor bool
-}
-
-// Encode writes the image m to w. opt determines the options used for
-// encoding, such as the compression type. If opt is nil, an uncompressed
-// image is written.
-func Encode(w io.Writer, m image.Image, opt *Options) error {
- d := m.Bounds().Size()
-
- compression := uint32(cNone)
- predictor := false
- if opt != nil {
- compression = opt.Compression.specValue()
- // The predictor field is only used with LZW. See page 64 of the spec.
- predictor = opt.Predictor && compression == cLZW
- }
-
- _, err := io.WriteString(w, leHeader)
- if err != nil {
- return err
- }
-
- // Compressed data is written into a buffer first, so that we
- // know the compressed size.
- var buf bytes.Buffer
- // dst holds the destination for the pixel data of the image --
- // either w or a writer to buf.
- var dst io.Writer
- // imageLen is the length of the pixel data in bytes.
- // The offset of the IFD is imageLen + 8 header bytes.
- var imageLen int
-
- switch compression {
- case cNone:
- dst = w
- // Write IFD offset before outputting pixel data.
- switch m.(type) {
- case *image.Paletted:
- imageLen = d.X * d.Y * 1
- case *image.Gray:
- imageLen = d.X * d.Y * 1
- case *image.Gray16:
- imageLen = d.X * d.Y * 2
- case *image.RGBA64:
- imageLen = d.X * d.Y * 8
- case *image.NRGBA64:
- imageLen = d.X * d.Y * 8
- default:
- imageLen = d.X * d.Y * 4
- }
- err = binary.Write(w, enc, uint32(imageLen+8))
- if err != nil {
- return err
- }
- case cDeflate:
- dst = zlib.NewWriter(&buf)
- }
-
- pr := uint32(prNone)
- photometricInterpretation := uint32(pRGB)
- samplesPerPixel := uint32(4)
- bitsPerSample := []uint32{8, 8, 8, 8}
- extraSamples := uint32(0)
- colorMap := []uint32{}
-
- if predictor {
- pr = prHorizontal
- }
- switch m := m.(type) {
- case *image.Paletted:
- photometricInterpretation = pPaletted
- samplesPerPixel = 1
- bitsPerSample = []uint32{8}
- colorMap = make([]uint32, 256*3)
- for i := 0; i < 256 && i < len(m.Palette); i++ {
- r, g, b, _ := m.Palette[i].RGBA()
- colorMap[i+0*256] = uint32(r)
- colorMap[i+1*256] = uint32(g)
- colorMap[i+2*256] = uint32(b)
- }
- err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.Gray:
- photometricInterpretation = pBlackIsZero
- samplesPerPixel = 1
- bitsPerSample = []uint32{8}
- err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.Gray16:
- photometricInterpretation = pBlackIsZero
- samplesPerPixel = 1
- bitsPerSample = []uint32{16}
- err = encodeGray16(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.NRGBA:
- extraSamples = 2 // Unassociated alpha.
- err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.NRGBA64:
- extraSamples = 2 // Unassociated alpha.
- bitsPerSample = []uint32{16, 16, 16, 16}
- err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.RGBA:
- extraSamples = 1 // Associated alpha.
- err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- case *image.RGBA64:
- extraSamples = 1 // Associated alpha.
- bitsPerSample = []uint32{16, 16, 16, 16}
- err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
- default:
- extraSamples = 1 // Associated alpha.
- err = encode(dst, m, predictor)
- }
- if err != nil {
- return err
- }
-
- if compression != cNone {
- if err = dst.(io.Closer).Close(); err != nil {
- return err
- }
- imageLen = buf.Len()
- if err = binary.Write(w, enc, uint32(imageLen+8)); err != nil {
- return err
- }
- if _, err = buf.WriteTo(w); err != nil {
- return err
- }
- }
-
- ifd := []ifdEntry{
- {tImageWidth, dtShort, []uint32{uint32(d.X)}},
- {tImageLength, dtShort, []uint32{uint32(d.Y)}},
- {tBitsPerSample, dtShort, bitsPerSample},
- {tCompression, dtShort, []uint32{compression}},
- {tPhotometricInterpretation, dtShort, []uint32{photometricInterpretation}},
- {tStripOffsets, dtLong, []uint32{8}},
- {tSamplesPerPixel, dtShort, []uint32{samplesPerPixel}},
- {tRowsPerStrip, dtShort, []uint32{uint32(d.Y)}},
- {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}},
- // There is currently no support for storing the image
- // resolution, so give a bogus value of 72x72 dpi.
- {tXResolution, dtRational, []uint32{72, 1}},
- {tYResolution, dtRational, []uint32{72, 1}},
- {tResolutionUnit, dtShort, []uint32{resPerInch}},
- }
- if pr != prNone {
- ifd = append(ifd, ifdEntry{tPredictor, dtShort, []uint32{pr}})
- }
- if len(colorMap) != 0 {
- ifd = append(ifd, ifdEntry{tColorMap, dtShort, colorMap})
- }
- if extraSamples > 0 {
- ifd = append(ifd, ifdEntry{tExtraSamples, dtShort, []uint32{extraSamples}})
- }
-
- return writeIFD(w, imageLen+8, ifd)
-}