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]]
name = "post_maker"
version = "0.2.6"
version = "0.3.0"
dependencies = [
"clap",
"dirs",

View File

@ -1,6 +1,6 @@
[package]
name = "post_maker"
version = "0.2.6"
version = "0.3.0"
edition = "2021"
description = "Post Maker helps you to make post for Instagram and other Social Media apps easily."
authors = ["PiyushXCoder <https://piyushxcoder.in>"]

View File

@ -128,6 +128,7 @@ pub(crate) struct ConfigFile {
pub(crate) tag2_position_ratio: f64,
pub(crate) image_ratio: (f64, f64),
pub(crate) color_layer: [u8; 4],
pub(crate) image_format: String,
}
impl Default for ConfigFile {
@ -138,7 +139,7 @@ impl Default for ConfigFile {
subquote2_font: String::new(),
tag_font: String::new(),
tag2_font: String::new(),
quote_font_ratio: 230.0,
quote_font_ratio: 250.0,
subquote_font_ratio: 230.0,
subquote2_font_ratio: 230.0,
tag_font_ratio: 150.0,
@ -150,6 +151,7 @@ impl Default for ConfigFile {
tag2_position_ratio: 0.95,
image_ratio: (4.0, 5.0),
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::{
app,
browser::{Browser, BrowserType},
button::Button,
button::{Button, RadioRoundButton},
dialog::{self, FileDialogOptions, NativeFileChooser},
enums::{self, Align, Event, Font},
frame::Frame,
group::Flex,
group::{Flex, Scroll},
image::SvgImage,
output::Output,
prelude::*,
@ -68,6 +68,8 @@ pub(crate) struct ConfigWindow {
pub(crate) translucent_layer_rgb: Button,
/// opacity value of top translucent layer
pub(crate) translucent_layer_alpha: ValueInput,
pub(crate) png_format: RadioRoundButton,
pub(crate) jpeg_format: RadioRoundButton,
pub(crate) defaults_btn: Button,
pub(crate) save_btn: Button,
pub(crate) cancel_btn: Button,
@ -78,12 +80,16 @@ pub(crate) struct ConfigWindow {
impl ConfigWindow {
pub(crate) fn new() -> Self {
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(
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
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(&bottom_padding_btn, 5);
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:");
label.set_label_font(enums::Font::HelveticaBold);
@ -358,7 +385,7 @@ impl ConfigWindow {
col.set_size(&hint, 20);
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);
let mut translucent_layer_rgb = Button::default();
translucent_layer_rgb.set_frame(enums::FrameType::BorderBox);
@ -368,25 +395,32 @@ impl ConfigWindow {
translucent_layer_flex.end();
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();
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();
row.end();
scroll.end();
scroll.make_resizable(true);
scroll.scroll_to(-1 * col.x() - 5, -1 * col.y() - 5);
win.end();
win.make_modal(true);
win.make_resizable(true);
let mut config_window = Self {
win,
@ -418,6 +452,8 @@ impl ConfigWindow {
image_ratio_height,
translucent_layer_rgb,
translucent_layer_alpha,
png_format,
jpeg_format,
defaults_btn,
save_btn,
cancel_btn,
@ -1006,6 +1042,30 @@ impl ConfigWindow {
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
let mut quote_font = self.quote_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 layer_rgb = self.translucent_layer_rgb.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 browse = self.browse.clone();
self.defaults_btn.set_callback(move |_| {
@ -1050,6 +1112,8 @@ impl ConfigWindow {
utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb);
layer_rgb.redraw();
layer_alpha.set_value(conf.color_layer[3] as f64);
png_format.set_value(true);
jpeg_format.set_value(false);
configs
.borrow_mut()
.insert(browse.selected_text().unwrap(), conf);

View File

@ -19,7 +19,7 @@ use std::{
};
use fltk::{button::Button, dialog, enums, prelude::*};
use image::{DynamicImage, GenericImageView, ImageBuffer};
use image::{DynamicImage, GenericImageView, ImageBuffer, ImageEncoder};
use serde::{Deserialize, Serialize};
use crate::globals;
@ -181,7 +181,7 @@ impl ImageContainer {
self.buffer = tmp;
}
/// Save image anf properities
/// Save image and properities
pub(crate) fn save(&self) {
let prop = self.properties.read().unwrap();
@ -190,9 +190,11 @@ impl ImageContainer {
None => return,
};
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(
path_original
.with_extension("jpg")
.with_extension(export_format)
.file_name()
.unwrap()
.to_str()
@ -245,12 +247,33 @@ impl ImageContainer {
}
};
let mut encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, 100);
encoder.set_pixel_density(image::codecs::jpeg::PixelDensity::dpi(300));
match export_format {
"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) {
dialog::alert_default("Failed to export Image!");
warn!("Failed to export Image!\n{:?}", e);
let (w, h) = img.dimensions();
if let Err(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);
}
}
_ => (),
}
}