move texture_to_image and image_to_texture into new module (#1381)
The `Texture::convert` function previously was only compiled when one of the image format features (`png`, `jpeg` etc.) were enabled. The `bevy_sprite` crate needs this function though, which led to compilation errors when using `cargo check --no-default-features --features render`. Now the `convert` function has no features and the `texture_to_image` and `image_to_texture` utilites functions are in an unconditionally compiled module.
This commit is contained in:
parent
1ca8ce4a79
commit
4796ea8d22
150
crates/bevy_render/src/texture/image_texture_conversion.rs
Normal file
150
crates/bevy_render/src/texture/image_texture_conversion.rs
Normal file
@ -0,0 +1,150 @@
|
||||
use super::{Extent3d, Texture, TextureDimension, TextureFormat};
|
||||
|
||||
/// Helper method to convert a `DynamicImage` to a `Texture`
|
||||
pub(crate) fn image_to_texture(dyn_img: image::DynamicImage) -> Texture {
|
||||
use bevy_core::AsBytes;
|
||||
|
||||
let width;
|
||||
let height;
|
||||
|
||||
let data: Vec<u8>;
|
||||
let format: TextureFormat;
|
||||
|
||||
match dyn_img {
|
||||
image::DynamicImage::ImageLuma8(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::R8Unorm;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageLumaA8(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rg8Unorm;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageRgb8(i) => {
|
||||
let i = image::DynamicImage::ImageRgb8(i).into_rgba8();
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rgba8UnormSrgb;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageRgba8(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rgba8UnormSrgb;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageBgr8(i) => {
|
||||
let i = image::DynamicImage::ImageBgr8(i).into_bgra8();
|
||||
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Bgra8UnormSrgb;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageBgra8(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Bgra8UnormSrgb;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageLuma16(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::R16Uint;
|
||||
|
||||
let raw_data = i.into_raw();
|
||||
|
||||
data = raw_data.as_slice().as_bytes().to_owned();
|
||||
}
|
||||
image::DynamicImage::ImageLumaA16(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rg16Uint;
|
||||
|
||||
let raw_data = i.into_raw();
|
||||
|
||||
data = raw_data.as_slice().as_bytes().to_owned();
|
||||
}
|
||||
|
||||
image::DynamicImage::ImageRgb16(image) => {
|
||||
width = image.width();
|
||||
height = image.height();
|
||||
format = TextureFormat::Rgba16Uint;
|
||||
|
||||
let mut local_data =
|
||||
Vec::with_capacity(width as usize * height as usize * format.pixel_size());
|
||||
|
||||
for pixel in image.into_raw().chunks_exact(3) {
|
||||
// TODO unsafe_get in release builds?
|
||||
let r = pixel[0];
|
||||
let g = pixel[1];
|
||||
let b = pixel[2];
|
||||
let a = u16::max_value();
|
||||
|
||||
local_data.extend_from_slice(&r.to_ne_bytes());
|
||||
local_data.extend_from_slice(&g.to_ne_bytes());
|
||||
local_data.extend_from_slice(&b.to_ne_bytes());
|
||||
local_data.extend_from_slice(&a.to_ne_bytes());
|
||||
}
|
||||
|
||||
data = local_data;
|
||||
}
|
||||
image::DynamicImage::ImageRgba16(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rgba16Uint;
|
||||
|
||||
let raw_data = i.into_raw();
|
||||
|
||||
data = raw_data.as_slice().as_bytes().to_owned();
|
||||
}
|
||||
}
|
||||
|
||||
Texture::new(
|
||||
Extent3d::new(width, height, 1),
|
||||
TextureDimension::D2,
|
||||
data,
|
||||
format,
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper method to convert a `Texture` to a `DynamicImage`. Not all `Texture` formats are
|
||||
/// covered, it will return `None` if the format is not supported
|
||||
pub(crate) fn texture_to_image(texture: &Texture) -> Option<image::DynamicImage> {
|
||||
match texture.format {
|
||||
TextureFormat::R8Unorm => image::ImageBuffer::from_raw(
|
||||
texture.size.width,
|
||||
texture.size.height,
|
||||
texture.data.clone(),
|
||||
)
|
||||
.map(image::DynamicImage::ImageLuma8),
|
||||
TextureFormat::Rg8Unorm => image::ImageBuffer::from_raw(
|
||||
texture.size.width,
|
||||
texture.size.height,
|
||||
texture.data.clone(),
|
||||
)
|
||||
.map(image::DynamicImage::ImageLumaA8),
|
||||
TextureFormat::Rgba8UnormSrgb => image::ImageBuffer::from_raw(
|
||||
texture.size.width,
|
||||
texture.size.height,
|
||||
texture.data.clone(),
|
||||
)
|
||||
.map(image::DynamicImage::ImageRgba8),
|
||||
TextureFormat::Bgra8UnormSrgb => image::ImageBuffer::from_raw(
|
||||
texture.size.width,
|
||||
texture.size.height,
|
||||
texture.data.clone(),
|
||||
)
|
||||
.map(image::DynamicImage::ImageBgra8),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
use super::{Extent3d, Texture, TextureDimension, TextureFormat};
|
||||
use super::image_texture_conversion::image_to_texture;
|
||||
use anyhow::Result;
|
||||
use bevy_asset::{AssetLoader, LoadContext, LoadedAsset};
|
||||
use bevy_utils::BoxedFuture;
|
||||
@ -60,152 +60,3 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper method to convert a `DynamicImage` to a `Texture`
|
||||
pub(crate) fn image_to_texture(dyn_img: image::DynamicImage) -> Texture {
|
||||
use bevy_core::AsBytes;
|
||||
|
||||
let width;
|
||||
let height;
|
||||
|
||||
let data: Vec<u8>;
|
||||
let format: TextureFormat;
|
||||
|
||||
match dyn_img {
|
||||
image::DynamicImage::ImageLuma8(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::R8Unorm;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageLumaA8(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rg8Unorm;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageRgb8(i) => {
|
||||
let i = image::DynamicImage::ImageRgb8(i).into_rgba8();
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rgba8UnormSrgb;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageRgba8(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rgba8UnormSrgb;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageBgr8(i) => {
|
||||
let i = image::DynamicImage::ImageBgr8(i).into_bgra8();
|
||||
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Bgra8UnormSrgb;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageBgra8(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Bgra8UnormSrgb;
|
||||
|
||||
data = i.into_raw();
|
||||
}
|
||||
image::DynamicImage::ImageLuma16(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::R16Uint;
|
||||
|
||||
let raw_data = i.into_raw();
|
||||
|
||||
data = raw_data.as_slice().as_bytes().to_owned();
|
||||
}
|
||||
image::DynamicImage::ImageLumaA16(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rg16Uint;
|
||||
|
||||
let raw_data = i.into_raw();
|
||||
|
||||
data = raw_data.as_slice().as_bytes().to_owned();
|
||||
}
|
||||
|
||||
image::DynamicImage::ImageRgb16(image) => {
|
||||
width = image.width();
|
||||
height = image.height();
|
||||
format = TextureFormat::Rgba16Uint;
|
||||
|
||||
let mut local_data =
|
||||
Vec::with_capacity(width as usize * height as usize * format.pixel_size());
|
||||
|
||||
for pixel in image.into_raw().chunks_exact(3) {
|
||||
// TODO unsafe_get in release builds?
|
||||
let r = pixel[0];
|
||||
let g = pixel[1];
|
||||
let b = pixel[2];
|
||||
let a = u16::max_value();
|
||||
|
||||
local_data.extend_from_slice(&r.to_ne_bytes());
|
||||
local_data.extend_from_slice(&g.to_ne_bytes());
|
||||
local_data.extend_from_slice(&b.to_ne_bytes());
|
||||
local_data.extend_from_slice(&a.to_ne_bytes());
|
||||
}
|
||||
|
||||
data = local_data;
|
||||
}
|
||||
image::DynamicImage::ImageRgba16(i) => {
|
||||
width = i.width();
|
||||
height = i.height();
|
||||
format = TextureFormat::Rgba16Uint;
|
||||
|
||||
let raw_data = i.into_raw();
|
||||
|
||||
data = raw_data.as_slice().as_bytes().to_owned();
|
||||
}
|
||||
}
|
||||
|
||||
Texture::new(
|
||||
Extent3d::new(width, height, 1),
|
||||
TextureDimension::D2,
|
||||
data,
|
||||
format,
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper method to convert a `Texture` to a `DynamicImage`. Not all `Texture` formats are
|
||||
/// covered, it will return `None` if the format is not supported
|
||||
pub(crate) fn texture_to_image(texture: &Texture) -> Option<image::DynamicImage> {
|
||||
match texture.format {
|
||||
TextureFormat::R8Unorm => image::ImageBuffer::from_raw(
|
||||
texture.size.width,
|
||||
texture.size.height,
|
||||
texture.data.clone(),
|
||||
)
|
||||
.map(image::DynamicImage::ImageLuma8),
|
||||
TextureFormat::Rg8Unorm => image::ImageBuffer::from_raw(
|
||||
texture.size.width,
|
||||
texture.size.height,
|
||||
texture.data.clone(),
|
||||
)
|
||||
.map(image::DynamicImage::ImageLumaA8),
|
||||
TextureFormat::Rgba8UnormSrgb => image::ImageBuffer::from_raw(
|
||||
texture.size.width,
|
||||
texture.size.height,
|
||||
texture.data.clone(),
|
||||
)
|
||||
.map(image::DynamicImage::ImageRgba8),
|
||||
TextureFormat::Bgra8UnormSrgb => image::ImageBuffer::from_raw(
|
||||
texture.size.width,
|
||||
texture.size.height,
|
||||
texture.data.clone(),
|
||||
)
|
||||
.map(image::DynamicImage::ImageBgra8),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,8 @@ mod texture;
|
||||
mod texture_descriptor;
|
||||
mod texture_dimension;
|
||||
|
||||
pub(crate) mod image_texture_conversion;
|
||||
|
||||
#[cfg(feature = "hdr")]
|
||||
pub use hdr_texture_loader::*;
|
||||
#[cfg(any(
|
||||
|
||||
@ -131,15 +131,8 @@ impl Texture {
|
||||
/// - `TextureFormat::Rg8Unorm`
|
||||
/// - `TextureFormat::Rgba8UnormSrgb`
|
||||
/// - `TextureFormat::Bgra8UnormSrgb`
|
||||
#[cfg(any(
|
||||
feature = "png",
|
||||
feature = "dds",
|
||||
feature = "tga",
|
||||
feature = "jpeg",
|
||||
feature = "bmp"
|
||||
))]
|
||||
pub fn convert(&self, new_format: TextureFormat) -> Option<Self> {
|
||||
super::texture_to_image(self)
|
||||
super::image_texture_conversion::texture_to_image(self)
|
||||
.and_then(|img| match new_format {
|
||||
TextureFormat::R8Unorm => Some(image::DynamicImage::ImageLuma8(img.into_luma8())),
|
||||
TextureFormat::Rg8Unorm => {
|
||||
@ -153,7 +146,7 @@ impl Texture {
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.map(super::image_to_texture)
|
||||
.map(super::image_texture_conversion::image_to_texture)
|
||||
}
|
||||
|
||||
pub fn texture_resource_system(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user