use crate::image::*;
use crate::meta::header::{Header, ImageAttributes};
use crate::error::{Result, UnitResult};
use crate::block::{UncompressedBlock, BlockIndex};
use crate::block::chunk::TileCoordinates;
use std::path::Path;
use std::io::{Read, BufReader};
use std::io::Seek;
use crate::meta::MetaData;
use crate::block::reader::ChunksReader;
#[derive(Debug, Clone)]
pub struct ReadImage<OnProgress, ReadLayers> {
on_progress: OnProgress,
read_layers: ReadLayers,
pedantic: bool,
parallel: bool,
}
impl<F, L> ReadImage<F, L> where F: FnMut(f64)
{
pub fn new(read_layers: L, on_progress: F) -> Self {
Self {
on_progress, read_layers,
pedantic: false, parallel: true,
}
}
pub fn pedantic(self) -> Self { Self { pedantic: true, ..self } }
pub fn non_parallel(self) -> Self { Self { parallel: false, ..self } }
pub fn on_progress<OnProgress>(self, on_progress: OnProgress) -> ReadImage<OnProgress, L>
where OnProgress: FnMut(f64)
{
ReadImage {
on_progress,
read_layers: self.read_layers,
pedantic: self.pedantic,
parallel: self.parallel
}
}
#[inline]
#[must_use]
pub fn from_file<Layers>(self, path: impl AsRef<Path>) -> Result<Image<Layers>>
where for<'s> L: ReadLayers<'s, Layers = Layers>
{
self.from_unbuffered(std::fs::File::open(path)?)
}
#[inline]
#[must_use]
pub fn from_unbuffered<Layers>(self, unbuffered: impl Read + Seek) -> Result<Image<Layers>>
where for<'s> L: ReadLayers<'s, Layers = Layers>
{
self.from_buffered(BufReader::new(unbuffered))
}
#[must_use]
pub fn from_buffered<Layers>(self, buffered: impl Read + Seek) -> Result<Image<Layers>>
where for<'s> L: ReadLayers<'s, Layers = Layers>
{
let chunks = crate::block::read(buffered, self.pedantic)?;
self.from_chunks(chunks)
}
#[must_use]
pub fn from_chunks<Layers>(mut self, chunks_reader: crate::block::reader::Reader<impl Read + Seek>) -> Result<Image<Layers>>
where for<'s> L: ReadLayers<'s, Layers = Layers>
{
let Self { pedantic, parallel, ref mut on_progress, ref mut read_layers } = self;
let layers_reader = read_layers.create_layers_reader(chunks_reader.headers())?;
let mut image_collector = ImageWithAttributesReader::new(chunks_reader.headers(), layers_reader)?;
let block_reader = chunks_reader
.filter_chunks(pedantic, |meta, tile, block| {
image_collector.filter_block(meta, tile, block)
})?
.on_progress(on_progress);
if parallel {
block_reader.decompress_parallel(pedantic, |meta_data, block|{
image_collector.read_block(&meta_data.headers, block)
})?;
}
else {
block_reader.decompress_sequential(pedantic, |meta_data, block|{
image_collector.read_block(&meta_data.headers, block)
})?;
}
Ok(image_collector.into_image())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ImageWithAttributesReader<L> {
image_attributes: ImageAttributes,
layers_reader: L,
}
impl<L> ImageWithAttributesReader<L> where L: LayersReader {
pub fn new(headers: &[Header], layers_reader: L) -> Result<Self>
{
Ok(ImageWithAttributesReader {
image_attributes: headers.first().as_ref().expect("invalid headers").shared_attributes.clone(),
layers_reader,
})
}
fn filter_block(&self, meta: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool {
self.layers_reader.filter_block(meta, tile, block)
}
fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult {
self.layers_reader.read_block(headers, block)
}
fn into_image(self) -> Image<L::Layers> {
Image {
attributes: self.image_attributes,
layer_data: self.layers_reader.into_layers()
}
}
}
pub trait ReadLayers<'s> {
type Layers;
type Reader: LayersReader<Layers = Self::Layers>;
fn create_layers_reader(&'s self, headers: &[Header]) -> Result<Self::Reader>;
fn all_attributes(self) -> ReadImage<fn(f64), Self> where Self: Sized {
ReadImage::new(self, ignore_progress)
}
}
pub trait LayersReader {
type Layers;
fn filter_block(&self, meta: &MetaData, tile: TileCoordinates, block: BlockIndex) -> bool;
fn read_block(&mut self, headers: &[Header], block: UncompressedBlock) -> UnitResult;
fn into_layers(self) -> Self::Layers;
}