Coverage Report

Created: 2025-07-11 07:25

/rust/registry/src/index.crates.io-6f17d22bba15001f/tiff-0.10.0/src/encoder/mod.rs
Line
Count
Source (jump to first uncovered line)
1
pub use tiff_value::*;
2
3
use std::{
4
    cmp,
5
    collections::BTreeMap,
6
    io::{self, Seek, Write},
7
    marker::PhantomData,
8
    mem,
9
    num::TryFromIntError,
10
};
11
12
use crate::{
13
    error::{TiffResult, UsageError},
14
    tags::{CompressionMethod, ResolutionUnit, SampleFormat, Tag},
15
    TiffError, TiffFormatError,
16
};
17
18
pub mod colortype;
19
pub mod compression;
20
mod tiff_value;
21
mod writer;
22
23
use self::colortype::*;
24
use self::compression::Compression as Comp;
25
use self::compression::*;
26
use self::writer::*;
27
28
/// Type of prediction to prepare the image with.
29
///
30
/// Image data can be very unpredictable, and thus very hard to compress. Predictors are simple
31
/// passes ran over the image data to prepare it for compression. This is mostly used for LZW
32
/// compression, where using [Predictor::Horizontal] we see a 35% improvement in compression
33
/// ratio over the unpredicted compression !
34
///
35
/// [Predictor::FloatingPoint] is currently not supported.
36
pub type Predictor = crate::tags::Predictor;
37
#[cfg(feature = "deflate")]
38
pub type DeflateLevel = compression::DeflateLevel;
39
40
#[derive(Clone, Copy, PartialEq)]
41
pub enum Compression {
42
    Uncompressed,
43
    #[cfg(feature = "lzw")]
44
    Lzw,
45
    #[cfg(feature = "deflate")]
46
    Deflate(DeflateLevel),
47
    Packbits,
48
}
49
50
impl Default for Compression {
51
0
    fn default() -> Self {
52
0
        Self::Uncompressed
53
0
    }
54
}
55
56
impl Compression {
57
0
    fn tag(&self) -> CompressionMethod {
58
0
        match self {
59
0
            Compression::Uncompressed => CompressionMethod::None,
60
            #[cfg(feature = "lzw")]
61
0
            Compression::Lzw => CompressionMethod::LZW,
62
            #[cfg(feature = "deflate")]
63
0
            Compression::Deflate(_) => CompressionMethod::Deflate,
64
0
            Compression::Packbits => CompressionMethod::PackBits,
65
        }
66
0
    }
67
68
0
    fn get_algorithm(&self) -> Compressor {
69
0
        match self {
70
0
            Compression::Uncompressed => compression::Uncompressed {}.get_algorithm(),
71
            #[cfg(feature = "lzw")]
72
0
            Compression::Lzw => compression::Lzw {}.get_algorithm(),
73
            #[cfg(feature = "deflate")]
74
0
            Compression::Deflate(level) => compression::Deflate::with_level(*level).get_algorithm(),
75
0
            Compression::Packbits => compression::Packbits {}.get_algorithm(),
76
        }
77
0
    }
78
}
79
80
/// Encoder for Tiff and BigTiff files.
81
///
82
/// With this type you can get a `DirectoryEncoder` or a `ImageEncoder`
83
/// to encode Tiff/BigTiff ifd directories with images.
84
///
85
/// See `DirectoryEncoder` and `ImageEncoder`.
86
///
87
/// # Examples
88
/// ```
89
/// # extern crate tiff;
90
/// # fn main() {
91
/// # let mut file = std::io::Cursor::new(Vec::new());
92
/// # let image_data = vec![0; 100*100*3];
93
/// use tiff::encoder::*;
94
///
95
/// // create a standard Tiff file
96
/// let mut tiff = TiffEncoder::new(&mut file).unwrap();
97
/// tiff.write_image::<colortype::RGB8>(100, 100, &image_data).unwrap();
98
///
99
/// // create a BigTiff file
100
/// let mut bigtiff = TiffEncoder::new_big(&mut file).unwrap();
101
/// bigtiff.write_image::<colortype::RGB8>(100, 100, &image_data).unwrap();
102
///
103
/// # }
104
/// ```
105
pub struct TiffEncoder<W, K: TiffKind = TiffKindStandard> {
106
    writer: TiffWriter<W>,
107
    kind: PhantomData<K>,
108
    predictor: Predictor,
109
    compression: Compression,
110
}
111
112
/// Constructor functions to create standard Tiff files.
113
impl<W: Write + Seek> TiffEncoder<W> {
114
    /// Creates a new encoder for standard Tiff files.
115
    ///
116
    /// To create BigTiff files, use [`new_big`][TiffEncoder::new_big] or
117
    /// [`new_generic`][TiffEncoder::new_generic].
118
0
    pub fn new(writer: W) -> TiffResult<TiffEncoder<W, TiffKindStandard>> {
119
0
        TiffEncoder::new_generic(writer)
120
0
    }
Unexecuted instantiation: <tiff::encoder::TiffEncoder<_>>::new
Unexecuted instantiation: <tiff::encoder::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::new
121
}
122
123
/// Constructor functions to create BigTiff files.
124
impl<W: Write + Seek> TiffEncoder<W, TiffKindBig> {
125
    /// Creates a new encoder for BigTiff files.
126
    ///
127
    /// To create standard Tiff files, use [`new`][TiffEncoder::new] or
128
    /// [`new_generic`][TiffEncoder::new_generic].
129
0
    pub fn new_big(writer: W) -> TiffResult<Self> {
130
0
        TiffEncoder::new_generic(writer)
131
0
    }
132
}
133
134
/// Generic functions that are available for both Tiff and BigTiff encoders.
135
impl<W: Write + Seek, K: TiffKind> TiffEncoder<W, K> {
136
    /// Creates a new Tiff or BigTiff encoder, inferred from the return type.
137
0
    pub fn new_generic(writer: W) -> TiffResult<Self> {
138
0
        let mut encoder = TiffEncoder {
139
0
            writer: TiffWriter::new(writer),
140
0
            kind: PhantomData,
141
0
            predictor: Predictor::None,
142
0
            compression: Compression::Uncompressed,
143
0
        };
144
0
145
0
        K::write_header(&mut encoder.writer)?;
146
147
0
        Ok(encoder)
148
0
    }
Unexecuted instantiation: <tiff::encoder::TiffEncoder<_, _>>::new_generic
Unexecuted instantiation: <tiff::encoder::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::new_generic
149
150
    /// Set the predictor to use
151
    ///
152
    /// A predictor is used to simplify the file before writing it. This is very
153
    /// useful when writing a file compressed using LZW as it can improve efficiency
154
0
    pub fn with_predictor(mut self, predictor: Predictor) -> Self {
155
0
        self.predictor = predictor;
156
0
157
0
        self
158
0
    }
159
160
    /// Set the compression method to use
161
0
    pub fn with_compression(mut self, compression: Compression) -> Self {
162
0
        self.compression = compression;
163
0
164
0
        self
165
0
    }
166
167
    /// Create a [`DirectoryEncoder`] to encode an ifd directory.
168
0
    pub fn new_directory(&mut self) -> TiffResult<DirectoryEncoder<W, K>> {
169
0
        DirectoryEncoder::new(&mut self.writer)
170
0
    }
171
172
    /// Create an [`ImageEncoder`] to encode an image one slice at a time.
173
0
    pub fn new_image<C: ColorType>(
174
0
        &mut self,
175
0
        width: u32,
176
0
        height: u32,
177
0
    ) -> TiffResult<ImageEncoder<W, C, K>> {
178
0
        let encoder = DirectoryEncoder::new(&mut self.writer)?;
179
0
        ImageEncoder::new(encoder, width, height, self.compression, self.predictor)
180
0
    }
181
182
    /// Convenience function to write an entire image from memory.
183
0
    pub fn write_image<C: ColorType>(
184
0
        &mut self,
185
0
        width: u32,
186
0
        height: u32,
187
0
        data: &[C::Inner],
188
0
    ) -> TiffResult<()>
189
0
    where
190
0
        [C::Inner]: TiffValue,
191
0
    {
192
0
        let encoder = DirectoryEncoder::new(&mut self.writer)?;
193
0
        let image: ImageEncoder<W, C, K> =
194
0
            ImageEncoder::new(encoder, width, height, self.compression, self.predictor)?;
195
0
        image.write_data(data)
196
0
    }
Unexecuted instantiation: <tiff::encoder::TiffEncoder<_, _>>::write_image::<_>
Unexecuted instantiation: <tiff::encoder::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_image::<tiff::encoder::colortype::RGB8>
Unexecuted instantiation: <tiff::encoder::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_image::<tiff::encoder::colortype::Gray8>
Unexecuted instantiation: <tiff::encoder::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_image::<tiff::encoder::colortype::RGB16>
Unexecuted instantiation: <tiff::encoder::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_image::<tiff::encoder::colortype::RGBA8>
Unexecuted instantiation: <tiff::encoder::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_image::<tiff::encoder::colortype::Gray16>
Unexecuted instantiation: <tiff::encoder::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_image::<tiff::encoder::colortype::RGBA16>
197
}
198
199
/// Low level interface to encode ifd directories.
200
///
201
/// You should call `finish` on this when you are finished with it.
202
/// Encoding can silently fail while this is dropping.
203
pub struct DirectoryEncoder<'a, W: 'a + Write + Seek, K: TiffKind> {
204
    writer: &'a mut TiffWriter<W>,
205
    dropped: bool,
206
    // We use BTreeMap to make sure tags are written in correct order
207
    ifd_pointer_pos: u64,
208
    ifd: BTreeMap<u16, DirectoryEntry<K::OffsetType>>,
209
}
210
211
impl<'a, W: 'a + Write + Seek, K: TiffKind> DirectoryEncoder<'a, W, K> {
212
0
    fn new(writer: &'a mut TiffWriter<W>) -> TiffResult<Self> {
213
0
        // the previous word is the IFD offset position
214
0
        let ifd_pointer_pos = writer.offset() - mem::size_of::<K::OffsetType>() as u64;
215
0
        writer.pad_word_boundary()?; // TODO: Do we need to adjust this for BigTiff?
216
0
        Ok(DirectoryEncoder {
217
0
            writer,
218
0
            dropped: false,
219
0
            ifd_pointer_pos,
220
0
            ifd: BTreeMap::new(),
221
0
        })
222
0
    }
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<_, _>>::new
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::new
223
224
    /// Write a single ifd tag.
225
0
    pub fn write_tag<T: TiffValue>(&mut self, tag: Tag, value: T) -> TiffResult<()> {
226
0
        let mut bytes = Vec::with_capacity(value.bytes());
227
0
        {
228
0
            let mut writer = TiffWriter::new(&mut bytes);
229
0
            value.write(&mut writer)?;
230
        }
231
232
0
        self.ifd.insert(
233
0
            tag.to_u16(),
234
0
            DirectoryEntry {
235
0
                data_type: <T>::FIELD_TYPE.to_u16(),
236
0
                count: value.count().try_into()?,
237
0
                data: bytes,
238
0
            },
239
0
        );
240
0
241
0
        Ok(())
242
0
    }
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<_, _>>::write_tag::<_>
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::write_tag::<tiff::encoder::tiff_value::Rational>
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::write_tag::<&[u32]>
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::write_tag::<&[u16]>
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::write_tag::<u32>
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::write_tag::<u16>
243
244
0
    fn write_directory(&mut self) -> TiffResult<u64> {
245
        // Start by writing out all values
246
        for &mut DirectoryEntry {
247
0
            data: ref mut bytes,
248
            ..
249
0
        } in self.ifd.values_mut()
250
        {
251
0
            let data_bytes = mem::size_of::<K::OffsetType>();
252
0
253
0
            if bytes.len() > data_bytes {
254
0
                let offset = self.writer.offset();
255
0
                self.writer.write_bytes(bytes)?;
256
0
                *bytes = vec![0; data_bytes];
257
0
                let mut writer = TiffWriter::new(bytes as &mut [u8]);
258
0
                K::write_offset(&mut writer, offset)?;
259
            } else {
260
0
                while bytes.len() < data_bytes {
261
0
                    bytes.push(0);
262
0
                }
263
            }
264
        }
265
266
0
        let offset = self.writer.offset();
267
0
268
0
        K::write_entry_count(self.writer, self.ifd.len())?;
269
        for (
270
0
            tag,
271
0
            DirectoryEntry {
272
0
                data_type: field_type,
273
0
                count,
274
0
                data: offset,
275
            },
276
0
        ) in self.ifd.iter()
277
        {
278
0
            self.writer.write_u16(*tag)?;
279
0
            self.writer.write_u16(*field_type)?;
280
0
            (*count).write(self.writer)?;
281
0
            self.writer.write_bytes(offset)?;
282
        }
283
284
0
        Ok(offset)
285
0
    }
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<_, _>>::write_directory
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::write_directory
286
287
    /// Write some data to the tiff file, the offset of the data is returned.
288
    ///
289
    /// This could be used to write tiff strips.
290
0
    pub fn write_data<T: TiffValue>(&mut self, value: T) -> TiffResult<u64> {
291
0
        let offset = self.writer.offset();
292
0
        value.write(self.writer)?;
293
0
        Ok(offset)
294
0
    }
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<_, _>>::write_data::<_>
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::write_data::<&[u8]>
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::write_data::<&[u16]>
295
296
    /// Provides the number of bytes written by the underlying TiffWriter during the last call.
297
0
    fn last_written(&self) -> u64 {
298
0
        self.writer.last_written()
299
0
    }
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<_, _>>::last_written
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::last_written
300
301
0
    fn finish_internal(&mut self) -> TiffResult<()> {
302
0
        let ifd_pointer = self.write_directory()?;
303
0
        let curr_pos = self.writer.offset();
304
0
305
0
        self.writer.goto_offset(self.ifd_pointer_pos)?;
306
0
        K::write_offset(self.writer, ifd_pointer)?;
307
0
        self.writer.goto_offset(curr_pos)?;
308
0
        K::write_offset(self.writer, 0)?;
309
310
0
        self.dropped = true;
311
0
312
0
        Ok(())
313
0
    }
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<_, _>>::finish_internal
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard>>::finish_internal
314
315
    /// Write out the ifd directory.
316
0
    pub fn finish(mut self) -> TiffResult<()> {
317
0
        self.finish_internal()
318
0
    }
319
}
320
321
impl<'a, W: Write + Seek, K: TiffKind> Drop for DirectoryEncoder<'a, W, K> {
322
0
    fn drop(&mut self) {
323
0
        if !self.dropped {
324
0
            let _ = self.finish_internal();
325
0
        }
326
0
    }
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<_, _> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <tiff::encoder::DirectoryEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::TiffKindStandard> as core::ops::drop::Drop>::drop
327
}
328
329
/// Type to encode images strip by strip.
330
///
331
/// You should call `finish` on this when you are finished with it.
332
/// Encoding can silently fail while this is dropping.
333
///
334
/// # Examples
335
/// ```
336
/// # extern crate tiff;
337
/// # fn main() {
338
/// # let mut file = std::io::Cursor::new(Vec::new());
339
/// # let image_data = vec![0; 100*100*3];
340
/// use tiff::encoder::*;
341
/// use tiff::tags::Tag;
342
///
343
/// let mut tiff = TiffEncoder::new(&mut file).unwrap();
344
/// let mut image = tiff.new_image::<colortype::RGB8>(100, 100).unwrap();
345
///
346
/// // You can encode tags here
347
/// image.encoder().write_tag(Tag::Artist, "Image-tiff").unwrap();
348
///
349
/// // Strip size can be configured before writing data
350
/// image.rows_per_strip(2).unwrap();
351
///
352
/// let mut idx = 0;
353
/// while image.next_strip_sample_count() > 0 {
354
///     let sample_count = image.next_strip_sample_count() as usize;
355
///     image.write_strip(&image_data[idx..idx+sample_count]).unwrap();
356
///     idx += sample_count;
357
/// }
358
/// image.finish().unwrap();
359
/// # }
360
/// ```
361
/// You can also call write_data function wich will encode by strip and finish
362
pub struct ImageEncoder<'a, W: 'a + Write + Seek, C: ColorType, K: TiffKind> {
363
    encoder: DirectoryEncoder<'a, W, K>,
364
    strip_idx: u64,
365
    strip_count: u64,
366
    row_samples: u64,
367
    width: u32,
368
    height: u32,
369
    rows_per_strip: u64,
370
    strip_offsets: Vec<K::OffsetType>,
371
    strip_byte_count: Vec<K::OffsetType>,
372
    dropped: bool,
373
    compression: Compression,
374
    predictor: Predictor,
375
    _phantom: ::std::marker::PhantomData<C>,
376
}
377
378
impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind> ImageEncoder<'a, W, T, K> {
379
0
    fn sanity_check(compression: Compression, predictor: Predictor) -> TiffResult<()> {
380
0
        match (predictor, compression, T::SAMPLE_FORMAT[0]) {
381
            (Predictor::Horizontal, _, SampleFormat::IEEEFP | SampleFormat::Void) => {
382
0
                Err(TiffError::UsageError(UsageError::PredictorIncompatible))
383
            }
384
            (Predictor::FloatingPoint, _, _) => {
385
0
                Err(TiffError::UsageError(UsageError::PredictorUnavailable))
386
            }
387
0
            _ => Ok(()),
388
        }
389
0
    }
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::sanity_check
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::sanity_check
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::sanity_check
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::sanity_check
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::sanity_check
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::sanity_check
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::sanity_check
390
391
0
    fn new(
392
0
        mut encoder: DirectoryEncoder<'a, W, K>,
393
0
        width: u32,
394
0
        height: u32,
395
0
        compression: Compression,
396
0
        predictor: Predictor,
397
0
    ) -> TiffResult<Self> {
398
0
        if width == 0 || height == 0 {
399
0
            return Err(TiffError::FormatError(TiffFormatError::InvalidDimensions(
400
0
                width, height,
401
0
            )));
402
0
        }
403
0
404
0
        Self::sanity_check(compression, predictor)?;
405
406
0
        let row_samples = u64::from(width) * u64::try_from(<T>::BITS_PER_SAMPLE.len())?;
407
0
        let row_bytes = row_samples * u64::from(<T::Inner>::BYTE_LEN);
408
409
        // Limit the strip size to prevent potential memory and security issues.
410
        // Also keep the multiple strip handling 'oiled'
411
0
        let rows_per_strip = {
412
0
            match compression.tag() {
413
0
                CompressionMethod::PackBits => 1, // Each row must be packed separately. Do not compress across row boundaries
414
0
                _ => (1_000_000 + row_bytes - 1) / row_bytes,
415
            }
416
        };
417
418
0
        let strip_count = (u64::from(height) + rows_per_strip - 1) / rows_per_strip;
419
0
420
0
        encoder.write_tag(Tag::ImageWidth, width)?;
421
0
        encoder.write_tag(Tag::ImageLength, height)?;
422
0
        encoder.write_tag(Tag::Compression, compression.tag().to_u16())?;
423
0
        encoder.write_tag(Tag::Predictor, predictor.to_u16())?;
424
425
0
        encoder.write_tag(Tag::BitsPerSample, <T>::BITS_PER_SAMPLE)?;
426
0
        let sample_format: Vec<_> = <T>::SAMPLE_FORMAT.iter().map(|s| s.to_u16()).collect();
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::new::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::new::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::new::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::new::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::new::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::new::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::new::{closure#0}
427
0
        encoder.write_tag(Tag::SampleFormat, &sample_format[..])?;
428
0
        encoder.write_tag(Tag::PhotometricInterpretation, <T>::TIFF_VALUE.to_u16())?;
429
430
0
        encoder.write_tag(Tag::RowsPerStrip, u32::try_from(rows_per_strip)?)?;
431
432
0
        encoder.write_tag(
433
0
            Tag::SamplesPerPixel,
434
0
            u16::try_from(<T>::BITS_PER_SAMPLE.len())?,
435
0
        )?;
436
0
        encoder.write_tag(Tag::XResolution, Rational { n: 1, d: 1 })?;
437
0
        encoder.write_tag(Tag::YResolution, Rational { n: 1, d: 1 })?;
438
0
        encoder.write_tag(Tag::ResolutionUnit, ResolutionUnit::None.to_u16())?;
439
440
0
        Ok(ImageEncoder {
441
0
            encoder,
442
0
            strip_count,
443
0
            strip_idx: 0,
444
0
            row_samples,
445
0
            rows_per_strip,
446
0
            width,
447
0
            height,
448
0
            strip_offsets: Vec::new(),
449
0
            strip_byte_count: Vec::new(),
450
0
            dropped: false,
451
0
            compression,
452
0
            predictor,
453
0
            _phantom: ::std::marker::PhantomData,
454
0
        })
455
0
    }
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::new
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::new
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::new
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::new
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::new
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::new
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::new
456
457
    /// Number of samples the next strip should have.
458
0
    pub fn next_strip_sample_count(&self) -> u64 {
459
0
        if self.strip_idx >= self.strip_count {
460
0
            return 0;
461
0
        }
462
0
463
0
        let raw_start_row = self.strip_idx * self.rows_per_strip;
464
0
        let start_row = cmp::min(u64::from(self.height), raw_start_row);
465
0
        let end_row = cmp::min(u64::from(self.height), raw_start_row + self.rows_per_strip);
466
0
467
0
        (end_row - start_row) * self.row_samples
468
0
    }
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::next_strip_sample_count
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::next_strip_sample_count
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::next_strip_sample_count
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::next_strip_sample_count
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::next_strip_sample_count
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::next_strip_sample_count
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::next_strip_sample_count
469
470
    /// Write a single strip.
471
0
    pub fn write_strip(&mut self, value: &[T::Inner]) -> TiffResult<()>
472
0
    where
473
0
        [T::Inner]: TiffValue,
474
0
    {
475
0
        let samples = self.next_strip_sample_count();
476
0
        if u64::try_from(value.len())? != samples {
477
0
            return Err(io::Error::new(
478
0
                io::ErrorKind::InvalidData,
479
0
                "Slice is wrong size for strip",
480
0
            )
481
0
            .into());
482
0
        }
483
484
        // Write the (possible compressed) data to the encoder.
485
0
        let offset = match self.predictor {
486
0
            Predictor::None => self.encoder.write_data(value)?,
487
            Predictor::Horizontal => {
488
0
                let mut row_result = Vec::with_capacity(value.len());
489
0
                for row in value.chunks_exact(self.row_samples as usize) {
490
0
                    T::horizontal_predict(row, &mut row_result);
491
0
                }
492
0
                self.encoder.write_data(row_result.as_slice())?
493
            }
494
0
            _ => unimplemented!(),
495
        };
496
497
0
        let byte_count = self.encoder.last_written() as usize;
498
0
499
0
        self.strip_offsets.push(K::convert_offset(offset)?);
500
0
        self.strip_byte_count.push(byte_count.try_into()?);
501
502
0
        self.strip_idx += 1;
503
0
        Ok(())
504
0
    }
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::write_strip
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::write_strip
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::write_strip
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::write_strip
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::write_strip
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::write_strip
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::write_strip
505
506
    /// Write strips from data
507
0
    pub fn write_data(mut self, data: &[T::Inner]) -> TiffResult<()>
508
0
    where
509
0
        [T::Inner]: TiffValue,
510
0
    {
511
0
        let num_pix = usize::try_from(self.width)?
512
0
            .checked_mul(usize::try_from(self.height)?)
513
0
            .ok_or_else(|| {
514
0
                io::Error::new(
515
0
                    io::ErrorKind::InvalidInput,
516
0
                    "Image width * height exceeds usize",
517
0
                )
518
0
            })?;
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::write_data::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::write_data::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::write_data::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::write_data::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::write_data::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::write_data::{closure#0}
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::write_data::{closure#0}
519
0
        if data.len() < num_pix {
520
0
            return Err(io::Error::new(
521
0
                io::ErrorKind::InvalidData,
522
0
                "Input data slice is undersized for provided dimensions",
523
0
            )
524
0
            .into());
525
0
        }
526
0
527
0
        self.encoder
528
0
            .writer
529
0
            .set_compression(self.compression.get_algorithm());
530
0
531
0
        let mut idx = 0;
532
0
        while self.next_strip_sample_count() > 0 {
533
0
            let sample_count = usize::try_from(self.next_strip_sample_count())?;
534
0
            self.write_strip(&data[idx..idx + sample_count])?;
535
0
            idx += sample_count;
536
        }
537
538
0
        self.encoder.writer.reset_compression();
539
0
        self.finish()?;
540
0
        Ok(())
541
0
    }
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::write_data
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::write_data
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::write_data
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::write_data
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::write_data
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::write_data
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::write_data
542
543
    /// Set image resolution
544
0
    pub fn resolution(&mut self, unit: ResolutionUnit, value: Rational) {
545
0
        self.encoder
546
0
            .write_tag(Tag::ResolutionUnit, unit.to_u16())
547
0
            .unwrap();
548
0
        self.encoder
549
0
            .write_tag(Tag::XResolution, value.clone())
550
0
            .unwrap();
551
0
        self.encoder.write_tag(Tag::YResolution, value).unwrap();
552
0
    }
553
554
    /// Set image resolution unit
555
0
    pub fn resolution_unit(&mut self, unit: ResolutionUnit) {
556
0
        self.encoder
557
0
            .write_tag(Tag::ResolutionUnit, unit.to_u16())
558
0
            .unwrap();
559
0
    }
560
561
    /// Set image x-resolution
562
0
    pub fn x_resolution(&mut self, value: Rational) {
563
0
        self.encoder.write_tag(Tag::XResolution, value).unwrap();
564
0
    }
565
566
    /// Set image y-resolution
567
0
    pub fn y_resolution(&mut self, value: Rational) {
568
0
        self.encoder.write_tag(Tag::YResolution, value).unwrap();
569
0
    }
570
571
    /// Set image number of lines per strip
572
    ///
573
    /// This function needs to be called before any calls to `write_data` or
574
    /// `write_strip` and will return an error otherwise.
575
0
    pub fn rows_per_strip(&mut self, value: u32) -> TiffResult<()> {
576
0
        if self.strip_idx != 0 {
577
0
            return Err(io::Error::new(
578
0
                io::ErrorKind::InvalidInput,
579
0
                "Cannot change strip size after data was written",
580
0
            )
581
0
            .into());
582
0
        }
583
0
        // Write tag as 32 bits
584
0
        self.encoder.write_tag(Tag::RowsPerStrip, value)?;
585
586
0
        let value: u64 = value as u64;
587
0
        self.strip_count = (self.height as u64 + value - 1) / value;
588
0
        self.rows_per_strip = value;
589
0
590
0
        Ok(())
591
0
    }
592
593
0
    fn finish_internal(&mut self) -> TiffResult<()> {
594
0
        self.encoder
595
0
            .write_tag(Tag::StripOffsets, K::convert_slice(&self.strip_offsets))?;
596
0
        self.encoder.write_tag(
597
0
            Tag::StripByteCounts,
598
0
            K::convert_slice(&self.strip_byte_count),
599
0
        )?;
600
0
        self.dropped = true;
601
0
602
0
        self.encoder.finish_internal()
603
0
    }
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::finish_internal
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::finish_internal
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::finish_internal
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::finish_internal
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::finish_internal
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::finish_internal
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::finish_internal
604
605
    /// Get a reference of the underlying `DirectoryEncoder`
606
0
    pub fn encoder(&mut self) -> &mut DirectoryEncoder<'a, W, K> {
607
0
        &mut self.encoder
608
0
    }
609
610
    /// Write out image and ifd directory.
611
0
    pub fn finish(mut self) -> TiffResult<()> {
612
0
        self.finish_internal()
613
0
    }
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _>>::finish
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard>>::finish
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard>>::finish
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard>>::finish
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard>>::finish
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard>>::finish
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard>>::finish
614
}
615
616
impl<'a, W: Write + Seek, C: ColorType, K: TiffKind> Drop for ImageEncoder<'a, W, C, K> {
617
0
    fn drop(&mut self) {
618
0
        if !self.dropped {
619
0
            let _ = self.finish_internal();
620
0
        }
621
0
    }
Unexecuted instantiation: <tiff::encoder::ImageEncoder<_, _, _> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB8, tiff::encoder::TiffKindStandard> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray8, tiff::encoder::TiffKindStandard> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGB16, tiff::encoder::TiffKindStandard> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA8, tiff::encoder::TiffKindStandard> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::Gray16, tiff::encoder::TiffKindStandard> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <tiff::encoder::ImageEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, tiff::encoder::colortype::RGBA16, tiff::encoder::TiffKindStandard> as core::ops::drop::Drop>::drop
622
}
623
624
struct DirectoryEntry<S> {
625
    data_type: u16,
626
    count: S,
627
    data: Vec<u8>,
628
}
629
630
/// Trait to abstract over Tiff/BigTiff differences.
631
///
632
/// Implemented for [`TiffKindStandard`] and [`TiffKindBig`].
633
pub trait TiffKind {
634
    /// The type of offset fields, `u32` for normal Tiff, `u64` for BigTiff.
635
    type OffsetType: TryFrom<usize, Error = TryFromIntError> + Into<u64> + TiffValue;
636
637
    /// Needed for the `convert_slice` method.
638
    type OffsetArrayType: ?Sized + TiffValue;
639
640
    /// Write the (Big)Tiff header.
641
    fn write_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<()>;
642
643
    /// Convert a file offset to `Self::OffsetType`.
644
    ///
645
    /// This returns an error for normal Tiff if the offset is larger than `u32::MAX`.
646
    fn convert_offset(offset: u64) -> TiffResult<Self::OffsetType>;
647
648
    /// Write an offset value to the given writer.
649
    ///
650
    /// Like `convert_offset`, this errors if `offset > u32::MAX` for normal Tiff.
651
    fn write_offset<W: Write>(writer: &mut TiffWriter<W>, offset: u64) -> TiffResult<()>;
652
653
    /// Write the IFD entry count field with the given `count` value.
654
    ///
655
    /// The entry count field is an `u16` for normal Tiff and `u64` for BigTiff. Errors
656
    /// if the given `usize` is larger than the representable values.
657
    fn write_entry_count<W: Write>(writer: &mut TiffWriter<W>, count: usize) -> TiffResult<()>;
658
659
    /// Internal helper method for satisfying Rust's type checker.
660
    ///
661
    /// The `TiffValue` trait is implemented for both primitive values (e.g. `u8`, `u32`) and
662
    /// slices of primitive values (e.g. `[u8]`, `[u32]`). However, this is not represented in
663
    /// the type system, so there is no guarantee that that for all `T: TiffValue` there is also
664
    /// an implementation of `TiffValue` for `[T]`. This method works around that problem by
665
    /// providing a conversion from `[T]` to some value that implements `TiffValue`, thereby
666
    /// making all slices of `OffsetType` usable with `write_tag` and similar methods.
667
    ///
668
    /// Implementations of this trait should always set `OffsetArrayType` to `[OffsetType]`.
669
    fn convert_slice(slice: &[Self::OffsetType]) -> &Self::OffsetArrayType;
670
}
671
672
/// Create a standard Tiff file.
673
pub struct TiffKindStandard;
674
675
impl TiffKind for TiffKindStandard {
676
    type OffsetType = u32;
677
    type OffsetArrayType = [u32];
678
679
0
    fn write_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<()> {
680
0
        write_tiff_header(writer)?;
681
        // blank the IFD offset location
682
0
        writer.write_u32(0)?;
683
684
0
        Ok(())
685
0
    }
Unexecuted instantiation: <tiff::encoder::TiffKindStandard as tiff::encoder::TiffKind>::write_header::<_>
Unexecuted instantiation: <tiff::encoder::TiffKindStandard as tiff::encoder::TiffKind>::write_header::<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>
686
687
0
    fn convert_offset(offset: u64) -> TiffResult<Self::OffsetType> {
688
0
        Ok(Self::OffsetType::try_from(offset)?)
689
0
    }
690
691
0
    fn write_offset<W: Write>(writer: &mut TiffWriter<W>, offset: u64) -> TiffResult<()> {
692
0
        writer.write_u32(u32::try_from(offset)?)?;
693
0
        Ok(())
694
0
    }
Unexecuted instantiation: <tiff::encoder::TiffKindStandard as tiff::encoder::TiffKind>::write_offset::<_>
Unexecuted instantiation: <tiff::encoder::TiffKindStandard as tiff::encoder::TiffKind>::write_offset::<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>
Unexecuted instantiation: <tiff::encoder::TiffKindStandard as tiff::encoder::TiffKind>::write_offset::<&mut [u8]>
695
696
0
    fn write_entry_count<W: Write>(writer: &mut TiffWriter<W>, count: usize) -> TiffResult<()> {
697
0
        writer.write_u16(u16::try_from(count)?)?;
698
699
0
        Ok(())
700
0
    }
Unexecuted instantiation: <tiff::encoder::TiffKindStandard as tiff::encoder::TiffKind>::write_entry_count::<_>
Unexecuted instantiation: <tiff::encoder::TiffKindStandard as tiff::encoder::TiffKind>::write_entry_count::<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>
701
702
0
    fn convert_slice(slice: &[Self::OffsetType]) -> &Self::OffsetArrayType {
703
0
        slice
704
0
    }
705
}
706
707
/// Create a BigTiff file.
708
pub struct TiffKindBig;
709
710
impl TiffKind for TiffKindBig {
711
    type OffsetType = u64;
712
    type OffsetArrayType = [u64];
713
714
0
    fn write_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<()> {
715
0
        write_bigtiff_header(writer)?;
716
        // blank the IFD offset location
717
0
        writer.write_u64(0)?;
718
719
0
        Ok(())
720
0
    }
721
722
0
    fn convert_offset(offset: u64) -> TiffResult<Self::OffsetType> {
723
0
        Ok(offset)
724
0
    }
725
726
0
    fn write_offset<W: Write>(writer: &mut TiffWriter<W>, offset: u64) -> TiffResult<()> {
727
0
        writer.write_u64(offset)?;
728
0
        Ok(())
729
0
    }
730
731
0
    fn write_entry_count<W: Write>(writer: &mut TiffWriter<W>, count: usize) -> TiffResult<()> {
732
0
        writer.write_u64(u64::try_from(count)?)?;
733
0
        Ok(())
734
0
    }
735
736
0
    fn convert_slice(slice: &[Self::OffsetType]) -> &Self::OffsetArrayType {
737
0
        slice
738
0
    }
739
}