github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/image/tiff/reader_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tiff 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "encoding/hex" 11 "errors" 12 "image" 13 "io/ioutil" 14 "os" 15 "strings" 16 "testing" 17 18 _ "image/png" 19 ) 20 21 const testdataDir = "../testdata/" 22 23 // Read makes *buffer implements io.Reader, so that we can pass one to Decode. 24 func (*buffer) Read([]byte) (int, error) { 25 panic("unimplemented") 26 } 27 28 func load(name string) (image.Image, error) { 29 f, err := os.Open(testdataDir + name) 30 if err != nil { 31 return nil, err 32 } 33 defer f.Close() 34 img, _, err := image.Decode(f) 35 if err != nil { 36 return nil, err 37 } 38 return img, nil 39 } 40 41 // TestNoRPS tests decoding an image that has no RowsPerStrip tag. The tag is 42 // mandatory according to the spec but some software omits it in the case of a 43 // single strip. 44 func TestNoRPS(t *testing.T) { 45 _, err := load("no_rps.tiff") 46 if err != nil { 47 t.Fatal(err) 48 } 49 } 50 51 // TestNoCompression tests decoding an image that has no Compression tag. This 52 // tag is mandatory, but most tools interpret a missing value as no 53 // compression. 54 func TestNoCompression(t *testing.T) { 55 _, err := load("no_compress.tiff") 56 if err != nil { 57 t.Fatal(err) 58 } 59 } 60 61 // TestUnpackBits tests the decoding of PackBits-encoded data. 62 func TestUnpackBits(t *testing.T) { 63 var unpackBitsTests = []struct { 64 compressed string 65 uncompressed string 66 }{{ 67 // Example data from Wikipedia. 68 "\xfe\xaa\x02\x80\x00\x2a\xfd\xaa\x03\x80\x00\x2a\x22\xf7\xaa", 69 "\xaa\xaa\xaa\x80\x00\x2a\xaa\xaa\xaa\xaa\x80\x00\x2a\x22\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 70 }} 71 for _, u := range unpackBitsTests { 72 buf, err := unpackBits(strings.NewReader(u.compressed)) 73 if err != nil { 74 t.Fatal(err) 75 } 76 if string(buf) != u.uncompressed { 77 t.Fatalf("unpackBits: want %x, got %x", u.uncompressed, buf) 78 } 79 } 80 } 81 82 func TestShortBlockData(t *testing.T) { 83 b, err := ioutil.ReadFile("../testdata/bw-uncompressed.tiff") 84 if err != nil { 85 t.Fatal(err) 86 } 87 // The bw-uncompressed.tiff image is a 153x55 bi-level image. This is 1 bit 88 // per pixel, or 20 bytes per row, times 55 rows, or 1100 bytes of pixel 89 // data. 1100 in hex is 0x44c, or "\x4c\x04" in little-endian. We replace 90 // that byte count (StripByteCounts-tagged data) by something less than 91 // that, so that there is not enough pixel data. 92 old := []byte{0x4c, 0x04} 93 new := []byte{0x01, 0x01} 94 i := bytes.Index(b, old) 95 if i < 0 { 96 t.Fatal(`could not find "\x4c\x04" byte count`) 97 } 98 if bytes.Contains(b[i+len(old):], old) { 99 t.Fatal(`too many occurrences of "\x4c\x04"`) 100 } 101 b[i+0] = new[0] 102 b[i+1] = new[1] 103 if _, err = Decode(bytes.NewReader(b)); err == nil { 104 t.Fatal("got nil error, want non-nil") 105 } 106 } 107 108 func TestDecodeInvalidDataType(t *testing.T) { 109 b, err := ioutil.ReadFile("../testdata/bw-uncompressed.tiff") 110 if err != nil { 111 t.Fatal(err) 112 } 113 114 // off is the offset of the ImageWidth tag. It is the offset of the overall 115 // IFD block (0x00000454), plus 2 for the uint16 number of IFD entries, plus 12 116 // to skip the first entry. 117 const off = 0x00000454 + 2 + 12*1 118 119 if v := binary.LittleEndian.Uint16(b[off : off+2]); v != tImageWidth { 120 t.Fatal(`could not find ImageWidth tag`) 121 } 122 binary.LittleEndian.PutUint16(b[off+2:], uint16(len(lengths))) // invalid datatype 123 124 if _, err = Decode(bytes.NewReader(b)); err == nil { 125 t.Fatal("got nil error, want non-nil") 126 } 127 } 128 129 func compare(t *testing.T, img0, img1 image.Image) { 130 b0 := img0.Bounds() 131 b1 := img1.Bounds() 132 if b0.Dx() != b1.Dx() || b0.Dy() != b1.Dy() { 133 t.Fatalf("wrong image size: want %s, got %s", b0, b1) 134 } 135 x1 := b1.Min.X - b0.Min.X 136 y1 := b1.Min.Y - b0.Min.Y 137 for y := b0.Min.Y; y < b0.Max.Y; y++ { 138 for x := b0.Min.X; x < b0.Max.X; x++ { 139 c0 := img0.At(x, y) 140 c1 := img1.At(x+x1, y+y1) 141 r0, g0, b0, a0 := c0.RGBA() 142 r1, g1, b1, a1 := c1.RGBA() 143 if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { 144 t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) 145 } 146 } 147 } 148 } 149 150 // TestDecode tests that decoding a PNG image and a TIFF image result in the 151 // same pixel data. 152 func TestDecode(t *testing.T) { 153 img0, err := load("video-001.png") 154 if err != nil { 155 t.Fatal(err) 156 } 157 img1, err := load("video-001.tiff") 158 if err != nil { 159 t.Fatal(err) 160 } 161 img2, err := load("video-001-strip-64.tiff") 162 if err != nil { 163 t.Fatal(err) 164 } 165 img3, err := load("video-001-tile-64x64.tiff") 166 if err != nil { 167 t.Fatal(err) 168 } 169 img4, err := load("video-001-16bit.tiff") 170 if err != nil { 171 t.Fatal(err) 172 } 173 174 compare(t, img0, img1) 175 compare(t, img0, img2) 176 compare(t, img0, img3) 177 compare(t, img0, img4) 178 } 179 180 // TestDecodeLZW tests that decoding a PNG image and a LZW-compressed TIFF 181 // image result in the same pixel data. 182 func TestDecodeLZW(t *testing.T) { 183 img0, err := load("blue-purple-pink.png") 184 if err != nil { 185 t.Fatal(err) 186 } 187 img1, err := load("blue-purple-pink.lzwcompressed.tiff") 188 if err != nil { 189 t.Fatal(err) 190 } 191 192 compare(t, img0, img1) 193 } 194 195 // TestDecompress tests that decoding some TIFF images that use different 196 // compression formats result in the same pixel data. 197 func TestDecompress(t *testing.T) { 198 var decompressTests = []string{ 199 "bw-uncompressed.tiff", 200 "bw-deflate.tiff", 201 "bw-packbits.tiff", 202 } 203 var img0 image.Image 204 for _, name := range decompressTests { 205 img1, err := load(name) 206 if err != nil { 207 t.Fatalf("decoding %s: %v", name, err) 208 } 209 if img0 == nil { 210 img0 = img1 211 continue 212 } 213 compare(t, img0, img1) 214 } 215 } 216 217 func replace(src []byte, find, repl string) ([]byte, error) { 218 removeSpaces := func(r rune) rune { 219 if r != ' ' { 220 return r 221 } 222 return -1 223 } 224 225 f, err := hex.DecodeString(strings.Map(removeSpaces, find)) 226 if err != nil { 227 return nil, err 228 } 229 r, err := hex.DecodeString(strings.Map(removeSpaces, repl)) 230 if err != nil { 231 return nil, err 232 } 233 dst := bytes.Replace(src, f, r, 1) 234 if bytes.Equal(dst, src) { 235 return nil, errors.New("replacement failed") 236 } 237 return dst, nil 238 } 239 240 // TestZeroBitsPerSample tests that an IFD with a bitsPerSample of 0 does not 241 // cause a crash. 242 // Issue 10711. 243 func TestZeroBitsPerSample(t *testing.T) { 244 b0, err := ioutil.ReadFile(testdataDir + "bw-deflate.tiff") 245 if err != nil { 246 t.Fatal(err) 247 } 248 249 // Mutate the loaded image to have the problem. 250 // 02 01: tag number (tBitsPerSample) 251 // 03 00: data type (short, or uint16) 252 // 01 00 00 00: count 253 // ?? 00 00 00: value (1 -> 0) 254 b1, err := replace(b0, 255 "02 01 03 00 01 00 00 00 01 00 00 00", 256 "02 01 03 00 01 00 00 00 00 00 00 00", 257 ) 258 if err != nil { 259 t.Fatal(err) 260 } 261 262 _, err = Decode(bytes.NewReader(b1)) 263 if err == nil { 264 t.Fatal("Decode with 0 bits per sample: got nil error, want non-nil") 265 } 266 } 267 268 // TestTileTooBig tests that we do not panic when a tile is too big compared to 269 // the data available. 270 // Issue 10712 271 func TestTileTooBig(t *testing.T) { 272 b0, err := ioutil.ReadFile(testdataDir + "video-001-tile-64x64.tiff") 273 if err != nil { 274 t.Fatal(err) 275 } 276 277 // Mutate the loaded image to have the problem. 278 // 279 // 42 01: tag number (tTileWidth) 280 // 03 00: data type (short, or uint16) 281 // 01 00 00 00: count 282 // xx 00 00 00: value (0x40 -> 0x44: a wider tile consumes more data 283 // than is available) 284 b1, err := replace(b0, 285 "42 01 03 00 01 00 00 00 40 00 00 00", 286 "42 01 03 00 01 00 00 00 44 00 00 00", 287 ) 288 if err != nil { 289 t.Fatal(err) 290 } 291 292 // Turn off the predictor, which makes it possible to hit the 293 // place with the defect. Without this patch to the image, we run 294 // out of data too early, and do not hit the part of the code where 295 // the original panic was. 296 // 297 // 3d 01: tag number (tPredictor) 298 // 03 00: data type (short, or uint16) 299 // 01 00 00 00: count 300 // xx 00 00 00: value (2 -> 1: 2 = horizontal, 1 = none) 301 b2, err := replace(b1, 302 "3d 01 03 00 01 00 00 00 02 00 00 00", 303 "3d 01 03 00 01 00 00 00 01 00 00 00", 304 ) 305 if err != nil { 306 t.Fatal(err) 307 } 308 309 _, err = Decode(bytes.NewReader(b2)) 310 if err == nil { 311 t.Fatal("did not expect nil error") 312 } 313 } 314 315 // TestZeroSizedImages tests that decoding does not panic when image dimensions 316 // are zero, and returns a zero-sized image instead. 317 // Issue 10393. 318 func TestZeroSizedImages(t *testing.T) { 319 testsizes := []struct { 320 w, h int 321 }{ 322 {0, 0}, 323 {1, 0}, 324 {0, 1}, 325 {1, 1}, 326 } 327 for _, r := range testsizes { 328 img := image.NewRGBA(image.Rect(0, 0, r.w, r.h)) 329 var buf bytes.Buffer 330 if err := Encode(&buf, img, nil); err != nil { 331 t.Errorf("encode w=%d h=%d: %v", r.w, r.h, err) 332 continue 333 } 334 if _, err := Decode(&buf); err != nil { 335 t.Errorf("decode w=%d h=%d: %v", r.w, r.h, err) 336 } 337 } 338 } 339 340 // TestLargeIFDEntry tests that a large IFD entry does not cause Decode to 341 // panic. 342 // Issue 10596. 343 func TestLargeIFDEntry(t *testing.T) { 344 testdata := "II*\x00\x08\x00\x00\x00\f\x000000000000" + 345 "00000000000000000000" + 346 "00000000000000000000" + 347 "00000000000000000000" + 348 "00000000000000\x17\x01\x04\x00\x01\x00" + 349 "\x00\xc0000000000000000000" + 350 "00000000000000000000" + 351 "00000000000000000000" + 352 "000000" 353 _, err := Decode(strings.NewReader(testdata)) 354 if err == nil { 355 t.Fatal("Decode with large IFD entry: got nil error, want non-nil") 356 } 357 } 358 359 // benchmarkDecode benchmarks the decoding of an image. 360 func benchmarkDecode(b *testing.B, filename string) { 361 b.StopTimer() 362 contents, err := ioutil.ReadFile(testdataDir + filename) 363 if err != nil { 364 b.Fatal(err) 365 } 366 r := &buffer{buf: contents} 367 b.StartTimer() 368 for i := 0; i < b.N; i++ { 369 _, err := Decode(r) 370 if err != nil { 371 b.Fatal("Decode:", err) 372 } 373 } 374 } 375 376 func BenchmarkDecodeCompressed(b *testing.B) { benchmarkDecode(b, "video-001.tiff") } 377 func BenchmarkDecodeUncompressed(b *testing.B) { benchmarkDecode(b, "video-001-uncompressed.tiff") }