tiff/encoder/
writer.rs

1use crate::encoder::compression::*;
2use crate::error::TiffResult;
3use std::io::{self, Seek, SeekFrom, Write};
4
5pub fn write_tiff_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<()> {
6    #[cfg(target_endian = "little")]
7    let boi: u8 = 0x49;
8    #[cfg(not(target_endian = "little"))]
9    let boi: u8 = 0x4d;
10
11    writer.writer.write_all(&[boi, boi])?;
12    writer.writer.write_all(&42u16.to_ne_bytes())?;
13    writer.offset += 4;
14
15    Ok(())
16}
17
18/// Writes a BigTiff header, excluding the IFD offset field.
19///
20/// Writes the byte order, version number, offset byte size, and zero constant fields. Does
21// _not_ write the offset to the first IFD, this should be done by the caller.
22pub fn write_bigtiff_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<()> {
23    #[cfg(target_endian = "little")]
24    let boi: u8 = 0x49;
25    #[cfg(not(target_endian = "little"))]
26    let boi: u8 = 0x4d;
27
28    // byte order indication
29    writer.writer.write_all(&[boi, boi])?;
30    // version number
31    writer.writer.write_all(&43u16.to_ne_bytes())?;
32    // bytesize of offsets (pointer size)
33    writer.writer.write_all(&8u16.to_ne_bytes())?;
34    // always 0
35    writer.writer.write_all(&0u16.to_ne_bytes())?;
36
37    // we wrote 8 bytes, so set the internal offset accordingly
38    writer.offset += 8;
39
40    Ok(())
41}
42
43pub struct TiffWriter<W> {
44    writer: W,
45    offset: u64,
46    byte_count: u64,
47    compressor: Compressor,
48}
49
50impl<W: Write> TiffWriter<W> {
51    pub fn new(writer: W) -> Self {
52        Self {
53            writer,
54            offset: 0,
55            byte_count: 0,
56            compressor: Compressor::default(),
57        }
58    }
59
60    pub fn set_compression(&mut self, compressor: Compressor) {
61        self.compressor = compressor;
62    }
63
64    pub fn reset_compression(&mut self) {
65        self.compressor = Compressor::default();
66    }
67
68    pub fn offset(&self) -> u64 {
69        self.offset
70    }
71
72    pub fn last_written(&self) -> u64 {
73        self.byte_count
74    }
75
76    pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), io::Error> {
77        self.byte_count = self.compressor.write_to(&mut self.writer, bytes)?;
78        self.offset += self.byte_count;
79        Ok(())
80    }
81
82    pub fn write_u8(&mut self, n: u8) -> Result<(), io::Error> {
83        self.byte_count = self
84            .compressor
85            .write_to(&mut self.writer, &n.to_ne_bytes())?;
86        self.offset += self.byte_count;
87        Ok(())
88    }
89
90    pub fn write_i8(&mut self, n: i8) -> Result<(), io::Error> {
91        self.byte_count = self
92            .compressor
93            .write_to(&mut self.writer, &n.to_ne_bytes())?;
94        self.offset += self.byte_count;
95        Ok(())
96    }
97
98    pub fn write_u16(&mut self, n: u16) -> Result<(), io::Error> {
99        self.byte_count = self
100            .compressor
101            .write_to(&mut self.writer, &n.to_ne_bytes())?;
102        self.offset += self.byte_count;
103
104        Ok(())
105    }
106
107    pub fn write_i16(&mut self, n: i16) -> Result<(), io::Error> {
108        self.byte_count = self
109            .compressor
110            .write_to(&mut self.writer, &n.to_ne_bytes())?;
111        self.offset += self.byte_count;
112
113        Ok(())
114    }
115
116    pub fn write_u32(&mut self, n: u32) -> Result<(), io::Error> {
117        self.byte_count = self
118            .compressor
119            .write_to(&mut self.writer, &n.to_ne_bytes())?;
120        self.offset += self.byte_count;
121
122        Ok(())
123    }
124
125    pub fn write_i32(&mut self, n: i32) -> Result<(), io::Error> {
126        self.byte_count = self
127            .compressor
128            .write_to(&mut self.writer, &n.to_ne_bytes())?;
129        self.offset += self.byte_count;
130
131        Ok(())
132    }
133
134    pub fn write_u64(&mut self, n: u64) -> Result<(), io::Error> {
135        self.byte_count = self
136            .compressor
137            .write_to(&mut self.writer, &n.to_ne_bytes())?;
138        self.offset += self.byte_count;
139
140        Ok(())
141    }
142
143    pub fn write_i64(&mut self, n: i64) -> Result<(), io::Error> {
144        self.byte_count = self
145            .compressor
146            .write_to(&mut self.writer, &n.to_ne_bytes())?;
147        self.offset += self.byte_count;
148
149        Ok(())
150    }
151
152    pub fn write_f32(&mut self, n: f32) -> Result<(), io::Error> {
153        self.byte_count = self
154            .compressor
155            .write_to(&mut self.writer, &u32::to_ne_bytes(n.to_bits()))?;
156        self.offset += self.byte_count;
157
158        Ok(())
159    }
160
161    pub fn write_f64(&mut self, n: f64) -> Result<(), io::Error> {
162        self.byte_count = self
163            .compressor
164            .write_to(&mut self.writer, &u64::to_ne_bytes(n.to_bits()))?;
165        self.offset += self.byte_count;
166
167        Ok(())
168    }
169
170    pub fn pad_word_boundary(&mut self) -> Result<(), io::Error> {
171        if self.offset % 4 != 0 {
172            let padding = [0, 0, 0];
173            let padd_len = 4 - (self.offset % 4);
174            self.writer.write_all(&padding[..padd_len as usize])?;
175            self.offset += padd_len;
176        }
177
178        Ok(())
179    }
180}
181
182impl<W: Seek> TiffWriter<W> {
183    pub fn goto_offset(&mut self, offset: u64) -> Result<(), io::Error> {
184        self.offset = offset;
185        self.writer.seek(SeekFrom::Start(offset))?;
186        Ok(())
187    }
188}