- Visualize HDR (#1555) has no default key: ⇧H cycles the Tool Overlay (#1473, issue #224)
- CR3 tests (#1461, #1462) accept adaptive QP 131–175, as #1694 decodes; cr3.md says the R6 Mark II files decode
- English fallbacks in the Czech and Polish catalogs use → for the menu triangle; Polish in the keyword-label test
- canvas handle tests show pins (Tool Overlay Always); a focused handle keeps its pins shown in Auto
- the model-install test and demo deadlock guards wait on deadlines long enough for a busy machine
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nikon bodies from before ~2016 record no CropArea, so the decoder kept
their whole sensor data, less trailing dark columns. Where that data
holds masked lines above black or optical black, they were developed as
a coloured or dark bar on that edge: the D7000 and D5100's 36 columns at
~600 (#976), the D800's 14 (#914, the top in portrait), the D600 / D610's
8 (#1236), the D3200's 46, and others.
MEASURED_BODIES (crates/raw/src/vendor/nef.rs) now gives 44 more model /
data size / depth groups the frame of their camera JPEG inside the data,
next to the D4, D7100 and D90 entries already there: D7000, D5100, D800,
D800E, Df, the D4's 12-bit mode, D3, D3S, D700, D300, D300S, D600, D610,
D810, D4S, D5600, Coolpix A, D3000, D40X, D60, D80, D2Xs, D200, D3200
and Nikon 1 V1; and, on best-guess frames short of the evidence rule,
each with a comment naming its evidence, the D3100 (3 of 4 clean files
agree), D5000 (4 of 5, and the D90's sensor), D40 (2 of 2), D50 and D70
(one file each, agreeing) and D70s (next to them, between pixels).
Every best-guess frame keeps the masked lines out by several pixels.
An entry matches model, data size and depth exactly. Bodies whose data
holds only picture beyond the camera frame get no entry and render as
before.
`cargo xtask raw-frame FILE...` (crates/engine/examples/raw_frame.rs)
measures a body: it aligns each raw's embedded camera JPEG with the
sensor data (half-size luminance, gradient correlation, sub-pixel peak;
weak, ambiguous or between-pixel peaks are flagged), counts the edge
lines that hold no picture and reports what the decoder's crop keeps
beyond the camera frame. A masked line is flat and its two CFA phases
agree within the noise or within 0.4% of white, so filler with a small
fixed offset between them (D90, D5000) counts. It prints entries only
with evidence: at least 3 clean files agreeing exactly, of the model
(12- and 14-bit pooled) or, with at least one of its own, with sibling
models of the same readout (data and JPEG size) that agree on the same
frame. On the D7500, which records its CropArea, it finds that area
exactly; it declines the Z f, whose JPEG is distortion-corrected. It
works for any make whose raw embeds a full-size camera JPEG: on Sony,
Canon CR2 / CR3, Pentax and Samsung files it finds the decoder's own
crop (relative to the active area).
Every Nikon raw on raw.pixls.us without CropArea was surveyed this way
(its 138 CC0 samples, plus 124 other publicly posted sample files; only
the measurements are committed). Bodies whose data holds only picture
beyond the frame need no entry (D750, D5300, D5500, D3300, D2X, D2Hs,
D3X, D5200, Coolpix P6000, Nikon 1 AW1 / J3 / V2 / V3, the D800's crop
modes); raw-parity.md lists them, and no longer claims every NEF
coding but HE decodes. measured_bodies_are_consistent checks every entry lies
inside its data and is listed once; measured_older_dx_bodies_image_area
covers the D200, D3200, Nikon 1 V1 and best-guess entries.
Fixes#976Fixes#914Fixes#1236
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A PEF or ORF maker-note crop with an origin of `u64::MAX` and a width of
1 made `x + width` wrap to 0, so the guard read it as inside the image and
`RawImage::check`'s identical comparison also wrapped: `validate()` passed
and `normalized()` then indexed past the sample buffer. Debug builds
panicked at the guard itself ("attempt to add with overflow").
The active-area check and both vendor crop guards (PEF AOC, ORF
ImageProcessing) now compare with `checked_add`, so a wrapping rectangle
is a `Corrupt` error at validate time. Exact fits still pass.
Regression test `an_active_area_that_wraps_past_the_image_is_corrupt`
builds such an image and asserts `validate()` and `normalized()` return
`Err` (fails before the fix with the overflow panic above).
A compressed PEF too short for its size, an uncompressed tile claiming far more samples than it holds, and an ARW6 with a failed tile now get refused before the big buffer is allocated.
Deflate-compressed DNG tiles are written at zlib level 1 instead of 6. Measured on
Sony A7R VI files (67 MP), 4 threads, best of 3:
- Photo Merge DNG (half floats, 3 channels): 3.88 → 0.55 s, 265.7 → 274.8 MB (+3.4 %)
- raw export with Deflate (16-bit CFA): 0.89 → 0.18 s, 96.7 → 103.0 MB (+6.5 %)
- rendered DNG: 4.60 → 0.69 s, 239.0 → 267.1 MB (+11.8 %)
Lossless either way; both written files decode back bit-exactly. Lossless-JPEG
DNGs (the default for convert/import) are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A 7-frame bracket of 67 MP raws ran out of memory: the merge decoded the frames four at a time, and the AHD demosaic
collected every tile before copying them into a second full-size picture. Full-size frames now decode one after the
other (the demosaic is parallel inside; previews stay parallel), and AHD fills the picture by rows of tiles. Peak memory
of 67 MP HDR merges: 3 frames 4.8 → 3.8 GB, 4 frames 6.3 → 4.7 GB, about the same time; AHD output is pixel-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EOS R6 Mark II C-RAW QP maps reach 172 and 175; crx.rs accepted 131-168,
so those files opened as their preview ("Canon CRX adaptive QP value 172").
Adaptive QP now goes to 175 (quantization value 51, step 228), the highest
seen in any file; uniform subband values still stop at 44.
Checked black-box against the camera JPEGs on private files: 144 R6 II /
R7 C-RAW files decode to identical hashes where they decoded before, the 3
failing ones now decode (green follows the JPEG at r 0.98), fine detail per
QP shows no jump at 172/175, 100 % crops are clean, and 1,492 files sampled
from a 35,796-file library decode with max QP 175. No third-party decoder
source consulted. Bumps RENDER_CACHE_VERSION to 63; cr3.md and What's New.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSGFEf87ba1zKJZb9uzddK
Resolve doc conflicts in gaps, parity-checklist and raw-parity; coverage
numbers regenerated with docs/raw/coverage.py, parity summary refreshed.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>