mirror of https://github.com/status-im/resize.git
Changed function signature to include error handling. Filters simplified.
This commit is contained in:
parent
d573c463cb
commit
14d51db8b4
36
filters.go
36
filters.go
|
@ -64,10 +64,10 @@ func Bilinear(x, y float32, img image.Image) color.RGBA64 {
|
||||||
|
|
||||||
var row [2]RGBA
|
var row [2]RGBA
|
||||||
var col [2]RGBA
|
var col [2]RGBA
|
||||||
row = [2]RGBA{toRGBA(img.At(xf, yf)), toRGBA(img.At(xf+1, yf))}
|
for i := 0; i < 2; i++ {
|
||||||
col[0] = linearInterp(x, &row)
|
row = [2]RGBA{toRGBA(img.At(xf, yf+i)), toRGBA(img.At(xf+1, yf+i))}
|
||||||
row = [2]RGBA{toRGBA(img.At(xf, yf+1)), toRGBA(img.At(xf+1, yf+1))}
|
col[i] = linearInterp(x, &row)
|
||||||
col[1] = linearInterp(x, &row)
|
}
|
||||||
|
|
||||||
c := linearInterp(y, &col)
|
c := linearInterp(y, &col)
|
||||||
return color.RGBA64{c[0], c[1], c[2], c[3]}
|
return color.RGBA64{c[0], c[1], c[2], c[3]}
|
||||||
|
@ -88,14 +88,10 @@ func Bicubic(x, y float32, img image.Image) color.RGBA64 {
|
||||||
|
|
||||||
var row [4]RGBA
|
var row [4]RGBA
|
||||||
var col [4]RGBA
|
var col [4]RGBA
|
||||||
row = [4]RGBA{toRGBA(img.At(xf-1, yf-1)), toRGBA(img.At(xf, yf-1)), toRGBA(img.At(xf+1, yf-1)), toRGBA(img.At(xf+2, yf-1))}
|
for i := 0; i < 4; i++ {
|
||||||
col[0] = cubicInterp(x, &row)
|
row = [4]RGBA{toRGBA(img.At(xf-1, yf+i-1)), toRGBA(img.At(xf, yf+i-1)), toRGBA(img.At(xf+1, yf+i-1)), toRGBA(img.At(xf+2, yf+i-1))}
|
||||||
row = [4]RGBA{toRGBA(img.At(xf-1, yf)), toRGBA(img.At(xf, yf)), toRGBA(img.At(xf+1, yf)), toRGBA(img.At(xf+2, yf))}
|
col[i] = cubicInterp(x, &row)
|
||||||
col[1] = cubicInterp(x, &row)
|
}
|
||||||
row = [4]RGBA{toRGBA(img.At(xf-1, yf+1)), toRGBA(img.At(xf, yf+1)), toRGBA(img.At(xf+1, yf+1)), toRGBA(img.At(xf+2, yf+1))}
|
|
||||||
col[2] = cubicInterp(x, &row)
|
|
||||||
row = [4]RGBA{toRGBA(img.At(xf-1, yf+2)), toRGBA(img.At(xf, yf+2)), toRGBA(img.At(xf+1, yf+2)), toRGBA(img.At(xf+2, yf+2))}
|
|
||||||
col[3] = cubicInterp(x, &row)
|
|
||||||
|
|
||||||
c := cubicInterp(y, &col)
|
c := cubicInterp(y, &col)
|
||||||
return color.RGBA64{c[0], c[1], c[2], c[3]}
|
return color.RGBA64{c[0], c[1], c[2], c[3]}
|
||||||
|
@ -124,18 +120,10 @@ func Lanczos3(x, y float32, img image.Image) color.RGBA64 {
|
||||||
|
|
||||||
var row [6]RGBA
|
var row [6]RGBA
|
||||||
var col [6]RGBA
|
var col [6]RGBA
|
||||||
row = [6]RGBA{toRGBA(img.At(xf-2, yf-2)), toRGBA(img.At(xf-1, yf-2)), toRGBA(img.At(xf, yf-2)), toRGBA(img.At(xf+1, yf-2)), toRGBA(img.At(xf+2, yf-2)), toRGBA(img.At(xf+3, yf-2))}
|
for i := 0; i < 6; i++ {
|
||||||
col[0] = lanczos_x(x, &row)
|
row = [6]RGBA{toRGBA(img.At(xf-2, yf+i-2)), toRGBA(img.At(xf-1, yf+i-2)), toRGBA(img.At(xf, yf+i-2)), toRGBA(img.At(xf+1, yf+i-2)), toRGBA(img.At(xf+2, yf+i-2)), toRGBA(img.At(xf+3, yf+i-2))}
|
||||||
row = [6]RGBA{toRGBA(img.At(xf-2, yf-1)), toRGBA(img.At(xf-1, yf-1)), toRGBA(img.At(xf, yf-1)), toRGBA(img.At(xf+1, yf-1)), toRGBA(img.At(xf+2, yf-1)), toRGBA(img.At(xf+3, yf-1))}
|
col[i] = lanczos_x(x, &row)
|
||||||
col[1] = lanczos_x(x, &row)
|
}
|
||||||
row = [6]RGBA{toRGBA(img.At(xf-2, yf)), toRGBA(img.At(xf-1, yf)), toRGBA(img.At(xf, yf)), toRGBA(img.At(xf+1, yf)), toRGBA(img.At(xf+2, yf)), toRGBA(img.At(xf+3, yf))}
|
|
||||||
col[2] = lanczos_x(x, &row)
|
|
||||||
row = [6]RGBA{toRGBA(img.At(xf-2, yf+1)), toRGBA(img.At(xf-1, yf+1)), toRGBA(img.At(xf, yf+1)), toRGBA(img.At(xf+1, yf+1)), toRGBA(img.At(xf+2, yf+1)), toRGBA(img.At(xf+3, yf+1))}
|
|
||||||
col[3] = lanczos_x(x, &row)
|
|
||||||
row = [6]RGBA{toRGBA(img.At(xf-2, yf+2)), toRGBA(img.At(xf-1, yf+2)), toRGBA(img.At(xf, yf+2)), toRGBA(img.At(xf+1, yf+2)), toRGBA(img.At(xf+2, yf+2)), toRGBA(img.At(xf+3, yf+2))}
|
|
||||||
col[4] = lanczos_x(x, &row)
|
|
||||||
row = [6]RGBA{toRGBA(img.At(xf-2, yf+3)), toRGBA(img.At(xf-1, yf+3)), toRGBA(img.At(xf, yf+3)), toRGBA(img.At(xf+1, yf+3)), toRGBA(img.At(xf+2, yf+3)), toRGBA(img.At(xf+3, yf+3))}
|
|
||||||
col[5] = lanczos_x(x, &row)
|
|
||||||
|
|
||||||
c := lanczos_x(y, &col)
|
c := lanczos_x(y, &col)
|
||||||
return color.RGBA64{c[0], c[1], c[2], c[3]}
|
return color.RGBA64{c[0], c[1], c[2], c[3]}
|
||||||
|
|
51
resize.go
51
resize.go
|
@ -25,6 +25,7 @@ THIS SOFTWARE.
|
||||||
package resize
|
package resize
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -46,28 +47,21 @@ func (t *Trans2) Eval(x, y float32) (u, v float32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate scaling factors using old and new image dimensions.
|
// Calculate scaling factors using old and new image dimensions.
|
||||||
func calcFactors(w, h int, wo, ho float32) (sx, sy float32) {
|
func calcFactors(width, height int, oldWidth, oldHeight float32) (scaleX, scaleY float32) {
|
||||||
if w <= 0 {
|
if width == -1 {
|
||||||
w = -1
|
if height == -1 {
|
||||||
}
|
scaleX = 1.0
|
||||||
if h <= 0 {
|
scaleY = 1.0
|
||||||
h = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
if w == -1 {
|
|
||||||
if h == -1 {
|
|
||||||
sx = 1.0
|
|
||||||
sy = 1.0
|
|
||||||
} else {
|
} else {
|
||||||
sy = ho / float32(h)
|
scaleY = oldHeight / float32(height)
|
||||||
sx = sy
|
scaleX = scaleY
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sx = wo / float32(w)
|
scaleX = oldWidth / float32(width)
|
||||||
if h == -1 {
|
if height == -1 {
|
||||||
sy = sx
|
scaleY = scaleX
|
||||||
} else {
|
} else {
|
||||||
sy = ho / float32(h)
|
scaleY = oldHeight / float32(height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -82,15 +76,19 @@ type InterpolationFunction func(float32, float32, image.Image) color.RGBA64
|
||||||
// If one of the parameters w or h is set to -1, its size will be calculated so that
|
// If one of the parameters w or h is set to -1, its size will be calculated so that
|
||||||
// the aspect ratio is that of the originating image.
|
// the aspect ratio is that of the originating image.
|
||||||
// The resizing algorithm uses channels for parallel computation.
|
// The resizing algorithm uses channels for parallel computation.
|
||||||
func Resize(w int, h int, img image.Image, interp InterpolationFunction) image.Image {
|
func Resize(width, height int, img image.Image, interp InterpolationFunction) (out image.Image, err error) {
|
||||||
b_old := img.Bounds()
|
if width < -1 || height < -1 {
|
||||||
w_old := float32(b_old.Dx())
|
err = errors.New("Wrong width/height argument")
|
||||||
h_old := float32(b_old.Dy())
|
return
|
||||||
|
}
|
||||||
|
oldBounds := img.Bounds()
|
||||||
|
oldWidth := float32(oldBounds.Dx())
|
||||||
|
oldHeight := float32(oldBounds.Dy())
|
||||||
|
|
||||||
scaleX, scaleY := calcFactors(w, h, w_old, h_old)
|
scaleX, scaleY := calcFactors(width, height, oldWidth, oldHeight)
|
||||||
t := Trans2{scaleX, 0, float32(b_old.Min.X), 0, scaleY, float32(b_old.Min.Y)}
|
t := Trans2{scaleX, 0, float32(oldBounds.Min.X), 0, scaleY, float32(oldBounds.Min.Y)}
|
||||||
|
|
||||||
m := image.NewRGBA64(image.Rect(0, 0, int(w_old/scaleX), int(h_old/scaleY)))
|
m := image.NewRGBA64(image.Rect(0, 0, int(oldWidth/scaleX), int(oldHeight/scaleY)))
|
||||||
b := m.Bounds()
|
b := m.Bounds()
|
||||||
|
|
||||||
c := make(chan int, NCPU)
|
c := make(chan int, NCPU)
|
||||||
|
@ -110,6 +108,7 @@ func Resize(w int, h int, img image.Image, interp InterpolationFunction) image.I
|
||||||
for i := 0; i < NCPU; i++ {
|
for i := 0; i < NCPU; i++ {
|
||||||
<-c
|
<-c
|
||||||
}
|
}
|
||||||
|
out = m
|
||||||
|
|
||||||
return m
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,30 +11,30 @@ var img = image.NewGray16(image.Rect(0, 0, 3, 3))
|
||||||
func Test_Nearest(t *testing.T) {
|
func Test_Nearest(t *testing.T) {
|
||||||
img.Set(1, 1, color.White)
|
img.Set(1, 1, color.White)
|
||||||
|
|
||||||
m := Resize(6, -1, img, NearestNeighbor)
|
m, err := Resize(6, -1, img, NearestNeighbor)
|
||||||
|
|
||||||
if m.At(2, 2) != m.At(3, 3) {
|
if err != nil || m.At(2, 2) != m.At(3, 3) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Param1(t *testing.T) {
|
func Test_Param1(t *testing.T) {
|
||||||
m := Resize(-1, -1, img, NearestNeighbor)
|
m, err := Resize(-1, -1, img, NearestNeighbor)
|
||||||
if m.Bounds() != img.Bounds() {
|
if err != nil || m.Bounds() != img.Bounds() {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Param2(t *testing.T) {
|
func Test_Param2(t *testing.T) {
|
||||||
m := Resize(-100, -1, img, NearestNeighbor)
|
_, err := Resize(-100, -1, img, NearestNeighbor)
|
||||||
if m.Bounds() != img.Bounds() {
|
if err == nil {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Param3(t *testing.T) {
|
func Test_Param3(t *testing.T) {
|
||||||
m := Resize(0, -1, img, NearestNeighbor)
|
m, err := Resize(0, -1, img, NearestNeighbor)
|
||||||
if m.Bounds() != img.Bounds() {
|
if err != nil || m.Bounds() != image.Rect(0, 0, 0, 0) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,8 @@ func Test_Param3(t *testing.T) {
|
||||||
func Test_ZeroImg(t *testing.T) {
|
func Test_ZeroImg(t *testing.T) {
|
||||||
zeroImg := image.NewGray16(image.Rect(0, 0, 0, 0))
|
zeroImg := image.NewGray16(image.Rect(0, 0, 0, 0))
|
||||||
|
|
||||||
m := Resize(-1, -1, zeroImg, NearestNeighbor)
|
m, err := Resize(-1, -1, zeroImg, NearestNeighbor)
|
||||||
if m.Bounds() != zeroImg.Bounds() {
|
if err != nil || m.Bounds() != zeroImg.Bounds() {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue