hzeller / rpi-rgb-led-matrix

Controlling up to three chains of 64x64, 32x32, 16x32 or similar RGB LED displays using Raspberry Pi GPIO
GNU General Public License v2.0
3.64k stars 1.16k forks source link

How to create a few FrameCanvases in Python? #1317

Open xXZyzzXx opened 3 years ago

xXZyzzXx commented 3 years ago

I have 8 chained 32x32 LED panels and I'm trying to display moving text separately in three areas of the frame:

    options.chain_length = 2
    self.left_matrix = RGBMatrix(options=options)
    options.chain_length = 4
    self.center_matrix = RGBMatrix(options=options)
    options.chain_length = 2
    self.right_matrix = RGBMatrix(options=options)

    left_matrix = self.left_matrix.CreateFrameCanvas()
    center_matrix = self.center_matrix.CreateFrameCanvas()
    right_matrix = self.right_matrix.CreateFrameCanvas()
    data = ["197", "text to display in a center", 3"]
    self.run_x_pos = center_matrix.width
    while True:
        self.left_matrix.Clear()
        self.center_matrix.Clear()
        self.right_matrix.Clear()
        self.textColor = graphics.Color(randrange(255), randrange(255), randrange(255))
        graphics.DrawText(left_matrix, font, self.run_x_pos, 22, self.textColor, data[0])
        text_len = graphics.DrawText(center_matrix, font, self.run_x_pos, y_pos, self.textColor, data[1])
        self.run_x_pos -= 1
        if self.run_x_pos + text_len < 0:
            self.run_x_pos = center_matrix.width
        graphics.DrawText(right_matrix, font, self.run_x_pos, y_pos, self.textColor, data[2])
        self.left_matrix.SwapOnVSync(left_matrix)
        self.center_matrix.SwapOnVSync(center_matrix)
        self.right_matrix.SwapOnVSync(right_matrix)

It doesn't work as it should, how to create multiple matrix correctly?

I found that it is possible to create multiple panels in https://github.com/hzeller/rpi-rgb-led-matrix/issues/622#issuecomment-389354771 comment

Or is there some way to limit the text display area inside the root frame?

raspberry-pi-maker commented 3 years ago

I think you can write multiple text lines in one canvas. So there is no need to divide it into multiple canvases.

options.chain_length = 8
self.matrix = RGBMatrix(options=options)
canvas = self.matrix.CreateFrameCanvas()
data = ["197", "text to display in a center", 3"]
self.run_x_pos = center_matrix.width
    while True:
        self.matrix.Clear()
        self.textColor = graphics.Color(randrange(255), randrange(255), randrange(255))
        graphics.DrawText(canvas, font, self.run_x_pos, 22, self.textColor, data[0])
        text_len = graphics.DrawText(canvas, font, self.run_x_pos, y_pos, self.textColor, data[1])
        self.run_x_pos -= 1
        if self.run_x_pos + text_len < 0:
            self.run_x_pos = canvas.width
        graphics.DrawText(canvas, font, self.run_x_pos, y_pos, self.textColor, data[2])
        canvas = self.matrix.SwapOnVSync(canvas)
xXZyzzXx commented 3 years ago

I think you can write multiple text lines in one canvas. So there is no need to divide it into multiple canvases.

options.chain_length = 8
self.matrix = RGBMatrix(options=options)
canvas = self.matrix.CreateFrameCanvas()
data = ["197", "text to display in a center", 3"]
self.run_x_pos = center_matrix.width
    while True:
        self.matrix.Clear()
        self.textColor = graphics.Color(randrange(255), randrange(255), randrange(255))
        graphics.DrawText(canvas, font, self.run_x_pos, 22, self.textColor, data[0])
        text_len = graphics.DrawText(canvas, font, self.run_x_pos, y_pos, self.textColor, data[1])
        self.run_x_pos -= 1
        if self.run_x_pos + text_len < 0:
            self.run_x_pos = canvas.width
        graphics.DrawText(canvas, font, self.run_x_pos, y_pos, self.textColor, data[2])
        canvas = self.matrix.SwapOnVSync(canvas)

I need the text to scroll only within its border. With one matrix, the pixels go beyond these limits and disappear only with a minus value of x. Scrolling text should not go beyond the first text.

raspberry-pi-maker commented 3 years ago

I am familiar with image processing libraries such as PIL and OpenCV. So, if I were to work, I would create 3 PIL images (64X32, 128X32, 64X32), work with text on each image, and then merge the 3 images. And I will display the combined image on one canvas like this.

from PIL import Image, ImageDraw, ImageFont

def get_concat_h(im1, im2, im3):
    dst = Image.new('RGB', (im1.width + im2.width + im3.width, im1.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (im1.width, 0))
    dst.paste(im3, (im1.width + im2.width, 0))
    return dst

fnt = ImageFont.truetype('./font/yourfontname.ttf', 40)
while True:
  im1 = Image.new('RGB', (64, 32),(255, 255, 255))
  im2 = Image.new('RGB', (128, 32),(255, 255, 255))
  im3 = Image.new('RGB', (64, 32),(255, 255, 255))

  draw1 = ImageDraw.Draw(im1)
  draw1.text((30,30), u'Hello World', font=fnt, fill=(0,0,255,128))
  draw2 = ImageDraw.Draw(im2)
  draw2.text((30,30), u'Hello World', font=fnt, fill=(0,0,255,128))
  draw3 = ImageDraw.Draw(im2)
  draw3.text((30,30), u'Hello World', font=fnt, fill=(0,0,255,128))

  im_pil = get_concat_h(im1,im2,im3)
  canvas.SetImage(im_pil)
  canvas = matrix.SwapOnVSync(canvas)