use barcoders::generators::image::*;
use barcoders::sym::code128::Code128;
use image::{DynamicImage, Rgba, RgbaImage};
pub fn from(input: &str, width: u32, height: u32, margin: u32) -> Result<DynamicImage, String> {
if input.is_empty() {
return Err("Input string cannot be empty".to_string());
}
if !input.is_ascii() {
return Err(
"Input string contains invalid characters. Only ASCII characters are allowed."
.to_string(),
);
}
let starting_char = if input.chars().all(|c| c.is_ascii_alphanumeric()) {
'À' } else if input.is_ascii() {
'Ɓ' } else {
'Ć' };
let formatted_input = format!("{starting_char}{input}");
let barcode = Code128::new(&formatted_input).map_err(|e| e.to_string())?;
let png = Image::png(height); let encoded = barcode.encode();
let png_vec = png.generate(&encoded).map_err(|e| e.to_string())?;
let barcode_image = image::load_from_memory(&png_vec).map_err(|e| e.to_string())?;
let barcode_height = barcode_image.height();
let mut canvas = RgbaImage::from_pixel(width, height, Rgba([255, 255, 255, 255]));
let resized_barcode = image::imageops::resize(
&barcode_image.to_rgba8(),
width - margin * 2, (height - margin * 2).min(barcode_height),
image::imageops::FilterType::Lanczos3,
);
let x_offset = margin;
let y_offset = margin + (height - margin * 2 - resized_barcode.height()) / 2;
image::imageops::overlay(
&mut canvas,
&resized_barcode,
x_offset.into(),
y_offset.into(),
);
Ok(DynamicImage::ImageRgba8(canvas))
}