first commit, working version
This commit is contained in:
commit
50a53af97d
6 changed files with 1205 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/target
|
||||||
|
*.jpg
|
||||||
|
!background.jpg
|
||||||
1064
Cargo.lock
generated
Normal file
1064
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "instinct"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "cli"
|
||||||
|
src = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
image = { version = "0.25.5", features = ["jpeg"], default-features = false }
|
||||||
|
photon-rs = "0.3.2"
|
||||||
BIN
background.jpg
Normal file
BIN
background.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
33
src/bin/cli.rs
Normal file
33
src/bin/cli.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
use instinct::{process_image, save_image};
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut files = std::env::args().collect::<Vec<String>>();
|
||||||
|
files.remove(0);
|
||||||
|
println!("\n📸 Starting instinct processing ✨");
|
||||||
|
|
||||||
|
let mut threads = vec![];
|
||||||
|
for file in files {
|
||||||
|
threads.push(thread::spawn(move || {
|
||||||
|
let path = std::path::Path::new(&file);
|
||||||
|
println!("🎞️ Processing {:?}", path.file_name().unwrap());
|
||||||
|
let image = process_image(path);
|
||||||
|
let mut new_file_path = std::path::PathBuf::from(path);
|
||||||
|
new_file_path.set_file_name(format!(
|
||||||
|
"{} - instagram compatible.jpg",
|
||||||
|
path.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.replace(".jpg", "")
|
||||||
|
));
|
||||||
|
|
||||||
|
save_image(image, new_file_path.to_str().unwrap());
|
||||||
|
println!("🖼️ done w/ file, wrote to: {new_file_path:#?}");
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
for handle in threads {
|
||||||
|
handle.join().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
93
src/lib.rs
Normal file
93
src/lib.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
use std::io::BufWriter;
|
||||||
|
|
||||||
|
use image::{
|
||||||
|
codecs::jpeg::JpegEncoder, DynamicImage::*, EncodableLayout, ExtendedColorType::*, ImageBuffer,
|
||||||
|
};
|
||||||
|
|
||||||
|
use photon_rs::{
|
||||||
|
multiple::watermark,
|
||||||
|
native::open_image,
|
||||||
|
transform::{resize, SamplingFilter},
|
||||||
|
PhotonImage,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Add option for 4:5 export and 1:1 export
|
||||||
|
|
||||||
|
pub fn process_image(path: &std::path::Path) -> PhotonImage {
|
||||||
|
let mut image = open_image(path.to_str().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let padding = 36;
|
||||||
|
let intended_size_in_frame = 1080 - padding;
|
||||||
|
|
||||||
|
let mut background = open_image("background.jpg").unwrap();
|
||||||
|
|
||||||
|
let width = image.get_width();
|
||||||
|
let height = image.get_height();
|
||||||
|
|
||||||
|
let biggest_dimension = std::cmp::max(width, height);
|
||||||
|
println!("Original dimensions {width}x{height}");
|
||||||
|
|
||||||
|
let scaled_other_dimension = if width == biggest_dimension {
|
||||||
|
(height as f32 / (width as f32 / intended_size_in_frame as f32)) as u32
|
||||||
|
} else {
|
||||||
|
(width as f32 / (height as f32 / intended_size_in_frame as f32)) as u32
|
||||||
|
};
|
||||||
|
|
||||||
|
let image = if width == biggest_dimension {
|
||||||
|
println!("Width is bigger, setting to {intended_size_in_frame}x{scaled_other_dimension}");
|
||||||
|
|
||||||
|
resize(
|
||||||
|
&mut image,
|
||||||
|
intended_size_in_frame,
|
||||||
|
scaled_other_dimension,
|
||||||
|
SamplingFilter::Lanczos3,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
println!("Height is bigger, setting to {scaled_other_dimension}x{intended_size_in_frame}");
|
||||||
|
|
||||||
|
resize(
|
||||||
|
&mut image,
|
||||||
|
scaled_other_dimension,
|
||||||
|
intended_size_in_frame,
|
||||||
|
SamplingFilter::Lanczos3,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if width == biggest_dimension {
|
||||||
|
watermark(
|
||||||
|
&mut background,
|
||||||
|
&image,
|
||||||
|
(1080 - intended_size_in_frame) / 2,
|
||||||
|
(1080 - scaled_other_dimension) / 2,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
watermark(
|
||||||
|
&mut background,
|
||||||
|
&image,
|
||||||
|
(1080 - scaled_other_dimension) / 2,
|
||||||
|
(1080 - intended_size_in_frame) / 2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save_image(background, "result.jpg").unwrap();
|
||||||
|
|
||||||
|
// println!("done!");
|
||||||
|
background
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_image(image: PhotonImage, path: &str) {
|
||||||
|
let raw_pixels = image.get_raw_pixels();
|
||||||
|
let width = image.get_width();
|
||||||
|
let height = image.get_height();
|
||||||
|
|
||||||
|
let buffer = ImageBuffer::from_vec(width, height, raw_pixels).unwrap();
|
||||||
|
let image = ImageRgba8(buffer).into_rgb8();
|
||||||
|
|
||||||
|
let file = std::fs::File::create(path).unwrap();
|
||||||
|
let ref mut buff = BufWriter::new(file);
|
||||||
|
let mut encoder = JpegEncoder::new_with_quality(buff, 100);
|
||||||
|
|
||||||
|
encoder
|
||||||
|
.encode(&image.as_bytes(), width, height, Rgb8)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue