-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpf.go
68 lines (56 loc) · 1.71 KB
/
pf.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
package pf
import (
"sync"
)
// Perform an operation on a single ARGB pixel
type PixelFunction func(v uint32) uint32
// Combine two functions to a single PixelFunction.
// The functions are applied in the same order as the arguments.
func Combine(a, b PixelFunction) PixelFunction {
return func(v uint32) uint32 {
return b(a(v))
}
}
// Combine three functions to a single PixelFunction.
// The functions are applied in the same order as the arguments.
func Combine3(a, b, c PixelFunction) PixelFunction {
return Combine(a, Combine(b, c))
}
// Divide a slice of pixels into several slices
func Divide(pixels []uint32, n int) [][]uint32 {
length := len(pixels)
sliceLen := length / n
leftover := length % n
var sliceOfSlices [][]uint32
for i := 0; i < (length - leftover); i += sliceLen {
sliceOfSlices = append(sliceOfSlices, pixels[i:i+sliceLen])
}
if leftover > 0 {
sliceOfSlices = append(sliceOfSlices, pixels[length-leftover:length])
}
return sliceOfSlices
}
func Map(cores int, f PixelFunction, pixels []uint32) {
wg := &sync.WaitGroup{}
// First copy the pixels into several separate slices
sliceOfSlices := Divide(pixels, cores)
// Then process the slices individually
wg.Add(len(sliceOfSlices))
for _, subPixels := range sliceOfSlices {
// subPixels is a slice of pixels
go func(wg *sync.WaitGroup, subPixels []uint32) {
for i := range subPixels {
subPixels[i] = f(subPixels[i])
}
wg.Done()
}(wg, subPixels)
}
wg.Wait()
// Then combine the slices into a new and better slice
newPixels := make([]uint32, len(pixels))
for _, subPixels := range sliceOfSlices {
newPixels = append(newPixels, subPixels...)
}
// Finally, replace the pixels with the processed pixels
pixels = newPixels
}