forked from fogleman/primitive
/
core.go
124 lines (118 loc) · 3.14 KB
/
core.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package primitive
import (
"image"
"math"
)
func computeColor(target, current *image.RGBA, lines []Scanline, alpha int) Color {
var rsum, gsum, bsum, count int64
a := 0x101 * 255 / alpha
for _, line := range lines {
i := target.PixOffset(line.X1, line.Y)
for x := line.X1; x <= line.X2; x++ {
tr := int(target.Pix[i])
tg := int(target.Pix[i+1])
tb := int(target.Pix[i+2])
cr := int(current.Pix[i])
cg := int(current.Pix[i+1])
cb := int(current.Pix[i+2])
i += 4
rsum += int64((tr-cr)*a + cr*0x101)
gsum += int64((tg-cg)*a + cg*0x101)
bsum += int64((tb-cb)*a + cb*0x101)
count++
}
}
if count == 0 {
return Color{}
}
r := clampInt(int(rsum/count)>>8, 0, 255)
g := clampInt(int(gsum/count)>>8, 0, 255)
b := clampInt(int(bsum/count)>>8, 0, 255)
return Color{r, g, b, alpha}
}
func copyLines(dst, src *image.RGBA, lines []Scanline) {
for _, line := range lines {
a := dst.PixOffset(line.X1, line.Y)
b := a + (line.X2-line.X1+1)*4
copy(dst.Pix[a:b], src.Pix[a:b])
}
}
func drawLines(im *image.RGBA, c Color, lines []Scanline) {
const m = 0xffff
sr, sg, sb, sa := c.NRGBA().RGBA()
for _, line := range lines {
ma := line.Alpha
a := (m - sa*ma/m) * 0x101
i := im.PixOffset(line.X1, line.Y)
for x := line.X1; x <= line.X2; x++ {
dr := uint32(im.Pix[i+0])
dg := uint32(im.Pix[i+1])
db := uint32(im.Pix[i+2])
da := uint32(im.Pix[i+3])
im.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
im.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
im.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
im.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
i += 4
}
}
}
func differenceFull(a, b *image.RGBA) float64 {
size := a.Bounds().Size()
w, h := size.X, size.Y
var total uint64
for y := 0; y < h; y++ {
i := a.PixOffset(0, y)
for x := 0; x < w; x++ {
ar := int(a.Pix[i])
ag := int(a.Pix[i+1])
ab := int(a.Pix[i+2])
aa := int(a.Pix[i+3])
br := int(b.Pix[i])
bg := int(b.Pix[i+1])
bb := int(b.Pix[i+2])
ba := int(b.Pix[i+3])
i += 4
dr := ar - br
dg := ag - bg
db := ab - bb
da := aa - ba
total += uint64(dr*dr + dg*dg + db*db + da*da)
}
}
return math.Sqrt(float64(total)/float64(w*h*4)) / 255
}
func differencePartial(target, before, after *image.RGBA, score float64, lines []Scanline) float64 {
size := target.Bounds().Size()
w, h := size.X, size.Y
total := uint64(math.Pow(score*255, 2) * float64(w*h*4))
for _, line := range lines {
i := target.PixOffset(line.X1, line.Y)
for x := line.X1; x <= line.X2; x++ {
tr := int(target.Pix[i])
tg := int(target.Pix[i+1])
tb := int(target.Pix[i+2])
ta := int(target.Pix[i+3])
br := int(before.Pix[i])
bg := int(before.Pix[i+1])
bb := int(before.Pix[i+2])
ba := int(before.Pix[i+3])
ar := int(after.Pix[i])
ag := int(after.Pix[i+1])
ab := int(after.Pix[i+2])
aa := int(after.Pix[i+3])
i += 4
dr1 := tr - br
dg1 := tg - bg
db1 := tb - bb
da1 := ta - ba
dr2 := tr - ar
dg2 := tg - ag
db2 := tb - ab
da2 := ta - aa
total -= uint64(dr1*dr1 + dg1*dg1 + db1*db1 + da1*da1)
total += uint64(dr2*dr2 + dg2*dg2 + db2*db2 + da2*da2)
}
}
return math.Sqrt(float64(total)/float64(w*h*4)) / 255
}