Image export formats
This commit is contained in:
parent
7f67d5ad29
commit
3d9b20bbc8
|
|
@ -626,7 +626,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "post_maker"
|
name = "post_maker"
|
||||||
version = "0.2.6"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "post_maker"
|
name = "post_maker"
|
||||||
version = "0.2.6"
|
version = "0.3.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Post Maker helps you to make post for Instagram and other Social Media apps easily."
|
description = "Post Maker helps you to make post for Instagram and other Social Media apps easily."
|
||||||
authors = ["PiyushXCoder <https://piyushxcoder.in>"]
|
authors = ["PiyushXCoder <https://piyushxcoder.in>"]
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,7 @@ pub(crate) struct ConfigFile {
|
||||||
pub(crate) tag2_position_ratio: f64,
|
pub(crate) tag2_position_ratio: f64,
|
||||||
pub(crate) image_ratio: (f64, f64),
|
pub(crate) image_ratio: (f64, f64),
|
||||||
pub(crate) color_layer: [u8; 4],
|
pub(crate) color_layer: [u8; 4],
|
||||||
|
pub(crate) image_format: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ConfigFile {
|
impl Default for ConfigFile {
|
||||||
|
|
@ -138,7 +139,7 @@ impl Default for ConfigFile {
|
||||||
subquote2_font: String::new(),
|
subquote2_font: String::new(),
|
||||||
tag_font: String::new(),
|
tag_font: String::new(),
|
||||||
tag2_font: String::new(),
|
tag2_font: String::new(),
|
||||||
quote_font_ratio: 230.0,
|
quote_font_ratio: 250.0,
|
||||||
subquote_font_ratio: 230.0,
|
subquote_font_ratio: 230.0,
|
||||||
subquote2_font_ratio: 230.0,
|
subquote2_font_ratio: 230.0,
|
||||||
tag_font_ratio: 150.0,
|
tag_font_ratio: 150.0,
|
||||||
|
|
@ -150,6 +151,7 @@ impl Default for ConfigFile {
|
||||||
tag2_position_ratio: 0.95,
|
tag2_position_ratio: 0.95,
|
||||||
image_ratio: (4.0, 5.0),
|
image_ratio: (4.0, 5.0),
|
||||||
color_layer: [20, 22, 25, 197],
|
color_layer: [20, 22, 25, 197],
|
||||||
|
image_format: "png".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
use fltk::{
|
use fltk::{
|
||||||
app,
|
app,
|
||||||
browser::{Browser, BrowserType},
|
browser::{Browser, BrowserType},
|
||||||
button::Button,
|
button::{Button, RadioRoundButton},
|
||||||
dialog::{self, FileDialogOptions, NativeFileChooser},
|
dialog::{self, FileDialogOptions, NativeFileChooser},
|
||||||
enums::{self, Align, Event, Font},
|
enums::{self, Align, Event, Font},
|
||||||
frame::Frame,
|
frame::Frame,
|
||||||
group::Flex,
|
group::{Flex, Scroll},
|
||||||
image::SvgImage,
|
image::SvgImage,
|
||||||
output::Output,
|
output::Output,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
|
@ -68,6 +68,8 @@ pub(crate) struct ConfigWindow {
|
||||||
pub(crate) translucent_layer_rgb: Button,
|
pub(crate) translucent_layer_rgb: Button,
|
||||||
/// opacity value of top translucent layer
|
/// opacity value of top translucent layer
|
||||||
pub(crate) translucent_layer_alpha: ValueInput,
|
pub(crate) translucent_layer_alpha: ValueInput,
|
||||||
|
pub(crate) png_format: RadioRoundButton,
|
||||||
|
pub(crate) jpeg_format: RadioRoundButton,
|
||||||
pub(crate) defaults_btn: Button,
|
pub(crate) defaults_btn: Button,
|
||||||
pub(crate) save_btn: Button,
|
pub(crate) save_btn: Button,
|
||||||
pub(crate) cancel_btn: Button,
|
pub(crate) cancel_btn: Button,
|
||||||
|
|
@ -78,12 +80,16 @@ pub(crate) struct ConfigWindow {
|
||||||
impl ConfigWindow {
|
impl ConfigWindow {
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
let configs = config::get_configs().unwrap_or(HashMap::new());
|
let configs = config::get_configs().unwrap_or(HashMap::new());
|
||||||
let mut win = Window::new(0, 0, 900, 680, "Config").center_screen();
|
let mut win = Window::new(0, 0, 900, 600, "Config").center_screen();
|
||||||
win.set_icon(Some(
|
win.set_icon(Some(
|
||||||
SvgImage::from_data(globals::ICON.to_str().unwrap()).unwrap(),
|
SvgImage::from_data(globals::ICON.to_str().unwrap()).unwrap(),
|
||||||
));
|
));
|
||||||
let mut row = Flex::default().with_size(890, 670).with_pos(5, 5).row();
|
|
||||||
let mut config_picker_flex = Flex::default().column();
|
// Config picking area
|
||||||
|
let mut config_picker_flex = Flex::default()
|
||||||
|
.with_size(200, win.height() - 50)
|
||||||
|
.with_pos(5, 5)
|
||||||
|
.column();
|
||||||
// Picker
|
// Picker
|
||||||
let browse = Browser::default().with_type(BrowserType::Hold);
|
let browse = Browser::default().with_type(BrowserType::Hold);
|
||||||
|
|
||||||
|
|
@ -103,9 +109,30 @@ impl ConfigWindow {
|
||||||
config_picker_flex.set_size(&panel_flex, 30);
|
config_picker_flex.set_size(&panel_flex, 30);
|
||||||
config_picker_flex.set_size(&bottom_padding_btn, 5);
|
config_picker_flex.set_size(&bottom_padding_btn, 5);
|
||||||
config_picker_flex.end();
|
config_picker_flex.end();
|
||||||
row.set_size(&config_picker_flex, 200);
|
|
||||||
|
|
||||||
let mut col = Flex::default().column();
|
// Bottom Panel
|
||||||
|
let mut panel_grp = Flex::default()
|
||||||
|
.with_size(win.width() - 10, 30)
|
||||||
|
.with_pos(5, win.height() - 40)
|
||||||
|
.row();
|
||||||
|
Frame::default();
|
||||||
|
let defaults_btn = Button::default().with_label("Defaults");
|
||||||
|
let save_btn = Button::default().with_label("Save");
|
||||||
|
let cancel_btn = Button::default().with_label("Cancel");
|
||||||
|
panel_grp.set_size(&defaults_btn, 100);
|
||||||
|
panel_grp.set_size(&save_btn, 100);
|
||||||
|
panel_grp.set_size(&cancel_btn, 100);
|
||||||
|
panel_grp.end();
|
||||||
|
|
||||||
|
// Rest everything
|
||||||
|
let mut scroll = Scroll::default()
|
||||||
|
.with_size(win.width() - 210, win.height() - 50)
|
||||||
|
.with_pos(205, 5);
|
||||||
|
|
||||||
|
let mut col = Flex::default()
|
||||||
|
.with_size(scroll.width() - 35, 700)
|
||||||
|
.column()
|
||||||
|
.with_pos(100, 0);
|
||||||
|
|
||||||
let mut label = Frame::default().with_label("Fonts:");
|
let mut label = Frame::default().with_label("Fonts:");
|
||||||
label.set_label_font(enums::Font::HelveticaBold);
|
label.set_label_font(enums::Font::HelveticaBold);
|
||||||
|
|
@ -358,7 +385,7 @@ impl ConfigWindow {
|
||||||
col.set_size(&hint, 20);
|
col.set_size(&hint, 20);
|
||||||
|
|
||||||
let mut translucent_layer_flex = Flex::default().row();
|
let mut translucent_layer_flex = Flex::default().row();
|
||||||
translucent_layer_flex.set_pad(2);
|
translucent_layer_flex.set_size(&Frame::default(), 20);
|
||||||
translucent_layer_flex.set_size(&Frame::default().with_label("Colour"), 50);
|
translucent_layer_flex.set_size(&Frame::default().with_label("Colour"), 50);
|
||||||
let mut translucent_layer_rgb = Button::default();
|
let mut translucent_layer_rgb = Button::default();
|
||||||
translucent_layer_rgb.set_frame(enums::FrameType::BorderBox);
|
translucent_layer_rgb.set_frame(enums::FrameType::BorderBox);
|
||||||
|
|
@ -368,25 +395,32 @@ impl ConfigWindow {
|
||||||
translucent_layer_flex.end();
|
translucent_layer_flex.end();
|
||||||
col.set_size(&translucent_layer_flex, 30);
|
col.set_size(&translucent_layer_flex, 30);
|
||||||
|
|
||||||
|
let mut label = Frame::default().with_label("Export Format:");
|
||||||
|
label.set_label_font(enums::Font::HelveticaBold);
|
||||||
|
col.set_size(&label, 15);
|
||||||
|
|
||||||
|
let mut hint = Frame::default().with_label("Image format to export image");
|
||||||
|
hint.set_label_font(Font::CourierItalic);
|
||||||
|
hint.set_label_size(12);
|
||||||
|
col.set_size(&hint, 20);
|
||||||
|
|
||||||
|
let mut image_format_flex = Flex::default().row();
|
||||||
|
image_format_flex.set_size(&Frame::default(), 20);
|
||||||
|
let mut png_format = RadioRoundButton::default().with_label("Png");
|
||||||
|
png_format.set_value(true);
|
||||||
|
let jpeg_format = RadioRoundButton::default().with_label("Jpeg");
|
||||||
|
image_format_flex.end();
|
||||||
|
col.set_size(&image_format_flex, 30);
|
||||||
|
|
||||||
Frame::default();
|
Frame::default();
|
||||||
|
|
||||||
let mut panel_grp = Flex::default().row();
|
|
||||||
Frame::default();
|
|
||||||
let defaults_btn = Button::default().with_label("Defaults");
|
|
||||||
let save_btn = Button::default().with_label("Save");
|
|
||||||
let cancel_btn = Button::default().with_label("Cancel");
|
|
||||||
panel_grp.set_size(&defaults_btn, 100);
|
|
||||||
panel_grp.set_size(&save_btn, 100);
|
|
||||||
panel_grp.set_size(&cancel_btn, 100);
|
|
||||||
panel_grp.end();
|
|
||||||
|
|
||||||
col.set_size(&panel_grp, 30);
|
|
||||||
|
|
||||||
col.end();
|
col.end();
|
||||||
row.end();
|
|
||||||
|
scroll.end();
|
||||||
|
scroll.make_resizable(true);
|
||||||
|
scroll.scroll_to(-1 * col.x() - 5, -1 * col.y() - 5);
|
||||||
|
|
||||||
win.end();
|
win.end();
|
||||||
win.make_modal(true);
|
win.make_modal(true);
|
||||||
win.make_resizable(true);
|
|
||||||
|
|
||||||
let mut config_window = Self {
|
let mut config_window = Self {
|
||||||
win,
|
win,
|
||||||
|
|
@ -418,6 +452,8 @@ impl ConfigWindow {
|
||||||
image_ratio_height,
|
image_ratio_height,
|
||||||
translucent_layer_rgb,
|
translucent_layer_rgb,
|
||||||
translucent_layer_alpha,
|
translucent_layer_alpha,
|
||||||
|
png_format,
|
||||||
|
jpeg_format,
|
||||||
defaults_btn,
|
defaults_btn,
|
||||||
save_btn,
|
save_btn,
|
||||||
cancel_btn,
|
cancel_btn,
|
||||||
|
|
@ -1006,6 +1042,30 @@ impl ConfigWindow {
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Png Image format
|
||||||
|
let browse = self.browse.clone();
|
||||||
|
let configs = Rc::clone(&self.configs);
|
||||||
|
self.png_format.set_callback(move |_| {
|
||||||
|
if let Some(conf) = configs
|
||||||
|
.borrow_mut()
|
||||||
|
.get_mut(&browse.selected_text().unwrap())
|
||||||
|
{
|
||||||
|
conf.image_format = "png".to_owned();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Jpeg Image format
|
||||||
|
let browse = self.browse.clone();
|
||||||
|
let configs = Rc::clone(&self.configs);
|
||||||
|
self.jpeg_format.set_callback(move |_| {
|
||||||
|
if let Some(conf) = configs
|
||||||
|
.borrow_mut()
|
||||||
|
.get_mut(&browse.selected_text().unwrap())
|
||||||
|
{
|
||||||
|
conf.image_format = "jpeg".to_owned();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Reset to default configuation button
|
// Reset to default configuation button
|
||||||
let mut quote_font = self.quote_font.clone();
|
let mut quote_font = self.quote_font.clone();
|
||||||
let mut subquote_font = self.subquote_font.clone();
|
let mut subquote_font = self.subquote_font.clone();
|
||||||
|
|
@ -1026,6 +1086,8 @@ impl ConfigWindow {
|
||||||
let mut image_ratio_height = self.image_ratio_height.clone();
|
let mut image_ratio_height = self.image_ratio_height.clone();
|
||||||
let mut layer_rgb = self.translucent_layer_rgb.clone();
|
let mut layer_rgb = self.translucent_layer_rgb.clone();
|
||||||
let mut layer_alpha = self.translucent_layer_alpha.clone();
|
let mut layer_alpha = self.translucent_layer_alpha.clone();
|
||||||
|
let mut png_format = self.png_format.clone();
|
||||||
|
let mut jpeg_format = self.jpeg_format.clone();
|
||||||
let configs = Rc::clone(&self.configs);
|
let configs = Rc::clone(&self.configs);
|
||||||
let browse = self.browse.clone();
|
let browse = self.browse.clone();
|
||||||
self.defaults_btn.set_callback(move |_| {
|
self.defaults_btn.set_callback(move |_| {
|
||||||
|
|
@ -1050,6 +1112,8 @@ impl ConfigWindow {
|
||||||
utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb);
|
utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb);
|
||||||
layer_rgb.redraw();
|
layer_rgb.redraw();
|
||||||
layer_alpha.set_value(conf.color_layer[3] as f64);
|
layer_alpha.set_value(conf.color_layer[3] as f64);
|
||||||
|
png_format.set_value(true);
|
||||||
|
jpeg_format.set_value(false);
|
||||||
configs
|
configs
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(browse.selected_text().unwrap(), conf);
|
.insert(browse.selected_text().unwrap(), conf);
|
||||||
|
|
|
||||||
39
src/utils.rs
39
src/utils.rs
|
|
@ -19,7 +19,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use fltk::{button::Button, dialog, enums, prelude::*};
|
use fltk::{button::Button, dialog, enums, prelude::*};
|
||||||
use image::{DynamicImage, GenericImageView, ImageBuffer};
|
use image::{DynamicImage, GenericImageView, ImageBuffer, ImageEncoder};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::globals;
|
use crate::globals;
|
||||||
|
|
@ -181,7 +181,7 @@ impl ImageContainer {
|
||||||
self.buffer = tmp;
|
self.buffer = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save image anf properities
|
/// Save image and properities
|
||||||
pub(crate) fn save(&self) {
|
pub(crate) fn save(&self) {
|
||||||
let prop = self.properties.read().unwrap();
|
let prop = self.properties.read().unwrap();
|
||||||
|
|
||||||
|
|
@ -190,9 +190,11 @@ impl ImageContainer {
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let path_properties = path_original.with_extension("prop");
|
let path_properties = path_original.with_extension("prop");
|
||||||
|
let config = globals::CONFIG.read().unwrap();
|
||||||
|
let export_format = config.image_format.as_str();
|
||||||
let export = path_original.parent().unwrap().join("export").join(
|
let export = path_original.parent().unwrap().join("export").join(
|
||||||
path_original
|
path_original
|
||||||
.with_extension("jpg")
|
.with_extension(export_format)
|
||||||
.file_name()
|
.file_name()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_str()
|
.to_str()
|
||||||
|
|
@ -245,12 +247,33 @@ impl ImageContainer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, 100);
|
match export_format {
|
||||||
encoder.set_pixel_density(image::codecs::jpeg::PixelDensity::dpi(300));
|
"png" => {
|
||||||
|
let encoder = image::codecs::png::PngEncoder::new_with_quality(
|
||||||
|
&mut output,
|
||||||
|
image::png::CompressionType::Default,
|
||||||
|
image::png::FilterType::NoFilter,
|
||||||
|
);
|
||||||
|
|
||||||
if let Err(e) = encoder.encode_image(&img) {
|
let (w, h) = img.dimensions();
|
||||||
dialog::alert_default("Failed to export Image!");
|
if let Err(e) =
|
||||||
warn!("Failed to export Image!\n{:?}", e);
|
encoder.write_image(&img.into_rgba8(), w, h, image::ColorType::Rgba8)
|
||||||
|
{
|
||||||
|
dialog::alert_default("Failed to export Image!");
|
||||||
|
warn!("Failed to export Image!\n{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"jpeg" => {
|
||||||
|
let mut encoder =
|
||||||
|
image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, 100);
|
||||||
|
encoder.set_pixel_density(image::codecs::jpeg::PixelDensity::dpi(300));
|
||||||
|
|
||||||
|
if let Err(e) = encoder.encode_image(&img) {
|
||||||
|
dialog::alert_default("Failed to export Image!");
|
||||||
|
warn!("Failed to export Image!\n{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue