#[cfg(feature = "image")]
extern crate image;
#[cfg(feature = "image")]
use std::path::Path;
use graphics::ImageSize;
use glium::texture::srgb_texture2d::{ SrgbTexture2d };
use glium::texture::{ RawImage2d, TextureCreationError };
use glium::backend::Facade;
#[cfg(feature = "image")]
use self::image::{ DynamicImage, RgbaImage };
use texture::{ self, TextureSettings, CreateTexture, TextureOp, UpdateTexture, Format };
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Flip {
None,
Vertical,
}
pub struct Texture(pub SrgbTexture2d);
impl Texture {
pub fn new(texture: SrgbTexture2d) -> Texture {
Texture(texture)
}
pub fn empty<F>(factory: &mut F) -> Result<Self, TextureCreationError>
where F: Facade
{
CreateTexture::create(factory, Format::Rgba8, &[0u8; 4], [1, 1], &TextureSettings::new())
}
#[cfg(feature = "image")]
pub fn from_path<F, P>(
factory: &mut F,
path: P,
flip: Flip,
settings: &TextureSettings
) -> Result<Self, String>
where F: Facade,
P: AsRef<Path>
{
let img = try!(image::open(path).map_err(|e| e.to_string()));
let img = match img {
DynamicImage::ImageRgba8(img) => img,
img => img.to_rgba()
};
let img = if flip == Flip::Vertical {
image::imageops::flip_vertical(&img)
} else {
img
};
Texture::from_image(factory, &img, settings).map_err(
|e| format!("{:?}", e))
}
#[cfg(feature = "image")]
pub fn from_image<F>(
factory: &mut F,
img: &RgbaImage,
settings: &TextureSettings
) -> Result<Self, TextureCreationError>
where F: Facade
{
let (width, height) = img.dimensions();
CreateTexture::create(factory, Format::Rgba8, img, [width, height], settings)
}
pub fn from_memory_alpha<F>(
factory: &mut F,
buffer: &[u8],
width: u32,
height: u32,
settings: &TextureSettings
) -> Result<Self, TextureCreationError>
where F: Facade
{
if width == 0 || height == 0 {
return Texture::empty(factory);
}
let size = [width, height];
let buffer = texture::ops::alpha_to_rgba8(buffer, size);
CreateTexture::create(factory, Format::Rgba8, &buffer, size, settings)
}
#[cfg(feature = "image")]
pub fn update<F>(&mut self, factory: &mut F, img: &RgbaImage)
-> Result<(), TextureCreationError>
where F: Facade
{
let (width, height) = img.dimensions();
UpdateTexture::update(self, factory, Format::Rgba8, img, [0, 0], [width, height])
}
}
impl ImageSize for Texture {
fn get_size(&self) -> (u32, u32) {
let ref tex = self.0;
(tex.get_width(), tex.get_height().unwrap())
}
}
impl<F> TextureOp<F> for Texture {
type Error = TextureCreationError;
}
impl<F> CreateTexture<F> for Texture
where F: Facade
{
fn create<S: Into<[u32; 2]>>(
factory: &mut F,
_format: Format,
memory: &[u8],
size: S,
_settings: &TextureSettings
) -> Result<Self, Self::Error> {
let size = size.into();
Ok(Texture(try!(SrgbTexture2d::new(factory,
RawImage2d::from_raw_rgba_reversed(memory,
(size[0], size[1]))))))
}
}
impl<F> UpdateTexture<F> for Texture
where F: Facade
{
#[allow(unused_variables)]
fn update<O: Into<[u32; 2]>, S: Into<[u32; 2]>>(
&mut self,
factory: &mut F,
_format: Format,
memory: &[u8],
offset: O,
size: S
) -> Result<(), Self::Error> {
use glium::Rect;
let offset = offset.into();
let size = size.into();
let (_, h) = self.get_size();
self.0.write(Rect {left: offset[0], bottom: h - offset[1] - size[1], width: size[0], height: size[1]},
RawImage2d::from_raw_rgba_reversed(memory, (size[0], size[1])));
Ok(())
}
}