]> Cypherpunks repositories - gostls13.git/commitdiff
Make image.Color.RGBA return 16 bit color instead of 32 bit color.
authorNigel Tao <nigeltao@golang.org>
Fri, 28 May 2010 19:59:21 +0000 (12:59 -0700)
committerNigel Tao <nigeltao@golang.org>
Fri, 28 May 2010 19:59:21 +0000 (12:59 -0700)
R=rsc
CC=golang-dev
https://golang.org/cl/1388041

src/pkg/exp/draw/color.go
src/pkg/exp/draw/draw.go
src/pkg/exp/draw/draw_test.go
src/pkg/exp/nacl/av/image.go
src/pkg/image/color.go
src/pkg/image/image.go
src/pkg/image/png/reader_test.go
src/pkg/image/png/writer.go

index f0e7597092b2307ef253e7976b66ffb1947d36f0..3fe7b4abc7ca996fc3ac75c88df038706bb58d04 100644 (file)
@@ -51,13 +51,9 @@ func (c Color) RGBA() (r, g, b, a uint32) {
        x := uint32(c)
        r, g, b, a = x>>24, (x>>16)&0xFF, (x>>8)&0xFF, x&0xFF
        r |= r << 8
-       r |= r << 16
        g |= g << 8
-       g |= g << 16
        b |= b << 8
-       b |= b << 16
        a |= a << 8
-       a |= a << 16
        return
 }
 
@@ -103,7 +99,7 @@ func toColor(color image.Color) image.Color {
                return c
        }
        r, g, b, a := color.RGBA()
-       return Color(r>>24<<24 | g>>24<<16 | b>>24<<8 | a>>24)
+       return Color(r>>8<<24 | g>>8<<16 | b>>8<<8 | a>>8)
 }
 
 func (c Color) ColorModel() image.ColorModel { return image.ColorModelFunc(toColor) }
index 41eaef4d4f3a24e09d1a8c4752b569a32260ebe8..d9d3d13eb09de8c522ee9f53ac5e909e542d5557 100644 (file)
@@ -105,13 +105,10 @@ func DrawMask(dst Image, r Rectangle, src image.Image, sp Point, mask image.Imag
                sx := sp.X + x0 - r.Min.X
                mx := mp.X + x0 - r.Min.X
                for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
-                       // A nil mask is equivalent to a fully opaque, infinitely large mask.
-                       // We work in 16-bit color, so that multiplying two values does not overflow a uint32.
                        const M = 1<<16 - 1
                        ma := uint32(M)
                        if mask != nil {
                                _, _, _, ma = mask.At(mx, my).RGBA()
-                               ma >>= 16
                        }
                        switch {
                        case ma == 0:
@@ -124,19 +121,11 @@ func DrawMask(dst Image, r Rectangle, src image.Image, sp Point, mask image.Imag
                                dst.Set(x, y, src.At(sx, sy))
                        default:
                                sr, sg, sb, sa := src.At(sx, sy).RGBA()
-                               sr >>= 16
-                               sg >>= 16
-                               sb >>= 16
-                               sa >>= 16
                                if out == nil {
                                        out = new(image.RGBA64Color)
                                }
                                if op == Over {
                                        dr, dg, db, da := dst.At(x, y).RGBA()
-                                       dr >>= 16
-                                       dg >>= 16
-                                       db >>= 16
-                                       da >>= 16
                                        a := M - (sa * ma / M)
                                        out.R = uint16((dr*a + sr*ma) / M)
                                        out.G = uint16((dg*a + sg*ma) / M)
@@ -158,10 +147,6 @@ func drawGlyphOver(dst *image.RGBA, r Rectangle, src image.ColorImage, mask *ima
        x0, x1 := r.Min.X, r.Max.X
        y0, y1 := r.Min.Y, r.Max.Y
        cr, cg, cb, ca := src.RGBA()
-       cr >>= 16
-       cg >>= 16
-       cb >>= 16
-       ca >>= 16
        for y, my := y0, mp.Y; y != y1; y, my = y+1, my+1 {
                p := dst.Pixel[y]
                for x, mx := x0, mp.X; x != x1; x, mx = x+1, mx+1 {
@@ -192,7 +177,7 @@ func drawFill(dst *image.RGBA, r Rectangle, src image.ColorImage) {
                return
        }
        cr, cg, cb, ca := src.RGBA()
-       color := image.RGBAColor{uint8(cr >> 24), uint8(cg >> 24), uint8(cb >> 24), uint8(ca >> 24)}
+       color := image.RGBAColor{uint8(cr >> 8), uint8(cg >> 8), uint8(cb >> 8), uint8(ca >> 8)}
        // The built-in copy function is faster than a straightforward for loop to fill the destination with
        // the color, but copy requires a slice source. We therefore use a for loop to fill the first row, and
        // then use the first row as the slice source for the remaining rows.
@@ -238,13 +223,8 @@ func drawRGBA(dst *image.RGBA, r Rectangle, src image.Image, sp Point, mask imag
                        ma := uint32(M)
                        if mask != nil {
                                _, _, _, ma = mask.At(mx, my).RGBA()
-                               ma >>= 16
                        }
                        sr, sg, sb, sa := src.At(sx, sy).RGBA()
-                       sr >>= 16
-                       sg >>= 16
-                       sb >>= 16
-                       sa >>= 16
                        var dr, dg, db, da uint32
                        if op == Over {
                                rgba := p[x]
index 675c4eaec5fb8d6230bd777bf669da5ca0932fbc..5303f2b3d85f056421bb9282d12945e35f746c1f 100644 (file)
@@ -106,20 +106,11 @@ func makeGolden(dst image.Image, t drawTest) image.Image {
                        var dr, dg, db, da uint32
                        if t.op == Over {
                                dr, dg, db, da = dst.At(x, y).RGBA()
-                               dr >>= 16
-                               dg >>= 16
-                               db >>= 16
-                               da >>= 16
                        }
                        sr, sg, sb, sa := t.src.At(sx, sy).RGBA()
-                       sr >>= 16
-                       sg >>= 16
-                       sb >>= 16
-                       sa >>= 16
                        ma := uint32(M)
                        if t.mask != nil {
                                _, _, _, ma = t.mask.At(mx, my).RGBA()
-                               ma >>= 16
                        }
                        a := M - (sa * ma / M)
                        golden.Set(x, y, image.RGBA64Color{
index f69f94a657e83f9a51b838cfac82e08588db7458..8de5311365cf09a7fe37fd7aa63da9cf29554b9a 100644 (file)
@@ -61,16 +61,12 @@ func (p Color) RGBA() (r, g, b, a uint32) {
        x := uint32(p)
        a = x >> 24
        a |= a << 8
-       a |= a << 16
        r = (x >> 16) & 0xFF
        r |= r << 8
-       r |= r << 16
        g = (x >> 8) & 0xFF
        g |= g << 8
-       g |= g << 16
        b = x & 0xFF
        b |= b << 8
-       b |= b << 16
        return
 }
 
index 31ba59280f4a98da8122a2ecfabb90585430bd3c..c17ffc38946a3efd728e510bcd15cbff4910cd5b 100644 (file)
@@ -4,14 +4,15 @@
 
 package image
 
-// TODO(nigeltao): Think about how floating-point color models work.
-
-// All Colors can convert themselves, with a possible loss of precision, to 128-bit alpha-premultiplied RGBA.
+// All Colors can convert themselves, with a possible loss of precision,
+// to 64-bit alpha-premultiplied RGBA. Each channel value ranges within
+// [0, 0xFFFF].
 type Color interface {
        RGBA() (r, g, b, a uint32)
 }
 
-// An RGBAColor represents a traditional 32-bit alpha-premultiplied color, having 8 bits for each of red, green, blue and alpha.
+// An RGBAColor represents a traditional 32-bit alpha-premultiplied color,
+// having 8 bits for each of red, green, blue and alpha.
 type RGBAColor struct {
        R, G, B, A uint8
 }
@@ -19,34 +20,23 @@ type RGBAColor struct {
 func (c RGBAColor) RGBA() (r, g, b, a uint32) {
        r = uint32(c.R)
        r |= r << 8
-       r |= r << 16
        g = uint32(c.G)
        g |= g << 8
-       g |= g << 16
        b = uint32(c.B)
        b |= b << 8
-       b |= b << 16
        a = uint32(c.A)
        a |= a << 8
-       a |= a << 16
        return
 }
 
-// An RGBA64Color represents a 64-bit alpha-premultiplied color, having 16 bits for each of red, green, blue and alpha.
+// An RGBA64Color represents a 64-bit alpha-premultiplied color,
+// having 16 bits for each of red, green, blue and alpha.
 type RGBA64Color struct {
        R, G, B, A uint16
 }
 
 func (c RGBA64Color) RGBA() (r, g, b, a uint32) {
-       r = uint32(c.R)
-       r |= r << 16
-       g = uint32(c.G)
-       g |= g << 16
-       b = uint32(c.B)
-       b |= b << 16
-       a = uint32(c.A)
-       a |= a << 16
-       return
+       return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
 }
 
 // An NRGBAColor represents a non-alpha-premultiplied 32-bit color.
@@ -59,24 +49,21 @@ func (c NRGBAColor) RGBA() (r, g, b, a uint32) {
        r |= r << 8
        r *= uint32(c.A)
        r /= 0xff
-       r |= r << 16
        g = uint32(c.G)
        g |= g << 8
        g *= uint32(c.A)
        g /= 0xff
-       g |= g << 16
        b = uint32(c.B)
        b |= b << 8
        b *= uint32(c.A)
        b /= 0xff
-       b |= b << 16
        a = uint32(c.A)
        a |= a << 8
-       a |= a << 16
        return
 }
 
-// An NRGBA64Color represents a non-alpha-premultiplied 64-bit color, having 16 bits for each of red, green, blue and alpha.
+// An NRGBA64Color represents a non-alpha-premultiplied 64-bit color,
+// having 16 bits for each of red, green, blue and alpha.
 type NRGBA64Color struct {
        R, G, B, A uint16
 }
@@ -85,18 +72,13 @@ func (c NRGBA64Color) RGBA() (r, g, b, a uint32) {
        r = uint32(c.R)
        r *= uint32(c.A)
        r /= 0xffff
-       r |= r << 16
        g = uint32(c.G)
        g *= uint32(c.A)
        g /= 0xffff
-       g |= g << 16
        b = uint32(c.B)
        b *= uint32(c.A)
        b /= 0xffff
-       b |= b << 16
        a = uint32(c.A)
-       a |= a << 8
-       a |= a << 16
        return
 }
 
@@ -108,12 +90,11 @@ type AlphaColor struct {
 func (c AlphaColor) RGBA() (r, g, b, a uint32) {
        a = uint32(c.A)
        a |= a << 8
-       a |= a << 16
        return a, a, a, a
 }
 
-// A ColorModel can convert foreign Colors, with a possible loss of precision, to a Color
-// from its own color model.
+// A ColorModel can convert foreign Colors, with a possible loss of precision,
+// to a Color from its own color model.
 type ColorModel interface {
        Convert(c Color) Color
 }
@@ -129,36 +110,32 @@ func (f ColorModelFunc) Convert(c Color) Color {
 }
 
 func toRGBAColor(c Color) Color {
-       if _, ok := c.(RGBAColor); ok { // no-op conversion
+       if _, ok := c.(RGBAColor); ok {
                return c
        }
        r, g, b, a := c.RGBA()
-       return RGBAColor{uint8(r >> 24), uint8(g >> 24), uint8(b >> 24), uint8(a >> 24)}
+       return RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
 }
 
 func toRGBA64Color(c Color) Color {
-       if _, ok := c.(RGBA64Color); ok { // no-op conversion
+       if _, ok := c.(RGBA64Color); ok {
                return c
        }
        r, g, b, a := c.RGBA()
-       return RGBA64Color{uint16(r >> 16), uint16(g >> 16), uint16(b >> 16), uint16(a >> 16)}
+       return RGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
 }
 
 func toNRGBAColor(c Color) Color {
-       if _, ok := c.(NRGBAColor); ok { // no-op conversion
+       if _, ok := c.(NRGBAColor); ok {
                return c
        }
        r, g, b, a := c.RGBA()
-       a >>= 16
        if a == 0xffff {
-               return NRGBAColor{uint8(r >> 24), uint8(g >> 24), uint8(b >> 24), 0xff}
+               return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
        }
        if a == 0 {
                return NRGBAColor{0, 0, 0, 0}
        }
-       r >>= 16
-       g >>= 16
-       b >>= 16
        // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
        r = (r * 0xffff) / a
        g = (g * 0xffff) / a
@@ -167,14 +144,10 @@ func toNRGBAColor(c Color) Color {
 }
 
 func toNRGBA64Color(c Color) Color {
-       if _, ok := c.(NRGBA64Color); ok { // no-op conversion
+       if _, ok := c.(NRGBA64Color); ok {
                return c
        }
        r, g, b, a := c.RGBA()
-       a >>= 16
-       r >>= 16
-       g >>= 16
-       b >>= 16
        if a == 0xffff {
                return NRGBA64Color{uint16(r), uint16(g), uint16(b), 0xffff}
        }
@@ -189,11 +162,11 @@ func toNRGBA64Color(c Color) Color {
 }
 
 func toAlphaColor(c Color) Color {
-       if _, ok := c.(AlphaColor); ok { // no-op conversion
+       if _, ok := c.(AlphaColor); ok {
                return c
        }
        _, _, _, a := c.RGBA()
-       return AlphaColor{uint8(a >> 24)}
+       return AlphaColor{uint8(a >> 8)}
 }
 
 // The ColorModel associated with RGBAColor.
index f4ac823e1bee5b021c720e38fa9924e13796ad4a..3ac7d4eb2a8fe1a0464342ecfa0d594ec5e4d680 100644 (file)
@@ -185,21 +185,18 @@ func (p PalettedColorModel) Convert(c Color) Color {
        if len(p) == 0 {
                return nil
        }
-       // TODO(nigeltao): Revisit the "pick the palette color which minimizes sum-squared-difference"
-       // algorithm when the premultiplied vs unpremultiplied issue is resolved.
-       // Currently, we only compare the R, G and B values, and ignore A.
        cr, cg, cb, _ := c.RGBA()
-       // Shift by 17 bits to avoid potential uint32 overflow in sum-squared-difference.
-       cr >>= 17
-       cg >>= 17
-       cb >>= 17
+       // Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
+       cr >>= 1
+       cg >>= 1
+       cb >>= 1
        result := Color(nil)
        bestSSD := uint32(1<<32 - 1)
        for _, v := range p {
                vr, vg, vb, _ := v.RGBA()
-               vr >>= 17
-               vg >>= 17
-               vb >>= 17
+               vr >>= 1
+               vg >>= 1
+               vb >>= 1
                dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
                ssd := (dr * dr) + (dg * dg) + (db * db)
                if ssd < bestSSD {
index 68aab78322c6600fc9e86a4ee1425a4b20b9fc82..1dc45992e930cce6b92828a874c630b79dda4b30 100644 (file)
@@ -76,9 +76,9 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
                io.WriteString(w, "PLTE {\n")
                for i := 0; i < len(cpm); i++ {
                        r, g, b, _ := cpm[i].RGBA()
-                       r >>= 24
-                       g >>= 24
-                       b >>= 24
+                       r >>= 8
+                       g >>= 8
+                       b >>= 8
                        fmt.Fprintf(w, "    (%3d,%3d,%3d)     # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
                }
                io.WriteString(w, "}\n")
index 06b6dcdc338e8a2e73f89b1297b47f4e08040247..e186ca819b9aaff6e0c64e9ca77d497dd5d65c53 100644 (file)
@@ -37,7 +37,7 @@ func opaque(m image.Image) bool {
        for y := 0; y < m.Height(); y++ {
                for x := 0; x < m.Width(); x++ {
                        _, _, _, a := m.At(x, y).RGBA()
-                       if a != 0xffffffff {
+                       if a != 0xffff {
                                return false
                        }
                }
@@ -101,13 +101,13 @@ func (e *encoder) writePLTE(p image.PalettedColorModel) {
        }
        for i := 0; i < len(p); i++ {
                r, g, b, a := p[i].RGBA()
-               if a != 0xffffffff {
+               if a != 0xffff {
                        e.err = UnsupportedError("non-opaque palette color")
                        return
                }
-               e.tmp[3*i+0] = uint8(r >> 24)
-               e.tmp[3*i+1] = uint8(g >> 24)
-               e.tmp[3*i+2] = uint8(b >> 24)
+               e.tmp[3*i+0] = uint8(r >> 8)
+               e.tmp[3*i+1] = uint8(g >> 8)
+               e.tmp[3*i+2] = uint8(b >> 8)
        }
        e.writeChunk(e.tmp[0:3*len(p)], "PLTE")
 }
@@ -261,9 +261,9 @@ func writeImage(w io.Writer, m image.Image, ct uint8) os.Error {
                        for x := 0; x < m.Width(); x++ {
                                // We have previously verified that the alpha value is fully opaque.
                                r, g, b, _ := m.At(x, y).RGBA()
-                               cr[0][3*x+1] = uint8(r >> 24)
-                               cr[0][3*x+2] = uint8(g >> 24)
-                               cr[0][3*x+3] = uint8(b >> 24)
+                               cr[0][3*x+1] = uint8(r >> 8)
+                               cr[0][3*x+2] = uint8(g >> 8)
+                               cr[0][3*x+3] = uint8(b >> 8)
                        }
                case ctPaletted:
                        for x := 0; x < m.Width(); x++ {