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, pub texture_format: TextureFormat, pub texture_dimension: i32, } impl FromValue for Texture2d { fn from_value(v: Value) -> Result { 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 { 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::, Vec<_>>::from_raw(w as u32, h as u32, buf) .unwrap(); Ok(im.into()) } RGB24 => { let im = image::ImageBuffer::, 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::, 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, }