diff --git a/Cargo.lock b/Cargo.lock index f199a88..cdb2455 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -499,8 +499,9 @@ dependencies = [ [[package]] name = "imageproc" -version = "0.22.0" -source = "git+https://github.com/image-rs/imageproc#b7942657b1a370fc485507693ed4df1f8a116cb7" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aee993351d466301a29655d628bfc6f5a35a0d062b6160ca0808f425805fd7" dependencies = [ "approx", "conv", @@ -883,7 +884,7 @@ dependencies = [ [[package]] name = "post_maker" -version = "0.4.0-alpha.5" +version = "0.5.0-alpha.1" dependencies = [ "bichannel", "clap", diff --git a/Cargo.toml b/Cargo.toml index 9bec406..963c209 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "post_maker" -version = "0.4.0-alpha.6" +version = "0.5.0-alpha.1" edition = "2021" description = "Post Maker helps you to make post for Instagram and other Social Media apps easily." authors = ["PiyushXCoder "] @@ -23,7 +23,7 @@ simplelog = "0.11" fltk = "1.2" fltk-theme = "0.4" image = "0.24.1" -imageproc = { git = "https://github.com/image-rs/imageproc" } +imageproc = "0.23" webp = "0.2" rusttype = "0.9" serde_json = "1.0" diff --git a/src/config.rs b/src/config.rs index 9fd0b61..27a8520 100644 --- a/src/config.rs +++ b/src/config.rs @@ -125,7 +125,8 @@ pub(crate) struct ConfigFile { pub(crate) quote_position_ratio: f64, pub(crate) subquote_position_ratio: f64, pub(crate) subquote2_position_ratio: f64, - pub(crate) tag_position_ratio: f64, + pub(crate) tag_x_position_ratio: f64, + pub(crate) tag_y_position_ratio: f64, pub(crate) tag2_position_ratio: f64, pub(crate) image_ratio: (f64, f64), pub(crate) color_layer: [u8; 4], @@ -150,7 +151,8 @@ impl Default for ConfigFile { quote_position_ratio: 0.7, subquote_position_ratio: 0.8, subquote2_position_ratio: 0.9, - tag_position_ratio: 0.5, + tag_x_position_ratio: 0.95, + tag_y_position_ratio: 0.5, tag2_position_ratio: 0.95, image_ratio: (4.0, 5.0), color_layer: [20, 22, 25, 197], diff --git a/src/config_window.rs b/src/config_window.rs index cdc4130..db0e1e7 100644 --- a/src/config_window.rs +++ b/src/config_window.rs @@ -17,8 +17,8 @@ use crate::{ config::{self, ConfigFile}, dialog, globals, + result_ext::ResultExt, utils::{self, ImageType}, - result_ext::ResultExt }; use fltk::{ app, @@ -60,7 +60,8 @@ pub(crate) struct ConfigWindow { pub(crate) quote_position_ratio: ValueInput, pub(crate) subquote_position_ratio: ValueInput, pub(crate) subquote2_position_ratio: ValueInput, - pub(crate) tag_position_ratio: ValueInput, + pub(crate) tag_x_position_ratio: ValueInput, + pub(crate) tag_y_position_ratio: ValueInput, pub(crate) tag2_position_ratio: ValueInput, pub(crate) image_ratio_width: ValueInput, pub(crate) image_ratio_height: ValueInput, @@ -335,16 +336,27 @@ impl ConfigWindow { // column 2 let mut col_grp = Flex::default().column(); - let mut tag_position_ratio_grp = Flex::default().row(); - tag_position_ratio_grp.set_size( + let mut tag_x_position_ratio_grp = Flex::default().row(); + tag_x_position_ratio_grp.set_size( &Frame::default() - .with_label("Tag") + .with_label("Tag (x)") .with_align(Align::Right | Align::Inside), 130, ); - let tag_position_ratio = ValueInput::default(); - tag_position_ratio_grp.end(); - col_grp.set_size(&tag_position_ratio_grp, 30); + let tag_x_position_ratio = ValueInput::default(); + tag_x_position_ratio_grp.end(); + col_grp.set_size(&tag_x_position_ratio_grp, 30); + + let mut tag_y_position_ratio_grp = Flex::default().row(); + tag_y_position_ratio_grp.set_size( + &Frame::default() + .with_label("Tag (y)") + .with_align(Align::Right | Align::Inside), + 130, + ); + let tag_y_position_ratio = ValueInput::default(); + tag_y_position_ratio_grp.end(); + col_grp.set_size(&tag_y_position_ratio_grp, 30); let mut tag2_position_ratio_grp = Flex::default().row(); tag2_position_ratio_grp.set_size( @@ -488,7 +500,8 @@ impl ConfigWindow { quote_position_ratio, subquote_position_ratio, subquote2_position_ratio, - tag_position_ratio, + tag_x_position_ratio, + tag_y_position_ratio, tag2_position_ratio, image_ratio_width, image_ratio_height, @@ -540,7 +553,10 @@ impl ConfigWindow { .set_value(config.subquote_position_ratio); self.subquote2_position_ratio .set_value(config.subquote2_position_ratio); - self.tag_position_ratio.set_value(config.tag_position_ratio); + self.tag_x_position_ratio + .set_value(config.tag_x_position_ratio); + self.tag_y_position_ratio + .set_value(config.tag_y_position_ratio); self.tag2_position_ratio .set_value(config.tag2_position_ratio); self.image_ratio_width.set_value(config.image_ratio.0); @@ -590,7 +606,8 @@ impl ConfigWindow { let mut quote_position_ratio = self.quote_position_ratio.clone(); let mut subquote_position_ratio = self.subquote_position_ratio.clone(); let mut subquote2_position_ratio = self.subquote2_position_ratio.clone(); - let mut tag_position_ratio = self.tag_position_ratio.clone(); + let mut tag_x_position_ratio = self.tag_x_position_ratio.clone(); + let mut tag_y_position_ratio = self.tag_y_position_ratio.clone(); let mut tag2_position_ratio = self.tag2_position_ratio.clone(); let mut image_ratio_width = self.image_ratio_width.clone(); let mut image_ratio_height = self.image_ratio_height.clone(); @@ -635,7 +652,8 @@ impl ConfigWindow { quote_position_ratio.set_value(conf.quote_position_ratio); subquote_position_ratio.set_value(conf.subquote_position_ratio); subquote2_position_ratio.set_value(conf.subquote2_position_ratio); - tag_position_ratio.set_value(conf.tag_position_ratio); + tag_x_position_ratio.set_value(conf.tag_x_position_ratio); + tag_y_position_ratio.set_value(conf.tag_y_position_ratio); tag2_position_ratio.set_value(conf.tag2_position_ratio); image_ratio_width.set_value(conf.image_ratio.0); image_ratio_height.set_value(conf.image_ratio.1); @@ -664,7 +682,8 @@ impl ConfigWindow { let mut quote_position_ratio = self.quote_position_ratio.clone(); let mut subquote_position_ratio = self.subquote_position_ratio.clone(); let mut subquote2_position_ratio = self.subquote2_position_ratio.clone(); - let mut tag_position_ratio = self.tag_position_ratio.clone(); + let mut tag_x_position_ratio = self.tag_x_position_ratio.clone(); + let mut tag_y_position_ratio = self.tag_y_position_ratio.clone(); let mut tag2_position_ratio = self.tag2_position_ratio.clone(); let mut image_ratio_width = self.image_ratio_width.clone(); let mut image_ratio_height = self.image_ratio_height.clone(); @@ -708,7 +727,8 @@ impl ConfigWindow { quote_position_ratio.set_value(conf.quote_position_ratio); subquote_position_ratio.set_value(conf.subquote_position_ratio); subquote2_position_ratio.set_value(conf.subquote2_position_ratio); - tag_position_ratio.set_value(conf.tag_position_ratio); + tag_x_position_ratio.set_value(conf.tag_x_position_ratio); + tag_y_position_ratio.set_value(conf.tag_y_position_ratio); tag2_position_ratio.set_value(conf.tag2_position_ratio); image_ratio_width.set_value(conf.image_ratio.0); image_ratio_height.set_value(conf.image_ratio.1); @@ -734,7 +754,8 @@ impl ConfigWindow { let mut quote_position_ratio = self.quote_position_ratio.clone(); let mut subquote_position_ratio = self.subquote_position_ratio.clone(); let mut subquote2_position_ratio = self.subquote2_position_ratio.clone(); - let mut tag_position_ratio = self.tag_position_ratio.clone(); + let mut tag_x_position_ratio = self.tag_x_position_ratio.clone(); + let mut tag_y_position_ratio = self.tag_y_position_ratio.clone(); let mut tag2_position_ratio = self.tag2_position_ratio.clone(); let mut image_ratio_width = self.image_ratio_width.clone(); let mut image_ratio_height = self.image_ratio_height.clone(); @@ -768,7 +789,8 @@ impl ConfigWindow { quote_position_ratio.set_value(conf.quote_position_ratio); subquote_position_ratio.set_value(conf.subquote_position_ratio); subquote2_position_ratio.set_value(conf.subquote2_position_ratio); - tag_position_ratio.set_value(conf.tag_position_ratio); + tag_x_position_ratio.set_value(conf.tag_x_position_ratio); + tag_y_position_ratio.set_value(conf.tag_y_position_ratio); tag2_position_ratio.set_value(conf.tag2_position_ratio); image_ratio_width.set_value(conf.image_ratio.0); image_ratio_height.set_value(conf.image_ratio.1); @@ -1011,16 +1033,31 @@ impl ConfigWindow { true }); - // Tag position ratio + // Tag x position ratio let browse = self.browse.clone(); let configs = Rc::clone(&self.configs); - self.tag_position_ratio.handle(move |f, ev| { + self.tag_x_position_ratio.handle(move |f, ev| { if ev == Event::KeyUp { if let Some(conf) = configs .borrow_mut() .get_mut(&browse.selected_text().unwrap()) { - conf.tag_position_ratio = f.value(); + conf.tag_x_position_ratio = f.value(); + } + } + true + }); + + // Tag y position ratio + let browse = self.browse.clone(); + let configs = Rc::clone(&self.configs); + self.tag_y_position_ratio.handle(move |f, ev| { + if ev == Event::KeyUp { + if let Some(conf) = configs + .borrow_mut() + .get_mut(&browse.selected_text().unwrap()) + { + conf.tag_y_position_ratio = f.value(); } } true @@ -1183,7 +1220,8 @@ impl ConfigWindow { let mut quote_position_ratio = self.quote_position_ratio.clone(); let mut subquote_position_ratio = self.subquote_position_ratio.clone(); let mut subquote2_position_ratio = self.subquote2_position_ratio.clone(); - let mut tag_position_ratio = self.tag_position_ratio.clone(); + let mut tag_x_position_ratio = self.tag_x_position_ratio.clone(); + let mut tag_y_position_ratio = self.tag_y_position_ratio.clone(); let mut tag2_position_ratio = self.tag2_position_ratio.clone(); let mut image_ratio_width = self.image_ratio_width.clone(); let mut image_ratio_height = self.image_ratio_height.clone(); @@ -1210,7 +1248,8 @@ impl ConfigWindow { quote_position_ratio.set_value(conf.quote_position_ratio); subquote_position_ratio.set_value(conf.subquote_position_ratio); subquote2_position_ratio.set_value(conf.subquote2_position_ratio); - tag_position_ratio.set_value(conf.tag_position_ratio); + tag_x_position_ratio.set_value(conf.tag_x_position_ratio); + tag_y_position_ratio.set_value(conf.tag_y_position_ratio); tag2_position_ratio.set_value(conf.tag2_position_ratio); image_ratio_width.set_value(conf.image_ratio.0); image_ratio_height.set_value(conf.image_ratio.1); diff --git a/src/draw_thread.rs b/src/draw_thread.rs index 7a365c2..56d57a9 100644 --- a/src/draw_thread.rs +++ b/src/draw_thread.rs @@ -68,6 +68,7 @@ pub(crate) fn spawn_image_thread( ) { let mut win = main_win.win.clone(); let mut file_choice = main_win.file_choice.clone(); + let mut name_prefix = main_win.name_prefix.clone(); let mut quote = main_win.quote.clone(); let mut subquote = main_win.subquote.clone(); let mut subquote2 = main_win.subquote2.clone(); @@ -101,6 +102,7 @@ pub(crate) fn spawn_image_thread( &mut file_choice, Arc::clone(&images_list), None, + &mut name_prefix, &mut quote, &mut subquote, &mut subquote2, @@ -134,6 +136,7 @@ pub(crate) fn spawn_image_thread( &mut file_choice, Arc::clone(&images_list), Some((x, y)), + &mut name_prefix, &mut quote, &mut subquote, &mut subquote2, @@ -240,6 +243,7 @@ fn load_image( file_choice: &mut menu::Choice, images_list: Arc>>, crop: Option<(f64, f64)>, + name_prefix: &mut Input, quote: &mut MultilineInput, subquote: &mut MultilineInput, subquote2: &mut MultilineInput, @@ -293,6 +297,7 @@ fn load_image( properties.merge(read, &tag.value(), &tag2.value()); properties.is_saved = true; + name_prefix.set_value(&properties.name_prefix); quote.set_value(&properties.quote); subquote.set_value(&properties.subquote); subquote2.set_value(&properties.subquote2); diff --git a/src/export_all_window.rs b/src/export_all_window.rs index 58db095..41d3f47 100644 --- a/src/export_all_window.rs +++ b/src/export_all_window.rs @@ -200,6 +200,12 @@ fn spawn_export_thread( let total = rw_read!(images_list).len(); progress.set_maximum(total as f64); progress.set_value(0.0); + + let mut update_progress = |idx: usize| { + progress.set_value(idx as f64 + 1.0); + progress.set_label(&format!("[{}/{}]", idx + 1, total)); + }; + for (idx, image) in (*rw_read!(images_list)).iter().enumerate() { image_name.set_label( image @@ -214,23 +220,29 @@ fn spawn_export_thread( let properties_file = utils::get_properties_path(image); let read = match File::open(&properties_file) { Ok(r) => r, - Err(_) => continue, + Err(_) => { + update_progress(idx); + continue; + } }; let read = match serde_json::from_reader::(read) { Ok(r) => r, - Err(_) => continue, + Err(_) => { + update_progress(idx); + continue; + } }; rw_write!(container.properties).merge(read, "", ""); if rw_read!(container.properties).quote.trim().len() == 0 { + update_progress(idx); continue; } container.save(); - progress.set_value(idx as f64 + 1.0); - progress.set_label(&format!("[{}/{}]", idx + 1, total)); + update_progress(idx); win.redraw(); app::awake(); @@ -247,6 +259,7 @@ fn spawn_export_thread( } } image_name.set_label("Finished"); + progress.set_value(total as f64); close_btn.set_label("Close"); *rw_write!(finished) = true; win.redraw(); diff --git a/src/main_window.rs b/src/main_window.rs index 0012d05..5feea3a 100644 --- a/src/main_window.rs +++ b/src/main_window.rs @@ -56,6 +56,7 @@ pub(crate) struct MainWindow { pub(crate) save_btn: Button, /// To choose the file which is being edited in directory pub(crate) file_choice: menu::Choice, + pub(crate) name_prefix: Input, pub(crate) quote: MultilineInput, pub(crate) subquote: MultilineInput, pub(crate) subquote2: MultilineInput, @@ -133,6 +134,15 @@ impl MainWindow { let mut workspace_flex = Flex::default().row(); // Controls Left let mut left_controls_flex = Flex::default().column(); + left_controls_flex.set_size( + &Frame::default() + .with_label("Name Prefix:") + .with_align(enums::Align::Left | enums::Align::Inside), + 25, + ); + let name_prefix = Input::default(); + left_controls_flex.set_size(&name_prefix, 30); + left_controls_flex.set_size( &Frame::default() .with_label("Quote:") @@ -355,6 +365,7 @@ impl MainWindow { next_btn, save_btn, file_choice, + name_prefix, quote, subquote, subquote2, @@ -675,7 +686,7 @@ impl MainWindow { self.reset_tag_position_btn.set_callback(move |_| { let mut prop = rw_write!(properties); let height = prop.original_dimension.1; - let pos = height * rw_read!(globals::CONFIG).tag_position_ratio; + let pos = height * rw_read!(globals::CONFIG).tag_y_position_ratio; prop.tag_position = pos; prop.is_saved = false; tag_position.set_value(pos); @@ -824,6 +835,17 @@ impl MainWindow { sender.send_it(DrawMessage::CheckImage); }); + // Name Prefix Input + let properties = Arc::clone(&self.properties); + self.name_prefix.handle(move |f, ev| { + if ev == enums::Event::KeyUp { + let mut prop = rw_write!(properties); + prop.name_prefix = f.value(); + prop.is_saved = false; + } + true + }); + // Quote Input let mut image = self.page.image.clone(); let properties = Arc::clone(&self.properties); diff --git a/src/utils.rs b/src/utils.rs index 149d66a..bfc1456 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -126,7 +126,7 @@ impl ImageContainer { prop.quote_position = height * config.quote_position_ratio; prop.subquote_position = height * config.subquote_position_ratio; prop.subquote2_position = height * config.subquote2_position_ratio; - prop.tag_position = height * config.tag_position_ratio; + prop.tag_position = height * config.tag_y_position_ratio; prop.tag2_position = height * config.tag2_position_ratio; Self { @@ -223,7 +223,7 @@ impl ImageContainer { let image_info = &prop.image_info; let (export_path, path_properties, mut original_image) = match image_info { Some(p) => ( - get_export_image_path(p), + get_export_image_path(p, &prop.name_prefix), get_properties_path(p), load_image(p), ), @@ -361,11 +361,10 @@ impl ImageContainer { pub(crate) fn delete(&self) { let prop = rw_read!(self.properties); - let image_info = &prop.image_info; let (export_path, path_image, path_properties) = match image_info { Some(p) => ( - get_export_image_path(p), + get_export_image_path(p, &prop.name_prefix), Path::new(&p.path), get_properties_path(p), ), @@ -390,6 +389,7 @@ impl ImageContainer { #[derive(Serialize, Deserialize, Debug, Clone)] pub(crate) struct ImagePropertiesFile { pub(crate) crop_position: Option<(f64, f64)>, + pub(crate) name_prefix: Option, pub(crate) quote: Option, pub(crate) subquote: Option, pub(crate) subquote2: Option, @@ -407,6 +407,7 @@ impl Default for ImagePropertiesFile { fn default() -> Self { Self { crop_position: None, + name_prefix: None, quote: None, subquote: None, subquote2: None, @@ -426,6 +427,7 @@ impl From<&ImageProperties> for ImagePropertiesFile { fn from(props: &ImageProperties) -> Self { Self { crop_position: props.crop_position, + name_prefix: Some(props.name_prefix.clone()), quote: Some(props.quote.clone()), subquote: Some(props.subquote.clone()), subquote2: Some(props.subquote2.clone()), @@ -448,6 +450,7 @@ pub(crate) struct ImageProperties { pub(crate) dimension: (f64, f64), pub(crate) original_dimension: (f64, f64), pub(crate) crop_position: Option<(f64, f64)>, + pub(crate) name_prefix: String, pub(crate) quote: String, pub(crate) subquote: String, pub(crate) subquote2: String, @@ -469,6 +472,7 @@ impl Default for ImageProperties { dimension: (0.0, 0.0), original_dimension: (0.0, 0.0), crop_position: None, + name_prefix: "".to_owned(), quote: "".to_owned(), subquote: "".to_owned(), subquote2: "".to_owned(), @@ -493,6 +497,7 @@ impl ImageProperties { tag2_default: &str, ) { self.crop_position = props.crop_position; + self.name_prefix = props.name_prefix.unwrap_or("".to_owned()); self.quote = props.quote.unwrap_or("".to_owned()); self.subquote = props.subquote.unwrap_or("".to_owned()); self.subquote2 = props.subquote2.unwrap_or("".to_owned()); @@ -564,7 +569,7 @@ fn draw_layer_and_text( subquote2_position: f64, tag: &str, tag2: &str, - tag_position: f64, + tag_y_position: f64, tag2_position: f64, original_height: f64, ) { @@ -624,8 +629,9 @@ fn draw_layer_and_text( imageproc::drawing::draw_text_mut( tmp, image::Rgba([255, 255, 255, 255]), - (width * 0.99 - text_width) as i32, - ((tag_position * height) / original_height + index as f64 * (text_height * 1.2)) as i32, + (width * rw_read!(globals::CONFIG).tag_x_position_ratio - text_width) as i32, + ((tag_y_position * height) / original_height + index as f64 * (text_height * 1.2)) + as i32, rusttype::Scale::uniform(size as f32), &globals::FONT_TAG, line, @@ -725,7 +731,7 @@ pub(crate) fn get_properties_path(image_info: &ImageInfo) -> PathBuf { } /// path of properties files -pub(crate) fn get_export_image_path(image_info: &ImageInfo) -> PathBuf { +pub(crate) fn get_export_image_path(image_info: &ImageInfo, name_prefix: &str) -> PathBuf { let config = rw_read!(globals::CONFIG); let export_format = &config.image_format; let image_name = image_info @@ -751,7 +757,8 @@ pub(crate) fn get_export_image_path(image_info: &ImageInfo) -> PathBuf { .into_iter() .rev(); let image_name = format!( - "{}.{}", + "{}{}.{}", + name_prefix, String::from_iter(image_name), export_format.as_extension() );