#![cfg(feature = "pdf")]
use panimg_core::codec::{CodecRegistry, DecodeOptions};
use panimg_core::format::ImageFormat;
use std::io::Write;
use tempfile::NamedTempFile;
fn minimal_pdf() -> Vec<u8> {
let content = b"1 0 0 rg 10 10 180 80 re f";
let content_len = content.len();
let mut pdf = Vec::new();
write!(pdf, "%PDF-1.4\n").unwrap();
let obj1_offset = pdf.len();
write!(pdf, "1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n").unwrap();
let obj2_offset = pdf.len();
write!(
pdf,
"2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n"
)
.unwrap();
let obj3_offset = pdf.len();
write!(
pdf,
"3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 100] /Contents 4 0 R >>\nendobj\n"
)
.unwrap();
let obj4_offset = pdf.len();
write!(pdf, "4 0 obj\n<< /Length {content_len} >>\nstream\n").unwrap();
pdf.extend_from_slice(content);
write!(pdf, "\nendstream\nendobj\n").unwrap();
let xref_offset = pdf.len();
write!(pdf, "xref\n0 5\n").unwrap();
write!(pdf, "0000000000 65535 f \n").unwrap();
write!(pdf, "{:010} 00000 n \n", obj1_offset).unwrap();
write!(pdf, "{:010} 00000 n \n", obj2_offset).unwrap();
write!(pdf, "{:010} 00000 n \n", obj3_offset).unwrap();
write!(pdf, "{:010} 00000 n \n", obj4_offset).unwrap();
write!(pdf, "trailer\n<< /Size 5 /Root 1 0 R >>\n").unwrap();
write!(pdf, "startxref\n{xref_offset}\n%%EOF\n").unwrap();
pdf
}
#[test]
fn detect_pdf_from_bytes() {
let data = minimal_pdf();
assert_eq!(ImageFormat::from_bytes(&data), Some(ImageFormat::Pdf));
}
#[test]
fn decode_pdf_first_page() {
let data = minimal_pdf();
let mut tmp = NamedTempFile::new().unwrap();
tmp.write_all(&data).unwrap();
tmp.flush().unwrap();
let img = CodecRegistry::decode(tmp.path()).expect("should decode PDF");
assert!(img.width() > 0);
assert!(img.height() > 0);
let expected_width = (200.0 * 150.0 / 72.0) as u32;
let expected_height = (100.0 * 150.0 / 72.0) as u32;
assert!((img.width() as i32 - expected_width as i32).unsigned_abs() <= 2);
assert!((img.height() as i32 - expected_height as i32).unsigned_abs() <= 2);
}
#[test]
fn decode_pdf_custom_dpi() {
let data = minimal_pdf();
let mut tmp = NamedTempFile::new().unwrap();
tmp.write_all(&data).unwrap();
tmp.flush().unwrap();
let opts = DecodeOptions { dpi: 72.0 };
let img = CodecRegistry::decode_with_options(tmp.path(), &opts).expect("should decode PDF");
assert!((img.width() as i32 - 200).unsigned_abs() <= 2);
assert!((img.height() as i32 - 100).unsigned_abs() <= 2);
}
#[test]
fn decode_pdf_high_dpi() {
let data = minimal_pdf();
let mut tmp = NamedTempFile::new().unwrap();
tmp.write_all(&data).unwrap();
tmp.flush().unwrap();
let opts = DecodeOptions { dpi: 300.0 };
let img = CodecRegistry::decode_with_options(tmp.path(), &opts).expect("should decode PDF");
let expected_width = (200.0 * 300.0 / 72.0) as u32;
assert!((img.width() as i32 - expected_width as i32).unsigned_abs() <= 2);
}
#[test]
fn pdf_format_in_all_list() {
assert!(ImageFormat::all().contains(&ImageFormat::Pdf));
}
#[test]
fn pdf_cannot_encode() {
assert!(!ImageFormat::Pdf.can_encode());
}