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.
This commit is contained in:
parent
3e06045c3f
commit
dd1c157427
28
filters.go
28
filters.go
|
@ -29,6 +29,7 @@ func clampToUint16(x float32) (y uint16) {
|
||||||
if x < 0 {
|
if x < 0 {
|
||||||
y = 0
|
y = 0
|
||||||
} else if x > float32(0xfffe) {
|
} else if x > float32(0xfffe) {
|
||||||
|
// "else if x > float32(0xffff)" will cause overflows!
|
||||||
y = 0xffff
|
y = 0xffff
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -150,8 +151,14 @@ func NearestNeighbor(img image.Image, factor [2]float32) Filter {
|
||||||
|
|
||||||
// Bilinear interpolation
|
// Bilinear interpolation
|
||||||
func Bilinear(img image.Image, factor [2]float32) Filter {
|
func Bilinear(img image.Image, factor [2]float32) Filter {
|
||||||
return createFilter(img, factor, 2, func(x float32) float32 {
|
return createFilter(img, factor, 2, func(x float32) (y float32) {
|
||||||
return 1 - float32(math.Abs(float64(x)))
|
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)))
|
absX := float32(math.Abs(float64(x)))
|
||||||
if absX <= 1 {
|
if absX <= 1 {
|
||||||
y = absX*absX*(1.5*absX-2.5) + 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
|
y = absX*(absX*(2.5-0.5*absX)-4) + 2
|
||||||
|
} else {
|
||||||
|
y = 0
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
|
@ -174,16 +183,23 @@ func MitchellNetravali(img image.Image, factor [2]float32) Filter {
|
||||||
absX := float32(math.Abs(float64(x)))
|
absX := float32(math.Abs(float64(x)))
|
||||||
if absX <= 1 {
|
if absX <= 1 {
|
||||||
y = absX*absX*(7*absX-12) + 16.0/3
|
y = absX*absX*(7*absX-12) + 16.0/3
|
||||||
} else {
|
} else if absX <= 2 {
|
||||||
y = -(absX - 2) * (absX - 2) / 3 * (7*absX - 8)
|
y = -(absX - 2) * (absX - 2) / 3 * (7*absX - 8)
|
||||||
|
} else {
|
||||||
|
y = 0
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func lanczosKernel(a uint) func(float32) float32 {
|
func lanczosKernel(a uint) func(float32) float32 {
|
||||||
return func(x float32) float32 {
|
return func(x float32) (y float32) {
|
||||||
return float32(Sinc(float64(x))) * float32(Sinc(float64(x/float32(a))))
|
if x > -float32(a) && x < float32(a) {
|
||||||
|
y = float32(Sinc(float64(x))) * float32(Sinc(float64(x/float32(a))))
|
||||||
|
} else {
|
||||||
|
y = 0
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
resize.go
13
resize.go
|
@ -21,7 +21,7 @@ THIS SOFTWARE.
|
||||||
// utilized in the computations.
|
// utilized in the computations.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// imgResized := resize.Resize(1000, 0, imgOld, Lanczos3)
|
// imgResized := resize.Resize(1000, 0, imgOld, resize.MitchellNetravali)
|
||||||
package resize
|
package resize
|
||||||
|
|
||||||
import (
|
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 y := b.Min.Y; y < b.Max.Y; y++ {
|
||||||
for x := b.Min.X; x < b.Max.X; x++ {
|
for x := b.Min.X; x < b.Max.X; x++ {
|
||||||
u, v = t.Eval(float32(x), float32(y))
|
u, v = t.Eval(float32(x), float32(y))
|
||||||
//resizedImg.SetRGBA64(x, y, filter.Interpolate(u, v))
|
|
||||||
color = filter.Interpolate(u, v)
|
color = filter.Interpolate(u, v)
|
||||||
|
|
||||||
i := resizedImg.PixOffset(x, y)
|
i := resizedImg.PixOffset(x, y)
|
||||||
resizedImg.Pix[i+0] = uint8(color.R >> 8)
|
resizedImg.Pix[i+0] = uint8(color.R >> 8)
|
||||||
resizedImg.Pix[i+1] = uint8(color.R)
|
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.
|
// Set filter scaling factor to avoid moire patterns.
|
||||||
// This is only useful in case of downscaling (factor>1).
|
// This is only useful in case of downscaling (factor>1).
|
||||||
func clampFactor(factor float32) (r float32) {
|
func clampFactor(factor float32) float32 {
|
||||||
r = factor
|
if factor < 1 {
|
||||||
if r < 1 {
|
factor = 1
|
||||||
r = 1
|
|
||||||
}
|
}
|
||||||
return
|
return factor
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set number of parallel jobs
|
// Set number of parallel jobs
|
||||||
|
|
Loading…
Reference in New Issue
Block a user