mirror of
https://github.com/golang/go
synced 2024-11-12 01:00:22 -07:00
image/draw: reduce drawPaletted allocations for special source cases
drawPaletted has to discover R,G,B,A color values of each source image pixel in a given rectangle. Doing that by calling image.Image.At() method returning color.Color interface is quite taxing allocation-wise since interface values go through heap. Introduce special cases for some concrete source types by fetching color values using type-specific methods. name old time/op new time/op delta Paletted-4 7.62ms ± 4% 3.72ms ± 3% -51.20% (p=0.008 n=5+5) name old alloc/op new alloc/op delta Paletted-4 480kB ± 0% 0kB ± 0% -99.99% (p=0.000 n=4+5) name old allocs/op new allocs/op delta Paletted-4 120k ± 0% 0k ± 0% -100.00% (p=0.008 n=5+5) Updates #15759. Change-Id: I0ce1770ff600ac80599541aaad4c2c826855c8fb Reviewed-on: https://go-review.googlesource.com/72370 Reviewed-by: Nigel Tao <nigeltao@golang.org>
This commit is contained in:
parent
f2d52519e1
commit
088209bbe8
@ -603,6 +603,18 @@ func drawPaletted(dst Image, r image.Rectangle, src image.Image, sp image.Point,
|
||||
quantErrorCurr = make([][4]int32, r.Dx()+2)
|
||||
quantErrorNext = make([][4]int32, r.Dx()+2)
|
||||
}
|
||||
pxRGBA := func(x, y int) (r, g, b, a uint32) { return src.At(x, y).RGBA() }
|
||||
// Fast paths for special cases to avoid excessive use of the color.Color
|
||||
// interface which escapes to the heap but need to be discovered for
|
||||
// each pixel on r. See also https://golang.org/issues/15759.
|
||||
switch src0 := src.(type) {
|
||||
case *image.RGBA:
|
||||
pxRGBA = func(x, y int) (r, g, b, a uint32) { return src0.RGBAAt(x, y).RGBA() }
|
||||
case *image.NRGBA:
|
||||
pxRGBA = func(x, y int) (r, g, b, a uint32) { return src0.NRGBAAt(x, y).RGBA() }
|
||||
case *image.YCbCr:
|
||||
pxRGBA = func(x, y int) (r, g, b, a uint32) { return src0.YCbCrAt(x, y).RGBA() }
|
||||
}
|
||||
|
||||
// Loop over each source pixel.
|
||||
out := color.RGBA64{A: 0xffff}
|
||||
@ -610,7 +622,7 @@ func drawPaletted(dst Image, r image.Rectangle, src image.Image, sp image.Point,
|
||||
for x := 0; x != r.Dx(); x++ {
|
||||
// er, eg and eb are the pixel's R,G,B values plus the
|
||||
// optional Floyd-Steinberg error.
|
||||
sr, sg, sb, sa := src.At(sp.X+x, sp.Y+y).RGBA()
|
||||
sr, sg, sb, sa := pxRGBA(sp.X+x, sp.Y+y)
|
||||
er, eg, eb, ea := int32(sr), int32(sg), int32(sb), int32(sa)
|
||||
if floydSteinberg {
|
||||
er = clamp(er + quantErrorCurr[x+1][0]/16)
|
||||
|
Loading…
Reference in New Issue
Block a user