From: Nigel Tao Date: Tue, 31 Jan 2012 03:01:53 +0000 (+1100) Subject: image: remove image/bmp and image/tiff from std. X-Git-Tag: weekly.2012-02-07~198 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=10498f4d335f6bf0089791b263e795233ff79ec5;p=gostls13.git image: remove image/bmp and image/tiff from std. They have moved to the code.google.com/p/go.image subrepo. R=rsc CC=golang-dev https://golang.org/cl/5552052 --- diff --git a/src/pkg/Makefile b/src/pkg/Makefile index 73079c59a8..cd9776d5a5 100644 --- a/src/pkg/Makefile +++ b/src/pkg/Makefile @@ -89,13 +89,11 @@ DIRS=\ html\ html/template\ image\ - image/bmp\ image/color\ image/draw\ image/gif\ image/jpeg\ image/png\ - image/tiff\ index/suffixarray\ io\ io/ioutil\ @@ -181,7 +179,6 @@ NOTEST+=\ exp/ebnflint\ go/doc\ hash\ - image/bmp\ image/gif\ net/http/pprof\ net/http/httptest\ diff --git a/src/pkg/image/bmp/Makefile b/src/pkg/image/bmp/Makefile deleted file mode 100644 index 56635f7ce3..0000000000 --- a/src/pkg/image/bmp/Makefile +++ /dev/null @@ -1,11 +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. - -include ../../../Make.inc - -TARG=image/bmp -GOFILES=\ - reader.go\ - -include ../../../Make.pkg diff --git a/src/pkg/image/bmp/reader.go b/src/pkg/image/bmp/reader.go deleted file mode 100644 index 58bd7812ff..0000000000 --- a/src/pkg/image/bmp/reader.go +++ /dev/null @@ -1,152 +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 bmp implements a BMP image decoder. -// -// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html. -package bmp - -import ( - "errors" - "image" - "image/color" - "io" -) - -// ErrUnsupported means that the input BMP image uses a valid but unsupported -// feature. -var ErrUnsupported = errors.New("bmp: unsupported BMP image") - -func readUint16(b []byte) uint16 { - return uint16(b[0]) | uint16(b[1])<<8 -} - -func readUint32(b []byte) uint32 { - return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 -} - -// decodePaletted reads an 8 bit-per-pixel BMP image from r. -func decodePaletted(r io.Reader, c image.Config) (image.Image, error) { - var tmp [4]byte - paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette)) - // BMP images are stored bottom-up rather than top-down. - for y := c.Height - 1; y >= 0; y-- { - p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width] - _, err := io.ReadFull(r, p) - if err != nil { - return nil, err - } - // Each row is 4-byte aligned. - if c.Width%4 != 0 { - _, err := io.ReadFull(r, tmp[:4-c.Width%4]) - if err != nil { - return nil, err - } - } - } - return paletted, nil -} - -// decodeRGBA reads a 24 bit-per-pixel BMP image from r. -func decodeRGBA(r io.Reader, c image.Config) (image.Image, error) { - rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height)) - // There are 3 bytes per pixel, and each row is 4-byte aligned. - b := make([]byte, (3*c.Width+3)&^3) - // BMP images are stored bottom-up rather than top-down. - for y := c.Height - 1; y >= 0; y-- { - _, err := io.ReadFull(r, b) - if err != nil { - return nil, err - } - p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4] - for i, j := 0, 0; i < len(p); i, j = i+4, j+3 { - // BMP images are stored in BGR order rather than RGB order. - p[i+0] = b[j+2] - p[i+1] = b[j+1] - p[i+2] = b[j+0] - p[i+3] = 0xFF - } - } - return rgba, nil -} - -// Decode reads a BMP image from r and returns it as an image.Image. -// Limitation: The file must be 8 or 24 bits per pixel. -func Decode(r io.Reader) (image.Image, error) { - c, err := DecodeConfig(r) - if err != nil { - return nil, err - } - if c.ColorModel == color.RGBAModel { - return decodeRGBA(r, c) - } - return decodePaletted(r, c) -} - -// DecodeConfig returns the color model and dimensions of a BMP image without -// decoding the entire image. -// Limitation: The file must be 8 or 24 bits per pixel. -func DecodeConfig(r io.Reader) (config image.Config, err error) { - // We only support those BMP images that are a BITMAPFILEHEADER - // immediately followed by a BITMAPINFOHEADER. - const ( - fileHeaderLen = 14 - infoHeaderLen = 40 - ) - var b [1024]byte - if _, err = io.ReadFull(r, b[:fileHeaderLen+infoHeaderLen]); err != nil { - return - } - if string(b[:2]) != "BM" { - err = errors.New("bmp: invalid format") - return - } - offset := readUint32(b[10:14]) - if readUint32(b[14:18]) != infoHeaderLen { - err = ErrUnsupported - return - } - width := int(readUint32(b[18:22])) - height := int(readUint32(b[22:26])) - if width < 0 || height < 0 { - err = ErrUnsupported - return - } - // We only support 1 plane, 8 or 24 bits per pixel and no compression. - planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34]) - if planes != 1 || compression != 0 { - err = ErrUnsupported - return - } - switch bpp { - case 8: - if offset != fileHeaderLen+infoHeaderLen+256*4 { - err = ErrUnsupported - return - } - _, err = io.ReadFull(r, b[:256*4]) - if err != nil { - return - } - pcm := make(color.Palette, 256) - for i := range pcm { - // BMP images are stored in BGR order rather than RGB order. - // Every 4th byte is padding. - pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF} - } - return image.Config{pcm, width, height}, nil - case 24: - if offset != fileHeaderLen+infoHeaderLen { - err = ErrUnsupported - return - } - return image.Config{color.RGBAModel, width, height}, nil - } - err = ErrUnsupported - return -} - -func init() { - image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig) -} diff --git a/src/pkg/image/decode_test.go b/src/pkg/image/decode_test.go index 1b7db8bade..d659867243 100644 --- a/src/pkg/image/decode_test.go +++ b/src/pkg/image/decode_test.go @@ -11,11 +11,9 @@ import ( "os" "testing" - _ "image/bmp" _ "image/gif" _ "image/jpeg" _ "image/png" - _ "image/tiff" ) type imageTest struct { @@ -25,7 +23,7 @@ type imageTest struct { } var imageTests = []imageTest{ - {"testdata/video-001.png", "testdata/video-001.bmp", 0}, + {"testdata/video-001.png", "testdata/video-001.png", 0}, // GIF images are restricted to a 256-color palette and the conversion // to GIF loses significant image quality. {"testdata/video-001.png", "testdata/video-001.gif", 64 << 8}, @@ -33,10 +31,7 @@ var imageTests = []imageTest{ {"testdata/video-001.png", "testdata/video-001.5bpp.gif", 128 << 8}, // JPEG is a lossy format and hence needs a non-zero tolerance. {"testdata/video-001.png", "testdata/video-001.jpeg", 8 << 8}, - {"testdata/video-001.png", "testdata/video-001.png", 0}, - {"testdata/video-001.png", "testdata/video-001.tiff", 0}, - - // Test grayscale images. + // Grayscale images. {"testdata/video-005.gray.png", "testdata/video-005.gray.jpeg", 8 << 8}, {"testdata/video-005.gray.png", "testdata/video-005.gray.png", 0}, } diff --git a/src/pkg/image/testdata/video-001.bmp b/src/pkg/image/testdata/video-001.bmp deleted file mode 100644 index ca3dd42a7c..0000000000 Binary files a/src/pkg/image/testdata/video-001.bmp and /dev/null differ diff --git a/src/pkg/image/testdata/video-001.tiff b/src/pkg/image/testdata/video-001.tiff deleted file mode 100644 index 0dd6cd9313..0000000000 Binary files a/src/pkg/image/testdata/video-001.tiff and /dev/null differ diff --git a/src/pkg/image/tiff/Makefile b/src/pkg/image/tiff/Makefile deleted file mode 100644 index 67ef5c9ec6..0000000000 --- a/src/pkg/image/tiff/Makefile +++ /dev/null @@ -1,14 +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. - -include ../../../Make.inc - -TARG=image/tiff -GOFILES=\ - buffer.go\ - compress.go\ - consts.go\ - reader.go\ - -include ../../../Make.pkg diff --git a/src/pkg/image/tiff/buffer.go b/src/pkg/image/tiff/buffer.go deleted file mode 100644 index 27533c6047..0000000000 --- a/src/pkg/image/tiff/buffer.go +++ /dev/null @@ -1,54 +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 -} - -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 - } - - 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 copy(p, b.buf[o:end]), err - } - } - - return copy(p, b.buf[o: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/src/pkg/image/tiff/buffer_test.go b/src/pkg/image/tiff/buffer_test.go deleted file mode 100644 index e13afb3619..0000000000 --- a/src/pkg/image/tiff/buffer_test.go +++ /dev/null @@ -1,36 +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" - "strings" - "testing" -) - -var readAtTests = []struct { - n int - off int64 - s string - err error -}{ - {2, 0, "ab", nil}, - {6, 0, "abcdef", nil}, - {3, 3, "def", nil}, - {3, 5, "f", io.EOF}, - {3, 6, "", io.EOF}, -} - -func TestReadAt(t *testing.T) { - r := newReaderAt(strings.NewReader("abcdef")) - b := make([]byte, 10) - for _, test := range readAtTests { - n, err := r.ReadAt(b[:test.n], test.off) - s := string(b[:n]) - if s != test.s || err != test.err { - t.Errorf("buffer.ReadAt(<%v bytes>, %v): got %v, %q; want %v, %q", test.n, test.off, err, s, test.err, test.s) - } - } -} diff --git a/src/pkg/image/tiff/compress.go b/src/pkg/image/tiff/compress.go deleted file mode 100644 index 40c7fd86c3..0000000000 --- a/src/pkg/image/tiff/compress.go +++ /dev/null @@ -1,59 +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]...) - } - } - panic("unreachable") -} diff --git a/src/pkg/image/tiff/consts.go b/src/pkg/image/tiff/consts.go deleted file mode 100644 index 169ba27721..0000000000 --- a/src/pkg/image/tiff/consts.go +++ /dev/null @@ -1,103 +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 - - tStripOffsets = 273 - tSamplesPerPixel = 277 - tRowsPerStrip = 278 - tStripByteCounts = 279 - - 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 -) - -// imageMode represents the mode of the image. -type imageMode int - -const ( - mBilevel imageMode = iota - mPaletted - mGray - mGrayInvert - mRGB - mRGBA - mNRGBA -) diff --git a/src/pkg/image/tiff/reader.go b/src/pkg/image/tiff/reader.go deleted file mode 100644 index dc5a87a9fb..0000000000 --- a/src/pkg/image/tiff/reader.go +++ /dev/null @@ -1,430 +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. -// -// The TIFF specification is at http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf -package tiff - -import ( - "compress/lzw" - "compress/zlib" - "encoding/binary" - "image" - "image/color" - "io" - "io/ioutil" -) - -// 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) -} - -// An InternalError reports that an internal error was encountered. -type InternalError string - -func (e InternalError) Error() string { - return "tiff: internal error: " + string(e) -} - -type decoder struct { - r io.ReaderAt - byteOrder binary.ByteOrder - config image.Config - mode imageMode - 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 - datatype := d.byteOrder.Uint16(p[2:4]) - count := d.byteOrder.Uint32(p[4:8]) - 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 the IFD entry in p is "interesting" and -// stows away the data in the decoder. -func (d *decoder) parseIFD(p []byte) error { - tag := d.byteOrder.Uint16(p[0:2]) - switch tag { - case tBitsPerSample, - tExtraSamples, - tPhotometricInterpretation, - tCompression, - tPredictor, - tStripOffsets, - tStripByteCounts, - tRowsPerStrip, - tImageLength, - tImageWidth: - val, err := d.ifdUint(p) - if err != nil { - return err - } - d.features[int(tag)] = val - case tColorMap: - val, err := d.ifdUint(p) - if err != nil { - return err - } - numcolors := len(val) / 3 - if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 { - return 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 err - } - for _, v := range val { - if v != 1 { - return UnsupportedError("sample format") - } - } - } - return nil -} - -// readBits reads n bits from the internal buffer starting at the current offset. -func (d *decoder) readBits(n uint) uint32 { - for d.nbits < n { - d.v <<= 8 - 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 -} - -// 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 -} - -// decode decodes the raw data of an image. -// It reads from d.buf and writes the strip with ymin <= y < ymax into dst. -func (d *decoder) decode(dst image.Image, ymin, 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 && d.firstVal(tBitsPerSample) == 8 { - var off int - spp := len(d.features[tBitsPerSample]) // samples per pixel - for y := ymin; y < ymax; y++ { - off += spp - for x := 0; x < (dst.Bounds().Dx()-1)*spp; x++ { - d.buf[off] += d.buf[off-spp] - off++ - } - } - } - - switch d.mode { - case mGray, mGrayInvert: - img := dst.(*image.Gray) - bpp := d.firstVal(tBitsPerSample) - max := uint32((1 << bpp) - 1) - for y := ymin; y < ymax; y++ { - for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ { - v := uint8(d.readBits(bpp) * 0xff / max) - if d.mode == mGrayInvert { - v = 0xff - v - } - img.SetGray(x, y, color.Gray{v}) - } - d.flushBits() - } - case mPaletted: - img := dst.(*image.Paletted) - bpp := d.firstVal(tBitsPerSample) - for y := ymin; y < ymax; y++ { - for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ { - img.SetColorIndex(x, y, uint8(d.readBits(bpp))) - } - d.flushBits() - } - case mRGB: - img := dst.(*image.RGBA) - min := img.PixOffset(0, ymin) - max := img.PixOffset(0, ymax) - var off int - for i := min; i < max; i += 4 { - 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: - img := dst.(*image.NRGBA) - min := img.PixOffset(0, ymin) - max := img.PixOffset(0, ymax) - if len(d.buf) != max-min { - return FormatError("short data strip") - } - copy(img.Pix[min:max], d.buf) - case mRGBA: - img := dst.(*image.RGBA) - min := img.PixOffset(0, ymin) - max := img.PixOffset(0, ymax) - if len(d.buf) != max-min { - return FormatError("short data strip") - } - copy(img.Pix[min:max], d.buf) - } - - 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 { - 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 - } - - for i := 0; i < len(p); i += ifdLen { - if err := d.parseIFD(p[i : i+ifdLen]); err != nil { - return nil, err - } - } - - d.config.Width = int(d.firstVal(tImageWidth)) - d.config.Height = int(d.firstVal(tImageLength)) - - if _, ok := d.features[tBitsPerSample]; !ok { - return nil, FormatError("BitsPerSample tag missing") - } - - // Determine the image mode. - switch d.firstVal(tPhotometricInterpretation) { - case pRGB: - for _, b := range d.features[tBitsPerSample] { - if b != 8 { - return nil, UnsupportedError("non-8-bit RGB image") - } - } - d.config.ColorModel = color.RGBAModel - // 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 - case 4: - switch d.firstVal(tExtraSamples) { - case 1: - d.mode = mRGBA - case 2: - d.mode = mNRGBA - 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 - d.config.ColorModel = color.GrayModel - case pBlackIsZero: - d.mode = mGray - 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 -} - -// 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 - } - - // Check if we have the right number of strips, offsets and counts. - rps := int(d.firstVal(tRowsPerStrip)) - if rps == 0 { - // Assume only one strip. - rps = d.config.Height - } - numStrips := (d.config.Height + rps - 1) / rps - if rps == 0 || len(d.features[tStripOffsets]) < numStrips || len(d.features[tStripByteCounts]) < numStrips { - return nil, FormatError("inconsistent header") - } - - switch d.mode { - case mGray, mGrayInvert: - img = image.NewGray(image.Rect(0, 0, d.config.Width, d.config.Height)) - case mPaletted: - img = image.NewPaletted(image.Rect(0, 0, d.config.Width, d.config.Height), d.palette) - case mNRGBA: - img = image.NewNRGBA(image.Rect(0, 0, d.config.Width, d.config.Height)) - case mRGB, mRGBA: - img = image.NewRGBA(image.Rect(0, 0, d.config.Width, d.config.Height)) - } - - for i := 0; i < numStrips; i++ { - ymin := i * rps - // The last strip may be shorter. - if i == numStrips-1 && d.config.Height%rps != 0 { - rps = d.config.Height % rps - } - offset := int64(d.features[tStripOffsets][i]) - n := int64(d.features[tStripByteCounts][i]) - switch d.firstVal(tCompression) { - case cNone: - // TODO(bsiegert): Avoid copy if r is a tiff.buffer. - d.buf = make([]byte, n) - _, err = d.r.ReadAt(d.buf, offset) - 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: - 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("compression") - } - if err != nil { - return - } - err = d.decode(img, ymin, ymin+rps) - } - return -} - -func init() { - image.RegisterFormat("tiff", leHeader, Decode, DecodeConfig) - image.RegisterFormat("tiff", beHeader, Decode, DecodeConfig) -} diff --git a/src/pkg/image/tiff/reader_test.go b/src/pkg/image/tiff/reader_test.go deleted file mode 100644 index ee5dafd996..0000000000 --- a/src/pkg/image/tiff/reader_test.go +++ /dev/null @@ -1,119 +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 ( - "image" - "io/ioutil" - "os" - "strings" - "testing" -) - -// Read makes *buffer implements io.Reader, so that we can pass one to Decode. -func (*buffer) Read([]byte) (int, error) { - panic("unimplemented") -} - -// TestNoRPS tries to decode an image that has no RowsPerStrip tag. -// The tag is mandatory according to the spec but some software omits -// it in the case of a single strip. -func TestNoRPS(t *testing.T) { - f, err := os.Open("testdata/no_rps.tiff") - if err != nil { - t.Fatal(err) - } - defer f.Close() - _, err = Decode(f) - if err != nil { - t.Fatal(err) - } -} - -// TestUnpackBits tests the decoding of PackBits-encoded data. -func TestUnpackBits(t *testing.T) { - var unpackBitsTests = []struct { - compressed string - uncompressed string - }{{ - // Example data from Wikipedia. - "\xfe\xaa\x02\x80\x00\x2a\xfd\xaa\x03\x80\x00\x2a\x22\xf7\xaa", - "\xaa\xaa\xaa\x80\x00\x2a\xaa\xaa\xaa\xaa\x80\x00\x2a\x22\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - }} - for _, u := range unpackBitsTests { - buf, err := unpackBits(strings.NewReader(u.compressed)) - if err != nil { - t.Fatal(err) - } - if string(buf) != u.uncompressed { - t.Fatalf("unpackBits: want %x, got %x", u.uncompressed, buf) - } - } -} - -// TestDecompress tests that decoding some TIFF images that use different -// compression formats result in the same pixel data. -func TestDecompress(t *testing.T) { - var decompressTests = []string{ - "bw-uncompressed.tiff", - "bw-deflate.tiff", - "bw-packbits.tiff", - } - var img0 image.Image - for _, name := range decompressTests { - f, err := os.Open("testdata/" + name) - if err != nil { - t.Fatal(err) - } - defer f.Close() - if img0 == nil { - img0, err = Decode(f) - if err != nil { - t.Fatalf("decoding %s: %v", name, err) - } - continue - } - - img1, err := Decode(f) - if err != nil { - t.Fatalf("decoding %s: %v", name, err) - } - b := img1.Bounds() - // Compare images. - if !b.Eq(img0.Bounds()) { - t.Fatalf("wrong image size: want %s, got %s", img0.Bounds(), b) - } - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - c0 := img0.At(x, y) - c1 := img1.At(x, y) - r0, g0, b0, a0 := c0.RGBA() - r1, g1, b1, a1 := c1.RGBA() - if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { - t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) - } - } - } - } -} - -const filename = "testdata/video-001-uncompressed.tiff" - -// BenchmarkDecode benchmarks the decoding of an image. -func BenchmarkDecode(b *testing.B) { - b.StopTimer() - contents, err := ioutil.ReadFile(filename) - if err != nil { - panic(err) - } - r := &buffer{buf: contents} - b.StartTimer() - for i := 0; i < b.N; i++ { - _, err := Decode(r) - if err != nil { - b.Fatal("Decode:", err) - } - } -} diff --git a/src/pkg/image/tiff/testdata/bw-deflate.tiff b/src/pkg/image/tiff/testdata/bw-deflate.tiff deleted file mode 100644 index 137a0c3ef1..0000000000 Binary files a/src/pkg/image/tiff/testdata/bw-deflate.tiff and /dev/null differ diff --git a/src/pkg/image/tiff/testdata/bw-packbits.tiff b/src/pkg/image/tiff/testdata/bw-packbits.tiff deleted file mode 100644 index d59fa4aeed..0000000000 Binary files a/src/pkg/image/tiff/testdata/bw-packbits.tiff and /dev/null differ diff --git a/src/pkg/image/tiff/testdata/bw-uncompressed.tiff b/src/pkg/image/tiff/testdata/bw-uncompressed.tiff deleted file mode 100644 index 8390f11357..0000000000 Binary files a/src/pkg/image/tiff/testdata/bw-uncompressed.tiff and /dev/null differ diff --git a/src/pkg/image/tiff/testdata/no_rps.tiff b/src/pkg/image/tiff/testdata/no_rps.tiff deleted file mode 100644 index 3280cf8e34..0000000000 Binary files a/src/pkg/image/tiff/testdata/no_rps.tiff and /dev/null differ diff --git a/src/pkg/image/tiff/testdata/video-001-uncompressed.tiff b/src/pkg/image/tiff/testdata/video-001-uncompressed.tiff deleted file mode 100644 index fad147107b..0000000000 Binary files a/src/pkg/image/tiff/testdata/video-001-uncompressed.tiff and /dev/null differ