e2rcore/implement/render/
texture.rs1extern 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