use super::{ExportError, ExportResult};
use crate::models::Table;
use base64::{Engine as _, engine::general_purpose};
use image::{ImageBuffer, ImageEncoder, Rgb, RgbImage};
pub struct PNGExporter;
impl PNGExporter {
pub fn new() -> Self {
Self
}
pub fn export(
&self,
tables: &[Table],
width: u32,
height: u32,
) -> Result<ExportResult, ExportError> {
let png_bytes = Self::export_model_from_tables(tables, width, height)?;
Ok(ExportResult {
content: general_purpose::STANDARD.encode(&png_bytes),
format: "png".to_string(),
})
}
fn export_model_from_tables(
tables: &[Table],
width: u32,
height: u32,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let tables_to_export: Vec<&Table> = tables.iter().collect();
let mut img: RgbImage = ImageBuffer::new(width, height);
for pixel in img.pixels_mut() {
*pixel = Rgb([255u8, 255u8, 255u8]);
}
for (i, _table) in tables_to_export.iter().enumerate() {
let x = (i as u32 % 4) * (width / 4) + 50;
let y = (i as u32 / 4) * 200 + 50;
let table_width = 200u32;
let table_height = 150u32;
for px in x..(x + table_width).min(width) {
for py in y..(y + table_height).min(height) {
if px == x || px == x + table_width - 1 || py == y || py == y + table_height - 1
{
img.put_pixel(px, py, Rgb([0u8, 0u8, 0u8]));
}
}
}
}
let mut buffer = Vec::new();
{
let encoder = image::codecs::png::PngEncoder::new(&mut buffer);
encoder.write_image(&img.into_raw(), width, height, image::ColorType::Rgb8)?;
}
Ok(buffer)
}
}
impl Default for PNGExporter {
fn default() -> Self {
Self::new()
}
}