Your code uses the Image interface and its At method, which is a
general-purpose interface with much overhead. For higher throughput,
it should use the implementation directly, if it's known, such as
NRGBA or whatever. That will make a big difference. Also, you're right
that there's much work to do in making the image libraries better.
Your "why bother?" question is a good one. There are many answers.
First, with cgo one could use PIL or some other library of course, and
there are situations where that approach is right. Go does not prevent
you using a library in another language.
The main reason for doing things again is to make them Go native,
native in the sense of fitting into the ecosystem well, building on
the libraries and interfaces that are already there, and feeding ideas
and insights back into the libraries and community.
But of course there's also the "why not?" retort: If one just accepts
that everything that needs to exist already does in its finest form,
there's no reason to do anything new (including designing a new
programming language). But in doing things again, one learns.
Designing a native package provides insight into how things should be
put together. For the particular problem you're working on,
implementing things that require performance encourages
performance-driven work. If every time a loop is slow we use an FFI
and the C compiler, we'll never find out where the Go compilers (and
libraries and runtime) could be made better in ways that would make
all programs faster.
Go's implementation is getting faster all the time. We've seen massive
improvements this year; relative to Go 1 the implementation at tip is
seeing benchmarks that are often 50% or more faster, sometimes much
more. We'll be releasing those improvements soon.
In the meantime, please keep pushing and poking at the code and giving
feedback and learning how to make things run fast. It benefits all of