diff --git a/src/Tools/tim_tool/src/gui/file_tab.rs b/src/Tools/tim_tool/src/gui/file_tab.rs index 649b287d..df6461da 100644 --- a/src/Tools/tim_tool/src/gui/file_tab.rs +++ b/src/Tools/tim_tool/src/gui/file_tab.rs @@ -2,6 +2,7 @@ use crate::MainWindow; use super::{GUIElements, GUIElementsRef, MainWindowRef, display_error}; use slint::{Image, SharedString}; use std::rc::Rc; +use tim_tool::logic::tim::Encoding; use tool_helper::Error; pub struct FileTab { @@ -10,6 +11,10 @@ pub struct FileTab { } impl FileTab { + const FOUR_BIT_NAME:&str = "4 bit"; + const EIGHT_BIT_NAME:&str = "8 bit"; + const FULL_COLOR_NAME:&str = "Full color"; + fn update_encoding_options(&self, width: u32, height: u32, has_palette: bool) -> Result<(), Error> { self.encoding_options.clear(); @@ -22,17 +27,17 @@ impl FileTab { } if has_4bit { - self.encoding_options.push(SharedString::from(format!("4 bit ({}/{})", width/4, height))); + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::FOUR_BIT_NAME, width/4, height))); } if has_8bit { - self.encoding_options.push(SharedString::from(format!("8 bit ({}/{})", width/2, height))); + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::EIGHT_BIT_NAME, width/2, height))); } Ok(()) } else { - self.encoding_options.push(SharedString::from(format!("16 bit ({}/{})", width, height))); + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::FULL_COLOR_NAME, width, height))); Ok(()) } } @@ -102,6 +107,26 @@ impl FileTab { self.main_window.borrow().get_file_tab_image_name().to_string() } + pub fn get_encoding(&self) -> Result { + let selected_encoding = self.main_window.borrow().get_file_tab_selected_encoding(); + + if selected_encoding.starts_with(Self::FOUR_BIT_NAME) { + Ok(Encoding::FourBit) + } + + else if selected_encoding.starts_with(Self::EIGHT_BIT_NAME) { + Ok(Encoding::EightBit) + } + + else if selected_encoding.starts_with(Self::FULL_COLOR_NAME) { + Ok(Encoding::FullColor) + } + + else { + Err(Error::from_str("Failed to obtain encoding")) + } + } + pub fn on_browse_file(&self, gui_elements: GUIElementsRef, mut function: impl FnMut(&mut GUIElements, &MainWindow) -> Result<(), Error> + 'static) { let main_window_cloned = self.main_window.clone(); let gui_cloned = gui_elements.clone(); diff --git a/src/Tools/tim_tool/src/logic/mod.rs b/src/Tools/tim_tool/src/logic/mod.rs index fd5fc7b3..71fbe9fc 100644 --- a/src/Tools/tim_tool/src/logic/mod.rs +++ b/src/Tools/tim_tool/src/logic/mod.rs @@ -2,7 +2,7 @@ pub mod tim; use std::path::PathBuf; use slint::Image; -use tim::TIMInfo; +use tim::{Encoding, TIMInfo}; use tool_helper::Error; pub struct Logic { @@ -16,18 +16,18 @@ impl Logic { pub fn set_unadded_tim(&mut self, path: &PathBuf) -> Result<(Image, Option), Error> { let tim_info = TIMInfo::from_image(path)?; - let image = tim_info.get_slint_images(); + let image = tim_info.get_slint_images(Encoding::FullColor); self.unadded_tim = Some(tim_info); Ok(image) } - pub fn add_unadded_tim_as(&mut self, _name: &String) -> Result<(Image, Option), Error> { + pub fn add_unadded_tim_as(&mut self, _name: &String, encoding: Encoding) -> Result<(Image, Option), Error> { if let Some(unadded_tim) = &self.unadded_tim { - let image = unadded_tim.get_slint_images(); + let (image, palette) = unadded_tim.get_slint_images(encoding); self.unadded_tim = None; - Ok(image) + Ok((image, palette)) } else { diff --git a/src/Tools/tim_tool/src/logic/tim.rs b/src/Tools/tim_tool/src/logic/tim.rs index 15a1f6b0..7cdf8d3b 100644 --- a/src/Tools/tim_tool/src/logic/tim.rs +++ b/src/Tools/tim_tool/src/logic/tim.rs @@ -2,6 +2,12 @@ use std::{fs::File, path::PathBuf}; use slint::{Rgba8Pixel, SharedPixelBuffer}; use tool_helper::Error; +pub enum Encoding { + FourBit, + EightBit, + FullColor, +} + pub struct TIMInfo { image_data: SharedPixelBuffer, palette: Option, @@ -86,8 +92,28 @@ impl TIMInfo { } } - pub fn get_slint_images(&self) -> (slint::Image, Option) { - (slint::Image::from_rgba8_premultiplied(self.image_data.clone()), if let Some(palette) = &self.palette { + pub fn get_slint_images(&self, encoding: Encoding) -> (slint::Image, Option) { + fn scaled_copy(src: &SharedPixelBuffer, factor: u32) -> SharedPixelBuffer { + let mut image_data = SharedPixelBuffer::::new(src.width()/factor, src.height()); + let mut dst_pixel = image_data.make_mut_slice(); + let src_pixel = src.as_slice(); + + for (idx, pixel) in src_pixel.into_iter().enumerate() { + if idx%factor as usize == 0 { + dst_pixel[0] = *pixel; + dst_pixel = &mut dst_pixel[1..]; + } + } + image_data + } + + let image_data = match encoding { + Encoding::FourBit => scaled_copy(&self.image_data, 4), + Encoding::EightBit => scaled_copy(&self.image_data, 2), + Encoding::FullColor => self.image_data.clone() + }; + + (slint::Image::from_rgba8_premultiplied(image_data), if let Some(palette) = &self.palette { Some(palette.get_image()) } else { None diff --git a/src/Tools/tim_tool/src/main.rs b/src/Tools/tim_tool/src/main.rs index 51155b7b..da21920a 100644 --- a/src/Tools/tim_tool/src/main.rs +++ b/src/Tools/tim_tool/src/main.rs @@ -84,7 +84,8 @@ fn setup_file_tab(gui_elements_ref: Rc>, logic_ref: Rc file_tab.conv-palette_width; in-out property file_tab-palette_height <=> file_tab.conv-palette_height; in-out property file_tab-palette_visible <=> file_tab.conv-palette_enable; + in-out property file_tab-selected_encoding <=> file_tab.conv-selected_encoding; in-out property file_tab-image_name <=> file_tab.conv-image_name; in-out property file_tab-enable <=> file_tab.conv-enable_view; callback file_tab-update_palette_size <=> file_tab.conv-image_update_palette_size; diff --git a/src/Tools/tim_tool/ui/tab/file-tab.slint b/src/Tools/tim_tool/ui/tab/file-tab.slint index f7a5c20c..2c2c7442 100644 --- a/src/Tools/tim_tool/ui/tab/file-tab.slint +++ b/src/Tools/tim_tool/ui/tab/file-tab.slint @@ -19,10 +19,11 @@ component ConvertImageWidget inherits Rectangle { in-out property image-width; in-out property image-height; in-out property palette_data; - in-out property palette_width: 0; - in-out property palette_height: 0; - in-out property enable_view: false; - in-out property palette_visible: false; + in-out property palette_width: 0; + in-out property palette_height: 0; + in-out property selected_encoding; + in-out property enable_view: false; + in-out property palette_visible: false; callback browse_clicked(); callback add_clicked(); @@ -92,8 +93,13 @@ component ConvertImageWidget inherits Rectangle { VerticalLayout { alignment: center; ComboBox { - model: root.encoding_options; - enabled: root.enable_view; + model: root.encoding_options; + enabled: root.enable_view; + current-value: root.encoding_options[0]; + + selected(current-value) => { + root.selected_encoding = current-value; + } } } } @@ -205,6 +211,7 @@ export component FileTab inherits Rectangle { in-out property conv-palette_data; in-out property conv-palette_width; in-out property conv-palette_height; + in-out property conv-selected_encoding; in-out property conv-palette_enable; in-out property conv-enable_view; @@ -244,17 +251,18 @@ export component FileTab inherits Rectangle { } if root.state == State.ConvertImage : ConvertImageWidget { - encoding_options <=> root.conv-encoding_options; - image_path <=> root.conv-image_path; - image_data <=> root.conv-image_data; - image-width <=> root.conv-image_width; - image-height <=> root.conv-image_height; - palette_data <=> root.conv-palette_data; - palette_width <=> root.conv-palette_width; - palette_height <=> root.conv-palette_height; - palette_visible <=> root.conv-palette_enable; - image_name <=> root.conv-image_name; - enable_view <=> root.conv-enable_view; + encoding_options <=> root.conv-encoding_options; + image_path <=> root.conv-image_path; + image_data <=> root.conv-image_data; + image-width <=> root.conv-image_width; + image-height <=> root.conv-image_height; + palette_data <=> root.conv-palette_data; + palette_width <=> root.conv-palette_width; + palette_height <=> root.conv-palette_height; + palette_visible <=> root.conv-palette_enable; + selected_encoding <=> root.conv-selected_encoding; + image_name <=> root.conv-image_name; + enable_view <=> root.conv-enable_view; update_palette_size(width, height) => { root.conv-image_update_palette_size(width, height);