mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-14 19:27:01 -04:00
Never crash: Fix export size panic for very long strips
Apply the 1 px and 65535 px bounds in turn instead of clamping between bounds that can cross.
This commit is contained in:
1 parent
b3d392b499
commit
337f02b4dc
2 files changed
+34
-2
No files matched your search
@@ -131,8 +131,9 @@ impl Resize {
|
||||
ResizeMode::Percent => v / 100.0,
|
||||
};
|
||||
let k = if self.dont_enlarge { k.min(1.0) } else { k };
|
||||
// at least one pixel, at most the encoders' 65535 limit
|
||||
k.clamp(1.0 / short, 65_535.0 / long)
|
||||
// at least one pixel, at most the encoders' 65535 limit; the limit wins for a photo more
|
||||
// than 65535 times as long as it is short (where `clamp` would panic: min above max)
|
||||
k.max(1.0 / short).min(65_535.0 / long)
|
||||
}
|
||||
|
||||
/// Output size for a `w × h` (cropped, full-resolution) photo.
|
||||
@@ -2783,6 +2784,33 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// A photo more than 65535 times as long as it is short (a 70000 × 1 strip) made `scale`
|
||||
/// clamp with its lower bound above its upper one, which panics, in the export and in the
|
||||
/// Export dialog's preview on the UI thread. The encoders' limit wins, the short edge keeps a
|
||||
/// pixel.
|
||||
#[test]
|
||||
fn resize_survives_photos_too_long_for_the_encoders() {
|
||||
let modes = [
|
||||
json!({"longEdge": 2000}),
|
||||
json!({"shortEdge": 1}),
|
||||
json!({"width": 500, "height": 500}),
|
||||
json!({"megapixels": 1}),
|
||||
json!({"percent": 50}),
|
||||
json!({"percent": 1000, "dontEnlarge": false}),
|
||||
];
|
||||
for p in modes {
|
||||
for (w, h) in [(70_000.0, 1.0), (1.0, 70_000.0), (1e9, 3.0), (65_536.0, 1.0)] {
|
||||
let r = ExportOptions::from_json(&p).resize.unwrap();
|
||||
let (ow, oh) = r.apply(w, h);
|
||||
assert!((1..=65_535).contains(&ow) && (1..=65_535).contains(&oh), "{p} on {w}×{h}: {ow}×{oh}");
|
||||
assert!(r.scale(w, h).is_finite());
|
||||
}
|
||||
}
|
||||
// (a short edge under a pixel would be scaled up to one, which the limit then caps)
|
||||
assert_eq!(Resize::long_edge(2000).apply(70_000.0, 1.0), (65_535, 1));
|
||||
assert_eq!(Resize::long_edge(2000).apply(1.0, 70_000.0), (1, 65_535));
|
||||
}
|
||||
|
||||
/// A flat field of a saturated green inside Display P3 but outside sRGB, rendered into `space`.
|
||||
fn p3_green(space: OutputSpace) -> Rgba8 {
|
||||
use lightcraft_color::{DISPLAY_P3, REC2020};
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
## 2026-10-13
|
||||
|
||||
### Reliability
|
||||
- Exporting a photo more than 65,535 times as long as it is wide (a one-pixel strip), or opening the Export dialog's
|
||||
watermark preview for it, no longer crashes LightCraft; the export is capped at the encoders' 65,535 pixels.
|
||||
|
||||
### Slider drags on large raws
|
||||
- Dragging a slider no longer re-renders the edited photo's filmstrip thumbnail on every frame; it follows once you
|
||||
let go. On a 64 MP raw the first of those renders decoded the whole file again, which held up the loupe's
|
||||
|
||||
Reference in new issue
Block a user