diff options
author | Adam T. Carpenter <atc@53hor.net> | 2020-10-20 09:50:08 -0400 |
---|---|---|
committer | Adam T. Carpenter <atc@53hor.net> | 2020-10-20 09:50:08 -0400 |
commit | 76a782599b4ecc4ecb9b0ce7acc6420ed9e1ec8e (patch) | |
tree | dfc108120f067880b708a64ef6567879f4bb3284 /dichroism/src/models/new_photo_data.rs | |
parent | d3a28fde46bb06f084c74904fa8849b40e5f8c87 (diff) | |
download | theglassyladies-76a782599b4ecc4ecb9b0ce7acc6420ed9e1ec8e.tar.xz theglassyladies-76a782599b4ecc4ecb9b0ce7acc6420ed9e1ec8e.zip |
back to basics -- working on the most-required functionality first, like handlers
Diffstat (limited to 'dichroism/src/models/new_photo_data.rs')
-rw-r--r-- | dichroism/src/models/new_photo_data.rs | 95 |
1 files changed, 95 insertions, 0 deletions
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(); + } +} |