e2rcore/implement/render/
texture.rs

1extern crate pretty_env_logger;
2extern crate image;
3extern crate num;
4
5use std::collections::HashMap;
6
7use self::image::Pixel;
8
9#[derive(Clone)]
10pub struct TextureNormalized {
11    _data: Vec<(Channel,f32)>,
12    _dim: Vec<usize>,
13    _channels: HashMap<Channel,usize>,
14    
15}
16
17#[derive(Clone)]
18#[derive(Eq)]
19#[derive(PartialEq)]
20#[derive(Hash)]
21pub enum Channel {
22    R,
23    G,
24    B,
25    A,
26}
27
28#[derive(Clone)]
29pub enum TextureBuiltin {
30    SOLID,
31    CHECKER,
32    UNKNOWN,
33}
34
35use std::ops::Index;
36
37#[derive(Clone)]
38pub struct Texture {
39    pub _data: Vec<(Channel, u8)>,
40    pub _dim: Vec<usize>,
41    pub _channels: HashMap<Channel,usize>,
42}
43
44impl Index<(usize, Channel)> for Texture {
45    type Output = u8;
46    fn index( &self, i: (usize, Channel) ) -> &u8 {
47        let tuple_index = match self._channels.get( &i.1 ) {
48            Some( &v ) => v,
49            _ => { panic!("unmatching channel detected"); },
50        };
51        &self._data[ i.0 * self._channels.len() + tuple_index ].1
52    }
53}
54
55impl Texture {
56    pub fn from< T: image::GenericImage >( img_buffer: &T ) -> Texture
57    {
58        let mut buf = vec![];
59        for (_x,_y,p) in img_buffer.pixels() {
60            let rgb = p.to_rgb();
61            let r: u8 = num::cast(rgb.data[0]).unwrap();
62            let g: u8 = num::cast(rgb.data[1]).unwrap();
63            let b: u8 = num::cast(rgb.data[2]).unwrap();
64            buf.push( ( Channel::R, r ) );
65            buf.push( ( Channel::G, g ) );
66            buf.push( ( Channel::B, b ) );
67        }
68        Texture {
69            _data: buf,
70            _dim: vec![ img_buffer.dimensions().0 as _, img_buffer.dimensions().1 as _ ],
71            _channels: [ (Channel::R, 0usize), (Channel::G, 1usize), (Channel::B, 2usize) ].iter().cloned().collect(),
72        }
73    }
74}
75
76impl From< Texture > for Vec< u8 > {
77    fn from( t: Texture ) -> Vec< u8 > {
78        let mut v = vec![];
79        for i in t._data {
80            v.push( i.1 );
81        }
82        v
83    }
84}
85
86impl TextureNormalized {
87    pub fn init_builtin( builtin: TextureBuiltin ) -> TextureNormalized {
88        match builtin {
89            TextureBuiltin::SOLID => {
90                return TextureNormalized {
91                    _data: vec![ (Channel::R, 1.0), (Channel::G, 1.0), (Channel::B, 0.0) ],
92                    _dim: vec![ 1 ],
93                    _channels: [ (Channel::R, 0usize), (Channel::G, 1usize), (Channel::B, 2usize) ].iter().cloned().collect(),
94                }
95            },
96            TextureBuiltin::CHECKER => {
97                return TextureNormalized {
98                    _data: vec![ (Channel::R, 0.0), (Channel::G, 0.0), (Channel::B, 0.0),
99                                 (Channel::R, 1.0), (Channel::G, 1.0), (Channel::B, 1.0) ],
100                    _dim: vec![ 2 ],
101                    _channels: [ (Channel::R, 0usize), (Channel::G, 1usize), (Channel::B, 2usize) ].iter().cloned().collect()
102                }
103            },
104            _ => panic!(),
105        }
106    }
107}
108
109pub fn modulate( normalized: & TextureNormalized, hm: & HashMap<Channel,u8> ) -> Texture {
110    let mut t = Texture {
111        _data: vec![],
112        _dim: normalized._dim.clone(),
113        _channels: normalized._channels.clone(),
114    };
115    for i in normalized._data.iter() {
116        match i {
117            &( ref c, ref v) => {
118                let val = match hm.get( c ){
119                    Some(&a) => a,
120                    _ => { warn!("unmatched channel, setting to 0 instead"); 0u8 },
121                };
122                t._data.push( (Channel::R, (v * val as f32) as u8 ) );
123            },
124        }
125    }
126    t
127}
128