Delegate IDML image metadata to shared registry

This commit is contained in:
Dylan M. Taylor committed 2026-11-13 05:21:03 -05:00
1 parent bd757a98ac
commit 8cd90b0b7a
4 files changed
+107 -62

No files matched your search

Generated
+73 -22
View File
@@ -1181,12 +1181,12 @@ source = "git+https://github.com/storytold/craft-libs?rev=19692b6190465671e41967
[[package]]
name = "craft-eps"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551"
source = "git+https://github.com/storytold/craft-libs?rev=ba24fe2435adb3c81ad6057faf36365fbba736cf#ba24fe2435adb3c81ad6057faf36365fbba736cf"
[[package]]
name = "craft-eps"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=ba24fe2435adb3c81ad6057faf36365fbba736cf#ba24fe2435adb3c81ad6057faf36365fbba736cf"
source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558"
[[package]]
name = "craft-epub"
@@ -1201,12 +1201,12 @@ dependencies = [
[[package]]
name = "craft-file-formats"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551"
source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558"
dependencies = [
"craft-eps 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)",
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)",
"craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)",
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)",
"craft-eps 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"serde",
"serde_json",
]
@@ -1242,10 +1242,10 @@ dependencies = [
[[package]]
name = "craft-idml"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551"
source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558"
dependencies = [
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)",
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)",
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"thiserror 2.0.21",
]
@@ -1303,6 +1303,28 @@ dependencies = [
"zune-jpegxl",
]
[[package]]
name = "craft-image-codecs"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558"
dependencies = [
"craft-jpeg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"exr",
"flate2",
"half",
"image",
"image-webp",
"jpeg-encoder",
"png",
"rayon",
"serde_json",
"thiserror 2.0.21",
"tiff",
"zune-core",
"zune-jpeg",
"zune-jpegxl",
]
[[package]]
name = "craft-indd"
version = "0.1.0"
@@ -1327,6 +1349,14 @@ dependencies = [
"thiserror 2.0.21",
]
[[package]]
name = "craft-jpeg"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558"
dependencies = [
"thiserror 2.0.21",
]
[[package]]
name = "craft-keymap"
version = "0.1.0"
@@ -1493,18 +1523,6 @@ dependencies = [
"usvg 0.48.1",
]
[[package]]
name = "craft-svg"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551"
dependencies = [
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551)",
"flate2",
"kurbo",
"roxmltree 0.21.2",
"thiserror 2.0.21",
]
[[package]]
name = "craft-svg"
version = "0.1.0"
@@ -1520,6 +1538,19 @@ dependencies = [
"usvg 0.48.1",
]
[[package]]
name = "craft-svg"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558"
dependencies = [
"craft-image-codecs 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)",
"flate2",
"kurbo",
"roxmltree 0.21.2",
"thiserror 2.0.21",
]
[[package]]
name = "craft-ui"
version = "0.1.0"
@@ -1649,6 +1680,15 @@ dependencies = [
"thiserror 2.0.21",
]
[[package]]
name = "craft-xml"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558"
dependencies = [
"quick-xml 0.41.0",
"thiserror 2.0.21",
]
[[package]]
name = "craft-xml"
version = "0.1.0"
@@ -1707,6 +1747,16 @@ dependencies = [
"zip 9.1.1",
]
[[package]]
name = "craft-zip"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558"
dependencies = [
"flate2",
"thiserror 2.0.21",
"zip 9.1.1",
]
[[package]]
name = "craft-zip"
version = "0.1.0"
@@ -2052,6 +2102,7 @@ dependencies = [
name = "designcraft-idml"
version = "0.20.1"
dependencies = [
"craft-file-formats",
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=fbdd905cdddd2f0de930021a3f92bcf1684973be)",
"craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cc23ffd4d26f3074808e2187d332564817624f8f)",
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=fbdd905cdddd2f0de930021a3f92bcf1684973be)",
+1 -1
View File
@@ -28,7 +28,7 @@ craft-wordmodel = { git = "https://github.com/storytold/craft-libs", rev = "ba24
craft-csv = { git = "https://github.com/dylanmtaylor/craft-libs", rev = "44d7ac8d942dbd87048f82b3efc3e0d14483cc8d", version = "=0.1.0" }
craft-image-codecs = { git = "https://github.com/dylanmtaylor/craft-libs", rev = "2e670cf9377b523112f3fe4b409399772c745895", version = "=0.1.0" }
craft-psd = { git = "https://github.com/dylanmtaylor/craft-libs", rev = "2e670cf9377b523112f3fe4b409399772c745895", version = "=0.1.0" }
craft-file-formats = { git = "https://github.com/storytold/craft-libs", rev = "8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551", version = "=0.1.0" }
craft-file-formats = { git = "https://github.com/storytold/craft-libs", rev = "eed3c28cf016723d004d6f2c79c61424c15d4558", version = "=0.1.0" }
craft-opc = { git = "https://github.com/storytold/craft-libs", rev = "8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551", version = "=0.1.0" }
craft-pptx = { git = "https://github.com/storytold/craft-libs", rev = "f6cab1980", version = "=0.1.0" }
# Shared keyboard bindings: chords, overrides, conflicts, egui dispatch, the Keyboard Shortcuts dialog.
+1
View File
@@ -16,6 +16,7 @@ designcraft-images = { workspace = true }
craft-idml = { workspace = true }
craft-xml = { workspace = true }
craft-svg = { workspace = true }
craft-file-formats = { workspace = true }
thiserror = { workspace = true }
log = { workspace = true }
+32 -39
View File
@@ -79,44 +79,37 @@ pub enum IdmlError {
pub type Result<T> = std::result::Result<T, IdmlError>;
/// Sniff an image's MIME type and pixel size (PNG, JPEG, GIF, WebP, TIFF, PDF, EPS).
/// MIME and size metadata for a placed image, delegated to the shared format registry and image
/// boundary. The application keeps only its EPS proxy pixel-size policy.
pub(crate) fn sniff_image(b: &[u8]) -> (Option<&'static str>, Option<(u32, u32)>) {
if designcraft_images::is_eps(b) {
return (Some("application/postscript"), designcraft_images::eps_pixel_size(b));
}
let be32 = |i: usize| b.get(i..i + 4).map(|s| u32::from_be_bytes([s[0], s[1], s[2], s[3]]));
if b.starts_with(b"\x89PNG\r\n\x1a\n") {
return (Some("image/png"), be32(16).zip(be32(20)));
}
if b.starts_with(&[0xFF, 0xD8]) {
let mut i = 2;
while i + 9 < b.len() {
if b[i] != 0xFF {
i += 1;
continue;
}
let m = b[i + 1];
let len = u16::from_be_bytes([b[i + 2], b[i + 3]]) as usize;
if matches!(m, 0xC0..=0xC3 | 0xC5..=0xC7 | 0xC9..=0xCB | 0xCD..=0xCF) {
let h = u16::from_be_bytes([b[i + 5], b[i + 6]]) as u32;
let w = u16::from_be_bytes([b[i + 7], b[i + 8]]) as u32;
return (Some("image/jpeg"), Some((w, h)));
}
i += 2 + len;
}
return (Some("image/jpeg"), None);
}
if b.starts_with(b"GIF8") && b.len() >= 10 {
return (Some("image/gif"), Some((u16::from_le_bytes([b[6], b[7]]) as u32, u16::from_le_bytes([b[8], b[9]]) as u32)));
}
if b.starts_with(b"RIFF") && b.get(8..12) == Some(b"WEBP") {
return (Some("image/webp"), None);
}
if b.starts_with(b"II*\0") || b.starts_with(b"MM\0*") {
return (Some("image/tiff"), None);
}
if b.starts_with(b"%PDF") {
return (Some("application/pdf"), None);
}
(None, None)
let Some(format) = craft_file_formats::detect("", b) else { return (None, None) };
let mime = format.mime_type();
let pixels = match format {
craft_file_formats::Format::Eps => designcraft_images::eps_pixel_size(b),
craft_file_formats::Format::Png
| craft_file_formats::Format::Jpeg
| craft_file_formats::Format::Bmp
| craft_file_formats::Format::Gif
| craft_file_formats::Format::Tiff
| craft_file_formats::Format::WebP
| craft_file_formats::Format::Tga
| craft_file_formats::Format::Ico
| craft_file_formats::Format::Pnm
| craft_file_formats::Format::Pcx
| craft_file_formats::Format::Xpm
| craft_file_formats::Format::Dds
| craft_file_formats::Format::Qoi
| craft_file_formats::Format::OpenExr
| craft_file_formats::Format::Hdr
| craft_file_formats::Format::Avif
| craft_file_formats::Format::Fits
| craft_file_formats::Format::Dpx
| craft_file_formats::Format::Jxl
| craft_file_formats::Format::Cineon
| craft_file_formats::Format::Dicom
| craft_file_formats::Format::Iff
| craft_file_formats::Format::Psd => designcraft_images::pixel_size(b),
_ => None,
};
(mime, pixels)
}