Path: blob/main/crates/bevy_image/src/compressed_image_saver.rs
9421 views
use crate::{Image, ImageFormat, ImageFormatSetting, ImageLoader, ImageLoaderSettings};12use bevy_asset::saver::{AssetSaver, SavedAsset};3use bevy_reflect::TypePath;4use futures_lite::AsyncWriteExt;5use thiserror::Error;67#[derive(TypePath)]8pub struct CompressedImageSaver;910#[non_exhaustive]11#[derive(Debug, Error, TypePath)]12pub enum CompressedImageSaverError {13#[error(transparent)]14Io(#[from] std::io::Error),15#[error("Cannot compress an uninitialized image")]16UninitializedImage,17}1819impl AssetSaver for CompressedImageSaver {20type Asset = Image;2122type Settings = ();23type OutputLoader = ImageLoader;24type Error = CompressedImageSaverError;2526async fn save(27&self,28writer: &mut bevy_asset::io::Writer,29image: SavedAsset<'_, '_, Self::Asset>,30_settings: &Self::Settings,31) -> Result<ImageLoaderSettings, Self::Error> {32let is_srgb = image.texture_descriptor.format.is_srgb();3334let compressed_basis_data = {35let mut compressor_params = basis_universal::CompressorParams::new();36compressor_params.set_basis_format(basis_universal::BasisTextureFormat::UASTC4x4);37compressor_params.set_generate_mipmaps(true);38let color_space = if is_srgb {39basis_universal::ColorSpace::Srgb40} else {41basis_universal::ColorSpace::Linear42};43compressor_params.set_color_space(color_space);44compressor_params.set_uastc_quality_level(basis_universal::UASTC_QUALITY_DEFAULT);4546let mut source_image = compressor_params.source_image_mut(0);47let size = image.size();48let Some(ref data) = image.data else {49return Err(CompressedImageSaverError::UninitializedImage);50};51source_image.init(data, size.x, size.y, 4);5253let mut compressor = basis_universal::Compressor::new(4);54#[expect(55unsafe_code,56reason = "The basis-universal compressor cannot be interacted with except through unsafe functions"57)]58// SAFETY: the CompressorParams are "valid" to the best of our knowledge. The basis-universal59// library bindings note that invalid params might produce undefined behavior.60unsafe {61compressor.init(&compressor_params);62compressor.process().unwrap();63}64compressor.basis_file().to_vec()65};6667writer.write_all(&compressed_basis_data).await?;68Ok(ImageLoaderSettings {69format: ImageFormatSetting::Format(ImageFormat::Basis),70is_srgb,71sampler: image.sampler.clone(),72asset_usage: image.asset_usage,73texture_format: None,74array_layout: None,75})76}77}787980