diff options
Diffstat (limited to 'src/pkg/image/jpeg')
-rw-r--r-- | src/pkg/image/jpeg/writer.go | 32 | ||||
-rw-r--r-- | src/pkg/image/jpeg/writer_test.go | 28 |
2 files changed, 59 insertions, 1 deletions
diff --git a/src/pkg/image/jpeg/writer.go b/src/pkg/image/jpeg/writer.go index 505cce04f..52b3dc4e2 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) diff --git a/src/pkg/image/jpeg/writer_test.go b/src/pkg/image/jpeg/writer_test.go index 00922dd5c..7aec70f01 100644 --- a/src/pkg/image/jpeg/writer_test.go +++ b/src/pkg/image/jpeg/writer_test.go @@ -8,6 +8,8 @@ import ( "bytes" "image" "image/png" + "io/ioutil" + "rand" "os" "testing" ) @@ -85,3 +87,29 @@ func TestWriter(t *testing.T) { } } } + +func BenchmarkEncodeRGBOpaque(b *testing.B) { + b.StopTimer() + img := image.NewRGBA(640, 480) + // Set all pixels to 0xFF alpha to force opaque mode. + bo := img.Bounds() + rnd := rand.New(rand.NewSource(123)) + for y := bo.Min.Y; y < bo.Max.Y; y++ { + for x := bo.Min.X; x < bo.Max.X; x++ { + img.Set(x, y, image.RGBAColor{ + uint8(rnd.Intn(256)), + uint8(rnd.Intn(256)), + uint8(rnd.Intn(256)), + 255}) + } + } + if !img.Opaque() { + panic("expected image to be opaque") + } + b.SetBytes(640 * 480 * 4) + b.StartTimer() + options := &Options{Quality: 90} + for i := 0; i < b.N; i++ { + Encode(ioutil.Discard, img, options) + } +} |