fax-0.2.0/.gitignore000064400000000000000000000000230072674642500124140ustar 00000000000000/target Cargo.lock fax-0.2.0/Cargo.lock0000644000000024570000000000100075740ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "fax" version = "0.2.0" dependencies = [ "fax_derive", ] [[package]] name = "fax_derive" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c1d7ffc9f2dc8316348c75281a99c8fdc60c1ddf4f82a366d117bf1b74d5a39" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "proc-macro2" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ "unicode-xid", ] [[package]] name = "quote" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2", ] [[package]] name = "syn" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" fax-0.2.0/Cargo.toml0000644000000015340000000000100076120ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "fax" version = "0.2.0" authors = ["Sebastian K "] description = "Decoder and Encoder for CCITT Group 3 and 4 bi-level image encodings used by fax machines TIFF and PDF." keywords = [ "CCITT", "fax", "CCITTFaxDecode", ] license = "MIT" repository = "https://github.com/pdf-rs/fax" [dependencies.fax_derive] version = "0.1.0" fax-0.2.0/Cargo.toml.orig0000644000000006210000000000100105450ustar [package] name = "fax" version = "0.2.0" authors = ["Sebastian K "] edition = "2018" description = "Decoder and Encoder for CCITT Group 3 and 4 bi-level image encodings used by fax machines TIFF and PDF." license = "MIT" keywords = ["CCITT", "fax", "CCITTFaxDecode"] repository = "https://github.com/pdf-rs/fax" [dependencies] fax_derive = { version = "0.1.0", path = "derive" } fax-0.2.0/Cargo.toml.orig000064400000000000000000000006210072674642500133170ustar 00000000000000[package] name = "fax" version = "0.2.0" authors = ["Sebastian K "] edition = "2018" description = "Decoder and Encoder for CCITT Group 3 and 4 bi-level image encodings used by fax machines TIFF and PDF." license = "MIT" keywords = ["CCITT", "fax", "CCITTFaxDecode"] repository = "https://github.com/pdf-rs/fax" [dependencies] fax_derive = { version = "0.1.0", path = "derive" } fax-0.2.0/README.md000064400000000000000000000001710072674642500117070ustar 00000000000000# CCITT Group 3 and 4 image encodings. Currently supported: - de- and encoding group 4 images - decoding group 3 images fax-0.2.0/examples/bitdiff.rs000064400000000000000000000016560072674642500142340ustar 00000000000000use fax::{BitWriter, Bits, ByteReader, BitReader}; use std::fs; struct Validator> { reader: ByteReader } impl> BitWriter for Validator { fn write(&mut self, bits: Bits) { let expected = Bits { data: self.reader.peek(bits.len).unwrap(), len: bits.len }; assert_eq!(expected, bits); self.reader.consume(bits.len); } } fn main() { let mut args = std::env::args().skip(1); let a = fs::read(&args.next().unwrap()).unwrap(); let b = fs::read(&args.next().unwrap()).unwrap(); for (i, (&a, &b)) in a.iter().zip(b.iter()).enumerate() { if a != b { println!("mismatch at byte {}: {:08b} vs. {:08b}", i, a, b); break; } } if a.len() > b.len() { println!("a has additional {:?}", &a[b.len()..]); } if b.len() > a.len() { println!("b has additional {:?}", &b[a.len()..]); } } fax-0.2.0/examples/fax2pbm.rs000064400000000000000000000021000072674642500141450ustar 00000000000000use fax::{VecWriter, decoder, decoder::pels, BitWriter, Bits, Color}; use std::io::Write; use std::fs::{self, File}; fn main() { let mut args = std::env::args().skip(1); let input: String = args.next().unwrap(); let width: u16 = args.next().unwrap().parse().unwrap(); let output = args.next().unwrap(); let data = fs::read(&input).unwrap(); let mut writer = VecWriter::new(); let mut height = 0; decoder::decode_g4(data.iter().cloned(), width, |transitions| { for c in pels(transitions, width) { let bit = match c { Color::Black => Bits { data: 1, len: 1 }, Color::White => Bits { data: 0, len: 1 } }; writer.write(bit); } writer.pad(); height += 1; }); let data = writer.finish(); assert_eq!(data.len(), height as usize * ((width as usize + 7) / 8)); let header = format!("P4\n{} {}\n", width, height); let mut out = File::create(&output).unwrap(); out.write_all(header.as_bytes()).unwrap(); out.write_all(&data).unwrap(); }fax-0.2.0/examples/pbm2fax.rs000064400000000000000000000021560072674642500141600ustar 00000000000000use fax::{VecWriter, encoder::Encoder, Color, ByteReader, tiff}; use std::fs; fn main() { let mut args = std::env::args().skip(1); let input: String = args.next().unwrap(); let output = args.next().unwrap(); let data = fs::read(&input).unwrap(); let mut parts = data.splitn(3, |&b| b == b'\n'); assert_eq!(parts.next().unwrap(), b"P4"); let mut size = parts.next().unwrap().splitn(2, |&b| b == b' '); let width: u32 = std::str::from_utf8(size.next().unwrap()).unwrap().parse().unwrap(); let height: u32 = std::str::from_utf8(size.next().unwrap()).unwrap().parse().unwrap(); let writer = VecWriter::new(); let mut encoder = Encoder::new(writer); for line in parts.next().unwrap().chunks((width as usize + 7) / 8) { let line = ByteReader::new(line.iter().cloned()).into_bits().take(width as usize) .map(|b| match b { false => Color::White, true => Color::Black }); encoder.encode_line(line, width as u16); } let data = encoder.finish().finish(); fs::write(&output, &tiff::wrap(&data, width, height)).unwrap(); } fax-0.2.0/examples/validate.rs000064400000000000000000000031450072674642500144110ustar 00000000000000use fax::{encoder::Encoder, BitWriter, Bits, Color, ByteReader, BitReader}; use std::fs; fn main() { let mut args = std::env::args().skip(1); let input: String = args.next().unwrap(); let output = args.next().unwrap(); let data = fs::read(&input).unwrap(); let reference_data = fs::read(&output).unwrap(); let mut parts = data.splitn(3, |&b| b == b'\n'); assert_eq!(parts.next().unwrap(), b"P4"); let mut size = parts.next().unwrap().splitn(2, |&b| b == b' '); let width: u16 = std::str::from_utf8(size.next().unwrap()).unwrap().parse().unwrap(); //let writer = VecWriter::new(); let writer = Validator { reader: ByteReader::from_slice(&reference_data) }; let mut encoder = Encoder::new(writer); for (y, line) in parts.next().unwrap().chunks((width as usize + 7) / 8).enumerate() { println!("\nline {}", y); let line = ByteReader::new(line.iter().cloned()).into_bits().take(width as usize) .map(|b| match b { false => Color::Black, true => Color::White }); encoder.encode_line(line, width); } let mut writer = encoder.finish(); writer.reader.print_remaining(); //let (data, _) = encoder.into_writer().finish(); //fs::write(&output, &data).unwrap(); } struct Validator> { reader: ByteReader } impl> BitWriter for Validator { fn write(&mut self, bits: Bits) { let expected = Bits { data: self.reader.peek(bits.len).unwrap(), len: bits.len }; assert_eq!(expected, bits); self.reader.consume(bits.len); } }fax-0.2.0/src/decoder.rs000064400000000000000000000131100072674642500131670ustar 00000000000000use crate::{ByteReader, BitReader, Color, Transitions}; use crate::maps::{Mode, black, white, mode, EDFB_HALF, EOL}; fn with_markup(decoder: D, reader: &mut R) -> Option where D: Fn(&mut R) -> Option { let mut sum = 0; while let Some(n) = decoder(reader) { //print!("{} ", n); sum += n; if n < 64 { //println!("= {}", sum); return Some(sum) } } None } fn colored(current: Color, reader: &mut impl BitReader) -> Option { //print!("{:?} ", current); match current { Color::Black => with_markup(black::decode, reader), Color::White => with_markup(white::decode, reader), } } /// Turn a list of color changing position into an iterator of pixel colors /// /// The width of the line/image has to be given in `width`. /// The iterator will produce exactly that many items. pub fn pels(line: &[u16], width: u16) -> impl Iterator + '_ { use std::iter::{repeat}; let mut color = Color::White; let mut last = 0; line.iter().flat_map(move |&p| { let c = color; color = !color; let n = p.saturating_sub(last); last = p; repeat(c).take(n as usize) }).chain(repeat(color)).take(width as usize) } /// Decode a Group 3 encoded image. /// /// The callback `line_cb` is called for each decoded line. /// The argument is the list of positions of color change, starting with white. /// /// To obtain an iterator over the pixel colors, the `pels` function is provided. pub fn decode_g3(input: impl Iterator, mut line_cb: impl FnMut(&[u16])) -> Option<()> { let mut reader = ByteReader::new(input); let mut current = vec![]; reader.expect(EOL).unwrap(); 'a: loop { let mut a0 = 0; let mut color = Color::White; while let Some(p) = colored(color, &mut reader) { a0 += p; current.push(a0); color = !color; } reader.expect(EOL).unwrap(); line_cb(¤t); current.clear(); for _ in 0 .. 6 { if reader.peek(EOL.len) == Some(EOL.data) { reader.consume(EOL.len); } else { continue 'a; } } break; } Some(()) } /// Decode a Group 4 Image /// /// - `width` is the width of the image. /// - The callback `line_cb` is called for each decoded line. /// The argument is the list of positions of color change, starting with white. /// /// If `height` is specified, at most that many lines will be decoded, /// otherwise data is decoded until the end-of-block marker (or end of data). /// /// To obtain an iterator over the pixel colors, the `pels` function is provided. pub fn decode_g4(input: impl Iterator, width: u16, height: Option, mut line_cb: impl FnMut(&[u16])) -> Option<()> { let mut reader = ByteReader::new(input); let mut reference: Vec = vec![]; let mut current: Vec = vec![]; let limit = height.unwrap_or(u16::MAX); 'outer: for _ in 0 .. limit { let mut transitions = Transitions::new(&reference); let mut a0 = 0; let mut color = Color::White; //println!("\n\nline {}", y); loop { //reader.print(); let mode = match mode::decode(&mut reader) { Some(mode) => mode, None => break 'outer, }; //println!("{:?}, color={:?}, a0={}", mode, color, a0); match mode { Mode::Pass => { let _ = transitions.next_color(a0, !color)?; //println!("b1={}", b1); if let Some(b2) = transitions.next() { //println!("b2={}", b2); a0 = b2; } } Mode::Vertical(delta) => { let b1 = match transitions.next_color(a0, !color) { Some(p) => p, None => break }; let a1 = (b1 as i16 + delta as i16) as u16; //println!("transition to {:?} at {}", !color, a1); current.push(a1); color = !color; a0 = a1; if delta < 0 { transitions.seek_back(a0); } } Mode::Horizontal => { let a0a1 = colored(color, &mut reader)?; let a1a2 = colored(!color, &mut reader)?; let a1 = a0 + a0a1; let a2 = a1 + a1a2; //println!("a0a1={}, a1a2={}, a1={}, a2={}", a0a1, a1a2, a1, a2); current.push(a1); if a2 >= width { break; } current.push(a2); a0 = a2; } Mode::Extension => { let _xxx = reader.peek(3)?; //println!("extension: {:03b}", xxx); reader.consume(3); //println!("{:?}", current); break 'outer; } } if a0 >= width { break; } } //println!("{:?}", current); line_cb(¤t); std::mem::swap(&mut reference, &mut current); current.clear(); } if height.is_none() { reader.expect(EDFB_HALF).ok()?; reader.expect(EDFB_HALF).ok()?; } //reader.print(); Some(()) } fax-0.2.0/src/encoder.rs000064400000000000000000000107320072674642500132100ustar 00000000000000use crate::{Color, BitWriter, Transitions, maps::{Mode, mode, black, white, EDFB_HALF}}; fn absdiff(a: u16, b: u16) -> u16 { if a > b { a - b } else { b - a } } pub struct Encoder { writer: W, reference: Vec, current: Vec, } fn encode_color(writer: &mut impl BitWriter, color: Color, mut n: u16) { let table = match color { Color::White => &white::ENTRIES, Color::Black => &black::ENTRIES, }; let mut write = |n: u16| { let idx = if n >= 64 { 63 + n / 64 } else { n } as usize; let (v, bits) = table[idx]; assert_eq!(v, n); //println!("{}", n); writer.write(bits); }; while n >= 2560 { write(2560); n -= 2560; } if n >= 64 { let d = n & !63; write(d); n -= d; } write(n); } impl Encoder { pub fn new(writer: W) -> Self { Encoder { writer, reference: vec![], current: vec![], } } pub fn encode_line(&mut self, pels: impl Iterator, width: u16) { let mut color = Color::White; let mut transitions = Transitions::new(&self.reference); let mut a0 = 0; let mut pels = pels.enumerate() .scan(Color::White, |state, (i, c)| { Some(if c != *state { *state = c; Some(i as u16) } else { None }) }).filter_map(|x| x); let writer = &mut self.writer; self.current.clear(); while let Some(a1) = pels.next() { //println!("a1={}", a1); self.current.push(a1); loop { transitions.seek_back(a0); let b1 = transitions.next_color(a0, !color); let b2 = transitions.peek(); //println!("b1={:?}, b2={:?}", b1, b2); match (b1, b2) { (Some(_b1), Some(b2)) if b2 < a1 => { //println!("Pass"); let bits = mode::encode(Mode::Pass).unwrap(); writer.write(bits); transitions.skip(1); a0 = b2; continue; } (Some(b1), _) if absdiff(a1, b1) <= 3 => { let delta = a1 as i16 - b1 as i16; //println!("Vertical({})", delta); let bits = mode::encode(Mode::Vertical(delta as i8)).unwrap(); writer.write(bits); a0 = a1; color = !color; } _ => { let a2 = match pels.next() { Some(a2) => { self.current.push(a2); a2 }, None => width }; let bits = mode::encode(Mode::Horizontal).unwrap(); writer.write(bits); let a0a1 = a1 - a0; let a1a2 = a2 - a1; //println!("Horizontal({}, {})", a0a1, a1a2); encode_color(writer, color, a0a1); encode_color(writer, !color, a1a2); a0 = a2; } } break; } } transitions.seek_back(a0); loop { let b1 = transitions.next_color(a0, !color); let b2 = transitions.peek(); //println!("b1={:?}, b2={:?}", b1, b2); if let Some(b1) = b1 { //println!("Pass"); let bits = mode::encode(Mode::Pass).unwrap(); writer.write(bits); transitions.skip(1); if let Some(b2) = b2 { a0 = b2; } else { a0 = b1; break; } } else { break; } } if a0 < width { //println!("Vertical(0)"); let bits = mode::encode(Mode::Vertical(0)).unwrap(); writer.write(bits); } std::mem::swap(&mut self.reference, &mut self.current); } pub fn finish(mut self) -> W { self.writer.write(EDFB_HALF); self.writer.write(EDFB_HALF); self.writer } }fax-0.2.0/src/lib.rs000064400000000000000000000145400072674642500123400ustar 00000000000000use std::ops::Not; use std::fmt; mod maps; /// Decoder module pub mod decoder; /// Encoder module pub mod encoder; /// TIFF helper functions pub mod tiff; /// Trait used to read data bitwise. /// /// For lazy people `ByteReader` is provided which implements this trait. pub trait BitReader { /// look at the next (up to 16) bits of data /// /// Data is returned in the lower bits of the `u16`. fn peek(&self, bits: u8) -> Option; /// Consume the given amount of bits from the input. fn consume(&mut self, bits: u8); /// Assert that the next bits matches the given pattern. /// /// If it does not match, the found pattern is returned if enough bits are aviable. /// Otherwise None is returned. fn expect(&mut self, bits: Bits) -> Result<(), Option> { match self.peek(bits.len) { None => Err(None), Some(val) if val == bits.data => Ok(()), Some(val) => Err(Some(Bits { data: val, len: bits.len })) } } } /// Trait to write data bitwise /// /// The `VecWriter` struct is provided for convinience. pub trait BitWriter { fn write(&mut self, bits: Bits); } pub struct VecWriter { data: Vec, partial: u32, len: u8 } impl BitWriter for VecWriter { fn write(&mut self, bits: Bits) { self.partial |= (bits.data as u32) << (32 - self.len - bits.len); self.len += bits.len; while self.len >= 8 { self.data.push((self.partial >> 24) as u8); self.partial <<= 8; self.len -= 8; } } } impl VecWriter { pub fn new() -> Self { VecWriter { data: Vec::new(), partial: 0, len: 0 } } // with capacity of `n` bits. pub fn with_capacity(n: usize) -> Self { VecWriter { data: Vec::with_capacity((n + 7) / 8), partial: 0, len: 0 } } /// Pad the output with `0` bits until it is at a byte boundary. pub fn pad(&mut self) { if self.len > 0 { self.data.push((self.partial >> 24) as u8); self.partial = 0; self.len = 0; } } /// pad and return the accumulated bytes pub fn finish(mut self) -> Vec { self.pad(); self.data } } pub struct ByteReader { read: R, partial: u32, valid: u8, } impl> ByteReader { /// Construct a new `ByteReader` from an iterator of `u8` pub fn new(read: R) -> Self { let mut bits = ByteReader { read, partial: 0, valid: 0 }; bits.fill(); bits } fn fill(&mut self) { while self.valid < 16 { if let Some(byte) = self.read.next() { self.partial = self.partial << 8 | byte as u32; self.valid += 8; } else { break } } } } impl<'a> ByteReader>> { /// Construct a new `ByteReader` from a slice of bytes. pub fn from_slice(slice: &'a [u8]) -> Self { ByteReader::new(slice.iter().cloned()) } } impl<'a, R: Iterator + 'a> ByteReader { /// Turn the reader into an iterator of bits. /// /// Yields one `bool` per bit, `1=true` and `0=false`. pub fn into_bits(mut self) -> impl Iterator + 'a { std::iter::from_fn(move || { let bit = self.peek(1)? == 1; self.consume(1); Some(bit) }) } /// Print the remaining data /// /// Note: For debug purposes only, not part of the API. pub fn print_remaining(&mut self) { println!("partial: {:0w$b}, valid: {}", self.partial, self.valid, w=self.valid as usize); for b in self.read.by_ref() { print!("{:08b} ", b); } println!(); } } impl> BitReader for ByteReader { fn peek(&self, bits: u8) -> Option { assert!(bits <= 16); if self.valid >= bits { let shift = self.valid - bits; let out = (self.partial >> shift) as u16; Some(out) } else { None } } fn consume(&mut self, bits: u8) { self.valid -= bits; self.partial &= (1< Self { match self { Color::Black => Color::White, Color::White => Color::Black, } } } struct Transitions<'a> { edges: &'a [u16], pos: usize } impl<'a> Transitions<'a> { fn new(edges: &'a [u16]) -> Self { Transitions { edges, pos: 0 } } fn seek_back(&mut self, start: u16) { while self.pos > 0 { if start < self.edges[self.pos-1] { self.pos -= 1; } else { break; } } } fn next_color(&mut self, start: u16, color: Color) -> Option { while self.pos < self.edges.len() { if self.edges[self.pos] <= start { self.pos += 1; continue; } if (self.pos % 2 == 0) != (color == Color::Black) { self.pos += 1; } break; } if self.pos < self.edges.len() { let val = self.edges[self.pos]; self.pos += 1; Some(val) } else { None } } fn next(&mut self) -> Option { if self.pos < self.edges.len() { let val = self.edges[self.pos]; self.pos += 1; Some(val) } else { None } } fn peek(&self) -> Option { self.edges.get(self.pos).cloned() } fn skip(&mut self, n: usize) { self.pos += n; } } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Bits { pub data: u16, pub len: u8 } impl fmt::Debug for Bits { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "d={:0b} w={}", self.data, self.len) } } fax-0.2.0/src/maps.rs000064400000000000000000000161640072674642500125360ustar 00000000000000use fax_derive::bitmaps; use crate::{BitReader, Bits}; enum Entry { Empty, Leaf(u8, &'static [Option<(T, u8)>]), Value(T, u8), Prefix(u8, &'static [Entry]) } impl Entry { fn find(&self, reader: &mut impl BitReader) -> Option { match *self { Entry::Empty => None, Entry::Value(val, len) => { reader.consume(len); Some(val) } Entry::Leaf(width, lut) => { let index = reader.peek(width)?; let (val, len) = lut[index as usize]?; reader.consume(len); Some(val) } Entry::Prefix(width, lut) => { let index = reader.peek(width)?; let entry = &lut[index as usize]; match *entry { Entry::Empty => None, Entry::Value(val, len) => { reader.consume(len); Some(val) } _ => { reader.consume(width); entry.find(reader) } } } } } } pub const EDFB_HALF: Bits = Bits { data: 1, len: 12 }; pub const EOL: Bits = Bits { data: 1, len: 12 }; #[derive(Copy, Clone, Debug)] pub enum Mode { Pass, Horizontal, Vertical(i8), Extension, } bitmaps! { mode { 0001 => Mode::Pass, 001 => Mode::Horizontal, 1 => Mode::Vertical(0), 011 => Mode::Vertical(1), 000011 => Mode::Vertical(2), 0000011 => Mode::Vertical(3), 010 => Mode::Vertical(-1), 000010 => Mode::Vertical(-2), 0000010 => Mode::Vertical(-3), 0000001 => Mode::Extension, }, black { 0000110111 => 0, 010 => 1, 11 => 2, 10 => 3, 011 => 4, 0011 => 5, 0010 => 6, 00011 => 7, 000101 => 8, 000100 => 9, 0000100 => 10, 0000101 => 11, 0000111 => 12, 00000100 => 13, 00000111 => 14, 000011000 => 15, 0000010111 => 16, 0000011000 => 17, 0000001000 => 18, 00001100111 => 19, 00001101000 => 20, 00001101100 => 21, 00000110111 => 22, 00000101000 => 23, 00000010111 => 24, 00000011000 => 25, 000011001010 => 26, 000011001011 => 27, 000011001100 => 28, 000011001101 => 29, 000001101000 => 30, 000001101001 => 31, 000001101010 => 32, 000001101011 => 33, 000011010010 => 34, 000011010011 => 35, 000011010100 => 36, 000011010101 => 37, 000011010110 => 38, 000011010111 => 39, 000001101100 => 40, 000001101101 => 41, 000011011010 => 42, 000011011011 => 43, 000001010100 => 44, 000001010101 => 45, 000001010110 => 46, 000001010111 => 47, 000001100100 => 48, 000001100101 => 49, 000001010010 => 50, 000001010011 => 51, 000000100100 => 52, 000000110111 => 53, 000000111000 => 54, 000000100111 => 55, 000000101000 => 56, 000001011000 => 57, 000001011001 => 58, 000000101011 => 59, 000000101100 => 60, 000001011010 => 61, 000001100110 => 62, 000001100111 => 63, 0000001111 => 64, 000011001000 => 128, 000011001001 => 192, 000001011011 => 256, 000000110011 => 320, 000000110100 => 384, 000000110101 => 448, 0000001101100 => 512, 0000001101101 => 576, 0000001001010 => 640, 0000001001011 => 704, 0000001001100 => 768, 0000001001101 => 832, 0000001110010 => 896, 0000001110011 => 960, 0000001110100 => 1024, 0000001110101 => 1088, 0000001110110 => 1152, 0000001110111 => 1216, 0000001010010 => 1280, 0000001010011 => 1344, 0000001010100 => 1408, 0000001010101 => 1472, 0000001011010 => 1536, 0000001011011 => 1600, 0000001100100 => 1664, 0000001100101 => 1728, 00000001000 => 1792, 00000001100 => 1856, 00000001101 => 1920, 000000010010 => 1984, 000000010011 => 2048, 000000010100 => 2112, 000000010101 => 2176, 000000010110 => 2240, 000000010111 => 2304, 000000011100 => 2368, 000000011101 => 2432, 000000011110 => 2496, 000000011111 => 2560, }, white { 00110101 => 0, 000111 => 1, 0111 => 2, 1000 => 3, 1011 => 4, 1100 => 5, 1110 => 6, 1111 => 7, 10011 => 8, 10100 => 9, 00111 => 10, 01000 => 11, 001000 => 12, 000011 => 13, 110100 => 14, 110101 => 15, 101010 => 16, 101011 => 17, 0100111 => 18, 0001100 => 19, 0001000 => 20, 0010111 => 21, 0000011 => 22, 0000100 => 23, 0101000 => 24, 0101011 => 25, 0010011 => 26, 0100100 => 27, 0011000 => 28, 00000010 => 29, 00000011 => 30, 00011010 => 31, 00011011 => 32, 00010010 => 33, 00010011 => 34, 00010100 => 35, 00010101 => 36, 00010110 => 37, 00010111 => 38, 00101000 => 39, 00101001 => 40, 00101010 => 41, 00101011 => 42, 00101100 => 43, 00101101 => 44, 00000100 => 45, 00000101 => 46, 00001010 => 47, 00001011 => 48, 01010010 => 49, 01010011 => 50, 01010100 => 51, 01010101 => 52, 00100100 => 53, 00100101 => 54, 01011000 => 55, 01011001 => 56, 01011010 => 57, 01011011 => 58, 01001010 => 59, 01001011 => 60, 00110010 => 61, 00110011 => 62, 00110100 => 63, 11011 => 64, 10010 => 128, 010111 => 192, 0110111 => 256, 00110110 => 320, 00110111 => 384, 01100100 => 448, 01100101 => 512, 01101000 => 576, 01100111 => 640, 011001100 => 704, 011001101 => 768, 011010010 => 832, 011010011 => 896, 011010100 => 960, 011010101 => 1024, 011010110 => 1088, 011010111 => 1152, 011011000 => 1216, 011011001 => 1280, 011011010 => 1344, 011011011 => 1408, 010011000 => 1472, 010011001 => 1536, 010011010 => 1600, 011000 => 1664, 010011011 => 1728, 00000001000 => 1792, 00000001100 => 1856, 00000001101 => 1920, 000000010010 => 1984, 000000010011 => 2048, 000000010100 => 2112, 000000010101 => 2176, 000000010110 => 2240, 000000010111 => 2304, 000000011100 => 2368, 000000011101 => 2432, 000000011110 => 2496, 000000011111 => 2560, }, } fax-0.2.0/src/tiff.rs000064400000000000000000000044330072674642500125220ustar 00000000000000#[derive(Copy, Clone)] enum Value { Short(u16), Long(u32), Rational(u32, u32), DataOffset, } pub fn wrap(data: &[u8], width: u32, height: u32) -> Vec { use Value::*; let header_data = [ (256, Long(width)), // ImageWidth (257, Long(height)), // ImageLength (259, Short(4)), // Compression (262, Short(0)), // PhotometricInterpretation (273, DataOffset), // StripOffsets (274, Short(1)), // Orientation (278, Long(height)), // RowsPerStrip (279, Long(data.len() as u32)), // StripByteCounts (282, Rational(200, 1)), // XResolution (283, Rational(200, 1)), // YResolution (296, Short(2)), // ResolutionUnit ]; let rat_data_len = 2 * 8; // number of rationals * 8 let ifd_end = 4 + // magic 4 + // IFD offset 2 + // IFD entry count 12 * header_data.len() + // IFD enties 4; // null pointer at end of IFD let header_size = ifd_end + rat_data_len; let mut out = Vec::with_capacity(header_size + data.len()); out.extend_from_slice(&[73, 73, 42, 0]); let ifd_offset: u32 = 8; out.extend_from_slice(&ifd_offset.to_le_bytes()); out.extend_from_slice(&u16::to_le_bytes(header_data.len() as u16)); let mut num_rat = 0; for &(tag, val) in header_data.iter() { let (typ_num, val) = match val { Short(n) => (3, n as u32), Long(n) => (4, n), Rational(_, _) => { let o = ifd_end + 8 * num_rat; num_rat += 1; (5, o as u32) } DataOffset => (4, header_size as u32) }; let count = 1; out.extend_from_slice(&u16::to_le_bytes(tag)); out.extend_from_slice(&u16::to_le_bytes(typ_num)); out.extend_from_slice(&u32::to_le_bytes(count)); out.extend_from_slice(&u32::to_le_bytes(val)); } // NULL at IFD end out.extend_from_slice(&[0; 4]); // write additional data for &(_, val) in header_data.iter() { if let Value::Rational(nom, denom) = val { out.extend_from_slice(&nom.to_le_bytes()); out.extend_from_slice(&denom.to_le_bytes()); } } assert_eq!(out.len(), header_size); out.extend_from_slice(data); out }