~eliasnaur/gio-patches

gio: widget: use correct premultiplied alpha in Icon v1 PROPOSED

~egonelbre
~egonelbre: 1
 widget: use correct premultiplied alpha in Icon

 3 files changed, 40 insertions(+), 1 deletions(-)
#392782 apple.yml success
#392783 freebsd.yml success
#392784 linux.yml success
#392785 openbsd.yml success
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~eliasnaur/gio-patches/patches/19460/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH gio] widget: use correct premultiplied alpha in Icon Export this patch

~egonelbre
From: Egon Elbre <egonelbre@gmail.com>

iconvg seems to expect `srgb(c) * alpha` and not `srgb(c*alpha)`

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
---
 internal/f32color/rgba.go      | 18 ++++++++++++++++++
 internal/f32color/rgba_test.go | 21 +++++++++++++++++++++
 widget/icon.go                 |  2 +-
 3 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 internal/f32color/rgba_test.go

diff --git a/internal/f32color/rgba.go b/internal/f32color/rgba.go
index d1b7564..c71e63c 100644
--- a/internal/f32color/rgba.go
+++ b/internal/f32color/rgba.go
@@ -77,6 +77,24 @@ func NRGBAToRGBA(col color.NRGBA) color.RGBA {
	}
}

// NRGBAToRGBA_PostAlpha converts from non-premultiplied sRGB color to premultiplied sRGB color.
//
// Each component in the result is `sRGBToLinear(c) * alpha`, where `c`
// is the linear color.
func NRGBAToRGBA_PostAlpha(col color.NRGBA) color.RGBA {
	if col.A == 0xFF {
		return color.RGBA(col)
	} else if col.A == 0x00 {
		return color.RGBA{}
	}
	return color.RGBA{
		R: uint8(uint32(col.R) * uint32(col.A) / 0xFF),
		G: uint8(uint32(col.G) * uint32(col.A) / 0xFF),
		B: uint8(uint32(col.B) * uint32(col.A) / 0xFF),
		A: col.A,
	}
}

// RGBAToNRGBA converts from premultiplied sRGB color to non-premultiplied sRGB color.
func RGBAToNRGBA(col color.RGBA) color.NRGBA {
	if col.A == 0xFF {
diff --git a/internal/f32color/rgba_test.go b/internal/f32color/rgba_test.go
new file mode 100644
index 0000000..b19f3a8
--- /dev/null
+++ b/internal/f32color/rgba_test.go
@@ -0,0 +1,21 @@
package f32color

import (
	"image/color"
	"testing"
)

func TestNRGBAToRGBA_PostAlpha_Boundary(t *testing.T) {
	for col := 0; col <= 0xFF; col++ {
		for alpha := 0; alpha <= 0xFF; alpha++ {
			in := color.NRGBA{R: uint8(col), A: uint8(alpha)}
			premul := NRGBAToRGBA_PostAlpha(in)
			if premul.A != uint8(alpha) {
				t.Errorf("%v: got %v expected %v", in, premul.A, alpha)
			}
			if premul.R > premul.A {
				t.Errorf("%v: R=%v > A=%v", in, premul.R, premul.A)
			}
		}
	}
}
diff --git a/widget/icon.go b/widget/icon.go
index f6f88d3..952ffa7 100644
--- a/widget/icon.go
+++ b/widget/icon.go
@@ -51,7 +51,7 @@ func (ic *Icon) image(sz int) paint.ImageOp {
	img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: int(float32(sz) * dy / dx)}})
	var ico iconvg.Rasterizer
	ico.SetDstImage(img, img.Bounds(), draw.Src)
	m.Palette[0] = f32color.NRGBAToRGBA(ic.Color)
	m.Palette[0] = f32color.NRGBAToRGBA_PostAlpha(ic.Color)
	iconvg.Decode(&ico, ic.src, &iconvg.DecodeOptions{
		Palette: &m.Palette,
	})
-- 
2.26.2