mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-12 05:12:39 +00:00
images: a WMF-only DOS EPS is not read as a TIFF preview
The DOS EPS header is 30 bytes: WMF offsets at 12/16, TIFF at 20/24, checksum at 28-29 (EPSF 3.0, section 5.2). Reading the TIFF preview from the WMF slot stopped standard previews from loading; the offsets and the fixture are back where the spec puts them, and a WMF-only file now has a regression test.
This commit is contained in:
1 parent
0c4fc4c0c5
commit
fb77f286e0
1 file changed
+27
-8
@@ -14,13 +14,10 @@ fn u32le(b: &[u8], at: usize) -> Option<usize> {
|
||||
}
|
||||
|
||||
/// The PostScript section and the TIFF preview (DOS EPS).
|
||||
///
|
||||
/// The binary header is 22 bytes: the magic (0xC5D0, 0xD3C6), `psStart`, `psLength`,
|
||||
/// `tiffStart`, `tiffLength`, then a two-byte checksum.
|
||||
fn sections(bytes: &[u8]) -> (&[u8], Option<&[u8]>) {
|
||||
if bytes.starts_with(&[0xC5, 0xD0, 0xD3, 0xC6]) {
|
||||
let ps = u32le(bytes, 4).zip(u32le(bytes, 8)).and_then(|(o, l)| bytes.get(o..o.checked_add(l)?)).unwrap_or(&[]);
|
||||
let tiff = u32le(bytes, 12).zip(u32le(bytes, 16)).filter(|(o, l)| *o > 0 && *l > 0).and_then(|(o, l)| bytes.get(o..o.checked_add(l)?));
|
||||
let tiff = u32le(bytes, 20).zip(u32le(bytes, 24)).filter(|(o, l)| *o > 0 && *l > 0).and_then(|(o, l)| bytes.get(o..o.checked_add(l)?));
|
||||
return (ps, tiff);
|
||||
}
|
||||
(bytes, None)
|
||||
@@ -227,16 +224,15 @@ mod tests {
|
||||
let (png, size) = eps_proxy(eps).unwrap();
|
||||
assert_eq!(size, (100.5, 50.25));
|
||||
assert_eq!(crate::pixel_size(&png), Some((201, 101)));
|
||||
// DOS EPS with a TIFF preview: the preview is the proxy. The binary header is 22 bytes:
|
||||
// the magic, psStart, psLength, tiffStart, tiffLength, then a two-byte checksum.
|
||||
// DOS EPS with a TIFF preview: the preview is the proxy.
|
||||
let mut tiff = Vec::new();
|
||||
image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(10, 5, image::Rgba([255, 0, 0, 255])))
|
||||
.write_to(&mut std::io::Cursor::new(&mut tiff), image::ImageFormat::Tiff)
|
||||
.unwrap();
|
||||
let mut dos = vec![0xC5, 0xD0, 0xD3, 0xC6];
|
||||
let ps_off = 22usize;
|
||||
let ps_off = 30usize;
|
||||
let tiff_off = ps_off + eps.len();
|
||||
for v in [ps_off, eps.len(), tiff_off, tiff.len()] {
|
||||
for v in [ps_off, eps.len(), 0, 0, tiff_off, tiff.len()] {
|
||||
dos.extend((v as u32).to_le_bytes());
|
||||
}
|
||||
dos.extend([0xFF, 0xFF]);
|
||||
@@ -249,6 +245,29 @@ mod tests {
|
||||
assert!(!is_eps(b"%!PS-Adobe-3.0\nnot encapsulated"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dos_eps_wmf_only_is_not_read_as_tiff() {
|
||||
let eps = b"%!PS-Adobe-3.0 EPSF-3.0\n%%BoundingBox: 0 0 100 50\nnewpath\n%%EOF\n";
|
||||
let wmf = b"WMFDATA!";
|
||||
let mut dos = vec![0xC5, 0xD0, 0xD3, 0xC6];
|
||||
let ps_off = 30usize;
|
||||
let wmf_off = ps_off + eps.len();
|
||||
for v in [ps_off, eps.len(), wmf_off, wmf.len(), 0, 0] {
|
||||
dos.extend((v as u32).to_le_bytes());
|
||||
}
|
||||
dos.extend([0xFF, 0xFF]);
|
||||
dos.extend_from_slice(eps);
|
||||
dos.extend_from_slice(wmf);
|
||||
assert!(is_eps(&dos));
|
||||
// The WMF bytes are not a TIFF preview.
|
||||
assert!(sections(&dos).1.is_none());
|
||||
// The PostScript section still parses, and the proxy is the no-preview placeholder.
|
||||
assert_eq!(bounding_box(&dos), Some([0.0, 0.0, 100.0, 50.0]));
|
||||
let (png, size) = eps_proxy(&dos).unwrap();
|
||||
assert_eq!(size, (100.0, 50.0));
|
||||
assert_eq!(crate::pixel_size(&png), Some((200, 100)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eps_bounding_box_rejects_nonfinite_sizes() {
|
||||
let bb = |line: &str| bounding_box(format!("%!PS-Adobe-3.0 EPSF-3.0\n{line}\n").as_bytes());
|
||||
|
||||
Reference in new issue
Block a user