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
#[derive(Copy, Clone)]
enum Value {
Short(u16),
Long(u32),
Rational(u32, u32),
DataOffset,
}
pub fn wrap(data: &[u8], width: u32, height: u32) -> Vec<u8> {
use Value::*;
let header_data = [
(256, Long(width)),
(257, Long(height)),
(259, Short(4)),
(262, Short(0)),
(273, DataOffset),
(274, Short(1)),
(278, Long(height)),
(279, Long(data.len() as u32)),
(282, Rational(200, 1)),
(283, Rational(200, 1)),
(296, Short(2)),
];
let rat_data_len = 2 * 8;
let ifd_end =
4 +
4 +
2 +
12 * header_data.len() +
4;
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));
}
out.extend_from_slice(&[0; 4]);
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
}