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) {
if err != nil {
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
// Add the multiplication factor and subtract one, effectively rounding up.
width = (width - p.xOffset + p.xFactor - 1) / p.xFactor
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 {
case cbG1, cbG2, cbG4, cbG8:
......@@ -457,6 +465,9 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
cdat[i] += p
}
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++ {
cdat[i] += pdat[i] / 2
}
......
......@@ -13,6 +13,7 @@ import (
"io"
"io/ioutil"
"os"
"reflect"
"strings"
"testing"
)
......@@ -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) {
// The following is an invalid 1x2 grayscale PNG image. The header is OK,
// 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