mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-02 22:20:50 -06:00
Merge pull request #2937 from dotCooCoo/fix/ai-image-left-out-warns
.ai import: the editing data reader warns about each image it can't read
This commit is contained in:
@@ -2012,9 +2012,15 @@ impl<'a> Reader<'a> {
|
||||
/// An image of operands `vals` and samples `data`.
|
||||
fn image_from(&mut self, vals: Vec<V>, data: &[u8]) -> Result<(), String> {
|
||||
let space = self.raster.as_ref().and_then(|r| r.space.clone()).unwrap_or_default();
|
||||
let Some(m) = vals.iter().find_map(|v| if let V::Arr(a) = v { Some(Self::nums(a)) } else { None }) else { return Ok(()) };
|
||||
let Some(m) = vals.iter().find_map(|v| if let V::Arr(a) = v { Some(Self::nums(a)) } else { None }) else {
|
||||
self.warn("an image VectorCraft can't read was left out");
|
||||
return Ok(());
|
||||
};
|
||||
let n = Self::nums(&vals);
|
||||
let [_, _, _, _, w, h, bits, kind, alpha, _, binary, ..] = n.as_slice() else { return Ok(()) };
|
||||
let [_, _, _, _, w, h, bits, kind, alpha, _, binary, ..] = n.as_slice() else {
|
||||
self.warn("an image VectorCraft can't read was left out");
|
||||
return Ok(());
|
||||
};
|
||||
let (w, h) = (*w as u64, *h as u64);
|
||||
if w == 0 || h == 0 || w.saturating_mul(h) > MAX_PIXELS || ![1.0, 8.0].contains(bits) {
|
||||
self.warn("an image VectorCraft can't read was left out");
|
||||
@@ -2080,7 +2086,10 @@ impl<'a> Reader<'a> {
|
||||
rgba.extend_from_slice(&[px[0], px[1], px[2], a]);
|
||||
}
|
||||
}
|
||||
let Some(img) = image::RgbaImage::from_raw(w as u32, h as u32, rgba) else { return Ok(()) };
|
||||
let Some(img) = image::RgbaImage::from_raw(w as u32, h as u32, rgba) else {
|
||||
self.warn("an image VectorCraft can't read was left out");
|
||||
return Ok(());
|
||||
};
|
||||
let mut png = vec![];
|
||||
if img.write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png).is_err() {
|
||||
self.warn("an image VectorCraft can't read was left out");
|
||||
@@ -2096,10 +2105,14 @@ impl<'a> Reader<'a> {
|
||||
// The matrix is an art-space matrix (y up) applied to the pixels with their rows running
|
||||
// downwards, (u, -v): pixels → (u, -v) → art space. Flipping the matrix's result instead
|
||||
// gives the same place only when the image isn't rotated (b = c = 0).
|
||||
let [a, b, c, d, tx, ty] = m else { return Ok(()) };
|
||||
let [a, b, c, d, tx, ty] = m else {
|
||||
self.warn("an image VectorCraft can't read was left out");
|
||||
return Ok(());
|
||||
};
|
||||
let to_doc = self.space();
|
||||
let xf = to_doc * Affine::new([*a, *b, *c, *d, *tx, *ty]) * FLIP;
|
||||
if !xf.as_coeffs().iter().all(|v| v.is_finite()) || xf.determinant().abs() < 1e-12 {
|
||||
self.warn("an image VectorCraft can't read was left out");
|
||||
return Ok(());
|
||||
}
|
||||
let mask = alpha.and_then(|a| self.alpha_mask(a, w, h, xf));
|
||||
|
||||
@@ -677,6 +677,40 @@ fn images_with_alpha_channels() {
|
||||
assert!(art(&r.doc).is_empty() && r.warnings.iter().any(|w| w.contains("cut short")));
|
||||
}
|
||||
|
||||
/// Editing data `data` opens without its one image and with the warning "an image VectorCraft can't read was left out" once.
|
||||
fn image_left_out_with_a_warning(data: &[u8]) {
|
||||
let r = read(data).unwrap();
|
||||
assert!(art(&r.doc).is_empty(), "{:#?}", art(&r.doc));
|
||||
let left_out = r.warnings.iter().filter(|w| *w == "an image VectorCraft can't read was left out").count();
|
||||
assert_eq!(left_out, 1, "{:?}", r.warnings);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_image_without_a_matrix_is_left_out_with_a_warning() {
|
||||
image_left_out_with_a_warning(&image("", (1, 1), ("DeviceRGB", 3, 0), &[255, 0, 0], 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_image_with_too_few_operands_is_left_out_with_a_warning() {
|
||||
// The operands hold 10 numbers after the matrix, one short of the binary flag.
|
||||
let text = String::from_utf8(image("[ 1 0 0 1 0 100 ]", (1, 1), ("DeviceRGB", 3, 0), b"abc", 3)).unwrap();
|
||||
let data = text.replacen("] 0 0 1 1 1 1 8 3 0 0 1 0 4 4 0 0\n", "] 0 0 1 1 1 1 8 3 0 0\n", 1);
|
||||
assert_ne!(data, text);
|
||||
image_left_out_with_a_warning(data.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_image_whose_matrix_isnt_six_numbers_is_left_out_with_a_warning() {
|
||||
image_left_out_with_a_warning(&image("[ 1 0 0 1 ]", (1, 1), ("DeviceRGB", 3, 0), &[255, 0, 0], 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_image_whose_matrix_has_no_area_is_left_out_with_a_warning() {
|
||||
image_left_out_with_a_warning(&image("[ 0 0 0 0 0 0 ]", (1, 1), ("DeviceRGB", 3, 0), &[255, 0, 0], 3));
|
||||
// This matrix maps the image onto a line.
|
||||
image_left_out_with_a_warning(&image("[ 1 2 2 4 0 100 ]", (1, 1), ("DeviceRGB", 3, 0), &[255, 0, 0], 3));
|
||||
}
|
||||
|
||||
/// The raster matrix `[a b c d tx ty]` is an art-space matrix (y up) applied to the image's pixels
|
||||
/// with their rows running downwards, `(u, -v)`: art x = a·u − c·v + tx, art y = b·u − d·v + ty.
|
||||
/// Without rotation (b = c = 0) that is the same as flipping the matrix's result; a rotated image
|
||||
|
||||
Reference in New Issue
Block a user