diff options
author | Russ Cox <rsc@golang.org> | 2011-05-03 01:50:43 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2011-05-03 01:50:43 -0400 |
commit | 125e91a174644b6cfc003ae04b8e127b0951edba (patch) | |
tree | 0416ea1065be7b368543be32bd29dbf814159401 | |
parent | 3854d346f616cb2db2a58c37ba5dd0e4ad8ab993 (diff) | |
download | go-125e91a174644b6cfc003ae04b8e127b0951edba.tar.gz go-125e91a174644b6cfc003ae04b8e127b0951edba.zip |
[release-branch.r57] jpeg: speed up RGBA encoding ~%50
««« CL 4433088 / 099dd59d3976
jpeg: speed up RGBA encoding ~%50
Avoids image.At(), color.RGBA(), opposing 8 bit shifts,
and min function calls in a loop. Not as pretty as before,
but the pure version is still there to revert back to
later if/when the compiler gets better.
before (best of 5)
jpeg.BenchmarkEncodeRGBOpaque 50 64781360 ns/op 18.97 MB/s
after (best of 5)
jpeg.BenchmarkEncodeRGBOpaque 50 42044300 ns/op 29.23 MB/s
(benchmarked on an HP z600; 16 core Xeon E5520 @ 2.27Ghz)
R=r, r2, nigeltao
CC=golang-dev
https://golang.org/cl/4433088
»»»
TBR=adg
CC=golang-dev
https://golang.org/cl/4431086
-rw-r--r-- | src/pkg/image/jpeg/writer.go | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/src/pkg/image/jpeg/writer.go b/src/pkg/image/jpeg/writer.go index 505cce04fb..52b3dc4e2c 100644 --- a/src/pkg/image/jpeg/writer.go +++ b/src/pkg/image/jpeg/writer.go @@ -391,6 +391,31 @@ func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) { } } +// rgbaToYCbCr is a specialized version of toYCbCr for image.RGBA images. +func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block) { + b := m.Bounds() + xmax := b.Max.X - 1 + ymax := b.Max.Y - 1 + for j := 0; j < 8; j++ { + sj := p.Y + j + if sj > ymax { + sj = ymax + } + yoff := sj * m.Stride + for i := 0; i < 8; i++ { + sx := p.X + i + if sx > xmax { + sx = xmax + } + col := &m.Pix[yoff+sx] + yy, cb, cr := ycbcr.RGBToYCbCr(col.R, col.G, col.B) + yBlock[8*j+i] = int(yy) + cbBlock[8*j+i] = int(cb) + crBlock[8*j+i] = int(cr) + } + } +} + // scale scales the 16x16 region represented by the 4 src blocks to the 8x8 // dst block. func scale(dst *block, src *[4]block) { @@ -431,13 +456,18 @@ func (e *encoder) writeSOS(m image.Image) { prevDCY, prevDCCb, prevDCCr int ) bounds := m.Bounds() + rgba, _ := m.(*image.RGBA) for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 { for x := bounds.Min.X; x < bounds.Max.X; x += 16 { for i := 0; i < 4; i++ { xOff := (i & 1) * 8 yOff := (i & 2) * 4 p := image.Point{x + xOff, y + yOff} - toYCbCr(m, p, &yBlock, &cbBlock[i], &crBlock[i]) + if rgba != nil { + rgbaToYCbCr(rgba, p, &yBlock, &cbBlock[i], &crBlock[i]) + } else { + toYCbCr(m, p, &yBlock, &cbBlock[i], &crBlock[i]) + } prevDCY = e.writeBlock(&yBlock, 0, prevDCY) } scale(&cBlock, &cbBlock) |