Making a 88x31 button book using ImageMagick
Crafting a Literary 88x31 Button Book via ImageMagick
Introduction
If you have spent significant time navigating the depths of the internet—particularly the Small Web—you have likely encountered the 88x31 button.
While many are static, the nature of digital displays allows for rapid visual shifts, leading to the creation of animated buttons. However, I've noticed that most animations are merely designed to be flashy intended to catch the eye or cycle through a few brief words. I wanted to push this concept further.
Technical Constraints & Dimensions
I was surprised to discover that the GIF format is incredibly permissive regarding frame count and resolution. The theoretical maximum resolution is:
This equates to roughly 4,295 megapixels. In contrast, our project is constrained to a tiny canvas (approximately megapixels).
| Feature | Standard GIF Limit | Our Button |
|---|---|---|
| Width | 65,536 px | 88 px |
| Height | 65,536 px | 31 px |
| Total Area | Gigapixels | Megapixels |
Because of this minuscule size, standard typography fails. For instance, Arial typically requires a minimum height of 10 pixels to remain legible, which would limit us to roughly eleven words per frame.
Seeking Alternative Typography
To bypass this, we need fonts specifically engineered for extreme low-resolution environments. While some fonts exist as small as , I found TomThumb to be the ideal "golden middle" for this project.
The Workflow: From Novel to GIF
1. Acquiring the Text
First, you need a plain text version of your chosen book. You can achieve this via:
- OCR: Extracting text from a physical copy.
- Conversion: Turning
.EPUBor.PDFfiles into text. - Direct Download: Finding a
.txtfile (e.g., Moby Dick from Project Gutenberg).
Note: After downloading, I manually removed the licensing information from the beginning and end of the file to keep the content pure.
2. Formatting the Layout
Given our canvas and a font size of (which includes characters plus spacing), we can fit 5 rows of 22 characters.
Since ImageMagick struggles with complex text layout, it is more efficient to handle the formatting using POSIX tools.
The specific command pipeline is as follows:
cat input.txt | tr '\n' ' ' | tr -d '\r' | fold -s -w 22 > 22w.txt
cat: Streams the file.tr '\n' ' ': Flattens the text into a single line.fold -s -w 22: Breaks the line into 22-character segments without splitting words.
3. Cleaning the Data
The fold command often mishandles multibyte characters. To fix this, I used grep to identify non-ASCII characters:
grep -P -n '[^\x00-\x7F]' input.txt
Then, I used sed to replace them (e.g., replacing curly quotes with straight ones):
sed -i 's/”/"/g' .
Additionally, to provide visual breathing room between chapters, I inserted extra newlines:
sed -i 's/CHAPTER /\n\n\nCHAPTER /g' input.txt
Generating the Animation
Step A: Initial Render
Using the tom.ttf font located in the local directory, run:
cat 22w.txt | convert -page 88x39+0+0 -background white -fill black -font tom.ttf -pointsize 6 text:- high.gif
Crucial Detail: ImageMagick tends to add an unwanted bottom margin. To compensate, I rendered the image 8 pixels taller () than the final target.
Step B: Cropping and Timing
To finalize the dimensions and set the speed, use the following:
convert high.gif -set delay 600 -coalesce -repage 0x0 -crop 88x31+0+0 +repage good.gif
I set the delay to 600 (approximately 6 seconds per frame), which feels appropriate for reading.
Enhancements
Python Bonus: Centering the Text
To avoid the text hugging the left edge, I implemented a simple Python script to center the strings:
#!/usr/bin/python3
from math import floor
with open("22w.txt") as file:
for line in file:
# Calculate padding for centering
i = (22 - len(line.strip())) / 2
o = " " * floor(i) + line.strip()
print(o)
Final Result: The Full Novel
To save bandwidth, the examples provided here only cover the first chapter. However, the complete version of Moby Dick is available—a 4.2 MB masterpiece that takes over 19 hours to fully play through.
Project Checklist:
- Obtain plain text
- Clean non-ASCII characters
- Format to 22-character width
- Render with ImageMagick
- Crop to
- (Optional) Center text via Python