use std::fs::File;
use std::io::BufWriter;
use std::path::{Path, PathBuf};
use firecrawl_pdfium::{Pdfium, RenderConfig, RenderedPage};
fn main() {
if let Err(err) = run() {
eprintln!("error: {err}");
std::process::exit(1);
}
}
fn run() -> Result<(), Box<dyn std::error::Error>> {
let path: PathBuf = std::env::args_os()
.nth(1)
.map(PathBuf::from)
.unwrap_or_else(|| {
Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/form_text_field.pdf")
});
let pdfium = Pdfium::load()?;
let bytes = std::fs::read(&path).map_err(|e| format!("cannot read {}: {e}", path.display()))?;
let doc = pdfium.load_document(bytes, None)?;
let form_type = doc.form_type();
println!("{}", path.display());
println!("form type: {form_type:?}");
println!(
"renderable by this crate (AcroForm only): {}",
form_type.is_renderable()
);
if form_type.is_renderable() {
doc.enable_form_rendering()?;
println!("form rendering enabled: {}", doc.forms_enabled());
} else {
println!("no renderable form layer; the two renders will be identical");
}
let page = doc.page(0)?;
println!("page 0: {} x {} pt", page.width(), page.height());
let base = page.render(&RenderConfig::new().scale(2.0).form_fields(false))?;
let with_forms = page.render(&RenderConfig::new().scale(2.0).form_fields(true))?;
let differing = base
.pixels()
.chunks_exact(4)
.zip(with_forms.pixels().chunks_exact(4))
.filter(|(a, b)| a != b)
.count();
let total = base.width() as usize * base.height() as usize;
println!("pixels changed by the form layer: {differing} of {total}");
let out_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("target");
let base_path = out_dir.join("form_base.png");
let forms_path = out_dir.join("form_fields.png");
write_png(&base_path, &base)?;
write_png(&forms_path, &with_forms)?;
println!("wrote {}", base_path.display());
println!("wrote {}", forms_path.display());
Ok(())
}
fn write_png(path: &Path, rendered: &RenderedPage) -> Result<(), Box<dyn std::error::Error>> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.map_err(|e| format!("cannot create {}: {e}", parent.display()))?;
}
let file = File::create(path).map_err(|e| format!("cannot create {}: {e}", path.display()))?;
let mut encoder = png::Encoder::new(BufWriter::new(file), rendered.width(), rendered.height());
encoder.set_color(png::ColorType::Rgba);
encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder.write_header()?;
writer.write_image_data(&rendered.to_rgba8())?;
writer.finish()?;
Ok(())
}