fixed image drawing, added some interpolation

This commit is contained in:
Thomas Friedel 2019-04-18 12:36:05 +02:00
parent a0a1adef12
commit e3bb07a09c
4 changed files with 99 additions and 59 deletions

70
backend/software/color.go Normal file
View file

@ -0,0 +1,70 @@
package softwarebackend
import (
"image/color"
"math"
)
func mix(src, dest color.Color) color.RGBA {
ir1, ig1, ib1, ia1 := src.RGBA()
r1 := float64(ir1) / 65535.0
g1 := float64(ig1) / 65535.0
b1 := float64(ib1) / 65535.0
a1 := float64(ia1) / 65535.0
ir2, ig2, ib2, _ := dest.RGBA()
r2 := float64(ir2) / 65535.0
g2 := float64(ig2) / 65535.0
b2 := float64(ib2) / 65535.0
r := (r1-r2)*a1 + r2
g := (g1-g2)*a1 + g2
b := (b1-b2)*a1 + b2
return color.RGBA{
R: uint8(math.Round(r * 255.0)),
G: uint8(math.Round(g * 255.0)),
B: uint8(math.Round(b * 255.0)),
A: 255,
}
}
func alphaColor(col color.Color, alpha color.Alpha) color.RGBA {
ir, ig, ib, _ := col.RGBA()
a2 := float64(alpha.A) / 255.0
r := float64(ir) * a2 / 65535.0
g := float64(ig) * a2 / 65535.0
b := float64(ib) * a2 / 65535.0
return color.RGBA{
R: uint8(r * 255.0),
G: uint8(g * 255.0),
B: uint8(b * 255.0),
A: 255,
}
}
func lerp(col1, col2 color.Color, ratio float64) color.RGBA {
ir1, ig1, ib1, ia1 := col1.RGBA()
r1 := float64(ir1) / 65535.0
g1 := float64(ig1) / 65535.0
b1 := float64(ib1) / 65535.0
a1 := float64(ia1) / 65535.0
ir2, ig2, ib2, ia2 := col2.RGBA()
r2 := float64(ir2) / 65535.0
g2 := float64(ig2) / 65535.0
b2 := float64(ib2) / 65535.0
a2 := float64(ia2) / 65535.0
r := (r1-r2)*ratio + r2
g := (g1-g2)*ratio + g2
b := (b1-b2)*ratio + b2
a := (a1-a2)*ratio + a2
return color.RGBA{
R: uint8(math.Round(r * 255.0)),
G: uint8(math.Round(g * 255.0)),
B: uint8(math.Round(b * 255.0)),
A: uint8(math.Round(a * 255.0)),
}
}

View file

@ -3,7 +3,6 @@ package softwarebackend
import (
"image"
"image/color"
"math"
"github.com/tfriedel6/canvas/backend/backendbase"
)
@ -39,50 +38,12 @@ func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
})
}
func mix(src, dest color.Color) color.RGBA {
ir1, ig1, ib1, ia1 := src.RGBA()
r1 := float64(ir1) / 65535.0
g1 := float64(ig1) / 65535.0
b1 := float64(ib1) / 65535.0
a1 := float64(ia1) / 65535.0
ir2, ig2, ib2, _ := dest.RGBA()
r2 := float64(ir2) / 65535.0
g2 := float64(ig2) / 65535.0
b2 := float64(ib2) / 65535.0
r := (r1-r2)*a1 + r2
g := (g1-g2)*a1 + g2
b := (b1-b2)*a1 + b2
return color.RGBA{
R: uint8(math.Round(r * 255.0)),
G: uint8(math.Round(g * 255.0)),
B: uint8(math.Round(b * 255.0)),
A: 255,
}
}
func alphaColor(col color.Color, alpha color.Alpha) color.RGBA {
ir, ig, ib, _ := col.RGBA()
a2 := float64(alpha.A) / 255.0
r := float64(ir) * a2 / 65535.0
g := float64(ig) * a2 / 65535.0
b := float64(ib) * a2 / 65535.0
return color.RGBA{
R: uint8(r * 255.0),
G: uint8(g * 255.0),
B: uint8(b * 255.0),
A: 255,
}
}
func (b *SoftwareBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [4][2]float64) {
mw := float64(mask.Bounds().Dx())
mh := float64(mask.Bounds().Dy())
b.fillQuad(pts, func(x, y int, sx2, sy2 float64) {
sxi := int(mw*sx2 + 0.5)
syi := int(mh*sy2 + 0.5)
sxi := int(mw * sx2)
syi := int(mh * sy2)
a := mask.AlphaAt(sxi, syi)
if a.A == 0 {
return

View file

@ -2,6 +2,7 @@ package softwarebackend
import (
"image"
"math"
"github.com/tfriedel6/canvas/backend/backendbase"
)
@ -21,9 +22,19 @@ func (b *SoftwareBackend) DrawImage(dimg backendbase.Image, sx, sy, sw, sh float
return
}
b.fillQuad(pts, func(x, y int, sx2, sy2 float64) {
sxi := int(sx + sw*sx2 + 0.5)
syi := int(sy + sh*sy2 + 0.5)
b.Image.Set(x, y, simg.img.At(sxi, syi))
imgx := sx + sw*sx2
imgy := sy + sh*sy2
imgxf := math.Floor(imgx)
imgyf := math.Floor(imgy)
rx := imgx - imgxf
ry := imgy - imgyf
ca := simg.img.At(int(imgxf), int(imgyf))
cb := simg.img.At(int(imgxf+1), int(imgyf))
cc := simg.img.At(int(imgxf), int(imgyf+1))
cd := simg.img.At(int(imgxf+1), int(imgyf+1))
ctop := lerp(ca, cb, rx)
cbtm := lerp(cc, cd, rx)
b.Image.Set(x, y, lerp(ctop, cbtm, ry))
})
}

View file

@ -134,27 +134,25 @@ func (b *SoftwareBackend) fillQuad(quad [4][2]float64, fn func(x, y int, sx, sy
continue
}
v0 := [2]float64{float64(l) - quad[0][0], float64(y) - quad[0][1]}
sx0 := topv[0]*v0[0] + topv[1]*v0[1]
sy0 := leftv[0]*v0[0] + leftv[1]*v0[1]
v1 := [2]float64{float64(r) - quad[0][0], float64(y) - quad[0][1]}
sx1 := topv[0]*v1[0] + topv[1]*v1[1]
sy1 := leftv[0]*v1[0] + leftv[1]*v1[1]
sx, sy := sx0/topLen, sy0/leftLen
sxStep := (sx1 - sx0) / float64(r-l) / topLen
syStep := (sy1 - sy0) / float64(r-l) / leftLen
sfy := float64(y) + 0.5 - quad[0][1]
fl, cr := int(math.Floor(l)), int(math.Ceil(r))
for x := fl; x <= cr; x++ {
fx := float64(x) + 0.5
if fx < l || fx >= r {
continue
}
fn(x, y, sx, sy)
sx += sxStep
sy += syStep
sfx := fx - quad[0][0]
var sx, sy float64
if math.Abs(leftv[0]) > math.Abs(leftv[1]) {
sx = (sfy - sfx*(leftv[1]/leftv[0])) / (topv[1] - topv[0]*(leftv[1]/leftv[0]))
sy = (sfx - topv[0]*sx) / leftv[0]
} else {
sx = (sfx - sfy*(leftv[0]/leftv[1])) / (topv[0] - topv[1]*(leftv[0]/leftv[1]))
sy = (sfy - topv[1]*sx) / leftv[1]
}
fn(x, y, sx/topLen, sy/leftLen)
}
}
}