use std::error::Error;
use std::fmt;
use std::fs::File;
use std::io::{BufRead, BufReader, Cursor, Seek};
use std::path::Path;
mod container;
mod formats;
mod util;
pub use container::heif::Compression;
use {
container::heif::{self},
formats::*,
};
#[derive(Debug)]
pub enum ImageError {
NotSupported,
CorruptedImage,
IoError(std::io::Error),
}
impl Error for ImageError {}
impl fmt::Display for ImageError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ImageError::*;
match self {
NotSupported => f.write_str("Could not decode image"),
CorruptedImage => f.write_str("Hit end of file before finding size"),
IoError(error) => error.fmt(f),
}
}
}
impl From<std::io::Error> for ImageError {
fn from(err: std::io::Error) -> ImageError {
ImageError::IoError(err)
}
}
pub type ImageResult<T> = Result<T, ImageError>;
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ImageType {
Aseprite,
Bmp,
Dds,
Exr,
Farbfeld,
Gif,
Hdr,
Heif(Compression),
Ico,
Ilbm,
Jpeg,
Jxl,
Ktx2,
Png,
Pnm,
Psd,
Qoi,
Tga,
Tiff,
Vtf,
Webp,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ImageSize {
pub width: usize,
pub height: usize,
}
impl Ord for ImageSize {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
(self.width * self.height).cmp(&(other.width * other.height))
}
}
impl PartialOrd for ImageSize {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
pub fn image_type(header: &[u8]) -> ImageResult<ImageType> {
formats::image_type(&mut Cursor::new(header))
}
pub fn size<P: AsRef<Path>>(path: P) -> ImageResult<ImageSize> {
let file = File::open(path)?;
let reader = BufReader::new(file);
reader_size(reader)
}
pub fn blob_size(data: &[u8]) -> ImageResult<ImageSize> {
let reader = Cursor::new(data);
reader_size(reader)
}
pub fn reader_size<R: BufRead + Seek>(mut reader: R) -> ImageResult<ImageSize> {
dispatch_header(&mut reader)
}
fn dispatch_header<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageSize> {
match formats::image_type(reader)? {
ImageType::Aseprite => aesprite::size(reader),
ImageType::Bmp => bmp::size(reader),
ImageType::Dds => dds::size(reader),
ImageType::Exr => exr::size(reader),
ImageType::Farbfeld => farbfeld::size(reader),
ImageType::Gif => gif::size(reader),
ImageType::Hdr => hdr::size(reader),
ImageType::Ico => ico::size(reader),
ImageType::Ilbm => ilbm::size(reader),
ImageType::Jpeg => jpeg::size(reader),
ImageType::Jxl => jxl::size(reader),
ImageType::Ktx2 => ktx2::size(reader),
ImageType::Png => png::size(reader),
ImageType::Pnm => pnm::size(reader),
ImageType::Psd => psd::size(reader),
ImageType::Qoi => qoi::size(reader),
ImageType::Tga => tga::size(reader),
ImageType::Tiff => tiff::size(reader),
ImageType::Vtf => vtf::size(reader),
ImageType::Webp => webp::size(reader),
ImageType::Heif(..) => heif::size(reader),
}
}