Browse Source

Fix wrong boundary calculation (bug #17)

This fix doesn't currently work concurrently. This will be fixed in another commit.
jst 11 years ago
parent
commit
e950449c49
4 changed files with 121 additions and 149 deletions
  1. 53 69
      converter.go
  2. 6 6
      filters.go
  3. 37 49
      nearest.go
  4. 25 25
      resize.go

+ 53 - 69
converter.go

@@ -41,28 +41,26 @@ func clampUint16(in int64) uint16 {
 }
 
 func resizeGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Bounds().Dx(), in.Bounds().Dy())
 	newBounds := out.Bounds()
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var rgba [4]int64
 			var sum int64
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				coeff := coeffs[ci+i]
 				if coeff != 0 {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						break
-					case xi >= oldBounds.Max.X:
-						xi = oldBounds.Min.X
-					default:
-						xi = oldBounds.Max.X - 1
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = maxX
 					}
-					r, g, b, a := in.At(xi, x).RGBA()
+					r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA()
 					rgba[0] += int64(coeff) * int64(r)
 					rgba[1] += int64(coeff) * int64(g)
 					rgba[2] += int64(coeff) * int64(b)
@@ -89,29 +87,27 @@ func resizeGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []in
 }
 
 func resizeRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []int16, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X * 4
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 4
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var rgba [4]int32
 			var sum int32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				coeff := coeffs[ci+i]
 				if coeff != 0 {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						xi *= 4
-					case xi >= oldBounds.Max.X:
-						xi = maxX
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = 4 * maxX
 					default:
-						xi = minX
+						xi *= 4
 					}
 					rgba[0] += int32(coeff) * int32(row[xi+0])
 					rgba[1] += int32(coeff) * int32(row[xi+1])
@@ -131,29 +127,27 @@ func resizeRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []int16,
 }
 
 func resizeRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X * 8
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 8
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var rgba [4]int64
 			var sum int64
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				coeff := coeffs[ci+i]
 				if coeff != 0 {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						xi *= 8
-					case xi >= oldBounds.Max.X:
-						xi = maxX
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = 8 * maxX
 					default:
-						xi = minX
+						xi *= 8
 					}
 					rgba[0] += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1]))
 					rgba[1] += int64(coeff) * int64(uint16(row[xi+2])<<8|uint16(row[xi+3]))
@@ -181,29 +175,25 @@ func resizeRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []i
 }
 
 func resizeGray(in *image.Gray, out *image.Gray, scale float64, coeffs []int16, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1)
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var gray int32
 			var sum int32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				coeff := coeffs[ci+i]
 				if coeff != 0 {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						break
-					case xi >= oldBounds.Max.X:
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
 						xi = maxX
-					default:
-						xi = minX
 					}
 					gray += int32(coeff) * int32(row[xi])
 					sum += int32(coeff)
@@ -217,29 +207,27 @@ func resizeGray(in *image.Gray, out *image.Gray, scale float64, coeffs []int16,
 }
 
 func resizeGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []int32, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X * 2
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 2
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var gray int64
 			var sum int64
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				coeff := coeffs[ci+i]
 				if coeff != 0 {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						xi *= 2
-					case xi >= oldBounds.Max.X:
-						xi = maxX
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = 2 * maxX
 					default:
-						xi = minX
+						xi *= 2
 					}
 					gray += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1]))
 					sum += int64(coeff)
@@ -255,29 +243,27 @@ func resizeGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []i
 }
 
 func resizeYCbCr(in *ycc, out *ycc, scale float64, coeffs []int16, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X * 3
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 3
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var p [3]int32
 			var sum int32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				coeff := coeffs[ci+i]
 				if coeff != 0 {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						xi *= 3
-					case xi >= oldBounds.Max.X:
-						xi = maxX
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = 3 * maxX
 					default:
-						xi = minX
+						xi *= 3
 					}
 					p[0] += int32(coeff) * int32(row[xi+0])
 					p[1] += int32(coeff) * int32(row[xi+1])
@@ -295,28 +281,26 @@ func resizeYCbCr(in *ycc, out *ycc, scale float64, coeffs []int16, offset []int,
 }
 
 func nearestYCbCr(in *ycc, out *ycc, scale float64, coeffs []bool, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X * 3
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 3
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var p [3]float32
 			var sum float32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				if coeffs[ci+i] {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						xi *= 3
-					case xi >= oldBounds.Max.X:
-						xi = maxX
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = 3 * maxX
 					default:
-						xi = minX
+						xi *= 3
 					}
 					p[0] += float32(row[xi+0])
 					p[1] += float32(row[xi+1])

+ 6 - 6
filters.go

@@ -80,14 +80,14 @@ func lanczos3(in float64) float64 {
 }
 
 // range [-256,256]
-func createWeights8(dy, minx, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int16, []int, int) {
+func createWeights8(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int16, []int, int) {
 	filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1))
 	filterFactor := math.Min(1./(blur*scale), 1)
 
 	coeffs := make([]int16, dy*filterLength)
 	start := make([]int, dy)
 	for y := 0; y < dy; y++ {
-		interpX := scale*(float64(y)+0.5) + float64(minx)
+		interpX := scale * (float64(y) + 0.5)
 		start[y] = int(interpX) - filterLength/2 + 1
 		interpX -= float64(start[y])
 		for i := 0; i < filterLength; i++ {
@@ -100,14 +100,14 @@ func createWeights8(dy, minx, filterLength int, blur, scale float64, kernel func
 }
 
 // range [-65536,65536]
-func createWeights16(dy, minx, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int32, []int, int) {
+func createWeights16(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int32, []int, int) {
 	filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1))
 	filterFactor := math.Min(1./(blur*scale), 1)
 
 	coeffs := make([]int32, dy*filterLength)
 	start := make([]int, dy)
 	for y := 0; y < dy; y++ {
-		interpX := scale*(float64(y)+0.5) + float64(minx)
+		interpX := scale * (float64(y) + 0.5)
 		start[y] = int(interpX) - filterLength/2 + 1
 		interpX -= float64(start[y])
 		for i := 0; i < filterLength; i++ {
@@ -119,14 +119,14 @@ func createWeights16(dy, minx, filterLength int, blur, scale float64, kernel fun
 	return coeffs, start, filterLength
 }
 
-func createWeightsNearest(dy, minx, filterLength int, blur, scale float64) ([]bool, []int, int) {
+func createWeightsNearest(dy, filterLength int, blur, scale float64) ([]bool, []int, int) {
 	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++ {
-		interpX := scale*(float64(y)+0.5) + float64(minx)
+		interpX := scale * (float64(y) + 0.5)
 		start[y] = int(interpX) - filterLength/2 + 1
 		interpX -= float64(start[y])
 		for i := 0; i < filterLength; i++ {

+ 37 - 49
nearest.go

@@ -35,27 +35,25 @@ func floatToUint16(x float32) uint16 {
 }
 
 func nearestGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Bounds().Dx(), in.Bounds().Dy())
 	newBounds := out.Bounds()
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var rgba [4]float32
 			var sum float32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				if coeffs[ci+i] {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						break
-					case xi >= oldBounds.Max.X:
-						xi = oldBounds.Min.X
-					default:
-						xi = oldBounds.Max.X - 1
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = maxX
 					}
-					r, g, b, a := in.At(xi, x).RGBA()
+					r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA()
 					rgba[0] += float32(r)
 					rgba[1] += float32(g)
 					rgba[2] += float32(b)
@@ -82,28 +80,26 @@ func nearestGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []b
 }
 
 func nearestRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []bool, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X * 4
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 4
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var rgba [4]float32
 			var sum float32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				if coeffs[ci+i] {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						xi *= 4
-					case xi >= oldBounds.Max.X:
-						xi = maxX
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = 4 * maxX
 					default:
-						xi = minX
+						xi *= 4
 					}
 					rgba[0] += float32(row[xi+0])
 					rgba[1] += float32(row[xi+1])
@@ -123,28 +119,26 @@ func nearestRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []bool,
 }
 
 func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X * 8
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 8
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var rgba [4]float32
 			var sum float32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				if coeffs[ci+i] {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						xi *= 8
-					case xi >= oldBounds.Max.X:
-						xi = maxX
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = 8 * maxX
 					default:
-						xi = minX
+						xi *= 8
 					}
 					rgba[0] += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1]))
 					rgba[1] += float32(uint16(row[xi+2])<<8 | uint16(row[xi+3]))
@@ -172,28 +166,24 @@ func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []
 }
 
 func nearestGray(in *image.Gray, out *image.Gray, scale float64, coeffs []bool, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1)
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var gray float32
 			var sum float32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				if coeffs[ci+i] {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						break
-					case xi >= oldBounds.Max.X:
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
 						xi = maxX
-					default:
-						xi = minX
 					}
 					gray += float32(row[xi])
 					sum++
@@ -207,28 +197,26 @@ func nearestGray(in *image.Gray, out *image.Gray, scale float64, coeffs []bool,
 }
 
 func nearestGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []bool, offset []int, filterLength int) {
-	oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
 	newBounds := out.Bounds()
-	minX := oldBounds.Min.X * 2
-	maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 2
+	maxX := in.Bounds().Dx() - 1
 
 	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
-		row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
+		row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
 		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
 			var gray float32
 			var sum float32
-			start := offset[y]
+			start := offset[y-newBounds.Min.Y]
 			ci := (y - newBounds.Min.Y) * filterLength
 			for i := 0; i < filterLength; i++ {
 				if coeffs[ci+i] {
 					xi := start + i
 					switch {
-					case uint(xi) < uint(oldBounds.Max.X):
-						xi *= 2
-					case xi >= oldBounds.Max.X:
-						xi = maxX
+					case xi < 0:
+						xi = 0
+					case xi >= maxX:
+						xi = 2 * maxX
 					default:
-						xi = minX
+						xi *= 2
 					}
 					gray += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1]))
 					sum++

+ 25 - 25
resize.go

@@ -91,7 +91,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 	}
 
 	taps, kernel := interp.kernel()
-	cpus := runtime.NumCPU()
+	cpus := 1 //runtime.NumCPU() TODO
 	wg := sync.WaitGroup{}
 
 	// Generic access to image.Image is slow in tight loops.
@@ -103,7 +103,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		result := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
+		coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.RGBA)
@@ -115,7 +115,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
+		coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.RGBA)
@@ -133,7 +133,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio)
 		result := newYCC(image.Rect(0, 0, int(width), int(height)), input.SubsampleRatio)
 
-		coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
+		coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
 		in := imageYCbCrToYCC(input)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
@@ -145,7 +145,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		}
 		wg.Wait()
 
-		coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
+		coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*ycc)
@@ -162,7 +162,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
+		coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.RGBA64)
@@ -174,7 +174,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
+		coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.RGBA64)
@@ -191,7 +191,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		result := image.NewGray(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
+		coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.Gray)
@@ -203,7 +203,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
+		coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.Gray)
@@ -220,7 +220,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		result := image.NewGray16(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
+		coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.Gray16)
@@ -232,7 +232,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
+		coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.Gray16)
@@ -249,7 +249,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), img.Bounds().Min.X, taps, blur, scaleX, kernel)
+		coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.RGBA64)
@@ -261,7 +261,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
+		coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.RGBA64)
@@ -287,7 +287,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		result := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
+		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.RGBA)
@@ -299,7 +299,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
+		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.RGBA)
@@ -317,7 +317,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio)
 		result := newYCC(image.Rect(0, 0, int(width), int(height)), input.SubsampleRatio)
 
-		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
+		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
 		in := imageYCbCrToYCC(input)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
@@ -329,7 +329,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		}
 		wg.Wait()
 
-		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
+		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*ycc)
@@ -346,7 +346,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
+		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.RGBA64)
@@ -358,7 +358,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
+		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.RGBA64)
@@ -375,7 +375,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		result := image.NewGray(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
+		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.Gray)
@@ -387,7 +387,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
+		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.Gray)
@@ -404,7 +404,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		result := image.NewGray16(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
+		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.Gray16)
@@ -416,7 +416,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
+		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.Gray16)
@@ -433,7 +433,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
 
 		// horizontal filter, results in transposed temporary image
-		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), img.Bounds().Min.X, taps, blur, scaleX)
+		coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(temp, i, cpus).(*image.RGBA64)
@@ -445,7 +445,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
 		wg.Wait()
 
 		// horizontal filter on transposed image, result is not transposed
-		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
+		coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
 		wg.Add(cpus)
 		for i := 0; i < cpus; i++ {
 			slice := makeSlice(result, i, cpus).(*image.RGBA64)