From 71908c659b2150e73b49836c44bec2111d50f679 Mon Sep 17 00:00:00 2001 From: Piotr Siuszko Date: Sat, 18 Jan 2025 11:49:57 +0100 Subject: [PATCH] CLI Basis format support --- crates/rpack_cli/Cargo.toml | 8 +-- crates/rpack_cli/src/lib.rs | 104 ++++++----------------------------- crates/rpack_egui/Cargo.toml | 4 +- 3 files changed, 24 insertions(+), 92 deletions(-) diff --git a/crates/rpack_cli/Cargo.toml b/crates/rpack_cli/Cargo.toml index da2ef38..557e43b 100644 --- a/crates/rpack_cli/Cargo.toml +++ b/crates/rpack_cli/Cargo.toml @@ -5,11 +5,11 @@ description = "CLI application for generating rpack atlases" repository = "https://github.com/Leinnan/rpack.git" homepage = "https://github.com/Leinnan/rpack" license = "MIT OR Apache-2.0" -version = "0.1.0" +version = "0.2.0" edition = "2021" [features] -default = ["cli", "dds"] +default = ["cli", "dds", "basis"] cli = ["dep:clap", "dep:glob"] basis = ["dep:basis-universal"] dds = ["dep:image_dds"] @@ -24,7 +24,7 @@ thiserror = "2" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] clap = { version = "4", features = ["derive"], optional = true } +glob = { version = "0.3", optional = true } basis-universal = { version = "0.3.1", optional = true } image_dds = { version = "0.7", optional = true } -glob = { version = "0.3", optional = true } -anyhow = "1" +anyhow = "1" \ No newline at end of file diff --git a/crates/rpack_cli/src/lib.rs b/crates/rpack_cli/src/lib.rs index f561e14..9c4eeb5 100644 --- a/crates/rpack_cli/src/lib.rs +++ b/crates/rpack_cli/src/lib.rs @@ -79,6 +79,7 @@ pub enum SaveImageFormat { #[default] Png, Dds, + Basis, } impl Display for SaveImageFormat { @@ -86,15 +87,7 @@ impl Display for SaveImageFormat { match self { SaveImageFormat::Png => f.write_str(".png"), SaveImageFormat::Dds => f.write_str(".dds"), - } - } -} - -impl From for image::ImageFormat { - fn from(val: SaveImageFormat) -> Self { - match val { - SaveImageFormat::Png => image::ImageFormat::Png, - SaveImageFormat::Dds => image::ImageFormat::Dds, + SaveImageFormat::Basis => f.write_str(".basis"), } } } @@ -185,14 +178,11 @@ impl Spritesheet { } #[cfg(all(feature = "basis", not(target_arch = "wasm32")))] - pub fn save_as_basis(&self, output_path: R) + pub fn save_as_basis(&self, output_path: R) -> anyhow::Result<()> where R: AsRef, { - use basis_universal::{ - BasisTextureFormat, Compressor, TranscodeParameters, Transcoder, - TranscoderTextureFormat, - }; + use basis_universal::{BasisTextureFormat, Compressor, Transcoder}; use image::{EncodableLayout, GenericImageView}; let rgba_image = self.image_data.to_rgba8(); @@ -201,8 +191,8 @@ impl Spritesheet { let (pixel_width, pixel_height) = self.image_data.dimensions(); let mut compressor_params = basis_universal::CompressorParams::new(); compressor_params.set_generate_mipmaps(true); - compressor_params.set_basis_format(BasisTextureFormat::UASTC4x4); - compressor_params.set_uastc_quality_level(basis_universal::UASTC_QUALITY_DEFAULT); + compressor_params.set_basis_format(BasisTextureFormat::ETC1S); + compressor_params.set_etc1s_quality_level(basis_universal::ETC1S_QUALITY_MAX); compressor_params.set_print_status_to_stdout(false); let mut compressor_image = compressor_params.source_image_mut(0); compressor_image.init( @@ -219,16 +209,14 @@ impl Spritesheet { let compression_time = unsafe { compressor.init(&compressor_params); let t0 = std::time::Instant::now(); - compressor.process().unwrap(); + compressor.process().expect("Failed to compress the image."); let t1 = std::time::Instant::now(); t1 - t0 }; // You could write it to disk like this let basis_file = compressor.basis_file(); - // std::fs::write("example_encoded_image.basis", basis_file).unwrap(); - - let mut transcoder = Transcoder::new(); + let transcoder = Transcoder::new(); let mip_level_count = transcoder.image_level_count(basis_file, 0); println!( "Compressed {} mip levels to {} total bytes in {} ms", @@ -236,70 +224,8 @@ impl Spritesheet { compressor.basis_file_size(), compression_time.as_secs_f64() * 1000.0 ); - - let userdata = transcoder.user_data(basis_file).unwrap(); - println!("Basis file has user data {:?}", userdata); - - // - // Now lets transcode it back to raw images - // - transcoder.prepare_transcoding(basis_file).unwrap(); - - let t0 = std::time::Instant::now(); - let result = transcoder - .transcode_image_level( - basis_file, - TranscoderTextureFormat::ASTC_4x4_RGBA, - TranscodeParameters { - image_index: 0, - level_index: 0, - ..Default::default() - }, - ) - .unwrap(); - let t1 = std::time::Instant::now(); - - println!( - "Transcoded mip level 0 to ASTC_4x4_RGBA: {} bytes {} ms", - result.len(), - (t1 - t0).as_secs_f64() * 1000.0 - ); - - let t0 = std::time::Instant::now(); - let result = transcoder - .transcode_image_level( - basis_file, - TranscoderTextureFormat::RGBA32, - TranscodeParameters { - image_index: 0, - level_index: 0, - ..Default::default() - }, - ) - .unwrap(); - let t1 = std::time::Instant::now(); - - println!( - "Transcoded mip level 0 to RGBA32: {} bytes {} ms", - result.len(), - (t1 - t0).as_secs_f64() * 1000.0 - ); - - transcoder.end_transcoding(); - - let description = transcoder - .image_level_description(basis_file, 0, 0) - .unwrap(); - let image = image::RgbaImage::from_raw( - description.original_width, - description.original_height, - result, - ) - .unwrap(); - // TODO THIS DOESNT WORK, NEED TO FIX THIS - image - .save_with_format(output_path.as_ref(), image::ImageFormat::Png) - .unwrap(); + std::fs::write(output_path.as_ref(), basis_file)?; + Ok(()) } } @@ -414,10 +340,16 @@ impl TilemapGenerationConfig { #[cfg(not(feature = "dds"))] panic!("Program is compiled without support for dds. Compile it yourself with feature `dds` enabled."); } - f => { + SaveImageFormat::Png => { spritesheet .image_data - .save_with_format(&atlas_image_path, f.into())?; + .save_with_format(&atlas_image_path, image::ImageFormat::Png)?; + } + SaveImageFormat::Basis => { + #[cfg(feature = "basis")] + spritesheet.save_as_basis(&atlas_image_path)?; + #[cfg(not(feature = "basis"))] + panic!("Program is compiled without support for basis. Compile it yourself with feature `basis` enabled."); } } let json = serde_json::to_string_pretty(&spritesheet.atlas_asset_json)?; diff --git a/crates/rpack_egui/Cargo.toml b/crates/rpack_egui/Cargo.toml index 230059f..85c78ae 100644 --- a/crates/rpack_egui/Cargo.toml +++ b/crates/rpack_egui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rpack_egui" -version = "0.1.0" +version = "0.2.0" description = "GUI application for generating rpack atlases" authors = ["Piotr Siuszko "] edition = "2021" @@ -19,7 +19,7 @@ eframe = { version = "0.30", default-features = false, features = [ ] } log = "0.4" egui_json_tree = "0.10" -rpack_cli = { default-features = false, path = "../rpack_cli", version = "0.1" } +rpack_cli = { default-features = false, path = "../rpack_cli", version = "0.2" } # You only need serde if you want app persistence: serde = { version = "1", features = ["derive"] }