draw

package
v0.12.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2023 License: BSD-3-Clause Imports: 6 Imported by: 2

Documentation

Overview

Package draw provides image composition functions.

See "The Go image/draw package" for an introduction to this package: http://golang.org/doc/articles/image_draw.html

This package is a superset of and a drop-in replacement for the image/draw package in the standard library.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// NearestNeighbor is the nearest neighbor interpolator. It is very fast,
	// but usually gives very low quality results. When scaling up, the result
	// will look 'blocky'.
	NearestNeighbor = Interpolator(nnInterpolator{})

	// ApproxBiLinear is a mixture of the nearest neighbor and bi-linear
	// interpolators. It is fast, but usually gives medium quality results.
	//
	// It implements bi-linear interpolation when upscaling and a bi-linear
	// blend of the 4 nearest neighbor pixels when downscaling. This yields
	// nicer quality than nearest neighbor interpolation when upscaling, but
	// the time taken is independent of the number of source pixels, unlike the
	// bi-linear interpolator. When downscaling a large image, the performance
	// difference can be significant.
	ApproxBiLinear = Interpolator(ablInterpolator{})

	// BiLinear is the tent kernel. It is slow, but usually gives high quality
	// results.
	BiLinear = &Kernel{1, func(t float64) float64 {
		return 1 - t
	}}

	// CatmullRom is the Catmull-Rom kernel. It is very slow, but usually gives
	// very high quality results.
	//
	// It is an instance of the more general cubic BC-spline kernel with parameters
	// B=0 and C=0.5. See Mitchell and Netravali, "Reconstruction Filters in
	// Computer Graphics", Computer Graphics, Vol. 22, No. 4, pp. 221-228.
	CatmullRom = &Kernel{2, func(t float64) float64 {
		if t < 1 {
			return (1.5*t-2.5)*t*t + 1
		}
		return ((-0.5*t+2.5)*t-4)*t + 2
	}}
)

Functions

func Copy

func Copy(dst Image, dp image.Point, src image.Image, sr image.Rectangle, op Op, opts *Options)

Copy copies the part of the source image defined by src and sr and writes the result of a Porter-Duff composition to the part of the destination image defined by dst and the translation of sr so that sr.Min translates to dp.

func Draw

func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op)

Draw calls DrawMask with a nil mask.

Example
package main

import (
	"fmt"
	"image"
	"image/color"
	"image/png"
	"log"
	"math"
	"os"

	"github.com/hmmftg/image/draw"
	"github.com/hmmftg/image/math/f64"
)

func main() {
	fSrc, err := os.Open("../testdata/blue-purple-pink.png")
	if err != nil {
		log.Fatal(err)
	}
	defer fSrc.Close()
	src, err := png.Decode(fSrc)
	if err != nil {
		log.Fatal(err)
	}

	dst := image.NewRGBA(image.Rect(0, 0, 400, 300))
	green := image.NewUniform(color.RGBA{0x00, 0x1f, 0x00, 0xff})
	draw.Copy(dst, image.Point{}, green, dst.Bounds(), draw.Src, nil)
	qs := []draw.Interpolator{
		draw.NearestNeighbor,
		draw.ApproxBiLinear,
		draw.CatmullRom,
	}
	const cos60, sin60 = 0.5, 0.866025404
	t := f64.Aff3{
		+2 * cos60, -2 * sin60, 100,
		+2 * sin60, +2 * cos60, 100,
	}

	draw.Copy(dst, image.Point{20, 30}, src, src.Bounds(), draw.Over, nil)
	for i, q := range qs {
		q.Scale(dst, image.Rect(200+10*i, 100*i, 600+10*i, 150+100*i), src, src.Bounds(), draw.Over, nil)
	}
	draw.NearestNeighbor.Transform(dst, t, src, src.Bounds(), draw.Over, nil)

	red := image.NewNRGBA(image.Rect(0, 0, 16, 16))
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			red.SetNRGBA(x, y, color.NRGBA{
				R: uint8(x * 0x11),
				A: uint8(y * 0x11),
			})
		}
	}
	red.SetNRGBA(0, 0, color.NRGBA{0xff, 0xff, 0x00, 0xff})
	red.SetNRGBA(15, 15, color.NRGBA{0xff, 0xff, 0x00, 0xff})

	ops := []draw.Op{
		draw.Over,
		draw.Src,
	}
	for i, op := range ops {
		dr := image.Rect(120+10*i, 150+60*i, 170+10*i, 200+60*i)
		draw.NearestNeighbor.Scale(dst, dr, red, red.Bounds(), op, nil)
		t := f64.Aff3{
			+cos60, -sin60, float64(190 + 10*i),
			+sin60, +cos60, float64(140 + 50*i),
		}
		draw.NearestNeighbor.Transform(dst, t, red, red.Bounds(), op, nil)
	}

	dr := image.Rect(0, 0, 128, 128)
	checkerboard := image.NewAlpha(dr)
	for y := dr.Min.Y; y < dr.Max.Y; y++ {
		for x := dr.Min.X; x < dr.Max.X; x++ {
			if (x/20)%2 == (y/20)%2 {
				checkerboard.SetAlpha(x, y, color.Alpha{0xff})
			}
		}
	}
	sr := image.Rect(0, 0, 16, 16)
	circle := image.NewAlpha(sr)
	for y := sr.Min.Y; y < sr.Max.Y; y++ {
		for x := sr.Min.X; x < sr.Max.X; x++ {
			dx, dy := x-10, y-8
			if d := 32 * math.Sqrt(float64(dx*dx)+float64(dy*dy)); d < 0xff {
				circle.SetAlpha(x, y, color.Alpha{0xff - uint8(d)})
			}
		}
	}
	cyan := image.NewUniform(color.RGBA{0x00, 0xff, 0xff, 0xff})
	draw.NearestNeighbor.Scale(dst, dr, cyan, sr, draw.Over, &draw.Options{
		DstMask: checkerboard,
		SrcMask: circle,
	})

	// Change false to true to write the resultant image to disk.
	if false {
		fDst, err := os.Create("out.png")
		if err != nil {
			log.Fatal(err)
		}
		defer fDst.Close()
		err = png.Encode(fDst, dst)
		if err != nil {
			log.Fatal(err)
		}
	}

	fmt.Printf("dst has bounds %v.\n", dst.Bounds())
}
Output:

dst has bounds (0,0)-(400,300).

func DrawMask

func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op)

DrawMask aligns r.Min in dst with sp in src and mp in mask and then replaces the rectangle r in dst with the result of a Porter-Duff composition. A nil mask is treated as opaque.

Types

type Drawer

type Drawer = draw.Drawer

Drawer contains the Draw method.

var FloydSteinberg Drawer = floydSteinberg{}

FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error diffusion.

type Image

type Image = draw.Image

Image is an image.Image with a Set method to change a single pixel.

type Interpolator

type Interpolator interface {
	Scaler
	Transformer
}

Interpolator is an interpolation algorithm, when dst and src pixels don't have a 1:1 correspondence.

Of the interpolators provided by this package:

  • NearestNeighbor is fast but usually looks worst.
  • CatmullRom is slow but usually looks best.
  • ApproxBiLinear has reasonable speed and quality.

The time taken depends on the size of dr. For kernel interpolators, the speed also depends on the size of sr, and so are often slower than non-kernel interpolators, especially when scaling down.

type Kernel

type Kernel struct {
	// Support is the kernel support and must be >= 0. At(t) is assumed to be
	// zero when t >= Support.
	Support float64
	// At is the kernel function. It will only be called with t in the
	// range [0, Support).
	At func(t float64) float64
}

Kernel is an interpolator that blends source pixels weighted by a symmetric kernel function.

func (*Kernel) NewScaler

func (q *Kernel) NewScaler(dw, dh, sw, sh int) Scaler

NewScaler returns a Scaler that is optimized for scaling multiple times with the same fixed destination and source width and height.

func (*Kernel) Scale

func (q *Kernel) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options)

Scale implements the Scaler interface.

func (*Kernel) Transform

func (q *Kernel) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options)

type Op

type Op = draw.Op

Op is a Porter-Duff compositing operator.

const (
	// Over specifies “(src in mask) over dst”.
	Over Op = draw.Over
	// Src specifies “src in mask”.
	Src Op = draw.Src
)

type Options

type Options struct {
	// Masks limit what parts of the dst image are drawn to and what parts of
	// the src image are drawn from.
	//
	// A dst or src mask image having a zero alpha (transparent) pixel value in
	// the respective coordinate space means that dst pixel is entirely
	// unaffected or that src pixel is considered transparent black. A full
	// alpha (opaque) value means that the dst pixel is maximally affected or
	// the src pixel contributes maximally. The default values, nil, are
	// equivalent to fully opaque, infinitely large mask images.
	//
	// The DstMask is otherwise known as a clip mask, and its pixels map 1:1 to
	// the dst image's pixels. DstMaskP in DstMask space corresponds to
	// image.Point{X:0, Y:0} in dst space. For example, when limiting
	// repainting to a 'dirty rectangle', use that image.Rectangle and a zero
	// image.Point as the DstMask and DstMaskP.
	//
	// The SrcMask's pixels map 1:1 to the src image's 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, use an
	// *image.Uniform as the src, and use the glyph atlas image and the
	// per-glyph offset as SrcMask and SrcMaskP:
	//	Copy(dst, dp, image.NewUniform(color), image.Rect(0, 0, glyphWidth, glyphHeight), &Options{
	//		SrcMask:  glyphAtlas,
	//		SrcMaskP: glyphOffset,
	//	})
	DstMask  image.Image
	DstMaskP image.Point
	SrcMask  image.Image
	SrcMaskP image.Point
}

Options are optional parameters to Copy, Scale and Transform.

A nil *Options means to use the default (zero) values of each field.

type Quantizer

type Quantizer = draw.Quantizer

Quantizer produces a palette for an image.

type RGBA64Image

type RGBA64Image = draw.RGBA64Image

RGBA64Image extends both the Image and image.RGBA64Image interfaces with a SetRGBA64 method to change a single pixel. SetRGBA64 is equivalent to calling Set, but it can avoid allocations from converting concrete color types to the color.Color interface type.

type Scaler

type Scaler interface {
	Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options)
}

Scaler scales the part of the source image defined by src and sr and writes the result of a Porter-Duff composition to the part of the destination image defined by dst and dr.

A Scaler is safe to use concurrently.

type Transformer

type Transformer interface {
	Transform(dst Image, m f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options)
}

Transformer transforms the part of the source image defined by src and sr and writes the result of a Porter-Duff composition to the part of the destination image defined by dst and the affine transform m applied to sr.

For example, if m is the matrix

m00 m01 m02
m10 m11 m12

then the src-space point (sx, sy) maps to the dst-space point (m00*sx + m01*sy + m02, m10*sx + m11*sy + m12).

A Transformer is safe to use concurrently.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL