From 14d51db8b485ef1604e853aa23e4f27f7299283e Mon Sep 17 00:00:00 2001 From: jst Date: Wed, 8 Aug 2012 21:32:51 +0200 Subject: [PATCH] Changed function signature to include error handling. Filters simplified. --- filters.go | 36 ++++++++++++----------------------- resize.go | 51 +++++++++++++++++++++++++------------------------- resize_test.go | 20 ++++++++++---------- 3 files changed, 47 insertions(+), 60 deletions(-) diff --git a/filters.go b/filters.go index 27c321f..4818a90 100644 --- a/filters.go +++ b/filters.go @@ -64,10 +64,10 @@ func Bilinear(x, y float32, img image.Image) color.RGBA64 { var row [2]RGBA var col [2]RGBA - row = [2]RGBA{toRGBA(img.At(xf, yf)), toRGBA(img.At(xf+1, yf))} - col[0] = linearInterp(x, &row) - row = [2]RGBA{toRGBA(img.At(xf, yf+1)), toRGBA(img.At(xf+1, yf+1))} - col[1] = linearInterp(x, &row) + for i := 0; i < 2; i++ { + row = [2]RGBA{toRGBA(img.At(xf, yf+i)), toRGBA(img.At(xf+1, yf+i))} + col[i] = linearInterp(x, &row) + } c := linearInterp(y, &col) 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 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))} - col[0] = cubicInterp(x, &row) - 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[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) + for i := 0; i < 4; i++ { + 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))} + col[i] = cubicInterp(x, &row) + } c := cubicInterp(y, &col) 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 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))} - col[0] = 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[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) + for i := 0; i < 6; i++ { + 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))} + col[i] = lanczos_x(x, &row) + } c := lanczos_x(y, &col) return color.RGBA64{c[0], c[1], c[2], c[3]} diff --git a/resize.go b/resize.go index a9bd798..089b81f 100644 --- a/resize.go +++ b/resize.go @@ -25,6 +25,7 @@ THIS SOFTWARE. package resize import ( + "errors" "image" "image/color" "runtime" @@ -46,28 +47,21 @@ func (t *Trans2) Eval(x, y float32) (u, v float32) { } // Calculate scaling factors using old and new image dimensions. -func calcFactors(w, h int, wo, ho float32) (sx, sy float32) { - if w <= 0 { - w = -1 - } - if h <= 0 { - h = -1 - } - - if w == -1 { - if h == -1 { - sx = 1.0 - sy = 1.0 +func calcFactors(width, height int, oldWidth, oldHeight float32) (scaleX, scaleY float32) { + if width == -1 { + if height == -1 { + scaleX = 1.0 + scaleY = 1.0 } else { - sy = ho / float32(h) - sx = sy + scaleY = oldHeight / float32(height) + scaleX = scaleY } } else { - sx = wo / float32(w) - if h == -1 { - sy = sx + scaleX = oldWidth / float32(width) + if height == -1 { + scaleY = scaleX } else { - sy = ho / float32(h) + scaleY = oldHeight / float32(height) } } 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 // the aspect ratio is that of the originating image. // The resizing algorithm uses channels for parallel computation. -func Resize(w int, h int, img image.Image, interp InterpolationFunction) image.Image { - b_old := img.Bounds() - w_old := float32(b_old.Dx()) - h_old := float32(b_old.Dy()) +func Resize(width, height int, img image.Image, interp InterpolationFunction) (out image.Image, err error) { + if width < -1 || height < -1 { + err = errors.New("Wrong width/height argument") + return + } + oldBounds := img.Bounds() + oldWidth := float32(oldBounds.Dx()) + oldHeight := float32(oldBounds.Dy()) - scaleX, scaleY := calcFactors(w, h, w_old, h_old) - t := Trans2{scaleX, 0, float32(b_old.Min.X), 0, scaleY, float32(b_old.Min.Y)} + scaleX, scaleY := calcFactors(width, height, oldWidth, oldHeight) + 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() 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++ { <-c } + out = m - return m + return } diff --git a/resize_test.go b/resize_test.go index f270bce..8dfd561 100644 --- a/resize_test.go +++ b/resize_test.go @@ -11,30 +11,30 @@ var img = image.NewGray16(image.Rect(0, 0, 3, 3)) func Test_Nearest(t *testing.T) { 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() } } func Test_Param1(t *testing.T) { - m := Resize(-1, -1, img, NearestNeighbor) - if m.Bounds() != img.Bounds() { + m, err := Resize(-1, -1, img, NearestNeighbor) + if err != nil || m.Bounds() != img.Bounds() { t.Fail() } } func Test_Param2(t *testing.T) { - m := Resize(-100, -1, img, NearestNeighbor) - if m.Bounds() != img.Bounds() { + _, err := Resize(-100, -1, img, NearestNeighbor) + if err == nil { t.Fail() } } func Test_Param3(t *testing.T) { - m := Resize(0, -1, img, NearestNeighbor) - if m.Bounds() != img.Bounds() { + m, err := Resize(0, -1, img, NearestNeighbor) + if err != nil || m.Bounds() != image.Rect(0, 0, 0, 0) { t.Fail() } } @@ -42,8 +42,8 @@ func Test_Param3(t *testing.T) { func Test_ZeroImg(t *testing.T) { zeroImg := image.NewGray16(image.Rect(0, 0, 0, 0)) - m := Resize(-1, -1, zeroImg, NearestNeighbor) - if m.Bounds() != zeroImg.Bounds() { + m, err := Resize(-1, -1, zeroImg, NearestNeighbor) + if err != nil || m.Bounds() != zeroImg.Bounds() { t.Fail() } }