func NewSpriteFromImage(fileName string) *Sprite { reader, err := os.Open(fileName) if err != nil { log.Fatal(err) } defer reader.Close() m, _, err := image.Decode(reader) if err != nil { log.Fatal(err) } bounds := m.Bounds() if bounds.Max.Y-bounds.Min.Y != 8 { log.Fatal("Invalid image size") } s := NewSprite(bounds.Max.X-bounds.Min.X, bounds.Max.Y-bounds.Min.Y) for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { r, g, b, _ := m.At(x, y).RGBA() s.SetPixel(x-bounds.Min.X, y-bounds.Min.Y, ledmatrix.RGB(int(r>>8), int(g>>8), int(b>>8))) } } return s }
func displayBuilder() { bg := ledmatrix.RGB(0, 0, 0) for { message := <-msgQueue writerQueue <- compose(message, bg) } }
func compose(data Message, bg ledmatrix.Color) *ledmatrix.Writer { matrix := ledmatrix.NewMatrix(tower.Rows, tower.Columns) writer := ledmatrix.NewWriter(matrix) writer.Spacer(matrix.Columns, 0) // Blank bootstrap for _, line := range data { var r, g, b int var f bitmapfont.Font if line.Font < 8 { f = bitmapfont.F68 } else { f = bitmapfont.F88 } fmt.Sscanf(line.Color, "#%02x%02x%02x", &r, &g, &b) writer.WriteText(line.Text, f, ledmatrix.RGB(r, g, b), bg) } return writer }
// renderdeTextMessage convert a text to a LED bitmap matrix. // This method is used by the displayBuilder gorouting. func textToBitmap(text []Line, bg uint32) *ledmatrix.Matrix { matrix := ledmatrix.NewMatrix(rows, 0) writer := ledmatrix.NewWriter(matrix) writer.Spacer(matrix.Columns, 0) // Blank bootstrap for _, line := range text { var r, g, b int var f font.Font if line.Font < 8 { f = font.Font6x8 } else { f = font.Font8x8 } fmt.Sscanf(line.Color, "#%02x%02x%02x", &r, &g, &b) writer.WriteText(line.Text, f, ledmatrix.RGB(r, g, b), bg) } return matrix }
func towerServer() { data := make(Message, 1) start := 0 data[0] = Line{Text: "Booting tower... please wait. ", Font: 6, Color: "#3333FF"} currentDisplay := compose(data, ledmatrix.RGB(0, 0, 0)) for { select { case m := <-writerQueue: currentDisplay = m start = 0 case _ = <-signalChannel: log.Println("Shutting down tower now") tower.Shutdown() os.Exit(0) default: // continue } tower.Roll(currentDisplay, start) start = tower.Columns } }
fmt.Sscanf(line.Color, "#%02x%02x%02x", &r, &g, &b) writer.WriteText(line.Text, f, ledmatrix.RGB(r, g, b), bg) } return matrix } // blank generates a "space" from the given color func blank(len int, bg uint32) *ledmatrix.Matrix { matrix := ledmatrix.NewMatrix(rows, columns) writer := ledmatrix.NewWriter(matrix) writer.Spacer(columns, bg) // Blank spacer return matrix } var bg = ledmatrix.RGB(0, 0, 0) var preamble = blank(columns, bg) func RenderMessage(message *TextMessage) *BitmapMessage { // If body is nil, then reset preamble. This is used when static // frames are sent to the tower and the next rolling message should // start with a blank. if message.Body == nil { preamble = blank(columns, bg) return nil } // render all parts of the message body := textToBitmap(message.Body, bg) introduction := textToBitmap(message.Introduction, bg) conclusion := textToBitmap(message.Conclusion, bg)