use crate::error::Pdf2MdError;
use crate::pipeline::visual::{
self, extract_visual_regions, extract_visual_regions_from_bytes,
extract_visual_regions_from_path, RegionSource, VisualRegion,
};
pub use visual::{RegionKind, MAX_AREA_FRAC, MIN_AREA_FRAC};
#[derive(Debug, Clone)]
pub struct PageRegion {
pub page_num: usize,
pub index: usize,
pub kind: RegionKind,
pub label: String,
pub bbox: (f32, f32, f32, f32),
pub width: u32,
pub height: u32,
pub image: image::DynamicImage,
pub source: RegionSource,
pub has_image: bool,
pub has_form: bool,
}
impl From<VisualRegion> for PageRegion {
fn from(v: VisualRegion) -> Self {
Self {
page_num: v.page_num,
index: v.index,
kind: v.kind,
label: v.label,
bbox: v.bbox,
width: v.width,
height: v.height,
image: v.image,
source: v.source,
has_image: v.has_image,
has_form: v.has_form,
}
}
}
pub fn extract_caption_regions_from_bytes(
pdf_bytes: &[u8],
password: Option<&str>,
) -> Result<Vec<PageRegion>, Pdf2MdError> {
Ok(extract_visual_regions_from_bytes(pdf_bytes, password)?
.into_iter()
.map(PageRegion::from)
.collect())
}
pub fn extract_caption_regions_from_path(
pdf_path: &std::path::Path,
password: Option<&str>,
) -> Result<Vec<PageRegion>, Pdf2MdError> {
Ok(extract_visual_regions_from_path(pdf_path, password)?
.into_iter()
.map(PageRegion::from)
.collect())
}
pub async fn extract_caption_regions(
pdf_bytes: &[u8],
password: Option<&str>,
) -> Result<Vec<PageRegion>, Pdf2MdError> {
Ok(extract_visual_regions(pdf_bytes, password)
.await?
.into_iter()
.map(PageRegion::from)
.collect())
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
fn sample_pdf() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test_cases/vector_figure_table_sample.pdf")
}
#[test]
fn facade_preserves_region_sized_crops() {
let path = sample_pdf();
if !path.exists() {
eprintln!("fixture missing: {path:?}");
return;
}
let regions = match extract_caption_regions_from_path(&path, None) {
Ok(v) => v,
Err(e) => {
eprintln!("pdfium unavailable: {e}");
return;
}
};
assert!(!regions.is_empty(), "expected regions from vector sample");
for r in ®ions {
let area = (r.width as u64) * (r.height as u64);
assert!(area < 1_200_000, "too large {}x{}", r.width, r.height);
}
}
}