mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
eb2b734059
commit
900b921dbf
2 files changed
+26
-10
No files matched your search
@@ -40,7 +40,7 @@ impl Psd {
|
|||||||
Ok(self.ref_samples(&raw, w, h))
|
Ok(self.ref_samples(&raw, w, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ref_samples(&self, raw: &[u8], w: usize, h: usize) -> Vec<f32> {
|
pub(crate) fn ref_samples(&self, raw: &[u8], w: usize, h: usize) -> Vec<f32> {
|
||||||
match self.depth {
|
match self.depth {
|
||||||
1 => {
|
1 => {
|
||||||
let rowb = w.div_ceil(8);
|
let rowb = w.div_ceil(8);
|
||||||
@@ -55,13 +55,29 @@ impl Psd {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
16 => raw.as_chunks::<2>().0.iter().take(w * h).map(|c| u16::from_be_bytes([c[0], c[1]]) as f32 / 65535.0).collect(),
|
16 => raw.as_chunks::<2>().0.iter().take(w * h).map(|c| u16::from_be_bytes([c[0], c[1]]) as f32 / 65535.0).collect(),
|
||||||
32 => raw.as_chunks::<4>().0.iter().take(w * h).map(|c| f32::from_be_bytes([c[0], c[1], c[2], c[3]])).collect(),
|
// As the previous decoder after the non-finite fix: NaN reads as 0, +inf as 1, -inf as 0.
|
||||||
|
32 => raw
|
||||||
|
.as_chunks::<4>()
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.take(w * h)
|
||||||
|
.map(|c| {
|
||||||
|
let v = f32::from_be_bytes([c[0], c[1], c[2], c[3]]);
|
||||||
|
if v.is_nan() || v == f32::NEG_INFINITY {
|
||||||
|
0.0
|
||||||
|
} else if v == f32::INFINITY {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
v
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
_ => raw.iter().take(w * h).map(|&b| b as f32 / 255.0).collect(),
|
_ => raw.iter().take(w * h).map(|&b| b as f32 / 255.0).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert colour channels (in the document's mode) to RGB.
|
/// Convert colour channels (in the document's mode) to RGB.
|
||||||
fn ref_to_rgb(&self, ch: &[Option<Vec<f32>>], i: usize) -> [f32; 3] {
|
pub(crate) fn ref_to_rgb(&self, ch: &[Option<Vec<f32>>], i: usize) -> [f32; 3] {
|
||||||
let g = |k: usize| ch.get(k).and_then(|c| c.as_ref()).map_or(0.0, |c| c[i]);
|
let g = |k: usize| ch.get(k).and_then(|c| c.as_ref()).map_or(0.0, |c| c[i]);
|
||||||
let rgb = match self.mode {
|
let rgb = match self.mode {
|
||||||
ColorMode::Rgb => [g(0), g(1), g(2)],
|
ColorMode::Rgb => [g(0), g(1), g(2)],
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ fn ref_decode_channel(p: &Psd, offset: usize, len: usize, w: usize, h: usize) ->
|
|||||||
}
|
}
|
||||||
c => return Err(Error::Unsupported(format!("compression {c}"))),
|
c => return Err(Error::Unsupported(format!("compression {c}"))),
|
||||||
};
|
};
|
||||||
Ok(p.samples(&raw, w, h))
|
Ok(p.ref_samples(&raw, w, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ref_composite(p: &Psd) -> Result<Pixels> {
|
fn ref_composite(p: &Psd) -> Result<Pixels> {
|
||||||
@@ -92,7 +92,7 @@ fn ref_composite(p: &Psd) -> Result<Pixels> {
|
|||||||
match comp {
|
match comp {
|
||||||
0 => {
|
0 => {
|
||||||
for pl in planes.iter_mut().take(want) {
|
for pl in planes.iter_mut().take(want) {
|
||||||
*pl = Some(p.samples(r.bytes(rowb * h)?, w, h));
|
*pl = Some(p.ref_samples(r.bytes(rowb * h)?, w, h));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
@@ -105,7 +105,7 @@ fn ref_composite(p: &Psd) -> Result<Pixels> {
|
|||||||
for row in 0..h {
|
for row in 0..h {
|
||||||
unpack_bits(r.bytes(counts[c * h + row])?, rowb, &mut out)?;
|
unpack_bits(r.bytes(counts[c * h + row])?, rowb, &mut out)?;
|
||||||
}
|
}
|
||||||
*pl = Some(p.samples(&out, w, h));
|
*pl = Some(p.ref_samples(&out, w, h));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 | 3 => {
|
2 | 3 => {
|
||||||
@@ -116,7 +116,7 @@ fn ref_composite(p: &Psd) -> Result<Pixels> {
|
|||||||
if comp == 3 {
|
if comp == 3 {
|
||||||
ref_unpredict(p.depth, &mut plane, w, h);
|
ref_unpredict(p.depth, &mut plane, w, h);
|
||||||
}
|
}
|
||||||
*pl = Some(p.samples(&plane, w, h));
|
*pl = Some(p.ref_samples(&plane, w, h));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c => return Err(Error::Unsupported(format!("compression {c}"))),
|
c => return Err(Error::Unsupported(format!("compression {c}"))),
|
||||||
@@ -124,7 +124,7 @@ fn ref_composite(p: &Psd) -> Result<Pixels> {
|
|||||||
let alpha = if p.merged_alpha && nch > cc { planes[cc].take() } else { None };
|
let alpha = if p.merged_alpha && nch > cc { planes[cc].take() } else { None };
|
||||||
let mut data = Vec::with_capacity(w * h);
|
let mut data = Vec::with_capacity(w * h);
|
||||||
for i in 0..w * h {
|
for i in 0..w * h {
|
||||||
let [r, g, b] = p.to_rgb(&planes, i);
|
let [r, g, b] = p.ref_to_rgb(&planes, i);
|
||||||
let a = alpha.as_ref().map_or(1.0, |a| a[i]);
|
let a = alpha.as_ref().map_or(1.0, |a| a[i]);
|
||||||
data.push([r, g, b, a]);
|
data.push([r, g, b, a]);
|
||||||
}
|
}
|
||||||
@@ -175,7 +175,7 @@ fn ref_layer_pixels(p: &Psd, index: usize, canvas: bool) -> Result<Pixels> {
|
|||||||
let i = y * sw + x;
|
let i = y * sw + x;
|
||||||
let (rgb, a) = match fill {
|
let (rgb, a) = match fill {
|
||||||
Some(f) if !l.has_pixels() => (f, 1.0),
|
Some(f) if !l.has_pixels() => (f, 1.0),
|
||||||
_ => (p.to_rgb(&planes, i), alpha.as_ref().map_or(1.0, |a| a[i])),
|
_ => (p.ref_to_rgb(&planes, i), alpha.as_ref().map_or(1.0, |a| a[i])),
|
||||||
};
|
};
|
||||||
out[dy * ow + dx] = [rgb[0], rgb[1], rgb[2], a];
|
out[dy * ow + dx] = [rgb[0], rgb[1], rgb[2], a];
|
||||||
}
|
}
|
||||||
@@ -463,7 +463,7 @@ fn raw_planes_are_borrowed_and_zip_planes_are_unpredicted_in_place() {
|
|||||||
let c = q.layers[0].channels[0];
|
let c = q.layers[0].channels[0];
|
||||||
let mut r = Reader::at(&q.data, c.offset);
|
let mut r = Reader::at(&q.data, c.offset);
|
||||||
let comp = r.u16().unwrap();
|
let comp = r.u16().unwrap();
|
||||||
let plane = q.plane_bytes(comp, &mut r, 40, 30).unwrap();
|
let plane = q.plane_bytes(comp, &mut r, 40, 30, &mut Budget::new(u64::MAX)).unwrap();
|
||||||
let Cow::Borrowed(b) = plane else { panic!("raw plane was copied") };
|
let Cow::Borrowed(b) = plane else { panic!("raw plane was copied") };
|
||||||
let file = q.data.as_ptr_range();
|
let file = q.data.as_ptr_range();
|
||||||
assert!(file.contains(&b.as_ptr()) && b.len() == 1200);
|
assert!(file.contains(&b.as_ptr()) && b.len() == 1200);
|
||||||
|
|||||||
Reference in new issue
Block a user