blob: 68aab78322c6600fc9e86a4ee1425a4b20b9fc82 [file] [log] [blame]
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package png
import (
"bufio"
"fmt"
"image"
"io"
"os"
"testing"
)
// The go PNG library currently supports only a subset of the full PNG specification.
// In particular, bit depths other than 8 are not supported, and neither are grayscale images.
var filenames = []string{
//"basn0g01", // bit depth is not 8
//"basn0g02", // bit depth is not 8
//"basn0g04", // bit depth is not 8
//"basn0g08", // grayscale color model
//"basn0g16", // bit depth is not 8
"basn2c08",
//"basn2c16", // bit depth is not 8
//"basn3p01", // bit depth is not 8
//"basn3p02", // bit depth is not 8
//"basn3p04", // bit depth is not 8
"basn3p08",
//"basn4a08", // grayscale color model
//"basn4a16", // bit depth is not 8
"basn6a08",
//"basn6a16", // bit depth is not 8
}
func readPng(filename string) (image.Image, os.Error) {
f, err := os.Open(filename, os.O_RDONLY, 0444)
if err != nil {
return nil, err
}
defer f.Close()
return Decode(f)
}
// An approximation of the sng command-line tool.
func sng(w io.WriteCloser, filename string, png image.Image) {
defer w.Close()
// For now, the go PNG parser only reads bitdepths of 8.
bitdepth := 8
// Write the filename and IHDR.
io.WriteString(w, "#SNG: from "+filename+".png\nIHDR {\n")
fmt.Fprintf(w, " width: %d; height: %d; bitdepth: %d;\n", png.Width(), png.Height(), bitdepth)
cm := png.ColorModel()
var paletted *image.Paletted
cpm, _ := cm.(image.PalettedColorModel)
switch {
case cm == image.RGBAColorModel:
io.WriteString(w, " using color;\n")
case cm == image.NRGBAColorModel:
io.WriteString(w, " using color alpha;\n")
case cpm != nil:
io.WriteString(w, " using color palette;\n")
paletted = png.(*image.Paletted)
default:
io.WriteString(w, "unknown PNG decoder color model\n")
}
io.WriteString(w, "}\n")
// We fake a gAMA output. The test files have a gAMA chunk but the go PNG parser ignores it
// (the PNG spec section 11.3 says "Ancillary chunks may be ignored by a decoder").
io.WriteString(w, "gAMA {1.0000}\n")
// Write the PLTE (if applicable).
if cpm != nil {
io.WriteString(w, "PLTE {\n")
for i := 0; i < len(cpm); i++ {
r, g, b, _ := cpm[i].RGBA()
r >>= 24
g >>= 24
b >>= 24
fmt.Fprintf(w, " (%3d,%3d,%3d) # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
}
io.WriteString(w, "}\n")
}
// Write the IMAGE.
io.WriteString(w, "IMAGE {\n pixels hex\n")
for y := 0; y < png.Height(); y++ {
switch {
case cm == image.RGBAColorModel:
for x := 0; x < png.Width(); x++ {
rgba := png.At(x, y).(image.RGBAColor)
fmt.Fprintf(w, "%02x%02x%02x ", rgba.R, rgba.G, rgba.B)
}
case cm == image.NRGBAColorModel:
for x := 0; x < png.Width(); x++ {
nrgba := png.At(x, y).(image.NRGBAColor)
fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
}
case cpm != nil:
for x := 0; x < png.Width(); x++ {
fmt.Fprintf(w, "%02x", paletted.ColorIndexAt(x, y))
}
}
io.WriteString(w, "\n")
}
io.WriteString(w, "}\n")
}
func TestReader(t *testing.T) {
for _, fn := range filenames {
// Read the .png file.
image, err := readPng("testdata/pngsuite/" + fn + ".png")
if err != nil {
t.Error(fn, err)
continue
}
piper, pipew := io.Pipe()
pb := bufio.NewReader(piper)
go sng(pipew, fn, image)
defer piper.Close()
// Read the .sng file.
sf, err := os.Open("testdata/pngsuite/"+fn+".sng", os.O_RDONLY, 0444)
if err != nil {
t.Error(fn, err)
continue
}
defer sf.Close()
sb := bufio.NewReader(sf)
if err != nil {
t.Error(fn, err)
continue
}
// Compare the two, in SNG format, line by line.
for {
ps, perr := pb.ReadString('\n')
ss, serr := sb.ReadString('\n')
if perr == os.EOF && serr == os.EOF {
break
}
if perr != nil {
t.Error(fn, perr)
break
}
if serr != nil {
t.Error(fn, serr)
break
}
if ps != ss {
t.Errorf("%s: Mismatch\n%sversus\n%s\n", fn, ps, ss)
break
}
}
}
}