/rust/registry/src/index.crates.io-1949cf8c6b5b557f/fax-0.2.6/src/tiff.rs
Line | Count | Source |
1 | | #[derive(Copy, Clone)] |
2 | | enum Value { |
3 | | Short(u16), |
4 | | Long(u32), |
5 | | Rational(u32, u32), |
6 | | DataOffset, |
7 | | } |
8 | | |
9 | 0 | pub fn wrap(data: &[u8], width: u32, height: u32) -> Vec<u8> { |
10 | | use Value::*; |
11 | 0 | let header_data = [ |
12 | 0 | (256, Long(width)), // ImageWidth |
13 | 0 | (257, Long(height)), // ImageLength |
14 | 0 | (259, Short(4)), // Compression |
15 | 0 | (262, Short(0)), // PhotometricInterpretation |
16 | 0 | (273, DataOffset), // StripOffsets |
17 | 0 | (274, Short(1)), // Orientation |
18 | 0 | (278, Long(height)), // RowsPerStrip |
19 | 0 | (279, Long(data.len() as u32)), // StripByteCounts |
20 | 0 | (282, Rational(200, 1)), // XResolution |
21 | 0 | (283, Rational(200, 1)), // YResolution |
22 | 0 | (296, Short(2)), // ResolutionUnit |
23 | 0 | ]; |
24 | 0 | let rat_data_len = 2 * 8; // number of rationals * 8 |
25 | 0 | let ifd_end = |
26 | 0 | 4 + // magic |
27 | 0 | 4 + // IFD offset |
28 | 0 | 2 + // IFD entry count |
29 | 0 | 12 * header_data.len() + // IFD enties |
30 | 0 | 4; // null pointer at end of IFD |
31 | 0 | let header_size = ifd_end + rat_data_len; |
32 | | |
33 | 0 | let mut out = Vec::with_capacity(header_size + data.len()); |
34 | | |
35 | 0 | out.extend_from_slice(&[73, 73, 42, 0]); |
36 | 0 | let ifd_offset: u32 = 8; |
37 | 0 | out.extend_from_slice(&ifd_offset.to_le_bytes()); |
38 | | |
39 | 0 | out.extend_from_slice(&u16::to_le_bytes(header_data.len() as u16)); |
40 | | |
41 | 0 | let mut num_rat = 0; |
42 | 0 | for &(tag, val) in header_data.iter() { |
43 | 0 | let (typ_num, val) = match val { |
44 | 0 | Short(n) => (3, n as u32), |
45 | 0 | Long(n) => (4, n), |
46 | | Rational(_, _) => { |
47 | 0 | let o = ifd_end + 8 * num_rat; |
48 | 0 | num_rat += 1; |
49 | 0 | (5, o as u32) |
50 | | } |
51 | 0 | DataOffset => (4, header_size as u32) |
52 | | }; |
53 | 0 | let count = 1; |
54 | 0 | out.extend_from_slice(&u16::to_le_bytes(tag)); |
55 | 0 | out.extend_from_slice(&u16::to_le_bytes(typ_num)); |
56 | 0 | out.extend_from_slice(&u32::to_le_bytes(count)); |
57 | 0 | out.extend_from_slice(&u32::to_le_bytes(val)); |
58 | | } |
59 | | // NULL at IFD end |
60 | 0 | out.extend_from_slice(&[0; 4]); |
61 | | |
62 | | // write additional data |
63 | 0 | for &(_, val) in header_data.iter() { |
64 | 0 | if let Value::Rational(nom, denom) = val { |
65 | 0 | out.extend_from_slice(&nom.to_le_bytes()); |
66 | 0 | out.extend_from_slice(&denom.to_le_bytes()); |
67 | 0 | } |
68 | | } |
69 | | |
70 | 0 | assert_eq!(out.len(), header_size); |
71 | 0 | out.extend_from_slice(data); |
72 | 0 | out |
73 | 0 | } |