Path: blob/main/crates/bevy_image/src/compressed_image_saver.rs
6595 views
use crate::{Image, ImageFormat, ImageFormatSetting, ImageLoader, ImageLoaderSettings};12use bevy_asset::saver::{AssetSaver, SavedAsset};3use futures_lite::AsyncWriteExt;4use thiserror::Error;56pub struct CompressedImageSaver;78#[non_exhaustive]9#[derive(Debug, Error)]10pub enum CompressedImageSaverError {11#[error(transparent)]12Io(#[from] std::io::Error),13#[error("Cannot compress an uninitialized image")]14UninitializedImage,15}1617impl AssetSaver for CompressedImageSaver {18type Asset = Image;1920type Settings = ();21type OutputLoader = ImageLoader;22type Error = CompressedImageSaverError;2324async fn save(25&self,26writer: &mut bevy_asset::io::Writer,27image: SavedAsset<'_, Self::Asset>,28_settings: &Self::Settings,29) -> Result<ImageLoaderSettings, Self::Error> {30let is_srgb = image.texture_descriptor.format.is_srgb();3132let compressed_basis_data = {33let mut compressor_params = basis_universal::CompressorParams::new();34compressor_params.set_basis_format(basis_universal::BasisTextureFormat::UASTC4x4);35compressor_params.set_generate_mipmaps(true);36let color_space = if is_srgb {37basis_universal::ColorSpace::Srgb38} else {39basis_universal::ColorSpace::Linear40};41compressor_params.set_color_space(color_space);42compressor_params.set_uastc_quality_level(basis_universal::UASTC_QUALITY_DEFAULT);4344let mut source_image = compressor_params.source_image_mut(0);45let size = image.size();46let Some(ref data) = image.data else {47return Err(CompressedImageSaverError::UninitializedImage);48};49source_image.init(data, size.x, size.y, 4);5051let mut compressor = basis_universal::Compressor::new(4);52#[expect(53unsafe_code,54reason = "The basis-universal compressor cannot be interacted with except through unsafe functions"55)]56// SAFETY: the CompressorParams are "valid" to the best of our knowledge. The basis-universal57// library bindings note that invalid params might produce undefined behavior.58unsafe {59compressor.init(&compressor_params);60compressor.process().unwrap();61}62compressor.basis_file().to_vec()63};6465writer.write_all(&compressed_basis_data).await?;66Ok(ImageLoaderSettings {67format: ImageFormatSetting::Format(ImageFormat::Basis),68is_srgb,69sampler: image.sampler.clone(),70asset_usage: image.asset_usage,71texture_format: None,72})73}74}757677