diff options
author | metamuffin <metamuffin@disroot.org> | 2025-03-12 00:26:35 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-03-12 00:26:35 +0100 |
commit | bed5904c0575a96d52f6e7fc3df95d3b772ef196 (patch) | |
tree | ee36a53d2ab24de3e363890adfd80e374b0911b0 /src/classes/texture2d.rs | |
parent | 79e341769d04a6daa5c1edae87d6ff8a9adba9c6 (diff) | |
download | unity-tools-bed5904c0575a96d52f6e7fc3df95d3b772ef196.tar unity-tools-bed5904c0575a96d52f6e7fc3df95d3b772ef196.tar.bz2 unity-tools-bed5904c0575a96d52f6e7fc3df95d3b772ef196.tar.zst |
texture formats
Diffstat (limited to 'src/classes/texture2d.rs')
-rw-r--r-- | src/classes/texture2d.rs | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/classes/texture2d.rs b/src/classes/texture2d.rs new file mode 100644 index 0000000..372aee7 --- /dev/null +++ b/src/classes/texture2d.rs @@ -0,0 +1,156 @@ +use super::FromValue; +use crate::object::Value; +use anyhow::{Result, bail}; +use image::{DynamicImage, Rgb, Rgba}; +use serde::Serialize; +use std::mem::transmute; + +#[derive(Debug, Serialize)] +pub struct Texture2d { + pub width: i32, + pub height: i32, + pub mip_count: i32, + pub name: String, + pub image_data: Vec<u8>, + pub texture_format: TextureFormat, + pub texture_dimension: i32, +} + +impl FromValue for Texture2d { + fn from_value(v: Value) -> Result<Self> { + let mut fields = v.as_class("Texture2D").unwrap(); + Ok(Texture2d { + width: fields.remove("m_Width").unwrap().as_i32().unwrap(), + height: fields.remove("m_Height").unwrap().as_i32().unwrap(), + mip_count: fields.remove("m_MipCount").unwrap().as_i32().unwrap(), + texture_dimension: fields + .remove("m_TextureDimension") + .unwrap() + .as_i32() + .unwrap(), + texture_format: unsafe { + transmute::<_, TextureFormat>( + fields.remove("m_TextureFormat").unwrap().as_i32().unwrap(), + ) + }, + name: fields.remove("m_Name").unwrap().as_string().unwrap(), + image_data: fields.remove("image data").unwrap().as_typeless().unwrap(), + }) + } +} +impl Texture2d { + pub fn to_image(&self) -> Result<DynamicImage> { + let w = self.width as usize; + let h = self.height as usize; + use TextureFormat::*; + match self.texture_format { + DXT5 => { + let mut buf = vec![0u8; w * h * 4]; + texpresso::Format::Bc3.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(); + Ok(im.into()) + } + RGB24 => { + let im = image::ImageBuffer::<Rgb<u8>, Vec<_>>::from_raw( + w as u32, + h as u32, + self.image_data.clone(), + ) + .unwrap(); + Ok(im.into()) + } + ARGB32 => { + let mut buf = self.image_data.clone(); + for pix in buf.array_chunks_mut::<4>() { + let a = pix[0]; + pix[0] = pix[1]; + pix[1] = pix[2]; + pix[2] = pix[3]; + pix[3] = a; + } + let im = image::ImageBuffer::<Rgba<u8>, Vec<_>>::from_raw(w as u32, h as u32, buf) + .unwrap(); + Ok(im.into()) + } + x => bail!("texture format {x:?} not supported"), + } + } +} + +#[allow(non_camel_case_types)] +#[repr(i32)] +#[derive(Debug, Serialize, PartialEq, Clone, Copy)] +pub enum TextureFormat { + Alpha8 = 1, + ARGB4444, + RGB24, + RGBA32, + ARGB32, + ARGBFloat, + RGB565, + BGR24, + R16, + DXT1, // Bc1 + DXT3, // Bc2 + DXT5, // Bc3 + RGBA4444, + BGRA32, + RHalf, + RGHalf, + RGBAHalf, + RFloat, + RGFloat, + RGBAFloat, + YUY2, + RGB9e5Float, + RGBFloat, + BC6H, + BC7, + BC4, + BC5, + DXT1Crunched, + DXT5Crunched, + PVRTC_RGB2, + PVRTC_RGBA2, + PVRTC_RGB4, + PVRTC_RGBA4, + ETC_RGB4, + ATC_RGB4, + ATC_RGBA8, + EAC_R = 41, + EAC_R_SIGNED, + EAC_RG, + EAC_RG_SIGNED, + ETC2_RGB, + ETC2_RGBA1, + ETC2_RGBA8, + ASTC_RGB_4x4, + ASTC_RGB_5x5, + ASTC_RGB_6x6, + ASTC_RGB_8x8, + ASTC_RGB_10x10, + ASTC_RGB_12x12, + ASTC_RGBA_4x4, + ASTC_RGBA_5x5, + ASTC_RGBA_6x6, + ASTC_RGBA_8x8, + ASTC_RGBA_10x10, + ASTC_RGBA_12x12, + ETC_RGB4_3DS, + ETC_RGBA8_3DS, + RG16, + R8, + ETC_RGB4Crunched, + ETC2_RGBA8Crunched, + R16_Alt, + ASTC_HDR_4x4, + ASTC_HDR_5x5, + ASTC_HDR_6x6, + ASTC_HDR_8x8, + ASTC_HDR_10x10, + ASTC_HDR_12x12, + RG32, + RGB48, + RGBA64, +} |