Pixelflut: Unterschied zwischen den Versionen

Aus Wiki CCC Göttingen
Zur Navigation springen Zur Suche springen
(Added link to github repository)
 
(8 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt)
Zeile 5: Zeile 5:
[[Datei:AlexN900 01 20120423 003.jpg|300px|thumb| Random Step + Testbild ]]
[[Datei:AlexN900 01 20120423 003.jpg|300px|thumb| Random Step + Testbild ]]


Experimente mit grafischen Algorithmen sind nur halb so spaßig, wenn man sie niemandem zeigen kann. Pixelflut bringt die Pixel von jedem im Netzwerk auf die selbe Leinwand (Beamer, LCD). Das Protokoll ist simpel, die Möglichkeiten begrenzt, aber genau das ist ja die Herausforderung.  
<big>'''Source code and documentation (english) ->''' https://github.com/defnull/pixelflut</big>
 
Experimente mit grafischen Algorithmen sind nur halb so spaßig, wenn man sie niemandem zeigen kann. Pixelflut bringt die Pixel von jedem im Netzwerk auf dieselbe Leinwand (Beamer, LCD). Das Protokoll ist simpel, die Möglichkeiten begrenzt, aber genau das ist ja die Herausforderung.  
 
Beispiel: EasterHegg 2014 in Stuttgart http://vimeo.com/92827556
 
 
 
 
== Protokoll ==


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


    # Setze ein weißes Pixel an die Position 20,30 (x,y)
* '''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 dezimal Zahlen.
    $ echo -en 'PX 20 30 ffffff\n' | netcat -q1 10.23.43.107 2342
* '''SIZE''' sendet sofort die Größe der Leinwand in der Form 'SIZE $x $y' zurück.


    # Setze ein orangefarbenes Pixel, aber nur mit 50% deckung
Beispiel:
    $ echo -en 'PX 20 30 ff880088\n' | netcat -q1 10.23.43.107 2342


    # Lese den Farbwert eines Pixels
# Setze ein orangefarbenes Pixel an die Position 20,30 (x,y)
    $ echo -en 'PX 20 30\n' | netcat -q1 10.23.43.107 2342
$ echo -en 'PX 20 30 ff8800\n' | netcat -q1 10.23.43.107 2342
    PX 20 30 255 192 128
 
# 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


    # Frage nach der Größe der Leinwand
    $ echo -en 'SIZE\n' | netcat -q1 10.23.43.107 2342
    SIZE 800 600


== Nächste Version ==
== Nächste Version ==
Zeile 30: Zeile 37:
* Farbwerte als Hex-Codes statt dezimal (Grau: xx RGB: rrggbb Alpha: rrggbbaa) '''done'''
* Farbwerte als Hex-Codes statt dezimal (Grau: xx RGB: rrggbb Alpha: rrggbbaa) '''done'''
* Ein 'faires' scheduling damit clients sich nicht gegenseitig aus bremsen '''done'''
* Ein 'faires' scheduling damit clients sich nicht gegenseitig aus bremsen '''done'''
  * Detail: Pro Frame hat jeder Client 10 Pixel frei. Sind diese verbraucht, muss er auf das nächste Frame warten.  
** 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?)
* Auslesen der Farbwerte von größeren Blöcken mit einem Befehl (16x16?)
* Eine Art Broadcast-Modus, bei dem jeder (der will) über jede Pixeländerung informiert wird.
* Eine Art Broadcast-Modus, bei dem jeder (der will) über jede Pixeländerung informiert wird.
Zeile 40: Zeile 47:


=== Bash ===
=== 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 ] ;\
   # 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" == "." ] ;\
         do b=`echo ${l:i:1}` ; echo $b $i $y ;if [ "$b" == "." ] ;\
Zeile 60: Zeile 67:
   def pixel(x,y,r,g,b,a=255):
   def pixel(x,y,r,g,b,a=255):
     if a == 255:
     if a == 255:
       send('PX %d %d %d %d %d\n' % (x,y,r,g,b))
       send('PX %d %d %02x%02x%02x\n' % (x,y,r,g,b))
     else:
     else:
       send('PX %d %d %d %d %d %d\n' % (x,y,r,g,b,a))
       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):
   def rect(x,y,w,h,r,g,b):
Zeile 69: Zeile 78:
       pixel(i,j,r,g,b)
       pixel(i,j,r,g,b)


   import random
 
   
   import random
   def worm(x,y,n,r,g,b):
   def worm(x,y,n,r,g,b):
     while n:
     while n:
Zeile 77: Zeile 86:
       y += random.randint(0,2)-1
       y += random.randint(0,2)-1
       n -= 1
       n -= 1
 
 
   from PIL import Image
   from PIL import Image
   im = Image.open('test.png').convert('RGB')
   im = Image.open('test.png').convert('RGB')
   im.thumbnail((200,300), Image.ANTIALIAS)
   im.thumbnail((200,300), Image.ANTIALIAS)
   _,_,w,h = im.getbbox()
   _,_,w,h = im.getbbox()
 
   for x in xrange(w):
   for x in xrange(w):
     for y in xrange(h):
     for y in xrange(h):
       r,g,b = im.getpixel((x,y))
       r,g,b = im.getpixel((x,y))
       pixel(x,y,r,g,b)
       pixel(x,y,r,g,b)

Aktuelle Version vom 31. März 2018, 20:06 Uhr


Pixel Flut[Bearbeiten]

Random Step + Testbild

Source code and documentation (english) -> https://github.com/defnull/pixelflut

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

Beispiel: EasterHegg 2014 in Stuttgart http://vimeo.com/92827556



Protokoll[Bearbeiten]

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 dezimal Zahlen.
  • SIZE sendet sofort die Größe der Leinwand in der Form 'SIZE $x $y' zurück.

Beispiel:

# 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[Bearbeiten]

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 aus bremsen 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 jeder (der will) über jede Pixeländerung informiert wird.
  • Eine Pixel/Sekunde Highscore, um Spammer zu identifizieren ;)

Code Sammlung[Bearbeiten]

Server Sources: https://github.com/defnull/pixelflut

Bash[Bearbeiten]

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[Bearbeiten]

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 xrange(x,x+w):
    for j in xrange(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 xrange(w):
   for y in xrange(h):
     r,g,b = im.getpixel((x,y))
     pixel(x,y,r,g,b)