/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tiff-0.11.3/src/encoder/writer.rs
Line | Count | Source |
1 | | use crate::encoder::compression::*; |
2 | | use crate::error::TiffResult; |
3 | | use std::io::{self, Seek, SeekFrom, Write}; |
4 | | |
5 | 0 | pub fn write_tiff_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<()> { |
6 | | #[cfg(target_endian = "little")] |
7 | 0 | let boi: u8 = 0x49; |
8 | | #[cfg(not(target_endian = "little"))] |
9 | | let boi: u8 = 0x4d; |
10 | | |
11 | 0 | writer.writer.write_all(&[boi, boi])?; |
12 | 0 | writer.writer.write_all(&42u16.to_ne_bytes())?; |
13 | 0 | writer.offset += 4; |
14 | | |
15 | 0 | Ok(()) |
16 | 0 | } Unexecuted instantiation: tiff::encoder::writer::write_tiff_header::<_> Unexecuted instantiation: tiff::encoder::writer::write_tiff_header::<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> |
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. |
22 | 0 | pub fn write_bigtiff_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<()> { |
23 | | #[cfg(target_endian = "little")] |
24 | 0 | let boi: u8 = 0x49; |
25 | | #[cfg(not(target_endian = "little"))] |
26 | | let boi: u8 = 0x4d; |
27 | | |
28 | | // byte order indication |
29 | 0 | writer.writer.write_all(&[boi, boi])?; |
30 | | // version number |
31 | 0 | writer.writer.write_all(&43u16.to_ne_bytes())?; |
32 | | // bytesize of offsets (pointer size) |
33 | 0 | writer.writer.write_all(&8u16.to_ne_bytes())?; |
34 | | // always 0 |
35 | 0 | writer.writer.write_all(&0u16.to_ne_bytes())?; |
36 | | |
37 | | // we wrote 8 bytes, so set the internal offset accordingly |
38 | 0 | writer.offset += 8; |
39 | | |
40 | 0 | Ok(()) |
41 | 0 | } |
42 | | |
43 | | pub struct TiffWriter<W> { |
44 | | writer: W, |
45 | | offset: u64, |
46 | | byte_count: u64, |
47 | | compressor: Compressor, |
48 | | } |
49 | | |
50 | | impl<W: Write> TiffWriter<W> { |
51 | 0 | pub fn new(writer: W) -> Self { |
52 | 0 | Self { |
53 | 0 | writer, |
54 | 0 | offset: 0, |
55 | 0 | byte_count: 0, |
56 | 0 | compressor: Compressor::default(), |
57 | 0 | } |
58 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::new Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut alloc::vec::Vec<u8>>>::new Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::new |
59 | | |
60 | 0 | pub fn set_compression(&mut self, compressor: Compressor) { |
61 | 0 | self.compressor = compressor; |
62 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::set_compression Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::set_compression |
63 | | |
64 | 0 | pub fn reset_compression(&mut self) { |
65 | 0 | self.compressor = Compressor::default(); |
66 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::reset_compression Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::reset_compression |
67 | | |
68 | 0 | pub fn offset(&self) -> u64 { |
69 | 0 | self.offset |
70 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::offset Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::offset |
71 | | |
72 | 0 | pub(crate) fn previous_ifd_pointer<K: super::TiffKind>(&self) -> u64 { |
73 | 0 | self.offset() - core::mem::size_of::<K::OffsetType>() as u64 |
74 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::previous_ifd_pointer::<_> Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::previous_ifd_pointer::<tiff::encoder::TiffKindStandard> |
75 | | |
76 | 0 | pub fn last_written(&self) -> u64 { |
77 | 0 | self.byte_count |
78 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::last_written Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::last_written |
79 | | |
80 | 0 | pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), io::Error> { |
81 | 0 | self.byte_count = self.compressor.write_to(&mut self.writer, bytes)?; |
82 | 0 | self.offset += self.byte_count; |
83 | 0 | Ok(()) |
84 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::write_bytes Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut alloc::vec::Vec<u8>>>::write_bytes Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_bytes |
85 | | |
86 | 0 | pub fn write_u8(&mut self, n: u8) -> Result<(), io::Error> { |
87 | 0 | self.byte_count = self |
88 | 0 | .compressor |
89 | 0 | .write_to(&mut self.writer, &n.to_ne_bytes())?; |
90 | 0 | self.offset += self.byte_count; |
91 | 0 | Ok(()) |
92 | 0 | } |
93 | | |
94 | 0 | pub fn write_i8(&mut self, n: i8) -> Result<(), io::Error> { |
95 | 0 | self.byte_count = self |
96 | 0 | .compressor |
97 | 0 | .write_to(&mut self.writer, &n.to_ne_bytes())?; |
98 | 0 | self.offset += self.byte_count; |
99 | 0 | Ok(()) |
100 | 0 | } |
101 | | |
102 | 0 | pub fn write_u16(&mut self, n: u16) -> Result<(), io::Error> { |
103 | 0 | self.byte_count = self |
104 | 0 | .compressor |
105 | 0 | .write_to(&mut self.writer, &n.to_ne_bytes())?; |
106 | 0 | self.offset += self.byte_count; |
107 | | |
108 | 0 | Ok(()) |
109 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::write_u16 Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut alloc::vec::Vec<u8>>>::write_u16 Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_u16 |
110 | | |
111 | 0 | pub fn write_i16(&mut self, n: i16) -> Result<(), io::Error> { |
112 | 0 | self.byte_count = self |
113 | 0 | .compressor |
114 | 0 | .write_to(&mut self.writer, &n.to_ne_bytes())?; |
115 | 0 | self.offset += self.byte_count; |
116 | | |
117 | 0 | Ok(()) |
118 | 0 | } |
119 | | |
120 | 0 | pub fn write_u32(&mut self, n: u32) -> Result<(), io::Error> { |
121 | 0 | self.byte_count = self |
122 | 0 | .compressor |
123 | 0 | .write_to(&mut self.writer, &n.to_ne_bytes())?; |
124 | 0 | self.offset += self.byte_count; |
125 | | |
126 | 0 | Ok(()) |
127 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::write_u32 Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut alloc::vec::Vec<u8>>>::write_u32 Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_u32 |
128 | | |
129 | 0 | pub fn write_i32(&mut self, n: i32) -> Result<(), io::Error> { |
130 | 0 | self.byte_count = self |
131 | 0 | .compressor |
132 | 0 | .write_to(&mut self.writer, &n.to_ne_bytes())?; |
133 | 0 | self.offset += self.byte_count; |
134 | | |
135 | 0 | Ok(()) |
136 | 0 | } |
137 | | |
138 | 0 | pub fn write_u64(&mut self, n: u64) -> Result<(), io::Error> { |
139 | 0 | self.byte_count = self |
140 | 0 | .compressor |
141 | 0 | .write_to(&mut self.writer, &n.to_ne_bytes())?; |
142 | 0 | self.offset += self.byte_count; |
143 | | |
144 | 0 | Ok(()) |
145 | 0 | } |
146 | | |
147 | 0 | pub fn write_i64(&mut self, n: i64) -> Result<(), io::Error> { |
148 | 0 | self.byte_count = self |
149 | 0 | .compressor |
150 | 0 | .write_to(&mut self.writer, &n.to_ne_bytes())?; |
151 | 0 | self.offset += self.byte_count; |
152 | | |
153 | 0 | Ok(()) |
154 | 0 | } |
155 | | |
156 | 0 | pub fn write_f32(&mut self, n: f32) -> Result<(), io::Error> { |
157 | 0 | self.byte_count = self |
158 | 0 | .compressor |
159 | 0 | .write_to(&mut self.writer, &u32::to_ne_bytes(n.to_bits()))?; |
160 | 0 | self.offset += self.byte_count; |
161 | | |
162 | 0 | Ok(()) |
163 | 0 | } |
164 | | |
165 | 0 | pub fn write_f64(&mut self, n: f64) -> Result<(), io::Error> { |
166 | 0 | self.byte_count = self |
167 | 0 | .compressor |
168 | 0 | .write_to(&mut self.writer, &u64::to_ne_bytes(n.to_bits()))?; |
169 | 0 | self.offset += self.byte_count; |
170 | | |
171 | 0 | Ok(()) |
172 | 0 | } |
173 | | |
174 | 0 | pub fn pad_word_boundary(&mut self) -> Result<(), io::Error> { |
175 | 0 | if self.offset % 4 != 0 { |
176 | 0 | let padding = [0, 0, 0]; |
177 | 0 | let padd_len = 4 - (self.offset % 4); |
178 | 0 | self.writer.write_all(&padding[..padd_len as usize])?; |
179 | 0 | self.offset += padd_len; |
180 | 0 | } |
181 | | |
182 | 0 | Ok(()) |
183 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::pad_word_boundary Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::pad_word_boundary |
184 | | } |
185 | | |
186 | | impl<W: Seek> TiffWriter<W> { |
187 | 0 | pub fn goto_offset(&mut self, offset: u64) -> Result<(), io::Error> { |
188 | 0 | self.offset = offset; |
189 | 0 | self.writer.seek(SeekFrom::Start(offset))?; |
190 | 0 | Ok(()) |
191 | 0 | } Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<_>>::goto_offset Unexecuted instantiation: <tiff::encoder::writer::TiffWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::goto_offset |
192 | | } |
193 | | |
194 | | #[test] |
195 | | fn encoder_on_short_writes() { |
196 | | struct ShortWriter<T> { |
197 | | inner: T, |
198 | | } |
199 | | |
200 | | impl<T: std::io::Write> std::io::Write for ShortWriter<T> { |
201 | | fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { |
202 | | let lower_bound = buf.len().min(1); |
203 | | let lower = buf.len().saturating_sub(1).max(lower_bound); |
204 | | |
205 | | self.inner.write(&buf[..lower]) |
206 | | } |
207 | | |
208 | | fn flush(&mut self) -> std::io::Result<()> { |
209 | | self.inner.flush() |
210 | | } |
211 | | } |
212 | | |
213 | | impl<T: std::io::Seek> std::io::Seek for ShortWriter<T> { |
214 | | fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> { |
215 | | self.inner.seek(pos) |
216 | | } |
217 | | } |
218 | | |
219 | | let mut write = ShortWriter { |
220 | | inner: std::io::Cursor::new(vec![0u8; 0]), |
221 | | }; |
222 | | |
223 | | let imgdata = vec![42u8; 100 * 100]; |
224 | | let mut data = crate::decoder::DecodingResult::U8(vec![]); |
225 | | |
226 | | for comp in [ |
227 | | super::Compression::Uncompressed, |
228 | | super::Compression::Packbits, |
229 | | ] { |
230 | | write.inner.set_position(0); |
231 | | write.inner.get_mut().clear(); |
232 | | |
233 | | { |
234 | | let mut tiff_writer = super::TiffEncoder::new(&mut write) |
235 | | .unwrap() |
236 | | .with_compression(comp); |
237 | | |
238 | | tiff_writer |
239 | | .write_image::<super::Gray8>(100, 100, &imgdata) |
240 | | .unwrap(); |
241 | | } |
242 | | |
243 | | write.inner.set_position(0); |
244 | | let mut tiff_reader = crate::decoder::Decoder::new(&mut write.inner).unwrap(); |
245 | | let _layout = tiff_reader.read_image_to_buffer(&mut data).unwrap(); |
246 | | |
247 | | assert!( |
248 | | matches!(&data, crate::decoder::DecodingResult::U8(v) if *v == imgdata), |
249 | | "{data:?} @ {}", |
250 | | data.as_buffer(0).byte_len() |
251 | | ); |
252 | | } |
253 | | } |