Introduction
After explaining a straightforward workflow for creating an article image in the post Fast and Easy Image Generation with Fabric and OpenAI, an additional step can be incorporated into such a workflow. In this post, I would like to demonstrate how a brief description can be transformed into a freely scalable logo in SVG format using Fabric, DALL‑E, and vectorization tools.
SVG format, utilizing Fabric, DALL‑E, and command-line vectorization tools.
Prerequisites
As outlined in the previous article, the following prerequisites must be met:
- An OpenAI account and an OpenAI API key.
- A functional installation of Fabric. Please refer to Installation and Getting Started with Fabric – the Prompt Optimizer.
- The command-line tool jq for processing JSON data.
Additionally, the following command-line programs are required for this workflow:
- Autotrace: Converts simple bitmaps into vector graphics and supports colors.
- Potrace: Transforms monochrome bitmaps into more precise vector graphics.
- ImageMagick: A powerful command-line graphic tool, utilized here for converting bitmap graphics.
I employ Autotrace and Potrace for the creation of vector graphics, as they yield different results. More on that below.
All these programs can be easily installed on a Mac using Homebrew:
brew install jq autotrace potrace imagemagick
The Workflow
As with most workflows involving Fabric, this one begins with a text input, which may be provided either as a text file or a simple string, depending on the complexity of the description. This input is then processed by Fabric along with a specialized pattern optimized for logo creation. The result is a prompt which will be passed to a script that invokes DALL‑E with that prompt, saves the generated logo as PNG, and forwards its path to the next script. This subsequent script then converts the PNG into a vector-based SVG file.
The Logo Pattern
With the installation of Fabric, a pattern specifically optimized for logo creation is already available: create_logo
. I duplicated this folder in the Patterns directory, renaming it to create_mylogo
, and replaced the content of the included system.md with the following:
# 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:
This file can be tailored and further optimized to meet individual requirements. Having prepared the pattern, we now proceed to the next step: the actual creation of the logo.
The CreateLogo Script
This script takes the prompt from Fabric and passes it to DALL‑E via the OpenAI API. Initially, I intended to invoke DALL‑E 2 at a size of 512x512 for logo creation, as this would make image generation somewhat more cost-effective. However, I was ultimately convinced by the superior interpretation of the prompt and the quality of the results to generate the logos using DALL‑E 3 instead.
Overall, the script closely resembles the script for article image generation from the previous article, with the only difference being the use of a square format of 1024x1024 for the image size. The created logos are also stored in a different folder. At the end of the script, I have commented out the lines for saving the prompts. If these are to be retained for optimizing the pattern, the comment symbol must be removed from those lines. It is important to note that the script only outputs the path of the created PNG file!
As always, I save the script in the $HOME/Applications/
folder under the name CreateLogo
and mark it as executable with:
chmod +x $HOME/Applications/CreateLogo
And here is the script:
#!/bin/zsh
# Check if data is piped into the script
if [ -t 0 ]; then
# Check if data is piped into the script
exit 1
else
# Read all piped inputs
prompt=$(cat -)
fi
# The OpenAI API key should be set as an environment variable
api_key="$OPENAI_API_KEY"
# Create JSON payload
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}'
)
# Get the current date and time for the filename
timestamp=$(date +"%Y%m%d_%H%M%S")
# Execute the curl command and save the response
response=$(curl -s https://api.openai.com/v1/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $api_key" \
-d "$json_payload")
# Extract the image URL from the response
image_url=$(echo $response | jq -r '.data[0].url')
# Save the image with date and time in the filename
curl -s "$image_url" -o "$HOME/Pictures/CreateLogo/image_${timestamp}.png"
# Extract the revised prompt from the response
# revised_prompt=$(echo $response | jq -r '.data[0].revised_prompt')
# echo "$revised_prompt" > "$HOME/Pictures/CreateLogo/revised_prompt_${timestamp}.txt"
# echo "Revised prompt has been saved as prompt_${timestamp}.txt"
# Save the prompt created by Fabric in a text file
# echo "$prompt" > "prompt_${timestamp}.txt"
# echo "Prompt has been saved as prompt_${timestamp}.txt"
# Output success message
echo $HOME/Pictures/CreateLogo/image_${timestamp}.png
# Open the image
# open image_${timestamp}.png
Vectorization
As previously mentioned, I utilize two distinct command-line tools in this example to handle the conversion from PNG to the vector format SVG. Interestingly, I have only found these two tools, which are quite dated. There are several AI-based services available online, but they do not necessarily provide an API and can be rather expensive.
Both programs are command-line tools, but they cannot be easily integrated into a Fabric workflow, as they do not accept the standard input. Therefore, I have encapsulated them in scripts that take the file path of the PNG, initiate the processing, and then name the SVG accordingly.
The Autotrace Script
The script first checks whether a file has been provided, verifies the path, and ensures that it is indeed a PNG file. While this may not be crucial for the Fabric workflow, it is beneficial to have some error checks in place if the script is used “standalone.” In principle, Autotrace can process other bitmap formats as well, but since OpenAI generates PNG files, I restrict the script to this format.
After the checks, the path to the file and the name are separated, allowing the SVG to be saved under the same path and name, but with the .svg extension. The Autotrace tool is then invoked with the path of the PNG file and several options, and the SVG is saved. I have yet to systematically experiment with the options, as there is certainly potential for improved results.
#!/bin/bash
# Check if data has been passed through the pipe
if [ -t 0 ]; then
echo "Keine Datei übergeben."
exit 1
fi
# Read the filename from standard input
read -r input_file_path
# Check if the file path is empty or the file does not exist
if [ -z "$input_file_path" ] || [ ! -f "$input_file_path" ]; then
echo "Ungültiger Dateipfad: $input_file_path"
exit 1
fi
# Check if the file is a PNG file
if [[ "$input_file_path" != *.png ]]; then
echo "Die Datei ist keine PNG-Datei."
exit 1
fi
# Extract the input filename without path and extension
input_filename=$(basename "$input_file_path")
input_basename="${input_filename%.*}"
# Determine the directory of the input file
input_dir=$(dirname "$input_file_path")
# Set the output file path
output_file="$input_dir/$input_basename.svg"
# Call autotrace with the specified parameters
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
open $output_file
This script will be saved as svgAuto
in the $HOME/Applications folder
and marked as executable.
Now the script can be tested. The echo command is used since the path, not the content of the PNGs, is being passed.
echo /path/to/logo.png | svgAuto
Here is an example with the source image logo.png:
And her the SVG converted by Autotrace:
The result is not bad, but it does not closely match the original contours. Adjusting the values of the options or utilizing additional options could lead to improvements. More options and further information can be easily accessed in the terminal using the command man autotrace
.
The Potrace Script
Potrace can only create monochrome vector files. It operates on grayscale or colored bitmaps using thresholds that may need to be adjusted based on the type of image. However, I have found the default settings, as used in the script, to be sufficient thus far. Interestingly, Inkscape also utilizes Potrace for vectorization but can process colored bitmaps as well. As far as I understand, it vectorizes the image in multiple passes with different thresholds and then reconstructs the created SVGs at the end. For my purposes, the monochromatic output is adequate. Additional options for Potrace can also be accessed in the terminal using man potrace
.
The script that works with the Potrace program functions similarly to the one with Autotrace. The first part is identical. The file path is passed using echo, parsed, and then used to save the SVG file in the correct location with the appropriate name.
Before Potrace is invoked, the original PNG image is first converted to the PGM format using the command magick
, which was installed with ImageMagick, since Potrace cannot process PNG files. After that, Potrace is called with several options that can also be optimized or supplemented, just like in the Autotrace script.
#!/bin/bash
# Check if data has been passed through the pipe
if [ -t 0 ]; then
echo "Keine Datei übergeben."
exit 1
fi
# Read the file path from standard input
read -r input_file_path
# Verify if the file path is empty or if the file does not exist
if [ -z "$input_file_path" ] || [ ! -f "$input_file_path" ]; then
echo "Ungültiger Dateipfad: $input_file_path"
exit 1
fi
# Check if the file is a PNG file
if [[ "$input_file_path" != *.png ]]; then
echo "Die Datei ist keine PNG-Datei."
exit 1
fi
# Determine the directory and filename of the input file without extension
input_dir=$(dirname "$input_file_path")
input_basename=$(basename "$input_file_path" .png)
# Create the PGM output path
output_pgm_path="$input_dir/$input_basename.pgm"
# Create the SVG output path
output_svg_path="$input_dir/$input_basename.svg"
# Step 1: Convert PNG to PGM using ImageMagick
magick "$input_file_path" "$output_pgm_path"
if [ $? -ne 0 ]; then
echo "Fehler bei der Konvertierung von PNG zu PGM."
exit 1
fi
# Step 2: Convert PGM to SVG using 'potrace' with the specified options
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
# Successful conversion
echo $output_svg_path
# Clean up the temporary file
rm "$output_pgm_path"
exit 0
The result of vectorization with Potrace of the previously used original PNG appears as follows (consider temporarily disabling dark mode if only a black area is visible):
The SVG converted by Potrace has traced the contours much more accurately than Autotrace. Furthermore, the paths can be edited more effectively in programs such as Inkscape or Affinity Designer. If you are in dark mode, you may see nothing due to the fact that the above SVG is transparent. There should actually be an option in Potrace that fills the background, but it somehow did not work for me. However, there is a solution, as SVG is an XML text format, allowing for relatively easy insertion of a definition that ensures the background turns white. The header section of the SVG file must be supplemented with the line
<rect width="100%" height="100%" fill="white"/>
before the <metadata>
tag. This can be accomplished, if desired, by the following script, which is specifically tailored to SVG files generated by Potrace and may not work with every SVG file:
#!/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"
Like all other scripts, this one is saved in the folder $HOME/Applications
as add_white_background
. The corresponding invocation can then look something like this:
echo "/path/to/image.png" | potrace | add_white_background
While the Autotrace solution can handle colors to a certain extent, the result is not as close to the original, and the created paths are essentially just path fragments. However, it may suffice to quickly generate a reasonably similar vector graphic for scaling images. Additionally, it is possible that better results can be achieved through improved settings in the options. I would be grateful for any tips.
The complete Call
Now all the components are combined, and a logo can be created, for instance, for a blog about Obsidian.
echo "Create a logo for a blog that discusses the PKM tool Obsidian" | fabric -sp create_mylogo | CreateLogo | svgPot | add_white_background
With this invocation, the following image was created, which captures the theme quite well:
As well as the corresponding SVG:
If the Autotrace script is used instead of the Potrace script, the SVG file for the same PNG appears as follows. Here, adjustments to the threshold would be necessary to achieve a better result. Note: Be sure to disable dark mode here as well! The script for setting the white background would need to be adjusted for the SVGs generated by Autotrace.
Conclusion
DALL‑E, Autotrace, and Potrace provide an efficient means of quickly generating vector graphics. As I mentioned in my conclusion in the article Fast and Easy Image Generation with Fabric and OpenAI, while these workflows are indeed helpful, they are primarily intended a source of inspiration and starting points for your own ideas.
This article also aims to demonstrate how powerful and flexible the combination of various tools with Fabric can be, offering a solid foundation for further automation and optimization of graphics processes.
I hope to achieve these two goals. The comment section is open for ideas, feedback, praise, or whatever else you may wish to share.
Leave a Reply