Pixelflut

Source code and documentation (english) on github.com
and in our gitlab.

Experimente mit grafischen Algorithmen sind nur halb so spaßig, wenn sie kein Mensch sehen kann. Pixelflut bringt die Pixel von allen im Netzwerk auf dieselbe Leinwand (Beamer, LCD). Das Protokoll ist simpel, uneffizient, die Möglichkeiten begrenzt, aber genau das ist ja die Herausforderung.

Beispiel vom EasterHegg 2014 in Stuttgart auf vimeo

Foto von einem Bildschirm auf dem Pixelflut läuft
Random Step und Testbild

Protokoll#

Der Server wird über TCP/IP angesprochen und versteht ASCII Befehle (einen pro Zeile).

PX $x $y $color setzt den Farbwert eines Pixels.

  • $color ist dabei ein hex-string, entweder 6-stellig (rrggbb) oder 8-stelig (rrggbbaa).
  • $x und $y sind dezimale Zahlen.

SIZE sendet sofort die Größe der Leinwand in der Form SIZE $x $y zurück.

Beispiele#

Setze ein orangefarbenes Pixel an die Position 20,30 (x,y):

$ echo -en 'PX 20 30 ff8800\n' | netcat -q1 10.23.43.107 2342

Setze ein blaues Pixel an die Position 20,30 (x,y), aber nur mit 50% Deckung:

$ echo -en 'PX 20 30 0000ff88\n' | netcat -q1 10.23.43.107 2342

Nächste Version#

Das simple Protokoll und seine Einschränkungen sind Teil des Konzepts, Befehle wie LINE, RECT oder FILL wird es also nicht geben. Einige Sachen wären aber noch schön:

  • Nur eine Verbindung pro IP zulassen done
  • Farbwerte als Hex-Codes statt dezimal (Grau: xx RGB: rrggbb Alpha: rrggbbaa) done
  • Ein 'faires' scheduling damit clients sich nicht gegenseitig ausbremsen done
    • Detail: Pro Frame hat jeder Client 10 Pixel frei. Sind diese verbraucht, muss er auf das nächste Frame warten.
  • Auslesen der Farbwerte von größeren Blöcken mit einem Befehl (16x16?)
  • Eine Art Broadcast-Modus, bei dem alle die wollen über jede Pixeländerung informiert werden.
  • Eine Pixel/Sekunde Highscore, um Spammer zu identifizieren ;)

Code Sammlung#

Server Sources auf github.com

Bash#

nur bis Api < 20120512

# y=0; cat a.xpm | while read l ; do i=0 ;x=0; max=${#l}; echo $max ; while [ $i -ne $max ] ;\
   do b=`echo ${l:i:1}` ; echo $b $i $y ;if [ "$b" == "." ] ;\
   then echo test ; echo  "px $i $y" ; fi ; let i++ ;echo $i; done;\
   let y++ ; done | grep "px" |netcat 10.23.42.107 2342 \

bei dieser Version muss noch der header aus dem XPM File entfernt werden

Python#

Primitiver client in Python (ready for copy/paste)

import socket
HOST = '10.23.42.107'
PORT = 2342
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
send = sock.send

def pixel(x,y,r,g,b,a=255):
    if a == 255:
        send('PX %d %d %02x%02x%02x\n' % (x,y,r,g,b))
    else:
        send('PX %d %d %02x%02x%02x%02x\n' % (x,y,r,g,b,a))

Ein paar nette Funktionen#

def rect(x,y,w,h,r,g,b):
    for i in range(x,x+w):
        for j in range(y,y+h):
            pixel(i,j,r,g,b)

import random  
def worm(x,y,n,r,g,b):
    while n:
        pixel(x,y,r,g,b,25)
        x += random.randint(0,2)-1
        y += random.randint(0,2)-1
        n -= 1

from PIL import Image
im = Image.open('test.png').convert('RGB')
im.thumbnail((200,300), Image.ANTIALIAS)
_,_,w,h = im.getbbox()  
for x in range(w):
    for y in range(h):
        r,g,b = im.getpixel((x,y))
        pixel(x,y,r,g,b)