exr/image/read/
any_channels.rs

1//! How to read arbitrary channels.
2
3use crate::image::*;
4use crate::meta::header::{Header};
5use crate::error::{Result, UnitResult};
6use crate::block::UncompressedBlock;
7use crate::block::lines::{LineRef};
8use crate::math::Vec2;
9use crate::meta::attribute::{Text, ChannelDescription};
10use crate::image::read::layers::{ReadChannels, ChannelsReader};
11use crate::block::chunk::TileCoordinates;
12
13/// A template that creates an [AnyChannelsReader] for each layer in the image.
14/// This loads all channels for each layer.
15/// The `ReadSamples` can, for example, be [ReadFlatSamples] or [ReadAllLevels<ReadFlatSamples>].
16#[derive(Debug, Clone, Eq, PartialEq)]
17pub struct ReadAnyChannels<ReadSamples> {
18
19    /// The sample reading specification
20    pub read_samples: ReadSamples
21}
22
23/// A template that creates a new [`SampleReader`] for each channel in each layer.
24pub trait ReadSamples {
25
26    /// The type of the temporary samples reader
27    type Reader: SamplesReader;
28
29    /// Create a single reader for a single channel of a layer
30    fn create_sample_reader(&self, header: &Header, channel: &ChannelDescription) -> Result<Self::Reader>;
31}
32
33/// Processes pixel blocks from a file and accumulates them into a collection of arbitrary channels.
34/// Loads all channels for each layer.
35#[derive(Debug, Clone, Eq, PartialEq)]
36pub struct AnyChannelsReader<SamplesReader> {
37
38    /// Stores a separate sample reader per channel in the layer
39    sample_channels_reader: SmallVec<[AnyChannelReader<SamplesReader>; 4]>,
40}
41
42/// Processes pixel blocks from a file and accumulates them into a single arbitrary channel.
43#[derive(Debug, Clone, Eq, PartialEq)]
44pub struct AnyChannelReader<SamplesReader> {
45
46    /// The custom reader that accumulates the pixel data for a single channel
47    samples: SamplesReader,
48
49    /// Temporarily accumulated meta data.
50    name: Text,
51
52    /// Temporarily accumulated meta data.
53    sampling_rate: Vec2<usize>,
54
55    /// Temporarily accumulated meta data.
56    quantize_linearly: bool,
57}
58
59/// Processes pixel blocks from a file and accumulates them into a single pixel channel.
60/// For example, stores thousands of "Red" pixel values for a single layer.
61pub trait SamplesReader {
62
63    /// The type of resulting sample storage
64    type Samples;
65
66    /// Specify whether a single block of pixels should be loaded from the file
67    fn filter_block(&self, tile: TileCoordinates) -> bool;
68
69    /// Load a single pixel line, which has not been filtered, into the reader, accumulating the sample data
70    fn read_line(&mut self, line: LineRef<'_>) -> UnitResult;
71
72    /// Deliver the final accumulated sample storage for the image
73    fn into_samples(self) -> Self::Samples;
74}
75
76
77impl<'s, S: 's + ReadSamples> ReadChannels<'s> for ReadAnyChannels<S> {
78    type Reader = AnyChannelsReader<S::Reader>;
79
80    fn create_channels_reader(&self, header: &Header) -> Result<Self::Reader> {
81        let samples: Result<_> = header.channels.list.iter()
82            .map(|channel: &ChannelDescription| Ok(AnyChannelReader {
83                samples: self.read_samples.create_sample_reader(header, channel)?,
84                name: channel.name.clone(),
85                sampling_rate: channel.sampling,
86                quantize_linearly: channel.quantize_linearly
87            }))
88            .collect();
89
90        Ok(AnyChannelsReader { sample_channels_reader: samples? })
91    }
92}
93
94impl<S: SamplesReader> ChannelsReader for AnyChannelsReader<S> {
95    type Channels = AnyChannels<S::Samples>;
96
97    fn filter_block(&self, tile: TileCoordinates) -> bool {
98        self.sample_channels_reader.iter().any(|channel| channel.samples.filter_block(tile))
99    }
100
101    fn read_block(&mut self, header: &Header, decompressed: UncompressedBlock) -> UnitResult {
102        /*for (bytes, line) in LineIndex::lines_in_block(decompressed.index, header) {
103            let channel = self.sample_channels_reader.get_mut(line.channel).unwrap();
104            channel.samples.read_line(LineSlice { location: line, value: &decompressed.data[bytes] })?;
105        }
106
107        Ok(())*/
108        for line in decompressed.lines(&header.channels) {
109            self.sample_channels_reader[line.location.channel].samples.read_line(line)?;
110        }
111
112        Ok(())
113    }
114
115    fn into_channels(self) -> Self::Channels {
116        AnyChannels { // not using `new()` as the channels are already sorted
117            list: self.sample_channels_reader.into_iter()
118                .map(|channel| AnyChannel {
119                    sample_data: channel.samples.into_samples(),
120
121                    name: channel.name,
122                    quantize_linearly: channel.quantize_linearly,
123                    sampling: channel.sampling_rate
124                })
125                .collect()
126        }
127    }
128}