// 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 ( ) // A FormatError reports that the input is not a valid TIFF image. type FormatError string func ( FormatError) () string { return "tiff: invalid format: " + string() } // An UnsupportedError reports that the input uses a valid but // unimplemented feature. type UnsupportedError string func ( UnsupportedError) () string { return "tiff: unsupported feature: " + string() } var ( errNoPixels = FormatError("not enough pixel data") errInvalidColorIndex = FormatError("invalid color index") ) const maxChunkSize = 10 << 20 // 10M // safeReadAt is a verbatim copy of internal/saferio.ReadDataAt from the // standard library, which is used to read data from a reader using a length // provided by untrusted data, without allocating the entire slice ahead of time // if it is large (>maxChunkSize). This allows us to avoid allocating giant // slices before learning that we can't actually read that much data from the // reader. func safeReadAt( io.ReaderAt, uint64, int64) ([]byte, error) { if int64() < 0 || != uint64(int()) { // n is too large to fit in int, so we can't allocate // a buffer large enough. Treat this as a read failure. return nil, io.ErrUnexpectedEOF } if < maxChunkSize { := make([]byte, ) , := .ReadAt(, ) if != nil { // io.SectionReader can return EOF for n == 0, // but for our purposes that is a success. if != io.EOF || > 0 { return nil, } } return , nil } var []byte := make([]byte, maxChunkSize) for > 0 { := if > maxChunkSize { = maxChunkSize } , := .ReadAt([:], ) if != nil { return nil, } = append(, [:]...) -= += int64() } return , nil } type decoder struct { r io.ReaderAt byteOrder binary.ByteOrder config image.Config mode imageMode bpp uint features map[int][]uint ifd map[int][ifdLen]byte 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 ( *decoder) ( int) uint { := .features[] if len() == 0 { return 0 } return [0] } // firstIntVal returns the first int of the features entry with the given tag, // or 0 if the tag does not exist. // If the tag overflows an int, it returns an error. func ( *decoder) ( int) (int, error) { := .firstVal() if > math.MaxInt { return 0, FormatError("IFD value too large") } return int(), nil } // ifdUint decodes the IFD entry in p, which must be of the Byte, Short // or Long type, and returns the decoded uint values. // // maxCount limits the number of values. // If the entry contains more than maxCount values, only the first maxCount are parsed. func ( *decoder) ( []byte, int) ( []uint, error) { var []byte if len() < ifdLen { return nil, FormatError("bad IFD entry") } := .byteOrder.Uint16([2:4]) if := int(); <= 0 || >= len(lengths) { return nil, UnsupportedError("IFD entry datatype") } := .byteOrder.Uint32([4:8]) if > math.MaxInt32/lengths[] { return nil, FormatError("IFD data too large") } := min(int(), ) if := lengths[] * ; > 4 { := uint64(lengths[]) * uint64() // The IFD contains a pointer to the real value. , = safeReadAt(.r, , int64(.byteOrder.Uint32([8:12]))) } else { = [8 : 8+] } if != nil { return nil, } = make([]uint, ) switch { case dtByte: for := range { [] = uint([]) } case dtShort: for := range { [] = uint(.byteOrder.Uint16([2* : 2*(+1)])) } case dtLong: for := range { [] = uint(.byteOrder.Uint32([4* : 4*(+1)])) } default: return nil, UnsupportedError("data type") } return , nil } // parseIFDOffsets parses an IFD entry stored in d.ifd using ifdUint. // For IFD entries which can be large, we delay reading and parsing the entry // until we know the image size, which lets us set reasonable bounds on the IFD entry. func ( *decoder) ( int, int) ( []uint, error) { , := .ifd[] if ! { return nil, nil } return .ifdUint([:], ) } // 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 ( *decoder) ( []byte) (int, error) { // smallEntryMaxCount is the limit to use for parsed IFD entries that // don't scale with the image size. // // We could be more precise and limit the number of entries to exactly the // correct limit (for example, tTileWidth should always have exactly one value), // but 16 is small enough to prevent excessive allocation and large enough to // allow for any multi-value entry. const = 16 := .byteOrder.Uint16([0:2]) switch { case tBitsPerSample, tExtraSamples, tPhotometricInterpretation, tCompression, tPredictor, tRowsPerStrip, tTileWidth, tTileLength, tImageLength, tImageWidth, tFillOrder, tT4Options, tT6Options: , := .ifdUint(, ) if != nil { return 0, } .features[int()] = case tStripOffsets, tStripByteCounts, tTileOffsets, tTileByteCounts: // These keys may contain many values. // Stash the IFD entry for later parsing. var [ifdLen]byte copy([:], ) .ifd[int()] = case tColorMap: const = 256 , := .ifdUint(, (3*)+1) if != nil { return 0, } := len() / 3 if len()%3 != 0 || <= 0 || > { return 0, FormatError("bad ColorMap length") } .palette = make([]color.Color, ) for := 0; < ; ++ { .palette[] = color.RGBA64{ uint16([]), uint16([+]), uint16([+2*]), 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. , := .ifdUint(, ) if != nil { return 0, } for , := range { if != 1 { return 0, UnsupportedError("sample format") } } } return int(), nil } // readBits reads n bits from the internal buffer starting at the current offset. func ( *decoder) ( uint) ( uint32, bool) { for .nbits < { .v <<= 8 if .off >= len(.buf) { return 0, false } .v |= uint32(.buf[.off]) .off++ .nbits += 8 } .nbits -= := .v >> .nbits .v &^= << .nbits return , true } // flushBits discards the unread bits in the buffer used by readBits. // It is used at the end of a line. func ( *decoder) () { .v = 0 .nbits = 0 } // minInt returns the smaller of x or y. func minInt(, int) int { if <= { return } return } // decode decodes the raw data of an image. // It reads from d.buf and writes the strip or tile into dst. func ( *decoder) ( image.Image, , , , int) error { .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 .firstVal(tPredictor) == prHorizontal { switch .bpp { case 16: var int := 2 * len(.features[tBitsPerSample]) // bytes per sample times samples per pixel for := ; < ; ++ { += for := 0; < (--1)*; += 2 { if +2 > len(.buf) { return errNoPixels } := .byteOrder.Uint16(.buf[- : -+2]) := .byteOrder.Uint16(.buf[ : +2]) .byteOrder.PutUint16(.buf[:+2], +) += 2 } } case 8: var int := 1 * len(.features[tBitsPerSample]) // bytes per sample times samples per pixel for := ; < ; ++ { += for := 0; < (--1)*; ++ { if >= len(.buf) { return errNoPixels } .buf[] += .buf[-] ++ } } case 1: return UnsupportedError("horizontal predictor with 1 BitsPerSample") } } // calcRowBytes returns the number of bytes in a row with numSamples samples per pixel // and bytesPerSample bytes per sample. := func(, , int, uint) int { return int((int64(-)*int64()*int64() + 7) / 8) } // calcRowOff returns the offset of the next row. := func(, , int) int { return ( - ) * } := minInt(, .Bounds().Max.X) := minInt(, .Bounds().Max.Y) switch .mode { case mGray, mGrayInvert: := (, , 1, .bpp) if .bpp == 16 { := .(*image.Gray16) for := ; < ; ++ { .off = (, , ) for := ; < ; ++ { if .off+2 > len(.buf) { return errNoPixels } := .byteOrder.Uint16(.buf[.off : .off+2]) .off += 2 if .mode == mGrayInvert { = 0xffff - } .SetGray16(, , color.Gray16{}) } } } else { := .(*image.Gray) := uint32((1 << .bpp) - 1) for := ; < ; ++ { .off = (, , ) .flushBits() for := ; < ; ++ { , := .readBits(.bpp) if ! { return errNoPixels } = * 0xff / if .mode == mGrayInvert { = 0xff - } .SetGray(, , color.Gray{uint8()}) } } } case mPaletted: := .(*image.Paletted) := len(.palette) := (, , 1, .bpp) for := ; < ; ++ { .off = (, , ) .flushBits() for := ; < ; ++ { , := .readBits(.bpp) if ! { return errNoPixels } := uint8() if int() >= { return errInvalidColorIndex } .SetColorIndex(, , ) } } case mRGB: := (, , 3, .bpp) if .bpp == 16 { := .(*image.RGBA64) for := ; < ; ++ { .off = (, , ) for := ; < ; ++ { if .off+6 > len(.buf) { return errNoPixels } := .byteOrder.Uint16(.buf[.off+0 : .off+2]) := .byteOrder.Uint16(.buf[.off+2 : .off+4]) := .byteOrder.Uint16(.buf[.off+4 : .off+6]) .off += 6 .SetRGBA64(, , color.RGBA64{, , , 0xffff}) } } } else { := .(*image.RGBA) for := ; < ; ++ { .off = (, , ) := .PixOffset(, ) := .PixOffset(, ) := ( - ) * ( - ) * 3 for := ; < ; += 4 { if +3 > len(.buf) { return errNoPixels } .Pix[+0] = .buf[+0] .Pix[+1] = .buf[+1] .Pix[+2] = .buf[+2] .Pix[+3] = 0xff += 3 } } } case mNRGBA: := (, , 4, .bpp) if .bpp == 16 { := .(*image.NRGBA64) for := ; < ; ++ { .off = (, , ) for := ; < ; ++ { if .off+8 > len(.buf) { return errNoPixels } := .byteOrder.Uint16(.buf[.off+0 : .off+2]) := .byteOrder.Uint16(.buf[.off+2 : .off+4]) := .byteOrder.Uint16(.buf[.off+4 : .off+6]) := .byteOrder.Uint16(.buf[.off+6 : .off+8]) .off += 8 .SetNRGBA64(, , color.NRGBA64{, , , }) } } } else { := .(*image.NRGBA) for := ; < ; ++ { := .PixOffset(, ) := .PixOffset(, ) , := (-)*(-)*4, (-+1)*(-)*4 if > len(.buf) { return errNoPixels } copy(.Pix[:], .buf[:]) } } case mRGBA: := (, , 4, .bpp) if .bpp == 16 { := .(*image.RGBA64) for := ; < ; ++ { .off = (, , ) for := ; < ; ++ { if .off+8 > len(.buf) { return errNoPixels } := .byteOrder.Uint16(.buf[.off+0 : .off+2]) := .byteOrder.Uint16(.buf[.off+2 : .off+4]) := .byteOrder.Uint16(.buf[.off+4 : .off+6]) := .byteOrder.Uint16(.buf[.off+6 : .off+8]) .off += 8 .SetRGBA64(, , color.RGBA64{, , , }) } } } else { := .(*image.RGBA) for := ; < ; ++ { := .PixOffset(, ) := .PixOffset(, ) , := (-)*(-)*4, (-+1)*(-)*4 if > len(.buf) { return errNoPixels } copy(.Pix[:], .buf[:]) } } } return nil } // maxBytesPerPixel is the maximum possible bytes-per-pixel, // used for conservative bounds checking. const maxBytesPerPixel = 8 func newDecoder( io.Reader) (*decoder, error) { := &decoder{ r: newReaderAt(), features: make(map[int][]uint), ifd: make(map[int][ifdLen]byte), } := make([]byte, 8) if , := .r.ReadAt(, 0); != nil { if == io.EOF { = io.ErrUnexpectedEOF } return nil, } switch string([0:4]) { case leHeader: .byteOrder = binary.LittleEndian case beHeader: .byteOrder = binary.BigEndian default: return nil, FormatError("malformed header") } := int64(.byteOrder.Uint32([4:8])) // The first two bytes contain the number of entries (12 bytes each). if , := .r.ReadAt([0:2], ); != nil { return nil, } := int(.byteOrder.Uint16([0:2])) // All IFD entries are read in one chunk. var error , = safeReadAt(.r, uint64(ifdLen*), +2) if != nil { return nil, } := -1 for := 0; < len(); += ifdLen { , := .parseIFD([ : +ifdLen]) if != nil { return nil, } if <= { return nil, FormatError("tags are not sorted in ascending order") } = } if .config.Width, = .firstIntVal(tImageWidth); != nil { return nil, } if .config.Height, = .firstIntVal(tImageLength); != nil { return nil, } if .config.Width == 0 || .config.Height == 0 { return nil, FormatError("zero-size image") } // Check that the image fits in memory. // This conservatively assumes 8 bytes per pixel, // rather than using the actual pixel size. if , := safemath.Mul3(.config.Width, .config.Height, maxBytesPerPixel); ! { return nil, FormatError("image too large") } if , := .features[tBitsPerSample]; ! { // Default is 1 per specification. .features[tBitsPerSample] = []uint{1} } .bpp = .firstVal(tBitsPerSample) switch .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", .bpp)) } // Determine the image mode. switch .firstVal(tPhotometricInterpretation) { case pRGB: if .bpp == 16 { for , := range .features[tBitsPerSample] { if != 16 { return nil, FormatError("wrong number of samples for 16bit RGB") } } } else { for , := range .features[tBitsPerSample] { if != 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(.features[tBitsPerSample]) { case 3: .mode = mRGB if .bpp == 16 { .config.ColorModel = color.RGBA64Model } else { .config.ColorModel = color.RGBAModel } case 4: switch .firstVal(tExtraSamples) { case 1: .mode = mRGBA if .bpp == 16 { .config.ColorModel = color.RGBA64Model } else { .config.ColorModel = color.RGBAModel } case 2: .mode = mNRGBA if .bpp == 16 { .config.ColorModel = color.NRGBA64Model } else { .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: .mode = mPaletted .config.ColorModel = color.Palette(.palette) case pWhiteIsZero: .mode = mGrayInvert if .bpp == 16 { .config.ColorModel = color.Gray16Model } else { .config.ColorModel = color.GrayModel } case pBlackIsZero: .mode = mGray if .bpp == 16 { .config.ColorModel = color.Gray16Model } else { .config.ColorModel = color.GrayModel } default: return nil, UnsupportedError("color model") } if .firstVal(tPhotometricInterpretation) != pRGB { if len(.features[tBitsPerSample]) != 1 { return nil, UnsupportedError("extra samples") } } return , nil } // DecodeConfig returns the color model and dimensions of a TIFF image without // decoding the entire image. func ( io.Reader) (image.Config, error) { , := newDecoder() if != nil { return image.Config{}, } return .config, nil } func ccittFillOrder( uint) ccitt.Order { if == 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 ( io.Reader) ( image.Image, error) { , := newDecoder() if != nil { return } := false := .config.Width := .config.Height := 1 := 1 if .config.Width == 0 { = 0 } if .config.Height == 0 { = 0 } var , []uint if .firstVal(tTileWidth) != 0 { = true if , = .firstIntVal(tTileWidth); != nil { return nil, } if , = .firstIntVal(tTileLength); != nil { return nil, } // The specification says that tile widths and lengths must be a multiple of 16. // We currently permit invalid sizes, but reject anything too small to limit the // amount of work a malicious input can force us to perform. if < 8 || < 8 { return nil, FormatError("tile size is too small") } // Same conservative assumption on bytes-per-pixel as for the image dimensions. if , := safemath.Mul3(, , maxBytesPerPixel); ! { return nil, FormatError("tile size is too large") } if -.config.Width > 16 || -.config.Height > 16 { // Tiles may be padded to the nearest multiple of 16, but one of // the dimensions of the tile exceeds the image dimension by more // than padding would require. // // Typical TIFF tiles are 256x256, but 1024x1024 appears to be // in occasional use. If the tile is both larger than the image // and has more than 1024 pixels in one dimension, it's // probably malicious input. // // Note that this still permits very large tiles, // so long as the tile is smaller than the image dimensions. // A gigapixel image with a 2048x2048 tile size // (used in some GIS applications) // will be valid because the image dimensions are much larger // than the tile size. if > 1024 || > 1024 { return nil, FormatError("tile size exceeds image size") } } if != 0 { = (.config.Width + - 1) / } if != 0 { = (.config.Height + - 1) / } , = .parseIFDOffsets(tTileOffsets, *) if != nil { return nil, } , = .parseIFDOffsets(tTileByteCounts, *) if != nil { return nil, } } else { if := .firstVal(tRowsPerStrip); > 0 && < uint() { = int() } if != 0 { // This can't overflow: We require that w*h*8 not overflow and // blockHeight is no more than d.config.Height. = (.config.Height + - 1) / } , = .parseIFDOffsets(tStripOffsets, ) if != nil { return nil, } , = .parseIFDOffsets(tStripByteCounts, ) if != nil { return nil, } } // Check if we have the right number of strips/tiles, offsets and counts. if := * ; len() < || len() < { return nil, FormatError("inconsistent header") } := image.Rect(0, 0, .config.Width, .config.Height) switch .mode { case mGray, mGrayInvert: if .bpp == 16 { = image.NewGray16() } else { = image.NewGray() } case mPaletted: = image.NewPaletted(, .palette) case mNRGBA: if .bpp == 16 { = image.NewNRGBA64() } else { = image.NewNRGBA() } case mRGB, mRGBA: if .bpp == 16 { = image.NewRGBA64() } else { = image.NewRGBA() } } if == 0 || == 0 { return } // Maximum data per pixel is 8 bytes (RGBA64). := int64() * int64() * 8 for := 0; < ; ++ { := if ! && == -1 && .config.Width% != 0 { = .config.Width % } for := 0; < ; ++ { := if ! && == -1 && .config.Height% != 0 { = .config.Height % } := int64([*+]) := int64([*+]) switch .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 > { return nil, FormatError("block data size too large") } if , := .r.(*buffer); { .buf, = .Slice(, ) } else { .buf, = safeReadAt(.r, uint64(), ) } case cG3: := .firstVal(tPhotometricInterpretation) == pWhiteIsZero := ccittFillOrder(.firstVal(tFillOrder)) := ccitt.NewReader(io.NewSectionReader(.r, , ), , ccitt.Group3, , , &ccitt.Options{Invert: , Align: false}) .buf, = readBuf(, .buf, ) case cG4: := .firstVal(tPhotometricInterpretation) == pWhiteIsZero := ccittFillOrder(.firstVal(tFillOrder)) := ccitt.NewReader(io.NewSectionReader(.r, , ), , ccitt.Group4, , , &ccitt.Options{Invert: , Align: false}) .buf, = readBuf(, .buf, ) case cLZW: := lzw.NewReader(io.NewSectionReader(.r, , ), lzw.MSB, 8) .buf, = readBuf(, .buf, ) .Close() case cDeflate, cDeflateOld: var io.ReadCloser , = zlib.NewReader(io.NewSectionReader(.r, , )) if != nil { return nil, } .buf, = readBuf(, .buf, ) .Close() case cPackBits: .buf, = unpackBits(io.NewSectionReader(.r, , ), ) default: = UnsupportedError(fmt.Sprintf("compression value %d", .firstVal(tCompression))) } if != nil { return nil, } := * := * := + := + = .decode(, , , , ) if != nil { return nil, } } } return } func readBuf( io.Reader, []byte, int64) ([]byte, error) { := bytes.NewBuffer([:0]) , := .ReadFrom(io.LimitReader(, )) return .Bytes(), } func init() { image.RegisterFormat("tiff", leHeader, Decode, DecodeConfig) image.RegisterFormat("tiff", beHeader, Decode, DecodeConfig) }