1 | //! How to read arbitrary channels.
|
2 |
|
3 | use crate::image::*;
|
4 | use crate::meta::header::{Header};
|
5 | use crate::error::{Result, UnitResult};
|
6 | use crate::block::UncompressedBlock;
|
7 | use crate::block::lines::{LineRef};
|
8 | use crate::math::Vec2;
|
9 | use crate::meta::attribute::{Text, ChannelDescription};
|
10 | use crate::image::read::layers::{ReadChannels, ChannelsReader};
|
11 | use 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)]
|
17 | pub 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.
|
24 | pub 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)]
|
36 | pub 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)]
|
44 | pub 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.
|
61 | pub 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 |
|
77 | impl<'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<_> = headerimpl Iterator- >
.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 |
|
94 | impl<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 | }
|
129 | |