mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
graphics: Add ColorM.Apply (#432)
This commit is contained in:
parent
2624ed6824
commit
6ae67fc6dd
@ -15,6 +15,8 @@
|
|||||||
package ebiten
|
package ebiten
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/affine"
|
"github.com/hajimehoshi/ebiten/internal/affine"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,6 +40,13 @@ func (c *ColorM) Reset() {
|
|||||||
c.impl.Reset()
|
c.impl.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply pre-multiplies a vector (r, g, b, a, 1) by the matrix
|
||||||
|
// where r, g, b, and a are clr's values after un-multiplied alpha.
|
||||||
|
// In other words, Apply calculates ColorM * (r, g, b, a, 1)^T.
|
||||||
|
func (c *ColorM) Apply(clr color.Color) color.Color {
|
||||||
|
return c.impl.Apply(clr)
|
||||||
|
}
|
||||||
|
|
||||||
// Concat multiplies a color matrix with the other color matrix.
|
// Concat multiplies a color matrix with the other color matrix.
|
||||||
// This is same as muptiplying the matrix other and the matrix c in this order.
|
// This is same as muptiplying the matrix other and the matrix c in this order.
|
||||||
func (c *ColorM) Concat(other ColorM) {
|
func (c *ColorM) Concat(other ColorM) {
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
package ebiten_test
|
package ebiten_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "github.com/hajimehoshi/ebiten"
|
"image/color"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/hajimehoshi/ebiten"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestColorMInit(t *testing.T) {
|
func TestColorMInit(t *testing.T) {
|
||||||
@ -165,3 +167,60 @@ func TestColorMConcatSelf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func abs(x uint32) uint32 {
|
||||||
|
if x < 0 {
|
||||||
|
return -x
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestColorMApply(t *testing.T) {
|
||||||
|
mono := ColorM{}
|
||||||
|
mono.ChangeHSV(0, 0, 1)
|
||||||
|
|
||||||
|
shiny := ColorM{}
|
||||||
|
shiny.Translate(1, 1, 1, 0)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
ColorM ColorM
|
||||||
|
In color.Color
|
||||||
|
Out color.Color
|
||||||
|
Delta uint32
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
ColorM: ColorM{},
|
||||||
|
In: color.RGBA{1, 2, 3, 4},
|
||||||
|
Out: color.RGBA{1, 2, 3, 4},
|
||||||
|
Delta: 0x101,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ColorM: mono,
|
||||||
|
In: color.NRGBA{0xff, 0xff, 0xff, 0},
|
||||||
|
Out: color.Transparent,
|
||||||
|
Delta: 0x101,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ColorM: mono,
|
||||||
|
In: color.RGBA{0xff, 0, 0, 0xff},
|
||||||
|
Out: color.RGBA{0x4c, 0x4c, 0x4c, 0xff},
|
||||||
|
Delta: 0x101,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ColorM: shiny,
|
||||||
|
In: color.RGBA{0x80, 0x90, 0xa0, 0xb0},
|
||||||
|
Out: color.RGBA{0xb0, 0xb0, 0xb0, 0xb0},
|
||||||
|
Delta: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
out := c.ColorM.Apply(c.In)
|
||||||
|
r0, g0, b0, a0 := out.RGBA()
|
||||||
|
r1, g1, b1, a1 := c.Out.RGBA()
|
||||||
|
if abs(r0-r1) > c.Delta || abs(g0-g1) > c.Delta ||
|
||||||
|
abs(b0-b1) > c.Delta || abs(a0-a1) > c.Delta {
|
||||||
|
println(r0, r1)
|
||||||
|
t.Errorf("%v.Apply(%v) = %v, want %v", c.ColorM, c.In, out, c.Out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
package affine
|
package affine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,6 +49,45 @@ func (c *ColorM) Reset() {
|
|||||||
c.elements = nil
|
c.elements = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func clamp(x float64) float64 {
|
||||||
|
if x > 1 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if x < 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ColorM) Apply(clr color.Color) color.Color {
|
||||||
|
if c.elements == nil {
|
||||||
|
return clr
|
||||||
|
}
|
||||||
|
r, g, b, a := clr.RGBA()
|
||||||
|
if a == 0 {
|
||||||
|
return color.Transparent
|
||||||
|
}
|
||||||
|
rf := float64(r) / float64(a)
|
||||||
|
gf := float64(g) / float64(a)
|
||||||
|
bf := float64(b) / float64(a)
|
||||||
|
af := float64(a) / 0xffff
|
||||||
|
e := c.elements
|
||||||
|
rf2 := e[0]*rf + e[1]*gf + e[2]*bf + e[3]*af + e[4]
|
||||||
|
gf2 := e[5]*rf + e[6]*gf + e[7]*bf + e[8]*af + e[9]
|
||||||
|
bf2 := e[10]*rf + e[11]*gf + e[12]*bf + e[13]*af + e[14]
|
||||||
|
af2 := e[15]*rf + e[16]*gf + e[17]*bf + e[18]*af + e[19]
|
||||||
|
rf2 = clamp(rf2)
|
||||||
|
gf2 = clamp(gf2)
|
||||||
|
bf2 = clamp(bf2)
|
||||||
|
af2 = clamp(af2)
|
||||||
|
return color.NRGBA64{
|
||||||
|
R: uint16(rf2 * 0xffff),
|
||||||
|
G: uint16(gf2 * 0xffff),
|
||||||
|
B: uint16(bf2 * 0xffff),
|
||||||
|
A: uint16(af2 * 0xffff),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ColorM) UnsafeElements() []float64 {
|
func (c *ColorM) UnsafeElements() []float64 {
|
||||||
if c.elements == nil {
|
if c.elements == nil {
|
||||||
c.elements = colorMIdentityElements
|
c.elements = colorMIdentityElements
|
||||||
|
Loading…
Reference in New Issue
Block a user