blob: d16ef8a1a4ddcbdf093ed68bfe5788ef06baab67 [file] [log] [blame]
Nigel Tao7483c6e2011-03-03 20:35:49 +11001// 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
5package image_test
6
7import (
8 "bufio"
Nigel Tao782db7f2015-03-10 19:01:44 +11009 "fmt"
Nigel Tao7483c6e2011-03-03 20:35:49 +110010 "image"
Nigel Taoa2846e62011-10-04 11:09:03 +110011 "image/color"
Nigel Tao7483c6e2011-03-03 20:35:49 +110012 "os"
13 "testing"
14
Rob Pike92834d32011-05-07 22:57:42 -070015 _ "image/gif"
Nigel Tao7483c6e2011-03-03 20:35:49 +110016 _ "image/jpeg"
17 _ "image/png"
18)
19
Nigel Tao7483c6e2011-03-03 20:35:49 +110020type imageTest struct {
Nigel Tao5f7b0bc2011-05-17 15:47:14 -070021 goldenFilename string
22 filename string
23 tolerance int
Nigel Tao7483c6e2011-03-03 20:35:49 +110024}
25
26var imageTests = []imageTest{
Nigel Tao10498f42012-01-31 14:01:53 +110027 {"testdata/video-001.png", "testdata/video-001.png", 0},
Nigel Tao7483c6e2011-03-03 20:35:49 +110028 // GIF images are restricted to a 256-color palette and the conversion
29 // to GIF loses significant image quality.
Nigel Tao5f7b0bc2011-05-17 15:47:14 -070030 {"testdata/video-001.png", "testdata/video-001.gif", 64 << 8},
31 {"testdata/video-001.png", "testdata/video-001.interlaced.gif", 64 << 8},
32 {"testdata/video-001.png", "testdata/video-001.5bpp.gif", 128 << 8},
Nigel Tao7483c6e2011-03-03 20:35:49 +110033 // JPEG is a lossy format and hence needs a non-zero tolerance.
Nigel Tao5f7b0bc2011-05-17 15:47:14 -070034 {"testdata/video-001.png", "testdata/video-001.jpeg", 8 << 8},
Nigel Tao8b624f62012-10-15 11:21:20 +110035 {"testdata/video-001.png", "testdata/video-001.progressive.jpeg", 8 << 8},
Nigel Tao782db7f2015-03-10 19:01:44 +110036 {"testdata/video-001.221212.png", "testdata/video-001.221212.jpeg", 8 << 8},
Nigel Taof10e0372015-02-13 18:09:21 +110037 {"testdata/video-001.cmyk.png", "testdata/video-001.cmyk.jpeg", 8 << 8},
Nigel Taocc009682015-03-05 17:54:46 +110038 {"testdata/video-001.rgb.png", "testdata/video-001.rgb.jpeg", 8 << 8},
Nigel Tao10498f42012-01-31 14:01:53 +110039 // Grayscale images.
Nigel Tao5f7b0bc2011-05-17 15:47:14 -070040 {"testdata/video-005.gray.png", "testdata/video-005.gray.jpeg", 8 << 8},
41 {"testdata/video-005.gray.png", "testdata/video-005.gray.png", 0},
Nigel Tao7483c6e2011-03-03 20:35:49 +110042}
43
Russ Coxc2049d22011-11-01 22:04:37 -040044func decode(filename string) (image.Image, string, error) {
Rob Pike8a90fd32011-04-04 23:42:14 -070045 f, err := os.Open(filename)
Nigel Tao7483c6e2011-03-03 20:35:49 +110046 if err != nil {
47 return nil, "", err
48 }
49 defer f.Close()
50 return image.Decode(bufio.NewReader(f))
51}
52
Russ Coxc2049d22011-11-01 22:04:37 -040053func decodeConfig(filename string) (image.Config, string, error) {
Nigel Tao0d111a62011-05-16 10:13:17 -070054 f, err := os.Open(filename)
55 if err != nil {
56 return image.Config{}, "", err
57 }
58 defer f.Close()
59 return image.DecodeConfig(bufio.NewReader(f))
60}
61
Nigel Tao7483c6e2011-03-03 20:35:49 +110062func delta(u0, u1 uint32) int {
63 d := int(u0) - int(u1)
64 if d < 0 {
65 return -d
66 }
67 return d
68}
69
Nigel Taoa2846e62011-10-04 11:09:03 +110070func withinTolerance(c0, c1 color.Color, tolerance int) bool {
Nigel Tao7483c6e2011-03-03 20:35:49 +110071 r0, g0, b0, a0 := c0.RGBA()
72 r1, g1, b1, a1 := c1.RGBA()
73 r := delta(r0, r1)
74 g := delta(g0, g1)
75 b := delta(b0, b1)
76 a := delta(a0, a1)
77 return r <= tolerance && g <= tolerance && b <= tolerance && a <= tolerance
78}
79
80func TestDecode(t *testing.T) {
Nigel Tao782db7f2015-03-10 19:01:44 +110081 rgba := func(c color.Color) string {
82 r, g, b, a := c.RGBA()
83 return fmt.Sprintf("rgba = 0x%04x, 0x%04x, 0x%04x, 0x%04x for %T%v", r, g, b, a, c, c)
84 }
85
Nigel Tao5f7b0bc2011-05-17 15:47:14 -070086 golden := make(map[string]image.Image)
Nigel Tao7483c6e2011-03-03 20:35:49 +110087loop:
88 for _, it := range imageTests {
Nigel Tao5f7b0bc2011-05-17 15:47:14 -070089 g := golden[it.goldenFilename]
90 if g == nil {
Russ Coxc2049d22011-11-01 22:04:37 -040091 var err error
Nigel Tao5f7b0bc2011-05-17 15:47:14 -070092 g, _, err = decode(it.goldenFilename)
93 if err != nil {
94 t.Errorf("%s: %v", it.goldenFilename, err)
95 continue loop
96 }
97 golden[it.goldenFilename] = g
98 }
Nigel Tao0d111a62011-05-16 10:13:17 -070099 m, imageFormat, err := decode(it.filename)
Nigel Tao7483c6e2011-03-03 20:35:49 +1100100 if err != nil {
101 t.Errorf("%s: %v", it.filename, err)
102 continue loop
103 }
Nigel Tao5f7b0bc2011-05-17 15:47:14 -0700104 b := g.Bounds()
Nigel Tao7483c6e2011-03-03 20:35:49 +1100105 if !b.Eq(m.Bounds()) {
Nigel Tao782db7f2015-03-10 19:01:44 +1100106 t.Errorf("%s: got bounds %v want %v", it.filename, m.Bounds(), b)
Nigel Tao7483c6e2011-03-03 20:35:49 +1100107 continue loop
108 }
109 for y := b.Min.Y; y < b.Max.Y; y++ {
110 for x := b.Min.X; x < b.Max.X; x++ {
Nigel Tao5f7b0bc2011-05-17 15:47:14 -0700111 if !withinTolerance(g.At(x, y), m.At(x, y), it.tolerance) {
Nigel Tao782db7f2015-03-10 19:01:44 +1100112 t.Errorf("%s: at (%d, %d):\ngot %v\nwant %v",
113 it.filename, x, y, rgba(m.At(x, y)), rgba(g.At(x, y)))
Nigel Tao7483c6e2011-03-03 20:35:49 +1100114 continue loop
115 }
116 }
117 }
Nigel Tao0d111a62011-05-16 10:13:17 -0700118 if imageFormat == "gif" {
119 // Each frame of a GIF can have a frame-local palette override the
120 // GIF-global palette. Thus, image.Decode can yield a different ColorModel
121 // than image.DecodeConfig.
122 continue
123 }
124 c, _, err := decodeConfig(it.filename)
125 if m.ColorModel() != c.ColorModel {
126 t.Errorf("%s: color models differ", it.filename)
127 continue loop
128 }
Nigel Tao7483c6e2011-03-03 20:35:49 +1100129 }
130}