Michael Limberger
Need me? Email mike@limberger.ca
AI
Base64 Encoding Explained
How do you send a picture as text?
Computers store images as binary data: ones and zeros representing pixel colors. But web requests and JSON (the format Ollama uses) are text-based. You cannot just paste binary into a text message.
The solution: Base64 encoding.
What Base64 is
Base64 is a way to represent binary data using only text characters. It takes any file (image, audio, PDF, whatever) and converts it into a long string of letters, numbers, and a few symbols.
A tiny 1 by 1 pixel image looks like this when Base64 encoded:
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGNg
YPj/HwADAgH/a7PLIQAAAABJRU5ErkJggg==
That gibberish IS the image, just represented as text. The receiving system decodes it back into binary.
Base64 increases file size by about 33 percent, because you are using text to represent binary. It lets you embed images directly in JSON requests.
Why the name
It uses 64 different characters to encode data: A-Z (26) + a-z (26) + 0-9 (10) + two symbols (+ and /).
Each character represents 6 bits of binary data. You do not need the math to use it.
Turning a PNG into a string
On macOS or Linux, use the base64 command.
Show me.
base64 -i image.png
This prints the encoded data to your terminal. The -i flag specifies the input file.
For scripts we want one line, no whitespace:
base64 -i image.png | perl -pe's~\s~~g'
Symbol map: the pipe | sends output to the next program. perl -pe runs a one-liner on each line and prints it. s~\s~~g is substitute: find whitespace (\s), replace with nothing, globally. The tildes are the delimiters instead of slashes.
Your terminal has a size limit
This bit us during testing. Your terminal has a maximum command length. On macOS, check it with:
Show me.
getconf ARG_MAX
You will see something like 1048576 (about 1 MB). Sounds like a lot, but Base64 inflates file size by 33 percent. A 750 KB image becomes a 1 MB string, which can exceed the limit.
If you get weird errors when sending large images, this is probably why. The fix: resize before encoding. Use sips (built into macOS):
sips --resampleHeightWidthMax 768 image.png --out resized.png
That shrinks the image so its longest side is 768 pixels. Plenty for vision model analysis. Keeps the Base64 string manageable.
Try it
Using any PNG you have:
Show me.
base64 -i yourimage.png | head -c 100
First 100 characters. You will see something like:
iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAIAAADwf7zUAAE...
Count the characters
Before sending to the API, verify the image is not too large:
base64 -i yourimage.png | perl -pe's~\s~~g' | wc -c
That shows the character count. If it is over 800,000 characters, resize first using sips.
Store it in a variable
For scripting, we store the encoded image in a shell variable:
Show me.
IMAGE_B64=$(base64 -i photo.png | perl -pe's~\s~~g')
The $(...) syntax runs the command and captures the output. Now IMAGE_B64 contains the entire encoded image as a string.
To verify it worked:
echo ${#IMAGE_B64}
That prints the length. You should see a large number (hundreds of thousands for a typical PNG).
Why this matters
When we send an image to Ollama, we put this Base64 string inside our JSON request. The vision model receives it, decodes it back to binary, and analyzes the actual image.
It is just a transport mechanism. The AI sees the original image, not the encoded gibberish.