reader_test.go 10.0 KB

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