Bug fixes:
1) use of windows sub system to avoid terminal 2) use of pathbuf for windows fix Features: 1) Saving in png file 2) Opening png file
This commit is contained in:
parent
3b0c3088fb
commit
303aad16db
|
|
@ -9,12 +9,11 @@ use fltk::{
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
path::PathBuf,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
static mut PATH: String = String::new();
|
|
||||||
|
|
||||||
/// Window to crop the existing image
|
/// Window to crop the existing image
|
||||||
pub(crate) struct CropWindow {
|
pub(crate) struct CropWindow {
|
||||||
pub win: Window,
|
pub win: Window,
|
||||||
|
|
@ -90,13 +89,9 @@ impl CropWindow {
|
||||||
/// Call it to show window to crop image
|
/// Call it to show window to crop image
|
||||||
pub(crate) fn load_to_crop(
|
pub(crate) fn load_to_crop(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &PathBuf,
|
||||||
crop_pos: Option<(f64, f64)>,
|
crop_pos: Option<(f64, f64)>,
|
||||||
) -> Option<(f64, f64)> {
|
) -> Option<(f64, f64)> {
|
||||||
unsafe {
|
|
||||||
PATH = path.to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut container =
|
let mut container =
|
||||||
ImageContainer::new(path, Arc::new(RwLock::new(ImageProperties::new())));
|
ImageContainer::new(path, Arc::new(RwLock::new(ImageProperties::new())));
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use fltk::{
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
path::Path,
|
path::{Path, PathBuf},
|
||||||
sync::{mpsc, Arc, RwLock},
|
sync::{mpsc, Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -37,6 +37,8 @@ pub(crate) fn spawn_image_thread(
|
||||||
main_win: &MainWindow,
|
main_win: &MainWindow,
|
||||||
) {
|
) {
|
||||||
let mut file_choice = main_win.file_choice.clone();
|
let mut file_choice = main_win.file_choice.clone();
|
||||||
|
let mut next_btn = main_win.next_btn.clone();
|
||||||
|
let mut back_btn = main_win.back_btn.clone();
|
||||||
let mut quote = main_win.quote.clone();
|
let mut quote = main_win.quote.clone();
|
||||||
let mut tag = main_win.tag.clone();
|
let mut tag = main_win.tag.clone();
|
||||||
let mut layer_red = main_win.layer_red.clone();
|
let mut layer_red = main_win.layer_red.clone();
|
||||||
|
|
@ -47,6 +49,7 @@ pub(crate) fn spawn_image_thread(
|
||||||
let mut tag_position = main_win.tag_position.clone();
|
let mut tag_position = main_win.tag_position.clone();
|
||||||
let mut page = main_win.page.clone();
|
let mut page = main_win.page.clone();
|
||||||
let mut status = main_win.status.clone();
|
let mut status = main_win.status.clone();
|
||||||
|
let images_path = Arc::clone(&main_win.images_path);
|
||||||
|
|
||||||
let mut _container: Option<ImageContainer> = None;
|
let mut _container: Option<ImageContainer> = None;
|
||||||
std::thread::spawn(move || loop {
|
std::thread::spawn(move || loop {
|
||||||
|
|
@ -56,6 +59,7 @@ pub(crate) fn spawn_image_thread(
|
||||||
status.set_label("Loading...");
|
status.set_label("Loading...");
|
||||||
load_image(
|
load_image(
|
||||||
&mut file_choice,
|
&mut file_choice,
|
||||||
|
Arc::clone(&images_path),
|
||||||
None,
|
None,
|
||||||
&mut quote,
|
&mut quote,
|
||||||
&mut tag,
|
&mut tag,
|
||||||
|
|
@ -74,8 +78,12 @@ pub(crate) fn spawn_image_thread(
|
||||||
}
|
}
|
||||||
DrawMessage::ChangeCrop((x, y)) => {
|
DrawMessage::ChangeCrop((x, y)) => {
|
||||||
status.set_label("Loading...");
|
status.set_label("Loading...");
|
||||||
|
file_choice.deactivate();
|
||||||
|
next_btn.deactivate();
|
||||||
|
back_btn.deactivate();
|
||||||
load_image(
|
load_image(
|
||||||
&mut file_choice,
|
&mut file_choice,
|
||||||
|
Arc::clone(&images_path),
|
||||||
Some((x, y)),
|
Some((x, y)),
|
||||||
&mut quote,
|
&mut quote,
|
||||||
&mut tag,
|
&mut tag,
|
||||||
|
|
@ -90,6 +98,9 @@ pub(crate) fn spawn_image_thread(
|
||||||
&properties,
|
&properties,
|
||||||
&mut _container,
|
&mut _container,
|
||||||
);
|
);
|
||||||
|
file_choice.activate();
|
||||||
|
next_btn.activate();
|
||||||
|
back_btn.activate();
|
||||||
status.set_label("");
|
status.set_label("");
|
||||||
}
|
}
|
||||||
DrawMessage::Recalc => {
|
DrawMessage::Recalc => {
|
||||||
|
|
@ -114,6 +125,7 @@ pub(crate) fn spawn_image_thread(
|
||||||
|
|
||||||
fn load_image(
|
fn load_image(
|
||||||
file_choice: &mut menu::Choice,
|
file_choice: &mut menu::Choice,
|
||||||
|
images_path: Arc<RwLock<Vec<PathBuf>>>,
|
||||||
crop: Option<(f64, f64)>,
|
crop: Option<(f64, f64)>,
|
||||||
quote: &mut MultilineInput,
|
quote: &mut MultilineInput,
|
||||||
tag: &mut Input,
|
tag: &mut Input,
|
||||||
|
|
@ -128,10 +140,8 @@ fn load_image(
|
||||||
properties: &Arc<RwLock<ImageProperties>>,
|
properties: &Arc<RwLock<ImageProperties>>,
|
||||||
container: &mut Option<ImageContainer>,
|
container: &mut Option<ImageContainer>,
|
||||||
) {
|
) {
|
||||||
let file: String = match file_choice.choice() {
|
let imgs = images_path.read().unwrap();
|
||||||
Some(val) => val,
|
let file = imgs.get(file_choice.value() as usize).unwrap();
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
*container = Some(ImageContainer::new(&file, Arc::clone(properties)));
|
*container = Some(ImageContainer::new(&file, Arc::clone(properties)));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![windows_subsystem = "windows"]
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod config_window;
|
mod config_window;
|
||||||
mod crop_window;
|
mod crop_window;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use fltk::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
window::Window,
|
window::Window,
|
||||||
};
|
};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::{mpsc, RwLock};
|
use std::sync::{mpsc, RwLock};
|
||||||
use std::{ffi::OsStr, fs, sync::Arc};
|
use std::{ffi::OsStr, fs, sync::Arc};
|
||||||
|
|
||||||
|
|
@ -41,6 +42,7 @@ pub(crate) struct MainWindow {
|
||||||
pub(crate) crop_btn: Button,
|
pub(crate) crop_btn: Button,
|
||||||
pub(crate) status: Frame,
|
pub(crate) status: Frame,
|
||||||
pub(crate) page: Page,
|
pub(crate) page: Page,
|
||||||
|
pub(crate) images_path: Arc<RwLock<Vec<PathBuf>>>,
|
||||||
pub(crate) draw_buff: Arc<RwLock<Vec<u8>>>,
|
pub(crate) draw_buff: Arc<RwLock<Vec<u8>>>,
|
||||||
pub(crate) properties: Arc<RwLock<ImageProperties>>,
|
pub(crate) properties: Arc<RwLock<ImageProperties>>,
|
||||||
pub(crate) sender: mpsc::Sender<DrawMessage>,
|
pub(crate) sender: mpsc::Sender<DrawMessage>,
|
||||||
|
|
@ -206,6 +208,7 @@ impl MainWindow {
|
||||||
reset_tag_position_btn,
|
reset_tag_position_btn,
|
||||||
crop_btn,
|
crop_btn,
|
||||||
status,
|
status,
|
||||||
|
images_path: Arc::new(RwLock::new(vec![])),
|
||||||
draw_buff,
|
draw_buff,
|
||||||
properties: Arc::clone(&properties),
|
properties: Arc::clone(&properties),
|
||||||
page: Page {
|
page: Page {
|
||||||
|
|
@ -226,6 +229,7 @@ impl MainWindow {
|
||||||
let mut file_choice = self.file_choice.clone();
|
let mut file_choice = self.file_choice.clone();
|
||||||
let sender = self.sender.clone();
|
let sender = self.sender.clone();
|
||||||
let mut win = self.win.clone();
|
let mut win = self.win.clone();
|
||||||
|
let imgs = Arc::clone(&self.images_path);
|
||||||
self.menubar.add(
|
self.menubar.add(
|
||||||
"&File/Open Folder...\t",
|
"&File/Open Folder...\t",
|
||||||
Shortcut::Ctrl | 'o',
|
Shortcut::Ctrl | 'o',
|
||||||
|
|
@ -249,11 +253,16 @@ impl MainWindow {
|
||||||
}
|
}
|
||||||
let files = fs::read_dir(&path).unwrap();
|
let files = fs::read_dir(&path).unwrap();
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
|
let mut imgs_b = imgs.write().unwrap();
|
||||||
|
*imgs_b = vec![];
|
||||||
for file in files {
|
for file in files {
|
||||||
let file = file.unwrap();
|
let file = file.unwrap();
|
||||||
let path = file.path();
|
let path = file.path();
|
||||||
if path.extension() == Some(OsStr::new("jpg")) {
|
if path.extension() == Some(OsStr::new("jpg"))
|
||||||
text = format!("{}|{}", text, path.to_str().unwrap());
|
|| path.extension() == Some(OsStr::new("png"))
|
||||||
|
{
|
||||||
|
text = format!("{}|{}", text, path.file_name().unwrap().to_str().unwrap());
|
||||||
|
imgs_b.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if text.len() == 0 {
|
if text.len() == 0 {
|
||||||
|
|
|
||||||
29
src/utils.rs
29
src/utils.rs
|
|
@ -1,9 +1,10 @@
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
path::Path,
|
path::{Path, PathBuf},
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use fltk::dialog;
|
||||||
use image::{DynamicImage, GenericImageView, ImageBuffer};
|
use image::{DynamicImage, GenericImageView, ImageBuffer};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
@ -55,8 +56,16 @@ pub(crate) struct ImageContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageContainer {
|
impl ImageContainer {
|
||||||
pub(crate) fn new(path: &str, properties: Arc<RwLock<ImageProperties>>) -> Self {
|
pub(crate) fn new(path: &PathBuf, properties: Arc<RwLock<ImageProperties>>) -> Self {
|
||||||
let img = image::open(path).unwrap();
|
let img = match image::open(path) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(_) => {
|
||||||
|
dialog::message_default("Failed to open image");
|
||||||
|
panic!("Failed to open image");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let img = DynamicImage::ImageRgb8(img.into_rgb8());
|
||||||
let (width, height): (f64, f64) = Coord::from(img.dimensions()).into();
|
let (width, height): (f64, f64) = Coord::from(img.dimensions()).into();
|
||||||
let (width, height) = (width, height);
|
let (width, height) = (width, height);
|
||||||
|
|
||||||
|
|
@ -178,20 +187,16 @@ impl ImageContainer {
|
||||||
prop.tag_position,
|
prop.tag_position,
|
||||||
prop.original_dimension.1,
|
prop.original_dimension.1,
|
||||||
);
|
);
|
||||||
image::save_buffer(
|
|
||||||
export,
|
if let Err(_) = img.save_with_format(&export, image::ImageFormat::Png) {
|
||||||
img.as_rgb8().unwrap().as_raw(),
|
dialog::message_default("Failed to save!");
|
||||||
crop_width as u32,
|
}
|
||||||
crop_height as u32,
|
|
||||||
image::ColorType::Rgb8,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub(crate) struct ImageProperties {
|
pub(crate) struct ImageProperties {
|
||||||
pub(crate) path: Option<String>,
|
pub(crate) path: Option<PathBuf>,
|
||||||
pub(crate) dimension: (f64, f64),
|
pub(crate) dimension: (f64, f64),
|
||||||
pub(crate) original_dimension: (f64, f64),
|
pub(crate) original_dimension: (f64, f64),
|
||||||
pub(crate) crop_position: Option<(f64, f64)>,
|
pub(crate) crop_position: Option<(f64, f64)>,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue