mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-30 04:57:22 -06:00
LR-IMP-CAMERA-COVERAGE: Nikon D90 NEFs drop their filler columns (no pink band)
The D90 writes 4352 x 2868 samples whose last 42 columns (from 4310) are filler at a flat ~254, above its dark image samples (black 0). The masked-column test only trims columns near zero, so they stayed in the image and developed as a pink band on the right. Measured on 10 of 550 NEFs from one body: the camera's 4288 x 2848 JPEG sits at (10, 10), and green saturates at 3840-3851 while red and blue run on to 4095, so one white level of 3830 keeps clipped highlights white. The D90 joins the D4 in MEASURED_BODIES; other bodies are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Vendored
+28
-2
@@ -74,8 +74,15 @@ struct MeasuredBody {
|
||||
/// 4928 × 3280 JPEG sits at (8, 6). Without this area the optical black shows as purple stripes on both sides.
|
||||
/// Green saturates at 15546–15672 while red and blue run on to 15687–16383, so the data's own top (~16300) leaves
|
||||
/// clipped highlights magenta; one level of 15520 for every channel turns them white and keeps the white balance.
|
||||
const MEASURED_BODIES: &[MeasuredBody] =
|
||||
&[MeasuredBody { model: "NIKON D4", size: (4992, 3292), bits: 14, crop: (8, 6, 4928, 3280), white: 15520.0 }];
|
||||
/// * **NIKON D90** (550 compressed 12-bit NEFs from one body, 10 measured): the data is 4352 × 2868 and its last 42
|
||||
/// columns (from 4310) are filler at a flat ~254 whatever the exposure, above the dark image samples (black 0), so
|
||||
/// the masked-column test keeps them and they develop as a pink band on the right. The camera's 4288 × 2848 JPEG
|
||||
/// sits at (10, 10). Green saturates at 3840–3851 while red and blue run on to 4095; one level of 3830 keeps
|
||||
/// clipped highlights white.
|
||||
const MEASURED_BODIES: &[MeasuredBody] = &[
|
||||
MeasuredBody { model: "NIKON D4", size: (4992, 3292), bits: 14, crop: (8, 6, 4928, 3280), white: 15520.0 },
|
||||
MeasuredBody { model: "NIKON D90", size: (4352, 2868), bits: 12, crop: (10, 10, 4288, 2848), white: 3830.0 },
|
||||
];
|
||||
|
||||
fn measured_body(model: &str, w: usize, h: usize, bits: u32) -> Option<&'static MeasuredBody> {
|
||||
MEASURED_BODIES.iter().find(|b| b.model == model.trim() && b.size == (w, h) && b.bits == bits)
|
||||
@@ -398,6 +405,25 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// The D90's last 42 columns are filler at a flat ~254, above its dark image samples: without the measured
|
||||
/// area they stay in the image and develop as a pink band on the right.
|
||||
#[test]
|
||||
fn measured_d90_drops_the_filler_columns() {
|
||||
let (w, h) = (4352usize, 2868usize);
|
||||
let mut px = vec![40u16; w * h];
|
||||
for row in px.chunks_mut(w) {
|
||||
row[4310..].fill(254);
|
||||
}
|
||||
let mut nef = nef(1, 12, vec![px.iter().flat_map(|v| v.to_le_bytes()).collect()], w as u32, h as u32, h as u32);
|
||||
let at = nef.windows(10).position(|b| b == b"NIKON TEST").unwrap();
|
||||
nef[at..at + 10].copy_from_slice(b"NIKON D90 ");
|
||||
let d90 = crate::decode(&nef).unwrap();
|
||||
assert_eq!(d90.crop, Rect::new(10, 10, 4288, 2848));
|
||||
assert!(d90.crop.x + d90.crop.width <= 4310, "the filler columns are outside the image");
|
||||
assert_eq!(d90.white, vec![3830.0]);
|
||||
assert_eq!((d90.metadata.width, d90.metadata.height), (Some(4288), Some(2848)));
|
||||
}
|
||||
|
||||
/// Issue #708: the active width is judged from the first [`MASK_ROWS`] rows in both modes, so the header probe
|
||||
/// (which reads only those rows' strips) and the full decode agree whether the masked columns are there or not.
|
||||
#[test]
|
||||
|
||||
File diff suppressed because one or more lines are too long
+4
-3
@@ -1,6 +1,6 @@
|
||||
# RAW parity: cameras, formats, demosaic, colour and lens profiles
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (EOS R5 Mark II decoded and verified: CRX QP-map escape, odd-height planes) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6 (Camera Raw 18.7)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (Nikon D90: filler columns no longer develop as a pink band; EOS R5 Mark II decoded and verified: CRX QP-map escape, odd-height planes) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6 (Camera Raw 18.7)
|
||||
|
||||
Raw processing is the deepest single dimension of Lightroom parity: a photographer whose camera
|
||||
does not decode, or decodes with the wrong colour, cannot switch. This document measures it model by
|
||||
@@ -118,7 +118,7 @@ checked, and Canon, the largest bucket, is the weakest of the big four.
|
||||
| CR3 | HEIF / HDR PQ | ⬜ | HEVC tracks recognised, not decoded |
|
||||
| CR3 | dual-pixel raw | ⬜ | never substituted |
|
||||
| CRW | all | ⬜ | preview |
|
||||
| NEF | uncompressed, lossless, lossy type 1 / 2, lossy after split | ✅ | D5100, D7000, D7500, Z f corpus; ~60 NEFs by hand; #633 |
|
||||
| NEF | uncompressed, lossless, lossy type 1 / 2, lossy after split | ✅ | D5100, D7000, D7500, Z f corpus; ~60 NEFs by hand; #633; D4 and D90 image area and white level measured against the camera JPEG |
|
||||
| NEF | packed 14-bit stored under a compressed tag (Z 6II uncompressed) | ⬜ | #769; fix in PR #671 (not merged) |
|
||||
| NEF | High Efficiency / HE★ (JPEG XS) | ⬜ | named, preview (#193); needs a JPEG XS decoder |
|
||||
| ARW | uncompressed, cRAW (ARW2), lossless LJ92 (L / M / S) | ✅ | 86 bodies (#535); M/S black level 1024 |
|
||||
@@ -172,7 +172,7 @@ sample files. A pointer for contributors, not legal advice.
|
||||
| Monochrome / LinearRaw | ✅ | handled, no demosaic | ✅ |
|
||||
| Pixel shift (Sony ARQ, Pentax, OM high-res, Nikon) | ✅ (Sony, Pentax, Nikon) | — | ⬜ |
|
||||
| Black and white levels | per model, calibrated | read from each file (masked columns, maker notes, SR2SubIFD, CMP1) | 🟡 per-body bugs keep surfacing: A450–A700 SR2 black level and M/S ARW pedestal (#535, fixed); 5D Mark IV CR2 renders dark (#455, open); white-level pile-up in phone DNGs (#548, fixed) |
|
||||
| Crop masks and aspect | ✅ | DefaultCrop, Sony recorded size, Canon AspectInfo, Panasonic in-camera crops, Nikon CropArea | 🟡 7RM3 / 7RM4 crop origin 8–32 px off (cosmetic) |
|
||||
| Crop masks and aspect | ✅ | DefaultCrop, Sony recorded size, Canon AspectInfo, Panasonic in-camera crops, Nikon CropArea, measured Nikon bodies without it (D4, D90) | 🟡 7RM3 / 7RM4 crop origin 8–32 px off (cosmetic) |
|
||||
| Lens metadata | ✅ read for profile selection | EXIF lens fields read; used only for the in-file corrections below | 🟡 |
|
||||
| Highlight reconstruction | ✅ | neutral clip, chromaticity diffusion (`highlight.rs`) | 🟡 tuned by eye |
|
||||
| AI denoise | ✅ Bayer and X-Trans, model bundled | Bayer only, user-installed weights, pure-Rust CPU / GPU | 🟡 no X-Trans, no shippable weights |
|
||||
@@ -266,6 +266,7 @@ Beyond decoding:
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-13 | minor | Nikon D90 image area (4288 × 2848 at 10, 10) and white level (3830) measured on 10 of 550 NEFs from one body: its 42 filler columns no longer develop as a pink band |
|
||||
| 2026-10-10 | minor | Compressed ORF: pointer to the two Olympus patents that describe the method, as a clean-room starting point |
|
||||
| 2026-10-11 | minor | EOS R5 Mark II verified (CRX QP-map first literal and limited-length escape, odd-height Bayer planes; 4 CC0 files pinned, QP maps of 33,665 private files): 235 verified, 942 unverified; use-weighted 85% (42% on verified bodies); decoding 77%, RAW readiness unchanged at ~56% |
|
||||
| 2026-10-10 (later) | major | Model-by-model measurement against Adobe's published list (1,446 models: 234 verified, 943 unverified, 233 preview, 36 unsupported); `docs/raw/` data and re-measure script; use-weighted share 84% (40% on verified bodies); variant matrix; colour and lens sections with scores; ranked next cameras; RAW readiness ~56% from written parts |
|
||||
|
||||
Reference in New Issue
Block a user