use std;
use glium;
use image;
use log;
pub const CROSSHAIR_PNG_FILE_BYTES : &[u8; 101] =
include_bytes!("../crosshair.png");
pub const CROSSHAIR_INVERSE_PNG_FILE_BYTES : &[u8; 95] =
include_bytes!("../crosshair-inverse.png");
pub const TILESET_EASCII_ACORN_8X8_PNG_FILE_BYTES : &[u8; 2538] =
include_bytes!("../tileset_eascii_acorn-bbc-micro_8x8.png");
pub const TILESET_EASCII_ACORN_8X8_INVERSE_PNG_FILE_BYTES : &[u8; 2526] =
include_bytes!("../tileset_eascii_acorn-bbc-micro_8x8-inverse.png");
pub const TILESET_EASCII_ACORN_16X16_PNG_FILE_BYTES : &[u8; 3427] =
include_bytes!("../tileset_eascii_acorn-bbc-micro_16x16.png");
pub const TILESET_EASCII_ACORN_16X16_INVERSE_PNG_FILE_BYTES : &[u8; 3427] =
include_bytes!("../tileset_eascii_acorn-bbc-micro_16x16-inverse.png");
pub const POINTER_HAND_PNG_FILE_BYTES_OFFSET : (&[u8; 183], [i16; 2]) =
(include_bytes!("../pointer-hand.png"), [3, -10]);
#[derive(Debug)]
pub enum LoadError {
IoError (std::io::Error),
ImageError (image::ImageError),
TextureCreationError (glium::texture::TextureCreationError)
}
pub fn texture2d_with_mipmaps_from_bytes (
glium_facade : &dyn glium::backend::Facade,
bytes : &[u8],
image_format : image::ImageFormat,
mipmaps : glium::texture::MipmapsOption
) -> Result <glium::Texture2d, LoadError> {
let img = image::load_from_memory_with_format (bytes, image_format)?
.to_rgba8();
let img_dimensions = img.dimensions();
log::debug!(dimensions:?=img_dimensions; "texture load bytes");
let raw_image_2d = glium::texture::RawImage2d::from_raw_rgba_reversed (
img.into_raw().as_slice(),
img_dimensions);
glium::Texture2d::with_mipmaps (glium_facade, raw_image_2d, mipmaps)
.map_err (Into::into)
}
pub fn texture2d_with_mipmaps_from_file (
glium_facade : &dyn glium::backend::Facade,
filepath : &'static str,
image_format : image::ImageFormat,
mipmaps : glium::texture::MipmapsOption
) -> Result <glium::Texture2d, LoadError> {
log::debug!(filepath:?; "texture load file");
let bytes = std::fs::read (filepath)?;
texture2d_with_mipmaps_from_bytes (
glium_facade, bytes.as_slice(), image_format, mipmaps)
}
pub fn texture2darray_with_mipmaps_from_bytes (
glium_facade : &dyn glium::backend::Facade,
bytes_slices : &[&[u8]],
image_format : image::ImageFormat,
mipmaps : glium::texture::MipmapsOption
) -> Result <glium::texture::Texture2dArray, LoadError> {
let raw_images = {
let mut v = Vec::with_capacity (bytes_slices.len());
for bytes in bytes_slices {
let img = image::load_from_memory_with_format (bytes, image_format)?
.to_rgba8();
let img_dimensions = img.dimensions();
log::debug!(dimensions:?=img_dimensions; "texture array load bytes");
let raw_image_2d = glium::texture::RawImage2d::from_raw_rgba_reversed (
img.into_raw().as_slice(),
img_dimensions);
v.push (raw_image_2d);
}
v
};
glium::texture::Texture2dArray::with_mipmaps (
glium_facade, raw_images, mipmaps
).map_err (Into::into)
}
pub fn texture2darray_with_mipmaps_from_files (
glium_facade : &dyn glium::backend::Facade,
filepaths : &[&'static str],
image_format : image::ImageFormat,
mipmaps : glium::texture::MipmapsOption
) -> Result <glium::texture::Texture2dArray, LoadError> {
if filepaths.is_empty() {
return Err (std::io::Error::new (std::io::ErrorKind::InvalidInput,
"no input paths provided").into())
}
let bytes = {
let mut v = Vec::with_capacity (filepaths.len());
v.resize_with (filepaths.len(), Default::default);
for (i, filepath) in filepaths.iter().enumerate() {
log::debug!(filepath:?; "texture load file");
v[i] = std::fs::read (filepath)?;
}
v
};
let bytes_vec = {
let mut v = Vec::with_capacity (filepaths.len());
for bytes in bytes.iter() {
v.push (bytes.as_slice());
}
v
};
let texture2darray = texture2darray_with_mipmaps_from_bytes (
glium_facade, &bytes_vec, image_format, mipmaps)?;
Ok (texture2darray)
}
impl std::fmt::Display for LoadError {
fn fmt (&self, f : &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
LoadError::IoError (err) => write!(f, "I/O error: {err}"),
LoadError::ImageError (err) => err.fmt (f),
LoadError::TextureCreationError (err) => err.fmt (f)
}
}
}
impl std::error::Error for LoadError {
fn source (&self) -> Option <&(dyn std::error::Error + 'static)> {
match self {
LoadError::IoError (err) => err.source(),
LoadError::ImageError (err) => err.source(),
LoadError::TextureCreationError (err) => err.source()
}
}
}
impl From <std::io::Error> for LoadError {
fn from (err : std::io::Error) -> Self {
LoadError::IoError (err)
}
}
impl From <image::ImageError> for LoadError {
fn from (err : image::ImageError) -> Self {
LoadError::ImageError (err)
}
}
impl From <glium::texture::TextureCreationError> for LoadError {
fn from (err : glium::texture::TextureCreationError) -> Self {
LoadError::TextureCreationError (err)
}
}