From 5a6676c19e02828eb7c74cc5b7cde3297267eca2 Mon Sep 17 00:00:00 2001 From: nfnt Date: Tue, 12 May 2015 15:18:07 +0200 Subject: [PATCH 1/3] Add test case for input data with pre-multiplied-alpha. --- resize_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/resize_test.go b/resize_test.go index 3ba03f2..487a69d 100644 --- a/resize_test.go +++ b/resize_test.go @@ -2,6 +2,7 @@ package resize import ( "image" + "fmt" "image/color" "runtime" "testing" @@ -85,6 +86,22 @@ func Test_SameSizeReturnsOriginal(t *testing.T) { } } +func Test_ResizeWithPremultipliedAlpha(t *testing.T) { + img := image.NewRGBA(image.Rect(0, 0, 1, 4)) + for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { + // 0x80 = 0.5 * 0xFF. + img.SetRGBA(0, y, color.RGBA{0x80, 0x80, 0x80, 0x80}) + } + + out := Resize(1, 2, img, MitchellNetravali) + + fmt.Println(out) + outputColor := out.At(0,0).(color.NRGBA) + if outputColor.R != 0xFF { + t.Fail() + } +} + const ( // Use a small image size for benchmarks. We don't want memory performance // to affect the benchmark results. From c3c062672a859426c8583e197795e67150a01a89 Mon Sep 17 00:00:00 2001 From: nfnt Date: Tue, 12 May 2015 15:19:11 +0200 Subject: [PATCH 2/3] Reverse alpha-premultiplication for image.RGBA, image.RGBA64 and generic images types. --- converter.go | 59 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/converter.go b/converter.go index f4d9d0f..84bd284 100644 --- a/converter.go +++ b/converter.go @@ -64,6 +64,17 @@ func resizeGeneric(in image.Image, out *image.NRGBA64, scale float64, coeffs []i xi = maxX } r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA() + + // reverse alpha-premultiplication. + if a != 0 { + r *= 0xffff + r /= a + g *= 0xffff + g /= a + b *= 0xffff + b /= a + } + rgba[0] += int64(coeff) * int64(r) rgba[1] += int64(coeff) * int64(g) rgba[2] += int64(coeff) * int64(b) @@ -112,10 +123,26 @@ func resizeRGBA(in *image.RGBA, out *image.NRGBA, scale float64, coeffs []int16, default: xi = 0 } - rgba[0] += int32(coeff) * int32(row[xi+0]) - rgba[1] += int32(coeff) * int32(row[xi+1]) - rgba[2] += int32(coeff) * int32(row[xi+2]) - rgba[3] += int32(coeff) * int32(row[xi+3]) + + r := uint32(row[xi+0]) + g := uint32(row[xi+1]) + b := uint32(row[xi+2]) + a := uint32(row[xi+3]) + + // reverse alpha-premultiplication. + if a != 0 { + r *= 0xffff + r /= a + g *= 0xffff + g /= a + b *= 0xffff + b /= a + } + + rgba[0] += int32(coeff) * int32(r) + rgba[1] += int32(coeff) * int32(g) + rgba[2] += int32(coeff) * int32(b) + rgba[3] += int32(coeff) * int32(a) sum += int32(coeff) } } @@ -192,10 +219,26 @@ func resizeRGBA64(in *image.RGBA64, out *image.NRGBA64, scale float64, coeffs [] default: xi = 0 } - 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])) - rgba[2] += int64(coeff) * int64(uint16(row[xi+4])<<8|uint16(row[xi+5])) - rgba[3] += int64(coeff) * int64(uint16(row[xi+6])<<8|uint16(row[xi+7])) + + r := uint32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) + g := uint32(uint16(row[xi+2])<<8 | uint16(row[xi+3])) + b := uint32(uint16(row[xi+4])<<8 | uint16(row[xi+5])) + a := uint32(uint16(row[xi+6])<<8 | uint16(row[xi+7])) + + // reverse alpha-premultiplication. + if a != 0 { + r *= 0xffff + r /= a + g *= 0xffff + g /= a + b *= 0xffff + b /= a + } + + rgba[0] += int64(coeff) * int64(r) + rgba[1] += int64(coeff) * int64(g) + rgba[2] += int64(coeff) * int64(b) + rgba[3] += int64(coeff) * int64(a) sum += int64(coeff) } } From 563154816f2ab7ceb8117c7a6e35c359d64eb76c Mon Sep 17 00:00:00 2001 From: nfnt Date: Tue, 12 May 2015 15:24:41 +0200 Subject: [PATCH 3/3] Remove debugging directives. --- resize_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resize_test.go b/resize_test.go index 487a69d..d5eb6db 100644 --- a/resize_test.go +++ b/resize_test.go @@ -2,7 +2,6 @@ package resize import ( "image" - "fmt" "image/color" "runtime" "testing" @@ -95,8 +94,7 @@ func Test_ResizeWithPremultipliedAlpha(t *testing.T) { out := Resize(1, 2, img, MitchellNetravali) - fmt.Println(out) - outputColor := out.At(0,0).(color.NRGBA) + outputColor := out.At(0, 0).(color.NRGBA) if outputColor.R != 0xFF { t.Fail() }