pxv
A simple image viewer and manipulator built with Python/Pillow/Tkinter that takes inspiration from the classic Unix xv image viewer.
Quickstart
Run directly from the GitHub repo (requires uv):
uvx --from git+https://github.com/linsomniac/pxv pxv photo.jpg
Or install locally:
uv pip install git+https://github.com/linsomniac/pxv
pxv photo.jpg
Pass files, directories, or nothing (opens a file dialog):
pxv image.png # single file
pxv *.jpg # multiple files
pxv ~/Photos/ # all images in a directory
pxv # open file dialog
Debian / Ubuntu (.deb)
Each GitHub release includes a
pxv_<version>_all.deb. Install it (apt pulls in python3-tk and Pillow):
sudo apt install ./pxv_1.0.1_all.deb
It targets current distributions (Debian 13 / Ubuntu 24.04 or newer, which ship
Pillow ≥ 10). After installing, pxv is on your PATH and appears in the
applications menu and image "Open with" lists.
NixOS / Nix (flake)
Run it without installing:
nix run github:linsomniac/pxv -- photo.jpg
Install into your profile:
nix profile install github:linsomniac/pxv
Add to a NixOS configuration via the overlay (this also installs the .desktop
entry and icon, so pxv appears in launchers and "Open with" menus):
{
inputs.pxv.url = "github:linsomniac/pxv";
# in your configuration.nix / module:
nixpkgs.overlays = [ inputs.pxv.overlays.default ];
environment.systemPackages = [ pkgs.pxv ];
}
Without flakes, nix-build produces the package from a checkout (uses default.nix).
Keyboard Shortcuts
| Key | Action |
|---|---|
? |
Show keyboard shortcuts help |
> |
Double zoom |
< |
Halve zoom |
. |
Increase zoom 10% |
, |
Reduce zoom 10% |
n |
Zoom to 1:1 (normal) |
M |
Zoom to fill display |
Space / Right |
Next image |
Backspace / Left |
Previous image |
b |
Browse thumbnails (Visual Schnauzer) |
c |
Crop to selection |
A |
Autocrop background borders |
u / Ctrl+Z |
Undo |
Ctrl+Y / Ctrl+Shift+Z |
Redo |
t |
Rotate clockwise |
T |
Rotate counterclockwise |
D |
Toggle dark/light background |
f / F11 |
Toggle fullscreen |
s |
Toggle slideshow |
+ / - |
Slideshow interval +/- 1s |
e |
Enhancement dialog |
d |
Draw / annotate (drawing palette) |
i |
Show image info / EXIF |
Ctrl+s |
Save as |
Escape |
Exit slideshow/fullscreen, or clear selection |
q |
Quit |
Right-click for additional options: rotate, flip, resize, grab (screenshot), print, and more.
Enhancements
The enhancement dialog (e) provides real-time adjustment with a live
histogram (luminance + RGB overlays, log scale, clipping readouts) that tracks
every change:
- Sliders — brightness, contrast, gamma, sharpen, blur, saturation, hue rotation, per-channel RGB balance
- Levels — black/gamma/white input markers over the channel histogram, output range, Auto (percentile clip), and black/gray/white eyedroppers that sample the image
- Curves — spline curve editor per channel (master + R/G/B) with histogram backdrop, editable histogram Equalize, and Invert — the classic xv intensity and RGB graphs, modernized
Compare (hold) flips between the original and adjusted image; Apply
bakes the adjustments into the working image (undoable with u/Ctrl+Z).
Annotations
Draw mode (d, or right-click → Draw / Annotate...) opens a tool palette and
turns the canvas into a drawing surface:
- Tools (keys
1–8) — Select, freehand, line, arrow, rectangle, ellipse, highlighter, and text labels - Styling — six color swatches plus a custom chooser, thin/medium/thick size presets (auto-scaled to the image size), filled-vs-outline toggle, and an opacity slider; with a shape selected, the controls restyle it live
- Editing — the Select tool picks the topmost shape: drag to move,
Delete/Backspaceto remove,u/Ctrl+Z/Ctrl+Yfor in-mode undo/redo; double-click a text label to re-edit it
Shapes stay editable vector objects while the palette is open, and their sizes are in image pixels — the saved file is independent of the zoom you drew at. Done (or closing the palette window) bakes them into the image as a single undoable edit; Cancel discards them after confirmation. Navigating away or quitting with unsaved annotation work prompts first.
Features
- Image annotations / draw mode: freehand, lines, arrows, boxes, ellipses, highlighter, and text labels — editable vectors during the session, baked as one undoable edit
- Histogram, levels, and curves in the enhancement dialog (beyond-xv: live histogram backdrop, eyedroppers, editable equalization)
- XV-style window sizing: window grows/shrinks to fit the displayed image, capped at the current monitor's bounds
- Multi-monitor aware: detects per-monitor geometry via xrandr so windows don't span displays
- EXIF-aware orientation
- Save-options dialog for JPEG/PNG/WebP/TIFF (quality, compression, lossless, keep-metadata)
- Slideshow auto-advance (
--slideshow[=SECS]) and fullscreen presentation mode (--fullscreen) - Rubber-band selection for cropping
- Wrap-around file navigation
- Supports PNG, JPEG, BMP, TIFF, GIF, WebP, PPM, PGM, PBM, ICO
Requirements
- Python 3.10+
- Tkinter (usually included with Python; on Debian/Ubuntu:
sudo apt install python3-tk) - Pillow 10.1+
Development
git clone https://github.com/linsomniac/pxv
cd pxv
uv sync
uv run pxv test_images/
Lint and type-check:
uv run ruff check src/
uv run ruff format --check src/
uv run mypy src/pxv/
Metadata
Release files for pxv 1.0.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pxv-1.0.6.tar.gz | 81.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pxv-1.0.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 176.2 kB
Release files / pxv-1.0.6.tar.gz
| Download URL | pxv-1.0.6.tar.gz |
|---|---|
| Size | 81.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4b26a4a11dd3b29cade2062ced258e215dcb34aa6a3f1724aa4178db2797fe12
|
|
BLAKE2b-256 checksum How to use checksums |
e5431dbdd31a5966f5366ee76e8f6d3247c88cd65c9da67bf71390a2aba7bf0b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 11, 2026.
Transparency logRelease files / pxv-1.0.6-py3-none-any.whl
| Download URL | pxv-1.0.6-py3-none-any.whl |
|---|---|
| Size | 94.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
37f5fc027391f4aa712cbfb203adb55c2961eb2d4ce81daf387bf93867d3bbe8
|
|
BLAKE2b-256 checksum How to use checksums |
3c044ec91542c130a708fb9421595515125953da0d998711aff286cee3a10d72
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 11, 2026.
Transparency log