From 60f7e34d15c13f34c23a62be5c1707233e5dafb4 Mon Sep 17 00:00:00 2001 From: Jaby Date: Tue, 27 Sep 2022 20:52:44 +0200 Subject: [PATCH] Convert IndexedImages --- .../src/images/reduced_tim/color_clut.rs | 117 +++++++++++++++--- .../src/images/reduced_tim/color_full16.rs | 4 +- .../src/images/reduced_tim/mod.rs | 10 +- .../src/images/reduced_tim/types.rs | 30 ++++- src/Tools/tool_helper/src/bits.rs | 1 + 5 files changed, 138 insertions(+), 24 deletions(-) diff --git a/src/Tools/jaby_engine_fconv/src/images/reduced_tim/color_clut.rs b/src/Tools/jaby_engine_fconv/src/images/reduced_tim/color_clut.rs index 95536848..1f7debb7 100644 --- a/src/Tools/jaby_engine_fconv/src/images/reduced_tim/color_clut.rs +++ b/src/Tools/jaby_engine_fconv/src/images/reduced_tim/color_clut.rs @@ -1,16 +1,21 @@ use tool_helper::Error; -use super::types::Color; +use super::types::{Color, PSXImageConverter}; pub enum OutputType { - TwoIndex, + FourBit, + EightBit, +} + +enum IndexPerByte { OneIndex, + TwoIndices, } pub struct IndexedImage { palette: Vec, - data: Vec, - bit_depth: png::BitDepth, - output_type: OutputType, + raw_data: std::vec::IntoIter, + index_byte: IndexPerByte, + next_func: fn(&mut Self) -> Option, width: u16, height: u16, } @@ -24,19 +29,27 @@ impl IndexedImage { Ok(info) => { let width = info.width as u16; let height = info.height as u16; - let bit_depth = info.bit_depth; + let index_byte = { + match info.bit_depth { + png::BitDepth::Four => IndexPerByte::TwoIndices, + png::BitDepth::Eight => IndexPerByte::OneIndex, + _ => { + return Err(Error::from_str("Only 4 and 8bit color depth are supported").with_action(action_name)); + } + } + }; if info.color_type != png::ColorType::Indexed { return Err(Error::from_str("PNG file must be indexed").with_action(action_name)); } - if bit_depth != png::BitDepth::Four && bit_depth != png::BitDepth::Eight { - Err(Error::from_str("Only 4 and 8bit color depth are supported").with_action(action_name)) - } - else { - - Ok(IndexedImage{palette: Self::make_palette(), data: buffer, bit_depth, output_type, width, height}) + Ok(IndexedImage{palette: Self::make_palette(reader.info()), raw_data: buffer.into_iter(), index_byte, next_func: { + match output_type { + OutputType::FourBit => Self::next_four_bit, + OutputType::EightBit => Self::next_eight_bit, + } + }, width, height}) } } @@ -46,7 +59,83 @@ impl IndexedImage { } } - fn make_palette() -> Vec { - Vec::new() + fn make_palette(png_info: &png::Info) -> Vec { + fn make_color(iter: &mut dyn std::iter::Iterator) -> Option { + let r = iter.next()?; + let g = iter.next()?; + let b = iter.next()?; + + Some(Color::non_transparent(*r, *g, *b)) + } + + let mut new_palette = Vec::new(); + + if let Some(palette) = &png_info.palette { + let mut iter = palette.iter(); + + while let Some(color) = make_color(&mut iter) { + new_palette.push(color); + } + } + new_palette + } + + fn split_into_two_indices(index: u8) -> (u8, u8) { + (index >> 4, index & 0xF) + } + + fn next_four_bit(&mut self) -> Option { + let (pixel0, pixel1, pixel2, pixel3) = { + match self.index_byte { + IndexPerByte::OneIndex => { + (self.raw_data.next()?, self.raw_data.next()?, self.raw_data.next()?, self.raw_data.next()?) + } + IndexPerByte::TwoIndices => { + let (pixel0, pixel1) = Self::split_into_two_indices(self.raw_data.next()?); + let (pixel2, pixel3) = Self::split_into_two_indices(self.raw_data.next()?); + + (pixel0, pixel1, pixel2, pixel3) + }, + } + }; + + Some(Color::new_4bit_entry(pixel0, pixel1, pixel2, pixel3)) + } + + fn next_eight_bit(&mut self) -> Option { + let (pixel0, pixel1) = { + match self.index_byte { + IndexPerByte::OneIndex => { + (self.raw_data.next()?, self.raw_data.next()?) + }, + IndexPerByte::TwoIndices => { + Self::split_into_two_indices(self.raw_data.next()?) + } + } + }; + + Some(Color::new_8bit_entry(pixel0, pixel1)) + } +} + +impl PSXImageConverter for IndexedImage { + fn width(&self) -> u16 { + self.width + } + + fn height(&self) -> u16 { + self.height + } + + fn get_palette(&self) -> Option<&Vec> { + Some(&self.palette) + } +} + +impl std::iter::Iterator for IndexedImage { + type Item = Color; + + fn next(&mut self) -> Option { + (self.next_func)(self) } } \ No newline at end of file diff --git a/src/Tools/jaby_engine_fconv/src/images/reduced_tim/color_full16.rs b/src/Tools/jaby_engine_fconv/src/images/reduced_tim/color_full16.rs index 96b375a2..c5539fda 100644 --- a/src/Tools/jaby_engine_fconv/src/images/reduced_tim/color_full16.rs +++ b/src/Tools/jaby_engine_fconv/src/images/reduced_tim/color_full16.rs @@ -25,7 +25,7 @@ impl PSXImageConverter for RgbImage { self.height } - fn get_palette(&self) -> Option> { + fn get_palette(&self) -> Option<&Vec> { None } } @@ -67,7 +67,7 @@ impl PSXImageConverter for RgbaImage { self.height } - fn get_palette(&self) -> Option> { + fn get_palette(&self) -> Option<&Vec> { None } } diff --git a/src/Tools/jaby_engine_fconv/src/images/reduced_tim/mod.rs b/src/Tools/jaby_engine_fconv/src/images/reduced_tim/mod.rs index e3087994..52db9fd6 100644 --- a/src/Tools/jaby_engine_fconv/src/images/reduced_tim/mod.rs +++ b/src/Tools/jaby_engine_fconv/src/images/reduced_tim/mod.rs @@ -77,19 +77,17 @@ fn convert_full16(input: Input, output: Output) -> Result<(), Error> { } } -fn convert_palette_based(input: Input, _: Output, color_type: ColorType) -> Result<(), Error> { +fn convert_palette_based(input: Input, output: Output, color_type: ColorType) -> Result<(), Error> { match png::Decoder::new(input).read_info() { Ok(reader) => { let output_type = { match color_type { - ColorType::Clut4 => color_clut::OutputType::TwoIndex, - ColorType::Clut8 => color_clut::OutputType::OneIndex, + ColorType::Clut4 => color_clut::OutputType::FourBit, + ColorType::Clut8 => color_clut::OutputType::EightBit, _ => return Err(Error::from_str("ColorType not supported")) } }; - let _image = IndexedImage::new(reader, output_type)?; - - Err(Error::from_str("Under construction")) + encode(IndexedImage::new(reader, output_type)?, ClutAlignment::None, output) }, Err(error) => Err(Error::from_error(error)) } diff --git a/src/Tools/jaby_engine_fconv/src/images/reduced_tim/types.rs b/src/Tools/jaby_engine_fconv/src/images/reduced_tim/types.rs index c0f77afa..5da937e0 100644 --- a/src/Tools/jaby_engine_fconv/src/images/reduced_tim/types.rs +++ b/src/Tools/jaby_engine_fconv/src/images/reduced_tim/types.rs @@ -40,7 +40,15 @@ impl Color { const STP_BIT_RANGE: BitRange = BitRange::from_to(15, 15); const RED_BIT_RANGE: BitRange = BitRange::from_to(0, 4); const GREEN_BIT_RANGE: BitRange = BitRange::from_to(5, 9); - const BLUE_BIT_RANGE: BitRange = BitRange::from_to(10, 14); + const BLUE_BIT_RANGE: BitRange = BitRange::from_to(10, 14); + + const PIXEL3_4_BIT_RANGE: BitRange = BitRange::from_to(12, 15); + const PIXEL2_4_BIT_RANGE: BitRange = BitRange::from_to(8, 11); + const PIXEL1_4_BIT_RANGE: BitRange = BitRange::from_to(4, 7); + const PIXEL0_4_BIT_RANGE: BitRange = BitRange::from_to(0, 3); + + const PIXEL1_8_BIT_RANGE: BitRange = BitRange::from_to(8, 15); + const PIXEL0_8_BIT_RANGE: BitRange = BitRange::from_to(0, 7); pub const fn transparent() -> Color { Color::new(0, 0, 0, 0) @@ -76,6 +84,24 @@ impl Color { Color::new(1, 0, 0, 0) } + pub const fn new_4bit_entry(pixel0_4: u8, pixel1_4: u8, pixel2_4: u8, pixel3_4: u8) -> Color { + let value = set_member_value!(set_member_value!(set_member_value!(set_member_value!(0, + pixel0_4, 0, u16), + pixel1_4, 0, u16), + pixel2_4, 0, u16), + pixel3_4, 0, u16); + + Color{value} + } + + pub const fn new_8bit_entry(pixel0_8: u8, pixel1_8: u8) -> Color { + let value = set_member_value!(set_member_value!(0, + pixel0_8, 0, u16), + pixel1_8, 0, u16); + + Color{value} + } + const fn new(stp: u8, red: u8, green: u8, blue: u8) -> Color { let value = set_member_value!(set_member_value!(set_member_value!(set_member_value!(0, stp, 0, u16), @@ -120,5 +146,5 @@ pub trait PSXImageConverter: std::iter::Iterator { fn width(&self) -> u16; fn height(&self) -> u16; - fn get_palette(&self) -> Option>; + fn get_palette(&self) -> Option<&Vec>; } \ No newline at end of file diff --git a/src/Tools/tool_helper/src/bits.rs b/src/Tools/tool_helper/src/bits.rs index 47665de7..ec926ce7 100644 --- a/src/Tools/tool_helper/src/bits.rs +++ b/src/Tools/tool_helper/src/bits.rs @@ -31,5 +31,6 @@ macro_rules! create_bit_functions { }; } +create_bit_functions!(u8); create_bit_functions!(u16); create_bit_functions!(u32); \ No newline at end of file