| 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 | |