2024-01-03 03:31:04 +00:00
|
|
|
use crate::{
|
|
|
|
render_asset::RenderAssetPersistencePolicy,
|
|
|
|
texture::{Image, TextureFormatPixelInfo},
|
|
|
|
};
|
2022-01-11 01:08:39 +00:00
|
|
|
use image::{DynamicImage, ImageBuffer};
|
Removed `anyhow` (#10003)
# Objective
- Fixes #8140
## Solution
- Added Explicit Error Typing for `AssetLoader` and `AssetSaver`, which
were the last instances of `anyhow` in use across Bevy.
---
## Changelog
- Added an associated type `Error` to `AssetLoader` and `AssetSaver` for
use with the `load` and `save` methods respectively.
- Changed `ErasedAssetLoader` and `ErasedAssetSaver` `load` and `save`
methods to use `Box<dyn Error + Send + Sync + 'static>` to allow for
arbitrary `Error` types from the non-erased trait variants. Note the
strict requirements match the pre-existing requirements around
`anyhow::Error`.
## Migration Guide
- `anyhow` is no longer exported by `bevy_asset`; Add it to your own
project (if required).
- `AssetLoader` and `AssetSaver` have an associated type `Error`; Define
an appropriate error type (e.g., using `thiserror`), or use a pre-made
error type (e.g., `anyhow::Error`). Note that using `anyhow::Error` is a
drop-in replacement.
- `AssetLoaderError` has been removed; Define a new error type, or use
an alternative (e.g., `anyhow::Error`)
- All the first-party `AssetLoader`'s and `AssetSaver`'s now return
relevant (and narrow) error types instead of a single ambiguous type;
Match over the specific error type, or encapsulate (`Box<dyn>`,
`thiserror`, `anyhow`, etc.)
## Notes
A simpler PR to resolve this issue would simply define a Bevy `Error`
type defined as `Box<dyn std::error::Error + Send + Sync + 'static>`,
but I think this type of error handling should be discouraged when
possible. Since only 2 traits required the use of `anyhow`, it isn't a
substantive body of work to solidify these error types, and remove
`anyhow` entirely. End users are still encouraged to use `anyhow` if
that is their preferred error handling style. Arguably, adding the
`Error` associated type gives more freedom to end-users to decide
whether they want more or less explicit error handling (`anyhow` vs
`thiserror`).
As an aside, I didn't perform any testing on Android or WASM. CI passed
locally, but there may be mistakes for those platforms I missed.
2023-10-06 07:20:13 +00:00
|
|
|
use thiserror::Error;
|
2021-12-14 03:58:23 +00:00
|
|
|
use wgpu::{Extent3d, TextureDimension, TextureFormat};
|
|
|
|
|
2022-09-03 17:47:38 +00:00
|
|
|
impl Image {
|
|
|
|
/// Converts a [`DynamicImage`] to an [`Image`].
|
2024-01-03 03:31:04 +00:00
|
|
|
pub fn from_dynamic(
|
|
|
|
dyn_img: DynamicImage,
|
|
|
|
is_srgb: bool,
|
|
|
|
cpu_persistent_access: RenderAssetPersistencePolicy,
|
|
|
|
) -> Image {
|
2022-09-03 17:47:38 +00:00
|
|
|
use bevy_core::cast_slice;
|
|
|
|
let width;
|
|
|
|
let height;
|
|
|
|
|
|
|
|
let data: Vec<u8>;
|
|
|
|
let format: TextureFormat;
|
|
|
|
|
|
|
|
match dyn_img {
|
2023-09-06 05:24:44 +00:00
|
|
|
DynamicImage::ImageLuma8(image) => {
|
|
|
|
let i = DynamicImage::ImageLuma8(image).into_rgba8();
|
2022-09-03 17:47:38 +00:00
|
|
|
width = i.width();
|
|
|
|
height = i.height();
|
|
|
|
format = if is_srgb {
|
|
|
|
TextureFormat::Rgba8UnormSrgb
|
|
|
|
} else {
|
|
|
|
TextureFormat::Rgba8Unorm
|
|
|
|
};
|
|
|
|
|
|
|
|
data = i.into_raw();
|
|
|
|
}
|
2023-09-06 05:24:44 +00:00
|
|
|
DynamicImage::ImageLumaA8(image) => {
|
|
|
|
let i = DynamicImage::ImageLumaA8(image).into_rgba8();
|
2022-09-03 17:47:38 +00:00
|
|
|
width = i.width();
|
|
|
|
height = i.height();
|
|
|
|
format = if is_srgb {
|
|
|
|
TextureFormat::Rgba8UnormSrgb
|
|
|
|
} else {
|
|
|
|
TextureFormat::Rgba8Unorm
|
|
|
|
};
|
|
|
|
|
|
|
|
data = i.into_raw();
|
|
|
|
}
|
2023-09-06 05:24:44 +00:00
|
|
|
DynamicImage::ImageRgb8(image) => {
|
|
|
|
let i = DynamicImage::ImageRgb8(image).into_rgba8();
|
2022-09-03 17:47:38 +00:00
|
|
|
width = i.width();
|
|
|
|
height = i.height();
|
|
|
|
format = if is_srgb {
|
|
|
|
TextureFormat::Rgba8UnormSrgb
|
|
|
|
} else {
|
|
|
|
TextureFormat::Rgba8Unorm
|
|
|
|
};
|
|
|
|
|
|
|
|
data = i.into_raw();
|
|
|
|
}
|
2023-09-06 05:24:44 +00:00
|
|
|
DynamicImage::ImageRgba8(image) => {
|
|
|
|
width = image.width();
|
|
|
|
height = image.height();
|
2022-09-03 17:47:38 +00:00
|
|
|
format = if is_srgb {
|
|
|
|
TextureFormat::Rgba8UnormSrgb
|
|
|
|
} else {
|
|
|
|
TextureFormat::Rgba8Unorm
|
|
|
|
};
|
|
|
|
|
2023-09-06 05:24:44 +00:00
|
|
|
data = image.into_raw();
|
2022-09-03 17:47:38 +00:00
|
|
|
}
|
2023-09-06 05:24:44 +00:00
|
|
|
DynamicImage::ImageLuma16(image) => {
|
|
|
|
width = image.width();
|
|
|
|
height = image.height();
|
2022-09-03 17:47:38 +00:00
|
|
|
format = TextureFormat::R16Uint;
|
2021-02-02 21:25:16 +00:00
|
|
|
|
2023-09-06 05:24:44 +00:00
|
|
|
let raw_data = image.into_raw();
|
2021-02-02 21:25:16 +00:00
|
|
|
|
2022-09-03 17:47:38 +00:00
|
|
|
data = cast_slice(&raw_data).to_owned();
|
|
|
|
}
|
2023-09-06 05:24:44 +00:00
|
|
|
DynamicImage::ImageLumaA16(image) => {
|
|
|
|
width = image.width();
|
|
|
|
height = image.height();
|
2022-09-03 17:47:38 +00:00
|
|
|
format = TextureFormat::Rg16Uint;
|
2021-02-02 21:25:16 +00:00
|
|
|
|
2023-09-06 05:24:44 +00:00
|
|
|
let raw_data = image.into_raw();
|
2021-02-02 21:25:16 +00:00
|
|
|
|
2022-09-03 17:47:38 +00:00
|
|
|
data = cast_slice(&raw_data).to_owned();
|
2021-06-08 02:26:51 +00:00
|
|
|
}
|
2022-09-03 17:47:38 +00:00
|
|
|
DynamicImage::ImageRgb16(image) => {
|
2023-09-06 05:24:44 +00:00
|
|
|
let i = DynamicImage::ImageRgb16(image).into_rgba16();
|
2022-09-03 17:47:38 +00:00
|
|
|
width = i.width();
|
|
|
|
height = i.height();
|
2023-09-06 05:24:44 +00:00
|
|
|
format = TextureFormat::Rgba16Unorm;
|
2021-02-02 21:25:16 +00:00
|
|
|
|
2022-09-03 17:47:38 +00:00
|
|
|
let raw_data = i.into_raw();
|
2021-06-08 02:26:51 +00:00
|
|
|
|
2022-09-03 17:47:38 +00:00
|
|
|
data = cast_slice(&raw_data).to_owned();
|
|
|
|
}
|
2023-09-06 05:24:44 +00:00
|
|
|
DynamicImage::ImageRgba16(image) => {
|
|
|
|
width = image.width();
|
|
|
|
height = image.height();
|
|
|
|
format = TextureFormat::Rgba16Unorm;
|
|
|
|
|
|
|
|
let raw_data = image.into_raw();
|
|
|
|
|
|
|
|
data = cast_slice(&raw_data).to_owned();
|
|
|
|
}
|
2022-09-03 17:47:38 +00:00
|
|
|
DynamicImage::ImageRgb32F(image) => {
|
|
|
|
width = image.width();
|
|
|
|
height = image.height();
|
|
|
|
format = TextureFormat::Rgba32Float;
|
|
|
|
|
|
|
|
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: use the array_chunks method once stabilised
|
|
|
|
// https://github.com/rust-lang/rust/issues/74985
|
|
|
|
let r = pixel[0];
|
|
|
|
let g = pixel[1];
|
|
|
|
let b = pixel[2];
|
Fix alpha channel in RGB32F image texture format conversion (#6914)
# Objective
The following code:
```rs
use bevy::prelude::Image;
use image::{ DynamicImage, GenericImage, Rgba };
fn main() {
let mut dynamic_image = DynamicImage::new_rgb32f(1, 1);
dynamic_image.put_pixel(0, 0, Rgba([1, 1, 1, 1]));
let image = Image::from_dynamic(dynamic_image, false); // Panic!
println!("{image:?}");
}
```
Can cause an assertion failed:
```
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `16`,
right: `14`: Pixel data, size and format have to match', .../bevy_render-0.9.1/src/texture/image.rs:209:9
stack backtrace:
...
4: core::panicking::assert_failed<usize,usize>
at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/panicking.rs:181
5: bevy_render::texture::image::Image::new
at .../bevy_render-0.9.1/src/texture/image.rs:209
6: bevy_render::texture::image::Image::from_dynamic
at .../bevy_render-0.9.1/src/texture/image_texture_conversion.rs:159
7: bevy_test::main
at ./src/main.rs:8
...
```
It seems to be cause by a copypasta in `crates/bevy_render/src/texture/image_texture_conversion.rs`. Let's fix it.
## Solution
```diff
// DynamicImage::ImageRgb32F(image) => {
- let a = u16::max_value();
+ let a = 1f32;
```
This will fix the conversion.
---
## Changelog
- Fixed the alpha channel of the `image::DynamicImage::ImageRgb32F` to `bevy_render::texture::Image` conversion in `bevy_render::texture::Image::from_dynamic()`.
2022-12-11 18:46:47 +00:00
|
|
|
let a = 1f32;
|
2022-09-03 17:47:38 +00:00
|
|
|
|
|
|
|
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;
|
2022-05-28 02:00:55 +00:00
|
|
|
}
|
2022-09-03 17:47:38 +00:00
|
|
|
DynamicImage::ImageRgba32F(image) => {
|
|
|
|
width = image.width();
|
|
|
|
height = image.height();
|
|
|
|
format = TextureFormat::Rgba32Float;
|
2022-05-28 02:00:55 +00:00
|
|
|
|
2022-09-03 17:47:38 +00:00
|
|
|
let raw_data = image.into_raw();
|
|
|
|
|
|
|
|
data = cast_slice(&raw_data).to_owned();
|
|
|
|
}
|
|
|
|
// DynamicImage is now non exhaustive, catch future variants and convert them
|
|
|
|
_ => {
|
|
|
|
let image = dyn_img.into_rgba8();
|
|
|
|
width = image.width();
|
|
|
|
height = image.height();
|
|
|
|
format = TextureFormat::Rgba8UnormSrgb;
|
|
|
|
|
|
|
|
data = image.into_raw();
|
|
|
|
}
|
2022-05-28 02:00:55 +00:00
|
|
|
}
|
|
|
|
|
2022-09-03 17:47:38 +00:00
|
|
|
Image::new(
|
|
|
|
Extent3d {
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
depth_or_array_layers: 1,
|
|
|
|
},
|
|
|
|
TextureDimension::D2,
|
|
|
|
data,
|
|
|
|
format,
|
2024-01-03 03:31:04 +00:00
|
|
|
cpu_persistent_access,
|
2022-09-03 17:47:38 +00:00
|
|
|
)
|
|
|
|
}
|
2022-05-28 02:00:55 +00:00
|
|
|
|
2023-02-20 22:56:57 +00:00
|
|
|
/// Convert a [`Image`] to a [`DynamicImage`]. Useful for editing image
|
2022-09-03 17:47:38 +00:00
|
|
|
/// data. Not all [`TextureFormat`] are covered, therefore it will return an
|
|
|
|
/// error if the format is unsupported. Supported formats are:
|
|
|
|
/// - `TextureFormat::R8Unorm`
|
|
|
|
/// - `TextureFormat::Rg8Unorm`
|
|
|
|
/// - `TextureFormat::Rgba8UnormSrgb`
|
2023-04-19 21:28:42 +00:00
|
|
|
/// - `TextureFormat::Bgra8UnormSrgb`
|
2022-09-03 17:47:38 +00:00
|
|
|
///
|
|
|
|
/// To convert [`Image`] to a different format see: [`Image::convert`].
|
Removed `anyhow` (#10003)
# Objective
- Fixes #8140
## Solution
- Added Explicit Error Typing for `AssetLoader` and `AssetSaver`, which
were the last instances of `anyhow` in use across Bevy.
---
## Changelog
- Added an associated type `Error` to `AssetLoader` and `AssetSaver` for
use with the `load` and `save` methods respectively.
- Changed `ErasedAssetLoader` and `ErasedAssetSaver` `load` and `save`
methods to use `Box<dyn Error + Send + Sync + 'static>` to allow for
arbitrary `Error` types from the non-erased trait variants. Note the
strict requirements match the pre-existing requirements around
`anyhow::Error`.
## Migration Guide
- `anyhow` is no longer exported by `bevy_asset`; Add it to your own
project (if required).
- `AssetLoader` and `AssetSaver` have an associated type `Error`; Define
an appropriate error type (e.g., using `thiserror`), or use a pre-made
error type (e.g., `anyhow::Error`). Note that using `anyhow::Error` is a
drop-in replacement.
- `AssetLoaderError` has been removed; Define a new error type, or use
an alternative (e.g., `anyhow::Error`)
- All the first-party `AssetLoader`'s and `AssetSaver`'s now return
relevant (and narrow) error types instead of a single ambiguous type;
Match over the specific error type, or encapsulate (`Box<dyn>`,
`thiserror`, `anyhow`, etc.)
## Notes
A simpler PR to resolve this issue would simply define a Bevy `Error`
type defined as `Box<dyn std::error::Error + Send + Sync + 'static>`,
but I think this type of error handling should be discouraged when
possible. Since only 2 traits required the use of `anyhow`, it isn't a
substantive body of work to solidify these error types, and remove
`anyhow` entirely. End users are still encouraged to use `anyhow` if
that is their preferred error handling style. Arguably, adding the
`Error` associated type gives more freedom to end-users to decide
whether they want more or less explicit error handling (`anyhow` vs
`thiserror`).
As an aside, I didn't perform any testing on Android or WASM. CI passed
locally, but there may be mistakes for those platforms I missed.
2023-10-06 07:20:13 +00:00
|
|
|
pub fn try_into_dynamic(self) -> Result<DynamicImage, IntoDynamicImageError> {
|
2022-09-03 17:47:38 +00:00
|
|
|
match self.texture_descriptor.format {
|
2023-10-23 20:49:02 +00:00
|
|
|
TextureFormat::R8Unorm => ImageBuffer::from_raw(self.width(), self.height(), self.data)
|
|
|
|
.map(DynamicImage::ImageLuma8),
|
|
|
|
TextureFormat::Rg8Unorm => {
|
|
|
|
ImageBuffer::from_raw(self.width(), self.height(), self.data)
|
|
|
|
.map(DynamicImage::ImageLumaA8)
|
|
|
|
}
|
|
|
|
TextureFormat::Rgba8UnormSrgb => {
|
|
|
|
ImageBuffer::from_raw(self.width(), self.height(), self.data)
|
|
|
|
.map(DynamicImage::ImageRgba8)
|
|
|
|
}
|
2023-04-19 21:28:42 +00:00
|
|
|
// This format is commonly used as the format for the swapchain texture
|
|
|
|
// This conversion is added here to support screenshots
|
2023-10-23 20:49:02 +00:00
|
|
|
TextureFormat::Bgra8UnormSrgb | TextureFormat::Bgra8Unorm => {
|
|
|
|
ImageBuffer::from_raw(self.width(), self.height(), {
|
2023-04-19 21:28:42 +00:00
|
|
|
let mut data = self.data;
|
|
|
|
for bgra in data.chunks_exact_mut(4) {
|
|
|
|
bgra.swap(0, 2);
|
|
|
|
}
|
|
|
|
data
|
2023-10-23 20:49:02 +00:00
|
|
|
})
|
|
|
|
.map(DynamicImage::ImageRgba8)
|
|
|
|
}
|
2022-09-03 17:47:38 +00:00
|
|
|
// Throw and error if conversion isn't supported
|
Removed `anyhow` (#10003)
# Objective
- Fixes #8140
## Solution
- Added Explicit Error Typing for `AssetLoader` and `AssetSaver`, which
were the last instances of `anyhow` in use across Bevy.
---
## Changelog
- Added an associated type `Error` to `AssetLoader` and `AssetSaver` for
use with the `load` and `save` methods respectively.
- Changed `ErasedAssetLoader` and `ErasedAssetSaver` `load` and `save`
methods to use `Box<dyn Error + Send + Sync + 'static>` to allow for
arbitrary `Error` types from the non-erased trait variants. Note the
strict requirements match the pre-existing requirements around
`anyhow::Error`.
## Migration Guide
- `anyhow` is no longer exported by `bevy_asset`; Add it to your own
project (if required).
- `AssetLoader` and `AssetSaver` have an associated type `Error`; Define
an appropriate error type (e.g., using `thiserror`), or use a pre-made
error type (e.g., `anyhow::Error`). Note that using `anyhow::Error` is a
drop-in replacement.
- `AssetLoaderError` has been removed; Define a new error type, or use
an alternative (e.g., `anyhow::Error`)
- All the first-party `AssetLoader`'s and `AssetSaver`'s now return
relevant (and narrow) error types instead of a single ambiguous type;
Match over the specific error type, or encapsulate (`Box<dyn>`,
`thiserror`, `anyhow`, etc.)
## Notes
A simpler PR to resolve this issue would simply define a Bevy `Error`
type defined as `Box<dyn std::error::Error + Send + Sync + 'static>`,
but I think this type of error handling should be discouraged when
possible. Since only 2 traits required the use of `anyhow`, it isn't a
substantive body of work to solidify these error types, and remove
`anyhow` entirely. End users are still encouraged to use `anyhow` if
that is their preferred error handling style. Arguably, adding the
`Error` associated type gives more freedom to end-users to decide
whether they want more or less explicit error handling (`anyhow` vs
`thiserror`).
As an aside, I didn't perform any testing on Android or WASM. CI passed
locally, but there may be mistakes for those platforms I missed.
2023-10-06 07:20:13 +00:00
|
|
|
texture_format => return Err(IntoDynamicImageError::UnsupportedFormat(texture_format)),
|
2022-05-28 02:00:55 +00:00
|
|
|
}
|
Removed `anyhow` (#10003)
# Objective
- Fixes #8140
## Solution
- Added Explicit Error Typing for `AssetLoader` and `AssetSaver`, which
were the last instances of `anyhow` in use across Bevy.
---
## Changelog
- Added an associated type `Error` to `AssetLoader` and `AssetSaver` for
use with the `load` and `save` methods respectively.
- Changed `ErasedAssetLoader` and `ErasedAssetSaver` `load` and `save`
methods to use `Box<dyn Error + Send + Sync + 'static>` to allow for
arbitrary `Error` types from the non-erased trait variants. Note the
strict requirements match the pre-existing requirements around
`anyhow::Error`.
## Migration Guide
- `anyhow` is no longer exported by `bevy_asset`; Add it to your own
project (if required).
- `AssetLoader` and `AssetSaver` have an associated type `Error`; Define
an appropriate error type (e.g., using `thiserror`), or use a pre-made
error type (e.g., `anyhow::Error`). Note that using `anyhow::Error` is a
drop-in replacement.
- `AssetLoaderError` has been removed; Define a new error type, or use
an alternative (e.g., `anyhow::Error`)
- All the first-party `AssetLoader`'s and `AssetSaver`'s now return
relevant (and narrow) error types instead of a single ambiguous type;
Match over the specific error type, or encapsulate (`Box<dyn>`,
`thiserror`, `anyhow`, etc.)
## Notes
A simpler PR to resolve this issue would simply define a Bevy `Error`
type defined as `Box<dyn std::error::Error + Send + Sync + 'static>`,
but I think this type of error handling should be discouraged when
possible. Since only 2 traits required the use of `anyhow`, it isn't a
substantive body of work to solidify these error types, and remove
`anyhow` entirely. End users are still encouraged to use `anyhow` if
that is their preferred error handling style. Arguably, adding the
`Error` associated type gives more freedom to end-users to decide
whether they want more or less explicit error handling (`anyhow` vs
`thiserror`).
As an aside, I didn't perform any testing on Android or WASM. CI passed
locally, but there may be mistakes for those platforms I missed.
2023-10-06 07:20:13 +00:00
|
|
|
.ok_or(IntoDynamicImageError::UnknownConversionError(
|
|
|
|
self.texture_descriptor.format,
|
|
|
|
))
|
2021-02-02 21:25:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Removed `anyhow` (#10003)
# Objective
- Fixes #8140
## Solution
- Added Explicit Error Typing for `AssetLoader` and `AssetSaver`, which
were the last instances of `anyhow` in use across Bevy.
---
## Changelog
- Added an associated type `Error` to `AssetLoader` and `AssetSaver` for
use with the `load` and `save` methods respectively.
- Changed `ErasedAssetLoader` and `ErasedAssetSaver` `load` and `save`
methods to use `Box<dyn Error + Send + Sync + 'static>` to allow for
arbitrary `Error` types from the non-erased trait variants. Note the
strict requirements match the pre-existing requirements around
`anyhow::Error`.
## Migration Guide
- `anyhow` is no longer exported by `bevy_asset`; Add it to your own
project (if required).
- `AssetLoader` and `AssetSaver` have an associated type `Error`; Define
an appropriate error type (e.g., using `thiserror`), or use a pre-made
error type (e.g., `anyhow::Error`). Note that using `anyhow::Error` is a
drop-in replacement.
- `AssetLoaderError` has been removed; Define a new error type, or use
an alternative (e.g., `anyhow::Error`)
- All the first-party `AssetLoader`'s and `AssetSaver`'s now return
relevant (and narrow) error types instead of a single ambiguous type;
Match over the specific error type, or encapsulate (`Box<dyn>`,
`thiserror`, `anyhow`, etc.)
## Notes
A simpler PR to resolve this issue would simply define a Bevy `Error`
type defined as `Box<dyn std::error::Error + Send + Sync + 'static>`,
but I think this type of error handling should be discouraged when
possible. Since only 2 traits required the use of `anyhow`, it isn't a
substantive body of work to solidify these error types, and remove
`anyhow` entirely. End users are still encouraged to use `anyhow` if
that is their preferred error handling style. Arguably, adding the
`Error` associated type gives more freedom to end-users to decide
whether they want more or less explicit error handling (`anyhow` vs
`thiserror`).
As an aside, I didn't perform any testing on Android or WASM. CI passed
locally, but there may be mistakes for those platforms I missed.
2023-10-06 07:20:13 +00:00
|
|
|
/// Errors that occur while converting an [`Image`] into a [`DynamicImage`]
|
|
|
|
#[non_exhaustive]
|
|
|
|
#[derive(Error, Debug)]
|
|
|
|
pub enum IntoDynamicImageError {
|
|
|
|
/// Conversion into dynamic image not supported for source format.
|
|
|
|
#[error("Conversion into dynamic image not supported for {0:?}.")]
|
|
|
|
UnsupportedFormat(TextureFormat),
|
|
|
|
|
|
|
|
/// Encountered an unknown error during conversion.
|
|
|
|
#[error("Failed to convert into {0:?}.")]
|
|
|
|
UnknownConversionError(TextureFormat),
|
|
|
|
}
|
|
|
|
|
2022-09-03 17:47:38 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use image::{GenericImage, Rgba};
|
|
|
|
|
|
|
|
use super::*;
|
2024-01-03 03:31:04 +00:00
|
|
|
use crate::render_asset::RenderAssetPersistencePolicy;
|
2022-09-03 17:47:38 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn two_way_conversion() {
|
|
|
|
// Check to see if color is preserved through an rgba8 conversion and back.
|
|
|
|
let mut initial = DynamicImage::new_rgba8(1, 1);
|
|
|
|
initial.put_pixel(0, 0, Rgba::from([132, 3, 7, 200]));
|
|
|
|
|
2024-01-03 03:31:04 +00:00
|
|
|
let image =
|
|
|
|
Image::from_dynamic(initial.clone(), true, RenderAssetPersistencePolicy::Unload);
|
2022-09-03 17:47:38 +00:00
|
|
|
|
|
|
|
// NOTE: Fails if `is_srbg = false` or the dynamic image is of the type rgb8.
|
|
|
|
assert_eq!(initial, image.try_into_dynamic().unwrap());
|
2021-02-02 21:25:16 +00:00
|
|
|
}
|
|
|
|
}
|