gamut / /
GitHub
About

A modern image viewer for understanding and acting on images.

What does modern mean? Today’s devices take photographs with embedded GPS position and orientation, HDR gain maps, depth information, raw development profiles, and more. A modern image viewer is one that uses, visualizes, and makes available this information. Beyond photos, it needs features for data rasters, animations, UI mockups and other uses.

Modern also means UI conveniences like a fuzzy file chooser, remappable keyboard and gesture actions, and GPU-driven performance.

Image viewers tend toward minimalism or full-fledged editors; gamut stakes a claim in the middle. It’s for when you need to see the image, understand it, and decide what you’re going to do with it: check for sharpness, assess a render, compare similar images, pull a pixel value or coordinate, extract some metadata, copy a region to chat, delete the image outright, or send it to a domain-specific editor.

Linux

gamut is packaged for Arch. The PKGBUILD builds the latest release:

git clone https://github.com/dcervelli/gamut.git
cd gamut/packaging && makepkg -si

Note: it takes a few minutes to build.

Omarchy setup

Omarchy ships imv as its image viewer. To use gamut in its place:

1. Window rule. Add this to ~/.config/hypr/hyprland.lua:

o.window("com.dcervelli.gamut", { float = true, center = true, tag = "-default-opacity", opacity = "1 1" })

gamut then opens floating and centered, at a size it works out from the image and the screen. The window is fully opaque, because Omarchy’s default translucency would tint the image with whatever is behind it. Hyprland picks up the change when you save.

2. Default viewer. Make gamut the viewer for every image type it reads:

xdg-mime default com.dcervelli.gamut.desktop $(sed -n 's/^MimeType=//p' /usr/share/applications/com.dcervelli.gamut.desktop | tr ';' '\n' | grep '^image/')

Folders still open in your file manager; gamut <folder> from a terminal views every image in one. The choice is written to ~/.config/mimeapps.list, where it can be changed back.

3. Theme. Nothing to do: gamut uses the current Omarchy theme and follows it when you switch.

macOS

gamut is packaged for Homebrew. The formula builds the latest release:

brew install dcervelli/gamut/gamut

Note: it takes a few minutes to build.

This installs the gamut command and Gamut.app. To launch it from Finder or Spotlight, link the app into /Applications:

ln -sf "$(brew --prefix gamut)/Gamut.app" /Applications/Gamut.app

Note: you currently won’t be able to send files to gamut from Finder’s “Open With”. We’ll fix this once we start doing proper app bundle builds.

Optional: exiftool

gamut uses exiftool for comprehensive raw image metadata presentation. Install it on your system if you want access to that data.

An image viewer serves many audiences: photographer, data scientist, programmer, designer, game developer, GIS analyst, and, of course, the casual user. We carefully consider these tenets in deciding if a feature clears the bar for inclusion.

Fast, always

Every pan and zoom runs at full frame rate; decoding and analysis never block the interface. Speed is never traded for a feature.

Faithful to the file

Color management; HDR as graded; 16-bit, float, single-channel data displayed as-is. The file’s actual pixel values are always a hover away.

Viewer, not editor

You can rename, trash, copy, and export, but nothing changes the file’s pixels. Adjustments are for seeing the image better, and what you see is what you copy or export.

Useful, not minimal

If a feature is conceptually simple but would otherwise require specialized software, it has a place.

Images come first

The interface is sparse, and every image, primary and thumbnail, gets as much room as possible. Specialized tools stay out of sight unless asked for.

Discoverable by mouse, driven by keyboard

Every feature is accessible through the UI and keyboard. Learn the keys via tooltips and in-app help.

Desktop native

Integrates with your theme, trash, thumbnail cache, file dialogs, and other image applications.

Web and everyday

Format Notes
JPEG ICC profiles; HDR gain maps; Google depth maps; orientation; CMYK
PNG 8 and 16-bit; indexed; alpha; PQ and HLG, ICC, gamma and primaries; animation
WebP Lossy and lossless; alpha; ICC profiles; orientation; animation
GIF Animation

Photography

Format Notes
Camera raw Every major make and DNG; camera white balance and color into Rec. 2020, no curve or sharpening; toggle to camera’s JPEG
iPhone ProRAW JPEG XL or lossless JPEG; rendered with iPhone profile or linear; each stage traced in the histogram
HEIC Color space; 10 and 12-bit; iPhone HDR gain maps; portrait depth in meters

HDR

Format Notes
JPEG, HEIC with gain maps Lifted within monitor’s headroom
iPhone ProRAW Profile rendering as a gain map
PNG, JPEG XL, AVIF, HEIC PQ and HLG; JPEG XL float kept above white
OpenEXR Half and full float; RLE, ZIP, PIZ, PXR24, B44; metered exposure, neutral tone map
Radiance HDR Linear float; metered exposure; header EXPOSURE= honored

Data

Format Notes
TIFF / BigTIFF 8 to 64-bit integer or float, never rescaled; false color ramps; no-data values excluded; GeoTIFF latitude and longitude; multi-page

Other

Format Notes
AVIF Stated color space; 10 and 12-bit
ICO Multiple icons shown as pages
BMP 1 to 32-bit; palettes; RLE
Netpbm PBM, PGM, PPM, PAM; ASCII or binary; 8 or 16-bit

Getting Started

Just pass filenames or directories to gamut:

gamut file1.jpg pictures file2.png

Directories are scanned non-recursively.

Keyboard

Basic keys to get going:

Key (Linux) Key (macOS) Action
? ? Show/hide help screen
], [ or PgDn, PgUp ], [ or Fn↓, Fn↑ Next / previous file
Space Space Cycle fit → fill → 100%
1 1, 0 or ⌘0 Actual size; wheel to zoom, drag to pan
h, i, m h, i, m Histogram, file information, minimap
` ` Hide the interface
tab tab Show/hide the file list
q, esc q, esc or ⌘Q, ⌘W Quit

All features can be keyboard-driven, but the hideable UI also has controls with tooltips to learn keyboard shortcuts. Most controls can also be set via CLI flags.

Open the keyboard shortcut display with ?. On a Mac, the keyboard shortcuts that use Ctrl on Linux generally use ⌘, and the help shows the macOS keys. Mouse gestures differ too: on Linux the scroll wheel zooms; on a Mac two-finger scrolling pans, and pinching or ⌘-scrolling zooms.

All keyboard shortcuts and mouse gestures can be customized in the config file.

The File List shows all of the files that navigation and sorting apply to. If specific directories were opened, gamut will watch them in addition to the listed files.

Navigation actions are as follows:

Action Linux macOS
Next file → ↓ ] Page Down → ↓ ] Page Down (fn+↓)
Previous file ← ↑ [ Page Up ← ↑ [ Page Up (fn+↑)
First file Home Home (fn+←)
Last file End End (fn+→)
History back Alt+← Alt+[ Alt+Page Up ⌘[
History forward Alt+→ Alt+] Alt+Page Down ⌘]
Open fuzzy finder Ctrl+P ⌘P

On a Mac keyboard without dedicated keys, fn with an arrow gives Page Up, Page Down, Home and End. A mouse’s back and forward buttons also step through history.

Other actions:

Action Linux macOS
Remove file from list, does not delete file ⌫ ⌫
Trash file Del ⌘⌫ ⌦

⌫ is the key labeled Backspace on a PC keyboard and delete on a Mac. ⌦ is forward delete, fn+⌫ on a Mac laptop.

Use the Sort menu to order the list however you prefer. Sort options:

Sort Description
Name File name, ignoring path
Path Full path to file
Type Image type (based on reader, not extension)
Modification Date File modification date
Capture Date Image capture date, if available
Size File size
Width Image width
Height Image height
Area Image width × height

Command-palette-style navigation over the file list with thumbnails and helpful metadata per row, Ctrl+P / ⌘P to open. Type a number after : to go to an index; negative numbers count from the end of the list. Numeric indexing can be useful after sorting the list.

Bird images from Fugleramme, augmented to include the common name in the metadata.

All files and directories that are opened are watched for changes and update immediately. This can be helpful in situations like the one in the example. Folders will update (and re-sort with current settings) when files are added, deleted, or changed.

Files with the same dimensions maintain pan and zoom for easy file comparison.

An easily triggerable loupe for quickly examining details. l to toggle or hold the right mouse button (on a Mac trackpad, a two-finger click) for a quick peek.

A dynamically scaled pixel grid atop the image. g to toggle.

Get coordinate or pixel information for the moused-over pixel. Easily copy either the coordinate or color (in a variety of formats).

Use the crop icon on the left or x to start drawing a region. Once a region is selected, the following will work:

  • Auto-fitting (Space) will fit the region before fitting the whole image
  • Image copy (Ctrl+C / ⌘C) will copy the region instead of the whole image
  • Region-specific keys will become active

When a region is showing, one of its handles (starting with the center) is always active. Clicking on a handle activates it. The key effect depends on which handle is active.

Handle Linux macOS Description
Center ↑ ↓ ← → ↑ ↓ ← → Shift the region by one pixel in the arrow direction
Center Ctrl+↑ ↓ ← → ⌘↑ ↓ ← → Grow the selection by one pixel in the arrow direction
Center Ctrl+Shift+↑ ↓ ← → ⇧⌘↑ ↓ ← → Shrink the selection by one pixel in the arrow direction
Corner ↑ ↓ ← → ↑ ↓ ← → Grow or shrink selection by one pixel on that corner
Side ↑ ↓ ← → (perpendicular to side) ↑ ↓ ← → (perpendicular to side) Grow or shrink selection by one pixel on that side
Side ↑ ↓ ← → (parallel to side) ↑ ↓ ← → (parallel to side) Shift selection by one pixel

The keys make it quite simple to select the exact area you want.

A basic file export. Choose either PNG (lossless) or JPG, with an option to resize.

Play animated GIF, PNG, WebP and JPEG XL files at normal speed or frame-by-frame. Tools and controls, like the histogram shown here, work on the current frame.

HDR-capable cameras often store HDR information in a gain map. In addition to viewing the image in HDR, the gain map itself can be seen and understood.

The first two images are Apple and Google gain maps, respectively. The ProRAW image doesn’t technically have a gain map; instead, the several steps of the Profile (see ProRAW histogram) accumulate to display an effective gain map.

Some phones capture depth information in certain modes. gamut supports displaying and querying the depth map. Shift+D / ⇧D to toggle.

Most modern photographs embed some amount of camera orientation information. Hovering over the orientation section or activating the Horizon Grid (b) will overlay as much information as possible about the camera orientation on the image.

Moving the mouse over the image when the grid is active shows two curves through the current point: a curve “parallel” to the horizon and a line oriented up.

When an image has pitch/roll information, the coordinate display can be set to azimuth and elevation.

Has Pitch/Roll Has Bearing Behavior
✅ ✅ Relative-to-horizon grid with compass bearings (as shown in the example)
✅ ✖️ Relative-to-horizon grid with bearings relative to the camera’s direction
✖️ ✅ A small circle showing the compass bearing at the center
✖️ ✖️ No horizon grid

A dynamic histogram primarily for inspecting the content of the image. This page describes images in “Photo” mode; you can read elsewhere about “Data” mode.

The histogram flow is read bottom to top. The bottom “Image” histogram shows raw data from the file. The currently hovered pixel is shown as vertical rules, one for each channel. Those pixel values flow into the “Display” histogram.

While gamut is a viewer, not an editor, you can make some adjustments in the Display histogram to help you understand the content of the image. You can adjust black and white points on the sliders, adjust the exposure, or apply a simple S-shaped tone curve.

At the top is the “Output” histogram. This is the histogram that most applications show: the pixels after the modifications in the Display section (or ProRAW profile).

See also: Data mode, RAW histogram, ProRAW histogram, HDR histogram, Data histogram.

The RAW histogram augments the basic histogram.

Starting at the bottom, the Image section now shows pixel values in their native bit depth (14-bit [up to 16383] in this example) and, when the RAW is mosaicked (which most are), it shows the specific red, green, or blue value for the hovered pixel. Further, there is a Photosites section that shows the raw values of the mosaic in the vicinity of the hovered pixel. You can toggle a complete mosaic view using the eye icon in that section. Mosaic view can also be toggled using the grid button in the lower right or the Shift+M / ⇧M shortcut.

An additional section, Develop, is above the Image section and includes information about the “development” of the raw. This usually involves, at least, demosaicing and applying white balance. It also displays a line indicating how many pixels of each channel were clipped during development.

Above that are the standard sections of the basic histogram.

See also: Basic histogram, ProRAW histogram.

Familiarize yourself with the basic histogram first.

The HDR histogram adds the Gain map section. It’s a histogram that shows the range of how much gain, in stops, is added across the image. Moving the mouse over the image will show where the particular pixel falls in the gain map. Read more about Gain maps.

The Display section also changes to allow values above 1 to be sent to the output.

The Output section shows stops above white (with chevrons showing in the light scale bar under its histogram).

ProRAW histograms build on aspects of both the HDR and RAW histograms with the addition of a Profile section, which describes how a Developed pixel is adjusted before Display modifications. These are the steps for a given pixel (shown when hovering over the image):

Step Description
Input The value of the pixel after the Develop section is the starting point
ProPhoto conversion Convert developed values to linear ProPhoto
Apply exposure Adds the profile’s baseline exposure value
Apply gain table Applies the relevant gain curve (separate curves distributed on a grid) to the pixel
Apply tone curve Applies the profile’s tone curve

The output of all the steps is summarized in the Total lift line and then a histogram is shown of the gain across the whole image. The application of the profile can be toggled with the icon on the right of the section. When the profile is showing (the default), the RAW should look very similar to the embedded JPEG (view with the button at the bottom or v).

Whenever an image file is opened, gamut chooses whether it should be in Photo or Data mode. The table below summarizes the differences between the modes. In the rare event that gamut chooses poorly or you want to experiment with the other mode, you can change it in the histogram, info panel or with the | key.

Photo Data
Values are light, with 1.0 as white (graded) or no stated white (scene) Values are raw numbers (likely not light at all)
Samples use the file’s curve (sRGB if none) Read as linear
Scene-referred files (EXR, Radiance) open metered, with key at middle gray No metering
Opens with dark→light window of 0..1 (“As stored”) Opens with dark→light window trimmed to the central 99.8%
Histogram’s Display section has Exposure and Curve rows Histogram’s Display section has only the Window row
No window rules Uses Window rules: (As stored / Full range / Trimmed)
Uses exposure adjustment No exposure adjustment; use histogram white handle instead
Uses the tone curve: Clip / Roll off No curve
Values above white go to the curve and HDR headroom Values clipped at the window’s top, even on HDR
Single-channel gray image is shown as light (unless false color is chosen) Single-channel gray image spread linearly over ramp
Linear light plotted in stops counting from white Plotted on its curve or codes (no stops)
Graded file’s histogram axis always reaches at least 1.0 Axis ends at the data’s maximum

Histograms in the Image section of the data raster are computed in their native values. This makes it easy to find percentiles and medians.

The sliders under the Display histogram can be used to narrow the output based on native value. In this example, the slope map is narrowed to 30–45°.

Single-channel files in data mode can be colored using a false color ramp. Set the ramp in the histogram section or cycle through them with the r key.

A curated set of image metadata is collected from the file. EXIF, XMP, RAW fields, and other sources are used to put together the following sections. All data is easily copyable and exportable and, in some cases, interactive. Raw data is also available.

Sections

File Name, path, size and last modified date. Always shown.
About Title, caption, comment, artist, keywords and copyright. Only shown if available from EXIF/XMP.
Image Resolution, format, samples, color space, alpha, and more. Always shown.
Camera Camera make and model, lens, owner, serial numbers and software. Shown if available.
Exposure Capture time, mode, shutter speed, aperture, ISO, compensation, focal length, metering, white balance, flash. Shown if available.
Location GPS and compass information. Link to external map. Shown if available.
Orientation 3D representation of the camera in space. Hovering shows Horizon Grid. Shown if available.
Gain map Info about the gain map: format, HDR headroom, the lift, and how much is currently applied. See HDR histogram. Shown if available.
Profile The profile’s baseline exposure, gain table and tone curve, and whether they are applied. Shown if available (currently just ProRAW).
Depth map Size, sample info, encoding, range and accuracy. Shown if available.
Regions A table of each region’s subject, position and size; hovering a row shows the region on the image.
Georeference Coordinate system info, pixel size and origin, ground extent, rotation and no-data value. Link to external map (center or bounds). Shown for GIS files.

If installed, gamut uses exiftool to provide a filterable interface to all of the image’s metadata. Data is easily copyable and exportable.

Open in…

Use the “Open in…” menu to send an image to another application. The file name is passed to the other application; any display adjustments you’ve made won’t show up in the opened application.

For images with GPS metadata, or georeferenced files, a button is available in the Location or Georeference sections of the Info panel to open that location in a browser. Georeferenced files also have a button to open the bounds of the file.

By default, the URL leads to geojson.io, with the center or bounds as a GeoJSON payload. You can modify the URL to one of your choosing in the config file.

On both Linux and macOS, gamut tries to respect your OS theme and will update without relaunching.

At startup (and with live reload, to the extent possible), gamut reads ~/.config/gamut/config (the same path on Linux and macOS). You can easily open this file (and create one if it doesn’t exist) using the button at the bottom of the help menu.

The config file allows you to adjust settings, keybindings, and gestures. CLI flags supersede config values.

gamut also manages a state file: ~/.local/state/gamut/state on Linux, ~/Library/Application Support/gamut/state on macOS.

This is the portion of the current default config not involved with keybindings and gestures:

# The panels around the picture; ` hides and shows them.
# show_ui = true

# The minimap, while the picture is larger than the window.
# show_minimap = true

# The file list down the left, while there is more than one file.
# show_filmstrip = true

# The histogram, in the side panel; it wins over show_info where both are on.
# show_histogram = false

# The file information, in the side panel.
# show_info = false

# A single file opened alone steps on through the other images in its folder.
# browse_folder = true

# The web page the map buttons in the info panel's Location and Georeference sections open: {lat} and {lng} are where the picture was taken, or the middle of what it covers, in degrees.
# open_map_link = https://geojson.io/#data=data:application/json,%7B%22type%22%3A%22Feature%22%2C%22properties%22%3A%7B%7D%2C%22geometry%22%3A%7B%22type%22%3A%22Point%22%2C%22coordinates%22%3A%5B{lng}%2C{lat}%5D%7D%7D

# The web page the corners button in the info panel's Georeference section opens: {lat_ul} and {lng_ul}, {lat_ur} and {lng_ur}, {lat_lr} and {lng_lr}, and {lat_ll} and {lng_ll} are the picture's upper left, upper right, lower right and lower left corners, in degrees.
# open_map_bounds_link = https://geojson.io/#data=data:application/json,%7B%22type%22%3A%22Feature%22%2C%22properties%22%3A%7B%7D%2C%22geometry%22%3A%7B%22type%22%3A%22Polygon%22%2C%22coordinates%22%3A%5B%5B%5B{lng_ll}%2C{lat_ll}%5D%2C%5B{lng_lr}%2C{lat_lr}%5D%2C%5B{lng_ur}%2C{lat_ur}%5D%2C%5B{lng_ul}%2C{lat_ul}%5D%2C%5B{lng_ll}%2C{lat_ll}%5D%5D%5D%7D%7D

# The program the info panel's Raw Data tab reads every tag with: a name looked for on the PATH, or a path.
# exiftool = exiftool