2012-08-02 21:59:40 +02:00
|
|
|
/*
|
|
|
|
Copyright (c) 2012, Jan Schlicht <jan.schlicht@gmail.com>
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any purpose
|
|
|
|
with or without fee is hereby granted, provided that the above copyright notice
|
|
|
|
and this permission notice appear in all copies.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
|
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
|
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
|
|
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
|
|
THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package resize
|
|
|
|
|
|
|
|
import (
|
2012-09-14 23:12:05 +02:00
|
|
|
"math"
|
2012-08-02 21:59:40 +02:00
|
|
|
)
|
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
func nearest(in float64) float64 {
|
|
|
|
if in >= -0.5 && in < 0.5 {
|
|
|
|
return 1
|
2012-08-02 21:59:40 +02:00
|
|
|
}
|
2014-07-19 13:19:31 +02:00
|
|
|
return 0
|
2012-08-02 21:59:40 +02:00
|
|
|
}
|
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
func linear(in float64) float64 {
|
|
|
|
in = math.Abs(in)
|
|
|
|
if in <= 1 {
|
|
|
|
return 1 - in
|
2014-01-28 18:48:08 +01:00
|
|
|
}
|
2014-07-19 13:19:31 +02:00
|
|
|
return 0
|
2014-01-28 18:48:08 +01:00
|
|
|
}
|
2012-09-04 18:49:04 +02:00
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
func cubic(in float64) float64 {
|
|
|
|
in = math.Abs(in)
|
|
|
|
if in <= 1 {
|
|
|
|
return in*in*(1.5*in-2.5) + 1.0
|
2012-09-04 18:49:04 +02:00
|
|
|
}
|
2014-07-19 13:19:31 +02:00
|
|
|
if in <= 2 {
|
|
|
|
return in*(in*(2.5-0.5*in)-4.0) + 2.0
|
2012-09-04 18:49:04 +02:00
|
|
|
}
|
2014-07-19 13:19:31 +02:00
|
|
|
return 0
|
2012-09-04 18:49:04 +02:00
|
|
|
}
|
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
func mitchellnetravali(in float64) float64 {
|
|
|
|
in = math.Abs(in)
|
|
|
|
if in <= 1 {
|
|
|
|
return (7.0*in*in*in - 12.0*in*in + 5.33333333333) * 0.16666666666
|
2012-09-04 18:49:04 +02:00
|
|
|
}
|
2014-07-19 13:19:31 +02:00
|
|
|
if in <= 2 {
|
|
|
|
return (-2.33333333333*in*in*in + 12.0*in*in - 20.0*in + 10.6666666667) * 0.16666666666
|
2012-09-21 20:02:25 +02:00
|
|
|
}
|
2014-07-19 13:19:31 +02:00
|
|
|
return 0
|
2012-09-04 18:49:04 +02:00
|
|
|
}
|
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
func sinc(x float64) float64 {
|
|
|
|
x = math.Abs(x) * math.Pi
|
|
|
|
if x >= 1.220703e-4 {
|
|
|
|
return math.Sin(x) / x
|
2012-09-21 20:02:25 +02:00
|
|
|
}
|
2014-07-19 13:19:31 +02:00
|
|
|
return 1
|
2012-09-14 23:12:05 +02:00
|
|
|
}
|
2012-09-04 18:49:04 +02:00
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
func lanczos2(in float64) float64 {
|
|
|
|
if in > -2 && in < 2 {
|
|
|
|
return sinc(in) * sinc(in*0.5)
|
|
|
|
}
|
|
|
|
return 0
|
2013-07-08 20:40:36 +02:00
|
|
|
}
|
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
func lanczos3(in float64) float64 {
|
|
|
|
if in > -3 && in < 3 {
|
|
|
|
return sinc(in) * sinc(in*0.3333333333333333)
|
|
|
|
}
|
|
|
|
return 0
|
2013-07-08 20:40:36 +02:00
|
|
|
}
|
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
// range [-256,256]
|
2014-08-20 20:54:59 +02:00
|
|
|
func createWeights8(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int16, []int, int) {
|
2014-07-19 13:19:31 +02:00
|
|
|
filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1))
|
|
|
|
filterFactor := math.Min(1./(blur*scale), 1)
|
|
|
|
|
|
|
|
coeffs := make([]int16, dy*filterLength)
|
2014-07-29 22:53:35 +02:00
|
|
|
start := make([]int, dy)
|
2014-07-19 13:19:31 +02:00
|
|
|
for y := 0; y < dy; y++ {
|
2015-03-19 20:52:55 +01:00
|
|
|
interpX := scale*(float64(y)+0.5) - 0.5
|
2014-07-29 22:53:35 +02:00
|
|
|
start[y] = int(interpX) - filterLength/2 + 1
|
2014-07-30 00:32:58 +02:00
|
|
|
interpX -= float64(start[y])
|
2014-07-19 13:19:31 +02:00
|
|
|
for i := 0; i < filterLength; i++ {
|
2014-07-30 00:32:58 +02:00
|
|
|
in := (interpX - float64(i)) * filterFactor
|
2014-07-19 13:19:31 +02:00
|
|
|
coeffs[y*filterLength+i] = int16(kernel(in) * 256)
|
2012-08-02 21:59:40 +02:00
|
|
|
}
|
2013-04-04 22:32:33 +02:00
|
|
|
}
|
2014-07-19 13:19:31 +02:00
|
|
|
|
2014-07-29 22:53:35 +02:00
|
|
|
return coeffs, start, filterLength
|
2013-04-04 22:32:33 +02:00
|
|
|
}
|
|
|
|
|
2014-07-19 13:19:31 +02:00
|
|
|
// range [-65536,65536]
|
2014-08-20 20:54:59 +02:00
|
|
|
func createWeights16(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int32, []int, int) {
|
2014-07-19 13:19:31 +02:00
|
|
|
filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1))
|
|
|
|
filterFactor := math.Min(1./(blur*scale), 1)
|
|
|
|
|
|
|
|
coeffs := make([]int32, dy*filterLength)
|
2014-07-29 22:53:35 +02:00
|
|
|
start := make([]int, dy)
|
2014-07-19 13:19:31 +02:00
|
|
|
for y := 0; y < dy; y++ {
|
2015-03-19 20:52:55 +01:00
|
|
|
interpX := scale*(float64(y)+0.5) - 0.5
|
2014-07-29 22:53:35 +02:00
|
|
|
start[y] = int(interpX) - filterLength/2 + 1
|
2014-07-30 00:32:58 +02:00
|
|
|
interpX -= float64(start[y])
|
2014-07-19 13:19:31 +02:00
|
|
|
for i := 0; i < filterLength; i++ {
|
2014-07-30 00:32:58 +02:00
|
|
|
in := (interpX - float64(i)) * filterFactor
|
2014-07-19 13:19:31 +02:00
|
|
|
coeffs[y*filterLength+i] = int32(kernel(in) * 65536)
|
2012-12-10 18:56:53 +01:00
|
|
|
}
|
2012-09-19 19:32:00 +02:00
|
|
|
}
|
2013-07-08 20:48:20 +02:00
|
|
|
|
2014-07-29 22:53:35 +02:00
|
|
|
return coeffs, start, filterLength
|
2013-07-08 20:48:20 +02:00
|
|
|
}
|
2014-07-30 00:32:58 +02:00
|
|
|
|
2014-08-20 20:54:59 +02:00
|
|
|
func createWeightsNearest(dy, filterLength int, blur, scale float64) ([]bool, []int, int) {
|
2014-07-30 00:32:58 +02:00
|
|
|
filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1))
|
|
|
|
filterFactor := math.Min(1./(blur*scale), 1)
|
|
|
|
|
|
|
|
coeffs := make([]bool, dy*filterLength)
|
|
|
|
start := make([]int, dy)
|
|
|
|
for y := 0; y < dy; y++ {
|
2015-03-19 20:52:55 +01:00
|
|
|
interpX := scale*(float64(y)+0.5) - 0.5
|
2014-07-30 00:32:58 +02:00
|
|
|
start[y] = int(interpX) - filterLength/2 + 1
|
|
|
|
interpX -= float64(start[y])
|
|
|
|
for i := 0; i < filterLength; i++ {
|
|
|
|
in := (interpX - float64(i)) * filterFactor
|
|
|
|
if in >= -0.5 && in < 0.5 {
|
|
|
|
coeffs[y*filterLength+i] = true
|
|
|
|
} else {
|
|
|
|
coeffs[y*filterLength+i] = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return coeffs, start, filterLength
|
|
|
|
}
|