Skip to content

image/draw: optimize DrawMask when drawing a Uniform Image onto a Paletted Image #35938

Closed

Description

@pjbgtnj

What version of Go are you using (go version)? 1.13.4

$ go version
go version devel +a18608a Mon Dec 2 20:12:54 2019 +0000 linux/amd64

Does this issue reproduce with the latest release?

Yes - and github master branch too

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOHOSTARCH="amd64"
GOHOSTOS="linux"

What did you do?

Wrote a program that ran much slower than expected. The following program will reproduce the slow speed:

package main

import (
	"fmt"
	"image"
	"image/color"
	"image/color/palette"
	"image/draw"
	"time"
)

func main() {
	startTime := time.Now()
	red := &color.RGBA{255, 0, 0, 0}
	rect := image.Rect(-1000, -1000, 1000, 1000)
	palettedImage := image.NewPaletted(rect, palette.WebSafe)
	uniformImage := image.NewUniform(red)
	draw.Draw(palettedImage, rect, uniformImage, image.Point{}, draw.Src)
	numPoints := rect.Dx() * rect.Dy()
	took := time.Since(startTime)
	fmt.Printf("Took: %s for %d points - %f pps\n", took, numPoints, float64(numPoints)/took.Seconds())
}

What did you expect to see?

It should run very quickly, not take several seconds. The DrawMask function in image/draw/draw.go is called a lot for the specific application I'm working with and this is the bottleneck.

What did you see instead?

I expected it to run nearly instantly

Here is a proposed fix:

diff --git a/src/image/draw/draw.go b/src/image/draw/draw.go
index 932a544..3a0157d 100644
--- a/src/image/draw/draw.go
+++ b/src/image/draw/draw.go
@@ -181,8 +181,25 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
                return
        case *image.Paletted:
                if op == Src && mask == nil && !processBackward(dst, r, src, sp) {
-                       drawPaletted(dst0, r, src, sp, false)
-                       return
+                        switch src0 := src.(type) {
+                        case *image.Uniform:
+                                i0 := dst0.PixOffset(r.Min.X, r.Min.Y)
+                                i1 := i0 + r.Dx()
+                                colorIdx := uint8(dst0.Palette.Index(src0.C))
+                                for i := i0; i < i1; i++ {
+                                        dst0.Pix[i] = colorIdx
+                                }
+                                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
+                        default:
+                                drawPaletted(dst0, r, src, sp, false)
+                                return
+                        }
                }
        }

Activity

  1. pjbgtnj commented on Dec 2, 2019

    @pjbgtnj
    Author

    Difference in speed between current version and proposed change:

    Current Version: Took: 3.722995689s for 4000000 points - 1074403.607777 pps
    
    With Change:      Took: 3.170383ms for 4000000 points - 1261677216.916694 pps
    
  2. changed the title [-]image/draw DrawMask slow when drawing a Uniform Image onto a Paletted Image[/-] [+]image/draw: optimize DrawMask when drawing a Uniform Image onto a Paletted Image[/+] on Dec 3, 2019
  3. added
    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.
    on Dec 3, 2019
  4. added this to the Backlog milestone on Dec 3, 2019
  5. cagedmantis commented on Dec 3, 2019

    @cagedmantis
    Contributor

    @bradfitz
    You've been active in this package. Please let me know if this should be directed toward anybody else.

  6. bradfitz commented on Dec 4, 2019

    @bradfitz
    Contributor

    @nigeltao primarily owns image/*.

  7. nigeltao commented on Dec 24, 2019

    @nigeltao
    Contributor

    Proposed fix looks fine for whenever the Go 1.15 tree opens, after the Go 1.14 release.

    The recommended process for contributing patches is documented at
    https://golang.org/doc/contribute.html

    Or, if you're happy without formal authorship attribution, in terms of the Author field in the git log, I'm happy to send out the code review with this fix.

  8. pjbgtnj commented on Dec 24, 2019

    @pjbgtnj
    Author

    @nigeltao - I'm fine without formal authorship but I will look into following the recommended process in the future.

  9. gopherbot commented on Apr 25, 2020

    @gopherbot
    Contributor

    Change https://golang.org/cl/230118 mentions this issue: image/draw: optimize paletted dst + uniform src

  10. added a commit that references this issue on May 21, 2020
    f31ea17
  11. locked and limited conversation to collaborators on Apr 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions