image generation is working

This commit is contained in:
Michal Vanko 2024-09-05 18:15:24 +02:00
parent 7734c03ba5
commit 7faafcdda9
5 changed files with 86 additions and 17 deletions

View File

@ -15,3 +15,6 @@ Cargo.lock
# `dist` folder with the export of SSG # `dist` folder with the export of SSG
dist/ dist/
# Image generator
generated_images/

View File

@ -1,27 +1,36 @@
use image::ImageFormat;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum ExportFormat { pub enum ExportFormat {
JPG, Jpeg,
AVIF, Avif,
SVG, Svg,
PNG, Png,
} }
impl ExportFormat { impl ExportFormat {
pub fn get_extension(&self) -> &str { pub fn get_extension(&self) -> &str {
match self { match self {
ExportFormat::JPG => "jpg", ExportFormat::Jpeg => "jpg",
ExportFormat::AVIF => "avif", ExportFormat::Avif => "avif",
ExportFormat::SVG => "svg", ExportFormat::Svg => "svg",
ExportFormat::PNG => "png", ExportFormat::Png => "png",
} }
} }
pub fn get_type(&self) -> &str { pub fn get_type(&self) -> &str {
match self { match self {
ExportFormat::JPG => "image/jpeg", ExportFormat::Jpeg => "image/jpeg",
ExportFormat::AVIF => "image/avif", ExportFormat::Avif => "image/avif",
ExportFormat::SVG => "image/svg+xml", ExportFormat::Svg => "image/svg+xml",
ExportFormat::PNG => "image/png", ExportFormat::Png => "image/png",
}
}
pub fn get_image_format(&self) -> ImageFormat {
match self {
ExportFormat::Jpeg => ImageFormat::Jpeg,
ExportFormat::Avif => ImageFormat::Avif,
ExportFormat::Svg => ImageFormat::Jpeg, // TODO what now?
ExportFormat::Png => ImageFormat::Png,
} }
} }
} }

View File

@ -0,0 +1,47 @@
use std::{fs::create_dir_all, path::Path};
use image::{imageops::FilterType, DynamicImage};
use tracing::{debug, error};
use super::export_format::ExportFormat;
pub fn generate_images(
image: &DynamicImage,
path_to_generated: &Path,
resolutions: &[(u32, u32, f32)],
formats: &[ExportFormat],
) -> Result<(), anyhow::Error> {
formats.iter().for_each(|format| {
resolutions.iter().for_each(|resolution| {
let (width, height, _) = *resolution;
// let image = image.clone();
let resized = image.resize_to_fill(width, height, FilterType::Triangle);
let file_name = path_to_generated.file_name().unwrap().to_str().unwrap();
let save_path = Path::new("./")
.join(path_to_generated.strip_prefix("/").unwrap())
.with_file_name(format!("{file_name}_{width}x{height}"))
.with_extension(format.get_extension());
if save_path.exists() {
return;
}
let parent_dir = save_path.parent().unwrap();
if !parent_dir.exists() {
create_dir_all(parent_dir).unwrap();
}
let result = resized.save_with_format(&save_path, format.get_image_format());
match result {
Err(err) => {
error!("Failed to generate {:?} - {:?}", &save_path, err);
}
_ => {
debug!("Generated image {:?}", &save_path);
}
}
});
});
Ok(())
}

View File

@ -22,4 +22,5 @@ It should be used from the templates as well
*/ */
pub mod export_format; pub mod export_format;
pub mod image_generator;
pub mod picture_markup_generator; pub mod picture_markup_generator;

View File

@ -7,7 +7,7 @@ use std::{
use anyhow::Context; use anyhow::Context;
use image::{GenericImageView, ImageReader}; use image::{GenericImageView, ImageReader};
use super::export_format::ExportFormat; use super::{export_format::ExportFormat, image_generator::generate_images};
pub const PIXEL_DENSITIES: [f32; 5] = [1., 1.5, 2., 3., 4.]; pub const PIXEL_DENSITIES: [f32; 5] = [1., 1.5, 2., 3., 4.];
@ -29,6 +29,15 @@ pub fn generate_picture_markup(
let orig_img_dimensions = orig_img.dimensions(); let orig_img_dimensions = orig_img.dimensions();
let resolutions = get_resolutions(orig_img_dimensions, width, height); let resolutions = get_resolutions(orig_img_dimensions, width, height);
// TODO lets generate images
generate_images(
&orig_img,
&path_to_generated,
&resolutions,
&exported_formats,
)
.with_context(|| "Failed to generate images".to_string())?;
let source_tags = exported_formats let source_tags = exported_formats
.iter() .iter()
.map(|format| { .map(|format| {
@ -243,8 +252,8 @@ fn get_export_formats(orig_img_path: &str) -> Vec<ExportFormat> {
.and_then(|ext| ext.to_str()); .and_then(|ext| ext.to_str());
match path { match path {
Some("jpg" | "jpeg") => vec![ExportFormat::AVIF, ExportFormat::JPG], Some("jpg" | "jpeg") => vec![ExportFormat::Avif, ExportFormat::Jpeg],
Some("png") => vec![ExportFormat::AVIF, ExportFormat::PNG], Some("png") => vec![ExportFormat::Avif, ExportFormat::Png],
Some(_) | None => vec![], Some(_) | None => vec![],
} }
} }
@ -253,13 +262,13 @@ fn get_export_formats(orig_img_path: &str) -> Vec<ExportFormat> {
fn test_get_export_formats() { fn test_get_export_formats() {
assert_eq!( assert_eq!(
get_export_formats("/images/uploads/img_name.jpg"), get_export_formats("/images/uploads/img_name.jpg"),
vec![ExportFormat::AVIF, ExportFormat::JPG] vec![ExportFormat::Avif, ExportFormat::Jpeg]
) )
} }
#[test] #[test]
fn test_generate_srcset() { fn test_generate_srcset() {
let orig_img_path = PathBuf::from_str("/generated_images/images/uploads/img_name").unwrap(); let orig_img_path = PathBuf::from_str("/generated_images/images/uploads/img_name").unwrap();
let export_format = ExportFormat::AVIF; let export_format = ExportFormat::Avif;
let resolutions = vec![ let resolutions = vec![
(320, 200, 1.), (320, 200, 1.),
(480, 300, 1.5), (480, 300, 1.5),