exr/image/read/
layers.rs

1//! How to read either a single or a list of layers.
2
3use crate::image::*;
4use crate::meta::header::{Header, LayerAttributes};
5use crate::error::{Result, UnitResult, Error};
6use crate::block::{UncompressedBlock, BlockIndex};
7use crate::math::Vec2;
8use crate::image::read::image::{ReadLayers, LayersReader};
9use crate::block::chunk::TileCoordinates;
10use crate::meta::MetaData;
11
12/// Specify to read all channels, aborting if any one is invalid.
13/// [`ReadRgbaChannels`] or [`ReadAnyChannels<ReadFlatSamples>`].
14#[derive(Debug, Clone, Eq, PartialEq)]
15pub struct ReadAllLayers<ReadChannels> {
16
17    /// The channel reading specification
18    pub read_channels: ReadChannels,
19}
20
21/// Specify to read only the first layer which meets the previously specified requirements
22// FIXME do not throw error on deep data but just skip it!
23#[derive(Debug, Clone, Eq, PartialEq)]
24pub struct ReadFirstValidLayer<ReadChannels> {
25
26    /// The channel reading specification
27    pub read_channels: ReadChannels,
28}
29
30/// A template that creates a [`ChannelsReader`] once for all channels per layer.
31pub trait ReadChannels<'s> {
32
33    /// The type of the temporary channels reader
34    type Reader: ChannelsReader;
35
36    /// Create a single reader for all channels of a specific layer
37    fn create_channels_reader(&'s self, header: &Header) -> Result<Self::Reader>;
38
39
40    /// Read only the first layer which meets the previously specified requirements
41    /// For example, skips layers with deep data, if specified earlier.
42    /// Aborts if the image contains no layers.
43    // TODO test if this filters non-deep layers while ignoring deep data layers!
44    fn first_valid_layer(self) -> ReadFirstValidLayer<Self> where Self:Sized { ReadFirstValidLayer { read_channels: self } }
45
46// FIXME do not throw error on deep data but just skip it!
47
48
49    /// Reads all layers, including an empty list. Aborts if any of the layers are invalid,
50    /// even if only one of the layers contains unexpected data.
51    fn all_layers(self) -> ReadAllLayers<Self> where Self:Sized { ReadAllLayers { read_channels: self } }
52
53    // TODO pub fn all_valid_layers(self) -> ReadAllValidLayers<Self> { ReadAllValidLayers { read_channels: self } }
54}
55
56
57/// Processes pixel blocks from a file and accumulates them into a list of layers.
58/// For example, `ChannelsReader` can be
59/// [`SpecificChannelsReader`] or [`AnyChannelsReader<FlatSamplesReader>`].
60#[derive(Debug, Clone, PartialEq)]
61pub struct AllLayersReader<ChannelsReader> {
62    layer_readers: SmallVec<[LayerReader<ChannelsReader>; 2]>, // TODO unpack struct?
63}
64
65/// Processes pixel blocks from a file and accumulates them into a single layers, using only the first.
66/// For example, `ChannelsReader` can be
67/// `SpecificChannelsReader` or `AnyChannelsReader<FlatSamplesReader>`.
68#[derive(Debug, Clone, PartialEq)]
69pub struct FirstValidLayerReader<ChannelsReader> {
70    layer_reader: LayerReader<ChannelsReader>,
71    layer_index: usize,
72}
73
74/// Processes pixel blocks from a file and accumulates them into a single layers.
75/// For example, `ChannelsReader` can be
76/// `SpecificChannelsReader` or `AnyChannelsReader<FlatSamplesReader>`.
77#[derive(Debug, Clone, PartialEq)]
78pub struct LayerReader<ChannelsReader> {
79    channels_reader: ChannelsReader,
80    attributes: LayerAttributes,
81    size: Vec2<usize>,
82    encoding: Encoding
83}
84
85/// Processes pixel blocks from a file and accumulates them into multiple channels per layer.
86pub trait ChannelsReader {
87
88    /// The type of the resulting channel collection
89    type Channels;
90
91    /// Specify whether a single block of pixels should be loaded from the file
92    fn filter_block(&self, tile: TileCoordinates) -> bool;
93
94    /// Load a single pixel block, which has not been filtered, into the reader, accumulating the channel data
95    fn read_block(&mut self, header: &Header, block: UncompressedBlock) -> UnitResult;
96
97    /// Deliver the final accumulated channel collection for the image
98    fn into_channels(self) -> Self::Channels;
99}
100
101
102impl<C> LayerReader<C> {
103    fn new(header: &Header, channels_reader: C) -> Result<Self> {
104        Ok(LayerReader {
105            channels_reader,
106            attributes: header.own_attributes.clone(),
107            size: header.layer_size,
108            encoding: Encoding {
109                compression: header.compression,
110                line_order: header.line_order,
111                blocks: match header.blocks {
112                    crate::meta::BlockDescription::ScanLines => Blocks::ScanLines,
113                    crate::meta::BlockDescription::Tiles(TileDescription { tile_size, .. }) => Blocks::Tiles(tile_size)
114                },
115            },
116        })
117    }
118}
119
120impl<'s, C> ReadLayers<'s> for ReadAllLayers<C> where C: ReadChannels<'s> {
121    type Layers = Layers<<C::Reader as ChannelsReader>::Channels>;
122    type Reader = AllLayersReader<C::Reader>;
123
124    fn create_layers_reader(&'s self, headers: &[Header]) -> Result<Self::Reader> {
125        let readers: Result<_> = headers.iter()
126            .map(|header| LayerReader::new(header, self.read_channels.create_channels_reader(header)?))
127            .collect();
128
129        Ok(AllLayersReader {
130            layer_readers: readers?
131        })
132    }
133}
134
135impl<C> LayersReader for AllLayersReader<C> where C: ChannelsReader {
136    type Layers = Layers<C::Channels>;
137
138    fn filter_block(&self, _: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool {
139        let layer = self.layer_readers.get(block.layer).expect("invalid layer index argument");
140        layer.channels_reader.filter_block(tile)
141    }
142
143    fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult {
144        self.layer_readers
145            .get_mut(block.index.layer).expect("invalid layer index argument")
146            .channels_reader.read_block(headers.get(block.index.layer).expect("invalid header index in block"), block)
147    }
148
149    fn into_layers(self) -> Self::Layers {
150        self.layer_readers
151            .into_iter()
152            .map(|layer| Layer {
153                channel_data: layer.channels_reader.into_channels(),
154                attributes: layer.attributes,
155                size: layer.size,
156                encoding: layer.encoding
157            })
158            .collect()
159    }
160}
161
162
163impl<'s, C> ReadLayers<'s> for ReadFirstValidLayer<C> where C: ReadChannels<'s> {
164    type Layers = Layer<<C::Reader as ChannelsReader>::Channels>;
165    type Reader = FirstValidLayerReader<C::Reader>;
166
167    fn create_layers_reader(&'s self, headers: &[Header]) -> Result<Self::Reader> {
168        headers.iter().enumerate()
169            .flat_map(|(index, header)|
170                self.read_channels.create_channels_reader(header)
171                    .and_then(|reader| Ok(FirstValidLayerReader {
172                        layer_reader: LayerReader::new(header, reader)?,
173                        layer_index: index
174                    }))
175                    .ok()
176            )
177            .next()
178            .ok_or(Error::invalid("no layer in the image matched your specified requirements"))
179    }
180}
181
182
183impl<C> LayersReader for FirstValidLayerReader<C> where C: ChannelsReader {
184    type Layers = Layer<C::Channels>;
185
186    fn filter_block(&self, _: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool {
187        block.layer == self.layer_index && self.layer_reader.channels_reader.filter_block(tile)
188    }
189
190    fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult {
191        debug_assert_eq!(block.index.layer, self.layer_index, "block should have been filtered out");
192        self.layer_reader.channels_reader.read_block(&headers[self.layer_index], block)
193    }
194
195    fn into_layers(self) -> Self::Layers {
196        Layer {
197            channel_data: self.layer_reader.channels_reader.into_channels(),
198            attributes: self.layer_reader.attributes,
199            size: self.layer_reader.size,
200            encoding: self.layer_reader.encoding
201        }
202    }
203}
204