diff options
Diffstat (limited to 'src/classes')
-rw-r--r-- | src/classes/texture2d.rs | 77 |
1 files changed, 63 insertions, 14 deletions
diff --git a/src/classes/texture2d.rs b/src/classes/texture2d.rs index 2bc1ade..e3f3225 100644 --- a/src/classes/texture2d.rs +++ b/src/classes/texture2d.rs @@ -1,7 +1,8 @@ use super::{FromValue, streaminginfo::StreamingInfo}; use crate::object::Value; use anyhow::{Result, bail}; -use image::{DynamicImage, Rgb, Rgba}; +use image::{DynamicImage, ImageBuffer, Luma, Rgb, Rgba}; +use log::info; use serde::Serialize; use std::mem::transmute; @@ -11,6 +12,7 @@ pub struct Texture2D { pub height: i32, pub mip_count: i32, pub name: String, + #[serde(skip)] pub image_data: Vec<u8>, pub format: TextureFormat, pub texture_dimension: i32, @@ -45,23 +47,70 @@ impl Texture2D { let w = self.width as usize; let h = self.height as usize; use TextureFormat::*; + let u32_rgba_buf_to_image = |buf: Vec<u32>| { + let buf = buf.into_iter().flat_map(u32::to_be_bytes).collect(); + let im = ImageBuffer::<Rgba<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf).unwrap(); + im.into() + }; match self.format { - DXT1 | DXT3 | DXT5 => { - use texpresso::Format::*; - let mut buf = vec![0u8; w * h * 4]; + Alpha8 => { + let buf = self.image_data.clone(); + let im = + ImageBuffer::<Luma<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf).unwrap(); + Ok(im.into()) + } + RGBAHalf => { + let buf = self + .image_data + .clone() + .into_iter() + .array_chunks::<2>() + .map(|x| u16::from_be_bytes(x)) + .map(|x| f16::from_bits(x) as f32) + .collect::<Vec<f32>>(); + Ok( + ImageBuffer::<Rgba<f32>, Vec<_>>::from_raw(w as u32, h as u32, buf) + .unwrap() + .into(), + ) + } + DXT1 | DXT3 | DXT5 | BC4 | BC5 => { + use texpresso::Format as F; let format = match self.format { - DXT1 => Bc1, - DXT3 => Bc2, - DXT5 => Bc3, + DXT1 => F::Bc1, + DXT3 => F::Bc2, + DXT5 => F::Bc3, + BC4 => F::Bc4, + BC5 => F::Bc5, _ => unreachable!(), }; + info!( + "decompressing {w}x{h} {:?} ({:?}) texture", + format, self.format + ); + let mut buf = vec![0u8; w * h * 4]; format.decompress(&self.image_data, w, h, &mut buf); - let im = image::ImageBuffer::<Rgba<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf) - .unwrap(); + let im = + ImageBuffer::<Rgba<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf).unwrap(); Ok(im.into()) } + DXT1Crunched | DXT5Crunched => { + let mut buf = vec![0u32; w * h]; + texture2ddecoder::decode_unity_crunch(&self.image_data, w, h, &mut buf).unwrap(); + Ok(u32_rgba_buf_to_image(buf)) + } + BC7 => { + let mut buf = vec![0u32; w * h]; + texture2ddecoder::decode_bc7(&self.image_data, w, h, &mut buf).unwrap(); + Ok(u32_rgba_buf_to_image(buf)) + } + BC6H => { + let mut buf = vec![0u32; w * h]; + texture2ddecoder::decode_bc6(&self.image_data, w, h, &mut buf, false).unwrap(); + Ok(u32_rgba_buf_to_image(buf)) + } RGB24 => { - let im = image::ImageBuffer::<Rgb<u8>, Vec<_>>::from_raw( + let im = ImageBuffer::<Rgb<u8>, Vec<_>>::from_raw( w as u32, h as u32, self.image_data.clone(), @@ -78,14 +127,14 @@ impl Texture2D { pix[2] = pix[3]; pix[3] = a; } - let im = image::ImageBuffer::<Rgba<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf) - .unwrap(); + let im = + ImageBuffer::<Rgba<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf).unwrap(); Ok(im.into()) } RGBA32 => { let buf = self.image_data.clone(); - let im = image::ImageBuffer::<Rgba<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf) - .unwrap(); + let im = + ImageBuffer::<Rgba<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf).unwrap(); Ok(im.into()) } x => bail!("texture format {x:?} not supported"), |