diff options
Diffstat (limited to 'dichroism/src/models')
-rw-r--r-- | dichroism/src/models/mod.rs | 13 | ||||
-rw-r--r-- | dichroism/src/models/new_photo.rs | 6 | ||||
-rw-r--r-- | dichroism/src/models/new_photo_data.rs | 95 | ||||
-rw-r--r-- | dichroism/src/models/new_photo_set.rs | 8 | ||||
-rw-r--r-- | dichroism/src/models/photo.rs | 5 | ||||
-rw-r--r-- | dichroism/src/models/photo_set.rs | 8 | ||||
-rw-r--r-- | dichroism/src/models/product.rs | 26 |
7 files changed, 161 insertions, 0 deletions
diff --git a/dichroism/src/models/mod.rs b/dichroism/src/models/mod.rs new file mode 100644 index 0000000..e0fc3bd --- /dev/null +++ b/dichroism/src/models/mod.rs @@ -0,0 +1,13 @@ +mod new_photo; +mod new_photo_data; +mod new_photo_set; +mod photo; +mod photo_set; +mod product; + +pub use new_photo::*; +pub use new_photo_data::*; +pub use new_photo_set::*; +pub use photo::*; +pub use photo_set::*; +pub use product::*; diff --git a/dichroism/src/models/new_photo.rs b/dichroism/src/models/new_photo.rs new file mode 100644 index 0000000..d348e95 --- /dev/null +++ b/dichroism/src/models/new_photo.rs @@ -0,0 +1,6 @@ +use crate::schema::photos; +#[table_name = "photos"] +#[derive(Debug, Insertable)] +pub struct NewPhoto { + pub path: String, +} diff --git a/dichroism/src/models/new_photo_data.rs b/dichroism/src/models/new_photo_data.rs new file mode 100644 index 0000000..19a6557 --- /dev/null +++ b/dichroism/src/models/new_photo_data.rs @@ -0,0 +1,95 @@ +use super::NewPhoto; +use super::NewPhotoSet; +use crate::error::DichroismError; +use crate::result::Result; +use base64::decode; +use image::imageops::FilterType; +use image::DynamicImage; +use image::GenericImageView; +use regex::Regex; +use std::path::PathBuf; +use uuid::Uuid; + +use once_cell::sync::Lazy; +static DATA_URI_RE: Lazy<Regex> = Lazy::new(|| { + Regex::new("^data:image/(png|jpeg);base64,(?P<data>.+)") + .expect("Couldn't parse data URI Regex.") +}); + +pub struct NewPhotoSetData { + original: DynamicImage, // original, just for safe-keeping + fullsize: DynamicImage, // full-size, "zoomed" view + base: DynamicImage, // basic viewing + thumbnail: DynamicImage, // tiny, square thumbnail +} + +impl NewPhotoSetData { + pub fn from_data_uri(uri: &str) -> Result<Self> { + let data = DATA_URI_RE + .captures(uri) + .ok_or(DichroismError::UriDataExtract)? + .name("data") + .ok_or(DichroismError::UriDataExtract)? + .as_str(); + let original = image::load_from_memory(&decode(data)?)?; + let fullsize = original.resize(1000, 1000, FilterType::Lanczos3); + let base = original.resize(640, 640, FilterType::Lanczos3); + + let (width, height) = original.dimensions(); + let thumbnail = if width > height { + let offset = (width - height) / 2; + original.crop_imm(offset, 0, width - offset * 2, height) + } else { + let offset = (height - width) / 2; + original.crop_imm(0, offset, width, height - offset * 2) + } + .resize(300, 300, FilterType::Lanczos3); + + Ok(NewPhotoSetData { + original, + fullsize, + base, + thumbnail, + }) + } + + pub fn commit(self, prefix: &str) -> Result<NewPhotoSet> { + Ok(NewPhotoSet { + original: self.commit_single(prefix, &self.original)?, + fullsize: self.commit_single(prefix, &self.fullsize)?, + base: self.commit_single(prefix, &self.base)?, + thumbnail: self.commit_single(prefix, &self.thumbnail)?, + }) + } + + fn commit_single(&self, prefix: &str, image: &DynamicImage) -> Result<NewPhoto> { + let base_name = Uuid::new_v3(&Uuid::NAMESPACE_OID, &image.to_bytes()) + .to_hyphenated() + .to_string(); + let mut path = PathBuf::new(); + path.push(prefix); + path.push(base_name); + path.set_extension("jpg"); + image.save(&path)?; + + Ok(NewPhoto { + path: path.to_str().ok_or(DichroismError::ImageWrite)?.to_string(), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_DATA_URI: &str = include_str!("../unit_test_data/img_data_uri.txt"); + const TEST_DATA_BASE64: &str = include_str!("../unit_test_data/test_data_base64.txt"); + + #[test] + fn test_gen_product_images() { + NewPhotoSetData::from_data_uri(TEST_DATA_URI.trim()) + .unwrap() + .commit(".") + .unwrap(); + } +} diff --git a/dichroism/src/models/new_photo_set.rs b/dichroism/src/models/new_photo_set.rs new file mode 100644 index 0000000..e907592 --- /dev/null +++ b/dichroism/src/models/new_photo_set.rs @@ -0,0 +1,8 @@ +use super::NewPhoto; + +pub struct NewPhotoSet { + pub original: NewPhoto, + pub fullsize: NewPhoto, + pub base: NewPhoto, + pub thumbnail: NewPhoto, +} diff --git a/dichroism/src/models/photo.rs b/dichroism/src/models/photo.rs new file mode 100644 index 0000000..2e8b3bf --- /dev/null +++ b/dichroism/src/models/photo.rs @@ -0,0 +1,5 @@ +#[derive(Debug, Queryable, Serialize, Clone)] +pub struct Photo { + pub id: i32, + pub path: String, +} diff --git a/dichroism/src/models/photo_set.rs b/dichroism/src/models/photo_set.rs new file mode 100644 index 0000000..2f6c128 --- /dev/null +++ b/dichroism/src/models/photo_set.rs @@ -0,0 +1,8 @@ +#[derive(Debug, Queryable, Clone)] +pub struct PhotoSet { + pub id: i32, + pub base: i32, + pub fullsize: i32, + pub thumbnail: i32, + pub original: i32, +} diff --git a/dichroism/src/models/product.rs b/dichroism/src/models/product.rs new file mode 100644 index 0000000..9b81b8a --- /dev/null +++ b/dichroism/src/models/product.rs @@ -0,0 +1,26 @@ +#[derive(Debug, Clone, Queryable, Serialize)] +pub struct Product { + pub id: i32, + pub name: String, + pub quantity: i32, + pub cents: i32, + pub description: String, + pub featured: bool, + pub category_path: String, + pub photo_set: PhotoSet, +} + +#[derive(Debug, Clone, Serialize)] +pub struct PhotoSet { + pub id: i32, + pub base: i32, + pub fullsize: i32, + pub thumbnail: i32, + pub original: i32, +} + +#[derive(Debug, Clone, Serialize)] +pub struct Photo { + pub id: i32, + pub path: String, +} |