1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//! How to read either a single or a list of layers.

use crate::image::*;
use crate::meta::header::{Header, LayerAttributes};
use crate::error::{Result, UnitResult, Error};
use crate::block::{UncompressedBlock, BlockIndex};
use crate::math::Vec2;
use crate::image::read::image::{ReadLayers, LayersReader};
use crate::block::chunk::TileCoordinates;
use crate::meta::MetaData;

/// Specify to read all channels, aborting if any one is invalid.
/// [`ReadRgbaChannels`] or [`ReadAnyChannels<ReadFlatSamples>`].
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ReadAllLayers<ReadChannels> {

    /// The channel reading specification
    pub read_channels: ReadChannels,
}

/// Specify to read only the first layer which meets the previously specified requirements
// FIXME do not throw error on deep data but just skip it!
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ReadFirstValidLayer<ReadChannels> {

    /// The channel reading specification
    pub read_channels: ReadChannels,
}

/// A template that creates a [`ChannelsReader`] once for all channels per layer.
pub trait ReadChannels<'s> {

    /// The type of the temporary channels reader
    type Reader: ChannelsReader;

    /// Create a single reader for all channels of a specific layer
    fn create_channels_reader(&'s self, header: &Header) -> Result<Self::Reader>;


    /// Read only the first layer which meets the previously specified requirements
    /// For example, skips layers with deep data, if specified earlier.
    /// Aborts if the image contains no layers.
    // TODO test if this filters non-deep layers while ignoring deep data layers!
    fn first_valid_layer(self) -> ReadFirstValidLayer<Self> where Self:Sized { ReadFirstValidLayer { read_channels: self } }

// FIXME do not throw error on deep data but just skip it!


    /// Reads all layers, including an empty list. Aborts if any of the layers are invalid,
    /// even if only one of the layers contains unexpected data.
    fn all_layers(self) -> ReadAllLayers<Self> where Self:Sized { ReadAllLayers { read_channels: self } }

    // TODO pub fn all_valid_layers(self) -> ReadAllValidLayers<Self> { ReadAllValidLayers { read_channels: self } }
}


/// Processes pixel blocks from a file and accumulates them into a list of layers.
/// For example, `ChannelsReader` can be
/// [`SpecificChannelsReader`] or [`AnyChannelsReader<FlatSamplesReader>`].
#[derive(Debug, Clone, PartialEq)]
pub struct AllLayersReader<ChannelsReader> {
    layer_readers: SmallVec<[LayerReader<ChannelsReader>; 2]>, // TODO unpack struct?
}

/// Processes pixel blocks from a file and accumulates them into a single layers, using only the first.
/// For example, `ChannelsReader` can be
/// `SpecificChannelsReader` or `AnyChannelsReader<FlatSamplesReader>`.
#[derive(Debug, Clone, PartialEq)]
pub struct FirstValidLayerReader<ChannelsReader> {
    layer_reader: LayerReader<ChannelsReader>,
    layer_index: usize,
}

/// Processes pixel blocks from a file and accumulates them into a single layers.
/// For example, `ChannelsReader` can be
/// `SpecificChannelsReader` or `AnyChannelsReader<FlatSamplesReader>`.
#[derive(Debug, Clone, PartialEq)]
pub struct LayerReader<ChannelsReader> {
    channels_reader: ChannelsReader,
    attributes: LayerAttributes,
    size: Vec2<usize>,
    encoding: Encoding
}

/// Processes pixel blocks from a file and accumulates them into multiple channels per layer.
pub trait ChannelsReader {

    /// The type of the resulting channel collection
    type Channels;

    /// Specify whether a single block of pixels should be loaded from the file
    fn filter_block(&self, tile: TileCoordinates) -> bool;

    /// Load a single pixel block, which has not been filtered, into the reader, accumulating the channel data
    fn read_block(&mut self, header: &Header, block: UncompressedBlock) -> UnitResult;

    /// Deliver the final accumulated channel collection for the image
    fn into_channels(self) -> Self::Channels;
}


impl<C> LayerReader<C> {
    fn new(header: &Header, channels_reader: C) -> Result<Self> {
        Ok(LayerReader {
            channels_reader,
            attributes: header.own_attributes.clone(),
            size: header.layer_size,
            encoding: Encoding {
                compression: header.compression,
                line_order: header.line_order,
                blocks: match header.blocks {
                    crate::meta::BlockDescription::ScanLines => Blocks::ScanLines,
                    crate::meta::BlockDescription::Tiles(TileDescription { tile_size, .. }) => Blocks::Tiles(tile_size)
                },
            },
        })
    }
}

impl<'s, C> ReadLayers<'s> for ReadAllLayers<C> where C: ReadChannels<'s> {
    type Layers = Layers<<C::Reader as ChannelsReader>::Channels>;
    type Reader = AllLayersReader<C::Reader>;

    fn create_layers_reader(&'s self, headers: &[Header]) -> Result<Self::Reader> {
        let readers: Result<_> = headers.iter()
            .map(|header| LayerReader::new(header, self.read_channels.create_channels_reader(header)?))
            .collect();

        Ok(AllLayersReader {
            layer_readers: readers?
        })
    }
}

impl<C> LayersReader for AllLayersReader<C> where C: ChannelsReader {
    type Layers = Layers<C::Channels>;

    fn filter_block(&self, _: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool {
        let layer = self.layer_readers.get(block.layer).expect("invalid layer index argument");
        layer.channels_reader.filter_block(tile)
    }

    fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult {
        self.layer_readers
            .get_mut(block.index.layer).expect("invalid layer index argument")
            .channels_reader.read_block(headers.get(block.index.layer).expect("invalid header index in block"), block)
    }

    fn into_layers(self) -> Self::Layers {
        self.layer_readers
            .into_iter()
            .map(|layer| Layer {
                channel_data: layer.channels_reader.into_channels(),
                attributes: layer.attributes,
                size: layer.size,
                encoding: layer.encoding
            })
            .collect()
    }
}


impl<'s, C> ReadLayers<'s> for ReadFirstValidLayer<C> where C: ReadChannels<'s> {
    type Layers = Layer<<C::Reader as ChannelsReader>::Channels>;
    type Reader = FirstValidLayerReader<C::Reader>;

    fn create_layers_reader(&'s self, headers: &[Header]) -> Result<Self::Reader> {
        headers.iter().enumerate()
            .flat_map(|(index, header)|
                self.read_channels.create_channels_reader(header)
                    .and_then(|reader| Ok(FirstValidLayerReader {
                        layer_reader: LayerReader::new(header, reader)?,
                        layer_index: index
                    }))
                    .ok()
            )
            .next()
            .ok_or(Error::invalid("no layer in the image matched your specified requirements"))
    }
}


impl<C> LayersReader for FirstValidLayerReader<C> where C: ChannelsReader {
    type Layers = Layer<C::Channels>;

    fn filter_block(&self, _: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool {
        block.layer == self.layer_index && self.layer_reader.channels_reader.filter_block(tile)
    }

    fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult {
        debug_assert_eq!(block.index.layer, self.layer_index, "block should have been filtered out");
        self.layer_reader.channels_reader.read_block(&headers[self.layer_index], block)
    }

    fn into_layers(self) -> Self::Layers {
        Layer {
            channel_data: self.layer_reader.channels_reader.into_channels(),
            attributes: self.layer_reader.attributes,
            size: self.layer_reader.size,
            encoding: self.layer_reader.encoding
        }
    }
}