The image/draw package in the standard library has these functions:
----
func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op)
func DrawMask(dst Image, r image.Rectangle, src image.Image, sp
image.Point, mask image.Image, mp image.Point, op Op)
----
These functions are covered by the Go 1 backwards compatibility guarantee.
The
golang.org/x/image/draw package is intended to be a drop-in
replacement for image/draw, and its API is a superset of the standard
image/draw's API. The additional API currently looks like:
----
func Scale(dst Image, dr image.Rectangle, src image.Image, sr
image.Rectangle, q Interpolator)
type Interpolator interface {
NewScaler(dw, dh, sw, sh int32) Scaler
}
type Scaler interface {
Scale(dst Image, dp image.Point, src image.Image, sp image.Point)
}
var NearestNeighbor = Interpolator(etc)
----
I would like to expand that API to allow for affine transformations,
including arbitrary rotations, as well as for clipping and masking.
The aim is, together with a Bezier curve rasterizer and a font
library, to be able to rasterize something similar to PDF 1.4's
graphics model. I propose for
golang.org/x/image/draw to have three
key functions:
----
func Copy(dst Image, dp image.Point, src image.Image, sr
image.Rectangle, opts *Options)
func Scale(dst Image, dr image.Rectangle, src image.Image, sr
image.Rectangle, q Interpolator, opts *Options)
func Transform(dst Image, m *f64.Mat3, src image.Image, sr
image.Rectangle, q Interpolator, opts *Options)
----
(I might also add Rotate90CW, Rotate180 and Rotate90CCW in the future,
with the same signature as Copy, but that's not part of my immediate
plans).
All three functions map the sr part of src onto the destination. All
three signatures are the same, except for the second argument (the map
from the src co-ordinate space to the dst co-ordinate space) and Copy
doesn't have an Interpolator, since it has a 1:1 relationship between
dst and src pixels.
For Copy, the map is a "dp image.Point" that denotes where the src
image's src.Min maps to. This is similar to how the dr and sp
arguments work for the existing Draw function, except rectangleness
has moved from dst to src, to be consistent with Scale and Transform.
For Scale, both dst and src are integer-quantized axis-aligned
rectangles, so the map is a "dr image.Rectangle" that denotes where
the src image's sr maps to.
For Transform, m is an arbitrary 2D affine transformation, and
dst-space co-ordinates equals m times src-space co-ordinates. It is an
*f64.Mat3, or if a specialized affine 3x2 matrix type exists, an
*f64.Aff3. I'll start a separate discussion thread about whether to
have an Aff3 type separate from Mat3.
A nil *Options means to use the default Options, which is equivalent
to a non-nil Options with zero-valued fields. Options is:
----
type Options struct {
// A zero Op means to use the Over operator.
Op Op
// Masks limit what parts of the dst image are drawn to and
// what parts of the src image are drawn from.
//
// The DstMask is otherwise known as a clip mask, and its
// pixels map 1:1 to dst pixels. DstMaskP in DstMask space
// corresponds to image.Point{X:0, Y:0} in dst space. For
// example, when limiting re-painting to a 'dirty rectangle',
// use that rectangle as the DstMask.
//
// The SrcMask's pixels map 1:1 to src pixels. SrcMaskP
// in SrcMask space corresponds to image.Point{X:0, Y:0}
// in src space. For example, when drawing font glyphs in
// a uniform color c (of type *image.Uniform), use c as the
// src, and use the glyph atlas image and the per-glyph
// offset as SrcMask and SrcMaskP.
DstMask image.Image
DstMaskP image.Point
SrcMask image.Image
SrcMaskP image.Point
}
----
The Scale and Interpolator types would then become:
----
type Interpolator interface {
NewScaler(dw, dh, sw, sh int32) Scaler
Transform(dst Image, m *f64.Mat3, src image.Image, sr
image.Rectangle, opts *Options)
}
type Scaler interface {
Scale(dst Image, dp image.Point, src image.Image, sp image.Point,
opts *Options)
}
----
I made a hand-wavy remark about using rectangles as masks. This would
be literally possible if image.Rectangle implemented image.Image. I'll
start a separate discussion thread about whether to do so.
golang-dev, WDYT?