Coverage Report

Created: 2025-07-18 06:49

/rust/registry/src/index.crates.io-6f17d22bba15001f/exr-1.73.0/src/block/chunk.rs
Line
Count
Source (jump to first uncovered line)
1
2
//! Read and write already compressed pixel data blocks.
3
//! Does not include the process of compression and decompression.
4
5
use crate::meta::attribute::{IntegerBounds};
6
7
/// A generic block of pixel information.
8
/// Contains pixel data and an index to the corresponding header.
9
/// All pixel data in a file is split into a list of chunks.
10
/// Also contains positioning information that locates this
11
/// data block in the referenced layer.
12
#[derive(Debug, Clone)]
13
pub struct Chunk {
14
15
    /// The index of the layer that the block belongs to.
16
    /// This is required as the pixel data can appear in any order in a file.
17
    // PDF says u64, but source code seems to be i32
18
    pub layer_index: usize,
19
20
    /// The compressed pixel contents.
21
    pub compressed_block: CompressedBlock,
22
}
23
24
/// The raw, possibly compressed pixel data of a file.
25
/// Each layer in a file can have a different type.
26
/// Also contains positioning information that locates this
27
/// data block in the corresponding layer.
28
/// Exists inside a `Chunk`.
29
#[derive(Debug, Clone)]
30
pub enum CompressedBlock {
31
32
    /// Scan line blocks of flat data.
33
    ScanLine(CompressedScanLineBlock),
34
35
    /// Tiles of flat data.
36
    Tile(CompressedTileBlock),
37
38
    /// Scan line blocks of deep data.
39
    DeepScanLine(CompressedDeepScanLineBlock),
40
41
    /// Tiles of deep data.
42
    DeepTile(CompressedDeepTileBlock),
43
}
44
45
/// A `Block` of possibly compressed flat scan lines.
46
/// Corresponds to type attribute `scanlineimage`.
47
#[derive(Debug, Clone)]
48
pub struct CompressedScanLineBlock {
49
50
    /// The block's y coordinate is the pixel space y coordinate of the top scan line in the block.
51
    /// The top scan line block in the image is aligned with the top edge of the data window.
52
    pub y_coordinate: i32,
53
54
    /// One or more scan lines may be stored together as a scan line block.
55
    /// The number of scan lines per block depends on how the pixel data are compressed.
56
    /// For each line in the tile, for each channel, the row values are contiguous.
57
    pub compressed_pixels: Vec<u8>,
58
}
59
60
/// This `Block` is a tile of flat (non-deep) data.
61
/// Corresponds to type attribute `tiledimage`.
62
#[derive(Debug, Clone)]
63
pub struct CompressedTileBlock {
64
65
    /// The tile location.
66
    pub coordinates: TileCoordinates,
67
68
    /// One or more scan lines may be stored together as a scan line block.
69
    /// The number of scan lines per block depends on how the pixel data are compressed.
70
    /// For each line in the tile, for each channel, the row values are contiguous.
71
    pub compressed_pixels: Vec<u8>,
72
}
73
74
/// Indicates the position and resolution level of a `TileBlock` or `DeepTileBlock`.
75
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
76
pub struct TileCoordinates {
77
78
    /// Index of the tile, not pixel position.
79
    pub tile_index: Vec2<usize>,
80
81
    /// Index of the Mip/Rip level.
82
    pub level_index: Vec2<usize>,
83
}
84
85
/// This `Block` consists of one or more deep scan lines.
86
/// Corresponds to type attribute `deepscanline`.
87
#[derive(Debug, Clone)]
88
pub struct CompressedDeepScanLineBlock {
89
90
    /// The block's y coordinate is the pixel space y coordinate of the top scan line in the block.
91
    /// The top scan line block in the image is aligned with the top edge of the data window.
92
    pub y_coordinate: i32,
93
94
    /// Count of samples.
95
    pub decompressed_sample_data_size: usize,
96
97
    /// The pixel offset table is a list of integers, one for each pixel column within the data window.
98
    /// Each entry in the table indicates the total number of samples required
99
    /// to store the pixel in it as well as all pixels to the left of it.
100
    pub compressed_pixel_offset_table: Vec<i8>,
101
102
    /// One or more scan lines may be stored together as a scan line block.
103
    /// The number of scan lines per block depends on how the pixel data are compressed.
104
    /// For each line in the tile, for each channel, the row values are contiguous.
105
    pub compressed_sample_data: Vec<u8>,
106
}
107
108
/// This `Block` is a tile of deep data.
109
/// Corresponds to type attribute `deeptile`.
110
#[derive(Debug, Clone)]
111
pub struct CompressedDeepTileBlock {
112
113
    /// The tile location.
114
    pub coordinates: TileCoordinates,
115
116
    /// Count of samples.
117
    pub decompressed_sample_data_size: usize,
118
119
    /// The pixel offset table is a list of integers, one for each pixel column within the data window.
120
    /// Each entry in the table indicates the total number of samples required
121
    /// to store the pixel in it as well as all pixels to the left of it.
122
    pub compressed_pixel_offset_table: Vec<i8>,
123
124
    /// One or more scan lines may be stored together as a scan line block.
125
    /// The number of scan lines per block depends on how the pixel data are compressed.
126
    /// For each line in the tile, for each channel, the row values are contiguous.
127
    pub compressed_sample_data: Vec<u8>,
128
}
129
130
131
use crate::io::*;
132
133
impl TileCoordinates {
134
135
    /// Without validation, write this instance to the byte stream.
136
913
    pub fn write<W: Write>(&self, write: &mut W) -> UnitResult {
137
913
        i32::write(usize_to_i32(self.tile_index.x()), write)?;
138
913
        i32::write(usize_to_i32(self.tile_index.y()), write)?;
139
913
        i32::write(usize_to_i32(self.level_index.x()), write)?;
140
913
        i32::write(usize_to_i32(self.level_index.y()), write)?;
141
913
        Ok(())
142
913
    }
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::write::<_>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::write::<exr::io::Tracking<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>
<exr::block::chunk::TileCoordinates>::write::<exr::io::Tracking<&mut std::io::cursor::Cursor<&mut alloc::vec::Vec<u8>>>>
Line
Count
Source
136
913
    pub fn write<W: Write>(&self, write: &mut W) -> UnitResult {
137
913
        i32::write(usize_to_i32(self.tile_index.x()), write)?;
138
913
        i32::write(usize_to_i32(self.tile_index.y()), write)?;
139
913
        i32::write(usize_to_i32(self.level_index.x()), write)?;
140
913
        i32::write(usize_to_i32(self.level_index.y()), write)?;
141
913
        Ok(())
142
913
    }
143
144
    /// Read the value without validating.
145
2.21k
    pub fn read(read: &mut impl Read) -> Result<Self> {
146
2.21k
        let tile_x = i32::read(read)?;
147
2.00k
        let tile_y = i32::read(read)?;
148
149
2.00k
        let level_x = i32::read(read)?;
150
2.00k
        let level_y = i32::read(read)?;
151
152
2.00k
        if level_x > 31 || level_y > 31 {
153
            // there can be at most 31 levels, because the largest level would have a size of 2^31,
154
            // which exceeds the maximum 32-bit integer value.
155
861
            return Err(Error::invalid("level index exceeding integer maximum"));
156
1.14k
        }
157
1.14k
158
1.14k
        Ok(TileCoordinates {
159
1.14k
            tile_index: Vec2(tile_x, tile_y).to_usize("tile coordinate index")?,
160
1.10k
            level_index: Vec2(level_x, level_y).to_usize("tile coordinate level")?
161
        })
162
2.21k
    }
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<_>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
<exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Line
Count
Source
145
1.29k
    pub fn read(read: &mut impl Read) -> Result<Self> {
146
1.29k
        let tile_x = i32::read(read)?;
147
1.09k
        let tile_y = i32::read(read)?;
148
149
1.09k
        let level_x = i32::read(read)?;
150
1.09k
        let level_y = i32::read(read)?;
151
152
1.09k
        if level_x > 31 || level_y > 31 {
153
            // there can be at most 31 levels, because the largest level would have a size of 2^31,
154
            // which exceeds the maximum 32-bit integer value.
155
861
            return Err(Error::invalid("level index exceeding integer maximum"));
156
230
        }
157
230
158
230
        Ok(TileCoordinates {
159
230
            tile_index: Vec2(tile_x, tile_y).to_usize("tile coordinate index")?,
160
195
            level_index: Vec2(level_x, level_y).to_usize("tile coordinate level")?
161
        })
162
1.29k
    }
<exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>>
Line
Count
Source
145
913
    pub fn read(read: &mut impl Read) -> Result<Self> {
146
913
        let tile_x = i32::read(read)?;
147
913
        let tile_y = i32::read(read)?;
148
149
913
        let level_x = i32::read(read)?;
150
913
        let level_y = i32::read(read)?;
151
152
913
        if level_x > 31 || level_y > 31 {
153
            // there can be at most 31 levels, because the largest level would have a size of 2^31,
154
            // which exceeds the maximum 32-bit integer value.
155
0
            return Err(Error::invalid("level index exceeding integer maximum"));
156
913
        }
157
913
158
913
        Ok(TileCoordinates {
159
913
            tile_index: Vec2(tile_x, tile_y).to_usize("tile coordinate index")?,
160
913
            level_index: Vec2(level_x, level_y).to_usize("tile coordinate level")?
161
        })
162
913
    }
Unexecuted instantiation: <exr::block::chunk::TileCoordinates>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
163
164
    /// The indices which can be used to index into the arrays of a data window.
165
    /// These coordinates are only valid inside the corresponding one header.
166
    /// Will start at 0 and always be positive.
167
416k
    pub fn to_data_indices(&self, tile_size: Vec2<usize>, max: Vec2<usize>) -> Result<IntegerBounds> {
168
416k
        let x = self.tile_index.x() * tile_size.width();
169
416k
        let y = self.tile_index.y() * tile_size.height();
170
416k
171
416k
        if x >= max.x() || y >= max.y() {
172
86
            Err(Error::invalid("tile index"))
173
        }
174
        else {
175
            Ok(IntegerBounds {
176
416k
                position: Vec2(usize_to_i32(x), usize_to_i32(y)),
177
416k
                size: Vec2(
178
416k
                    calculate_block_size(max.x(), tile_size.width(), x)?,
179
416k
                    calculate_block_size(max.y(), tile_size.height(), y)?,
180
                ),
181
            })
182
        }
183
416k
    }
184
185
    /// Absolute coordinates inside the global 2D space of a file, may be negative.
186
0
    pub fn to_absolute_indices(&self, tile_size: Vec2<usize>, data_window: IntegerBounds) -> Result<IntegerBounds> {
187
0
        let data = self.to_data_indices(tile_size, data_window.size)?;
188
0
        Ok(data.with_origin(data_window.position))
189
0
    }
190
191
    /// Returns if this is the original resolution or a smaller copy.
192
654k
    pub fn is_largest_resolution_level(&self) -> bool {
193
654k
        self.level_index == Vec2(0, 0)
194
654k
    }
195
}
196
197
198
199
use crate::meta::{MetaData, BlockDescription, calculate_block_size};
200
201
impl CompressedScanLineBlock {
202
203
    /// Without validation, write this instance to the byte stream.
204
0
    pub fn write<W: Write>(&self, write: &mut W) -> UnitResult {
205
0
        debug_assert_ne!(self.compressed_pixels.len(), 0, "empty blocks should not be put in the file bug");
206
207
0
        i32::write(self.y_coordinate, write)?;
208
0
        u8::write_i32_sized_slice(write, &self.compressed_pixels)?;
209
0
        Ok(())
210
0
    }
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::write::<_>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::write::<exr::io::Tracking<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::write::<exr::io::Tracking<&mut std::io::cursor::Cursor<&mut alloc::vec::Vec<u8>>>>
211
212
    /// Read the value without validating.
213
1.59k
    pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result<Self> {
214
1.59k
        let y_coordinate = i32::read(read)?;
215
1.52k
        let compressed_pixels = u8::read_i32_sized_vec(read, max_block_byte_size, Some(max_block_byte_size), "scan line block sample count")?;
216
1.42k
        Ok(CompressedScanLineBlock { y_coordinate, compressed_pixels })
217
1.59k
    }
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<_>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
<exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Line
Count
Source
213
1.06k
    pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result<Self> {
214
1.06k
        let y_coordinate = i32::read(read)?;
215
990
        let compressed_pixels = u8::read_i32_sized_vec(read, max_block_byte_size, Some(max_block_byte_size), "scan line block sample count")?;
216
892
        Ok(CompressedScanLineBlock { y_coordinate, compressed_pixels })
217
1.06k
    }
Unexecuted instantiation: <exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>>
<exr::block::chunk::CompressedScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Line
Count
Source
213
533
    pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result<Self> {
214
533
        let y_coordinate = i32::read(read)?;
215
533
        let compressed_pixels = u8::read_i32_sized_vec(read, max_block_byte_size, Some(max_block_byte_size), "scan line block sample count")?;
216
529
        Ok(CompressedScanLineBlock { y_coordinate, compressed_pixels })
217
533
    }
218
}
219
220
impl CompressedTileBlock {
221
222
    /// Without validation, write this instance to the byte stream.
223
913
    pub fn write<W: Write>(&self, write: &mut W) -> UnitResult {
224
913
        debug_assert_ne!(self.compressed_pixels.len(), 0, "empty blocks should not be put in the file bug");
225
226
913
        self.coordinates.write(write)?;
227
913
        u8::write_i32_sized_slice(write, &self.compressed_pixels)?;
228
913
        Ok(())
229
913
    }
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::write::<_>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::write::<exr::io::Tracking<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>
<exr::block::chunk::CompressedTileBlock>::write::<exr::io::Tracking<&mut std::io::cursor::Cursor<&mut alloc::vec::Vec<u8>>>>
Line
Count
Source
223
913
    pub fn write<W: Write>(&self, write: &mut W) -> UnitResult {
224
913
        debug_assert_ne!(self.compressed_pixels.len(), 0, "empty blocks should not be put in the file bug");
225
226
913
        self.coordinates.write(write)?;
227
913
        u8::write_i32_sized_slice(write, &self.compressed_pixels)?;
228
913
        Ok(())
229
913
    }
230
231
    /// Read the value without validating.
232
2.21k
    pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result<Self> {
233
2.21k
        let coordinates = TileCoordinates::read(read)?;
234
1.06k
        let compressed_pixels = u8::read_i32_sized_vec(read, max_block_byte_size, Some(max_block_byte_size), "tile block sample count")?;
235
1.04k
        Ok(CompressedTileBlock { coordinates, compressed_pixels })
236
2.21k
    }
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<_>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
<exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Line
Count
Source
232
1.29k
    pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result<Self> {
233
1.29k
        let coordinates = TileCoordinates::read(read)?;
234
155
        let compressed_pixels = u8::read_i32_sized_vec(read, max_block_byte_size, Some(max_block_byte_size), "tile block sample count")?;
235
133
        Ok(CompressedTileBlock { coordinates, compressed_pixels })
236
1.29k
    }
<exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>>
Line
Count
Source
232
913
    pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result<Self> {
233
913
        let coordinates = TileCoordinates::read(read)?;
234
913
        let compressed_pixels = u8::read_i32_sized_vec(read, max_block_byte_size, Some(max_block_byte_size), "tile block sample count")?;
235
913
        Ok(CompressedTileBlock { coordinates, compressed_pixels })
236
913
    }
Unexecuted instantiation: <exr::block::chunk::CompressedTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
237
}
238
239
impl CompressedDeepScanLineBlock {
240
241
    /// Without validation, write this instance to the byte stream.
242
0
    pub fn write<W: Write>(&self, write: &mut W) -> UnitResult {
243
0
        debug_assert_ne!(self.compressed_sample_data.len(), 0, "empty blocks should not be put in the file bug");
244
245
0
        i32::write(self.y_coordinate, write)?;
246
0
        u64::write(self.compressed_pixel_offset_table.len() as u64, write)?;
247
0
        u64::write(self.compressed_sample_data.len() as u64, write)?; // TODO just guessed
248
0
        u64::write(self.decompressed_sample_data_size as u64, write)?;
249
0
        i8::write_slice(write, &self.compressed_pixel_offset_table)?;
250
0
        u8::write_slice(write, &self.compressed_sample_data)?;
251
0
        Ok(())
252
0
    }
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::write::<_>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::write::<exr::io::Tracking<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::write::<exr::io::Tracking<&mut std::io::cursor::Cursor<&mut alloc::vec::Vec<u8>>>>
253
254
    /// Read the value without validating.
255
0
    pub fn read(read: &mut impl Read, max_block_byte_size: usize) -> Result<Self> {
256
0
        let y_coordinate = i32::read(read)?;
257
0
        let compressed_pixel_offset_table_size = u64_to_usize(u64::read(read)?);
258
0
        let compressed_sample_data_size = u64_to_usize(u64::read(read)?);
259
0
        let decompressed_sample_data_size = u64_to_usize(u64::read(read)?);
260
261
        // doc said i32, try u8
262
0
        let compressed_pixel_offset_table = i8::read_vec(
263
0
            read, compressed_pixel_offset_table_size,
264
0
            6 * u16::MAX as usize, Some(max_block_byte_size),
265
0
            "deep scan line block table size"
266
0
        )?;
267
268
0
        let compressed_sample_data = u8::read_vec(
269
0
            read, compressed_sample_data_size,
270
0
            6 * u16::MAX as usize, Some(max_block_byte_size),
271
0
            "deep scan line block sample count"
272
0
        )?;
273
274
0
        Ok(CompressedDeepScanLineBlock {
275
0
            y_coordinate,
276
0
            decompressed_sample_data_size,
277
0
            compressed_pixel_offset_table,
278
0
            compressed_sample_data,
279
0
        })
280
0
    }
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<_>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepScanLineBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
281
}
282
283
284
impl CompressedDeepTileBlock {
285
286
    /// Without validation, write this instance to the byte stream.
287
0
    pub fn write<W: Write>(&self, write: &mut W) -> UnitResult {
288
0
        debug_assert_ne!(self.compressed_sample_data.len(), 0, "empty blocks should not be put in the file bug");
289
290
0
        self.coordinates.write(write)?;
291
0
        u64::write(self.compressed_pixel_offset_table.len() as u64, write)?;
292
0
        u64::write(self.compressed_sample_data.len() as u64, write)?; // TODO just guessed
293
0
        u64::write(self.decompressed_sample_data_size as u64, write)?;
294
0
        i8::write_slice(write, &self.compressed_pixel_offset_table)?;
295
0
        u8::write_slice(write, &self.compressed_sample_data)?;
296
0
        Ok(())
297
0
    }
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::write::<_>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::write::<exr::io::Tracking<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::write::<exr::io::Tracking<&mut std::io::cursor::Cursor<&mut alloc::vec::Vec<u8>>>>
298
299
    /// Read the value without validating.
300
0
    pub fn read(read: &mut impl Read, hard_max_block_byte_size: usize) -> Result<Self> {
301
0
        let coordinates = TileCoordinates::read(read)?;
302
0
        let compressed_pixel_offset_table_size = u64_to_usize(u64::read(read)?);
303
0
        let compressed_sample_data_size = u64_to_usize(u64::read(read)?); // TODO u64 just guessed
304
0
        let decompressed_sample_data_size = u64_to_usize(u64::read(read)?);
305
306
0
        let compressed_pixel_offset_table = i8::read_vec(
307
0
            read, compressed_pixel_offset_table_size,
308
0
            6 * u16::MAX as usize, Some(hard_max_block_byte_size),
309
0
            "deep tile block table size"
310
0
        )?;
311
312
0
        let compressed_sample_data = u8::read_vec(
313
0
            read, compressed_sample_data_size,
314
0
            6 * u16::MAX as usize, Some(hard_max_block_byte_size),
315
0
            "deep tile block sample count"
316
0
        )?;
317
318
0
        Ok(CompressedDeepTileBlock {
319
0
            coordinates,
320
0
            decompressed_sample_data_size,
321
0
            compressed_pixel_offset_table,
322
0
            compressed_sample_data,
323
0
        })
324
0
    }
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<_>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>>
Unexecuted instantiation: <exr::block::chunk::CompressedDeepTileBlock>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
325
}
326
327
use crate::error::{UnitResult, Result, Error, u64_to_usize, usize_to_i32, i32_to_usize};
328
use crate::math::Vec2;
329
330
/// Validation of chunks is done while reading and writing the actual data. (For example in exr::full_image)
331
impl Chunk {
332
333
    /// Without validation, write this instance to the byte stream.
334
913
    pub fn write(&self, write: &mut impl Write, header_count: usize) -> UnitResult {
335
913
        debug_assert!(self.layer_index < header_count, "layer index bug"); // validation is done in full_image or simple_image
336
337
913
        if header_count != 1 {  usize_to_i32(self.layer_index).write(write)?; }
338
913
        else { assert_eq!(self.layer_index, 0, "invalid header index for single layer file"); }
339
340
913
        match self.compressed_block {
341
0
            CompressedBlock::ScanLine     (ref value) => value.write(write),
342
913
            CompressedBlock::Tile         (ref value) => value.write(write),
343
0
            CompressedBlock::DeepScanLine (ref value) => value.write(write),
344
0
            CompressedBlock::DeepTile     (ref value) => value.write(write),
345
        }
346
913
    }
Unexecuted instantiation: <exr::block::chunk::Chunk>::write::<_>
Unexecuted instantiation: <exr::block::chunk::Chunk>::write::<exr::io::Tracking<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>
<exr::block::chunk::Chunk>::write::<exr::io::Tracking<&mut std::io::cursor::Cursor<&mut alloc::vec::Vec<u8>>>>
Line
Count
Source
334
913
    pub fn write(&self, write: &mut impl Write, header_count: usize) -> UnitResult {
335
913
        debug_assert!(self.layer_index < header_count, "layer index bug"); // validation is done in full_image or simple_image
336
337
913
        if header_count != 1 {  usize_to_i32(self.layer_index).write(write)?; }
338
913
        else { assert_eq!(self.layer_index, 0, "invalid header index for single layer file"); }
339
340
913
        match self.compressed_block {
341
0
            CompressedBlock::ScanLine     (ref value) => value.write(write),
342
913
            CompressedBlock::Tile         (ref value) => value.write(write),
343
0
            CompressedBlock::DeepScanLine (ref value) => value.write(write),
344
0
            CompressedBlock::DeepTile     (ref value) => value.write(write),
345
        }
346
913
    }
347
348
    /// Read the value without validating.
349
3.81k
    pub fn read(read: &mut impl Read, meta_data: &MetaData) -> Result<Self> {
350
3.81k
        let layer_number = i32_to_usize(
351
3.81k
            if meta_data.requirements.is_multilayer() { i32::read(read)? } // documentation says u64, but is i32
352
3.80k
            else { 0_i32 }, // reference the first header for single-layer images
353
            "chunk data part number"
354
0
        )?;
355
356
3.81k
        if layer_number >= meta_data.headers.len() {
357
1
            return Err(Error::invalid("chunk data part number"));
358
3.80k
        }
359
3.80k
360
3.80k
        let header = &meta_data.headers[layer_number];
361
3.80k
        let max_block_byte_size = header.max_block_byte_size();
362
363
2.46k
        let chunk = Chunk {
364
3.80k
            layer_index: layer_number,
365
1.59k
            compressed_block: match header.blocks {
366
                // flat data
367
1.59k
                BlockDescription::ScanLines if !header.deep => CompressedBlock::ScanLine(CompressedScanLineBlock::read(read, max_block_byte_size)?),
368
2.21k
                BlockDescription::Tiles(_) if !header.deep     => CompressedBlock::Tile(CompressedTileBlock::read(read, max_block_byte_size)?),
369
370
                // deep data
371
0
                BlockDescription::ScanLines   => CompressedBlock::DeepScanLine(CompressedDeepScanLineBlock::read(read, max_block_byte_size)?),
372
0
                BlockDescription::Tiles(_)    => CompressedBlock::DeepTile(CompressedDeepTileBlock::read(read, max_block_byte_size)?),
373
            },
374
        };
375
376
2.46k
        Ok(chunk)
377
3.81k
    }
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<_>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Unexecuted instantiation: <exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
<exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Line
Count
Source
349
2.36k
    pub fn read(read: &mut impl Read, meta_data: &MetaData) -> Result<Self> {
350
2.36k
        let layer_number = i32_to_usize(
351
2.36k
            if meta_data.requirements.is_multilayer() { i32::read(read)? } // documentation says u64, but is i32
352
2.36k
            else { 0_i32 }, // reference the first header for single-layer images
353
            "chunk data part number"
354
0
        )?;
355
356
2.36k
        if layer_number >= meta_data.headers.len() {
357
1
            return Err(Error::invalid("chunk data part number"));
358
2.36k
        }
359
2.36k
360
2.36k
        let header = &meta_data.headers[layer_number];
361
2.36k
        let max_block_byte_size = header.max_block_byte_size();
362
363
1.02k
        let chunk = Chunk {
364
2.36k
            layer_index: layer_number,
365
1.06k
            compressed_block: match header.blocks {
366
                // flat data
367
1.06k
                BlockDescription::ScanLines if !header.deep => CompressedBlock::ScanLine(CompressedScanLineBlock::read(read, max_block_byte_size)?),
368
1.29k
                BlockDescription::Tiles(_) if !header.deep     => CompressedBlock::Tile(CompressedTileBlock::read(read, max_block_byte_size)?),
369
370
                // deep data
371
0
                BlockDescription::ScanLines   => CompressedBlock::DeepScanLine(CompressedDeepScanLineBlock::read(read, max_block_byte_size)?),
372
0
                BlockDescription::Tiles(_)    => CompressedBlock::DeepTile(CompressedDeepTileBlock::read(read, max_block_byte_size)?),
373
            },
374
        };
375
376
1.02k
        Ok(chunk)
377
2.36k
    }
<exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>>
Line
Count
Source
349
913
    pub fn read(read: &mut impl Read, meta_data: &MetaData) -> Result<Self> {
350
913
        let layer_number = i32_to_usize(
351
913
            if meta_data.requirements.is_multilayer() { i32::read(read)? } // documentation says u64, but is i32
352
913
            else { 0_i32 }, // reference the first header for single-layer images
353
            "chunk data part number"
354
0
        )?;
355
356
913
        if layer_number >= meta_data.headers.len() {
357
0
            return Err(Error::invalid("chunk data part number"));
358
913
        }
359
913
360
913
        let header = &meta_data.headers[layer_number];
361
913
        let max_block_byte_size = header.max_block_byte_size();
362
363
913
        let chunk = Chunk {
364
913
            layer_index: layer_number,
365
0
            compressed_block: match header.blocks {
366
                // flat data
367
0
                BlockDescription::ScanLines if !header.deep => CompressedBlock::ScanLine(CompressedScanLineBlock::read(read, max_block_byte_size)?),
368
913
                BlockDescription::Tiles(_) if !header.deep     => CompressedBlock::Tile(CompressedTileBlock::read(read, max_block_byte_size)?),
369
370
                // deep data
371
0
                BlockDescription::ScanLines   => CompressedBlock::DeepScanLine(CompressedDeepScanLineBlock::read(read, max_block_byte_size)?),
372
0
                BlockDescription::Tiles(_)    => CompressedBlock::DeepTile(CompressedDeepTileBlock::read(read, max_block_byte_size)?),
373
            },
374
        };
375
376
913
        Ok(chunk)
377
913
    }
<exr::block::chunk::Chunk>::read::<exr::io::PeekRead<exr::io::Tracking<std::io::cursor::Cursor<&[u8]>>>>
Line
Count
Source
349
533
    pub fn read(read: &mut impl Read, meta_data: &MetaData) -> Result<Self> {
350
533
        let layer_number = i32_to_usize(
351
533
            if meta_data.requirements.is_multilayer() { i32::read(read)? } // documentation says u64, but is i32
352
533
            else { 0_i32 }, // reference the first header for single-layer images
353
            "chunk data part number"
354
0
        )?;
355
356
533
        if layer_number >= meta_data.headers.len() {
357
0
            return Err(Error::invalid("chunk data part number"));
358
533
        }
359
533
360
533
        let header = &meta_data.headers[layer_number];
361
533
        let max_block_byte_size = header.max_block_byte_size();
362
363
529
        let chunk = Chunk {
364
533
            layer_index: layer_number,
365
533
            compressed_block: match header.blocks {
366
                // flat data
367
533
                BlockDescription::ScanLines if !header.deep => CompressedBlock::ScanLine(CompressedScanLineBlock::read(read, max_block_byte_size)?),
368
0
                BlockDescription::Tiles(_) if !header.deep     => CompressedBlock::Tile(CompressedTileBlock::read(read, max_block_byte_size)?),
369
370
                // deep data
371
0
                BlockDescription::ScanLines   => CompressedBlock::DeepScanLine(CompressedDeepScanLineBlock::read(read, max_block_byte_size)?),
372
0
                BlockDescription::Tiles(_)    => CompressedBlock::DeepTile(CompressedDeepTileBlock::read(read, max_block_byte_size)?),
373
            },
374
        };
375
376
529
        Ok(chunk)
377
533
    }
378
}
379