Browse Source

Added some utils + Farbfeld reader

Getty Ritter 5 years ago
parent
commit
cb6940ec5d
5 changed files with 113 additions and 7 deletions
  1. 75 0
      therm_model/src/farbfeld.rs
  2. 1 0
      therm_model/src/lib.rs
  3. 1 0
      therm_util/Cargo.toml
  4. 2 0
      therm_util/src/lib.rs
  5. 34 7
      therm_util/src/reader.rs

+ 75 - 0
therm_model/src/farbfeld.rs

@@ -0,0 +1,75 @@
+use glium::texture::{RawImage2d,Texture2dDataSource};
+use therm_util::reader::ByteReader;
+
+#[derive(Debug,Clone)]
+pub struct FFImage {
+    pixels: Vec<Vec<(u16,u16,u16,u16)>>
+}
+
+fn parse_pixel<Rd>(r: &mut ByteReader<Rd>) -> Result<(u16,u16,u16,u16), String>
+    where Rd: Iterator<Item=u8>
+{
+    Ok((try!(r.read_u16be()),
+        try!(r.read_u16be()),
+        try!(r.read_u16be()),
+        try!(r.read_u16be())))
+}
+
+impl FFImage {
+    pub fn from_bz2_file(path: &str) -> Result<FFImage, String> {
+        let mut r = match ByteReader::from_compressed_file(path) {
+            Ok(x) => x,
+            Err(_) => return Err("Unable to open file".to_string()),
+        };
+        FFImage::from_reader(&mut r)
+    }
+
+    pub fn from_file(path: &str) -> Result<FFImage, String> {
+        let mut r = match ByteReader::from_file(path) {
+            Ok(x) => x,
+            Err(_) => return Err("Unable to open file".to_string()),
+        };
+        FFImage::from_reader(&mut r)
+    }
+
+
+    pub fn from_reader<Rd>(r: &mut ByteReader<Rd>) -> Result<FFImage, String>
+        where Rd: Iterator<Item=u8>
+    {
+        assert!(try!(r.next()) == 'f' as u8);
+        assert!(try!(r.next()) == 'a' as u8);
+        assert!(try!(r.next()) == 'r' as u8);
+        assert!(try!(r.next()) == 'b' as u8);
+        assert!(try!(r.next()) == 'f' as u8);
+        assert!(try!(r.next()) == 'e' as u8);
+        assert!(try!(r.next()) == 'l' as u8);
+        assert!(try!(r.next()) == 'd' as u8);
+
+        let w = try!(r.read_u32be());
+        let h = try!(r.read_u32be());
+
+        let mut pixels = vec![];
+        for _ in 0..h {
+            let mut row = vec![];
+            for _ in 0..w {
+                row.push(try!(parse_pixel(r)));
+            }
+            pixels.push(row)
+        }
+        pixels.reverse();
+
+        Ok(FFImage { pixels: pixels })
+    }
+
+    pub fn get_raw_data(self) -> Vec<Vec<(u16,u16,u16,u16)>> {
+        self.pixels
+    }
+}
+
+impl <'a> Texture2dDataSource<'a> for FFImage {
+    type Data = (u16, u16, u16, u16);
+
+    fn into_raw(self) -> RawImage2d<'a, (u16, u16, u16, u16)> {
+        self.pixels.into_raw()
+    }
+}

+ 1 - 0
therm_model/src/lib.rs

@@ -6,6 +6,7 @@ extern crate therm_util;
 
 pub mod model;
 pub mod graph;
+pub mod farbfeld;
 
 #[cfg(test)]
 mod tests {

+ 1 - 0
therm_util/Cargo.toml

@@ -4,3 +4,4 @@ version = "0.1.0"
 authors = ["Getty Ritter <gdritter@galois.com>"]
 
 [dependencies]
+bzip2="*"

+ 2 - 0
therm_util/src/lib.rs

@@ -1,3 +1,5 @@
+extern crate bzip2;
+
 pub mod adnot;
 pub mod reader;
 

+ 34 - 7
therm_util/src/reader.rs

@@ -1,4 +1,5 @@
-use std::{fs,io,iter,slice,vec};
+use std::{fs,io,iter,mem,slice,vec};
+use bzip2::bufread::BzDecoder;
 
 /// A `ByteReader` is just a tiny wrapper over a mutable byte iterator, so we
 /// can parse things more easily.
@@ -6,9 +7,7 @@ pub struct ByteReader<Rd> {
     bytes: Rd,
 }
 
-impl<R: io::Read>
-    ByteReader<iter::FilterMap<io::Bytes<R>,
-                               &'static Fn(io::Result<u8>) -> Option<u8>>>
+impl<R: io::Read> ByteReader<iter::FilterMap<io::Bytes<R>, &'static Fn(io::Result<u8>) -> Option<u8>>>
 {
     /// Create a ByteReader from any type that implement Read
     pub fn from_reader(r: R) -> Self {
@@ -35,11 +34,23 @@ impl ByteReader<vec::IntoIter<u8>> {
     }
 }
 
-impl<'a> ByteReader<iter::Map<slice::Iter<'a, u8>, &'static Fn(&u8) -> u8>> {
+impl<'a> ByteReader<iter::Cloned<slice::Iter<'a, u8>>> {
     /// Create a reader from a borrowed slice, with a copy on each access
     pub fn from_slice(lst: &'a [u8]) -> Self {
-        const DEREF: &'static Fn(&u8) -> u8 = &|s| *s;
-        ByteReader { bytes: lst.iter().map(DEREF) }
+        ByteReader { bytes: lst.iter().cloned() }
+    }
+}
+
+impl<R: io::BufRead> ByteReader<iter::FilterMap<io::Bytes<BzDecoder<R>>, &'static Fn(io::Result<u8>) -> Option<u8>>> {
+    pub fn from_compressed_reader(r: R) -> Self {
+        ByteReader::from_reader(BzDecoder::new(r))
+    }
+}
+
+impl ByteReader<iter::FilterMap<io::Bytes<BzDecoder<io::BufReader<fs::File>>>, &'static Fn(io::Result<u8>) -> Option<u8>>> {
+    pub fn from_compressed_file(path: &str) -> io::Result<Self> {
+        let f = try!(fs::File::open(path));
+        Ok(ByteReader::from_compressed_reader(io::BufReader::new(f)))
     }
 }
 
@@ -81,6 +92,22 @@ impl<T> ByteReader<T> where T: Iterator<Item=u8> {
         Ok(b as f32 / 255.0)
     }
 
+    pub fn read_u32be(&mut self) -> Result<u32, String> {
+        let a = try!(self.next());
+        let b = try!(self.next());
+        let c = try!(self.next());
+        let d = try!(self.next());
+        let rs = [ d, c, b, a ];
+        unsafe { Ok(mem::transmute::<[u8;4],u32>(rs)) }
+    }
+
+    pub fn read_u16be(&mut self) -> Result<u16, String> {
+        let a = try!(self.next());
+        let b = try!(self.next());
+        let rs = [ b, a ];
+        unsafe { Ok(mem::transmute::<[u8;2],u16>(rs)) }
+    }
+
     /// This reads a 64-bit int with a packed PrefixInteger representation.
     /// The shorter the int, the shorter the representation.
     pub fn read_prefix_int(&mut self) -> Result<u64, String> {