canvas and toolkit

pull/3/head
Máximo Cuadros 8 years ago
parent 58fa88515e
commit a0f12c800e

@ -0,0 +1,76 @@
package rgbmatrix
import (
"image"
"image/color"
"image/draw"
)
// Canvas is a image.Image representation of a WS281x matrix, it implements
// image.Image interface and can be used with draw.Draw for example
type Canvas struct {
w, h int
m Matrix
closed bool
}
// NewCanvas returns a new Canvas using the given width and height and creates
// a new WS281x matrix using the given config
func NewCanvas(m Matrix) *Canvas {
w, h := m.Geometry()
return &Canvas{
w: w,
h: h,
m: m,
}
}
// Render update the display with the data from the LED buffer
func (c *Canvas) Render() error {
return c.m.Render()
}
// ColorModel returns the canvas' color model, always color.RGBAModel
func (c *Canvas) ColorModel() color.Model {
return color.RGBAModel
}
// Bounds return the topology of the Canvas
func (c *Canvas) Bounds() image.Rectangle {
return image.Rect(0, 0, c.w, c.h)
}
// At returns the color of the pixel at (x, y)
func (c *Canvas) At(x, y int) color.Color {
return c.m.At(c.position(x, y))
}
// Set set LED at position x,y to the provided 24-bit color value
func (c *Canvas) Set(x, y int, color color.Color) {
c.m.Set(c.position(x, y), color)
}
func (c *Canvas) position(x, y int) int {
return x + (y * c.w)
}
// Clear set all the leds on the matrix with color.Black
func (c *Canvas) Clear() error {
draw.Draw(c, c.Bounds(), &image.Uniform{color.Black}, image.ZP, draw.Src)
return c.m.Render()
}
// Close clears the matrix and close the matrix
func (c *Canvas) Close() error {
c.Clear()
return c.m.Close()
}
type Matrix interface {
Geometry() (width, height int)
At(position int) color.Color
Set(position int, c color.Color)
Apply([]color.Color) error
Render() error
Close() error
}

@ -5,8 +5,11 @@ package rgbmatrix
#cgo LDFLAGS: -lrgbmatrix -L${SRCDIR}/vendor/rpi-rgb-led-matrix/lib -lstdc++ -lm #cgo LDFLAGS: -lrgbmatrix -L${SRCDIR}/vendor/rpi-rgb-led-matrix/lib -lstdc++ -lm
#include <led-matrix-c.h> #include <led-matrix-c.h>
void led_matrix_swap(struct LedCanvas *offscreen_canvas, void led_matrix_swap(struct RGBLedMatrix *matrix,
int width, int height, const uint32_t pixels[]) { int width, int height, const uint32_t pixels[]) {
struct LedCanvas *offscreen_canvas;
offscreen_canvas = led_matrix_create_offscreen_canvas(matrix);
int i, x, y; int i, x, y;
uint32_t color; uint32_t color;
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
@ -18,6 +21,8 @@ void led_matrix_swap(struct LedCanvas *offscreen_canvas,
(color >> 16) & 255, (color >> 8) & 255, color & 255); (color >> 16) & 255, (color >> 8) & 255, color & 255);
} }
} }
led_matrix_swap_on_vsync(matrix, offscreen_canvas);
} }
*/ */
import "C" import "C"
@ -112,7 +117,7 @@ type RGBLedMatrix struct {
} }
// NewRGBLedMatrix returns a new matrix using the given size and config // NewRGBLedMatrix returns a new matrix using the given size and config
func NewRGBLedMatrix(config *HardwareConfig) (Matrix, error) { func NewRGBLedMatrix(config *HardwareConfig) (*RGBLedMatrix, error) {
w, h := config.geometry() w, h := config.geometry()
c := &RGBLedMatrix{ c := &RGBLedMatrix{
@ -140,6 +145,14 @@ func (c *RGBLedMatrix) Geometry() (width, height int) {
return c.width, c.height return c.width, c.height
} }
func (c *RGBLedMatrix) Apply(leds []color.Color) error {
for position, l := range leds {
c.Set(position, l)
}
return c.Render()
}
// Render update the display with the data from the LED buffer // Render update the display with the data from the LED buffer
func (c *RGBLedMatrix) Render() error { func (c *RGBLedMatrix) Render() error {
C.led_matrix_swap( C.led_matrix_swap(
@ -148,6 +161,7 @@ func (c *RGBLedMatrix) Render() error {
(*C.uint32_t)(unsafe.Pointer(&c.leds[0])), (*C.uint32_t)(unsafe.Pointer(&c.leds[0])),
) )
c.leds = make([]C.uint32_t, 2048)
return nil return nil
} }
@ -169,6 +183,10 @@ func (c *RGBLedMatrix) Close() error {
} }
func colorToUint32(c color.Color) uint32 { func colorToUint32(c color.Color) uint32 {
if c == nil {
return 0
}
// A color's RGBA method returns values in the range [0, 65535] // A color's RGBA method returns values in the range [0, 65535]
red, green, blue, _ := c.RGBA() red, green, blue, _ := c.RGBA()
return (red>>8)<<16 | (green>>8)<<8 | blue>>8 return (red>>8)<<16 | (green>>8)<<8 | blue>>8

@ -0,0 +1,66 @@
package rgbmatrix
import (
"image"
"image/draw"
"image/gif"
"io"
"time"
)
type ToolKit struct {
Canvas *Canvas
}
func (tk *ToolKit) PlayImage(i image.Image, delay time.Duration) error {
start := time.Now()
defer func() { time.Sleep(delay - time.Since(start)) }()
draw.Draw(tk.Canvas, tk.Canvas.Bounds(), i, image.ZP, draw.Over)
return tk.Canvas.Render()
}
func (tk *ToolKit) PlayImages(images []image.Image, delay []time.Duration, loop int) chan bool {
quit := make(chan bool, 0)
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
}
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
}
Loading…
Cancel
Save