use fovea::image::PlainImage;
use fovea::pixel::PlainChannel;
use crate::pixel::{GpuPixel, TextureFormat};
pub trait TextureSource {
fn texture_format(&self) -> TextureFormat;
fn texture_width(&self) -> u32;
fn texture_height(&self) -> u32;
fn texture_bytes(&self) -> &[u8];
fn bytes_per_row(&self) -> u32;
}
impl<T> TextureSource for T
where
T: PlainImage,
T::Pixel: GpuPixel,
{
#[inline]
fn texture_format(&self) -> TextureFormat {
<T::Pixel as GpuPixel>::TEXTURE_FORMAT
}
#[inline]
fn texture_width(&self) -> u32 {
self.size().width as u32
}
#[inline]
fn texture_height(&self) -> u32 {
self.size().height as u32
}
#[inline]
fn texture_bytes(&self) -> &[u8] {
self.as_bytes()
}
#[inline]
fn bytes_per_row(&self) -> u32 {
(self.size().width * <T::Pixel as PlainChannel>::SIZE) as u32
}
}
#[cfg(test)]
mod tests {
use super::*;
use fovea::image::{Image, ImageArray};
use fovea::pixel::*;
#[test]
fn image2d_mono8_texture_source() {
let img = Image::<Mono8>::zero(10, 5);
assert_eq!(img.texture_format(), TextureFormat::R8Unorm);
assert_eq!(img.texture_width(), 10);
assert_eq!(img.texture_height(), 5);
assert_eq!(img.bytes_per_row(), 10);
assert_eq!(img.texture_bytes().len(), 10 * 5);
}
#[test]
fn image2d_srgba8_texture_source() {
let img = Image::fill(16, 8, Srgba8::new(255, 0, 0, 255));
assert_eq!(img.texture_format(), TextureFormat::Rgba8Srgb);
assert_eq!(img.texture_width(), 16);
assert_eq!(img.texture_height(), 8);
assert_eq!(img.bytes_per_row(), 16 * 4);
assert_eq!(img.texture_bytes().len(), 16 * 8 * 4);
}
#[test]
fn image2d_rgba8_texture_source() {
let img = Image::fill(3, 7, Rgba8::new(1, 2, 3, 4));
assert_eq!(img.texture_format(), TextureFormat::Rgba8Unorm);
assert_eq!(img.texture_width(), 3);
assert_eq!(img.texture_height(), 7);
assert_eq!(img.bytes_per_row(), 3 * 4);
assert_eq!(img.texture_bytes().len(), 3 * 7 * 4);
}
#[test]
fn image2d_mono16_texture_source() {
let img = Image::<Mono16>::zero(100, 50);
assert_eq!(img.texture_format(), TextureFormat::R16Unorm);
assert_eq!(img.texture_width(), 100);
assert_eq!(img.texture_height(), 50);
assert_eq!(img.bytes_per_row(), 100 * 2);
assert_eq!(img.texture_bytes().len(), 100 * 50 * 2);
}
#[test]
fn image2d_f32_texture_source() {
let img = Image::<fovea::pixel::MonoF32>::zero(8, 4);
assert_eq!(img.texture_format(), TextureFormat::R32Float);
assert_eq!(img.texture_width(), 8);
assert_eq!(img.texture_height(), 4);
assert_eq!(img.bytes_per_row(), 8 * 4);
assert_eq!(img.texture_bytes().len(), 8 * 4 * 4);
}
#[test]
fn image2d_rgba_f32_texture_source() {
let img = Image::fill(
2,
3,
RgbaF32 {
r: 1.0,
g: 0.0,
b: 0.0,
a: 1.0,
},
);
assert_eq!(img.texture_format(), TextureFormat::Rgba32Float);
assert_eq!(img.texture_width(), 2);
assert_eq!(img.texture_height(), 3);
assert_eq!(img.bytes_per_row(), 2 * 16);
assert_eq!(img.texture_bytes().len(), 2 * 3 * 16);
}
#[test]
fn image_array_rgba8_texture_source() {
let img = ImageArray::<Rgba8, 4, 4>::new([Rgba8::new(0, 0, 0, 0); 16]);
assert_eq!(img.texture_format(), TextureFormat::Rgba8Unorm);
assert_eq!(img.texture_width(), 4);
assert_eq!(img.texture_height(), 4);
assert_eq!(img.bytes_per_row(), 4 * 4);
assert_eq!(img.texture_bytes().len(), 4 * 4 * 4);
}
#[test]
fn bytes_per_row_equals_width_times_pixel_size() {
let img = Image::fill(17, 3, MonoA16::new(0, 0));
assert_eq!(
img.bytes_per_row(),
img.texture_width() * img.texture_format().bytes_per_pixel() as u32
);
}
#[test]
fn texture_bytes_len_equals_width_times_height_times_bpp() {
let img = Image::fill(13, 7, Bgra8::new(0, 0, 0, 0));
let expected = img.texture_width() as usize
* img.texture_height() as usize
* img.texture_format().bytes_per_pixel();
assert_eq!(img.texture_bytes().len(), expected);
}
#[test]
fn zero_size_image_texture_source() {
let img = Image::<Mono8>::zero(0, 0);
assert_eq!(img.texture_width(), 0);
assert_eq!(img.texture_height(), 0);
assert_eq!(img.bytes_per_row(), 0);
assert_eq!(img.texture_bytes().len(), 0);
}
#[test]
fn texture_bytes_contain_correct_pixel_data() {
let img = Image::fill(2, 1, Srgba8::new(0xAA, 0xBB, 0xCC, 0xDD));
let bytes = img.texture_bytes();
assert_eq!(bytes, &[0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD]);
}
#[test]
fn single_pixel_image_texture_bytes() {
let img = Image::fill(1, 1, Mono8::new(42));
assert_eq!(img.texture_bytes(), &[42]);
}
}