fixed image drawing, added some interpolation
This commit is contained in:
parent
a0a1adef12
commit
e3bb07a09c
4 changed files with 99 additions and 59 deletions
70
backend/software/color.go
Normal file
70
backend/software/color.go
Normal 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)),
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue