diff --git a/converter.go b/converter.go index 48ce882..fa0cae1 100644 --- a/converter.go +++ b/converter.go @@ -43,7 +43,7 @@ func clampUint16(in int64) uint16 { return 0 } -func resizeGeneric(in image.Image, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { +func resizeGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 @@ -63,7 +63,7 @@ func resizeGeneric(in image.Image, out *image.NRGBA64, scale float64, coeffs []i case xi >= maxX: xi = maxX } - // Forward alpha-premultiplication (if needed) + r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA() rgba[0] += int64(coeff) * int64(r) @@ -75,34 +75,24 @@ func resizeGeneric(in image.Image, out *image.NRGBA64, scale float64, coeffs []i } offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - // Reverse alpha-premultiplication - r := rgba[0] / sum - g := rgba[1] / sum - b := rgba[2] / sum - a := rgba[3] / sum - if a != 0 { - r = r * 0xffff / a - g = g * 0xffff / a - b = b * 0xffff / a - } - value := clampUint16(r) + value := clampUint16(rgba[0] / sum) out.Pix[offset+0] = uint8(value >> 8) out.Pix[offset+1] = uint8(value) - value = clampUint16(g) + value = clampUint16(rgba[1] / sum) out.Pix[offset+2] = uint8(value >> 8) out.Pix[offset+3] = uint8(value) - value = clampUint16(b) + value = clampUint16(rgba[2] / sum) out.Pix[offset+4] = uint8(value >> 8) out.Pix[offset+5] = uint8(value) - value = clampUint16(a) + value = clampUint16(rgba[3] / sum) out.Pix[offset+6] = uint8(value >> 8) out.Pix[offset+7] = uint8(value) } } } -func resizeRGBA(in *image.RGBA, out *image.NRGBA, scale float64, coeffs []int16, offset []int, filterLength int) { +func resizeRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []int16, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 @@ -135,27 +125,16 @@ func resizeRGBA(in *image.RGBA, out *image.NRGBA, scale float64, coeffs []int16, } xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - // Reverse alpha-premultiplication - r := rgba[0] / sum - g := rgba[1] / sum - b := rgba[2] / sum - a := rgba[3] / sum - if a != 0 { - r = r * 0xff / a - g = g * 0xff / a - b = b * 0xff / a - } - - out.Pix[xo+0] = clampUint8(r) - out.Pix[xo+1] = clampUint8(g) - out.Pix[xo+2] = clampUint8(b) - out.Pix[xo+3] = clampUint8(a) + out.Pix[xo+0] = clampUint8(rgba[0] / sum) + out.Pix[xo+1] = clampUint8(rgba[1] / sum) + out.Pix[xo+2] = clampUint8(rgba[2] / sum) + out.Pix[xo+3] = clampUint8(rgba[3] / sum) } } } -func resizeNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []int16, offset []int, filterLength int) { +func resizeNRGBA(in *image.NRGBA, out *image.RGBA, scale float64, coeffs []int16, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 @@ -190,27 +169,16 @@ func resizeNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []int1 } xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - // Reverse alpha-premultiplication - r := rgba[0] / sum - g := rgba[1] / sum - b := rgba[2] / sum - a := rgba[3] / sum - if a != 0 { - r = r * 0xff / a - g = g * 0xff / a - b = b * 0xff / a - } - - out.Pix[xo+0] = clampUint8(r) - out.Pix[xo+1] = clampUint8(g) - out.Pix[xo+2] = clampUint8(b) - out.Pix[xo+3] = clampUint8(a) + out.Pix[xo+0] = clampUint8(rgba[0] / sum) + out.Pix[xo+1] = clampUint8(rgba[1] / sum) + out.Pix[xo+2] = clampUint8(rgba[2] / sum) + out.Pix[xo+3] = clampUint8(rgba[3] / sum) } } } -func resizeRGBA64(in *image.RGBA64, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { +func resizeRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 @@ -243,34 +211,24 @@ func resizeRGBA64(in *image.RGBA64, out *image.NRGBA64, scale float64, coeffs [] } xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - // Reverse alpha-premultiplication - r := rgba[0] / sum - g := rgba[1] / sum - b := rgba[2] / sum - a := rgba[3] / sum - if a != 0 { - r = r * 0xffff / a - g = g * 0xffff / a - b = b * 0xffff / a - } - value := clampUint16(r) + value := clampUint16(rgba[0] / sum) out.Pix[xo+0] = uint8(value >> 8) out.Pix[xo+1] = uint8(value) - value = clampUint16(g) + value = clampUint16(rgba[1] / sum) out.Pix[xo+2] = uint8(value >> 8) out.Pix[xo+3] = uint8(value) - value = clampUint16(b) + value = clampUint16(rgba[2] / sum) out.Pix[xo+4] = uint8(value >> 8) out.Pix[xo+5] = uint8(value) - value = clampUint16(a) + value = clampUint16(rgba[3] / sum) out.Pix[xo+6] = uint8(value >> 8) out.Pix[xo+7] = uint8(value) } } } -func resizeNRGBA64(in *image.NRGBA64, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { +func resizeNRGBA64(in *image.NRGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 @@ -305,27 +263,17 @@ func resizeNRGBA64(in *image.NRGBA64, out *image.NRGBA64, scale float64, coeffs } xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - // Reverse alpha-premultiplication - r := rgba[0] / sum - g := rgba[1] / sum - b := rgba[2] / sum - a := rgba[3] / sum - if a != 0 { - r = r * 0xffff / a - g = g * 0xffff / a - b = b * 0xffff / a - } - value := clampUint16(r) + value := clampUint16(rgba[0] / sum) out.Pix[xo+0] = uint8(value >> 8) out.Pix[xo+1] = uint8(value) - value = clampUint16(g) + value = clampUint16(rgba[1] / sum) out.Pix[xo+2] = uint8(value >> 8) out.Pix[xo+3] = uint8(value) - value = clampUint16(b) + value = clampUint16(rgba[2] / sum) out.Pix[xo+4] = uint8(value >> 8) out.Pix[xo+5] = uint8(value) - value = clampUint16(a) + value = clampUint16(rgba[3] / sum) out.Pix[xo+6] = uint8(value >> 8) out.Pix[xo+7] = uint8(value) } diff --git a/resize.go b/resize.go index c167243..57bd1fc 100644 --- a/resize.go +++ b/resize.go @@ -105,14 +105,14 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i switch input := img.(type) { case *image.RGBA: // 8-bit precision - temp := image.NewNRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA(image.Rect(0, 0, int(width), int(height))) + temp := image.NewRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) + 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(), taps, blur, scaleX, kernel) wg.Add(cpus) for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA) + slice := makeSlice(temp, i, cpus).(*image.RGBA) go func() { defer wg.Done() resizeRGBA(input, slice, scaleX, coeffs, offset, filterLength) @@ -124,24 +124,24 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i 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.NRGBA) + slice := makeSlice(result, i, cpus).(*image.RGBA) go func() { defer wg.Done() - resizeNRGBA(temp, slice, scaleY, coeffs, offset, filterLength) + resizeRGBA(temp, slice, scaleY, coeffs, offset, filterLength) }() } wg.Wait() return result case *image.NRGBA: // 8-bit precision - temp := image.NewNRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA(image.Rect(0, 0, int(width), int(height))) + temp := image.NewRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) + 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(), taps, blur, scaleX, kernel) wg.Add(cpus) for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA) + slice := makeSlice(temp, i, cpus).(*image.RGBA) go func() { defer wg.Done() resizeNRGBA(input, slice, scaleX, coeffs, offset, filterLength) @@ -153,10 +153,10 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i 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.NRGBA) + slice := makeSlice(result, i, cpus).(*image.RGBA) go func() { defer wg.Done() - resizeNRGBA(temp, slice, scaleY, coeffs, offset, filterLength) + resizeRGBA(temp, slice, scaleY, coeffs, offset, filterLength) }() } wg.Wait() @@ -194,14 +194,14 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i return result.YCbCr() case *image.RGBA64: // 16-bit precision - temp := image.NewNRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height))) + temp := image.NewRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) + 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(), taps, blur, scaleX, kernel) wg.Add(cpus) for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA64) + slice := makeSlice(temp, i, cpus).(*image.RGBA64) go func() { defer wg.Done() resizeRGBA64(input, slice, scaleX, coeffs, offset, filterLength) @@ -213,24 +213,24 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i 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.NRGBA64) + slice := makeSlice(result, i, cpus).(*image.RGBA64) go func() { defer wg.Done() - resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) + resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) }() } wg.Wait() return result case *image.NRGBA64: // 16-bit precision - temp := image.NewNRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height))) + temp := image.NewRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) + 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(), taps, blur, scaleX, kernel) wg.Add(cpus) for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA64) + slice := makeSlice(temp, i, cpus).(*image.RGBA64) go func() { defer wg.Done() resizeNRGBA64(input, slice, scaleX, coeffs, offset, filterLength) @@ -242,10 +242,10 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i 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.NRGBA64) + slice := makeSlice(result, i, cpus).(*image.RGBA64) go func() { defer wg.Done() - resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) + resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) }() } wg.Wait() @@ -310,14 +310,14 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i return result default: // 16-bit precision - temp := image.NewNRGBA64(image.Rect(0, 0, img.Bounds().Dy(), int(width))) - result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height))) + temp := image.NewRGBA64(image.Rect(0, 0, img.Bounds().Dy(), int(width))) + 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(), taps, blur, scaleX, kernel) wg.Add(cpus) for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA64) + slice := makeSlice(temp, i, cpus).(*image.RGBA64) go func() { defer wg.Done() resizeGeneric(img, slice, scaleX, coeffs, offset, filterLength) @@ -329,10 +329,10 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i 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.NRGBA64) + slice := makeSlice(result, i, cpus).(*image.RGBA64) go func() { defer wg.Done() - resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) + resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) }() } wg.Wait() diff --git a/resize_test.go b/resize_test.go index 2ab5145..d4b80be 100644 --- a/resize_test.go +++ b/resize_test.go @@ -56,7 +56,7 @@ func Test_SameColorWithRGBA(t *testing.T) { out := Resize(10, 10, img, Lanczos3) for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.NRGBA) + color := out.At(x, y).(color.RGBA) if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF { t.Errorf("%+v", color) } @@ -74,7 +74,7 @@ func Test_SameColorWithNRGBA(t *testing.T) { out := Resize(10, 10, img, Lanczos3) for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.NRGBA) + color := out.At(x, y).(color.RGBA) if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF { t.Errorf("%+v", color) } @@ -92,7 +92,7 @@ func Test_SameColorWithRGBA64(t *testing.T) { out := Resize(10, 10, img, Lanczos3) for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.NRGBA64) + color := out.At(x, y).(color.RGBA64) if color.R != 0x8000 || color.G != 0x8000 || color.B != 0x8000 || color.A != 0xFFFF { t.Errorf("%+v", color) } @@ -110,7 +110,7 @@ func Test_SameColorWithNRGBA64(t *testing.T) { out := Resize(10, 10, img, Lanczos3) for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.NRGBA64) + color := out.At(x, y).(color.RGBA64) if color.R != 0x8000 || color.G != 0x8000 || color.B != 0x8000 || color.A != 0xFFFF { t.Errorf("%+v", color) } @@ -204,8 +204,8 @@ func Test_ResizeWithPremultipliedAlpha(t *testing.T) { out := Resize(1, 2, img, MitchellNetravali) - outputColor := out.At(0, 0).(color.NRGBA) - if outputColor.R != 0xFF { + outputColor := out.At(0, 0).(color.RGBA) + if outputColor.R != 0x80 { t.Fail() } } @@ -213,8 +213,8 @@ func Test_ResizeWithPremultipliedAlpha(t *testing.T) { func Test_ResizeWithTranslucentColor(t *testing.T) { img := image.NewNRGBA(image.Rect(0, 0, 1, 2)) - // Set the pixel colors to an "invisible green" and white. - // After resizing, the green shouldn't be visible. + // Set the pixel colors to an "invisible green" and white. + // After resizing, the green shouldn't be visible. img.SetNRGBA(0, 0, color.NRGBA{0x00, 0xFF, 0x00, 0x00}) img.SetNRGBA(0, 1, color.NRGBA{0x00, 0x00, 0x00, 0xFF})