1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
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<Self, Error>
{
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,
}
|