Einleitung
Nachdem ich im vorherigen Artikel Schnelle und einfache Bildgenerierung mit Fabric und OpenAI einen einfachen Workflow vorgestellt habe, um für einen Artikel ein Schmuckbild zu erstellen, möchte ich mit diesem Artikel einen Schritt weitergehen und zeigen, wie aus einer kurzen Beschreibung, mithilfe von Fabric, DALL‑E und Vektorisierungstools, ein frei skalierbares Logo im SVG-Format entsteht.
Voraussetzungen
Wie im vorhergehenden Artikel sind folgende Voraussetzungen zu erfüllen:
- Ein OpenAI-Account und einen OpenAI-API-Key (OpenAI Platform).
- Eine lauffähige Installation von Fabric. Siehe Installation und erste Schritte mit Fabric – dem Prompt-Optimierer.
- Das Kommandozeilenprogramm jq, um JSON-Daten zu verarbeiten.
Für diesen Workflow werden noch folgende Kommandozeilenprogramme benötigt:
- Autotrace: Konvertiert einfache Bitmaps in Vektorgrafiken und unterstützt Farben.
- Potrace: Konvertiert monochrome Bitmaps in präzisere Vektorgrafiken.
- ImageMagick: Leistungsfähiges Kommandozeilen-Grafiktool, hier genutzt zur Konvertierung von Bitmap-Grafiken.
Ich nutze Autotrace und Potrace für die Erstellung der Vektorgrafiken, da sie unterschiedliche Ergebnisse produzieren. Aber dazu unten mehr.
Diese Programme lassen sich auf dem Mac am einfachsten mit Homebrew installieren:
brew install autotrace potrace imagemagick
Der Workflow
Wie die meisten Workflows mit Fabric startet auch dieser mit einer Texteingabe, je nach Komplexität der Beschreibung entweder mit einer Textdatei oder mit einem einfachen String. Diese Eingabe wird dann von Fabric und einem speziellen, auf Logos optimierten Pattern bearbeitet. Der daraus generierte Prompt wird an ein Skript übergeben, das DALL‑E mit diesem Prompt aufruft, das generierte PNG speichert und dessen Pfad an das nächste Skript übergibt. Dieses konvertiert dann das PNG in eine vektorbasierte SVG-Datei.
Das Logo-Pattern
Mit der Installation von Fabric steht bereits ein Pattern zur Verfügung, das speziell für die Logoerstellung optimiert wurde: create_logo
. Diesen Ordner im Patterns-Ordner habe ich dupliziert und in create_mylogo
umbenannt und den Inhalt der enthaltenen system.md
durch folgenden Inhalt ersetzt:
# IDENTITY and PURPOSE You create simple, elegant, and impactful company logos based on the input given to you. The logos are super minimalist, minimal colors. Take a deep breath and think step by step about how to best accomplish this goal using the following steps. # OUTPUT SECTIONS - Output a prompt that can be sent to an AI image generator for a simple and elegant logo that captures and incorporates the meaning of the input sent. - The prompt should take the input and create a simple, vector graphic logo description for the AI to generate. - This logo should be optimal for convert it with potrace. Only white backgound. No Colors, No Text. - Make an very detailed description with 100 words # OUTPUT INSTRUCTIONS - Ensure the description asks for a simple, vector graphic logo with a white background. - Ensure the description asks for minimalist vector graphic logo. - Ensure the description asks for a design that emphasizes smooth curves and geometric shapes. - Ensure the description asks for an entirely in black on a white background. - Ensure the description asks for stylized form of all objects. - Do not output anything other than the raw image description that will be sent to the image generator. - You only output human-readable Markdown. - Do not output warnings or notes —- just the requested sections. # INPUT: INPUT:
Natürlich kann diese Datei an die eigenen Anforderungen angepasst und weiter optimiert werden. Nachdem wir nun das Pattern vorbereitet haben, gehen wir zum nächsten Schritt über: die eigentliche Erstellung des Logos.
Das CreateLogo Skript
Dieses Skript übernimmt den Prompt von Fabric und übergibt ihn über die OpenAI API an DALL‑E. Eigentlich wollte ich für die Erstellung eines Logos DALL-E‑2 in der Größe 512x512 aufrufen, da damit die Bildgenerierung etwas kostengünstiger ist. Am Ende hat mich aber die bessere Interpretation des Prompts und die Qualität des Ergebnisses davon überzeugt, doch eher die Logos mit DALL-E‑3 zu generieren.
Im Großen und Ganzen entspricht das Skript dem Skript zur Artikelbildgenerierung aus dem vorherigen Artikel. Nur für die Bildgröße wird das quadratische Format 1024x1024 verwendet. Die erstellten Logos werden auch in einem anderen Ordner gespeichert. Am Ende des Skripts habe ich die Zeilen für die Speicherung der Prompts auskommentiert. Falls diese z.B. für die Optimierung des Patterns eingesehen werden sollen, muss in diesen Zeilen das Kommentarzeichen entfernt werden. Wichtig ist, dass das Skript nur den Pfad der erstellten PNG-Datei ausgibt!
Wie immer speichere ich das Skript in dem Ordner $HOME/Applications/
mit dem Namen CreateLogo
und markiere es mit chmod +x
als ausführbar.
#!/bin/zsh # Überprüfen, ob Daten in das Skript gepiped werden if [ -t 0 ]; then # Es wurden keine Eingaben gepiped exit 1 else # Alle gepipeten Eingaben lesen prompt=$(cat -) fi # Der OpenAI API-Schlüssel sollte als Umgebungsvariable gesetzt sein api_key="$OPENAI_API_KEY" # JSON-Nutzlast erstellen json_payload=$(jq -n \ --arg model "dall-e-3" \ --arg prompt "$prompt" \ --argjson n 1 \ --arg size "1024x1024" \ '{model: $model, prompt: $prompt, n: $n, size: $size}' ) # Aktuelles Datum und Uhrzeit für den Dateinamen abrufen timestamp=$(date +"%Y%m%d_%H%M%S") # Den curl-Befehl ausführen und die Antwort speichern response=$(curl -s https://api.openai.com/v1/images/generations \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $api_key" \ -d "$json_payload") # Die Bild-URL aus der Antwort extrahieren image_url=$(echo $response | jq -r '.data[0].url') # Das Bild mit Datum und Uhrzeit im Dateinamen speichern curl -s "$image_url" -o "$HOME/Pictures/CreateLogo/image_${timestamp}.png" # Den überarbeiteten Prompt aus der Antwort extrahieren # revised_prompt=$(echo $response | jq -r '.data[0].revised_prompt') # echo "$revised_prompt" > "$HOME/Pictures/CreateLogo/revised_prompt_${timestamp}.txt" # echo "Revised Prompt wurde als prompt_${timestamp}.txt gespeichert" # Den von Fabrix erstellten Prompt in einer Textdatei speichern # echo "$prompt" > "prompt_${timestamp}.txt" # echo "Prompt wurde als prompt_${timestamp}.txt gespeichert" # Erfolgsnachricht ausgeben echo $HOME/Pictures/CreateLogo/image_${timestamp}.png # Das bild wird geöffnet # open image_${timestamp}.png
Das Vektorisieren
Wie schon erwähnt, nutze ich in diesem Beispiel zwei unterschiedliche Kommandozeilenprogramme, die den Teil der Umwandlung von dem PNG in das Vektorformat SVG übernehmen. Ich habe nur diese beiden Tools gefunden, die interessanterweise schon recht alt sind. Es gibt im Netz einige KI-basierte Services, die aber nicht unbedingt eine API zur Verfügung stellen und teilweise auch recht teuer sind.
Beide Programme sind zwar Kommandozeilen-Tools, lassen sich aber nicht so ohne Weiteres in einen Fabric-Workflow einbauen, da sie nicht den Standard-Input aufnehmen. Daher habe ich sie beide in Skripte eingepackt, die den Dateipfad des PNGs aufnehmen, die Verarbeitung starten und dann das SVG entsprechend benennen.
Das Autotrace Skript
Das Skript testet zunächst, ob überhaupt eine Datei übergeben wurde, ob der Pfad stimmt und ob es sich um eine PNG-Datei handelt. Das ist für den Fabric-Workflow vielleicht nicht so wichtig, aber falls das Skript z.B. „standalone” verwendet wird, ist es hilfreich, einige Fehlerprüfungen zu haben. Im Prinzip kann Autotrace auch andere Bitmap-Formate verarbeiten, aber da OpenAI PNG-Dateien erzeugt, beschränke ich mich in dem Skript auf dieses Format.
Nach den Prüfungen werden der Pfad zur Datei und der Name separiert, damit das SVG unter dem gleichen Pfad und Namen, nur mit der Extension .svg
, gespeichert werden kann.
Jetzt wird Autotrace mit dem Pfad der PNG-Datei und einigen Optionen aufgerufen und das SVG gespeichert. Die Optionen habe ich noch nicht systematisch ausprobiert. Da gibt es sicher noch Potential für bessere Ergebnisse.
#!/bin/bash # Überprüfen, ob Daten über die Pipe übergeben wurden if [ -t 0 ]; then echo "Keine Datei übergeben." exit 1 fi # Lese den Dateinamen aus der Standardeingabe read -r input_file_path # Überprüfen, ob der Dateipfad leer ist oder die Datei nicht existiert if [ -z "$input_file_path" ] || [ ! -f "$input_file_path" ]; then echo "Ungültiger Dateipfad: $input_file_path" exit 1 fi # Überprüfen, ob die Datei eine PNG-Datei ist if [[ "$input_file_path" != *.png ]]; then echo "Die Datei ist keine PNG-Datei." exit 1 fi # Den Namen der Eingabedatei ohne Pfad und Erweiterung extrahieren input_filename=$(basename "$input_file_path") input_basename="${input_filename%.*}" # Verzeichnis der Eingabedatei ermitteln input_dir=$(dirname "$input_file_path") # Ausgabedateipfad festlegen output_file="$input_dir/$input_basename.svg" # Aufruf von autotrace mit den angegebenen Parametern if ! autotrace "$input_file_path" \ --output-file "$output_file" \ --input-format png \ --output-format svg \ --color-count 256 \ --background-color FFFFFF \ --despeckle-level 20 \ --remove-adjacent-corners \ --corner-threshold 0.5 \ --line-threshold 1; then echo "Fehler bei der Konvertierung mit autotrace." exit 1 fi echo $output_file
Dieses Skript wird als svgAuto
im Ordner $HOME/Applications
gespeichert und als ausführbar markiert.
Nun kann das Skript getestet werden. Es wird dabei der echo
Befehl verwendet, da der Pfad und nicht der Inhalt der PNGs übergeben wird.
echo /path/to/logo.png | svgAuto
Hier als Beispiel das Bild logo.png
Sowie hier das generierte SVG logo.svg
:
Das Ergebnis ist nicht schlecht, aber nicht ganz nah an den Originalkonturen. Hier könnten andere Werte bei den Optionen oder auch die Verwendung weiterer Optionen eine Verbesserung bringen. Mehr Optionen und weitere Informationen können am einfachsten im Terminal mit dem Befehl man autotrace
abgerufen werden.
Das Potrace Skript
Potrace kann nur monochrome Vektordateien erstellen. Es arbeitet bei Graustufen oder farbigen Bitmaps mit Schwellenwerten, die ggf. an die Art des Bildes angepasst werden müssen. Allerdings war für mich die Standardeinstellung, wie in dem Skript, bisher ausreichend. Interessant in diesem Zusammenhang ist, dass Inkscape intern auch Potrace zum Vektorisieren verwendet, aber auch farbige Bitmaps damit verarbeiten kann. Soweit ich das verstanden habe wird dafür das Bild in mehreren Durchläufen mit unterschiedlichen Schwellenwerten vektorisiert und dann diese erstellten SVGs am Ende wieder zusammengebaut. Aber für meine Zwecke reicht die monochromatische Ausgabe. Auch für Potrace können weitere Optionen mit man potrace
im Terminal abgerufen werden.
Das Skript, das mit dem Programm Potrace arbeitet, funktioniert ähnlich wie das mit Autotrace. Der erste Teil ist identisch. Der Dateipfad wird mit echo
übergeben, auseinandergebaut und um die SVG-Datei an der richtigen Stelle mit dem richtigen Namen zu speichern.
Bevor aber Potrace aufgerufen wird, wird das Original-PNG-Bild zunächst mit dem Befehl magick
, der mit imagemagick
installiert wurde, in das PGM-Format konvertiert, da Potrace keine PNG-Dateien verarbeiten kann. Danach wird Potrace mit einigen Optionen aufgerufen, die ebenso wie bei dem Autotrace-Skript optimiert oder ergänzt werden können.
#!/bin/bash # Überprüfen, ob Daten über die Pipe übergeben wurden if [ -t 0 ]; then echo "Keine Datei übergeben." exit 1 fi # Lese den Dateipfad aus der Standardeingabe read -r input_file_path # Überprüfen, ob der Dateipfad leer ist oder die Datei nicht existiert if [ -z "$input_file_path" ] || [ ! -f "$input_file_path" ]; then echo "Ungültiger Dateipfad: $input_file_path" exit 1 fi # Überprüfen, ob die Datei eine PNG-Datei ist if [[ "$input_file_path" != *.png ]]; then echo "Die Datei ist keine PNG-Datei." exit 1 fi # Verzeichnis und Dateiname der Eingabedatei ohne Erweiterung ermitteln input_dir=$(dirname "$input_file_path") input_basename=$(basename "$input_file_path" .png) # Erstellen des PGM-Ausgabepfads output_pgm_path="$input_dir/$input_basename.pgm" # Erstellen des SVG-Ausgabepfads output_svg_path="$input_dir/$input_basename.svg" # Schritt 1: Konvertierung von PNG zu PGM mithilfe von ImageMagick magick "$input_file_path" "$output_pgm_path" if [ $? -ne 0 ]; then echo "Fehler bei der Konvertierung von PNG zu PGM." exit 1 fi # Schritt 2: Konvertierung von PGM zu SVG mithilfe von 'potrace' mit den angegebenen Optionen if ! potrace "$output_pgm_path" \ --svg \ --output="$output_svg_path" \ --turdsize 2 \ --turnpolicy black \ --alphamax 1 \ --opttolerance 0.2; then echo "Fehler bei der Konvertierung mit potrace." exit 1 fi # Erfolgreiche Konvertierung echo $output_svg_path # Bereinigen der Zwischendatei rm "$output_pgm_path" exit 0
Das Ergebnis einer Vektorisierung mit Potrace des obigen Original-PNG sieht dann so aus (ggf. den Darkmode kurz mal ausschalten, falls nur eine schwarze Fläche zu sehen ist):
Das von Potrace konvertierte SVG hat die Konturen viel genauer nachgezeichnet als Autotrace. Außerdem lassen sich die Pfade auch besser in Programmen wie Inkscape oder Affinity Designer bearbeiten.
Das Problem mit dem Darkmode liegt daran, dass das obige SVG transparent ist. Eigentlich sollte es dafür eine Option in Potrace geben die den Hintergrund füllt, das klappte bei diesem Bild irgendwie nicht. Es gibt jedoch eine Lösung dafür, denn SVG ist ein XML-Textformat, sodass man relativ leicht eine Definition einfügen kann, die dafür sorgt, dass der Hintergrund weiß wird. Es muss der Kopfbereich der SVG-Datei
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="1024.000000pt" height="1024.000000pt" viewBox="0 0 1024.000000 1024.000000" preserveAspectRatio="xMidYMid meet"> <metadata>
um die Zeile <rect width="100%" height="100%" fill="white"/>
vor dem Tag <metadata>
ergänzt werden. Das wird, falls gewünscht, von folgendem Skript erledigt, das allerdings auf die von Potrace erzeugten SVG-Dateien angepasst ist und nicht bei jeder SVG-Datei funktioniert:
#!/bin/zsh # Check if input is provided via a pipe if [ -t 0 ]; then echo "No file path provided through the pipe." exit 1 fi # Read the file path from the standard input (pipe) read -r input_file # Check if the file exists and is an SVG file if [ ! -f "$input_file" ] || [[ "$input_file" != *.svg ]]; then echo "Invalid or non-SVG file provided: $input_file" exit 1 fi # Create the output file path with the "_weiss" suffix output_file="${input_file%.svg}_weiss.svg" # Insert <rect> tag before <metadata> and save to new file sed '/<metadata>/i\ <rect width="100%" height="100%" fill="white"/>' "$input_file" > "$output_file" # Output the new file path echo "$output_file"
Wie alle anderen Skripte, wird dieses im Ordner $HOME/Applications
als add_white_background
gespeichert. Der entsprechende Aufruf kann dann z.B. so aussehen:
echo "/path/to/image.png" | potrace | add_white_background
Die Autotrace-Lösung kann zwar in gewissem Rahmen mit Farben umgehen, dafür ist das Ergebnis nicht so nah am Original und die erstellten Pfade sind eigentlich nur Pfadfragmente. Aber um schnell eine einigermaßen ähnliche Vektorgrafik zum Skalieren von Bildern zu erzeugen, mag es reichen. Außerdem kann es gut sein, dass durch bessere Einstellungen in den Optionen bessere Ergebnisse erreicht werden können. Für Tipps wäre ich dankbar.
Der ganze Aufruf
Nun sind alle Teile zusammen und es kann ein Logo z.B. für einen Blog über Obsidian erstellt werden.
echo "erstelle ein Logo für ein Blog in dem über das PKM Tool Obsidian geschrieben wird" | fabric -sp create_mylogo | CreateLogo | svgPot | add_white_background
Beim diesem Aufruf wurde dieses Image, das das Thema recht gut trifft, erstellt:
Sowie das entsprechende SVG:
Wird das Autotrace-Skript statt des Potrace-Skript verwendet wird, sieht die SVG Datei bei dem gleichen PNG, so aus. Hier müsste etwas an dem Schwellenwert gearbeitet werden, um ein besseres Ergebnis zubekommen. Achtung: Auch hier den Darkmode ausstellen! Das Skript zum Setzen des weißen Hintergrunds müsste für die SVG, die von Autotrace erstellt werden, angepasst werden.
Fazit
DALL‑E, Autotrace und Potrace bietet eine effiziente Möglichkeit, schnell Vektorgrafiken zu erzeugen. Wie bereits in meinem Fazit im Artikel Schnelle und einfache Bildgenerierung mit Fabric und OpenAI erwähnt, sind diese Workflows zwar hilfreich, aber in erster Linie als Inspirationsquelle und Ausgangspunkt für eigene Ideen gedacht.
Dieser Artikel soll auch zeigen, wie leistungsfähig und flexibel die Kombination von verschiedenen Tools mit Fabric sein kann, und bietet eine solide Grundlage für die weitere Automatisierung und Optimierung von Grafikprozessen.
Schreibe einen Kommentar