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;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ReadAllLayers<ReadChannels> {
pub read_channels: ReadChannels,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ReadFirstValidLayer<ReadChannels> {
pub read_channels: ReadChannels,
}
pub trait ReadChannels<'s> {
type Reader: ChannelsReader;
fn create_channels_reader(&'s self, header: &Header) -> Result<Self::Reader>;
fn first_valid_layer(self) -> ReadFirstValidLayer<Self> where Self:Sized { ReadFirstValidLayer { read_channels: self } }
fn all_layers(self) -> ReadAllLayers<Self> where Self:Sized { ReadAllLayers { read_channels: self } }
}
#[derive(Debug, Clone, PartialEq)]
pub struct AllLayersReader<ChannelsReader> {
layer_readers: SmallVec<[LayerReader<ChannelsReader>; 2]>, }
#[derive(Debug, Clone, PartialEq)]
pub struct FirstValidLayerReader<ChannelsReader> {
layer_reader: LayerReader<ChannelsReader>,
layer_index: usize,
}
#[derive(Debug, Clone, PartialEq)]
pub struct LayerReader<ChannelsReader> {
channels_reader: ChannelsReader,
attributes: LayerAttributes,
size: Vec2<usize>,
encoding: Encoding
}
pub trait ChannelsReader {
type Channels;
fn filter_block(&self, tile: TileCoordinates) -> bool;
fn read_block(&mut self, header: &Header, block: UncompressedBlock) -> UnitResult;
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
}
}
}