From dd1c157427bffb531598079c27242f8ef9448a76 Mon Sep 17 00:00:00 2001 From: jst Date: Mon, 10 Dec 2012 18:56:53 +0100 Subject: [PATCH] Include kernel boundary check Filter kernels should yield Zero if they are evaluted outside their intended size. Though filterModel.Interpolate doesn't do this by design, it's better to include it anyways. --- filters.go | 28 ++++++++++++++++++++++------ resize.go | 13 ++++++------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/filters.go b/filters.go index 1ffcd25..87770e4 100644 --- a/filters.go +++ b/filters.go @@ -29,6 +29,7 @@ func clampToUint16(x float32) (y uint16) { if x < 0 { y = 0 } else if x > float32(0xfffe) { + // "else if x > float32(0xffff)" will cause overflows! y = 0xffff } return @@ -150,8 +151,14 @@ func NearestNeighbor(img image.Image, factor [2]float32) Filter { // Bilinear interpolation func Bilinear(img image.Image, factor [2]float32) Filter { - return createFilter(img, factor, 2, func(x float32) float32 { - return 1 - float32(math.Abs(float64(x))) + return createFilter(img, factor, 2, func(x float32) (y float32) { + absX := float32(math.Abs(float64(x))) + if absX <= 1 { + y = 1 - absX + } else { + y = 0 + } + return }) } @@ -161,8 +168,10 @@ func Bicubic(img image.Image, factor [2]float32) Filter { absX := float32(math.Abs(float64(x))) if absX <= 1 { y = absX*absX*(1.5*absX-2.5) + 1 - } else { + } else if absX <= 2 { y = absX*(absX*(2.5-0.5*absX)-4) + 2 + } else { + y = 0 } return }) @@ -174,16 +183,23 @@ func MitchellNetravali(img image.Image, factor [2]float32) Filter { absX := float32(math.Abs(float64(x))) if absX <= 1 { y = absX*absX*(7*absX-12) + 16.0/3 - } else { + } else if absX <= 2 { y = -(absX - 2) * (absX - 2) / 3 * (7*absX - 8) + } else { + y = 0 } return }) } func lanczosKernel(a uint) func(float32) float32 { - return func(x float32) float32 { - return float32(Sinc(float64(x))) * float32(Sinc(float64(x/float32(a)))) + return func(x float32) (y float32) { + if x > -float32(a) && x < float32(a) { + y = float32(Sinc(float64(x))) * float32(Sinc(float64(x/float32(a)))) + } else { + y = 0 + } + return } } diff --git a/resize.go b/resize.go index 7fd2ec9..a45b4fc 100644 --- a/resize.go +++ b/resize.go @@ -21,7 +21,7 @@ THIS SOFTWARE. // utilized in the computations. // // Example: -// imgResized := resize.Resize(1000, 0, imgOld, Lanczos3) +// imgResized := resize.Resize(1000, 0, imgOld, resize.MitchellNetravali) package resize import ( @@ -77,8 +77,8 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X; x < b.Max.X; x++ { u, v = t.Eval(float32(x), float32(y)) - //resizedImg.SetRGBA64(x, y, filter.Interpolate(u, v)) color = filter.Interpolate(u, v) + i := resizedImg.PixOffset(x, y) resizedImg.Pix[i+0] = uint8(color.R >> 8) resizedImg.Pix[i+1] = uint8(color.R) @@ -124,12 +124,11 @@ func calcFactors(width, height uint, oldWidth, oldHeight float32) (scaleX, scale // Set filter scaling factor to avoid moire patterns. // This is only useful in case of downscaling (factor>1). -func clampFactor(factor float32) (r float32) { - r = factor - if r < 1 { - r = 1 +func clampFactor(factor float32) float32 { + if factor < 1 { + factor = 1 } - return + return factor } // Set number of parallel jobs