diff options
author | Ian Lance Taylor <iant@google.com> | 2016-02-03 21:58:02 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-02-03 21:58:02 +0000 |
commit | f98dd1a338867a408f7c72d73fbad7fe7fc93e3a (patch) | |
tree | 2f8da9862a9c1fe0df138917f997b03439c02773 /libgo/go/image | |
parent | b081ed4efc144da0c45a6484aebfd10e0eb9fda3 (diff) | |
download | gcc-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.go | 62 | ||||
-rw-r--r-- | libgo/go/image/color/ycbcr_test.go | 26 | ||||
-rw-r--r-- | libgo/go/image/draw/draw.go | 50 | ||||
-rw-r--r-- | libgo/go/image/gif/writer.go | 2 | ||||
-rw-r--r-- | libgo/go/image/gif/writer_test.go | 10 | ||||
-rw-r--r-- | libgo/go/image/image.go | 21 | ||||
-rw-r--r-- | libgo/go/image/png/reader.go | 7 | ||||
-rw-r--r-- | libgo/go/image/png/reader_test.go | 12 | ||||
-rw-r--r-- | libgo/go/image/ycbcr.go | 126 |
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, + } +} |