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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
use std::collections::HashMap; extern crate image; extern crate num; use self::image::Pixel; #[derive(Clone)] pub struct TextureNormalized { _data: Vec<(Channel,f32)>, _dim: Vec<usize>, _channels: HashMap<Channel,usize>, } #[derive(Clone)] #[derive(Eq)] #[derive(PartialEq)] #[derive(Hash)] pub enum Channel { R, G, B, A, } #[derive(Clone)] pub enum TextureBuiltin { SOLID, CHECKER, UNKNOWN, } use std::ops::Index; #[derive(Clone)] pub struct Texture { pub _data: Vec<(Channel, u8)>, pub _dim: Vec<usize>, pub _channels: HashMap<Channel,usize>, } impl Index<(usize, Channel)> for Texture { type Output = u8; fn index( &self, i: (usize, Channel) ) -> &u8 { let tuple_index = match self._channels.get( &i.1 ) { Some( &v ) => v, _ => { panic!("unmatching channel detected"); }, }; &self._data[ i.0 * self._channels.len() + tuple_index ].1 } } impl Texture { pub fn from< T: image::GenericImage >( img_buffer: &T ) -> Texture { let mut buf = vec![]; for (_x,_y,p) in img_buffer.pixels() { let rgb = p.to_rgb(); let r: u8 = num::cast(rgb.data[0]).unwrap(); let g: u8 = num::cast(rgb.data[1]).unwrap(); let b: u8 = num::cast(rgb.data[2]).unwrap(); buf.push( ( Channel::R, r ) ); buf.push( ( Channel::G, g ) ); buf.push( ( Channel::B, b ) ); } Texture { _data: buf, _dim: vec![ img_buffer.dimensions().0 as _, img_buffer.dimensions().1 as _ ], _channels: [ (Channel::R, 0usize), (Channel::G, 1usize), (Channel::B, 2usize) ].iter().cloned().collect(), } } } impl From< Texture > for Vec< u8 > { fn from( t: Texture ) -> Vec< u8 > { let mut v = vec![]; for i in t._data { v.push( i.1 ); } v } } impl TextureNormalized { pub fn init_builtin( builtin: TextureBuiltin ) -> TextureNormalized { match builtin { TextureBuiltin::SOLID => { return TextureNormalized { _data: vec![ (Channel::R, 1.0), (Channel::G, 1.0), (Channel::B, 0.0) ], _dim: vec![ 1 ], _channels: [ (Channel::R, 0usize), (Channel::G, 1usize), (Channel::B, 2usize) ].iter().cloned().collect(), } }, TextureBuiltin::CHECKER => { return TextureNormalized { _data: vec![ (Channel::R, 0.0), (Channel::G, 0.0), (Channel::B, 0.0), (Channel::R, 1.0), (Channel::G, 1.0), (Channel::B, 1.0) ], _dim: vec![ 2 ], _channels: [ (Channel::R, 0usize), (Channel::G, 1usize), (Channel::B, 2usize) ].iter().cloned().collect() } }, _ => panic!(), } } } pub fn modulate( normalized: & TextureNormalized, hm: & HashMap<Channel,u8> ) -> Texture { let mut t = Texture { _data: vec![], _dim: normalized._dim.clone(), _channels: normalized._channels.clone(), }; for i in normalized._data.iter() { match i { &( ref c, ref v) => { let val = match hm.get( c ){ Some(&a) => a, _ => { println!("unmatched channel, setting to 0 instead"); 0u8 }, }; t._data.push( (Channel::R, (v * val as f32) as u8 ) ); }, } } t }