Feature Request: Basic draw functions in standard library

589 views
Skip to first unread message

Rick Smith

unread,
May 21, 2015, 12:05:15 PM5/21/15
to golan...@googlegroups.com
While I am grateful for the image drawing functions and the ability to change a single pixel's color at a time, I feel that perhaps Go's standard library could be spruced up slightly.  In particular, it would be really nice to have functions that could draw lines and rectangles.  While not really that hard to write, it seems to me that they are required enough that they could merit a spot in image.draw.

Are there any good reasons this has not been included?
Is anyone working on including this in the standard library?
Would work in the this area be welcome?

Thanks!

Mateusz Czapliński

unread,
May 21, 2015, 2:33:46 PM5/21/15
to golan...@googlegroups.com

Are you aware of the line-drawing functions in freetype-go? Especially:
  https://godoc.org/code.google.com/p/freetype-go/freetype/raster#Rasterizer
(it's dual-licensed, either GPL or "FreeType License, which is similar to the original BSD license with an advertising clause")
or, alternatively, some other packages building on that:
  https://godoc.org/code.google.com/p/freetype-go/freetype/raster?importers

/M.

Rick Smith

unread,
May 21, 2015, 3:35:31 PM5/21/15
to golan...@googlegroups.com
Yes, I'm aware of those libraries--I've even used freetype-go for writing strings.  It seemed quite good, but I feel like the standard library shouldn't have to rely on third-parties for core functionality like this.  

Thanks for the reply!

Brendan Tracey

unread,
May 22, 2015, 10:15:12 AM5/22/15
to golan...@googlegroups.com
Depending on what you need, you may find some of the functions in github.com/gonum/plot/vg/draw useful.

simon place

unread,
May 22, 2015, 8:16:24 PM5/22/15
to golan...@googlegroups.com
seems to me the 'usual' context of Go is server/cloud, and image pixel creation is usually done on the client, (deliver SVG for example) so it makes sense its not there/ low priority to be built-in, just import a 3rd party lib.

on the other hand, there was a thread recently about contextual syntax modification, ie being able to modify syntax depending on application context, i thought go's syntax too simple (pure?) to have that, but i made an argument for context based std lib's, solving the same problem.

so if there was a 'local'/'client' version of the std lib, then this should most definitely have basic image generation.

of course packages only get imported when needed, and nothing not used appears in the compiled code, but maybe multiple std libs, with particular focuses, might be nice for concentrating a coders learning, for the context he has at hand.

Rick Smith

unread,
May 27, 2015, 7:27:13 PM5/27/15
to golan...@googlegroups.com
Based on the comments I've got here, I'm under the impression that the general consensus is that there is little pushback on adding the drawing functions but they are also not a high priority.  I'm therefore volunteering to do the work to try to include the following functions into src/image/draw/draw.go:


DrawLine(image draw.Image, start image.Point, stop image.Point, color image.Color, thickness float)

DrawRect(image draw.Image, rect image.Rectangle, color image.Color, thickness float)

DrawCurve(image draw.Image, p0 image.Point, p1 image.Point, p2 image.Point, color image.Color, thickness float)

DrawEllipse(image draw.Image, rect image.Rectangle, color image.Color, thickness float)

DrawCircle(image draw.Image, center image.Point, color image.Color, thickness float) 



FillRect(image draw.Image, rect image.Rectangle, color image.Color)

FillEllipse(image draw.Image, rect image.Rectangle, color image.Color)

FillCircle(image draw.Image, center image.Point, color image.Color)

FillPolygon(image draw.Image, points []image.Point, color image.Color)


I am planning on implementing these functions using variations on Bresenham's algorithm because it is robust, fast, simple, exact, smooth, and allows varying thicknesses.  Please provide feedback on any improvements or changes that should to be made.


@Bendan Thanks for the link, it inspired me to add FillPolygon().  

@Simon Your ideas about std libs are interesting, it's a lot to think about.  I'll write these functions and let people smarter than me decide where they go ;)



Roberto Zanotto

unread,
May 27, 2015, 8:20:56 PM5/27/15
to golan...@googlegroups.com
Maybe instead of an image.Color it would be more general to use a draw.Image to specify the filling. An image can represent a solid color, a bitmap fill, a gradient fill or whatever.

Nigel Tao

unread,
May 27, 2015, 9:27:59 PM5/27/15
to Rick Smith, golang-nuts
On Thu, May 28, 2015 at 9:27 AM, Rick Smith <ricoch...@gmail.com> wrote:
> I'm therefore volunteering
> to do the work to try to include the following functions into
> src/image/draw/draw.go:

First of all, the standard library is currently in feature freeze up
until the Go 1.5 release, due August 1:
https://groups.google.com/d/msg/golang-dev/otCULnOjs7I/kmNcWjvcMvYJ

Even so, speaking as the maintainer of the image/draw package in the
standard library, I don't see a need for such functions to live there.
Furthermore, anything that ships in the stdlib has to have its API
frozen for ever more, so you couldn't add a draw.Op argument, or some
control over anti-aliasing, in the future, if you later changed your
mind on what the best API should be.

There's already metric tonnes of useful Go code out there that aren't
in the stdlib. I don't see why a Bresenham's algorithm implementation
is any different. Just make your own package, on github.com or
somewhere else, that's as easy to install as "step 1 is go get
github.com/foo/draw; there is no step 2".

If there's overwhelming usage of your library, after it's released,
then I'm open to reconsidering merging those features into the stdlib.
But I think that adding it to the stdlib before there's clear demand
for it is doing things in the wrong order.

OTOH, X11 servers are bound by backwards compatibility to provide
functions like this (and stippling!) in the X protocol, but I can't
think of any modern GUI programs that use them (they use e.g. cairo
instead), so at this point in time such features have no benefit but
still have a maintenance cost.

ajstarks

unread,
May 28, 2015, 9:49:33 AM5/28/15
to golan...@googlegroups.com
FWIW, I've worked with these 2D drawing APIs in Go:


My interest is finding the correct abstraction to programming pictures. [5]
With all of these APIs, I've found the best model is to think in terms of higher-level objects, programming 
relationships, and applying attributes as needed.

Rick Smith

unread,
May 28, 2015, 1:44:04 PM5/28/15
to golan...@googlegroups.com, ricoch...@gmail.com
First off, thanks for your work maintaining the image/draw package as well as taking the time to respond. 
 

First of all, the standard library is currently in feature freeze up
until the Go 1.5 release, due August 1:
https://groups.google.com/d/msg/golang-dev/otCULnOjs7I/kmNcWjvcMvYJ

Yup, definitely wasn't thinking I'd get into 1.5.


Even so, speaking as the maintainer of the image/draw package in the
standard library, I don't see a need for such functions to live there.

My thought process is that the standard libraries that I know of that include image manipulation, all seem to also include basic drawing functions.  image/draw seems a little naked to me without it and so I've made this suggestion.  However, my goal is to help you so if you don't want the code in image/draw, I respect that.  
 

There's already metric tonnes of useful Go code out there that aren't
in the stdlib.  I don't see why a Bresenham's algorithm implementation 
is any different.  Just make your own package, on github.com or 
somewhere else, that's as easy to install as "step 1 is go get
github.com/foo/draw; there is no step 2".

If there's overwhelming usage of your library, after it's released,
then I'm open to reconsidering merging those features into the stdlib.
But I think that adding it to the stdlib before there's clear demand
for it is doing things in the wrong order.

 
This is a very fair statement; I will create a github package.  To ensure that I don't bother you prematurely, what do you consider "overwhelming usage"?  100 stars of github?  Or some other metric perhaps?

 
Furthermore, anything that ships in the stdlib has to have its API 
frozen for ever more, so you couldn't add a draw.Op argument, or some 
control over anti-aliasing, in the future, if you later changed your 
mind on what the best API should be. 

My thought on this was I wasn't sure how much code I could contribute to image/draw without getting too much kickback.  I figured I'd cover what I perceived to be the most common case and if that was not what someone wanted they could do their own (they'd be now worse off than they currently are) or if there was a common alternate case a new function could be added (ie. DrawLineNoAA).  I understand that there are pros and cons to this and they may not be the tradeoff you'd like.  I'm open.

I also considered creating a Draw struct for each shape like:

NewRectDrawer(image, rect, color).SetFill(true).Draw()

or where creating a new struct for each Draw() would hurt performance:

rd := NewRectDrawer(image, rect, color).SetThickness(5).Draw()
rd.SetRect(rect2).Draw()

Basically all functions in each Drawer returns its pointer to allow chaining.  This allows unlimited new methods to be added to change behaviour while maintaining backwards compatibility.  I can also do something more like draw.Ops if you'd prefer.

To be clear, I get your skepticism about the need for these functions.  I just want to make sure that should I get sufficient traction, my code is such that you'd be consider merging it into the stdlib.  So please, provide a little more feedback for me if you could.

Thanks.

Nigel Tao

unread,
May 29, 2015, 12:09:06 AM5/29/15
to Rick Smith, golang-nuts
On Fri, May 29, 2015 at 3:44 AM, Rick Smith <ricoch...@gmail.com> wrote:
> This is a very fair statement; I will create a github package. To ensure
> that I don't bother you prematurely, what do you consider "overwhelming
> usage"? 100 stars of github? Or some other metric perhaps?

There's no single metric that defines "overwhelming". It's not a game
where 100 github stars lets you level up.

To be honest, though, I don't see much demand for this. For example,
I've been on the mailing list since day 0, and grepping my mail for
[golang-nuts draw ellipse] gives me about 1 post a year.


> To be clear, I get your skepticism about the need for these functions. I
> just want to make sure that should I get sufficient traction, my code is
> such that you'd be consider merging it into the stdlib. So please, provide
> a little more feedback for me if you could.

If your code does get good traction, then we can always debate whether
and how the API should change as it moves to the stdlib, especially if
we can back up any argument with things like "with two years of
hindsight, users want to do X more often than we first expected, don't
use Y at all, and doing Z efficiently is hard, so let's change such
and such". Until then, I'd just recommend scratching whatever your
immediate itch is, and resist the urge for premature generalization.

If you want a concrete suggestion, I'd add a radius argument to your
Draw/FillCircle functions. :-)

Rick Smith

unread,
Jun 2, 2015, 2:04:07 PM6/2/15
to golan...@googlegroups.com, ricoch...@gmail.com
I've created a repository for development on this here: https://github.com/ricochet2200/drawer

It's bare at the moment, but I'll be adding code in near future.


There's no single metric that defines "overwhelming". It's not a game
where 100 github stars lets you level up.

 
I think you may misunderstand my intention.  You've made it fairly clear you don't think these features are important and I can tell you are not that interested.  I get it, you've got a lot of other things you have higher on your priority list...it is your right to focus on what you think is the most important.  I've said my piece and posted my link and I'm ready to bow out.  I'm just trying to gauge what it would take for you to want to talk about this again.  Yeah, no single metric defines it, but unless you want to further specify "overwhelming" I think stars serves as a reasonable heuristic for determining when further talks might be merited.

Thanks everyone for the feedback.  I'll post again after I've leveled up!    ;)
Reply all
Reply to author
Forward
0 new messages