Artikel

Wort als Bild – Processing

Ein kleines Programm, dass aus Wörtern und Sätzen Bilder generiert.

Die Aufgabe bzw. Grundidee richtet sich nach dem Motto des diesjährigen Weltformat Graphic Design Festivals: Designing Tools. Es geht um Werkzeuge und Instrumente der Gestaltung. Ich entwickelte ein Programm in Processing, welches aus gegebenen Wörtern und Sätzen Bilder generiert.

Das unten stehende Programm funktioniert sehr einfach ausgedrückt folgendermaßen: Jedem Buchstaben und Zeichen wird eine Zahl zugeordnet. A = 1, B = 2, C = 3 etc. Ich entschied mich jedoch dafür, die Zeichen nach ihrer prozentualen Häufigkeit im deutschen Sprachgebrauch anzuordnen. Jetzt wird ein Text, Satz oder Wort in das Programm eingegeben, den Zeichen wird ihre jeweilige Nummer zugeordnet und in dieser Reihenfolge gespeichert. Aus diesen Zeichen ergeben sich daraufhin Formen und Farben. Angenommen das Wort „Hallo“ entspricht folgendem Zahlencode: „8 1 12 12 15“. Das Programm nimmt nach dem RGB Schema jetzt die erste, zweite und dritte Zahl um die Farbe zu bestimmen. Dann wird ein Dreieck mit den Koordinaten der dritten, vierten und fünften Zahl gezeichnet.

Hier einige Ergebnisse:

Von oben links nach unten rechts, reihenweise:

  • YyQqXxJjßÖöÄäÜüPpVvKkZzWwFfBbOoMmGgLlCcUuDdHhAaSsTtRrIiNnEe ,.!?;-’/() (Der Zeichensatz)
  • Am Anfang schuf Gott Himmel und Erde.
  • Ilsebill salzte nach.
  • I have a dream.
  • Die Würde des Menschen ist unantastbar. Sie zu achten und zu schützen ist Verpflichtung aller staatlichen Gewalt. Das Deutsche Volk bekennt sich darum zu unverletzlichen und unveräußerlichen Menschenrechten als Grundlage jeder menschlichen Gemeinschaft, des Friedens und der Gerechtigkeit in der Welt.
  • Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte, fand er sich in seinem Bett zu einem ungeheueren Ungeziefer verwandelt.
  • Hamilkar Schaß, mein Großvater, ein Herrchen von, sagen wir mal, einundsiebzig Jahren, hatte sich gerade das Lesen beigebracht, als die Sache losging.
  • That’s one small step for man but one giant leap for mankind.

Code:

Diverse Variablen

import java.util.*;

//Teiler für das erzeugte Feld (1000/41)
int trarr = 24; 

//Teiler für RGB (255/41)
int farbmult = 6; 

//Teiler für letzte else-if (Dreieckshäufigkeit)
int teiler = 0;
int anz = 0;
float fanz = 0; 

//Zeichensatz
String alphabet = "YyQqXxJjßÖöÄäÜüPpVvKkZzWwFfBbOoMmGgLlCcUuDdHhAaSsTtRrIiNnEe ,.!?;-’/()"; 

//Array zur Spiegelung des Zeichensatzes. Doppelte Zahlen stehen für Groß- und Kleinbuchstabe
int[] arr = {1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41};

//Das zu erzeugene Integer Array aus dem gegebenen String Array
int[] textarr = new int [0]; 

Beispieltexte

 //Beispielstrings
String bibel = "Am Anfang schuf Gott Himmel und Erde.";
String Butt = "Ilsebill salzte nach.";
String moon = "That’s one small step for man but one giant leap for mankind.";
String dream = "I have a dream.";

//String zum Einsetzen der Beispiele
String text = moon;

Setup für das Feld, die Arrays und Teiler um zu verhindern, dass nicht unnötig viele Objekte gezeichnet werden.

void setup() {

//Felderzeugung
  size(1000, 1000);
  background(0);

//Schleifen zum befüllen des Integers Arrays mit den zu den gegeben Zeichen passenden Zahlen. Dies passiert dynamisch (siehe tmp).
  for (int i = 0; i < text.length(); i++) {           
    for (int j=0; j < alphabet.length(); j++) {
      if (text.charAt(i) == alphabet.charAt(j)) {
        int [] tmp = new int[textarr.length+1];
        System.arraycopy(textarr, 0, tmp, 0, textarr.length);
        textarr = tmp;
        textarr[i]=arr[j];
      }
    }
  }

//Strichdicke
  strokeWeight(10);

//Teilerfestlegung zur späteren Benutzung in einer else-if Bedingung
  if (textarr.length>=100) {             
    fanz = (float)textarr.length/500*100;
    anz = (int)fanz;
  } else {
    anz=5;
  }

  smooth();
  noFill();
}

Das eigentliche Zeichenprogramm. Jeweils drei Bedingungen, da ich auch die Zeichen vor und hinter dem aktuellen berücksichtigen wollte. Heißt für den ersten und letzen Indes musste ich Sonderfälle schaffen.

void draw() {
 
//Schleife nach Array Länge
  for (int farbcounter=0; farbcounter<textarr.length; farbcounter++) {

//RGB Auswahl

//erstes Zeichen
    if (farbcounter==0) {
      stroke(textarr[farbcounter]*farbmult, textarr[farbcounter]*farbmult, textarr[farbcounter+1]*farbmult);

//letztes Zeichen
    } else if (farbcounter==textarr.length-1) {
      stroke(textarr[farbcounter]*farbmult, textarr[farbcounter-1]*farbmult, textarr[farbcounter]*farbmult);

//Restzeichen
    } else {
      stroke(textarr[farbcounter]*farbmult, textarr[farbcounter-1]*farbmult, textarr[farbcounter+1]*farbmult);
    }

//Zeichnen nach gegebenen Zeichen

//Erste beide Zeichen
    if (farbcounter==0 || farbcounter==1) {
      if (textarr[farbcounter]%3==0) {
        point(textarr[farbcounter], textarr[farbcounter+1]);
      } else if (textarr[farbcounter]%7==0) {
        line(textarr[farbcounter], textarr[farbcounter+1]*trarr, textarr[farbcounter], textarr[farbcounter]*trarr);
      } else if (textarr[farbcounter]==30) {
        triangle(textarr[farbcounter]*trarr, textarr[farbcounter]*trarr, textarr[farbcounter], textarr[farbcounter+1]*trarr, textarr[farbcounter+1]*trarr, textarr[farbcounter]*trarr);
      } else if (30<=textarr[farbcounter] && textarr[farbcounter]<=40) {
        fill(textarr[farbcounter]*farbmult, textarr[farbcounter+1]*farbmult, textarr[farbcounter+1]*farbmult);
        quad(textarr[farbcounter], textarr[farbcounter+1]*trarr, textarr[farbcounter], textarr[farbcounter]*trarr, textarr[farbcounter]*trarr, textarr[farbcounter]*trarr, textarr[farbcounter]*trarr, textarr[farbcounter+1]*trarr);
        noFill();
      } else {
      }

//Letzte zwei Zeichen
    } else if (farbcounter==textarr.length-1 || farbcounter == textarr.length-2) { 
      if (textarr[farbcounter]%3==0) {
        point(textarr[farbcounter], textarr[farbcounter-1]*trarr);
      } else if (textarr[farbcounter]%7==0) {
        line(textarr[farbcounter], textarr[farbcounter-1]*trarr, textarr[farbcounter]*trarr, textarr[farbcounter]*trarr);
      } else if (textarr[farbcounter]==30) {
        triangle(textarr[farbcounter], textarr[farbcounter]*trarr, textarr[farbcounter]*trarr, textarr[farbcounter-1]*trarr, textarr[farbcounter-1]*trarr, textarr[farbcounter]*trarr);
      } else {
        point(textarr[farbcounter], textarr[farbcounter-1]*trarr);
      }

//Restliche Zeichen
    } else if (farbcounter<textarr.length-2 && farbcounter>2) {

//Filter nach einem beliebig gewähltem Zeichen
      if (textarr[farbcounter]==10) { 
        fill(textarr[farbcounter]*farbmult, textarr[farbcounter-1]*farbmult, textarr[farbcounter+1]*farbmult, 63);
        quad(textarr[farbcounter+1]*trarr, textarr[farbcounter+2]*trarr, textarr[farbcounter-1]*trarr, textarr[farbcounter-2]*trarr, textarr[farbcounter+2], textarr[farbcounter-1], textarr[farbcounter-2]*trarr, textarr[farbcounter+1]);
        noFill();

//Filter nach gleichen hintereinander vorkommenden Zeichen
      } else if (textarr[farbcounter]==textarr[farbcounter+1]) { 
        line(textarr[farbcounter]*textarr[farbcounter], textarr[farbcounter-1]*trarr, textarr[farbcounter+1]*trarr, textarr[farbcounter]*trarr);

//Zeichen ohne Buchstaben
      } else if (31<=textarr[farbcounter] && textarr[farbcounter]<=41) { 
        point(textarr[farbcounter+2]*trarr, textarr[farbcounter-1]*trarr);

//Zeichen ohne Satz-/ Sonderzeichen
      } else if (textarr[farbcounter]<=30 && teiler%anz==0) { 
        triangle(textarr[farbcounter]*textarr[farbcounter], textarr[farbcounter-1]*textarr[farbcounter-1], textarr[farbcounter-1]*textarr[farbcounter-1], textarr[farbcounter+1]*textarr[farbcounter+1], textarr[farbcounter+1]*textarr[farbcounter-1], textarr[farbcounter-2]*textarr[farbcounter-1]);
      } else {
      }

//Teiler für die letzte else-if Bedingung
      teiler++; 
    }
  }

//Bild nur einmal malen
  noLoop();
}