Why I built Paint
Whenever I wanted to make a very small edit on my Debian laptop, crop a screenshot, add a quick arrow, or block out a small area, the system only had GIMP for editing images. Powerful, but heavy and slow for tiny, frequent tasks. I wanted something nimble: quick to open, easy to use, and focused on the common one-off edits people do dozens of times a day.
This project started from that itch and grew into a polished, compact Swing-based application (with GraalVM native builds and platform installers). The goal remains the same: make the small workflows lightning fast.
Short feature summary
Core drawing tools
Editing & image handling
UI & UX
File formats & packaging
Development timeline (high-level commit history)
This timeline is extracted from the project’s git history to tell the story of how Paint evolved.
- 2025-11-03, initial commit, project foundation and first implementation.
- 2025-11-04, undo/redo functionality and keyboard shortcuts were added, UI/ribbon alignment improved.
- 2025-11-05, File→Open added; installer scaffolding and CI release flows introduced (installer dev release commits).
- 2025-11-05, reachability metadata updates and Linux packaging/icon tweaks for installers.
- 2025-11-06, FlatLaf integration for modern look & feel; canvas size controls wired into status bar; tests improved.
- 2025-11-06, OS-specific native-image packaging settings and multi-line app description support for installers.
- 2025-11-07, reachability metadata and DEB packaging refinements.
- 2025-11-08, Transparent Highlighter and Drawing Arrows added; crop behavior and image placement refined; open image from CLI arguments.
- 2025-11-10, CI consolidation: native-image builds and OS packaging unified into a single workflow; Linux/macOS packaging improvements.
- 2025-11-11, final release staging and small fixes for canvas sizing and GUI status synchronization.
For the exact commit list and messages, see the repository’s git log history.
How it works (implementation notes)
- Canvas model: the app uses a persistent
BufferedImageas the backing canvas (DrawArea.cache) and a separate transparenthighlightLayerfor the highlighter tool. This makes highlights non-accumulating and easy to composite. - Drawing: continuous tools (pencil, eraser, highlighter) commit during dragging for a responsive feel; shapes/lines/arrow/bucket commit at mouse release (with an undo snapshot taken appropriately).
- Image placement: pasted or opened images are shown as a pending overlay with a dashed border; the user can drag them, press Enter to accept (commits to the backing image), or Esc to cancel (restores any cut area if moving a selection).
- Undo/Redo: snapshot-based (base + highlight) with a capped history size to keep memory usage bounded.
- Packaging: Maven profiles for native (
-Pnative) and installer (-Pinstaller) builds; CI workflows prepare and upload native and installer artifacts automatically.
Try it locally
Requirements: Java (JDK 25+ recommended), Maven 3.6+.
Build and run the JAR:
cd /home/ozkan/projects/paint
mvn -q clean package
java -jar target/paint-1.0.0.jar
Open an image directly from the command line:
java -jar target/paint-1.0.0.jar /path/to/screenshot.png
GraalVM native (optional):
export JAVA_HOME=/path/to/graalvm
export PATH="$JAVA_HOME/bin:$PATH"
gu install native-image # if needed
mvn -Pnative -DskipTests -q clean package
./target/paint
Packaging: there are helper scripts in src/installer/ci/bin/ and a Maven installer profile that uses jpackage to produce platform installers (DEB, DMG, MSI). See the README for details.
Roadmap (next steps)
UX
Features
Distribution
Tests & CI
Notes & credits
This app is intentionally lightweight and focuses on the frequent day-to-day editing tasks where a full image editor is overkill. The project uses FlatLaf for modern theming and includes helper scripts and CI workflows to build native binaries and installers.
Top comments (0)