| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- import socket
- class Matrix(object):
- '''A Framebuffer display interface that sends a frame via UDP.
- see https://github.com/hzeller/flaschen-taschen/blob/master/doc/protocols.md
- '''
- def __init__(self, host, width, height, layer=1, x_offset=0, y_offset=0, transparent=False, port=1337):
- '''
- Args:
- host: The flaschen taschen server hostname or ip address.
- port: The flaschen taschen server port number.
- width: The width of the flaschen taschen display in pixels.
- height: The height of the flaschen taschen display in pixels.
- layer: The layer of the flaschen taschen display to write to. (layer=0 is permanent, layer > 0 decays, see --layer-timeout server opt)
- transparent: If true, black(0, 0, 0) will be transparent and show the layer below.
- '''
- self.width = width
- self.height = height
- self.layer = layer
- self.transparent = transparent
- self.x_offset = x_offset
- self.y_offset = y_offset
- self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- self._sock.connect((host, port))
- self._init_data()
- def _init_data(self):
- header = ''.join(["P6\n",
- "%d %d\n" % (self.width, self.height),
- "255\n"]).encode('utf-8')
- footer = ''.join(["%d\n" % self.x_offset,
- "%d\n" % self.y_offset,
- "%d\n" % self.layer]).encode('utf-8')
- self._data = bytearray(self.width * self.height * 3 + len(header) + len(footer))
- self._data[0:len(header)] = header
- self._data[-1 * len(footer):] = footer
- self._header_len = len(header)
- def set(self, x, y, color):
- '''Set the pixel at the given coordinates to the specified color.
- Args:
- x: x offset of the pixel to set
- y: y offset of the piyel to set
- color: A 3 tuple of (r, g, b) color values, 0-255
- '''
- if x >= self.width or y >= self.height or x < 0 or y < 0:
- return
- # [dr]: inverted logic
- if color == (0, 0, 0) and self.transparent:
- color = (1, 1, 1)
- offset = (x + y * self.width) * 3 + self._header_len
- self._data[offset] = color[0]
- self._data[offset + 1] = color[1]
- self._data[offset + 2] = color[2]
- def draw_img(self, x, y, img, ignore_black=True):
- '''draw a PIL image at (x, y)
- '''
- #~ for img_x in range(img.width):
- #~ for img_y in range(img.height):
- #~ color = img.getpixel((img_x, img_y))[:3]
- #~ if not ignore_black or sum(color) > 0:
- #~ self.set(x + img_x , y + img_y, color)
- width = img.width
- imgdata = img.getdata()
- for img_x in range(img.width):
- for img_y in range(img.height):
- color = imgdata[img_y * width + img_x]
- if not ignore_black or (color[0] or color[1] or color[2]):
- self.set(x + img_x , y + img_y, color)
- def set_offset(self, x, y):
- self.x_offset = x
- self.y_offset = y
- self._init_data()
- def send(self):
- '''Send the updated pixels to the display.'''
- self._sock.send(self._data)
- def clear(self, send=True):
- '''clear pane with black (reinit self._data)
- '''
- self._init_data()
- if send:
- self.send()
- if __name__ == '__main__':
- f = Matrix('192.168.178.144', 50, 50)
- import time
- for j in range(10):
- time.sleep(1)
- f.set_offset(j*2, j)
- for i in range(100):
- f.set(i, i, (200, 0, 0))
- f.send()
|