Skip to content

Commit

Permalink
create error images for faulty decodes
Browse files Browse the repository at this point in the history
  • Loading branch information
o-tho committed Dec 6, 2024
1 parent 72724f0 commit 87cea53
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 33 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ time = "0.3.36"
ttf-parser = "0.25.0"
typst-pdf = "0.12.0"
typst-render = "0.12.0"
ab_glyph = "0.2.29"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
rayon = "1.10.0"
Expand Down
55 changes: 29 additions & 26 deletions src/image_container.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::image_helpers::{binary_image_from_image, fax_to_grayimage};
use crate::image_helpers::{binary_image_from_image, create_error_image, fax_to_grayimage};
use image::{DynamicImage, GrayImage, ImageDecoder};

use pdf::any::AnySync;
Expand Down Expand Up @@ -129,9 +129,7 @@ impl ImageContainer for PdfContainer {
fn get_page(&mut self, n: usize) -> Result<GrayImage, std::boxed::Box<dyn std::error::Error>> {
let file = &self.pdf_file;
let resolver = file.resolver();

let page = file.get_page(n as u32)?;

let image = page.resources()?.xobjects.iter().find_map(|(_name, &r)| {
resolver.get(r).ok().and_then(|o| match *o {
XObject::Image(ref im) => Some(im.clone()),
Expand All @@ -141,35 +139,40 @@ impl ImageContainer for PdfContainer {

if let Some(img) = image {
let (image_data, filter) = img.raw_image_data(&resolver).unwrap();
let grayimage: Result<GrayImage, std::boxed::Box<dyn std::error::Error>> = match filter
{
Some(pdf::enc::StreamFilter::DCTDecode(_)) => Ok(binary_image_from_image(
image::load_from_memory_with_format(&image_data, image::ImageFormat::Jpeg)?,
)),

Some(pdf::enc::StreamFilter::FlateDecode(_)) => Ok(binary_image_from_image(
image::load_from_memory_with_format(&image_data, image::ImageFormat::Png)?,
)),

let result = match filter {
Some(pdf::enc::StreamFilter::DCTDecode(_)) => {
match image::load_from_memory_with_format(&image_data, image::ImageFormat::Jpeg)
{
Ok(img) => Ok(binary_image_from_image(img)),
Err(e) => Ok(create_error_image(&format!(
"Failed to decode JPEG on page {}: {}",
n + 1,
e
))),
}
}
Some(pdf::enc::StreamFilter::FlateDecode(_)) => {
match image::load_from_memory_with_format(&image_data, image::ImageFormat::Png)
{
Ok(img) => Ok(binary_image_from_image(img)),
Err(e) => Ok(create_error_image(&format!(
"Failed to decode PNG on page {}: {}",
n + 1,
e
))),
}
}
Some(pdf::enc::StreamFilter::CCITTFaxDecode(_)) => {
Ok(fax_to_grayimage(&image_data, img.width, img.height))
}

_ => Err(std::boxed::Box::new(image::ImageError::Unsupported(
image::error::UnsupportedError::from_format_and_kind(
image::error::ImageFormatHint::Unknown,
image::error::UnsupportedErrorKind::GenericFeature(
"Unsupported feature".to_string(),
),
),
_ => Ok(create_error_image(&format!(
"Could not decode image on page {}: Unsupported format",
n + 1
))),
};
grayimage
result
} else {
Err(std::boxed::Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"Page has no image",
)))
Ok(create_error_image(&format!("No image on page {}", n + 1)))
}
}
}
35 changes: 35 additions & 0 deletions src/image_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use fax::decoder;
use fax::Color;
use image::{DynamicImage, GrayImage, ImageReader, Luma, RgbImage};
use imageproc::drawing;

use std::path::Path;

/// This is the computation of the Kapur level using equ. (18) in
Expand Down Expand Up @@ -158,3 +159,37 @@ pub fn rgb_to_egui_color_image(image: &RgbImage) -> egui::ColorImage {
pixels,
}
}

pub fn create_error_image(error_text: &str) -> GrayImage {
// Create a new 400x300 grayscale image
let mut image = GrayImage::new(800, 300);

// Fill with light gray background
for pixel in image.pixels_mut() {
*pixel = image::Luma([240u8]);
}

// Load font from binary data embedded in the executable
let font_data = crate::typst_helpers::BIOLINUM_BOLD;
let font = ab_glyph::FontArc::try_from_slice(font_data).expect("Error loading font");

// Configure font scale (size)
let scale = ab_glyph::PxScale::from(30.0);

// Calculate text position
let x = 20; // Padding from left
let y = 150; // Vertically centered

// Draw the error text
imageproc::drawing::draw_text_mut(
&mut image,
image::Luma([50u8]), // Dark gray text
x,
y,
scale,
&font,
error_text,
);

image
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub fn generate_reports_for_image_container(
let scan = Scan { image: img };
let template_scan = TemplateScan::new(template, scan);
let report = template_scan
.generate_image_report(key, &format!("page{}", idx + turn * chunksize));
.generate_image_report(key, &format!("page{}", idx + turn * chunksize + 1));
report.save_to_file(&out_prefix);
let file_name = report.save_filename(&"".to_string());
(file_name, report.sid, report.score)
Expand Down
3 changes: 0 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ fn main() -> Result<(), std::boxed::Box<dyn std::error::Error>> {
csv_report =
generate_reports_for_image_container(&mut container, &t, &k, outpath)
.expect("error generating report");
println!("{}", csv_report);
}
Some("tif") | Some("tiff") => {
let buffer = std::io::BufReader::new(
Expand Down Expand Up @@ -209,8 +208,6 @@ fn main() -> Result<(), std::boxed::Box<dyn std::error::Error>> {
&template,
);

// println!("{:#?}", document);

let pdf = typst_pdf::pdf(&document, &typst_pdf::PdfOptions::default()).expect("bla");
let _ = std::fs::write(format!("{}.pdf", outprefix), pdf);

Expand Down
4 changes: 2 additions & 2 deletions src/typst_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use crate::point::Point;
use crate::template::{Box, Question, Template};

// hardcoding these for easy wasm support
const BIOLINUM: &[u8] = include_bytes!("../assets/linux-biolinum.regular.ttf");
const BIOLINUM_BOLD: &[u8] = include_bytes!("../assets/linux-biolinum.bold.ttf");
pub const BIOLINUM: &[u8] = include_bytes!("../assets/linux-biolinum.regular.ttf");
pub const BIOLINUM_BOLD: &[u8] = include_bytes!("../assets/linux-biolinum.bold.ttf");

#[derive(Debug)]
enum BubbleType {
Expand Down
2 changes: 1 addition & 1 deletion src/webapp/generate_report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ impl GenerateReport {
let template_scan = TemplateScan::new(&template, scan);
template_scan.generate_image_report(
&key,
&format!("page{}", idx + turn * chunksize),
&format!("page{}", idx + turn * chunksize + 1),
)
})
.collect();
Expand Down

0 comments on commit 87cea53

Please sign in to comment.