]> Cypherpunks.ru repositories - gostls13.git/commitdiff
image/draw: optimize paletted dst + uniform src
authorNigel Tao <nigeltao@golang.org>
Sat, 25 Apr 2020 12:29:02 +0000 (22:29 +1000)
committerNigel Tao <nigeltao@golang.org>
Mon, 27 Apr 2020 23:05:16 +0000 (23:05 +0000)
name            old time/op  new time/op  delta
PalettedFill-4  5.74ms ± 1%  0.01ms ± 1%  -99.78%  (p=0.008 n=5+5)
PalettedRGBA-4  3.34ms ± 3%  3.33ms ± 0%     ~     (p=0.690 n=5+5)

Fixes #35938

Thanks to pjbgtnj for the suggestion.

Change-Id: I07b494482cce918f556e196c5a4b481b4c16de3a
Reviewed-on: https://go-review.googlesource.com/c/go/+/230118
Run-TryBot: Nigel Tao <nigeltao@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
src/image/draw/bench_test.go
src/image/draw/draw.go
src/image/draw/draw_test.go

index a41d7e7dfb7ec783c41235f0d7bdd18276ba7f90..831fd958ba3ed3efb292c12ef09aea4f6bd58607 100644 (file)
@@ -236,7 +236,11 @@ func BenchmarkRGBA(b *testing.B) {
        bench(b, color.RGBAModel, color.RGBA64Model, nil, Src)
 }
 
-func BenchmarkPaletted(b *testing.B) {
+func BenchmarkPalettedFill(b *testing.B) {
+       bench(b, palette, nil, nil, Src)
+}
+
+func BenchmarkPalettedRGBA(b *testing.B) {
        bench(b, palette, color.RGBAModel, nil, Src)
 }
 
index 932a5444831b92ddc7fb1778dd9139e8930e1fbc..8f96aa2d180eb7d774240c242d6fab14e24e90d6 100644 (file)
@@ -180,9 +180,25 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
                drawRGBA(dst0, r, src, sp, mask, mp, op)
                return
        case *image.Paletted:
-               if op == Src && mask == nil && !processBackward(dst, r, src, sp) {
-                       drawPaletted(dst0, r, src, sp, false)
-                       return
+               if op == Src && mask == nil {
+                       if src0, ok := src.(*image.Uniform); ok {
+                               colorIndex := uint8(dst0.Palette.Index(src0.C))
+                               i0 := dst0.PixOffset(r.Min.X, r.Min.Y)
+                               i1 := i0 + r.Dx()
+                               for i := i0; i < i1; i++ {
+                                       dst0.Pix[i] = colorIndex
+                               }
+                               firstRow := dst0.Pix[i0:i1]
+                               for y := r.Min.Y + 1; y < r.Max.Y; y++ {
+                                       i0 += dst0.Stride
+                                       i1 += dst0.Stride
+                                       copy(dst0.Pix[i0:i1], firstRow)
+                               }
+                               return
+                       } else if !processBackward(dst, r, src, sp) {
+                               drawPaletted(dst0, r, src, sp, false)
+                               return
+                       }
                }
        }
 
index dea51b6bc50671287a465130998802363cc28b0d..9c5a118400e095ebc3681a479e4e0c1448352a3e 100644 (file)
@@ -434,11 +434,11 @@ func TestPaletted(t *testing.T) {
                t.Fatalf("open: %v", err)
        }
        defer f.Close()
-       src, err := png.Decode(f)
+       video001, err := png.Decode(f)
        if err != nil {
                t.Fatalf("decode: %v", err)
        }
-       b := src.Bounds()
+       b := video001.Bounds()
 
        cgaPalette := color.Palette{
                color.RGBA{0x00, 0x00, 0x00, 0xff},
@@ -450,19 +450,25 @@ func TestPaletted(t *testing.T) {
                "src":             Src,
                "floyd-steinberg": FloydSteinberg,
        }
+       sources := map[string]image.Image{
+               "uniform":  &image.Uniform{color.RGBA{0xff, 0x7f, 0xff, 0xff}},
+               "video001": video001,
+       }
 
-loop:
        for dName, d := range drawers {
-               dst0 := image.NewPaletted(b, cgaPalette)
-               dst1 := image.NewPaletted(b, cgaPalette)
-               d.Draw(dst0, b, src, image.Point{})
-               d.Draw(embeddedPaletted{dst1}, b, src, image.Point{})
-               for y := b.Min.Y; y < b.Max.Y; y++ {
-                       for x := b.Min.X; x < b.Max.X; x++ {
-                               if !eq(dst0.At(x, y), dst1.At(x, y)) {
-                                       t.Errorf("%s: at (%d, %d), %v versus %v",
-                                               dName, x, y, dst0.At(x, y), dst1.At(x, y))
-                                       continue loop
+       loop:
+               for sName, src := range sources {
+                       dst0 := image.NewPaletted(b, cgaPalette)
+                       dst1 := image.NewPaletted(b, cgaPalette)
+                       d.Draw(dst0, b, src, image.Point{})
+                       d.Draw(embeddedPaletted{dst1}, b, src, image.Point{})
+                       for y := b.Min.Y; y < b.Max.Y; y++ {
+                               for x := b.Min.X; x < b.Max.X; x++ {
+                                       if !eq(dst0.At(x, y), dst1.At(x, y)) {
+                                               t.Errorf("%s / %s: at (%d, %d), %v versus %v",
+                                                       dName, sName, x, y, dst0.At(x, y), dst1.At(x, y))
+                                               continue loop
+                                       }
                                }
                        }
                }