Load indexed png
This commit is contained in:
parent
6fa574c921
commit
4f0103e8fa
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
png = "0.17.16"
|
||||
rfd = "0.15.2"
|
||||
slint = "1.9.2"
|
||||
tiny-skia = "0.11.4"
|
||||
|
|
|
@ -40,6 +40,6 @@ impl UnaddedTIM {
|
|||
}
|
||||
|
||||
fn empty() -> UnaddedTIM {
|
||||
UnaddedTIM{info: TIMInfo{}, image: Image::default()}
|
||||
UnaddedTIM{info: TIMInfo::default(), image: Image::default()}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,63 @@
|
|||
use std::path::PathBuf;
|
||||
use std::{default, fmt::format, fs::File, path::PathBuf};
|
||||
use slint::{Rgba8Pixel, SharedPixelBuffer};
|
||||
use tool_helper::Error;
|
||||
|
||||
pub struct TIMInfo {}
|
||||
pub struct TIMInfo {
|
||||
image_data: SharedPixelBuffer<Rgba8Pixel>,
|
||||
palette: Option<Vec<Rgba8Pixel>>,
|
||||
}
|
||||
|
||||
impl std::default::Default for TIMInfo {
|
||||
fn default() -> Self {
|
||||
TIMInfo{}
|
||||
TIMInfo{image_data: SharedPixelBuffer::new(1, 1), palette: None}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_image(path: PathBuf) -> Result<(slint::Image, TIMInfo), Error> {
|
||||
Ok((slint::Image::load_from_path(&path).or_else(|_| {Err(Error::from_str("Failed loading image"))})?, TIMInfo{}))
|
||||
pub fn load_image(path: &PathBuf) -> Result<(slint::Image, TIMInfo), Error> {
|
||||
fn make_color(iter: &mut dyn std::iter::Iterator<Item = &u8>) -> Option<Rgba8Pixel> {
|
||||
Some(Rgba8Pixel::new(
|
||||
*iter.next()?, *iter.next()?, *iter.next()?,
|
||||
0xFF))
|
||||
}
|
||||
|
||||
let mut reader = png::Decoder::new(File::open(path)?).read_info().or_else(|error| {Err(Error::from_error(error))})?;
|
||||
let info = reader.info().clone();
|
||||
|
||||
let mut buffer = vec![0; reader.output_buffer_size()];
|
||||
let frame_info = reader.next_frame(&mut buffer).or_else(|error| {Err(Error::from_error(error))})?;
|
||||
let bit_depth = frame_info.bit_depth;
|
||||
let mut image_data = SharedPixelBuffer::new(frame_info.width, frame_info.height);
|
||||
|
||||
if info.color_type == png::ColorType::Indexed {
|
||||
let palette = info.palette.ok_or(Error::from_str("Found indexed PNG without palette"))?;
|
||||
let mut palette_colors = Vec::new();
|
||||
let mut iter = palette.iter();
|
||||
|
||||
while let Some(color) = make_color(&mut iter) {
|
||||
palette_colors.push(color);
|
||||
}
|
||||
|
||||
let mut dst_pixels = image_data.make_mut_slice();
|
||||
for byte in buffer.into_iter() {
|
||||
match bit_depth {
|
||||
png::BitDepth::Four => {
|
||||
dst_pixels[0] = palette_colors[(byte >> 4) as usize];
|
||||
dst_pixels[1] = palette_colors[(byte & 0xF) as usize];
|
||||
dst_pixels = &mut dst_pixels[2..];
|
||||
},
|
||||
png::BitDepth::Eight => {
|
||||
dst_pixels[0] = palette_colors[byte as usize];
|
||||
dst_pixels = &mut dst_pixels[1..];
|
||||
},
|
||||
_ => {return Err(Error::from_str("Only 4 and 8bit color depth are supported"));}
|
||||
}
|
||||
}
|
||||
|
||||
let image = slint::Image::from_rgba8_premultiplied(image_data.clone());
|
||||
Ok((image, TIMInfo{image_data, palette: Some(palette_colors)}))
|
||||
}
|
||||
|
||||
else {
|
||||
Err(Error::not_implemented("Support for non indexed images"))
|
||||
}
|
||||
}
|
|
@ -47,8 +47,8 @@ fn setup_file_tab(gui_elements_ref: Rc<RefCell<GUIElements>>, logic_ref: Rc<RefC
|
|||
}
|
||||
|
||||
let file = FileDialog::new()
|
||||
.add_filter("Images (.png; .bmp; .jpeg)", &["png", "bmp", "jpeg"])
|
||||
.set_title("Select image file")
|
||||
.add_filter("PNG image (.png)", &["png"])
|
||||
.set_title("PNG image file")
|
||||
.pick_file();
|
||||
|
||||
if let Some(file) = file {
|
||||
|
@ -59,7 +59,7 @@ fn setup_file_tab(gui_elements_ref: Rc<RefCell<GUIElements>>, logic_ref: Rc<RefC
|
|||
let file_tab = &gui_elements.file_tab;
|
||||
let file_name = if let Some(name) = file.file_name() {Some(name.to_string_lossy().to_string())} else {None};
|
||||
|
||||
let (image, info) = match load_image(file) {
|
||||
let (image, info) = match load_image(&file) {
|
||||
Ok((image, info)) => (image, info),
|
||||
Err(error) => {
|
||||
file_tab.clear_load();
|
||||
|
|
Loading…
Reference in New Issue