| 1 | //! How to read either a single or a list of layers.
|
| 2 |
|
| 3 | use crate::image::*;
|
| 4 | use crate::meta::header::{Header, LayerAttributes};
|
| 5 | use crate::error::{Result, UnitResult, Error};
|
| 6 | use crate::block::{UncompressedBlock, BlockIndex};
|
| 7 | use crate::math::Vec2;
|
| 8 | use crate::image::read::image::{ReadLayers, LayersReader};
|
| 9 | use crate::block::chunk::TileCoordinates;
|
| 10 | use 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)]
|
| 15 | pub 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)]
|
| 24 | pub 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.
|
| 31 | pub 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)]
|
| 61 | pub 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)]
|
| 69 | pub 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)]
|
| 78 | pub 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.
|
| 86 | pub 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 |
|
| 102 | impl<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: Vec2, .. }) => Blocks::Tiles(tile_size)
|
| 114 | },
|
| 115 | },
|
| 116 | })
|
| 117 | }
|
| 118 | }
|
| 119 |
|
| 120 | impl<'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<_> = headersimpl Iterator- >
.iter()
|
| 126 | .map(|header: &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 |
|
| 135 | impl<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 |
|
| 163 | impl<'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(err:Error::invalid(message:"no layer in the image matched your specified requirements" ))
|
| 179 | }
|
| 180 | }
|
| 181 |
|
| 182 |
|
| 183 | impl<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 |
|
| 205 | |