Reference

Specifications

Everything Halidra does, in detail — system requirements, camera support, the colour pipeline, every develop control, and a full functional-requirements table.

On this page

01 System requirements

Halidra runs as a Windows desktop app with a WebGL2 develop pipeline and a pure-JavaScript RAW reader. No native modules, no Adobe dependency.

Operating system
Windows 10 or 11, 64-bit (x64)
GPU
WebGL2-capable — the whole develop pipeline runs on the GPU
Download size
~95 MB (portable single .exe or installer)
Disk
Download size, plus a thumbnail cache
macOS
Coming soon
Internet
Not required to edit

Note: Minimum RAM and CPU figures have not been published yet. Tier 2 sensor decode is the heaviest task and runs on a single thread.

02 Distribution

Two Windows x64 executables, both built from the same source.

FileWhat it is
Halidra-1.0.0-portable.exeSingle file, ~95 MB. Double-click and it runs — no install, nothing left behind in Program Files.
Halidra-1.0.0-setup.exeInstaller, ~95 MB. Lets you choose the location and adds Start Menu and desktop shortcuts.

Packaged builds are checked with a self-test before being handed over: it boots the app, confirms WebGL initialises, confirms the decode worker loads as an ES module from inside the packaged app, and confirms a real image renders to non-black pixels. Builds are signed with Microsoft Artifact Signing (Azure Trusted Signing), and the signature is checked by asking Windows directly — not by reading the build log.

03 Camera & file support

Every RAW file is read in two tiers, and which tier you get decides how much latitude you have — not whether the file opens.

Tier 1 — the embedded preview

Every RAW the camera wrote a JPEG preview into opens, culls, rates and exports. That is effectively every camera: it's the camera's own full-resolution rendering, which is also what makes culling quick.

Tier 2 — the sensor data

Demosaicing the actual sensor plane gives real highlight headroom and the full tonal range. Press Ctrl+Alt+R to switch a photo to it.

Format support by tier
FormatTier 1Tier 2
Canon CR2yesyes
DNG (lossless JPEG or uncompressed)yesyes
Any uncompressed RAWyesyes
Sony ARW (ARW2)yesyes
Nikon NEF (compressed)yesyes
Canon CR3 (lossless)yesyes
Canon CR3 (C-RAW)yesyes
Panasonic RW2 (RawFormat 4, 5, 6)yesyes
Panasonic RW2 (RawFormat 7)yesyes
Panasonic RW2 (RawFormat 8)yesyes
Fujifilm RAF (Bayer, uncompressed)yesyes
Fujifilm RAF (compressed X-Trans, lossless)yesyes
Fujifilm RAF (compressed X-Trans, lossy)yesyes
Fujifilm RAF (compressed Bayer)yesyes

Containers & other input

Containers parsed directly: CR2, NEF, ARW, DNG, ORF, RW2, PEF, SRW, IIQ, 3FR (TIFF/IFD), CR3 (ISO-BMFF) and RAF (Fujifilm header). Anything with an embedded preview opens via a brute-force scan even if the container itself is unrecognised, so unknown formats still open at Tier 1. JPEG, PNG and TIFF files can also be imported directly alongside RAW.

Tier 2 is opt-in — Ctrl+Alt+R — pure JavaScript, and takes about 13 seconds for a 26 MP frame on one thread, which is why it isn't the default. If a body ever looks wrong, the same shortcut returns you to the embedded preview.

04 Colour pipeline

Colour needs no per-camera table. Instead, the camera-RGB → sRGB transform is fitted per-photo against the camera's own embedded preview of that same frame.

Matrix fitting
Full 3×3 matrix fitted against the embedded preview
Row constraint
Each row sums to 1, which keeps neutrals neutral
Fallback
Per-channel gains when the scene can't constrain a full matrix
Fallback rate
3 of 12 reference files take the fallback
Black level
Measured from the optically shielded sensor border
White balance
As-shot, read from the camera's MakerNote

A full matrix needs six free parameters, which needs a scene with colour in it; per-channel gains need only two, so they work on a near-monochrome scene. Two of the twelve reference files are near-monochrome, and one has ample blue-green variation but almost no red-green, leaving its red row unconstrained — all three take the gains fallback. Gains fix the colour cast, which is what makes an uncorrected render obviously wrong, but leave saturation where the sensor put it. Which tier a file lands in is reported in the sensor-decode line and asserted by the test suite.

Canon files state none of the DNG metadata a decoder needs. The MakerNote is read for the sensor borders (SensorInfo) and the as-shot white balance (ColorData, whose layout is identified by record length); the white level comes from the real bit depth of the compressed stream rather than an assumption.

05 Develop controls

100 controls across 10 groups, plus Auto Tone, Auto White Balance, a before/after split view and clipping warnings. Every control takes the mouse wheel — Shift for fine steps, Ctrl for coarse — and this works identically on a favourited copy of a control.

Develop panel groups
GroupControls
ProfileProfile, Amount, Black & White
BasicTemp, Tint, Exposure, Contrast, Highlights, Shadows, Whites, Blacks, Texture, Clarity, Dehaze, Vibrance, Saturation
Tone CurvePoint curve (RGB + per-channel) over a live histogram, plus parametric Highlights / Lights / Darks / Shadows
Color MixerHue / Saturation / Luminance for 8 colour bands
Color GradingShadows / Midtones / Highlights / Global wheels, Blending, Balance
DetailSharpening amount · radius · detail · masking, luminance & colour noise reduction
OpticsDistortion, lens vignetting, purple/green defringe, chromatic aberration
GeometryRotation (90° steps), Straighten, perspective V/H, aspect, scale, offset, flips
EffectsPost-crop vignette (amount · midpoint · roundness · feather · highlights), grain
CalibrationShadow tint, R/G/B primary hue & saturation

06 Masking spec

Add a mask and every control in the app — tone, curves, colour mixer, colour grading, detail, effects, calibration — applies inside it and nowhere else.

Mask types
MaskWhat it selects
RadialAn ellipse you move, resize and rotate — vignettes, drawing the eye
Linear GradientA straight falloff — skies, foregrounds, raking light
BrushPainted by hand; Alt-drag erases, wheel resizes
Color RangeEverything matching a colour you pick off the photo
Luminance RangeEverything inside a brightness band
Per-mask controls
Feather, opacity, invert, show/hide
Stack limit
Up to 8 masks per photo
Coordinates
Source-image coordinates — stay glued through crop, straighten, 90° rotation, perspective and lens distortion
Rendering
Each mask gets a complete pipeline pass of its own, composited over the global result by coverage

Select a mask and the develop panels turn blue and start writing into it; deselect and they go back to the whole photo. A mask is seeded from the photo's settings at the moment it's created, so its sliders start where the picture already is — later changes to the global settings do not flow into an existing mask.

The test suite asserts confinement exactly: at the centre of a mask the result equals the fully-adjusted value, and a sample outside it is identical to the untouched original — not close, identical.

07 Healing spec

Click a blemish and it is repaired; drag to choose where the repair comes from. Q opens the tool, Shift+Q toggles Heal ↔ Clone.

Heal
Blend with background — keeps the source's texture, replaces colour and brightness with the destination's
Clone
Replace with similar — the source area is copied verbatim
Formula
source − blur(source) + blur(destination)
Auto source
Ring matching around the spot against candidate positions, rejecting overlaps with the spot, other spots, or the frame edge
Spot limit
Up to 32 spots per photo, all applied on the GPU, all fully reversible
Coordinates
Source-image coordinates — stay stuck through crop, straighten, 90° rotation, perspective and lens distortion

The difference between Heal and Clone is easy to see on a gradient: healing from a much darker area onto a bright background reads 196 against a 198 background (invisible), while cloning the same source reads 42 — an obvious dark blotch. That comparison is an assertion in the test suite.

Brush size follows the mouse wheel or [ / ]; feather and opacity are set per spot; Del removes the selected spot.

08 Auto adjust

The Auto ▾ button in the toolbar, or its shortcuts, offer three different solves.

ModeShortcutWhat it does
Whole photoCtrl+UBalances tone across the frame and neutralises any colour cast
From a subject / area…Ctrl+Alt+UDrag a box around your subject; exposure and highlight/shadow recovery come from that selection's own distribution
From a white / neutral area…Ctrl+Shift+WDrag a box over something neutral; white balance is solved directly, then exposure set so the reference sits just below clipping

The neutral-area solve is a true solve, not a guess: on a blue-cast test frame it moves the blue-minus-red difference from +59 to −4.

09 Styles

29 built-in looks in the Styles panel, grouped into seven categories.

GroupNamed examples
EssentialsPunch, Soft Light, Crisp Detail, Flat / Log, HDR Natural
FilmKodachrome, Portra 400, Faded Film, Ektar Vivid, Tungsten Night
CinematicTeal & Orange, Bleach Bypass, Golden Hour
PortraitClean Skin
LandscapeVivid Landscape
Black & WhiteRed Filter B&W
CreativeCross Process

A Strength slider scales the whole look: numeric settings interpolate from their defaults toward the style's values, so 50% really is half the look rather than a different one. Switching styles cleans up whatever the previous one touched, and Clear returns those controls to their defaults — a style is never a trap. Styles are separate from presets: presets capture your photo's exact settings, styles are reusable starting points.

10 Library & culling

  • Import a folder (optionally including subfolders) of RAW and JPEG/PNG/TIFF files
  • Grid and filmstrip with lazily-decoded, disk-cached thumbnails
  • Rate 0–5 stars, flag pick/reject, colour-label red→purple
  • Auto-advance mode — a rating keystroke moves straight to the next frame
  • Filter by minimum rating, flag, label, text; sort by name/date/rating/flag/size
  • RAW+JPEG pairs shot together are detected and grouped

11 Crop, geometry & zoom

Crop — C

Drag the rectangle or its eight handles, lock to an aspect ratio (1:1, 4:5, 3:2, 16:9, 21:9, original, free), straighten with the angle slider, rotate in 90° steps, flip orientation, and choose an overlay (thirds, golden ratio, grid, diagonal, centre cross). Enter applies, Esc cancels. The crop travels with the photo through rotation, copy/paste and export.

Zoom

Fit / Fill / 1:1 / 2:1 / 4:1 buttons, + / - stepping, Z for 100%, Space to toggle fit↔100%, cursor-anchored scroll-wheel zoom, drag to pan, and a navigator thumbnail showing (and letting you move) the visible region. The renderer only processes the visible region at screen resolution, so zooming to 1:1 costs the same as fit-to-window.

12 Display calibration

Ctrl+Shift+K. A view transform, never an edit.

Set your panel's white point (or dial R/G/B gains by eye against neutral strips), correct any shadow cast with black-point lifts, and match gamma against a striped reference. Halidra then compensates the preview so what you judge as neutral on your screen is neutral in the actual file.

Exported pixels are never compensated — asserted in the test suite, which renders the same photo through both paths and checks the export is bit-identical with calibration on and off while the preview measurably changes. This is calibration by eye, not measurement; if you own a colorimeter, profile the display with that and leave this switched off.

13 Copy / paste / sync / presets / history

ActionShortcut
Copy SettingsCtrl+Shift+C
PasteCtrl+Shift+V
Paste Settings (choose…) — checklist of just white balance, tone, etc.Ctrl+Alt+V
Paste From Previous PhotoCtrl+Alt+P
Sync to selected (same checklist as Paste choose)Ctrl+Shift+S

Presets save the whole look for reuse; a per-photo history list lets you step back through edits. Favourites: drag any control's label out of a develop panel into a Favourites box in the right panel — reorder within a box, drag between boxes, add and rename boxes. A favourited slider is a live copy, in sync with the original, and the layout persists between sessions.

14 Keyboard

Ctrl+K opens the shortcut editor: 576 bindable commands, searchable and filtered by category. Every control is assignable — each slider gets Increase / Decrease / Reset / Focus / Add to Favorites; toggles get Toggle; dropdowns get Next/Previous Option. Record a combination with + Add. Conflicts show in red and the new binding takes the key. Multiple keys per command are allowed, and the keymap survives upgrades.

Default shortcuts (abridged)
Ctrl+O / Ctrl+Shift+OImport folder / with subfolders
G E DGrid · Loupe · Develop
0–5Set rating · , . decrease/increase
P X UPick · Reject · Unflag
6–9, Shift+9Colour labels
← →Previous / next photo
Z / Shift+Z / Space100% · 200% · toggle fit↔100%
Ctrl+0 / Ctrl+Shift+0Fit · Fill
CCrop tool (Enter apply, Esc cancel)
Q / Shift+QHeal tool · toggle Heal↔Clone
M / Shift+M / Alt+MMasks panel · add radial · add brush
OToggle mask overlay
Ctrl+U / Ctrl+Alt+U / Ctrl+Shift+WAuto: whole photo · from subject · from white
[ ] / DelBrush smaller · larger · delete selected spot
Ctrl+Shift+KCalibrate display
Y / Alt+YBefore/After split (side-by-side / top-bottom)
JClipping warnings
Ctrl+Shift+C / Ctrl+Shift+V / Ctrl+Alt+VCopy · Paste · Paste (choose)
Ctrl+Alt+P / Ctrl+Shift+SPaste from previous · Sync to selected
Ctrl+U / Ctrl+Shift+UAuto Tone · Auto White Balance
Ctrl+Z / Ctrl+YUndo · Redo
Alt+1…Alt+9Jump to a develop panel
F7 F8 F9 F6Toggle left · right · favourites · filmstrip
Ctrl+EExport
Ctrl+KShortcut editor

15 Export formats

Ctrl+E exports the selected photos, rendered through the same GPU pipeline at full resolution, with quality and long-edge resize. The originals are untouched in every case.

FormatNotes
JPEG8-bit, adjustable quality
PNG8-bit lossless
WebP8-bit, adjustable quality
TIFF 8-bitUncompressed RGB, universally accepted
TIFF 16-bitUncompressed RGB, read straight off the float render target — for print or further retouching

16 Data & storage

Catalog
.halidra/catalog.json
Location
Beside the photos
Originals
Opened read-only, never written to
Legacy catalogs
.aperture/

Ratings, flags, labels, crops, healing spots and every develop setting live in the catalog and are baked into pixels only when you export. Catalogs written by earlier versions under .aperture/ are still read, and favourites, shortcuts, presets and calibration are migrated across on first launch, so nothing is lost in the rename.

17 Quality assurance

76 end-to-end checks boot the real renderer headlessly and cover WebGL initialisation, folder import, thumbnail and full-image decode, that exposure / white balance / saturation / tone curve / clarity / sharpening / vignette / grain actually change rendered pixels, rating and catalog round-trips, keyboard dispatch and rebinding, favourites drag targets and cross-copy sync, crop geometry, 90° rotation with crop remapping, copy/paste, undo/redo, zoom and pan clamping, image orientation, mouse-wheel control of sliders/toggles/dropdowns, healing, styles and strength scaling, display calibration reaching the preview but never the export, TIFF structure and bit depth, masking confinement, all three auto-adjust modes, and export in all five formats. Screenshots are written to test/screenshots/ on every run.

Per-vendor RAW suite

A separate suite runs against ~500 MB of CC0 RAW samples from raw.pixls.us — the same database darktable and RawTherapee regression-test against. Opening, reading metadata and rendering the preview are pass/fail; sensor decode for vendors not yet covered is reported as a named gap, not a failure, and a gap becomes a pass once the codec lands.

LibRaw reference comparison

LibRaw's unprocessed_raw writes the mosaiced sensor plane with nothing else applied, giving an exact pixel-level answer to compare against — catching errors a preview-correlation check alone would miss (this is what caught a Sony plane sitting two bits low, which still correlated at 0.98 against the preview).

Correctness without reference renders

A new decoder is correlated against the camera's own preview — a different rendering of the same frame — over a 24×16 grid, deliberately coarse enough to be fair (a correct decoder scores 0.98) but fine enough to catch structural errors (a decoder with its rows shifted by one byte scores 0.79 at this grid, versus 0.96 at a too-coarse 4×4).

Packaged executables are verified with a self-test before release, and their signatures are verified rather than assumed.

18 Functional requirements

A representative slice of the product requirements, with an acceptance criterion the README states is asserted or observable for each.

IDRequirementAcceptance criterion
FR-LIB-01Import a folder of RAW/JPEG/PNG/TIFF, optionally with subfoldersImported files appear in Grid with cached thumbnails
FR-LIB-02Rate, flag and colour-label photos0–5 stars, pick/reject flags, red→purple labels persist to the catalog
FR-LIB-03Auto-advance after ratingA rating keystroke moves selection to the next frame
FR-LIB-04Filter and sort the libraryFilter by rating/flag/label/text; sort by name/date/rating/flag/size
FR-LIB-05Detect RAW+JPEG pairsPairs shot together are grouped in the grid
FR-DEC-01Open Tier 1 (embedded preview) for any supported containerPreview located via container parsing, or a brute-force JPEG scan as fallback
FR-DEC-02Open Tier 2 (sensor decode) on demandCtrl+Alt+R switches the active photo to a 16-bit linear sensor render
FR-DEC-03Tier 2 decode correctnessSensor render correlates against the camera's own preview over a 24×16 grid, and matches LibRaw's unprocessed_raw pixel-for-pixel where available
FR-CLR-01Fit a camera-RGB→sRGB matrix per photo3×3 matrix with each row summing to 1, fitted against the embedded preview
FR-CLR-02Fall back to per-channel gainsGains used when the scene can't constrain a full matrix; reported in the sensor-decode line
FR-CLR-03Measure black levelRead from the optically shielded sensor border rather than assumed
FR-DEV-01Provide 100 develop controls across 10 groupsProfile, Basic, Tone Curve, Color Mixer, Color Grading, Detail, Optics, Geometry, Effects, Calibration panels all present
FR-DEV-02Every slider responds to the mouse wheelWheel adjusts the hovered control; Shift = fine step, Ctrl = coarse step
FR-DEV-03Before/After split viewY / Alt+Y toggle side-by-side and top-bottom split
FR-DEV-04Clipping warningsJ toggles highlight/shadow clipping overlay
FR-MSK-01Five mask types availableRadial, Linear Gradient, Brush, Color Range, Luminance Range all selectable from the Masks panel
FR-MSK-02Every develop control works inside a maskSelecting a mask redirects the whole develop panel, not a restricted subset
FR-MSK-03Mask confinementCentre-of-mask sample equals the fully-adjusted value; outside-mask sample is identical to the untouched original
FR-MSK-04Stack up to 8 masksEight masks stack and composite on one photo
FR-MSK-05Masks survive geometry changesMask position is correct after crop, straighten, 90° rotation, perspective and lens distortion
FR-HEAL-01Heal and Clone modesHeal keeps source texture and adopts destination colour/brightness; Clone copies the source verbatim
FR-HEAL-02Heal vs Clone gradient testHeal from a darker source onto a 198 background reads 196; Clone of the same source reads 42
FR-HEAL-03Automatic source selectionRing-matching picks a continuation of the surroundings, rejecting overlap with the spot, other spots, or the frame edge
FR-HEAL-04Spot limit and reversibilityUp to 32 spots per photo, each independently deletable via Del
FR-AUTO-01Auto Tone (whole photo)Ctrl+U balances tone and neutralises colour cast across the frame
FR-AUTO-02Auto from subject/areaCtrl+Alt+U exposes for a dragged selection's own distribution
FR-AUTO-03Auto from neutral area (grey-card solve)On a blue-cast test frame, blue-minus-red moves from +59 to −4
FR-STY-0129 built-in styles across 7 groupsStyles panel lists all 29, grouped and searchable
FR-STY-02Strength slider scales the look50% Strength interpolates every numeric setting halfway from default to the style's value
FR-STY-03Clear resets touched controlsClear returns only the controls the style touched to their defaults
FR-CAL-01Display calibration affects preview onlyExport output is bit-identical whether calibration is on or off, while the preview visibly changes
FR-CPY-01Copy/paste develop settingsCtrl+Shift+C / Ctrl+Shift+V copy and paste the full setting set onto one or many photos
FR-CPY-02Selective paste and syncCtrl+Alt+V opens a checklist; Sync applies the same checklist to every other selected photo
FR-CROP-01Crop with aspect lock and overlays1:1, 4:5, 3:2, 16:9, 21:9, original and free ratios; thirds/golden ratio/grid/diagonal/centre-cross overlays
FR-CROP-02Crop travels with the photoCrop region remains correct through rotation, copy/paste and export
FR-ZOOM-01Zoom levels and navigationFit / Fill / 1:1 / 2:1 / 4:1, Z, Space toggle, cursor-anchored wheel zoom, navigator thumbnail
FR-EXP-01Export to five formatsJPEG, PNG, WebP, TIFF 8-bit and TIFF 16-bit all produced from the GPU render target
FR-EXP-02Originals never modified by exportSource file bytes are unchanged after any export operation
FR-KEY-01576 bindable commandsShortcut editor (Ctrl+K) lists and allows rebinding of all 576 commands
FR-KEY-02Every control is assignableSliders expose Increase/Decrease/Reset/Focus/Add-to-Favorites; toggles expose Toggle; dropdowns expose Next/Previous Option
FR-KEY-03Keymap persistence across upgradesUser rebindings survive an upgrade; newly added commands keep factory defaults
NFR-DATA-01Originals are never written toRAW and JPEG files are opened read-only for the lifetime of the app
NFR-DATA-02Legacy catalog migration.aperture/ catalogs, favourites, shortcuts, presets and calibration are read and migrated on first launch
NFR-PERF-01Zoom cost is resolution-independentRendering 1:1 costs the same as fit-to-window — only the visible region is processed
NFR-PERF-02Tier 2 decode time is bounded and disclosedA 26 MP frame takes about 13 seconds on one thread; the badge discloses which tier is active
NFR-QA-01End-to-end regression coverage76 checks run headlessly against the real renderer on every change
NFR-QA-02Per-vendor RAW regression coverageSony, Nikon, Panasonic and Fujifilm held to the Tier 1 guarantee; Tier 2 gaps reported by name, not silently failed
NFR-QA-03Packaged-build verificationSelf-test boots the packaged .exe, checks WebGL init and non-black render output before release
NFR-SEC-01Release builds are code-signednpm run verify:sign exits non-zero if any shipped executable is unsigned