#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(missing_docs)]
#[cfg(feature = "fitsio")]
use fitsio::errors::Error as FitsError;
#[cfg(feature = "fitsio")]
use std::path::{Path, PathBuf};
use image::{imageops::FilterType, ColorType, DynamicImage};
pub use image::{ImageFormat, ImageResult};
use serde::{Deserialize, Serialize};
use super::{ImageMetaData, SerialImageBuffer};
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
pub enum DynamicSerialImage {
U8(SerialImageBuffer<u8>),
U16(SerialImageBuffer<u16>),
F32(SerialImageBuffer<f32>),
}
impl DynamicSerialImage {
pub fn get_metadata(&self) -> Option<ImageMetaData> {
match self {
DynamicSerialImage::U8(value) => value.get_metadata(),
DynamicSerialImage::U16(value) => value.get_metadata(),
DynamicSerialImage::F32(value) => value.get_metadata(),
}
}
pub fn set_metadata(&mut self, meta: ImageMetaData) {
match self {
DynamicSerialImage::U8(value) => value.set_metadata(Some(meta)),
DynamicSerialImage::U16(value) => value.set_metadata(Some(meta)),
DynamicSerialImage::F32(value) => value.set_metadata(Some(meta)),
}
}
pub fn width(&self) -> usize {
match self {
DynamicSerialImage::U8(value) => value.width(),
DynamicSerialImage::U16(value) => value.width(),
DynamicSerialImage::F32(value) => value.width(),
}
}
pub fn height(&self) -> usize {
match self {
DynamicSerialImage::U8(value) => value.height(),
DynamicSerialImage::U16(value) => value.height(),
DynamicSerialImage::F32(value) => value.height(),
}
}
pub fn as_u8(&self) -> Option<&SerialImageBuffer<u8>> {
match self {
DynamicSerialImage::U8(value) => Some(value),
_ => None,
}
}
pub fn as_u16(&self) -> Option<&SerialImageBuffer<u16>> {
match self {
DynamicSerialImage::U16(value) => Some(value),
_ => None,
}
}
pub fn as_f32(&self) -> Option<&SerialImageBuffer<f32>> {
match self {
DynamicSerialImage::F32(value) => Some(value),
_ => None,
}
}
pub fn into_luma(&self) -> SerialImageBuffer<u16> {
match self {
DynamicSerialImage::U8(value) => value.into_luma(),
DynamicSerialImage::U16(value) => value.into_luma(),
DynamicSerialImage::F32(value) => value.into_luma(),
}
}
pub fn into_luma_alpha(&self) -> SerialImageBuffer<u16> {
match self {
DynamicSerialImage::U8(value) => value.into_luma_alpha(),
DynamicSerialImage::U16(value) => value.into_luma_alpha(),
DynamicSerialImage::F32(value) => value.into_luma_alpha(),
}
}
pub fn resize(self, nwidth: usize, nheight: usize, filter: FilterType) -> Self {
match self {
DynamicSerialImage::U8(value) => DynamicSerialImage::U8(value.resize(nwidth, nheight, filter)),
DynamicSerialImage::U16(value) => DynamicSerialImage::U16(value.resize(nwidth, nheight, filter)),
DynamicSerialImage::F32(value) => DynamicSerialImage::F32(value.resize(nwidth, nheight, filter)),
}
}
pub fn save(&self, path: &str) -> ImageResult<()> {
let img: DynamicImage = self.into();
img.save(path)
}
#[cfg_attr(docsrs, doc(cfg(feature = "fitsio")))]
#[cfg(feature = "fitsio")]
pub fn savefits(
&self,
dir_prefix: &Path,
file_prefix: &str,
progname: Option<&str>,
compress: bool,
overwrite: bool,
) -> Result<PathBuf, FitsError> {
match self {
DynamicSerialImage::U8(value) => {
value.savefits(dir_prefix, file_prefix, progname, compress, overwrite)
}
DynamicSerialImage::U16(value) => {
value.savefits(dir_prefix, file_prefix, progname, compress, overwrite)
}
DynamicSerialImage::F32(value) => {
value.savefits(dir_prefix, file_prefix, progname, compress, overwrite)
}
}
}
}
impl DynamicSerialImage {
pub fn from_vec_u8(width: usize, height: usize, data: Vec<u8>) -> Result<Self, &'static str> {
Ok(DynamicSerialImage::U8(SerialImageBuffer::from_vec(
width, height, data,
)?))
}
pub fn from_vec_u16(width: usize, height: usize, data: Vec<u16>) -> Result<Self, &'static str> {
Ok(DynamicSerialImage::U16(SerialImageBuffer::from_vec(
width, height, data,
)?))
}
pub fn from_vec_f32(width: usize, height: usize, data: Vec<f32>) -> Result<Self, &'static str> {
Ok(DynamicSerialImage::F32(SerialImageBuffer::from_vec(
width, height, data,
)?))
}
}
impl From<DynamicImage> for DynamicSerialImage {
fn from(value: DynamicImage) -> DynamicSerialImage {
let color = value.color();
match color {
ColorType::L8 | ColorType::Rgb8 | ColorType::Rgba8 | ColorType::La8 => {
DynamicSerialImage::U8(value.try_into().unwrap())
}
ColorType::L16 | ColorType::Rgb16 | ColorType::Rgba16 | ColorType::La16 => {
DynamicSerialImage::U16(value.try_into().unwrap())
}
ColorType::Rgb32F | ColorType::Rgba32F => {
DynamicSerialImage::F32(value.try_into().unwrap())
}
_ => {
panic!("Unsupported image type");
}
}
}
}
impl From<&DynamicImage> for DynamicSerialImage {
fn from(value: &DynamicImage) -> Self {
let color = value.color();
match color {
ColorType::L8 | ColorType::Rgb8 | ColorType::Rgba8 | ColorType::La8 => {
DynamicSerialImage::U8(value.try_into().unwrap())
}
ColorType::L16 | ColorType::Rgb16 | ColorType::Rgba16 | ColorType::La16 => {
DynamicSerialImage::U16(value.try_into().unwrap())
}
ColorType::Rgb32F | ColorType::Rgba32F => {
DynamicSerialImage::F32(value.try_into().unwrap())
}
_ => {
panic!("Unsupported image type");
}
}
}
}
impl From<DynamicSerialImage> for DynamicImage {
fn from(value: DynamicSerialImage) -> Self {
match value {
DynamicSerialImage::U8(value) => value.into(),
DynamicSerialImage::U16(value) => value.into(),
DynamicSerialImage::F32(value) => value.into(),
}
}
}
impl From<&DynamicSerialImage> for DynamicImage {
fn from(value: &DynamicSerialImage) -> Self {
match value {
DynamicSerialImage::U8(value) => value.into(),
DynamicSerialImage::U16(value) => value.into(),
DynamicSerialImage::F32(value) => value.into(),
}
}
}
impl From<SerialImageBuffer<u8>> for DynamicSerialImage {
fn from(value: SerialImageBuffer<u8>) -> Self {
DynamicSerialImage::U8(value)
}
}
impl From<SerialImageBuffer<u16>> for DynamicSerialImage {
fn from(value: SerialImageBuffer<u16>) -> Self {
DynamicSerialImage::U16(value)
}
}
impl From<SerialImageBuffer<f32>> for DynamicSerialImage {
fn from(value: SerialImageBuffer<f32>) -> Self {
DynamicSerialImage::F32(value)
}
}
impl From<&SerialImageBuffer<u8>> for DynamicSerialImage {
fn from(value: &SerialImageBuffer<u8>) -> Self {
DynamicSerialImage::U8(value.clone())
}
}
impl From<&SerialImageBuffer<u16>> for DynamicSerialImage {
fn from(value: &SerialImageBuffer<u16>) -> Self {
DynamicSerialImage::U16(value.clone())
}
}
impl From<&SerialImageBuffer<f32>> for DynamicSerialImage {
fn from(value: &SerialImageBuffer<f32>) -> Self {
DynamicSerialImage::F32(value.clone())
}
}
impl TryInto<SerialImageBuffer<u8>> for DynamicSerialImage {
type Error = &'static str;
fn try_into(self) -> Result<SerialImageBuffer<u8>, &'static str> {
match self {
DynamicSerialImage::U8(value) => Ok(value),
_ => Err("Could not convert DynamicSerialImage to SerialImageBuffer<u8>"),
}
}
}
impl TryInto<SerialImageBuffer<u8>> for &DynamicSerialImage {
type Error = &'static str;
fn try_into(self) -> Result<SerialImageBuffer<u8>, &'static str> {
match self {
DynamicSerialImage::U8(value) => Ok(value.clone()),
_ => Err("Could not convert DynamicSerialImage to SerialImageBuffer<u16>"),
}
}
}
impl TryInto<SerialImageBuffer<u16>> for DynamicSerialImage {
type Error = &'static str;
fn try_into(self) -> Result<SerialImageBuffer<u16>, &'static str> {
match self {
DynamicSerialImage::U16(value) => Ok(value),
_ => Err("Could not convert DynamicSerialImage to SerialImageBuffer<u8>"),
}
}
}
impl TryInto<SerialImageBuffer<u16>> for &DynamicSerialImage {
type Error = &'static str;
fn try_into(self) -> Result<SerialImageBuffer<u16>, &'static str> {
match self {
DynamicSerialImage::U16(value) => Ok(value.clone()),
_ => Err("Could not convert DynamicSerialImage to SerialImageBuffer<u16>"),
}
}
}
impl TryInto<SerialImageBuffer<f32>> for DynamicSerialImage {
type Error = &'static str;
fn try_into(self) -> Result<SerialImageBuffer<f32>, &'static str> {
match self {
DynamicSerialImage::F32(value) => Ok(value),
_ => Err("Could not convert DynamicSerialImage to SerialImageBuffer<u8>"),
}
}
}
impl TryInto<SerialImageBuffer<f32>> for &DynamicSerialImage {
type Error = &'static str;
fn try_into(self) -> Result<SerialImageBuffer<f32>, &'static str> {
match self {
DynamicSerialImage::F32(value) => Ok(value.clone()),
_ => Err("Could not convert DynamicSerialImage to SerialImageBuffer<u16>"),
}
}
}