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

Add SetScaleStyle for zoomed images #173

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
73 changes: 72 additions & 1 deletion context.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type Context struct {
fontHeight float64
matrix Matrix
stack []*Context
scaleStyle ScaleStyle
}

// NewContext creates a new image.RGBA with the specified width and height
Expand Down Expand Up @@ -112,6 +113,76 @@ func NewContextForRGBA(im *image.RGBA) *Context {
}
}

// ScaleStyle determines the way image pixels are interpolated when scaled.
// See
// https://pkg.go.dev/golang.org/x/image/draw
// for the corresponding interpolators.
type ScaleStyle int

const (
// BiLinear is the tent kernel. It is slow, but usually gives high quality
// results.
BiLinear ScaleStyle = iota

// 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

// 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

// 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
)

func (s ScaleStyle) transformer() draw.Interpolator {
switch s {
case BiLinear:
return draw.BiLinear
case ApproxBiLinear:
return draw.ApproxBiLinear
case NearestNeighbor:
return draw.NearestNeighbor
case CatmullRom:
return draw.CatmullRom
}
return draw.BiLinear // BiLinear by default.
}

func (dc *Context) SetScaleStyle(s ScaleStyle) {
dc.scaleStyle = s
}

func (dc *Context) SetScaleBiLinear() {
dc.SetScaleStyle(BiLinear)
}

func (dc *Context) SetScaleApproxBiLinear() {
dc.SetScaleStyle(ApproxBiLinear)
}

func (dc *Context) SetScaleNearestNeighbor() {
dc.SetScaleStyle(NearestNeighbor)
}

func (dc *Context) SetScaleCatmullRom() {
dc.SetScaleStyle(CatmullRom)
}

// GetCurrentPoint will return the current point and if there is a current point.
// The point will have been transformed by the context's transformation matrix.
func (dc *Context) GetCurrentPoint() (Point, bool) {
Expand Down Expand Up @@ -673,7 +744,7 @@ func (dc *Context) DrawImageAnchored(im image.Image, x, y int, ax, ay float64) {
s := im.Bounds().Size()
x -= int(ax * float64(s.X))
y -= int(ay * float64(s.Y))
transformer := draw.BiLinear
transformer := dc.scaleStyle.transformer()
fx, fy := float64(x), float64(y)
m := dc.matrix.Translate(fx, fy)
s2d := f64.Aff3{m.XX, m.XY, m.X0, m.YX, m.YY, m.Y0}
Expand Down