summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/disintegration/imaging/resize.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/disintegration/imaging/resize.go')
-rw-r--r--vendor/github.com/disintegration/imaging/resize.go132
1 files changed, 69 insertions, 63 deletions
diff --git a/vendor/github.com/disintegration/imaging/resize.go b/vendor/github.com/disintegration/imaging/resize.go
index b21eed544..937f63fe9 100644
--- a/vendor/github.com/disintegration/imaging/resize.go
+++ b/vendor/github.com/disintegration/imaging/resize.go
@@ -5,17 +5,12 @@ import (
"math"
)
-type iwpair struct {
- i int
- w int32
+type indexWeight struct {
+ index int
+ weight float64
}
-type pweights struct {
- iwpairs []iwpair
- wsum int32
-}
-
-func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
+func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight {
du := float64(srcSize) / float64(dstSize)
scale := du
if scale < 1.0 {
@@ -23,7 +18,7 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
}
ru := math.Ceil(scale * filter.Support)
- out := make([]pweights, dstSize)
+ out := make([][]indexWeight, dstSize)
for v := 0; v < dstSize; v++ {
fu := (float64(v)+0.5)*du - 0.5
@@ -37,15 +32,19 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) []pweights {
endu = srcSize - 1
}
- wsum := int32(0)
+ var sum float64
for u := startu; u <= endu; u++ {
- w := int32(0xff * filter.Kernel((float64(u)-fu)/scale))
+ w := filter.Kernel((float64(u) - fu) / scale)
if w != 0 {
- wsum += w
- out[v].iwpairs = append(out[v].iwpairs, iwpair{u, w})
+ sum += w
+ out[v] = append(out[v], indexWeight{index: u, weight: w})
+ }
+ }
+ if sum != 0 {
+ for i := range out[v] {
+ out[v][i].weight /= sum
}
}
- out[v].wsum = wsum
}
return out
@@ -127,22 +126,26 @@ func resizeHorizontal(src *image.NRGBA, width int, filter ResampleFilter) *image
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
+ i0 := dstY * src.Stride
+ j0 := dstY * dst.Stride
for dstX := 0; dstX < dstW; dstX++ {
- var c [4]int64
- for _, iw := range weights[dstX].iwpairs {
- i := dstY*src.Stride + iw.i*4
- a := int64(src.Pix[i+3]) * int64(iw.w)
- c[0] += int64(src.Pix[i+0]) * a
- c[1] += int64(src.Pix[i+1]) * a
- c[2] += int64(src.Pix[i+2]) * a
- c[3] += a
+ var r, g, b, a float64
+ for _, w := range weights[dstX] {
+ i := i0 + w.index*4
+ aw := float64(src.Pix[i+3]) * w.weight
+ r += float64(src.Pix[i+0]) * aw
+ g += float64(src.Pix[i+1]) * aw
+ b += float64(src.Pix[i+2]) * aw
+ a += aw
+ }
+ if a != 0 {
+ aInv := 1 / a
+ j := j0 + dstX*4
+ dst.Pix[j+0] = clamp(r * aInv)
+ dst.Pix[j+1] = clamp(g * aInv)
+ dst.Pix[j+2] = clamp(b * aInv)
+ dst.Pix[j+3] = clamp(a)
}
- j := dstY*dst.Stride + dstX*4
- sum := weights[dstX].wsum
- dst.Pix[j+0] = clampint32(int32(float64(c[0])/float64(c[3]) + 0.5))
- dst.Pix[j+1] = clampint32(int32(float64(c[1])/float64(c[3]) + 0.5))
- dst.Pix[j+2] = clampint32(int32(float64(c[2])/float64(c[3]) + 0.5))
- dst.Pix[j+3] = clampint32(int32(float64(c[3])/float64(sum) + 0.5))
}
}
})
@@ -163,33 +166,33 @@ func resizeVertical(src *image.NRGBA, height int, filter ResampleFilter) *image.
weights := precomputeWeights(dstH, srcH, filter)
parallel(dstW, func(partStart, partEnd int) {
-
for dstX := partStart; dstX < partEnd; dstX++ {
for dstY := 0; dstY < dstH; dstY++ {
- var c [4]int64
- for _, iw := range weights[dstY].iwpairs {
- i := iw.i*src.Stride + dstX*4
- a := int64(src.Pix[i+3]) * int64(iw.w)
- c[0] += int64(src.Pix[i+0]) * a
- c[1] += int64(src.Pix[i+1]) * a
- c[2] += int64(src.Pix[i+2]) * a
- c[3] += a
+ var r, g, b, a float64
+ for _, w := range weights[dstY] {
+ i := w.index*src.Stride + dstX*4
+ aw := float64(src.Pix[i+3]) * w.weight
+ r += float64(src.Pix[i+0]) * aw
+ g += float64(src.Pix[i+1]) * aw
+ b += float64(src.Pix[i+2]) * aw
+ a += aw
+ }
+ if a != 0 {
+ aInv := 1 / a
+ j := dstY*dst.Stride + dstX*4
+ dst.Pix[j+0] = clamp(r * aInv)
+ dst.Pix[j+1] = clamp(g * aInv)
+ dst.Pix[j+2] = clamp(b * aInv)
+ dst.Pix[j+3] = clamp(a)
}
- j := dstY*dst.Stride + dstX*4
- sum := weights[dstY].wsum
- dst.Pix[j+0] = clampint32(int32(float64(c[0])/float64(c[3]) + 0.5))
- dst.Pix[j+1] = clampint32(int32(float64(c[1])/float64(c[3]) + 0.5))
- dst.Pix[j+2] = clampint32(int32(float64(c[2])/float64(c[3]) + 0.5))
- dst.Pix[j+3] = clampint32(int32(float64(c[3])/float64(sum) + 0.5))
}
}
-
})
return dst
}
-// fast nearest-neighbor resize, no filtering
+// resizeNearest is a fast nearest-neighbor resize, no filtering.
func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
dstW, dstH := width, height
@@ -205,13 +208,16 @@ func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
parallel(dstH, func(partStart, partEnd int) {
for dstY := partStart; dstY < partEnd; dstY++ {
- fy := (float64(dstY)+0.5)*dy - 0.5
+ srcY := int((float64(dstY) + 0.5) * dy)
+ if srcY > srcH-1 {
+ srcY = srcH - 1
+ }
for dstX := 0; dstX < dstW; dstX++ {
- fx := (float64(dstX)+0.5)*dx - 0.5
-
- srcX := int(math.Min(math.Max(math.Floor(fx+0.5), 0.0), float64(srcW)))
- srcY := int(math.Min(math.Max(math.Floor(fy+0.5), 0.0), float64(srcH)))
+ srcX := int((float64(dstX) + 0.5) * dx)
+ if srcX > srcW-1 {
+ srcX = srcW - 1
+ }
srcOff := srcY*src.Stride + srcX*4
dstOff := dstY*dst.Stride + dstX*4
@@ -326,7 +332,7 @@ func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image
return Fill(img, width, height, Center, filter)
}
-// Resample filter struct. It can be used to make custom filters.
+// ResampleFilter is a resampling filter struct. It can be used to define custom filters.
//
// Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali,
// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine.
@@ -361,7 +367,7 @@ type ResampleFilter struct {
Kernel func(float64) float64
}
-// Nearest-neighbor filter, no anti-aliasing.
+// NearestNeighbor is a nearest-neighbor filter (no anti-aliasing).
var NearestNeighbor ResampleFilter
// Box filter (averaging pixels).
@@ -373,37 +379,37 @@ var Linear ResampleFilter
// Hermite cubic spline filter (BC-spline; B=0; C=0).
var Hermite ResampleFilter
-// Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
+// MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
var MitchellNetravali ResampleFilter
-// Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
+// CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
var CatmullRom ResampleFilter
-// Cubic B-spline - smooth cubic filter (BC-spline; B=1; C=0).
+// BSpline is a smooth cubic filter (BC-spline; B=1; C=0).
var BSpline ResampleFilter
-// Gaussian Blurring Filter.
+// Gaussian is a Gaussian blurring Filter.
var Gaussian ResampleFilter
-// Bartlett-windowed sinc filter (3 lobes).
+// Bartlett is a Bartlett-windowed sinc filter (3 lobes).
var Bartlett ResampleFilter
// Lanczos filter (3 lobes).
var Lanczos ResampleFilter
-// Hann-windowed sinc filter (3 lobes).
+// Hann is a Hann-windowed sinc filter (3 lobes).
var Hann ResampleFilter
-// Hamming-windowed sinc filter (3 lobes).
+// Hamming is a Hamming-windowed sinc filter (3 lobes).
var Hamming ResampleFilter
-// Blackman-windowed sinc filter (3 lobes).
+// Blackman is a Blackman-windowed sinc filter (3 lobes).
var Blackman ResampleFilter
-// Welch-windowed sinc filter (parabolic window, 3 lobes).
+// Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes).
var Welch ResampleFilter
-// Cosine-windowed sinc filter (3 lobes).
+// Cosine is a Cosine-windowed sinc filter (3 lobes).
var Cosine ResampleFilter
func bcspline(x, b, c float64) float64 {