Skip to main content

exr/image/read/
any_channels.rs

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