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.
21 var filenames
= []string{
59 var filenamesPaletted
= []string{
67 var filenamesShort
= []string{
73 func readPNG(filename
string) (image
.Image
, error
) {
74 f
, err
:= os
.Open(filename
)
82 // fakebKGDs maps from filenames to fake bKGD chunks for our approximation to
83 // the sng command-line tool. Package png doesn't keep that metadata when
84 // png.Decode returns an image.Image.
85 var fakebKGDs
= map[string]string{
86 "ftbbn0g01": "bKGD {gray: 0;}\n",
87 "ftbbn0g02": "bKGD {gray: 0;}\n",
88 "ftbbn0g04": "bKGD {gray: 0;}\n",
89 "ftbbn2c16": "bKGD {red: 0; green: 0; blue: 65535;}\n",
90 "ftbbn3p08": "bKGD {index: 245}\n",
91 "ftbgn2c16": "bKGD {red: 0; green: 65535; blue: 0;}\n",
92 "ftbgn3p08": "bKGD {index: 245}\n",
93 "ftbrn2c08": "bKGD {red: 255; green: 0; blue: 0;}\n",
94 "ftbwn0g16": "bKGD {gray: 65535;}\n",
95 "ftbwn3p08": "bKGD {index: 0}\n",
96 "ftbyn3p08": "bKGD {index: 245}\n",
99 // fakegAMAs maps from filenames to fake gAMA chunks for our approximation to
100 // the sng command-line tool. Package png doesn't keep that metadata when
101 // png.Decode returns an image.Image.
102 var fakegAMAs
= map[string]string{
104 "ftbbn0g02": "gAMA {0.45455}\n",
107 // fakeIHDRUsings maps from filenames to fake IHDR "using" lines for our
108 // approximation to the sng command-line tool. The PNG model is that
109 // transparency (in the tRNS chunk) is separate to the color/grayscale/palette
110 // color model (in the IHDR chunk). The Go model is that the concrete
111 // image.Image type returned by png.Decode, such as image.RGBA (with all pixels
112 // having 100% alpha) or image.NRGBA, encapsulates whether or not the image has
113 // transparency. This map is a hack to work around the fact that the Go model
114 // can't otherwise discriminate PNG's "IHDR says color (with no alpha) but tRNS
115 // says alpha" and "IHDR says color with alpha".
116 var fakeIHDRUsings
= map[string]string{
117 "ftbbn0g01": " using grayscale;\n",
118 "ftbbn0g02": " using grayscale;\n",
119 "ftbbn0g04": " using grayscale;\n",
120 "ftbbn2c16": " using color;\n",
121 "ftbgn2c16": " using color;\n",
122 "ftbrn2c08": " using color;\n",
123 "ftbwn0g16": " using grayscale;\n",
126 // An approximation of the sng command-line tool.
127 func sng(w io
.WriteCloser
, filename
string, png image
.Image
) {
129 bounds
:= png
.Bounds()
130 cm
:= png
.ColorModel()
133 case color
.RGBAModel
, color
.NRGBAModel
, color
.AlphaModel
, color
.GrayModel
:
138 cpm
, _
:= cm
.(color
.Palette
)
139 var paletted
*image
.Paletted
151 paletted
= png
.(*image
.Paletted
)
154 // Write the filename and IHDR.
155 io
.WriteString(w
, "#SNG: from "+filename
+".png\nIHDR {\n")
156 fmt
.Fprintf(w
, " width: %d; height: %d; bitdepth: %d;\n", bounds
.Dx(), bounds
.Dy(), bitdepth
)
157 if s
, ok
:= fakeIHDRUsings
[filename
]; ok
{
161 case cm
== color
.RGBAModel
, cm
== color
.RGBA64Model
:
162 io
.WriteString(w
, " using color;\n")
163 case cm
== color
.NRGBAModel
, cm
== color
.NRGBA64Model
:
164 io
.WriteString(w
, " using color alpha;\n")
165 case cm
== color
.GrayModel
, cm
== color
.Gray16Model
:
166 io
.WriteString(w
, " using grayscale;\n")
168 io
.WriteString(w
, " using color palette;\n")
170 io
.WriteString(w
, "unknown PNG decoder color model\n")
173 io
.WriteString(w
, "}\n")
175 // We fake a gAMA chunk. The test files have a gAMA chunk but the go PNG
176 // parser ignores it (the PNG spec section 11.3 says "Ancillary chunks may
177 // be ignored by a decoder").
178 if s
, ok
:= fakegAMAs
[filename
]; ok
{
181 io
.WriteString(w
, "gAMA {1.0000}\n")
184 // Write the PLTE and tRNS (if applicable).
185 useTransparent
:= false
188 io
.WriteString(w
, "PLTE {\n")
189 for i
, c
:= range cpm
{
191 switch c
:= c
.(type) {
193 r
, g
, b
, a
= c
.R
, c
.G
, c
.B
, 0xff
195 r
, g
, b
, a
= c
.R
, c
.G
, c
.B
, c
.A
197 panic("unknown palette color type")
202 fmt
.Fprintf(w
, " (%3d,%3d,%3d) # rgb = (0x%02x,0x%02x,0x%02x)\n", r
, g
, b
, r
, g
, b
)
204 io
.WriteString(w
, "}\n")
205 if s
, ok
:= fakebKGDs
[filename
]; ok
{
209 io
.WriteString(w
, "tRNS {\n")
210 for i
:= 0; i
<= lastAlpha
; i
++ {
211 _
, _
, _
, a
:= cpm
[i
].RGBA()
213 fmt
.Fprintf(w
, " %d", a
)
215 io
.WriteString(w
, "}\n")
217 } else if strings
.HasPrefix(filename
, "ft") {
218 if s
, ok
:= fakebKGDs
[filename
]; ok
{
221 // We fake a tRNS chunk. The test files' grayscale and truecolor
222 // transparent images all have their top left corner transparent.
223 switch c
:= png
.At(0, 0).(type) {
226 useTransparent
= true
227 io
.WriteString(w
, "tRNS {\n")
229 case "ftbbn0g01", "ftbbn0g02", "ftbbn0g04":
230 // The standard image package doesn't have a "gray with
231 // alpha" type. Instead, we use an image.NRGBA.
232 fmt
.Fprintf(w
, " gray: %d;\n", c
.R
)
234 fmt
.Fprintf(w
, " red: %d; green: %d; blue: %d;\n", c
.R
, c
.G
, c
.B
)
236 io
.WriteString(w
, "}\n")
240 useTransparent
= true
241 io
.WriteString(w
, "tRNS {\n")
244 // The standard image package doesn't have a "gray16 with
245 // alpha" type. Instead, we use an image.NRGBA64.
246 fmt
.Fprintf(w
, " gray: %d;\n", c
.R
)
248 fmt
.Fprintf(w
, " red: %d; green: %d; blue: %d;\n", c
.R
, c
.G
, c
.B
)
250 io
.WriteString(w
, "}\n")
256 io
.WriteString(w
, "IMAGE {\n pixels hex\n")
257 for y
:= bounds
.Min
.Y
; y
< bounds
.Max
.Y
; y
++ {
259 case cm
== color
.GrayModel
:
260 for x
:= bounds
.Min
.X
; x
< bounds
.Max
.X
; x
++ {
261 gray
:= png
.At(x
, y
).(color
.Gray
)
262 fmt
.Fprintf(w
, "%02x", gray
.Y
)
264 case cm
== color
.Gray16Model
:
265 for x
:= bounds
.Min
.X
; x
< bounds
.Max
.X
; x
++ {
266 gray16
:= png
.At(x
, y
).(color
.Gray16
)
267 fmt
.Fprintf(w
, "%04x ", gray16
.Y
)
269 case cm
== color
.RGBAModel
:
270 for x
:= bounds
.Min
.X
; x
< bounds
.Max
.X
; x
++ {
271 rgba
:= png
.At(x
, y
).(color
.RGBA
)
272 fmt
.Fprintf(w
, "%02x%02x%02x ", rgba
.R
, rgba
.G
, rgba
.B
)
274 case cm
== color
.RGBA64Model
:
275 for x
:= bounds
.Min
.X
; x
< bounds
.Max
.X
; x
++ {
276 rgba64
:= png
.At(x
, y
).(color
.RGBA64
)
277 fmt
.Fprintf(w
, "%04x%04x%04x ", rgba64
.R
, rgba64
.G
, rgba64
.B
)
279 case cm
== color
.NRGBAModel
:
280 for x
:= bounds
.Min
.X
; x
< bounds
.Max
.X
; x
++ {
281 nrgba
:= png
.At(x
, y
).(color
.NRGBA
)
283 case "ftbbn0g01", "ftbbn0g02", "ftbbn0g04":
284 fmt
.Fprintf(w
, "%02x", nrgba
.R
)
287 fmt
.Fprintf(w
, "%02x%02x%02x ", nrgba
.R
, nrgba
.G
, nrgba
.B
)
289 fmt
.Fprintf(w
, "%02x%02x%02x%02x ", nrgba
.R
, nrgba
.G
, nrgba
.B
, nrgba
.A
)
293 case cm
== color
.NRGBA64Model
:
294 for x
:= bounds
.Min
.X
; x
< bounds
.Max
.X
; x
++ {
295 nrgba64
:= png
.At(x
, y
).(color
.NRGBA64
)
298 fmt
.Fprintf(w
, "%04x ", nrgba64
.R
)
301 fmt
.Fprintf(w
, "%04x%04x%04x ", nrgba64
.R
, nrgba64
.G
, nrgba64
.B
)
303 fmt
.Fprintf(w
, "%04x%04x%04x%04x ", nrgba64
.R
, nrgba64
.G
, nrgba64
.B
, nrgba64
.A
)
309 for x
:= bounds
.Min
.X
; x
< bounds
.Max
.X
; x
++ {
310 b
= b
<<uint(bitdepth
) |
int(paletted
.ColorIndexAt(x
, y
))
313 fmt
.Fprintf(w
, "%02x", b
)
319 for c
!= 8/bitdepth
{
320 b
= b
<< uint(bitdepth
)
323 fmt
.Fprintf(w
, "%02x", b
)
326 io
.WriteString(w
, "\n")
328 io
.WriteString(w
, "}\n")
331 func TestReader(t
*testing
.T
) {
334 names
= filenamesShort
336 for _
, fn
:= range names
{
337 // Read the .png file.
338 img
, err
:= readPNG("testdata/pngsuite/" + fn
+ ".png")
344 if fn
== "basn4a16" {
345 // basn4a16.sng is gray + alpha but sng() will produce true color + alpha
346 // so we just check a single random pixel.
347 c
:= img
.At(2, 1).(color
.NRGBA64
)
348 if c
.R
!= 0x11a7 || c
.G
!= 0x11a7 || c
.B
!= 0x11a7 || c
.A
!= 0x1085 {
349 t
.Error(fn
, fmt
.Errorf("wrong pixel value at (2, 1): %x", c
))
354 piper
, pipew
:= io
.Pipe()
355 pb
:= bufio
.NewScanner(piper
)
356 go sng(pipew
, fn
, img
)
359 // Read the .sng file.
360 sf
, err
:= os
.Open("testdata/pngsuite/" + fn
+ ".sng")
366 sb
:= bufio
.NewScanner(sf
)
372 // Compare the two, in SNG format, line by line.
380 t
.Errorf("%s: Different sizes", fn
)
386 // Newer versions of the sng command line tool append an optional
387 // color name to the RGB tuple. For example:
388 // # rgb = (0xff,0xff,0xff) grey100
389 // # rgb = (0x00,0x00,0xff) blue1
390 // instead of the older version's plainer:
391 // # rgb = (0xff,0xff,0xff)
392 // # rgb = (0x00,0x00,0xff)
393 // We strip any such name.
394 if strings
.Contains(ss
, "# rgb = (") && !strings
.HasSuffix(ss
, ")") {
395 if i
:= strings
.LastIndex(ss
, ") "); i
>= 0 {
401 t
.Errorf("%s: Mismatch\n%s\nversus\n%s\n", fn
, ps
, ss
)
406 t
.Error(fn
, pb
.Err())
409 t
.Error(fn
, sb
.Err())
414 var readerErrors
= []struct {
418 {"invalid-zlib.png", "zlib: invalid checksum"},
419 {"invalid-crc32.png", "invalid checksum"},
420 {"invalid-noend.png", "unexpected EOF"},
421 {"invalid-trunc.png", "unexpected EOF"},
424 func TestReaderError(t
*testing
.T
) {
425 for _
, tt
:= range readerErrors
{
426 img
, err
:= readPNG("testdata/" + tt
.file
)
428 t
.Errorf("decoding %s: missing error", tt
.file
)
431 if !strings
.Contains(err
.Error(), tt
.err
) {
432 t
.Errorf("decoding %s: %s, want %s", tt
.file
, err
, tt
.err
)
435 t
.Errorf("decoding %s: have image + error", tt
.file
)
440 func TestPalettedDecodeConfig(t
*testing
.T
) {
441 for _
, fn
:= range filenamesPaletted
{
442 f
, err
:= os
.Open("testdata/pngsuite/" + fn
+ ".png")
444 t
.Errorf("%s: open failed: %v", fn
, err
)
448 cfg
, err
:= DecodeConfig(f
)
450 t
.Errorf("%s: %v", fn
, err
)
453 pal
, ok
:= cfg
.ColorModel
.(color
.Palette
)
455 t
.Errorf("%s: expected paletted color model", fn
)
459 t
.Errorf("%s: palette not initialized", fn
)
465 func TestInterlaced(t
*testing
.T
) {
466 a
, err
:= readPNG("testdata/gray-gradient.png")
470 b
, err
:= readPNG("testdata/gray-gradient.interlaced.png")
474 if !reflect
.DeepEqual(a
, b
) {
475 t
.Fatalf("decodings differ:\nnon-interlaced:\n%#v\ninterlaced:\n%#v", a
, b
)
479 func TestIncompleteIDATOnRowBoundary(t
*testing
.T
) {
480 // The following is an invalid 1x2 grayscale PNG image. The header is OK,
481 // but the zlib-compressed IDAT payload contains two bytes "\x02\x00",
482 // which is only one row of data (the leading "\x02" is a row filter).
484 ihdr
= "\x00\x00\x00\x0dIHDR\x00\x00\x00\x01\x00\x00\x00\x02\x08\x00\x00\x00\x00\xbc\xea\xe9\xfb"
485 idat
= "\x00\x00\x00\x0eIDAT\x78\x9c\x62\x62\x00\x04\x00\x00\xff\xff\x00\x06\x00\x03\xfa\xd0\x59\xae"
486 iend
= "\x00\x00\x00\x00IEND\xae\x42\x60\x82"
488 _
, err
:= Decode(strings
.NewReader(pngHeader
+ ihdr
+ idat
+ iend
))
490 t
.Fatal("got nil error, want non-nil")
494 func TestTrailingIDATChunks(t
*testing
.T
) {
495 // The following is a valid 1x1 PNG image containing color.Gray{255} and
496 // a trailing zero-length IDAT chunk (see PNG specification section 12.9):
498 ihdr
= "\x00\x00\x00\x0dIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x00\x00\x00\x00\x3a\x7e\x9b\x55"
499 idatWhite
= "\x00\x00\x00\x0eIDAT\x78\x9c\x62\xfa\x0f\x08\x00\x00\xff\xff\x01\x05\x01\x02\x5a\xdd\x39\xcd"
500 idatZero
= "\x00\x00\x00\x00IDAT\x35\xaf\x06\x1e"
501 iend
= "\x00\x00\x00\x00IEND\xae\x42\x60\x82"
503 _
, err
:= Decode(strings
.NewReader(pngHeader
+ ihdr
+ idatWhite
+ idatZero
+ iend
))
505 t
.Fatalf("decoding valid image: %v", err
)
508 // Non-zero-length trailing IDAT chunks should be ignored (recoverable error).
509 // The following chunk contains a single pixel with color.Gray{0}.
510 const idatBlack
= "\x00\x00\x00\x0eIDAT\x78\x9c\x62\x62\x00\x04\x00\x00\xff\xff\x00\x06\x00\x03\xfa\xd0\x59\xae"
512 img
, err
:= Decode(strings
.NewReader(pngHeader
+ ihdr
+ idatWhite
+ idatBlack
+ iend
))
514 t
.Fatalf("trailing IDAT not ignored: %v", err
)
516 if img
.At(0, 0) == (color
.Gray
{0}) {
517 t
.Fatal("decoded image from trailing IDAT chunk")
521 func TestMultipletRNSChunks(t
*testing
.T
) {
523 The following is a valid 1x1 paletted PNG image with a 1-element palette
524 containing color.NRGBA{0xff, 0x00, 0x00, 0x7f}:
525 0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
526 0000010: 0000 0001 0000 0001 0803 0000 0028 cb34 .............(.4
527 0000020: bb00 0000 0350 4c54 45ff 0000 19e2 0937 .....PLTE......7
528 0000030: 0000 0001 7452 4e53 7f80 5cb4 cb00 0000 ....tRNS..\.....
529 0000040: 0e49 4441 5478 9c62 6200 0400 00ff ff00 .IDATx.bb.......
530 0000050: 0600 03fa d059 ae00 0000 0049 454e 44ae .....Y.....IEND.
532 Dropping the tRNS chunk makes that color's alpha 0xff instead of 0x7f.
535 ihdr
= "\x00\x00\x00\x0dIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x03\x00\x00\x00\x28\xcb\x34\xbb"
536 plte
= "\x00\x00\x00\x03PLTE\xff\x00\x00\x19\xe2\x09\x37"
537 trns
= "\x00\x00\x00\x01tRNS\x7f\x80\x5c\xb4\xcb"
538 idat
= "\x00\x00\x00\x0eIDAT\x78\x9c\x62\x62\x00\x04\x00\x00\xff\xff\x00\x06\x00\x03\xfa\xd0\x59\xae"
539 iend
= "\x00\x00\x00\x00IEND\xae\x42\x60\x82"
541 for i
:= 0; i
< 4; i
++ {
543 b
= append(b
, pngHeader
...)
544 b
= append(b
, ihdr
...)
545 b
= append(b
, plte
...)
546 for j
:= 0; j
< i
; j
++ {
547 b
= append(b
, trns
...)
549 b
= append(b
, idat
...)
550 b
= append(b
, iend
...)
553 m
, err
:= Decode(bytes
.NewReader(b
))
557 t
.Errorf("%d tRNS chunks: %v", i
, err
)
560 want
= color
.RGBA
{0xff, 0x00, 0x00, 0xff}
563 t
.Errorf("%d tRNS chunks: %v", i
, err
)
566 want
= color
.NRGBA
{0xff, 0x00, 0x00, 0x7f}
569 t
.Errorf("%d tRNS chunks: got nil error, want non-nil", i
)
573 if got
:= m
.At(0, 0); got
!= want
{
574 t
.Errorf("%d tRNS chunks: got %T %v, want %T %v", i
, got
, got
, want
, want
)
579 func TestUnknownChunkLengthUnderflow(t
*testing
.T
) {
580 data
:= []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0xff, 0xff,
581 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0xf4, 0x7c, 0x55, 0x04, 0x1a,
582 0xd3, 0x11, 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e, 0x00, 0x00,
583 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0x7c, 0x55, 0x04, 0x1a,
585 _
, err
:= Decode(bytes
.NewReader(data
))
587 t
.Errorf("Didn't fail reading an unknown chunk with length 0xffffffff")
591 func TestGray8Transparent(t
*testing
.T
) {
592 // These bytes come from https://github.com/golang/go/issues/19553
593 m
, err
:= Decode(bytes
.NewReader([]byte{
594 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
595 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x85, 0x2c, 0x88,
596 0x80, 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0x00, 0xff, 0x5b, 0x91, 0x22, 0xb5, 0x00,
597 0x00, 0x00, 0x02, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x00, 0x00, 0x00,
598 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x0a, 0xf0, 0x01, 0x42, 0xac,
599 0x34, 0x98, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5, 0x04, 0x02, 0x12, 0x11,
600 0x11, 0xf7, 0x65, 0x3d, 0x8b, 0x00, 0x00, 0x00, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63,
601 0xf8, 0xff, 0xff, 0xff, 0xb9, 0xbd, 0x70, 0xf0, 0x8c, 0x01, 0xc8, 0xaf, 0x6e, 0x99, 0x02, 0x05,
602 0xd9, 0x7b, 0xc1, 0xfc, 0x6b, 0xff, 0xa1, 0xa0, 0x87, 0x30, 0xff, 0xd9, 0xde, 0xbd, 0xd5, 0x4b,
603 0xf7, 0xee, 0xfd, 0x0e, 0xe3, 0xef, 0xcd, 0x06, 0x19, 0x14, 0xf5, 0x1e, 0xce, 0xef, 0x01, 0x31,
604 0x92, 0xd7, 0x82, 0x41, 0x31, 0x9c, 0x3f, 0x07, 0x02, 0xee, 0xa1, 0xaa, 0xff, 0xff, 0x9f, 0xe1,
605 0xd9, 0x56, 0x30, 0xf8, 0x0e, 0xe5, 0x03, 0x00, 0xa9, 0x42, 0x84, 0x3d, 0xdf, 0x8f, 0xa6, 0x8f,
606 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
609 t
.Fatalf("Decode: %v", err
)
612 const hex
= "0123456789abcdef"
615 for y
:= bounds
.Min
.Y
; y
< bounds
.Max
.Y
; y
++ {
616 for x
:= bounds
.Min
.X
; x
< bounds
.Max
.X
; x
++ {
617 if r
, _
, _
, a
:= m
.At(x
, y
).RGBA(); a
!= 0 {
631 got
= append(got
, '\n')
635 ".. .. .. ce bd bd bd bd bd bd bd bd bd bd e6 \n" +
636 ".. .. .. 7b 84 94 94 94 94 94 94 94 94 6b bd \n" +
637 ".. .. .. 7b d6 .. .. .. .. .. .. .. .. 8c bd \n" +
638 ".. .. .. 7b d6 .. .. .. .. .. .. .. .. 8c bd \n" +
639 ".. .. .. 7b d6 .. .. .. .. .. .. .. .. 8c bd \n" +
640 "e6 bd bd 7b a5 bd bd f7 .. .. .. .. .. 8c bd \n" +
641 "bd 6b 94 94 94 94 5a ef .. .. .. .. .. 8c bd \n" +
642 "bd 8c .. .. .. .. 63 ad ad ad ad ad ad 73 bd \n" +
643 "bd 8c .. .. .. .. 63 9c 9c 9c 9c 9c 9c 9c de \n" +
644 "bd 6b 94 94 94 94 5a ef .. .. .. .. .. .. .. \n" +
645 "e6 b5 b5 b5 b5 b5 b5 f7 .. .. .. .. .. .. .. \n"
647 if string(got
) != want
{
648 t
.Errorf("got:\n%swant:\n%s", got
, want
)
652 func benchmarkDecode(b
*testing
.B
, filename
string, bytesPerPixel
int) {
654 data
, err
:= ioutil
.ReadFile(filename
)
659 cfg
, err
:= DecodeConfig(strings
.NewReader(s
))
663 b
.SetBytes(int64(cfg
.Width
* cfg
.Height
* bytesPerPixel
))
665 for i
:= 0; i
< b
.N
; i
++ {
666 Decode(strings
.NewReader(s
))
670 func BenchmarkDecodeGray(b
*testing
.B
) {
671 benchmarkDecode(b
, "testdata/benchGray.png", 1)
674 func BenchmarkDecodeNRGBAGradient(b
*testing
.B
) {
675 benchmarkDecode(b
, "testdata/benchNRGBA-gradient.png", 4)
678 func BenchmarkDecodeNRGBAOpaque(b
*testing
.B
) {
679 benchmarkDecode(b
, "testdata/benchNRGBA-opaque.png", 4)
682 func BenchmarkDecodePaletted(b
*testing
.B
) {
683 benchmarkDecode(b
, "testdata/benchPaletted.png", 1)
686 func BenchmarkDecodeRGB(b
*testing
.B
) {
687 benchmarkDecode(b
, "testdata/benchRGB.png", 4)
690 func BenchmarkDecodeInterlacing(b
*testing
.B
) {
691 benchmarkDecode(b
, "testdata/benchRGB-interlace.png", 4)