messense/mupdf-rs

How to use `Page`'s `to_svg` method?

namespaceYcZ opened this issue · 0 comments

The program panic when I try coverting a page to svg(STATUS_ACCESS_VIOLATION):

use std::fmt::Display;
use std::io::Write;
use std::path::Path;

use mupdf::document::Document;
use mupdf::{Matrix, Page};
/// Renders each page in the PDF file at the given path to a separate JPEG file.
pub fn export_pdf_to_images<P: Display>(
    document: Document,
    to_render: &[i32],
    rename_fn: &impl Fn(i32) -> P,
    image_path: &Path,
) -> Result<Vec<i32>, std::io::Error> {
    let mut res = vec![];
    if !image_path.exists() {
        std::fs::create_dir_all(image_path).map_err(crate::common::map_std_io_err)?;
    }
    let matrix = Matrix::IDENTITY;
    tracing::debug!("render config created: {matrix:?}");
    if to_render.is_empty() {
        // ... then render each page to a bitmap image, saving each image to a JPEG file.
        for (index, page) in document
            .pages()
            .map_err(crate::common::map_std_io_err)?
            .enumerate()
        {
            self::export_pdf_page(
                page.map_err(crate::common::map_std_io_err)?,
                image_path,
                rename_fn,
                index as i32,
                &matrix,
                &mut res,
            )?;
        }
    } else {
        for page_no in to_render {
            self::export_pdf_page(
                document
                    .load_page(*page_no)
                    .map_err(crate::common::map_std_io_err)?,
                image_path,
                rename_fn,
                *page_no,
                &matrix,
                &mut res,
            )?;
        }
    }

    Ok(res)
}
fn export_pdf_page<P: Display>(
    page: Page,
    image_path: &Path,
    rename_fn: &impl Fn(i32) -> P,
    page_no: i32,
    ctm: &Matrix,
    res: &mut Vec<i32>,
) -> std::io::Result<()> {
    let mut this_path = image_path.to_path_buf();
    let image_file_name = format!("{}.svg", rename_fn(page_no));
    tracing::debug!("image name: {image_file_name}");
    this_path.push(image_file_name);
    tracing::debug!("save image to: {this_path:?}");
    let bounds = page.bounds().map_err(crate::common::map_std_io_err)?;
    tracing::debug!("pdf bounds: {bounds}");
    let svg = page.to_svg(ctm).map_err(crate::common::map_std_io_err)?;
    tracing::debug!("page-{page_no} rendered!");
    let mut file = std::fs::File::create(this_path)?;
    tracing::debug!("file created!");
    file.write_all(svg.as_bytes())?;
    tracing::debug!("file written!");
    res.push(page_no);
    Ok(())
}
mod tests {
    #[test]
    fn test_save() -> std::io::Result<()> {
        let log_guards = crate::config::log_config::init_tracing();
        let document = mupdf::document::Document::open(
            "D:/Storage/SomePdf.pdf",
        )
        .map_err(crate::common::map_std_io_err)?;
        tracing::debug!(
            "document loaded: {} pages",
            document
                .page_count()
                .map_err(crate::common::map_std_io_err)?
        );
        super::export_pdf_to_images(
            document,
            &[1, 2],
            &|page_no| format!("test-page-{page_no}"),
            "./external/output/pics".as_ref(),
        )?;
        drop(log_guards);
        Ok(())
    }
}

test_save:
image
(As you can see, Page's bounds method was invoked successfully, so I think the mupdf lib was build correctly)

Environment

  • OS: Windows 11 version 22H2
  • Architecture: Intel x86_64
  • Rust version: 1.73.0
  • mupdf-rs version: 0.4.1