forked from mcuadros/go-rpi-rgb-led-matrix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtoolkit.go
142 lines (117 loc) · 3.23 KB
/
toolkit.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package rgbmatrix
import (
"image"
"image/draw"
"image/gif"
"io"
"time"
)
// ToolKit is a convinient set of function to operate with a led of Matrix
type ToolKit struct {
// Canvas is the Canvas wrapping the Matrix, if you want to instanciate
// a ToolKit with a custom Canvas you can use directly the struct,
// without calling NewToolKit
Canvas *Canvas
// Transform function if present is applied just before draw the image to
// the Matrix, this is a small example:
// tk.Transform = func(img image.Image) *image.NRGBA {
// return imaging.Fill(img, 64, 96, imaging.Center, imaging.Lanczos)
// }
Transform func(img image.Image) *image.NRGBA
}
// NewToolKit returns a new ToolKit wrapping the given Matrix
func NewToolKit(m Matrix) *ToolKit {
return &ToolKit{
Canvas: NewCanvas(m),
}
}
// PlayImage draws the given image during the given delay
func (tk *ToolKit) PlayImage(i image.Image, delay time.Duration) error {
start := time.Now()
defer func() { time.Sleep(delay - time.Since(start)) }()
if tk.Transform != nil {
i = tk.Transform(i)
}
draw.Draw(tk.Canvas, tk.Canvas.Bounds(), i, image.Point{}, draw.Over)
return tk.Canvas.Render()
}
type Animation interface {
Next() (image.Image, <-chan time.Time, error)
}
// PlayAnimation play the image during the delay returned by Next, until an err
// is returned, if io.EOF is returned, PlayAnimation finish without an error
func (tk *ToolKit) PlayAnimation(a Animation) error {
var err error
var i image.Image
var n <-chan time.Time
for {
i, n, err = a.Next()
if err != nil {
break
}
if err := tk.PlayImageUntil(i, n); err != nil {
return err
}
}
if err == io.EOF {
return nil
}
return err
}
// PlayImageUntil draws the given image until is notified to stop
func (tk *ToolKit) PlayImageUntil(i image.Image, notify <-chan time.Time) error {
defer func() {
<-notify
}()
if tk.Transform != nil {
i = tk.Transform(i)
}
draw.Draw(tk.Canvas, tk.Canvas.Bounds(), i, image.Point{}, draw.Over)
return tk.Canvas.Render()
}
// PlayImages draws a sequence of images during the given delays, the len of
// images should be equal to the len of delay. If loop is true the function
// loops over images until a true is sent to the returned chan
func (tk *ToolKit) PlayImages(images []image.Image, delay []time.Duration, loop int) chan bool {
quit := make(chan bool)
go func() {
l := len(images)
i := 0
for {
select {
case <-quit:
return
default:
tk.PlayImage(images[i], delay[i])
}
i++
if i >= l {
if loop == 0 {
i = 0
continue
}
break
}
}
}()
return quit
}
// PlayGIF reads and draw a gif file from r. It use the contained images and
// delays and loops over it, until a true is sent to the returned chan
func (tk *ToolKit) PlayGIF(r io.Reader) (chan bool, error) {
gif, err := gif.DecodeAll(r)
if err != nil {
return nil, err
}
delay := make([]time.Duration, len(gif.Delay))
images := make([]image.Image, len(gif.Image))
for i, image := range gif.Image {
images[i] = image
delay[i] = time.Millisecond * time.Duration(gif.Delay[i]) * 10
}
return tk.PlayImages(images, delay, gif.LoopCount), nil
}
// Close close the toolkit and the inner canvas
func (tk *ToolKit) Close() error {
return tk.Canvas.Close()
}