pub mod converter;
pub mod decoders;
pub mod formats;
pub mod helpers;
pub mod types;
pub use converter::{Texture2DConverter, Texture2DProcessor}; pub use decoders::{Decoder, TextureDecoder};
pub use formats::{TextureFormat, TextureFormatInfo};
pub use helpers::{TextureExporter, TextureSwizzler};
pub use types::{GLTextureSettings, StreamingInfo, Texture2D};
pub use decoders::{BasicDecoder, CompressedDecoder, CrunchDecoder, MobileDecoder};
pub use helpers::export::ExportOptions;
pub struct TextureProcessor {
converter: Texture2DConverter,
decoder: TextureDecoder,
}
impl TextureProcessor {
pub fn new(version: crate::unity_version::UnityVersion) -> Self {
Self {
converter: Texture2DConverter::new(version),
decoder: TextureDecoder::new(),
}
}
pub fn convert_object(
&self,
obj: &crate::object::UnityObject,
) -> crate::error::Result<Texture2D> {
self.converter.from_unity_object(obj)
}
pub fn decode_texture(&self, texture: &Texture2D) -> crate::error::Result<image::RgbaImage> {
self.decoder.decode(texture)
}
pub fn process_and_export<P: AsRef<std::path::Path>>(
&self,
obj: &crate::object::UnityObject,
output_path: P,
) -> crate::error::Result<()> {
let texture = self.convert_object(obj)?;
let image = self.decode_texture(&texture)?;
TextureExporter::export_auto(&image, output_path)
}
pub fn can_process(&self, format: TextureFormat) -> bool {
self.decoder.can_decode(format)
}
pub fn supported_formats(&self) -> Vec<TextureFormat> {
self.decoder.supported_formats()
}
}
impl Default for TextureProcessor {
fn default() -> Self {
Self::new(crate::unity_version::UnityVersion::default())
}
}
pub fn create_processor() -> TextureProcessor {
TextureProcessor::default()
}
pub fn is_format_supported(format: TextureFormat) -> bool {
let decoder = TextureDecoder::new();
decoder.can_decode(format)
}
pub fn get_supported_formats() -> Vec<TextureFormat> {
let decoder = TextureDecoder::new();
decoder.supported_formats()
}
pub fn decode_texture_data(
format: TextureFormat,
width: u32,
height: u32,
data: Vec<u8>,
) -> crate::error::Result<image::RgbaImage> {
let texture = Texture2D {
name: "decoded_texture".to_string(),
width: width as i32,
height: height as i32,
format,
image_data: data,
..Default::default()
};
let decoder = TextureDecoder::new();
decoder.decode(&texture)
}
pub fn export_image<P: AsRef<std::path::Path>>(
image: &image::RgbaImage,
path: P,
) -> crate::error::Result<()> {
TextureExporter::export_auto(image, path)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_support() {
assert!(is_format_supported(TextureFormat::RGBA32));
assert!(is_format_supported(TextureFormat::RGB24));
assert!(is_format_supported(TextureFormat::ARGB32));
}
#[test]
fn test_processor_creation() {
let processor = create_processor();
assert!(processor.can_process(TextureFormat::RGBA32));
}
#[test]
fn test_supported_formats_list() {
let formats = get_supported_formats();
assert!(!formats.is_empty());
assert!(formats.contains(&TextureFormat::RGBA32));
}
#[test]
fn test_texture_format_info() {
let format = TextureFormat::RGBA32;
let info = format.info();
assert_eq!(info.name, "RGBA32");
assert_eq!(info.bits_per_pixel, 32);
assert!(!info.compressed);
assert!(info.has_alpha);
assert!(info.supported);
}
#[test]
fn test_format_categories() {
assert!(TextureFormat::RGBA32.is_basic_format());
assert!(!TextureFormat::RGBA32.is_compressed_format());
assert!(!TextureFormat::RGBA32.is_mobile_format());
assert!(!TextureFormat::RGBA32.is_crunch_compressed());
assert!(TextureFormat::DXT1.is_compressed_format());
assert!(!TextureFormat::DXT1.is_basic_format());
assert!(TextureFormat::ETC2_RGB.is_mobile_format());
assert!(!TextureFormat::ETC2_RGB.is_basic_format());
assert!(TextureFormat::DXT1Crunched.is_crunch_compressed());
assert!(!TextureFormat::DXT1Crunched.is_basic_format());
}
}