mirror of
https://framagit.org/almet/jardiflore.git
synced 2025-04-28 12:02:37 +02:00
Generate a PDF out of the images
This commit is contained in:
parent
b64dd9a32c
commit
68981092ad
2 changed files with 70 additions and 25 deletions
|
@ -13,6 +13,8 @@ calamine = "0.26.1"
|
|||
chrono = "0.4.40"
|
||||
image = "0.25.6"
|
||||
imageproc = "0.25.0"
|
||||
printpdf = { version = "0.8.2", features = ["png"] }
|
||||
serde = "1.0.217"
|
||||
small_uid = "0.2.4"
|
||||
structopt = "0.3.26"
|
||||
tempfile = "3.19.1"
|
||||
|
|
93
main.rs
93
main.rs
|
@ -1,13 +1,19 @@
|
|||
use calamine::{open_workbook, Data, Reader, Xlsx};
|
||||
|
||||
use printpdf::image::RawImage;
|
||||
use printpdf::{
|
||||
Mm, Op, PdfDocument, PdfPage, PdfSaveOptions, PdfWarnMsg, RawImageData, RawImageFormat,
|
||||
XObjectTransform,
|
||||
};
|
||||
use structopt::StructOpt;
|
||||
|
||||
use ab_glyph::{FontRef, PxScale};
|
||||
use image::{ImageBuffer, Rgba};
|
||||
use image::{EncodableLayout, ImageBuffer, Rgba};
|
||||
use imageproc::drawing::draw_text_mut;
|
||||
use small_uid::SmallUid;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
// A4 dimensions
|
||||
const A4_WIDTH: f32 = 210.0;
|
||||
const A4_HEIGHT: f32 = 297.0;
|
||||
// Configuration for the label
|
||||
const DPI: f32 = 300.0;
|
||||
const MM_TO_PX: f32 = DPI / 25.4;
|
||||
|
@ -98,24 +104,13 @@ fn parse_xlsx(delivery_week_filter: &str) -> Result<Vec<Record>, Box<dyn std::er
|
|||
Ok(records)
|
||||
}
|
||||
|
||||
// The label looks like this:
|
||||
//
|
||||
// Tomate (Solanum lycopersicum) (species) /^\
|
||||
// Variété: San Marzano (variety) / j \
|
||||
// / ard \
|
||||
// / iflore\
|
||||
// ---------
|
||||
// SEMAINE DE LIVRAISON: 22
|
||||
//
|
||||
// 123 Allée des Récoltes
|
||||
// Tél: Téléphone.
|
||||
//
|
||||
fn generate_label(output_dir: &String, record: Record) -> PathBuf {
|
||||
fn generate_label(record: Record) -> ImageBuffer<Rgba<u8>, Vec<u8>> {
|
||||
let font_data = include_bytes!("./assets/DejaVuSans.ttf");
|
||||
let font = FontRef::try_from_slice(font_data).unwrap();
|
||||
let logo = image::open("./assets/logo.png").unwrap();
|
||||
|
||||
let mut label = ImageBuffer::new(LABEL_WIDTH as u32, LABEL_HEIGHT as u32);
|
||||
let mut label: ImageBuffer<Rgba<u8>, Vec<u8>> =
|
||||
ImageBuffer::new(LABEL_WIDTH as u32, LABEL_HEIGHT as u32);
|
||||
|
||||
// Fill in the background
|
||||
for pixel in label.pixels_mut() {
|
||||
|
@ -167,13 +162,62 @@ fn generate_label(output_dir: &String, record: Record) -> PathBuf {
|
|||
&font,
|
||||
&species_varieties,
|
||||
);
|
||||
return label;
|
||||
}
|
||||
|
||||
// Save the label
|
||||
fn combine_labels(
|
||||
labels: &[ImageBuffer<Rgba<u8>, Vec<u8>>],
|
||||
output_dir: &str,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let labels_per_page = (A4_HEIGHT / LABEL_HEIGHT).floor() as usize;
|
||||
|
||||
let output_path = Path::new(output_dir).join(format!("label_{}.png", SmallUid::new()));
|
||||
label.save(output_path.clone()).unwrap();
|
||||
// Create a new PDF document
|
||||
let mut doc = PdfDocument::new("Labels Document");
|
||||
let mut pages = Vec::new();
|
||||
let mut warnings: Vec<PdfWarnMsg> = Vec::new();
|
||||
|
||||
return output_path;
|
||||
// Group labels by page
|
||||
for chunk in labels.chunks(labels_per_page) {
|
||||
let mut page_contents = Vec::new();
|
||||
let mut y_position = A4_HEIGHT - LABEL_HEIGHT;
|
||||
|
||||
for label in chunk {
|
||||
// let image = RawImage::decode_from_bytes(label.as_raw(), &mut Vec::new()).unwrap();
|
||||
// let bytes = include_bytes!("output/label_GV-Ek9pYRis.png");
|
||||
let pixels = label.clone().into_raw();
|
||||
let image = RawImage {
|
||||
pixels: RawImageData::U8(pixels),
|
||||
width: LABEL_WIDTH as usize,
|
||||
height: LABEL_HEIGHT as usize,
|
||||
data_format: RawImageFormat::RGBA8,
|
||||
tag: Vec::new(),
|
||||
};
|
||||
let image_id = doc.add_image(&image);
|
||||
|
||||
// Add image to page at current y position
|
||||
page_contents.push(Op::UseXobject {
|
||||
id: image_id,
|
||||
transform: XObjectTransform::default(),
|
||||
});
|
||||
|
||||
// Move y position up for next label
|
||||
y_position -= LABEL_HEIGHT;
|
||||
}
|
||||
|
||||
// Create page and add to pages list
|
||||
let page = PdfPage::new(Mm(A4_WIDTH), Mm(A4_HEIGHT), page_contents);
|
||||
pages.push(page);
|
||||
}
|
||||
|
||||
// Add all pages to document and save
|
||||
let pdf_bytes: Vec<u8> = doc
|
||||
.with_pages(pages)
|
||||
.save(&PdfSaveOptions::default(), &mut warnings);
|
||||
|
||||
// Write PDF bytes to file
|
||||
std::fs::write("test.pdf", pdf_bytes)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(StructOpt)]
|
||||
|
@ -190,10 +234,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let week_number = "s".to_owned() + &opts.week;
|
||||
let records = parse_xlsx(&week_number)?;
|
||||
|
||||
let mut labels = Vec::new();
|
||||
for record in records {
|
||||
let path = generate_label(&opts.output_dir, record);
|
||||
println!("{}", path.into_os_string().into_string().unwrap())
|
||||
labels.push(generate_label(record));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
combine_labels(&labels, &opts.output_dir)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue