use std::path::PathBuf;
use image::{DynamicImage, GenericImageView, SubImage};
use log::debug;
use crate::{max_size_in_rect, Vec2d, ZoomError};
use crate::encoder::canvas::ImageWriter;
use crate::tile::Tile;
pub mod canvas;
pub mod png_encoder;
pub mod pixel_streamer;
pub mod tile_buffer;
pub mod iiif_encoder;
mod retiler;
pub trait Encoder: Send + 'static {
fn add_tile(&mut self, tile: Tile) -> std::io::Result<()>;
fn finalize(&mut self) -> std::io::Result<()>;
fn size(&self) -> Vec2d;
}
fn encoder_for_name(destination: PathBuf, size: Vec2d, compression: u8) -> Result<Box<dyn Encoder>, ZoomError> {
let extension = destination.extension().unwrap_or_default();
let quality = 100u8.saturating_sub(compression);
if extension == "png" {
debug!("Using the streaming png encoder");
Ok(Box::new(png_encoder::PngEncoder::new(destination, size, compression)?))
} else if extension == "iiif" {
debug!("Using the iiif tiling encoder");
Ok(Box::new(iiif_encoder::IiifEncoder::new(destination, size, quality)?))
} else if extension == "jpeg" || extension == "jpg" {
debug!("Using the jpeg encoder with a quality of {}", quality);
let image_writer = ImageWriter::Jpeg { quality };
Ok(Box::new(canvas::Canvas::new(destination, size, image_writer)?))
} else {
debug!("Using the generic canvas implementation {}", &destination.to_string_lossy());
Ok(Box::new(canvas::Canvas::new(destination, size, ImageWriter::Generic)?))
}
}
pub fn crop_tile(tile: &Tile, canvas_size: Vec2d) -> SubImage<&DynamicImage> {
let Vec2d { x: xmax, y: ymax } = max_size_in_rect(tile.position, tile.size(), canvas_size);
tile.image.view(0, 0, xmax, ymax)
}