This commit is contained in:
Brandon Thomas committed 2026-10-12 23:31:21 -04:00
commit f2a9888f75
1 file changed
+52 -4
+52 -4
View File
@@ -245,11 +245,25 @@ pub fn decode_unguarded(bytes: &[u8], format: Format, opts: &DecodeOptions) -> R
/// Convert a decode result to linear Rec.2020 D65 (Bradford-adapted), the develop working space.
pub fn to_working(d: &Decoded) -> Rgb32f {
if d.space.is_working() {
return d.image.clone();
let mut image = if d.space.is_working() {
d.image.clone()
} else {
let m = d.space.to_working().to_f32();
d.image.map(|p| mat_apply(&m, p))
};
// Straight alpha onto white. JPEG and contact sheets have no alpha, and a transparent
// pixel is usually stored as black (#1212).
if let Some(alpha) = &d.alpha {
let w = image.width;
lightcraft_raster::par_rows(&mut image.data, w, |y, row| {
let a = alpha.row(y);
for (p, &alpha) in row.iter_mut().zip(a) {
let a = alpha.clamp(0.0, 1.0);
*p = p.map(|c| c * a + (1.0 - a));
}
});
}
let m = d.space.to_working().to_f32();
d.image.map(|p| mat_apply(&m, p))
image
}
/// Where a thumbnail came from.
@@ -323,3 +337,37 @@ pub fn decode_thumbnail_with(bytes: &[u8], opts: &ThumbnailOptions) -> Result<Th
source_height: d.source_height,
})
}
#[cfg(test)]
mod alpha_tests {
use super::*;
use lightcraft_raster::Plane;
#[test]
fn straight_alpha_composites_onto_white_in_the_working_space() {
let image = Rgb32f::filled(2, 1, [0.0, 0.0, 0.0]);
let alpha = Plane::from_fn(2, 1, |x, _| if x == 0 { 0.0 } else { 0.5 });
let d = Decoded {
format: Format::Png,
image,
alpha: Some(alpha),
space: SourceSpace::named(NamedSpace::Rec2020, SpaceOrigin::Container),
bit_depth: 8,
float: false,
has_alpha: true,
grayscale: false,
cmyk: false,
orientation: 1,
exif: None,
xmp: None,
icc: None,
width: 2,
height: 1,
source_width: 2,
source_height: 1,
};
let w = to_working(&d);
assert!((w.get(0, 0)[0] - 1.0).abs() < 1e-5, "a fully transparent black pixel becomes white");
assert!((w.get(1, 0)[0] - 0.5).abs() < 1e-5);
}
}