Commit 8bd50895 authored by Nigel Tao's avatar Nigel Tao

image: change Pix from []FooColor to []uint8.

Some benchmark numbers below. The image/draw fast-paths show dramatic
improvement, the generic slow-paths show a smaller slow-down.

BEFORE
png.BenchmarkEncodePaletted      200       8203800 ns/op      37.45 MB/s
png.BenchmarkEncodeRGBOpaque         100      26940440 ns/op      45.61 MB/s
png.BenchmarkEncodeRGBA       20      73821000 ns/op      16.65 MB/s
jpeg.BenchmarkEncodeRGBOpaque         50      35598640 ns/op      34.52 MB/s
draw.BenchmarkFillOver	     500	   4024226 ns/op
draw.BenchmarkFillSrc	   10000	    152736 ns/op
draw.BenchmarkCopyOver	     500	   3452824 ns/op
draw.BenchmarkCopySrc	   50000	     73218 ns/op
draw.BenchmarkNRGBAOver	     500	   3941234 ns/op
draw.BenchmarkNRGBASrc	    1000	   2484400 ns/op
draw.BenchmarkYCbCr	    1000	   2609005 ns/op
draw.BenchmarkGlyphOver	    2000	   1169575 ns/op
draw.BenchmarkRGBA	     200	   9031390 ns/op
draw.BenchmarkGenericOver	      50	  34636620 ns/op
draw.BenchmarkGenericMaskOver	     100	  16561150 ns/op
draw.BenchmarkGenericSrc	     100	  13873760 ns/op
draw.BenchmarkGenericMaskSrc	     100	  25198860 ns/op

AFTER
png.BenchmarkEncodePaletted      200       8206600 ns/op      37.43 MB/s
png.BenchmarkEncodeRGBOpaque         100      26129530 ns/op      47.03 MB/s
png.BenchmarkEncodeRGBA       20      75776750 ns/op      16.22 MB/s
jpeg.BenchmarkEncodeRGBOpaque         50      37192940 ns/op      33.04 MB/s
draw.BenchmarkFillOver	     500	   3008134 ns/op
draw.BenchmarkFillSrc	   10000	    154214 ns/op
draw.BenchmarkCopyOver	    1000	   2169988 ns/op
draw.BenchmarkCopySrc	   50000	     73095 ns/op
draw.BenchmarkNRGBAOver	    1000	   2491079 ns/op
draw.BenchmarkNRGBASrc	    2000	   1361244 ns/op
draw.BenchmarkYCbCr	    1000	   2554269 ns/op
draw.BenchmarkGlyphOver	    2000	   1042225 ns/op
draw.BenchmarkRGBA	     100	  10233340 ns/op
draw.BenchmarkGenericOver	      50	  38421560 ns/op
draw.BenchmarkGenericMaskOver	     100	  17521190 ns/op
draw.BenchmarkGenericSrc	     100	  16351200 ns/op
draw.BenchmarkGenericMaskSrc	     100	  26538190 ns/op

R=r
CC=golang-dev
https://golang.org/cl/4675076
parent 6ec6f1ef
......@@ -92,18 +92,19 @@ func (c *conn) writeSocket() {
return
}
p := c.img.Pix[(y-b.Min.Y)*c.img.Stride:]
for x, dx := 0, b.Dx(); x < dx; {
for x, dx := 0, 4*b.Dx(); x < dx; {
nx := dx - x
if nx > len(c.flushBuf1)/4 {
nx = len(c.flushBuf1) / 4
if nx > len(c.flushBuf1) {
nx = len(c.flushBuf1) &^ 3
}
for i, rgba := range p[x : x+nx] {
c.flushBuf1[4*i+0] = rgba.B
c.flushBuf1[4*i+1] = rgba.G
c.flushBuf1[4*i+2] = rgba.R
for i := 0; i < nx; i += 4 {
// X11's order is BGRX, not RGBA.
c.flushBuf1[i+0] = p[x+i+2]
c.flushBuf1[i+1] = p[x+i+1]
c.flushBuf1[i+2] = p[x+i+0]
}
x += nx
if _, err := c.w.Write(c.flushBuf1[:4*nx]); err != nil {
if _, err := c.w.Write(c.flushBuf1[:nx]); err != nil {
if err != os.EOF {
log.Println("x11:", err.String())
}
......
......@@ -58,10 +58,13 @@ func decodeRGBA(r io.Reader, c image.Config) (image.Image, os.Error) {
if err != nil {
return nil, err
}
p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width]
for x := range p {
p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
// BMP images are stored in BGR order rather than RGB order.
p[x] = image.RGBAColor{b[3*x+2], b[3*x+1], b[3*x+0], 0xFF}
p[i+0] = b[j+2]
p[i+1] = b[j+1]
p[i+2] = b[j+0]
p[i+3] = 0xFF
}
}
return rgba, nil
......
......@@ -4,14 +4,14 @@
package image
// All Colors can convert themselves, with a possible loss of precision,
// to 64-bit alpha-premultiplied RGBA. Each channel value ranges within
// [0, 0xFFFF].
// Color can convert itself to alpha-premultiplied RGBA, with a possible loss
// of precision. Each value ranges within [0, 0xFFFF], but is represented by a
// uint32 so that multiplying by a blend factor up to 0xFFFF will not overflow.
type Color interface {
RGBA() (r, g, b, a uint32)
}
// An RGBAColor represents a traditional 32-bit alpha-premultiplied color,
// 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
......@@ -29,7 +29,7 @@ func (c RGBAColor) RGBA() (r, g, b, a uint32) {
return
}
// An RGBA64Color represents a 64-bit alpha-premultiplied color,
// 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
......@@ -39,7 +39,7 @@ func (c RGBA64Color) RGBA() (r, g, b, a uint32) {
return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
}
// An NRGBAColor represents a non-alpha-premultiplied 32-bit color.
// NRGBAColor represents a non-alpha-premultiplied 32-bit color.
type NRGBAColor struct {
R, G, B, A uint8
}
......@@ -62,7 +62,7 @@ func (c NRGBAColor) RGBA() (r, g, b, a uint32) {
return
}
// An NRGBA64Color represents a non-alpha-premultiplied 64-bit color,
// 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
......@@ -82,7 +82,7 @@ func (c NRGBA64Color) RGBA() (r, g, b, a uint32) {
return
}
// An AlphaColor represents an 8-bit alpha.
// AlphaColor represents an 8-bit alpha.
type AlphaColor struct {
A uint8
}
......@@ -93,7 +93,7 @@ func (c AlphaColor) RGBA() (r, g, b, a uint32) {
return a, a, a, a
}
// An Alpha16Color represents a 16-bit alpha.
// Alpha16Color represents a 16-bit alpha.
type Alpha16Color struct {
A uint16
}
......@@ -103,7 +103,7 @@ func (c Alpha16Color) RGBA() (r, g, b, a uint32) {
return a, a, a, a
}
// A GrayColor represents an 8-bit grayscale color.
// GrayColor represents an 8-bit grayscale color.
type GrayColor struct {
Y uint8
}
......@@ -114,7 +114,7 @@ func (c GrayColor) RGBA() (r, g, b, a uint32) {
return y, y, y, 0xffff
}
// A Gray16Color represents a 16-bit grayscale color.
// Gray16Color represents a 16-bit grayscale color.
type Gray16Color struct {
Y uint16
}
......@@ -124,7 +124,7 @@ func (c Gray16Color) RGBA() (r, g, b, a uint32) {
return y, y, y, 0xffff
}
// A ColorModel can convert foreign Colors, with a possible loss of precision,
// 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
......
This diff is collapsed.
This diff is collapsed.
......@@ -319,16 +319,7 @@ func (d *decoder) processSOS(n int) os.Error {
// Perform the inverse DCT and store the MCU component to the image.
if d.nComp == nGrayComponent {
idct(d.tmp[:64], 8, &b)
// Convert from []uint8 to []image.GrayColor.
p := d.img1.Pix[8*(my*d.img1.Stride+mx):]
for y := 0; y < 8; y++ {
dst := p[y*d.img1.Stride:]
src := d.tmp[8*y:]
for x := 0; x < 8; x++ {
dst[x] = image.GrayColor{src[x]}
}
}
idct(d.img1.Pix[8*(my*d.img1.Stride+mx):], d.img1.Stride, &b)
} else {
switch i {
case 0:
......
......@@ -397,14 +397,14 @@ func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block)
if sj > ymax {
sj = ymax
}
offset := (sj-b.Min.Y)*m.Stride - b.Min.X
offset := (sj-b.Min.Y)*m.Stride - b.Min.X*4
for i := 0; i < 8; i++ {
sx := p.X + i
if sx > xmax {
sx = xmax
}
col := &m.Pix[offset+sx]
yy, cb, cr := ycbcr.RGBToYCbCr(col.R, col.G, col.B)
pix := m.Pix[offset+sx*4:]
yy, cb, cr := ycbcr.RGBToYCbCr(pix[0], pix[1], pix[2])
yBlock[8*j+i] = int(yy)
cbBlock[8*j+i] = int(cb)
crBlock[8*j+i] = int(cr)
......
......@@ -275,11 +275,6 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
bpp := 0 // Bytes per pixel.
// Used by fast paths for common image types
var paletted *image.Paletted
var rgba *image.RGBA
rgba, _ = m.(*image.RGBA)
switch cb {
case cbG8:
bpp = 1
......@@ -287,7 +282,6 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
bpp = 3
case cbP8:
bpp = 1
paletted = m.(*image.Paletted)
case cbTCA8:
bpp = 4
case cbTC16:
......@@ -323,12 +317,13 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
case cbTC8:
// We have previously verified that the alpha value is fully opaque.
cr0 := cr[0]
if rgba != nil {
offset := (y - b.Min.Y) * rgba.Stride
for _, color := range rgba.Pix[offset : offset+b.Dx()] {
cr0[i+0] = color.R
cr0[i+1] = color.G
cr0[i+2] = color.B
if rgba, _ := m.(*image.RGBA); rgba != nil {
j0 := (y - b.Min.Y) * rgba.Stride
j1 := j0 + b.Dx()*4
for j := j0; j < j1; j += 4 {
cr0[i+0] = rgba.Pix[j+0]
cr0[i+1] = rgba.Pix[j+1]
cr0[i+2] = rgba.Pix[j+2]
i += 3
}
} else {
......@@ -341,6 +336,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
}
}
case cbP8:
paletted := m.(*image.Paletted)
offset := (y - b.Min.Y) * paletted.Stride
copy(cr[0][1:], paletted.Pix[offset:offset+b.Dx()])
case cbTCA8:
......
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