use std::path::Path;
use image::DynamicImage;
use log::{info, debug, error};
use crate::utils::logger::Logger;
use crate::tiff::errors::{TiffError, TiffResult};
use super::region::Region;
use super::array_strategy::ArrayData;
pub trait ExtractorStrategy {
fn extract_to_file(&mut self, source_path: &str, output_path: &str,
region: Option<Region>, shape: Option<&str>) -> TiffResult<()>;
fn extract_image(&mut self, source_path: &str,
region: Option<Region>) -> TiffResult<DynamicImage>;
fn extract_to_array(&mut self, source_path: &str, output_path: &str,
format: &str, region: Option<Region>) -> TiffResult<()>;
fn extract_array_data(&mut self, source_path: &str,
region: Option<Region>) -> TiffResult<ArrayData>;
fn supports_format(&self, file_path: &str) -> bool {
let extension = Path::new(file_path)
.extension()
.and_then(std::ffi::OsStr::to_str)
.unwrap_or("")
.to_lowercase();
matches!(extension.as_str(), "tif" | "tiff")
}
}
pub struct ExtractorStrategyFactory<'a> {
logger: &'a Logger,
use_array_extractor: bool,
}
impl<'a> ExtractorStrategyFactory<'a> {
pub fn new(logger: &'a Logger, use_array_extractor: bool) -> Self {
ExtractorStrategyFactory {
logger,
use_array_extractor,
}
}
pub fn create_strategy(&self, file_path: &str) -> TiffResult<Box<dyn ExtractorStrategy + 'a>> {
let extension = Path::new(file_path)
.extension()
.and_then(std::ffi::OsStr::to_str)
.unwrap_or("")
.to_lowercase();
debug!("Determining strategy for file extension: {}", extension);
match extension.as_str() {
"tif" | "tiff" => {
if self.use_array_extractor {
info!("Using array extractor strategy for {}", file_path);
Ok(Box::new(super::array_strategy::ArrayExtractorStrategy::new(self.logger)))
} else {
info!("Using TIFF extractor strategy for {}", file_path);
Ok(Box::new(super::tiff_strategy::TiffExtractorStrategy::new(self.logger)))
}
},
_ => {
error!("Unsupported file format: {}", extension);
Err(TiffError::GenericError(format!("Unsupported file format: {}", extension)))
}
}
}
}
pub struct ImageExtractor<'a> {
logger: &'a Logger,
factory: ExtractorStrategyFactory<'a>,
}
impl<'a> ImageExtractor<'a> {
pub fn new(logger: &'a Logger) -> Self {
ImageExtractor {
logger,
factory: ExtractorStrategyFactory::new(logger, false),
}
}
pub fn new_array_extractor(logger: &'a Logger) -> Self {
ImageExtractor {
logger,
factory: ExtractorStrategyFactory::new(logger, true),
}
}
pub fn extract_to_file(&mut self, source_path: &str, output_path: &str,
region: Option<Region>, shape: Option<&str>) -> TiffResult<()> {
info!("Extracting from {} to {}", source_path, output_path);
let mut strategy = self.factory.create_strategy(source_path)?;
strategy.extract_to_file(source_path, output_path, region, shape)
}
pub fn extract_image(&mut self, source_path: &str,
region: Option<Region>) -> TiffResult<DynamicImage> {
info!("Extracting image from {} to memory", source_path);
let mut strategy = self.factory.create_strategy(source_path)?;
strategy.extract_image(source_path, region)
}
pub fn extract_to_array(&mut self, source_path: &str, output_path: &str,
format: &str, region: Option<Region>) -> TiffResult<()> {
info!("Extracting array data from {} to {} in {} format",
source_path, output_path, format);
let mut strategy = self.factory.create_strategy(source_path)?;
strategy.extract_to_array(source_path, output_path, format, region)
}
pub fn extract_array_data(&mut self, source_path: &str,
region: Option<Region>) -> TiffResult<ArrayData> {
info!("Extracting array data from {} to memory", source_path);
let mut strategy = self.factory.create_strategy(source_path)?;
strategy.extract_array_data(source_path, region)
}
}