use std::path::Path; use image::io::Reader as ImageReader; use image::{DynamicImage, ImageError}; use crate::opengl::texture::{PixelDataFormat, Texture as InnerTexture}; use crate::vector::Vec2; mod reexports { pub use crate::opengl::texture::{Filtering, Wrapping}; } pub use reexports::*; #[derive(Debug)] pub struct Texture { inner: InnerTexture, } impl Texture { /// Opens a texture image. /// /// # Errors /// Will return `Err` if: /// - Opening the image fails /// - The image data is not 8-bit/color RGB #[allow(clippy::new_without_default)] pub fn open(path: &Path) -> Result { let image = ImageReader::open(path) .map_err(Error::OpenImageFailed)? .decode() .map_err(Error::DecodeImageFailed)?; let pixel_data_format = match &image { DynamicImage::ImageRgb8(_) => PixelDataFormat::Rgb, DynamicImage::ImageRgba8(_) => PixelDataFormat::Rgba, _ => { return Err(Error::UnsupportedImageDataKind); } }; let inner = InnerTexture::new(); inner.bind(|texture_curr_bound| { InnerTexture::generate( &texture_curr_bound, &Vec2 { x: image.width(), y: image.height() }, image.as_bytes(), pixel_data_format, ); }); let me = Self { inner }; me.set_wrap(Wrapping::Repeat); me.set_magnifying_filter(Filtering::Linear); me.set_minifying_filter(Filtering::Nearest); Ok(me) } pub fn set_wrap(&self, wrapping: Wrapping) { self.inner.bind(|texture_curr_bound| { InnerTexture::set_wrap(texture_curr_bound, wrapping); }); } pub fn set_magnifying_filter(&self, filtering: Filtering) { self.inner.bind(|texture_curr_bound| { InnerTexture::set_magnifying_filter(texture_curr_bound, filtering); }); } pub fn set_minifying_filter(&self, filtering: Filtering) { self.inner.bind(|texture_curr_bound| { InnerTexture::set_minifying_filter(texture_curr_bound, filtering); }); } pub(crate) fn inner(&self) -> &InnerTexture { &self.inner } } /// Texture error. #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Failed to open texture image")] OpenImageFailed(#[source] std::io::Error), #[error("Failed to decode texture image")] DecodeImageFailed(#[source] ImageError), #[error("Unsupported image data kind")] UnsupportedImageDataKind, }