Publishing & Exhibition
Export, sign, and deploy Processing sketches for gallery installations, from cross-platform applications to Raspberry Pi and OpenProcessing.
Getting a Processing sketch out of the IDE and into a gallery, venue, or online platform requires attention to runtime dependencies, operating system signing requirements, and the operational realities of unattended installation hardware. This article covers the full path from export to archival documentation.
Export Application
Processing’s built-in export bundles your sketch with a Java runtime for each platform. Go to File > Export Application and select the target platforms (macOS, Windows, Linux). The result is a self-contained directory per platform:
MySketch/
application.macos/
MySketch.app
application.windows64/
MySketch.exe
lib/
application.linux64/
MySketch
lib/
Important cross-platform considerations:
- File paths: Use
sketchPath("data/file.txt")ordataPath("file.txt"), never absolute paths. These resolve correctly regardless of platform. - Case sensitivity: Linux file systems are case-sensitive; Windows and macOS (by default) are not. A
data/Image.pngloaded as"image.png"works on Windows but fails silently on Linux. - Font embedding: Call
createFont("MyFont.ttf", 18)and ensure the.ttffile is in thedata/folder. Do not rely on system fonts being installed. - Library natives: Third-party libraries with native components (OpenCV, Syphon) are platform-specific. Export for only the platforms the library supports.
Code Signing on macOS
Since macOS Catalina, unsigned applications are quarantined by Gatekeeper and refuse to open. For gallery deployment, you need an Apple Developer account and a signed, notarised build.
The export produces MySketch.app. Sign it:
# Sign all dylibs inside the app first
find MySketch.app/Contents -name "*.dylib" -exec \
codesign --force --sign "Developer ID Application: Your Name (TEAMID)" {} \;
# Sign the app bundle
codesign --force --deep --options runtime \
--sign "Developer ID Application: Your Name (TEAMID)" \
--entitlements entitlements.plist \
MySketch.app
A minimal entitlements.plist for a Processing sketch:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key><true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key><true/>
<key>com.apple.security.cs.disable-library-validation</key><true/>
</dict>
</plist>
Then notarise:
# Zip the app
zip -r MySketch.zip MySketch.app
# Submit for notarisation
xcrun notarytool submit MySketch.zip \
--apple-id "you@example.com" \
--team-id "YOURTEAMID" \
--password "@keychain:AC_PASSWORD" \
--wait
# Staple the ticket
xcrun stapler staple MySketch.app
Notarisation typically takes 1–5 minutes. The stapled app will open without Gatekeeper warnings on any Mac.
Raspberry Pi Deployment
A Raspberry Pi 4 (4GB RAM) runs Processing 4 adequately for 2D sketches without heavy shader work. Headless deployment with a fixed display server avoids requiring a keyboard at the venue.
Install Processing on Raspberry Pi:
curl https://processing.org/download/install-arm64.sh | sudo sh
Run headlessly with DISPLAY environment variable:
export DISPLAY=:0
/usr/local/bin/processing-java --sketch=/home/pi/sketches/MySketch \
--run &
Auto-start on boot via systemd:
# /etc/systemd/system/mysketch.service
[Unit]
Description=Processing Installation Sketch
After=graphical.target
[Service]
User=pi
Environment=DISPLAY=:0
ExecStart=/usr/local/bin/processing-java \
--sketch=/home/pi/sketches/MySketch --run
Restart=always
RestartSec=5
[Install]
WantedBy=graphical.target
Enable it:
sudo systemctl enable mysketch.service
sudo systemctl start mysketch.service
The service restarts automatically after a crash. Use journalctl -fu mysketch.service to tail logs remotely over SSH.
Prevent display sleep:
# In /etc/xdg/lxsession/LXDE-pi/autostart, add:
@xset s off
@xset -dpms
@xset s noblank
Writing a Tech Rider
A tech rider specifies what you need from a venue. Precision prevents last-minute scrambles.
TECHNICAL REQUIREMENTS — "Subdivision" by Jane Doe
Hardware:
- 1× Mac Mini M2, 8GB RAM, running macOS 14 (provided by artist)
OR 1× Windows 11 PC, i7, 16GB RAM, GTX 3060 or equivalent (venue supplied)
- 1× Full-HD projector (1920×1080), minimum 3000 ANSI lumens
- HDMI cable, max run 5m (longer runs require active repeater)
Software:
- Processing 4.3.1 (bundled in application export — no install needed)
- No internet connection required after installation
Physical:
- Dark room preferred; max ambient illuminance 50 lux
- Projection surface: matte white wall or 130" screen, 16:9 ratio
- Power: 1× standard outlet within 2m of computer
Runtime:
- Resolution: 1920×1080 @ 60fps
- Operating hours: continuous (sketch loops indefinitely)
- Restart procedure: double-click MySketch.app; sketch enters fullscreen in 3s
- Emergency stop: press Escape or close the window
Contact: jane@example.com +44 7700 900000
Documenting Generative Work
Archival documentation for generative work captures both the process and specific instances.
Recording parameters per output file:
void saveDocumented() {
String ts = year() + nf(month(),2) + nf(day(),2) + "-" + nf(hour(),2) + nf(minute(),2);
String base = sketchPath("archive/" + ts + "_seed" + seed);
saveFrame(base + ".png");
String[] meta = {
"title=Subdivision v1.2",
"seed=" + seed,
"date=" + ts,
"processingVersion=4.3.1",
"sketchHash=" + sketchHash(), // see below
"width=" + width,
"height=" + height,
"params=" + exportParams()
};
saveStrings(base + ".txt", meta);
}
String sketchHash() {
// MD5 or CRC of the main .pde file — ties output to exact code version
try {
java.io.File f = new java.io.File(sketchPath(sketchName + ".pde"));
byte[] b = loadBytes(f.getAbsolutePath());
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] hash = md.digest(b);
StringBuilder sb = new StringBuilder();
for (byte byt : hash) sb.append(String.format("%02x", byt));
return sb.toString().substring(0, 8);
} catch (Exception e) { return "unknown"; }
}
OpenProcessing.org
OpenProcessing hosts Processing and p5.js sketches as interactive browser applets. Processing 4 exports to JavaScript via its JavaScript mode, but the most reliable route for complex sketches is p5.js rewrite.
For pure Processing Java sketches, upload the .pde files directly. OpenProcessing handles compilation server-side for simpler sketches. For library-dependent work, a libraries.txt in the upload specifies which libraries to include.
GitHub for Processing Sketches
A .gitignore for a Processing project:
# Processing build output
application.linux64/
application.macos/
application.windows64/
*.class
# Output files (large — track separately or exclude)
output/*.png
output/*.svg
archive/
# macOS
.DS_Store
# Java
*.jar
!data/*.jar
Keep data/ assets in the repo for reproducibility. For large asset files (video, high-res images), use Git LFS:
git lfs install
git lfs track "*.png" "*.mov" "*.wav"
git add .gitattributes
Complete Exhibition Startup Script
A shell script that initialises the environment, verifies the display, and launches the sketch with logging:
#!/usr/bin/env bash
# launch-installation.sh
SKETCH_DIR="$HOME/sketches/MySketch"
LOG_FILE="$HOME/logs/installation-$(date +%Y%m%d-%H%M%S).log"
PROCESSING_BIN="/usr/local/bin/processing-java"
mkdir -p "$HOME/logs"
echo "=== Installation startup $(date) ===" | tee -a "$LOG_FILE"
# Ensure display is up
export DISPLAY=:0
if ! xdpyinfo >/dev/null 2>&1; then
echo "ERROR: No display on :0. Is Xorg running?" | tee -a "$LOG_FILE"
exit 1
fi
# Disable screen blanking
xset s off -dpms 2>>"$LOG_FILE"
# Kill any stale instance
pkill -f "processing-java" 2>/dev/null
sleep 2
echo "Launching sketch..." | tee -a "$LOG_FILE"
# Run indefinitely; restart on crash
while true; do
$PROCESSING_BIN --sketch="$SKETCH_DIR" --run >> "$LOG_FILE" 2>&1
EXIT_CODE=$?
echo "Sketch exited with code $EXIT_CODE at $(date). Restarting in 5s..." \
| tee -a "$LOG_FILE"
sleep 5
done
Make it executable and drop a systemd unit around it as described in the Raspberry Pi section. Set up remote SSH access so you can pull logs and restart the sketch during the exhibition without being physically present.
Exhibition Checklist
Before opening day, run through this list:
Pre-install:
[ ] Application signed and notarised (macOS) or tested on target OS
[ ] All data files present in exported application
[ ] sketch runs for 8+ hours without memory leak (check with top/Activity Monitor)
[ ] frameRate() measured at venue resolution and projector
Hardware:
[ ] Power connected to UPS (uninterruptible power supply)
[ ] Display auto-on after power cut confirmed
[ ] Startup script set to auto-launch on login
[ ] Remote SSH access tested from external network
Opening:
[ ] Emergency stop procedure briefed to gallery staff
[ ] Log file location noted for diagnosis
[ ] Contact number left with venue
[ ] Archive of current output images stored off-site
An installation that runs unattended for weeks requires the same discipline as any production software deployment. The checklist, the startup script, and the tech rider are as much a part of the work as the code itself.