use oar_ocr::domain::structure::{LayoutElementType, StructureResult};
use std::path::Path;
pub fn export_markdown_with_images(
result: &StructureResult,
output_dir: impl AsRef<Path>,
) -> std::io::Result<String> {
let output_dir = output_dir.as_ref();
let imgs_dir = output_dir.join("imgs");
if !imgs_dir.exists() {
std::fs::create_dir_all(&imgs_dir)?;
}
for element in &result.layout_elements {
if matches!(
element.element_type,
LayoutElementType::Image | LayoutElementType::Chart
) {
let type_name = if element.element_type == LayoutElementType::Chart {
"chart"
} else {
"image"
};
let img_name = format!(
"img_in_{}_box_{:.0}_{:.0}_{:.0}_{:.0}.jpg",
type_name,
element.bbox.x_min(),
element.bbox.y_min(),
element.bbox.x_max(),
element.bbox.y_max()
);
let img_path = imgs_dir.join(&img_name);
if let Some(ref img) = result.rectified_img {
let x = element.bbox.x_min().max(0.0) as u32;
let y = element.bbox.y_min().max(0.0) as u32;
let width = ((element.bbox.x_max() - element.bbox.x_min()) as u32)
.min(img.width().saturating_sub(x));
let height = ((element.bbox.y_max() - element.bbox.y_min()) as u32)
.min(img.height().saturating_sub(y));
if width > 0 && height > 0 {
let cropped =
image::imageops::crop_imm(img.as_ref(), x, y, width, height).to_image();
if let Err(e) = cropped.save(&img_path) {
tracing::warn!("Failed to save image {}: {}", img_path.display(), e);
}
}
}
}
}
Ok(result.to_markdown())
}
pub fn export_concatenated_markdown_with_images(
results: &[StructureResult],
output_dir: impl AsRef<Path>,
) -> std::io::Result<String> {
let output_dir = output_dir.as_ref();
if results.is_empty() {
return Ok(String::new());
}
for result in results {
export_markdown_with_images(result, output_dir)?;
}
let raw_markdown = oar_ocr::domain::structure::concatenate_markdown_pages(results);
let processed_markdown = oar_ocr::domain::structure::postprocess_markdown(&raw_markdown);
Ok(processed_markdown)
}