aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/image
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2016-02-03 21:58:02 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-02-03 21:58:02 +0000
commitf98dd1a338867a408f7c72d73fbad7fe7fc93e3a (patch)
tree2f8da9862a9c1fe0df138917f997b03439c02773 /libgo/go/image
parentb081ed4efc144da0c45a6484aebfd10e0eb9fda3 (diff)
downloadgcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.zip
gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.tar.gz
gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.tar.bz2
libgo: Update to go1.6rc1.
Reviewed-on: https://go-review.googlesource.com/19200 From-SVN: r233110
Diffstat (limited to 'libgo/go/image')
-rw-r--r--libgo/go/image/color/ycbcr.go62
-rw-r--r--libgo/go/image/color/ycbcr_test.go26
-rw-r--r--libgo/go/image/draw/draw.go50
-rw-r--r--libgo/go/image/gif/writer.go2
-rw-r--r--libgo/go/image/gif/writer_test.go10
-rw-r--r--libgo/go/image/image.go21
-rw-r--r--libgo/go/image/png/reader.go7
-rw-r--r--libgo/go/image/png/reader_test.go12
-rw-r--r--libgo/go/image/ycbcr.go126
9 files changed, 268 insertions, 48 deletions
diff --git a/libgo/go/image/color/ycbcr.go b/libgo/go/image/color/ycbcr.go
index 4bcb07d..904434f 100644
--- a/libgo/go/image/color/ycbcr.go
+++ b/libgo/go/image/color/ycbcr.go
@@ -98,7 +98,7 @@ func (c YCbCr) RGBA() (uint32, uint32, uint32, uint32) {
// fmt.Printf("0x%04x 0x%04x 0x%04x\n", r0, g0, b0)
// fmt.Printf("0x%04x 0x%04x 0x%04x\n", r1, g1, b1)
// prints:
- // 0x7e18 0x808e 0x7db9
+ // 0x7e18 0x808d 0x7db9
// 0x7e7e 0x8080 0x7d7d
yy1 := int32(c.Y) * 0x10100 // Convert 0x12 to 0x121200.
@@ -137,6 +137,66 @@ func yCbCrModel(c Color) Color {
return YCbCr{y, u, v}
}
+// NYCbCrA represents a non-alpha-premultiplied Y'CbCr-with-alpha color, having
+// 8 bits each for one luma, two chroma and one alpha component.
+type NYCbCrA struct {
+ YCbCr
+ A uint8
+}
+
+func (c NYCbCrA) RGBA() (uint32, uint32, uint32, uint32) {
+ // The first part of this method is the same as YCbCr.RGBA.
+ yy1 := int32(c.Y) * 0x10100 // Convert 0x12 to 0x121200.
+ cb1 := int32(c.Cb) - 128
+ cr1 := int32(c.Cr) - 128
+ r := (yy1 + 91881*cr1) >> 8
+ g := (yy1 - 22554*cb1 - 46802*cr1) >> 8
+ b := (yy1 + 116130*cb1) >> 8
+ if r < 0 {
+ r = 0
+ } else if r > 0xffff {
+ r = 0xffff
+ }
+ if g < 0 {
+ g = 0
+ } else if g > 0xffff {
+ g = 0xffff
+ }
+ if b < 0 {
+ b = 0
+ } else if b > 0xffff {
+ b = 0xffff
+ }
+
+ // The second part of this method applies the alpha.
+ a := uint32(c.A) * 0x101
+ return uint32(r) * a / 0xffff, uint32(g) * a / 0xffff, uint32(b) * a / 0xffff, a
+}
+
+// NYCbCrAModel is the Model for non-alpha-premultiplied Y'CbCr-with-alpha
+// colors.
+var NYCbCrAModel Model = ModelFunc(nYCbCrAModel)
+
+func nYCbCrAModel(c Color) Color {
+ switch c := c.(type) {
+ case NYCbCrA:
+ return c
+ case YCbCr:
+ return NYCbCrA{c, 0xff}
+ }
+ r, g, b, a := c.RGBA()
+
+ // Convert from alpha-premultiplied to non-alpha-premultiplied.
+ if a != 0 {
+ r = (r * 0xffff) / a
+ g = (g * 0xffff) / a
+ b = (b * 0xffff) / a
+ }
+
+ y, u, v := RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
+ return NYCbCrA{YCbCr{Y: y, Cb: u, Cr: v}, uint8(a >> 8)}
+}
+
// RGBToCMYK converts an RGB triple to a CMYK quadruple.
func RGBToCMYK(r, g, b uint8) (uint8, uint8, uint8, uint8) {
rr := uint32(r)
diff --git a/libgo/go/image/color/ycbcr_test.go b/libgo/go/image/color/ycbcr_test.go
index 5da49d3..f5e7cbf 100644
--- a/libgo/go/image/color/ycbcr_test.go
+++ b/libgo/go/image/color/ycbcr_test.go
@@ -67,7 +67,31 @@ func TestYCbCrToRGBConsistency(t *testing.T) {
// TestYCbCrGray tests that YCbCr colors are a superset of Gray colors.
func TestYCbCrGray(t *testing.T) {
for i := 0; i < 256; i++ {
- if err := eq(YCbCr{uint8(i), 0x80, 0x80}, Gray{uint8(i)}); err != nil {
+ c0 := YCbCr{uint8(i), 0x80, 0x80}
+ c1 := Gray{uint8(i)}
+ if err := eq(c0, c1); err != nil {
+ t.Errorf("i=0x%02x:\n%v", i, err)
+ }
+ }
+}
+
+// TestNYCbCrAAlpha tests that NYCbCrA colors are a superset of Alpha colors.
+func TestNYCbCrAAlpha(t *testing.T) {
+ for i := 0; i < 256; i++ {
+ c0 := NYCbCrA{YCbCr{0xff, 0x80, 0x80}, uint8(i)}
+ c1 := Alpha{uint8(i)}
+ if err := eq(c0, c1); err != nil {
+ t.Errorf("i=0x%02x:\n%v", i, err)
+ }
+ }
+}
+
+// TestNYCbCrAYCbCr tests that NYCbCrA colors are a superset of YCbCr colors.
+func TestNYCbCrAYCbCr(t *testing.T) {
+ for i := 0; i < 256; i++ {
+ c0 := NYCbCrA{YCbCr{uint8(i), 0x40, 0xc0}, 0xff}
+ c1 := YCbCr{uint8(i), 0x40, 0xc0}
+ if err := eq(c0, c1); err != nil {
t.Errorf("i=0x%02x:\n%v", i, err)
}
}
diff --git a/libgo/go/image/draw/draw.go b/libgo/go/image/draw/draw.go
index 9419d5e..e47c48d 100644
--- a/libgo/go/image/draw/draw.go
+++ b/libgo/go/image/draw/draw.go
@@ -240,15 +240,15 @@ func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
i1 := i0 + r.Dx()*4
for y := r.Min.Y; y != r.Max.Y; y++ {
for i := i0; i < i1; i += 4 {
- dr := uint32(dst.Pix[i+0])
- dg := uint32(dst.Pix[i+1])
- db := uint32(dst.Pix[i+2])
- da := uint32(dst.Pix[i+3])
-
- dst.Pix[i+0] = uint8((dr*a/m + sr) >> 8)
- dst.Pix[i+1] = uint8((dg*a/m + sg) >> 8)
- dst.Pix[i+2] = uint8((db*a/m + sb) >> 8)
- dst.Pix[i+3] = uint8((da*a/m + sa) >> 8)
+ dr := &dst.Pix[i+0]
+ dg := &dst.Pix[i+1]
+ db := &dst.Pix[i+2]
+ da := &dst.Pix[i+3]
+
+ *dr = uint8((uint32(*dr)*a/m + sr) >> 8)
+ *dg = uint8((uint32(*dg)*a/m + sg) >> 8)
+ *db = uint8((uint32(*db)*a/m + sb) >> 8)
+ *da = uint8((uint32(*da)*a/m + sa) >> 8)
}
i0 += dst.Stride
i1 += dst.Stride
@@ -310,18 +310,18 @@ func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.
sb := uint32(spix[i+2]) * 0x101
sa := uint32(spix[i+3]) * 0x101
- dr := uint32(dpix[i+0])
- dg := uint32(dpix[i+1])
- db := uint32(dpix[i+2])
- da := uint32(dpix[i+3])
+ dr := &dpix[i+0]
+ dg := &dpix[i+1]
+ db := &dpix[i+2]
+ da := &dpix[i+3]
// The 0x101 is here for the same reason as in drawRGBA.
a := (m - sa) * 0x101
- dpix[i+0] = uint8((dr*a/m + sr) >> 8)
- dpix[i+1] = uint8((dg*a/m + sg) >> 8)
- dpix[i+2] = uint8((db*a/m + sb) >> 8)
- dpix[i+3] = uint8((da*a/m + sa) >> 8)
+ *dr = uint8((uint32(*dr)*a/m + sr) >> 8)
+ *dg = uint8((uint32(*dg)*a/m + sg) >> 8)
+ *db = uint8((uint32(*db)*a/m + sb) >> 8)
+ *da = uint8((uint32(*da)*a/m + sa) >> 8)
}
d0 += ddelta
s0 += sdelta
@@ -471,18 +471,18 @@ func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask
}
ma |= ma << 8
- dr := uint32(dst.Pix[i+0])
- dg := uint32(dst.Pix[i+1])
- db := uint32(dst.Pix[i+2])
- da := uint32(dst.Pix[i+3])
+ dr := &dst.Pix[i+0]
+ dg := &dst.Pix[i+1]
+ db := &dst.Pix[i+2]
+ da := &dst.Pix[i+3]
// The 0x101 is here for the same reason as in drawRGBA.
a := (m - (sa * ma / m)) * 0x101
- dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
- dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
- dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
- dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
+ *dr = uint8((uint32(*dr)*a + sr*ma) / m >> 8)
+ *dg = uint8((uint32(*dg)*a + sg*ma) / m >> 8)
+ *db = uint8((uint32(*db)*a + sb*ma) / m >> 8)
+ *da = uint8((uint32(*da)*a + sa*ma) / m >> 8)
}
i0 += dst.Stride
i1 += dst.Stride
diff --git a/libgo/go/image/gif/writer.go b/libgo/go/image/gif/writer.go
index dd31790..1918196 100644
--- a/libgo/go/image/gif/writer.go
+++ b/libgo/go/image/gif/writer.go
@@ -83,7 +83,7 @@ func (b blockWriter) Write(data []byte) (int, error) {
total += n
b.e.buf[0] = uint8(n)
- n, b.e.err = b.e.w.Write(b.e.buf[:n+1])
+ _, b.e.err = b.e.w.Write(b.e.buf[:n+1])
if b.e.err != nil {
return 0, b.e.err
}
diff --git a/libgo/go/image/gif/writer_test.go b/libgo/go/image/gif/writer_test.go
index db61a5c..775ccea 100644
--- a/libgo/go/image/gif/writer_test.go
+++ b/libgo/go/image/gif/writer_test.go
@@ -328,11 +328,11 @@ func TestEncodeAllFramesOutOfBounds(t *testing.T) {
func TestEncodeNonZeroMinPoint(t *testing.T) {
points := []image.Point{
- image.Point{-8, -9},
- image.Point{-4, -4},
- image.Point{-3, +3},
- image.Point{+0, +0},
- image.Point{+2, +2},
+ {-8, -9},
+ {-4, -4},
+ {-3, +3},
+ {+0, +0},
+ {+2, +2},
}
for _, p := range points {
src := image.NewPaletted(image.Rectangle{Min: p, Max: p.Add(image.Point{6, 6})}, palette.Plan9)
diff --git a/libgo/go/image/image.go b/libgo/go/image/image.go
index 20b64d7..bebb9f7 100644
--- a/libgo/go/image/image.go
+++ b/libgo/go/image/image.go
@@ -148,7 +148,7 @@ func (p *RGBA) Opaque() bool {
return true
}
-// NewRGBA returns a new RGBA with the given bounds.
+// NewRGBA returns a new RGBA image with the given bounds.
func NewRGBA(r Rectangle) *RGBA {
w, h := r.Dx(), r.Dy()
buf := make([]uint8, 4*w*h)
@@ -260,7 +260,7 @@ func (p *RGBA64) Opaque() bool {
return true
}
-// NewRGBA64 returns a new RGBA64 with the given bounds.
+// NewRGBA64 returns a new RGBA64 image with the given bounds.
func NewRGBA64(r Rectangle) *RGBA64 {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 8*w*h)
@@ -359,7 +359,7 @@ func (p *NRGBA) Opaque() bool {
return true
}
-// NewNRGBA returns a new NRGBA with the given bounds.
+// NewNRGBA returns a new NRGBA image with the given bounds.
func NewNRGBA(r Rectangle) *NRGBA {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 4*w*h)
@@ -471,7 +471,7 @@ func (p *NRGBA64) Opaque() bool {
return true
}
-// NewNRGBA64 returns a new NRGBA64 with the given bounds.
+// NewNRGBA64 returns a new NRGBA64 image with the given bounds.
func NewNRGBA64(r Rectangle) *NRGBA64 {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 8*w*h)
@@ -563,7 +563,7 @@ func (p *Alpha) Opaque() bool {
return true
}
-// NewAlpha returns a new Alpha with the given bounds.
+// NewAlpha returns a new Alpha image with the given bounds.
func NewAlpha(r Rectangle) *Alpha {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 1*w*h)
@@ -658,7 +658,7 @@ func (p *Alpha16) Opaque() bool {
return true
}
-// NewAlpha16 returns a new Alpha16 with the given bounds.
+// NewAlpha16 returns a new Alpha16 image with the given bounds.
func NewAlpha16(r Rectangle) *Alpha16 {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 2*w*h)
@@ -737,7 +737,7 @@ func (p *Gray) Opaque() bool {
return true
}
-// NewGray returns a new Gray with the given bounds.
+// NewGray returns a new Gray image with the given bounds.
func NewGray(r Rectangle) *Gray {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 1*w*h)
@@ -819,7 +819,7 @@ func (p *Gray16) Opaque() bool {
return true
}
-// NewGray16 returns a new Gray16 with the given bounds.
+// NewGray16 returns a new Gray16 image with the given bounds.
func NewGray16(r Rectangle) *Gray16 {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 2*w*h)
@@ -905,7 +905,7 @@ func (p *CMYK) Opaque() bool {
return true
}
-// NewCMYK returns a new CMYK with the given bounds.
+// NewCMYK returns a new CMYK image with the given bounds.
func NewCMYK(r Rectangle) *CMYK {
w, h := r.Dx(), r.Dy()
buf := make([]uint8, 4*w*h)
@@ -1014,7 +1014,8 @@ func (p *Paletted) Opaque() bool {
return true
}
-// NewPaletted returns a new Paletted with the given width, height and palette.
+// NewPaletted returns a new Paletted image with the given width, height and
+// palette.
func NewPaletted(r Rectangle, p color.Palette) *Paletted {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 1*w*h)
diff --git a/libgo/go/image/png/reader.go b/libgo/go/image/png/reader.go
index bbd6f75..9e6f985 100644
--- a/libgo/go/image/png/reader.go
+++ b/libgo/go/image/png/reader.go
@@ -154,8 +154,8 @@ func (d *decoder) parseIHDR(length uint32) error {
d.interlace = int(d.tmp[12])
w := int32(binary.BigEndian.Uint32(d.tmp[0:4]))
h := int32(binary.BigEndian.Uint32(d.tmp[4:8]))
- if w < 0 || h < 0 {
- return FormatError("negative dimension")
+ if w <= 0 || h <= 0 {
+ return FormatError("non-positive dimension")
}
nPixels := int64(w) * int64(h)
if nPixels != int64(int(nPixels)) {
@@ -727,6 +727,9 @@ func (d *decoder) parseChunk() error {
d.stage = dsSeenIEND
return d.parseIEND(length)
}
+ if length > 0x7fffffff {
+ return FormatError(fmt.Sprintf("Bad chunk length: %d", length))
+ }
// Ignore this chunk (of a known length).
var ignored [4096]byte
for length > 0 {
diff --git a/libgo/go/image/png/reader_test.go b/libgo/go/image/png/reader_test.go
index f89e7ef..f058f6b 100644
--- a/libgo/go/image/png/reader_test.go
+++ b/libgo/go/image/png/reader_test.go
@@ -408,6 +408,18 @@ func TestMultipletRNSChunks(t *testing.T) {
}
}
+func TestUnknownChunkLengthUnderflow(t *testing.T) {
+ data := []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0xf4, 0x7c, 0x55, 0x04, 0x1a,
+ 0xd3, 0x11, 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e, 0x00, 0x00,
+ 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0x7c, 0x55, 0x04, 0x1a,
+ 0xd3}
+ _, err := Decode(bytes.NewReader(data))
+ if err == nil {
+ t.Errorf("Didn't fail reading an unknown chunk with length 0xffffffff")
+ }
+}
+
func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
b.StopTimer()
data, err := ioutil.ReadFile(filename)
diff --git a/libgo/go/image/ycbcr.go b/libgo/go/image/ycbcr.go
index 93c354b..71c0518 100644
--- a/libgo/go/image/ycbcr.go
+++ b/libgo/go/image/ycbcr.go
@@ -138,9 +138,8 @@ func (p *YCbCr) Opaque() bool {
return true
}
-// NewYCbCr returns a new YCbCr with the given bounds and subsample ratio.
-func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
- w, h, cw, ch := r.Dx(), r.Dy(), 0, 0
+func yCbCrSize(r Rectangle, subsampleRatio YCbCrSubsampleRatio) (w, h, cw, ch int) {
+ w, h = r.Dx(), r.Dy()
switch subsampleRatio {
case YCbCrSubsampleRatio422:
cw = (r.Max.X+1)/2 - r.Min.X/2
@@ -162,6 +161,13 @@ func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
cw = w
ch = h
}
+ return
+}
+
+// NewYCbCr returns a new YCbCr image with the given bounds and subsample
+// ratio.
+func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
+ w, h, cw, ch := yCbCrSize(r, subsampleRatio)
i0 := w*h + 0*cw*ch
i1 := w*h + 1*cw*ch
i2 := w*h + 2*cw*ch
@@ -176,3 +182,117 @@ func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
Rect: r,
}
}
+
+// NYCbCrA is an in-memory image of non-alpha-premultiplied Y'CbCr-with-alpha
+// colors. A and AStride are analogous to the Y and YStride fields of the
+// embedded YCbCr.
+type NYCbCrA struct {
+ YCbCr
+ A []uint8
+ AStride int
+}
+
+func (p *NYCbCrA) ColorModel() color.Model {
+ return color.NYCbCrAModel
+}
+
+func (p *NYCbCrA) At(x, y int) color.Color {
+ return p.NYCbCrAAt(x, y)
+}
+
+func (p *NYCbCrA) NYCbCrAAt(x, y int) color.NYCbCrA {
+ if !(Point{X: x, Y: y}.In(p.Rect)) {
+ return color.NYCbCrA{}
+ }
+ yi := p.YOffset(x, y)
+ ci := p.COffset(x, y)
+ ai := p.AOffset(x, y)
+ return color.NYCbCrA{
+ color.YCbCr{
+ Y: p.Y[yi],
+ Cb: p.Cb[ci],
+ Cr: p.Cr[ci],
+ },
+ p.A[ai],
+ }
+}
+
+// AOffset returns the index of the first element of A that corresponds to the
+// pixel at (x, y).
+func (p *NYCbCrA) AOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.AStride + (x - p.Rect.Min.X)
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *NYCbCrA) SubImage(r Rectangle) Image {
+ r = r.Intersect(p.Rect)
+ // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+ // either r1 or r2 if the intersection is empty. Without explicitly checking for
+ // this, the Pix[i:] expression below can panic.
+ if r.Empty() {
+ return &NYCbCrA{
+ YCbCr: YCbCr{
+ SubsampleRatio: p.SubsampleRatio,
+ },
+ }
+ }
+ yi := p.YOffset(r.Min.X, r.Min.Y)
+ ci := p.COffset(r.Min.X, r.Min.Y)
+ ai := p.AOffset(r.Min.X, r.Min.Y)
+ return &NYCbCrA{
+ YCbCr: YCbCr{
+ Y: p.Y[yi:],
+ Cb: p.Cb[ci:],
+ Cr: p.Cr[ci:],
+ SubsampleRatio: p.SubsampleRatio,
+ YStride: p.YStride,
+ CStride: p.CStride,
+ Rect: r,
+ },
+ A: p.A[ai:],
+ AStride: p.AStride,
+ }
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *NYCbCrA) Opaque() bool {
+ if p.Rect.Empty() {
+ return true
+ }
+ i0, i1 := 0, p.Rect.Dx()
+ for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+ for _, a := range p.A[i0:i1] {
+ if a != 0xff {
+ return false
+ }
+ }
+ i0 += p.AStride
+ i1 += p.AStride
+ }
+ return true
+}
+
+// NewNYCbCrA returns a new NYCbCrA image with the given bounds and subsample
+// ratio.
+func NewNYCbCrA(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *NYCbCrA {
+ w, h, cw, ch := yCbCrSize(r, subsampleRatio)
+ i0 := 1*w*h + 0*cw*ch
+ i1 := 1*w*h + 1*cw*ch
+ i2 := 1*w*h + 2*cw*ch
+ i3 := 2*w*h + 2*cw*ch
+ b := make([]byte, i3)
+ return &NYCbCrA{
+ YCbCr: YCbCr{
+ Y: b[:i0:i0],
+ Cb: b[i0:i1:i1],
+ Cr: b[i1:i2:i2],
+ SubsampleRatio: subsampleRatio,
+ YStride: w,
+ CStride: cw,
+ Rect: r,
+ },
+ A: b[i2:],
+ AStride: w,
+ }
+}