Image export formats

This commit is contained in:
Piyush मिश्रः 2022-03-05 00:18:57 +05:30
parent 7f67d5ad29
commit 3d9b20bbc8
5 changed files with 123 additions and 34 deletions

2
Cargo.lock generated
View File

@ -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",

View File

@ -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>"]

View File

@ -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(),
} }
} }
} }

View File

@ -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);

View File

@ -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);
}
}
_ => (),
} }
} }