Tim Rodenbröker entwickelt gerade eine E-Learning-Plattform für Processing. In seinem Einsteiger-Tutorial zeigt er Schritt für Schritt, wie man Fotos mithilfe von Processing rastert. Auf dem Weg dorthin lernen wir die fundamentalen Prinzipien von Programmierung und generativer Gestaltung kennen.
Datenvisualisierung und generatives Design waren lange Zeit das Alleinstellungsmerkmal der Programmiersprache Processing, aber das ist längst nicht ihr ganzes Potenzial.
In den fast 20 Jahren, die es sie gibt, hat sich eine große Community rund um diese Technologie entwickelt und sie wurde zum Sinnbild für die Schnittmenge aus Kunst und Technik, die Idee des kreativen Programmierens.
Inzwischen ist sie universell einsetzbar und man kann mit ihr zum Beispiel auch Algorithmen für InDesign schreiben, um Layouts zu automatisieren. Für Tim Rodenbröker ist Processing jedenfalls der ideale Weg, um Gestalter in die Welt des Codens einzuführen.
Dieses Material benötigt ihr für das Processing-Tutorial
Dazu könnt ihr Euch die Entwicklungsumgebung Processing unter www.processing.org kostenlos herunterladen und auf jedem Betriebssystem installieren. Mac-User können das Programm nach dem Entzippen auch ohne Installation per Doppelklick starten.
Außerdem findet ihr hier eine Zip-Datei mit der fertigen App und dem Bildmaterial. Das Tutorial ist erstmals in der PAGE 02.2020 erschienen – hier findet ihr die Processing-Schritte noch einmal grafisch und übersichtlich aufgearbeitet. Wenn ihr mehr über seine E-Learning-Plattform und seine Vision für Gestalter erfahren wollt, lest hier unser Interview mit ihm.
Außerdem findet ihr unten auch eine Video-Anleitung zum Rastern mit Processing von Tim.
Processing-App: Schritt für Schritt Fotos rastern
Wie man mit Processing eine App entwickelt, die Bilder in Punkte zerlegt, indem sie Pixel aus den Bilddaten extrahiert und ihre Farb- in Helligkeitswerte umwandelt, erklärt Tim Rodenbröker in diesem Tutorial für Einsteiger.
1. Processing herunterladen
Die Entwicklungsumgebung Processing kann man gratis unter www.processing.org herunterladen und auf jedem Betriebssystem installieren. Mac-User können das Programm nach dem Entzippen auch ohne Installation per Doppelklick aufs Symbol starten.
2. Processing-Editor erkunden
In die weiße Fläche des Editors schreibt man den Code. Oben links sind zwei Buttons zu sehen, mit denen man den Sketch starten und stoppen kann . »Sketch« ist die offizielle Bezeichnung für ein Processing-Projekt. Ein Sketch ist immer ein Ordner, der eine Datei mit dem Namen dieses Ordners und der Dateiendung .pde enthält. PDE steht für Processing Development Environment.
3. Bilddatei vorbereiten
Bevor wir wirklich starten, brauchen wir eine geeignete Bilddatei. Für unser Vorhaben funktionieren am besten eng beschnittene Porträts, auf denen die Person sehr gut erkennbar ist. Schneide dein Bild unbedingt quadratisch zu (500 mal 500 Pixel) und lege es als JPEG-Datei auf dem Desktop ab.
4. Erste Zeilen Code schreiben
Jeder Processing-Sketch basiert auf zwei elementaren Bausteinen: der setup()- und der draw()-Funktion. In setup() definieren wir Projekteigenschaften wie etwa die Größe des Sketches. Diese Funktion wird generell nur ein einziges Mal am Anfang der Laufzeit ausgeführt. Draw() beschreibt, was im Laufe der Zeit passieren soll, und läuft mit einem Tempo von 30 Frames pro Sekunde, bis man den Sketch mit der Stopptaste anhält. Merk dir einfach, dass innerhalb der geschweiften Klammern der draw()-Funktion der Code steht, der dann das Visual zeichnet.
void setup()
size(500,500);
}
void draw(){
}
5. Kreise erzeugen und bewegen
Mit der Funktion ellipse() lassen sich Kreise zeichnen. Sie nimmt vier Argumente entgegen, die jeweils die Position und die Größe der Form definieren. Die ersten beiden Argumente legen die Position (x und y) fest, die Argumente drei und vier die Breite und die Höhe. Wenn du die Code-Zeile in die draw-Funktion einfügst, kannst du die Ellipse mit der Maus über das Sketch-Fenster bewegen. Allerdings hat die Sache zwei Haken: Zum einen hinterlässt der Kreis eine ungewollte Spur und verhält sich dabei wie ein Pinsel.
Aus diesem Grund kommt in Schritt sechs die Background-Funktion ins Spiel. Zum anderen haben wir noch keine Farben definiert, sodass das Styling derzeit noch ziemlich lahm daherkommt.
void draw(){
background(200);
6. Hintergrundfarbe festlegen
Mit der background()-Funktion färben wir das Sketch-Fenster mit einer Hintergrundfarbe.
Die background()-Funktion nimmt eine Farbe als Argument entgegen. 0 steht für Schwarz und 255 für Weiß. Die Zahl 200 zwischen den Klammern ergibt einen relativ hellen Grauton.
void draw(){
background(200);
7. Kontur und Füllung definieren
Wie in jedem anderen Designprogramm hat auch in Processing jede geometrische Form eine Kontur und eine Füllung.
Diese Eigenschaften können wir mit bestimmten Funktionen steuern. Angenommen, wir möchten schwarze, konturlose Kreise zeichnen. In diesem Fall deaktivieren wir zunächst die Kontur mit noStroke() und legen mit fill() die Füllfarbe fest: Die 0 in der zweiten Zeile steht hier für reines Schwarz.
noStroke();
fill(0);
ellipse(mouseX,mouseY,80,80);
}
8. Loops bestimmen
Mit einer sogenannten for-Schleife befehlen wir dem Sketch, eine bestimmte Aktion mehrfach auszuführen. Die erste Zeile im folgenden Script-Abschnitt kann schon ganz schön überfordern, aber lasst euch nicht irremachen: In 99 Prozent aller Fälle muss man sich über das Code-Kauderwelsch keine Gedanken machen. Wichtig ist hier erst mal nur die Zahl 100, die angibt, wie oft Processing die Aktion durchführen soll. Im folgenden Beispiel zeichnet Processing 100 Ellipsen.
for (int i = 0; i < 100; i++) {
ellipse(mouseX,mouseY,80,80);
}
Das ergibt hier jedoch keinen Sinn, da alle 100 Ellipsen übereinanderliegen und die vorderste Ellipse alle darunterliegenden verdeckt. Im nächsten Code-Block nutze ich die random()-Funktion, die einen Von-bis-Bereich als Argument entgegennimmt und eine dazwischenliegende zufällige Zahl zurückgibt. Mit dieser Funktion kann ich den Kreisen eine zufällige Position geben.
for (int i = 0; i < 100; i++) {
ellipse(random(0,width),random(9,height),80,80);
}
9. Mit Variablentypen umgehen
Wie jede andere Programmiersprache merkt Processing sich Informationen, indem es diese in Variablen speichert. Allerdings muss man dafür immer einen Variablentyp bestimmen. Sie fungieren als kleine Datenspeicher, die jede Art von Information enthalten können. Hier ein praktisches Beispiel: Angenommen, wir möchten mehreren geometrischen Formen eine einheitliche Größe geben. Möglich macht dies der Variablentyp integer, abgekürzt int, der die Größe als ganze Zahl speichert. Es gibt noch unzählige andere Variablentypen, gleich erwähne ich noch den Variablentyp float, in dem man eine Zahl mit Nachkommastelle speichert.
int size = 80;
for (int i = 0; i < 100; i++) {
ellipse(random(0,width),random(9,height),size,size);
}
10. Raster zeichnen
Nun zeichnen wir aus Kreisen das Raster. Die Zahl der Rasterzellen auf der Horizontalen geben wir vorweg in einer Variablen oberhalb der setup-Zeile an – ich nenne die Variable immer tiles. Danach müssen wir sie in draw() verknüpfen und dann die Breite und Höhe der einzelnen Rasterzellen kalkulieren, indem wir die Breite des Sketches durch die Anzahl der Rasterzellen teilen.
float tiles = 100; // Variable initialisieren
tiles = mouseX/10;
float tileSize = width/tiles;
Klasse! Wir sind jetzt bereit, das Raster zu zeichnen. Dafür verwenden wir einen zweidimensionalen for-Loop, der die Grundvoraussetzung für das Zeichnen jeden Rasters ist. Innerhalb der verschachtelten for-Schleife haben wir Zugriff auf die Variablen x und y.
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
ellipse(x*tileSize,y*tileSize,5,5);
}
11. Das Bild einbinden
Perfekt! Da die Grundlage steht, können wir uns jetzt der Bilddatei widmen. Diese machen wir in unserem Sketch verfügbar, indem wir eine JPEG-Datei aufs Editor-Fenster ziehen. Processing kopiert sie automatisch in den »data«-Ordner im Sketch-Verzeichnis. Sobald dort eine Datei liegt, hat Processing Zugriff darauf.
Nun binden wir das Bild in unseren Sketch ein und speichern es in einer Variablen. Für Bilder bietet Processing den Variablentyp PImage. Wichtig ist, dass die Variable im Code über setup() steht und in setup() mit der Bilddatei verknüpft wird.
Im Code realisieren wir das folgendermaßen:
PImage img; // Variable initialisieren
void setup(){
size(500,500);
img = loadImage(“woman.jpg”); // Verknüpfung mit der Datei
img.resize(width,height);
}
void draw(){
}
12. Pixel aus dem Bild extrahieren
Als Nächstes extrahieren wir die Farbe aus den jeweiligen Pixeln des Bilds und wandeln diesen Farbwert nun in einen Helligkeitswert um. Dazu nutzen wir die brightness()-Funktion. Je nach Helligkeit speichert die Variable brightness einen numerischen Wert in dem Bereich 0 bis 255.
for (int x = 0; x < tiles; x++){
for (int y = 0; y < tiles; y++){
int pixelX = int(x*tileSize);
int pixelY = int(y*tileSize);
color pixel = img.get(pixelX,pixelY);
float brightness = brightness(pixel);
}
13. Die Rasterpunkte darstellen
Fast fertig! Jetzt müssen wir noch die Rasterpunkte zeichnen. Dazu koppeln wir den brightness-Wert an die Größe des Rasterpunkts.
for (int x = 0; x < tiles; x++){
for (int y = 0; y < tiles; y++){
int pixelX = int(x*tileSize);
int pixelY = int(y*tileSize);
color pixel = img.get(pixelX,pixelY);
float brightness = brightness(pixel);
ellipse(x*tileSize,y*tileSize, brightness, brightness);
}
Es gibt hier noch einen Haken: Die Kreise sind viel zu groß und bedecken jetzt das ganze Bild, sodass wir nur eine schwarze Fläche sehen.
Hier hilft uns die map()-Funktion, die den Wertebereich zwischen 0 und 255 auf einen neuen Wertebereich skaliert. Die map()-Funktion nimmt fünf Argumente entgegen: die Quelle, den Minimal- und Maximalwert des alten Wertebereichs sowie den Minimal- und den Maximalwert für den neuen Wertebereich.
for (int x = 0; x < tiles; x++){
for (int y = 0; y < tiles; y++){
int pixelX = int(x*tileSize);
int pixelY = int(y*tileSize);
color pixel = img.get(pixelX,pixelY);
float brightness = brightness(pixel);
float size = map(brightness,0,255,tileSize,0);
ellipse(x*tileSize, y*tileSize, size, size);
}
Processing-Tutorial im Video: Keep learning and happy coding!
In diesen wenigen Schritten steckt schon viel wertvolles Wissen über Programmierung. Der Zugang zu diesem Thema über visuelle Experimente ist noch relativ neu und hat bei mir ein Feuer entfacht. Vielleicht konnte ich euch ein kleines bisschen inspirieren, das Thema Code aus einer neuen Perspektive zu betrachten.
nach oben
Mehr über Processing-Spezialist Tim Rodenbröker
Tim Rodenbröker beschäftigt sich seit vielen Jahren mit der Vermittlung von Creative Coding in der Designausbildung und baut auf seiner Website derzeit eine E-Learning-Plattform dafür auf www.timrodenbroeker.de Erfahrt mehr über sein Konzept und die ersten Kurse zu Design, Kommunikation und Code unter www.page-online.de/interview-mit-tim