* gcc.dg/guality/guality.exp: Skip on AIX.
[official-gcc.git] / libgo / go / image / png / reader_test.go
blobac0d949a9d3905eff785db46c2af683a3c1a63d7
1 // Copyright 2009 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.
5 package png
7 import (
8 "bufio"
9 "fmt"
10 "image"
11 "image/color"
12 "io"
13 "io/ioutil"
14 "os"
15 "strings"
16 "testing"
19 var filenames = []string{
20 "basn0g01",
21 "basn0g01-30",
22 "basn0g02",
23 "basn0g02-29",
24 "basn0g04",
25 "basn0g04-31",
26 "basn0g08",
27 "basn0g16",
28 "basn2c08",
29 "basn2c16",
30 "basn3p01",
31 "basn3p02",
32 "basn3p04",
33 "basn3p08",
34 "basn3p08-trns",
35 "basn4a08",
36 "basn4a16",
37 "basn6a08",
38 "basn6a16",
41 var filenamesPaletted = []string{
42 "basn3p01",
43 "basn3p02",
44 "basn3p04",
45 "basn3p08",
46 "basn3p08-trns",
49 var filenamesShort = []string{
50 "basn0g01",
51 "basn0g04-31",
52 "basn6a16",
55 func readPNG(filename string) (image.Image, error) {
56 f, err := os.Open(filename)
57 if err != nil {
58 return nil, err
60 defer f.Close()
61 return Decode(f)
64 // An approximation of the sng command-line tool.
65 func sng(w io.WriteCloser, filename string, png image.Image) {
66 defer w.Close()
67 bounds := png.Bounds()
68 cm := png.ColorModel()
69 var bitdepth int
70 switch cm {
71 case color.RGBAModel, color.NRGBAModel, color.AlphaModel, color.GrayModel:
72 bitdepth = 8
73 default:
74 bitdepth = 16
76 cpm, _ := cm.(color.Palette)
77 var paletted *image.Paletted
78 if cpm != nil {
79 switch {
80 case len(cpm) <= 2:
81 bitdepth = 1
82 case len(cpm) <= 4:
83 bitdepth = 2
84 case len(cpm) <= 16:
85 bitdepth = 4
86 default:
87 bitdepth = 8
89 paletted = png.(*image.Paletted)
92 // Write the filename and IHDR.
93 io.WriteString(w, "#SNG: from "+filename+".png\nIHDR {\n")
94 fmt.Fprintf(w, " width: %d; height: %d; bitdepth: %d;\n", bounds.Dx(), bounds.Dy(), bitdepth)
95 switch {
96 case cm == color.RGBAModel, cm == color.RGBA64Model:
97 io.WriteString(w, " using color;\n")
98 case cm == color.NRGBAModel, cm == color.NRGBA64Model:
99 io.WriteString(w, " using color alpha;\n")
100 case cm == color.GrayModel, cm == color.Gray16Model:
101 io.WriteString(w, " using grayscale;\n")
102 case cpm != nil:
103 io.WriteString(w, " using color palette;\n")
104 default:
105 io.WriteString(w, "unknown PNG decoder color model\n")
107 io.WriteString(w, "}\n")
109 // We fake a gAMA output. The test files have a gAMA chunk but the go PNG parser ignores it
110 // (the PNG spec section 11.3 says "Ancillary chunks may be ignored by a decoder").
111 io.WriteString(w, "gAMA {1.0000}\n")
113 // Write the PLTE and tRNS (if applicable).
114 if cpm != nil {
115 lastAlpha := -1
116 io.WriteString(w, "PLTE {\n")
117 for i, c := range cpm {
118 var r, g, b, a uint8
119 switch c := c.(type) {
120 case color.RGBA:
121 r, g, b, a = c.R, c.G, c.B, 0xff
122 case color.NRGBA:
123 r, g, b, a = c.R, c.G, c.B, c.A
124 default:
125 panic("unknown palette color type")
127 if a != 0xff {
128 lastAlpha = i
130 fmt.Fprintf(w, " (%3d,%3d,%3d) # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
132 io.WriteString(w, "}\n")
133 if lastAlpha != -1 {
134 io.WriteString(w, "tRNS {\n")
135 for i := 0; i <= lastAlpha; i++ {
136 _, _, _, a := cpm[i].RGBA()
137 a >>= 8
138 fmt.Fprintf(w, " %d", a)
140 io.WriteString(w, "}\n")
144 // Write the IMAGE.
145 io.WriteString(w, "IMAGE {\n pixels hex\n")
146 for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
147 switch {
148 case cm == color.GrayModel:
149 for x := bounds.Min.X; x < bounds.Max.X; x++ {
150 gray := png.At(x, y).(color.Gray)
151 fmt.Fprintf(w, "%02x", gray.Y)
153 case cm == color.Gray16Model:
154 for x := bounds.Min.X; x < bounds.Max.X; x++ {
155 gray16 := png.At(x, y).(color.Gray16)
156 fmt.Fprintf(w, "%04x ", gray16.Y)
158 case cm == color.RGBAModel:
159 for x := bounds.Min.X; x < bounds.Max.X; x++ {
160 rgba := png.At(x, y).(color.RGBA)
161 fmt.Fprintf(w, "%02x%02x%02x ", rgba.R, rgba.G, rgba.B)
163 case cm == color.RGBA64Model:
164 for x := bounds.Min.X; x < bounds.Max.X; x++ {
165 rgba64 := png.At(x, y).(color.RGBA64)
166 fmt.Fprintf(w, "%04x%04x%04x ", rgba64.R, rgba64.G, rgba64.B)
168 case cm == color.NRGBAModel:
169 for x := bounds.Min.X; x < bounds.Max.X; x++ {
170 nrgba := png.At(x, y).(color.NRGBA)
171 fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
173 case cm == color.NRGBA64Model:
174 for x := bounds.Min.X; x < bounds.Max.X; x++ {
175 nrgba64 := png.At(x, y).(color.NRGBA64)
176 fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
178 case cpm != nil:
179 var b, c int
180 for x := bounds.Min.X; x < bounds.Max.X; x++ {
181 b = b<<uint(bitdepth) | int(paletted.ColorIndexAt(x, y))
183 if c == 8/bitdepth {
184 fmt.Fprintf(w, "%02x", b)
185 b = 0
186 c = 0
190 io.WriteString(w, "\n")
192 io.WriteString(w, "}\n")
195 func TestReader(t *testing.T) {
196 names := filenames
197 if testing.Short() {
198 names = filenamesShort
200 for _, fn := range names {
201 // Read the .png file.
202 img, err := readPNG("testdata/pngsuite/" + fn + ".png")
203 if err != nil {
204 t.Error(fn, err)
205 continue
208 if fn == "basn4a16" {
209 // basn4a16.sng is gray + alpha but sng() will produce true color + alpha
210 // so we just check a single random pixel.
211 c := img.At(2, 1).(color.NRGBA64)
212 if c.R != 0x11a7 || c.G != 0x11a7 || c.B != 0x11a7 || c.A != 0x1085 {
213 t.Error(fn, fmt.Errorf("wrong pixel value at (2, 1): %x", c))
215 continue
218 piper, pipew := io.Pipe()
219 pb := bufio.NewScanner(piper)
220 go sng(pipew, fn, img)
221 defer piper.Close()
223 // Read the .sng file.
224 sf, err := os.Open("testdata/pngsuite/" + fn + ".sng")
225 if err != nil {
226 t.Error(fn, err)
227 continue
229 defer sf.Close()
230 sb := bufio.NewScanner(sf)
231 if err != nil {
232 t.Error(fn, err)
233 continue
236 // Compare the two, in SNG format, line by line.
237 for {
238 pdone := pb.Scan()
239 sdone := sb.Scan()
240 if pdone && sdone {
241 break
243 if pdone || sdone {
244 t.Errorf("%s: Different sizes", fn)
245 break
247 ps := pb.Text()
248 ss := sb.Text()
249 if ps != ss {
250 t.Errorf("%s: Mismatch\n%sversus\n%s\n", fn, ps, ss)
251 break
254 if pb.Err() != nil {
255 t.Error(fn, pb.Err())
257 if sb.Err() != nil {
258 t.Error(fn, sb.Err())
263 var readerErrors = []struct {
264 file string
265 err string
267 {"invalid-zlib.png", "zlib: invalid checksum"},
268 {"invalid-crc32.png", "invalid checksum"},
269 {"invalid-noend.png", "unexpected EOF"},
270 {"invalid-trunc.png", "unexpected EOF"},
273 func TestReaderError(t *testing.T) {
274 for _, tt := range readerErrors {
275 img, err := readPNG("testdata/" + tt.file)
276 if err == nil {
277 t.Errorf("decoding %s: missing error", tt.file)
278 continue
280 if !strings.Contains(err.Error(), tt.err) {
281 t.Errorf("decoding %s: %s, want %s", tt.file, err, tt.err)
283 if img != nil {
284 t.Errorf("decoding %s: have image + error", tt.file)
289 func TestPalettedDecodeConfig(t *testing.T) {
290 for _, fn := range filenamesPaletted {
291 f, err := os.Open("testdata/pngsuite/" + fn + ".png")
292 if err != nil {
293 t.Errorf("%s: open failed: %v", fn, err)
294 continue
296 defer f.Close()
297 cfg, err := DecodeConfig(f)
298 if err != nil {
299 t.Errorf("%s: %v", fn, err)
300 continue
302 pal, ok := cfg.ColorModel.(color.Palette)
303 if !ok {
304 t.Errorf("%s: expected paletted color model", fn)
305 continue
307 if pal == nil {
308 t.Errorf("%s: palette not initialized", fn)
309 continue
314 func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
315 b.StopTimer()
316 data, err := ioutil.ReadFile(filename)
317 if err != nil {
318 b.Fatal(err)
320 s := string(data)
321 cfg, err := DecodeConfig(strings.NewReader(s))
322 if err != nil {
323 b.Fatal(err)
325 b.SetBytes(int64(cfg.Width * cfg.Height * bytesPerPixel))
326 b.StartTimer()
327 for i := 0; i < b.N; i++ {
328 Decode(strings.NewReader(s))
332 func BenchmarkDecodeGray(b *testing.B) {
333 benchmarkDecode(b, "testdata/benchGray.png", 1)
336 func BenchmarkDecodeNRGBAGradient(b *testing.B) {
337 benchmarkDecode(b, "testdata/benchNRGBA-gradient.png", 4)
340 func BenchmarkDecodeNRGBAOpaque(b *testing.B) {
341 benchmarkDecode(b, "testdata/benchNRGBA-opaque.png", 4)
344 func BenchmarkDecodePaletted(b *testing.B) {
345 benchmarkDecode(b, "testdata/benchPaletted.png", 1)
348 func BenchmarkDecodeRGB(b *testing.B) {
349 benchmarkDecode(b, "testdata/benchRGB.png", 4)