-
Notifications
You must be signed in to change notification settings - Fork 121
/
Copy patheffects.go
87 lines (75 loc) · 1.89 KB
/
effects.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
package gift
import (
"image"
"image/draw"
)
type pixelateFilter struct {
size int
}
func (p *pixelateFilter) Bounds(srcBounds image.Rectangle) (dstBounds image.Rectangle) {
dstBounds = image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy())
return
}
func (p *pixelateFilter) Draw(dst draw.Image, src image.Image, options *Options) {
if options == nil {
options = &defaultOptions
}
blockSize := p.size
if blockSize <= 1 {
copyimage(dst, src, options)
return
}
srcb := src.Bounds()
dstb := dst.Bounds()
numBlocksX := srcb.Dx() / blockSize
if srcb.Dx()%blockSize > 0 {
numBlocksX++
}
numBlocksY := srcb.Dy() / blockSize
if srcb.Dy()%blockSize > 0 {
numBlocksY++
}
pixGetter := newPixelGetter(src)
pixSetter := newPixelSetter(dst)
parallelize(options.Parallelization, 0, numBlocksY, func(start, stop int) {
for by := start; by < stop; by++ {
for bx := 0; bx < numBlocksX; bx++ {
// Calculate the block bounds.
bb := image.Rect(bx*blockSize, by*blockSize, (bx+1)*blockSize, (by+1)*blockSize)
bbSrc := bb.Add(srcb.Min).Intersect(srcb)
bbDst := bbSrc.Sub(srcb.Min).Add(dstb.Min).Intersect(dstb)
// Calculate the average color of the block.
var r, g, b, a float32
var cnt float32
for y := bbSrc.Min.Y; y < bbSrc.Max.Y; y++ {
for x := bbSrc.Min.X; x < bbSrc.Max.X; x++ {
px := pixGetter.getPixel(x, y)
r += px.r
g += px.g
b += px.b
a += px.a
cnt++
}
}
if cnt > 0 {
r /= cnt
g /= cnt
b /= cnt
a /= cnt
}
// Set the calculated color for all pixels in the block.
for y := bbDst.Min.Y; y < bbDst.Max.Y; y++ {
for x := bbDst.Min.X; x < bbDst.Max.X; x++ {
pixSetter.setPixel(x, y, pixel{r, g, b, a})
}
}
}
}
})
}
// Pixelate creates a filter that applies a pixelation effect to an image.
func Pixelate(size int) Filter {
return &pixelateFilter{
size: size,
}
}