Commit ca6ba492 authored by Nigel Tao's avatar Nigel Tao

image/png: don't read filter bytes for empty interlace passes.

Fixes #11604

The gray-gradient.png image was created by a Go program:

----
package main

import (
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
)

func main() {
	f, err := os.Create("a.png")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	m := image.NewGray(image.Rect(0, 0, 1, 16))
	for i := 0; i < 16; i++ {
		m.SetGray(0, i, color.Gray{uint8(i * 0x11)})
	}
	err = png.Encode(f, m)
	if err != nil {
		log.Fatal(err)
	}
}
----

The equivalent gray-gradient.interlaced.png image was created via ImageMagick:
$ convert -interlace PNG gray-gradient.png gray-gradient.interlaced.png

As a sanity check:
$ file gray-gradient.*
gray-gradient.interlaced.png: PNG image data, 1 x 16, 4-bit grayscale, interlaced
gray-gradient.png:            PNG image data, 1 x 16, 8-bit grayscale, non-interlaced

Change-Id: I7700284f74d1ea30073aede3bce4d7651787bdbc
Reviewed-on: https://go-review.googlesource.com/12064Reviewed-by: 's avatarRob Pike <r@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 616cb3c0
...@@ -340,7 +340,9 @@ func (d *decoder) decode() (image.Image, error) { ...@@ -340,7 +340,9 @@ func (d *decoder) decode() (image.Image, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
d.mergePassInto(img, imagePass, pass) if imagePass != nil {
d.mergePassInto(img, imagePass, pass)
}
} }
} }
...@@ -382,6 +384,12 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image ...@@ -382,6 +384,12 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
// Add the multiplication factor and subtract one, effectively rounding up. // Add the multiplication factor and subtract one, effectively rounding up.
width = (width - p.xOffset + p.xFactor - 1) / p.xFactor width = (width - p.xOffset + p.xFactor - 1) / p.xFactor
height = (height - p.yOffset + p.yFactor - 1) / p.yFactor height = (height - p.yOffset + p.yFactor - 1) / p.yFactor
// A PNG image can't have zero width or height, but for an interlaced
// image, an individual pass might have zero width or height. If so, we
// shouldn't even read a per-row filter type byte, so return early.
if width == 0 || height == 0 {
return nil, nil
}
} }
switch d.cb { switch d.cb {
case cbG1, cbG2, cbG4, cbG8: case cbG1, cbG2, cbG4, cbG8:
...@@ -457,6 +465,9 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image ...@@ -457,6 +465,9 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
cdat[i] += p cdat[i] += p
} }
case ftAverage: case ftAverage:
// The first column has no column to the left of it, so it is a
// special case. We know that the first column exists because we
// check above that width != 0, and so len(cdat) != 0.
for i := 0; i < bytesPerPixel; i++ { for i := 0; i < bytesPerPixel; i++ {
cdat[i] += pdat[i] / 2 cdat[i] += pdat[i] / 2
} }
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"reflect"
"strings" "strings"
"testing" "testing"
) )
...@@ -320,6 +321,20 @@ func TestPalettedDecodeConfig(t *testing.T) { ...@@ -320,6 +321,20 @@ func TestPalettedDecodeConfig(t *testing.T) {
} }
} }
func TestInterlaced(t *testing.T) {
a, err := readPNG("testdata/gray-gradient.png")
if err != nil {
t.Fatal(err)
}
b, err := readPNG("testdata/gray-gradient.interlaced.png")
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(a, b) {
t.Fatalf("decodings differ:\nnon-interlaced:\n%#v\ninterlaced:\n%#v", a, b)
}
}
func TestIncompleteIDATOnRowBoundary(t *testing.T) { func TestIncompleteIDATOnRowBoundary(t *testing.T) {
// The following is an invalid 1x2 grayscale PNG image. The header is OK, // The following is an invalid 1x2 grayscale PNG image. The header is OK,
// but the zlib-compressed IDAT payload contains two bytes "\x02\x00", // but the zlib-compressed IDAT payload contains two bytes "\x02\x00",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment