Implement convert functions for RGB(A)

This commit is contained in:
2022-09-22 21:18:01 +02:00
parent a52207061f
commit 8a88eae02a
4 changed files with 99 additions and 33 deletions

View File

@@ -1,53 +1,95 @@
use super::types::{Header, PSXImageConverter};
use super::types::{Color, Header, PSXImageConverter};
use tool_helper::{Error, Output};
pub struct RgbImage {
image: image::RgbImage
raw_data: std::vec::IntoIter<u8>,
width: u16,
height: u16,
}
impl RgbImage {
pub fn new(image: image::RgbImage) -> RgbImage {
RgbImage{image}
let width = image.width() as u16;
let height = image.height() as u16;
let raw_data = image.into_raw().into_iter();
RgbImage{raw_data, width, height}
}
}
impl PSXImageConverter for RgbImage {
fn width(&self) -> u32 {
image::RgbImage::width(&self.image)
fn width(&self) -> u16 {
self.width
}
fn height(&self) -> u32 {
image::RgbImage::height(&self.image)
fn height(&self) -> u16 {
self.height
}
}
impl std::iter::Iterator for RgbImage {
type Item = Color;
fn next(&mut self) -> Option<Self::Item> {
let r = self.raw_data.next()?;
let g = self.raw_data.next()?;
let b = self.raw_data.next()?;
Some(Color::non_transparent(r, g, b))
}
}
pub struct RgbaImage {
image: image::RgbaImage
raw_data: std::vec::IntoIter<u8>,
width: u16,
height: u16,
}
impl RgbaImage {
pub fn new(image: image::RgbaImage) -> RgbaImage {
RgbaImage{image}
let width = image.width() as u16;
let height = image.height() as u16;
let raw_data = image.into_raw().into_iter();
RgbaImage{raw_data, width, height}
}
}
impl PSXImageConverter for RgbaImage {
fn width(&self) -> u32 {
image::RgbaImage::width(&self.image)
fn width(&self) -> u16 {
self.width
}
fn height(&self) -> u32 {
image::RgbaImage::height(&self.image)
fn height(&self) -> u16 {
self.height
}
}
impl std::iter::Iterator for RgbaImage {
type Item = Color;
fn next(&mut self) -> Option<Self::Item> {
let r = self.raw_data.next()?;
let g = self.raw_data.next()?;
let b = self.raw_data.next()?;
let a = self.raw_data.next()?;
Some(
match a {
0x0 => Color::transparent(),
0xFF => Color::non_transparent(r, g, b),
_ => Color::semi_transparent(r, g, b),
}
)
}
}
pub fn encode<T: PSXImageConverter>(image: T, _: Output) -> Result<(), Error> {
let width = image.width();
let height = image.height();
let _header = Header::encode(width, height, 0, 0).ok_or(Error::from_callback(|| {format!("Image size {}, {} needs to be even", width, height)}));
if !Header::can_encode(width, height) {
return Err(Error::from_text(format!("Image size {}, {} needs to be even", width, height)));
}
for _ in image {}
Ok(())
}

View File

@@ -47,10 +47,28 @@ impl Color {
}
pub const fn non_transparent(red: u8, green: u8, blue: u8) -> Color {
Color::new(0, red, green, blue)
if red == 0 && green == 0 && blue == 0 {
Color::black()
}
else {
Color::new(0, red, green, blue)
}
}
pub const fn semi_transparent(red: u8, green: u8, blue: u8) -> Color {
pub const fn semi_transparent(mut red: u8, mut green: u8, mut blue: u8) -> Color {
if red == 0 {
red = 1;
}
if green == 0 {
green = 1;
}
if blue == 0 {
blue = 1;
}
Color::new(1, red, green, blue)
}
@@ -81,22 +99,24 @@ impl Header {
const CLUT_WIDTH_BIT_RANGE: BitRange = BitRange::from_to(17, 22);
const CLUT_HEIGHT_BIT_RANGE: BitRange = BitRange::from_to(23, 31);
pub fn new(tex_width: u16, tex_height: u16, clut_width: u16, clut_height: u16) -> Header {
let value = set_member_value!(set_member_value!(set_member_value!(set_member_value!(0,
tex_width, 1, u32),
tex_height, 1, u32),
clut_width, 4, u32),
clut_height, 0, u32);
pub fn encode(tex_width: u16, tex_height: u16, clut_width: u16, clut_height: u16) -> Option<Header> {
if tex_width & 1 == 1 || tex_height & 1 == 1 {
None
}
Header{value}
}
else {
let value = set_member_value!(set_member_value!(set_member_value!(set_member_value!(0,
tex_width, 1, u32),
tex_height, 1, u32),
clut_width, 4, u32),
clut_height, 0, u32);
pub fn can_encode(width: u32, height: u32) -> bool {
width & 1 == 0 && height & 1 == 0
Some(Header{value})
}
}
}
pub trait PSXImageConverter {
fn width(&self) -> u32;
fn height(&self) -> u32;
pub trait PSXImageConverter: std::iter::Iterator<Item = Color> {
fn width(&self) -> u16;
fn height(&self) -> u16;
}