Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/image: vector.go rasterizer shifts alpha mask and is slow when target is offset and small relative image size #25657

Open
srwiley opened this issue May 31, 2018 · 1 comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Performance
Milestone

Comments

@srwiley
Copy link

srwiley commented May 31, 2018

Please answer these questions before submitting your issue. Thanks!

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

1.10.2

Does this issue reproduce with the latest release?

Yes

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

linux/amd64

What did you do?

In the golang.org/x/image/vector.go there is this function:

func (z *Rasterizer) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point)
r is the target rectangle for rendering the image. When r is a smaller rectangle than the bounds of the destination image dst, and offset into the middle of dst, two problems emerge:

First, the alpha mask, which is the whole point of the Draw command shifts with the target rectangle rather than staying fixed to the upper left corner of the image. I believe this should not be the default behavior. It is not consistent with other rasterizers, such as the free type rasterizer. If the mask shifts with the target and you are rendering a path using, say, Bezier curves, and want to draw that path onto an image, you must either determine before hand the exact boundaries of the path and shift the coordinates accordingly, because as it is, a target drawn somewhere in the middle of an image will always draw the mask relative to the upper left corner of the target rectangle. Having to determine the boundaries before hand requires flattening the curves and either storing the resulting line segments or repeating the process when actually rendering the alpha mask. It is much simpler to keep the alpha mask fixed to the upper left corner of the image boundary rather than move with the target rectangle.

Second, no matter how big the target rectangle is relative to the entire image, the "accumulate step" traverses the entire image, which is inefficient when the target is a small fraction of the image.

I have created a modified version of the rasterizer here: https://github.com/srwiley/image

In the vector_test.go file are modified versions of the TestBasicPathDstAlpha and TestBasicPathDstRGBA test functions. These are changed to test for fixing the alpha mask to the image and not shifting with the target. They will fail with the current version of vector.go, but not the forked version.

There are also a series of benchmarks showing the improved performance when the target is small relative the destination image. This is what the benchmark output looks like:

BenchmarkDrawPathBounds1000-16         	      30	  44412739 ns/op
BenchmarkDrawImageBounds1000-16        	      20	  53485352 ns/op
BenchmarkDrawPathBounds100-16          	    3000	    458989 ns/op
BenchmarkDrawImageBounds100-16         	      20	  53309779 ns/op
BenchmarkDrawPathBounds10-16           	  200000	      6054 ns/op
BenchmarkDrawImageBounds10-16          	      20	  55934650 ns/op
BenchmarkDrawPathBounds2-16            	 1000000	      1021 ns/op
BenchmarkDrawImageBounds2-16           	      20	  54077408 ns/op

BenchmarkDrawPathBoundsX draw only the path boundary for a path of a hexagon of the indicated radius X in a 2200x2200 sized image. BenchmarkDrawImageBoundsX draws the entire image, which is what the current vector.go file does. So, as the size of the path gets smaller the speed difference increases.

What did you expect to see?

Significantly greater speed when the target is small compared to the image size and the alpha mask fixed to the upper left of the destination image.

What did you see instead?

Inefficient speed for small target sizes relative the image size, and the alpha mask fixed relative the target rectangle upper left corner and not the destination image bounds.

@ianlancetaylor ianlancetaylor changed the title Vector.go rasterizer shifts alpha mask and is slow when target is offset and small relative image size x/image: vector.go rasterizer shifts alpha mask and is slow when target is offset and small relative image size May 31, 2018
@gopherbot gopherbot added this to the Unreleased milestone May 31, 2018
@ianlancetaylor ianlancetaylor added Performance NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels May 31, 2018
@ianlancetaylor
Copy link
Contributor

CC @nigeltao

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Performance
Projects
None yet
Development

No branches or pull requests

3 participants