use std::io;
use std::io::Write;
use std::path::Path;
use std::u32;
#[cfg(feature = "bmp")]
use crate::codecs::bmp;
#[cfg(feature = "gif")]
use crate::codecs::gif;
#[cfg(feature = "ico")]
use crate::codecs::ico;
#[cfg(feature = "jpeg")]
use crate::codecs::jpeg;
#[cfg(feature = "png")]
use crate::codecs::png;
#[cfg(feature = "pnm")]
use crate::codecs::pnm;
#[cfg(feature = "farbfeld")]
use crate::codecs::farbfeld;
#[cfg(feature = "tga")]
use crate::codecs::tga;
#[cfg(feature = "avif")]
use crate::codecs::avif;
use crate::buffer_::{
    BgrImage, BgraImage, ConvertBuffer, GrayAlphaImage, GrayAlpha16Image,
    GrayImage, Gray16Image, ImageBuffer, RgbImage, Rgb16Image, RgbaImage,
    Rgba16Image,
};
use crate::color::{self, IntoColor};
use crate::error::{ImageError, ImageFormatHint, ImageResult, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind};
use crate::flat::FlatSamples;
use crate::image;
use crate::image::{GenericImage, GenericImageView, ImageDecoder, ImageFormat, ImageOutputFormat};
use crate::image::ImageEncoder;
use crate::io::free_functions;
use crate::imageops;
use crate::math::resize_dimensions;
use crate::traits::Pixel;
#[derive(Clone)]
pub enum DynamicImage {
    
    ImageLuma8(GrayImage),
    
    ImageLumaA8(GrayAlphaImage),
    
    ImageRgb8(RgbImage),
    
    ImageRgba8(RgbaImage),
    
    ImageBgr8(BgrImage),
    
    ImageBgra8(BgraImage),
    
    ImageLuma16(Gray16Image),
    
    ImageLumaA16(GrayAlpha16Image),
    
    ImageRgb16(Rgb16Image),
    
    ImageRgba16(Rgba16Image),
}
macro_rules! dynamic_map(
        ($dynimage: expr, ref $image: ident => $action: expr) => (
                match $dynimage {
                        DynamicImage::ImageLuma8(ref $image) => DynamicImage::ImageLuma8($action),
                        DynamicImage::ImageLumaA8(ref $image) => DynamicImage::ImageLumaA8($action),
                        DynamicImage::ImageRgb8(ref $image) => DynamicImage::ImageRgb8($action),
                        DynamicImage::ImageRgba8(ref $image) => DynamicImage::ImageRgba8($action),
                        DynamicImage::ImageBgr8(ref $image) => DynamicImage::ImageBgr8($action),
                        DynamicImage::ImageBgra8(ref $image) => DynamicImage::ImageBgra8($action),
                        DynamicImage::ImageLuma16(ref $image) => DynamicImage::ImageLuma16($action),
                        DynamicImage::ImageLumaA16(ref $image) => DynamicImage::ImageLumaA16($action),
                        DynamicImage::ImageRgb16(ref $image) => DynamicImage::ImageRgb16($action),
                        DynamicImage::ImageRgba16(ref $image) => DynamicImage::ImageRgba16($action),
                }
        );
        ($dynimage: expr, ref mut $image: ident => $action: expr) => (
                match $dynimage {
                        DynamicImage::ImageLuma8(ref mut $image) => DynamicImage::ImageLuma8($action),
                        DynamicImage::ImageLumaA8(ref mut $image) => DynamicImage::ImageLumaA8($action),
                        DynamicImage::ImageRgb8(ref mut $image) => DynamicImage::ImageRgb8($action),
                        DynamicImage::ImageRgba8(ref mut $image) => DynamicImage::ImageRgba8($action),
                        DynamicImage::ImageBgr8(ref mut $image) => DynamicImage::ImageBgr8($action),
                        DynamicImage::ImageBgra8(ref mut $image) => DynamicImage::ImageBgra8($action),
                        DynamicImage::ImageLuma16(ref mut $image) => DynamicImage::ImageLuma16($action),
                        DynamicImage::ImageLumaA16(ref mut $image) => DynamicImage::ImageLumaA16($action),
                        DynamicImage::ImageRgb16(ref mut $image) => DynamicImage::ImageRgb16($action),
                        DynamicImage::ImageRgba16(ref mut $image) => DynamicImage::ImageRgba16($action),
                }
        );
        ($dynimage: expr, ref $image: ident -> $action: expr) => (
                match $dynimage {
                        DynamicImage::ImageLuma8(ref $image) => $action,
                        DynamicImage::ImageLumaA8(ref $image) => $action,
                        DynamicImage::ImageRgb8(ref $image) => $action,
                        DynamicImage::ImageRgba8(ref $image) => $action,
                        DynamicImage::ImageBgr8(ref $image) => $action,
                        DynamicImage::ImageBgra8(ref $image) => $action,
                        DynamicImage::ImageLuma16(ref $image) => $action,
                        DynamicImage::ImageLumaA16(ref $image) => $action,
                        DynamicImage::ImageRgb16(ref $image) => $action,
                        DynamicImage::ImageRgba16(ref $image) => $action,
                }
        );
        ($dynimage: expr, ref mut $image: ident -> $action: expr) => (
                match $dynimage {
                        DynamicImage::ImageLuma8(ref mut $image) => $action,
                        DynamicImage::ImageLumaA8(ref mut $image) => $action,
                        DynamicImage::ImageRgb8(ref mut $image) => $action,
                        DynamicImage::ImageRgba8(ref mut $image) => $action,
                        DynamicImage::ImageBgr8(ref mut $image) => $action,
                        DynamicImage::ImageBgra8(ref mut $image) => $action,
                        DynamicImage::ImageLuma16(ref mut $image) => $action,
                        DynamicImage::ImageLumaA16(ref mut $image) => $action,
                        DynamicImage::ImageRgb16(ref mut $image) => $action,
                        DynamicImage::ImageRgba16(ref mut $image) => $action,
                }
        );
);
impl DynamicImage {
    
    pub fn new_luma8(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageLuma8(ImageBuffer::new(w, h))
    }
    
    
    pub fn new_luma_a8(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageLumaA8(ImageBuffer::new(w, h))
    }
    
    pub fn new_rgb8(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageRgb8(ImageBuffer::new(w, h))
    }
    
    pub fn new_rgba8(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageRgba8(ImageBuffer::new(w, h))
    }
    
    pub fn new_bgra8(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageBgra8(ImageBuffer::new(w, h))
    }
    
    pub fn new_bgr8(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageBgr8(ImageBuffer::new(w, h))
    }
    
    pub fn new_luma16(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageLuma16(ImageBuffer::new(w, h))
    }
    
    
    pub fn new_luma_a16(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageLumaA16(ImageBuffer::new(w, h))
    }
    
    pub fn new_rgb16(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageRgb16(ImageBuffer::new(w, h))
    }
    
    pub fn new_rgba16(w: u32, h: u32) -> DynamicImage {
        DynamicImage::ImageRgba16(ImageBuffer::new(w, h))
    }
    
    pub fn from_decoder<'a>(decoder: impl ImageDecoder<'a>)
        -> ImageResult<Self>
    {
        decoder_to_image(decoder)
    }
    
    #[deprecated = "replaced by `to_rgb8`"]
    pub fn to_rgb(&self) -> RgbImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_rgb8(&self) -> RgbImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_rgb16(&self) -> Rgb16Image {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    #[deprecated = "replaced by `to_rgba8`"]
    pub fn to_rgba(&self) -> RgbaImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_rgba8(&self) -> RgbaImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_rgba16(&self) -> Rgba16Image {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    #[deprecated = "replaced by `to_bgr8`"]
    pub fn to_bgr(&self) -> BgrImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_bgr8(&self) -> BgrImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    #[deprecated = "replaced by `to_bgra8`"]
    pub fn to_bgra(&self) -> BgraImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_bgra8(&self) -> BgraImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    #[deprecated = "replaced by `to_luma8`"]
    pub fn to_luma(&self) -> GrayImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_luma8(&self) -> GrayImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_luma16(&self) -> Gray16Image {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    #[deprecated = "replaced by `to_luma_alpha8`"]
    pub fn to_luma_alpha(&self) -> GrayAlphaImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_luma_alpha8(&self) -> GrayAlphaImage {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    pub fn to_luma_alpha16(&self) -> GrayAlpha16Image {
        dynamic_map!(*self, ref p -> {
            p.convert()
        })
    }
    
    
    
    
    #[deprecated = "replaced by `into_rgb8`"]
    pub fn into_rgb(self) -> RgbImage {
        match self {
            DynamicImage::ImageRgb8(x) => x,
            x => x.to_rgb8(),
        }
    }
    
    
    
    
    pub fn into_rgb8(self) -> RgbImage {
        match self {
            DynamicImage::ImageRgb8(x) => x,
            x => x.to_rgb8(),
        }
    }
    
    
    
    
    pub fn into_rgb16(self) -> Rgb16Image {
        match self {
            DynamicImage::ImageRgb16(x) => x,
            x => x.to_rgb16(),
        }
    }
    
    
    
    
    #[deprecated = "replaced by `into_rgba8`"]
    pub fn into_rgba(self) -> RgbaImage {
        match self {
            DynamicImage::ImageRgba8(x) => x,
            x => x.to_rgba8(),
        }
    }
    
    
    
    
    pub fn into_rgba8(self) -> RgbaImage {
        match self {
            DynamicImage::ImageRgba8(x) => x,
            x => x.to_rgba8(),
        }
    }
    
    
    
    
    pub fn into_rgba16(self) -> Rgba16Image {
        match self {
            DynamicImage::ImageRgba16(x) => x,
            x => x.to_rgba16(),
        }
    }
    
    
    
    
    #[deprecated = "replaced by `into_bgra8`"]
    pub fn into_bgr(self) -> BgrImage {
        match self {
            DynamicImage::ImageBgr8(x) => x,
            x => x.to_bgr8(),
        }
    }
    
    
    
    
    pub fn into_bgr8(self) -> BgrImage {
        match self {
            DynamicImage::ImageBgr8(x) => x,
            x => x.to_bgr8(),
        }
    }
    
    
    
    
    
    #[deprecated = "replaced by `into_bgra8`"]
    pub fn into_bgra(self) -> BgraImage {
        match self {
            DynamicImage::ImageBgra8(x) => x,
            x => x.to_bgra8(),
        }
    }
    
    
    
    
    pub fn into_bgra8(self) -> BgraImage {
        match self {
            DynamicImage::ImageBgra8(x) => x,
            x => x.to_bgra8(),
        }
    }
    
    
    
    
    
    #[deprecated = "replaced by `into_luma8`"]
    pub fn into_luma(self) -> GrayImage {
        match self {
            DynamicImage::ImageLuma8(x) => x,
            x => x.to_luma8(),
        }
    }
    
    
    
    
    pub fn into_luma8(self) -> GrayImage {
        match self {
            DynamicImage::ImageLuma8(x) => x,
            x => x.to_luma8(),
        }
    }
    
    
    
    
    pub fn into_luma16(self) -> Gray16Image {
        match self {
            DynamicImage::ImageLuma16(x) => x,
            x => x.to_luma16(),
        }
    }
    
    
    
    
    #[deprecated = "replaced by `into_luma_alpha8`"]
    pub fn into_luma_alpha(self) -> GrayAlphaImage {
        match self {
            DynamicImage::ImageLumaA8(x) => x,
            x => x.to_luma_alpha8(),
        }
    }
    
    
    
    
    pub fn into_luma_alpha8(self) -> GrayAlphaImage {
        match self {
            DynamicImage::ImageLumaA8(x) => x,
            x => x.to_luma_alpha8(),
        }
    }
    
    
    
    
    pub fn into_luma_alpha16(self) -> GrayAlpha16Image {
        match self {
            DynamicImage::ImageLumaA16(x) => x,
            x => x.to_luma_alpha16(),
        }
    }
    
    
    
    
    pub fn crop(&mut self, x: u32, y: u32, width: u32, height: u32) -> DynamicImage {
        dynamic_map!(*self, ref mut p => imageops::crop(p, x, y, width, height).to_image())
    }
    
    pub fn crop_imm(&self, x: u32, y: u32, width: u32, height: u32) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::crop_imm(p, x, y, width, height).to_image())
    }
    
    pub fn as_rgb8(&self) -> Option<&RgbImage> {
        match *self {
            DynamicImage::ImageRgb8(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_rgb8(&mut self) -> Option<&mut RgbImage> {
        match *self {
            DynamicImage::ImageRgb8(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_bgr8(&self) -> Option<&BgrImage> {
        match *self {
            DynamicImage::ImageBgr8(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_bgr8(&mut self) -> Option<&mut BgrImage> {
        match *self {
            DynamicImage::ImageBgr8(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_rgba8(&self) -> Option<&RgbaImage> {
        match *self {
            DynamicImage::ImageRgba8(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_rgba8(&mut self) -> Option<&mut RgbaImage> {
        match *self {
            DynamicImage::ImageRgba8(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_bgra8(&self) -> Option<&BgraImage> {
        match *self {
            DynamicImage::ImageBgra8(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_bgra8(&mut self) -> Option<&mut BgraImage> {
        match *self {
            DynamicImage::ImageBgra8(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_luma8(&self) -> Option<&GrayImage> {
        match *self {
            DynamicImage::ImageLuma8(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_luma8(&mut self) -> Option<&mut GrayImage> {
        match *self {
            DynamicImage::ImageLuma8(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_luma_alpha8(&self) -> Option<&GrayAlphaImage> {
        match *self {
            DynamicImage::ImageLumaA8(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_luma_alpha8(&mut self) -> Option<&mut GrayAlphaImage> {
        match *self {
            DynamicImage::ImageLumaA8(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_rgb16(&self) -> Option<&Rgb16Image> {
        match *self {
            DynamicImage::ImageRgb16(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_rgb16(&mut self) -> Option<&mut Rgb16Image> {
        match *self {
            DynamicImage::ImageRgb16(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_rgba16(&self) -> Option<&Rgba16Image> {
        match *self {
            DynamicImage::ImageRgba16(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_rgba16(&mut self) -> Option<&mut Rgba16Image> {
        match *self {
            DynamicImage::ImageRgba16(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_luma16(&self) -> Option<&Gray16Image> {
        match *self {
            DynamicImage::ImageLuma16(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_luma16(&mut self) -> Option<&mut Gray16Image> {
        match *self {
            DynamicImage::ImageLuma16(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_luma_alpha16(&self) -> Option<&GrayAlpha16Image> {
        match *self {
            DynamicImage::ImageLumaA16(ref p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_mut_luma_alpha16(&mut self) -> Option<&mut GrayAlpha16Image> {
        match *self {
            DynamicImage::ImageLumaA16(ref mut p) => Some(p),
            _ => None,
        }
    }
    
    pub fn as_flat_samples_u8(&self) -> Option<FlatSamples<&[u8]>> {
        match *self {
            DynamicImage::ImageLuma8(ref p) => Some(p.as_flat_samples()),
            DynamicImage::ImageLumaA8(ref p) => Some(p.as_flat_samples()),
            DynamicImage::ImageRgb8(ref p) => Some(p.as_flat_samples()),
            DynamicImage::ImageRgba8(ref p) => Some(p.as_flat_samples()),
            DynamicImage::ImageBgr8(ref p) => Some(p.as_flat_samples()),
            DynamicImage::ImageBgra8(ref p) => Some(p.as_flat_samples()),
            _ => None,
        }
    }
    
    pub fn as_flat_samples_u16(&self) -> Option<FlatSamples<&[u16]>> {
        match *self {
            DynamicImage::ImageLuma16(ref p) => Some(p.as_flat_samples()),
            DynamicImage::ImageLumaA16(ref p) => Some(p.as_flat_samples()),
            DynamicImage::ImageRgb16(ref p) => Some(p.as_flat_samples()),
            DynamicImage::ImageRgba16(ref p) => Some(p.as_flat_samples()),
            _ => None,
        }
    }
    
    pub fn as_bytes(&self) -> &[u8] {
        image_as_bytes(self)
    }
    
    
    
    pub fn into_bytes(self) -> Vec<u8> {
        image_into_bytes(self)
    }
    
    pub fn to_bytes(&self) -> Vec<u8> {
        image_to_bytes(self)
    }
    
    pub fn color(&self) -> color::ColorType {
        match *self {
            DynamicImage::ImageLuma8(_) => color::ColorType::L8,
            DynamicImage::ImageLumaA8(_) => color::ColorType::La8,
            DynamicImage::ImageRgb8(_) => color::ColorType::Rgb8,
            DynamicImage::ImageRgba8(_) => color::ColorType::Rgba8,
            DynamicImage::ImageBgra8(_) => color::ColorType::Bgra8,
            DynamicImage::ImageBgr8(_) => color::ColorType::Bgr8,
            DynamicImage::ImageLuma16(_) => color::ColorType::L16,
            DynamicImage::ImageLumaA16(_) => color::ColorType::La16,
            DynamicImage::ImageRgb16(_) => color::ColorType::Rgb16,
            DynamicImage::ImageRgba16(_) => color::ColorType::Rgba16,
        }
    }
    
    pub fn grayscale(&self) -> DynamicImage {
        match *self {
            DynamicImage::ImageLuma8(ref p) => DynamicImage::ImageLuma8(p.clone()),
            DynamicImage::ImageLumaA8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
            DynamicImage::ImageRgb8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
            DynamicImage::ImageRgba8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
            DynamicImage::ImageBgr8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
            DynamicImage::ImageBgra8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
            DynamicImage::ImageLuma16(ref p) => DynamicImage::ImageLuma16(p.clone()),
            DynamicImage::ImageLumaA16(ref p) => DynamicImage::ImageLuma16(imageops::grayscale(p)),
            DynamicImage::ImageRgb16(ref p) => DynamicImage::ImageLuma16(imageops::grayscale(p)),
            DynamicImage::ImageRgba16(ref p) => DynamicImage::ImageLuma16(imageops::grayscale(p)),
        }
    }
    
    
    pub fn invert(&mut self) {
        dynamic_map!(*self, ref mut p -> imageops::invert(p))
    }
    
    
    
    
    pub fn resize(&self, nwidth: u32, nheight: u32, filter: imageops::FilterType) -> DynamicImage {
        let (width2, height2) =
            resize_dimensions(self.width(), self.height(), nwidth, nheight, false);
        self.resize_exact(width2, height2, filter)
    }
    
    
    
    pub fn resize_exact(
        &self,
        nwidth: u32,
        nheight: u32,
        filter: imageops::FilterType,
    ) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::resize(p, nwidth, nheight, filter))
    }
    
    
    
    
    
    
    
    
    pub fn thumbnail(&self, nwidth: u32, nheight: u32) -> DynamicImage {
        let (width2, height2) =
            resize_dimensions(self.width(), self.height(), nwidth, nheight, false);
        self.thumbnail_exact(width2, height2)
    }
    
    
    
    
    
    
    pub fn thumbnail_exact(&self, nwidth: u32, nheight: u32) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::thumbnail(p, nwidth, nheight))
    }
    
    
    
    
    
    
    pub fn resize_to_fill(
        &self,
        nwidth: u32,
        nheight: u32,
        filter: imageops::FilterType,
    ) -> DynamicImage {
        let (width2, height2) =
            resize_dimensions(self.width(), self.height(), nwidth, nheight, true);
        let mut intermediate = self.resize_exact(width2, height2, filter);
        let (iwidth, iheight) = intermediate.dimensions();
        let ratio = u64::from(iwidth) * u64::from(nheight);
        let nratio = u64::from(nwidth) * u64::from(iheight);
        if nratio > ratio {
            intermediate.crop(0, (iheight - nheight) / 2, nwidth, nheight)
        } else {
            intermediate.crop((iwidth - nwidth) / 2, 0, nwidth, nheight)
        }
    }
    
    
    pub fn blur(&self, sigma: f32) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::blur(p, sigma))
    }
    
    
    
    
    
    pub fn unsharpen(&self, sigma: f32, threshold: i32) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::unsharpen(p, sigma, threshold))
    }
    
    pub fn filter3x3(&self, kernel: &[f32]) -> DynamicImage {
        if kernel.len() != 9 {
            panic!("filter must be 3 x 3")
        }
        dynamic_map!(*self, ref p => imageops::filter3x3(p, kernel))
    }
    
    
    
    pub fn adjust_contrast(&self, c: f32) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::contrast(p, c))
    }
    
    
    
    pub fn brighten(&self, value: i32) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::brighten(p, value))
    }
    
    
    
    
    pub fn huerotate(&self, value: i32) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::huerotate(p, value))
    }
    
    pub fn flipv(&self) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::flip_vertical(p))
    }
    
    pub fn fliph(&self) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::flip_horizontal(p))
    }
    
    pub fn rotate90(&self) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::rotate90(p))
    }
    
    pub fn rotate180(&self) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::rotate180(p))
    }
    
    pub fn rotate270(&self) -> DynamicImage {
        dynamic_map!(*self, ref p => imageops::rotate270(p))
    }
    
    pub fn write_to<W: Write, F: Into<ImageOutputFormat>>(
        &self,
        w: &mut W,
        format: F,
    ) -> ImageResult<()> {
        #[allow(unused_variables)]
        
        let w = w;
        #[allow(unused_variables,unused_mut)]
        let mut bytes = self.to_bytes();
        #[allow(unused_variables)]
        let (width, height) = self.dimensions();
        #[allow(unused_variables,unused_mut)]
        let mut color = self.color();
        let format = format.into();
        #[allow(deprecated)]
        match format {
            #[cfg(feature = "png")]
            image::ImageOutputFormat::Png => {
                let p = png::PngEncoder::new(w);
                match *self {
                    DynamicImage::ImageBgra8(_) => {
                        bytes = self.to_rgba().iter().cloned().collect();
                        color = color::ColorType::Rgba8;
                    }
                    DynamicImage::ImageBgr8(_) => {
                        bytes = self.to_rgb().iter().cloned().collect();
                        color = color::ColorType::Rgb8;
                    }
                    _ => {}
                }
                p.encode(&bytes, width, height, color)?;
                Ok(())
            }
            #[cfg(feature = "pnm")]
            image::ImageOutputFormat::Pnm(subtype) => {
                let mut p = pnm::PnmEncoder::new(w).with_subtype(subtype);
                match *self {
                    DynamicImage::ImageBgra8(_) => {
                        bytes = self.to_rgba().iter().cloned().collect();
                        color = color::ColorType::Rgba8;
                    }
                    DynamicImage::ImageBgr8(_) => {
                        bytes = self.to_rgb().iter().cloned().collect();
                        color = color::ColorType::Rgb8;
                    }
                    _ => {}
                }
                p.encode(&bytes[..], width, height, color)?;
                Ok(())
            }
            #[cfg(feature = "jpeg")]
            image::ImageOutputFormat::Jpeg(quality) => {
                let j = jpeg::JpegEncoder::new_with_quality(w, quality);
                j.write_image(&bytes, width, height, color)?;
                Ok(())
            }
            #[cfg(feature = "gif")]
            image::ImageOutputFormat::Gif => {
                let mut g = gif::GifEncoder::new(w);
                g.encode_frame(crate::animation::Frame::new(self.to_rgba()))?;
                Ok(())
            }
            #[cfg(feature = "ico")]
            image::ImageOutputFormat::Ico => {
                let i = ico::IcoEncoder::new(w);
                i.encode(&bytes, width, height, color)?;
                Ok(())
            }
            #[cfg(feature = "bmp")]
            image::ImageOutputFormat::Bmp => {
                let mut b = bmp::BmpEncoder::new(w);
                b.encode(&bytes, width, height, color)?;
                Ok(())
            }
            #[cfg(feature = "farbfeld")]
            image::ImageOutputFormat::Farbfeld => {
                farbfeld::FarbfeldEncoder::new(w).write_image(&bytes, width, height, color)
            }
            #[cfg(feature = "tga")]
            image::ImageOutputFormat::Tga => {
                tga::TgaEncoder::new(w).write_image(&bytes, width, height, color)
            }
            #[cfg(feature = "avif")]
            image::ImageOutputFormat::Avif => {
                avif::AvifEncoder::new(w).write_image(&bytes, width, height, color)
            }
            image::ImageOutputFormat::Unsupported(msg) => {
                Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
                    ImageFormatHint::Unknown,
                    UnsupportedErrorKind::Format(ImageFormatHint::Name(msg)))))
            },
            image::ImageOutputFormat::__NonExhaustive(marker) => match marker._private {},
        }
    }
    
    
    
    pub fn save<Q>(&self, path: Q) -> ImageResult<()>
    where
        Q: AsRef<Path>,
    {
        dynamic_map!(*self, ref p -> {
            p.save(path)
        })
    }
    
    
    
    
    
    pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> ImageResult<()>
    where
        Q: AsRef<Path>,
    {
        dynamic_map!(*self, ref p -> {
            p.save_with_format(path, format)
        })
    }
}
#[allow(deprecated)]
impl GenericImageView for DynamicImage {
    type Pixel = color::Rgba<u8>;
    type InnerImageView = Self;
    fn dimensions(&self) -> (u32, u32) {
        dynamic_map!(*self, ref p -> p.dimensions())
    }
    fn bounds(&self) -> (u32, u32, u32, u32) {
        dynamic_map!(*self, ref p -> p.bounds())
    }
    fn get_pixel(&self, x: u32, y: u32) -> color::Rgba<u8> {
        dynamic_map!(*self, ref p -> p.get_pixel(x, y).to_rgba().into_color())
    }
    fn inner(&self) -> &Self::InnerImageView {
        self
    }
}
#[allow(deprecated)]
impl GenericImage for DynamicImage {
    type InnerImage = DynamicImage;
    fn put_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba<u8>) {
        match *self {
            DynamicImage::ImageLuma8(ref mut p) => p.put_pixel(x, y, pixel.to_luma()),
            DynamicImage::ImageLumaA8(ref mut p) => p.put_pixel(x, y, pixel.to_luma_alpha()),
            DynamicImage::ImageRgb8(ref mut p) => p.put_pixel(x, y, pixel.to_rgb()),
            DynamicImage::ImageRgba8(ref mut p) => p.put_pixel(x, y, pixel),
            DynamicImage::ImageBgr8(ref mut p) => p.put_pixel(x, y, pixel.to_bgr()),
            DynamicImage::ImageBgra8(ref mut p) => p.put_pixel(x, y, pixel.to_bgra()),
            DynamicImage::ImageLuma16(ref mut p) => p.put_pixel(x, y, pixel.to_luma().into_color()),
            DynamicImage::ImageLumaA16(ref mut p) => p.put_pixel(x, y, pixel.to_luma_alpha().into_color()),
            DynamicImage::ImageRgb16(ref mut p) => p.put_pixel(x, y, pixel.to_rgb().into_color()),
            DynamicImage::ImageRgba16(ref mut p) => p.put_pixel(x, y, pixel.into_color()),
        }
    }
    
    fn blend_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba<u8>) {
        match *self {
            DynamicImage::ImageLuma8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma()),
            DynamicImage::ImageLumaA8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma_alpha()),
            DynamicImage::ImageRgb8(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb()),
            DynamicImage::ImageRgba8(ref mut p) => p.blend_pixel(x, y, pixel),
            DynamicImage::ImageBgr8(ref mut p) => p.blend_pixel(x, y, pixel.to_bgr()),
            DynamicImage::ImageBgra8(ref mut p) => p.blend_pixel(x, y, pixel.to_bgra()),
            DynamicImage::ImageLuma16(ref mut p) => p.blend_pixel(x, y, pixel.to_luma().into_color()),
            DynamicImage::ImageLumaA16(ref mut p) => p.blend_pixel(x, y, pixel.to_luma_alpha().into_color()),
            DynamicImage::ImageRgb16(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb().into_color()),
            DynamicImage::ImageRgba16(ref mut p) => p.blend_pixel(x, y, pixel.into_color()),
        }
    }
    
    fn get_pixel_mut(&mut self, _: u32, _: u32) -> &mut color::Rgba<u8> {
        unimplemented!()
    }
    fn inner_mut(&mut self) -> &mut Self::InnerImage {
        self
    }
}
fn decoder_to_image<'a, I: ImageDecoder<'a>>(decoder: I) -> ImageResult<DynamicImage> {
    let (w, h) = decoder.dimensions();
    let color_type = decoder.color_type();
    let image = match color_type {
        color::ColorType::Rgb8 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb8)
        }
        color::ColorType::Rgba8 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba8)
        }
        color::ColorType::Bgr8 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageBgr8)
        }
        color::ColorType::Bgra8 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageBgra8)
        }
        color::ColorType::L8 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLuma8)
        }
        color::ColorType::La8 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLumaA8)
        }
        color::ColorType::Rgb16 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb16)
        }
        color::ColorType::Rgba16 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba16)
        }
        color::ColorType::L16 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLuma16)
        }
        color::ColorType::La16 => {
            let buf = image::decoder_to_vec(decoder)?;
            ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLumaA16)
        }
        _ => return Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
            ImageFormatHint::Unknown,
            UnsupportedErrorKind::Color(color_type.into()),
        ))),
    };
    match image {
        Some(image) => Ok(image),
        None => Err(ImageError::Parameter(
            ParameterError::from_kind(ParameterErrorKind::DimensionMismatch)
        ))
    }
}
#[allow(deprecated)]
fn image_to_bytes(image: &DynamicImage) -> Vec<u8> {
    use crate::traits::EncodableLayout;
    match *image {
        
        DynamicImage::ImageLuma8(ref a) => a.iter().cloned().collect(),
        DynamicImage::ImageLumaA8(ref a) => a.iter().cloned().collect(),
        DynamicImage::ImageRgb8(ref a) => a.iter().cloned().collect(),
        DynamicImage::ImageRgba8(ref a) => a.iter().cloned().collect(),
        DynamicImage::ImageBgr8(ref a) => a.iter().cloned().collect(),
        DynamicImage::ImageBgra8(ref a) => a.iter().cloned().collect(),
        DynamicImage::ImageLuma16(ref a) => a.as_bytes().to_vec(),
        DynamicImage::ImageLumaA16(ref a) => a.as_bytes().to_vec(),
        DynamicImage::ImageRgb16(ref a) => a.as_bytes().to_vec(),
        DynamicImage::ImageRgba16(ref a) => a.as_bytes().to_vec(),
    }
}
fn image_into_bytes(image: DynamicImage) -> Vec<u8> {
    match image {
        DynamicImage::ImageLuma8(a) => a.into_raw(),
        DynamicImage::ImageLumaA8(a) => a.into_raw(),
        DynamicImage::ImageRgb8(a) => a.into_raw(),
        DynamicImage::ImageRgba8(a) => a.into_raw(),
        DynamicImage::ImageBgr8(a) => a.into_raw(),
        DynamicImage::ImageBgra8(a) => a.into_raw(),
        DynamicImage::ImageLuma16(_) => image.to_bytes(),
        DynamicImage::ImageLumaA16(_) => image.to_bytes(),
        DynamicImage::ImageRgb16(_) => image.to_bytes(),
        DynamicImage::ImageRgba16(_) => image.to_bytes(),
    }
}
fn image_as_bytes(image: &DynamicImage) -> &[u8] {
    use bytemuck::cast_slice;
    match image {
        DynamicImage::ImageLuma8(a) => &*a,
        DynamicImage::ImageLumaA8(a) => &*a,
        DynamicImage::ImageRgb8(a) => &*a,
        DynamicImage::ImageRgba8(a) => &*a,
        DynamicImage::ImageBgr8(a) => &*a,
        DynamicImage::ImageBgra8(a) => &*a,
        DynamicImage::ImageLuma16(a) => cast_slice(&*a),
        DynamicImage::ImageLumaA16(a) => cast_slice(&*a),
        DynamicImage::ImageRgb16(a) => cast_slice(&*a),
        DynamicImage::ImageRgba16(a) => cast_slice(&*a),
    }
}
pub fn open<P>(path: P) -> ImageResult<DynamicImage>
where
    P: AsRef<Path>,
{
    
    free_functions::open_impl(path.as_ref())
}
pub fn image_dimensions<P>(path: P) -> ImageResult<(u32, u32)>
where
    P: AsRef<Path>,
{
    
    free_functions::image_dimensions_impl(path.as_ref())
}
pub fn save_buffer<P>(
    path: P,
    buf: &[u8],
    width: u32,
    height: u32,
    color: color::ColorType,
) -> ImageResult<()>
where
    P: AsRef<Path>,
{
    
    free_functions::save_buffer_impl(path.as_ref(), buf, width, height, color)
}
pub fn save_buffer_with_format<P>(
    path: P,
    buf: &[u8],
    width: u32,
    height: u32,
    color: color::ColorType,
    format: ImageFormat,
) -> ImageResult<()>
where
    P: AsRef<Path>,
{
    
    free_functions::save_buffer_with_format_impl(path.as_ref(), buf, width, height, color, format)
}
pub fn load_from_memory(buffer: &[u8]) -> ImageResult<DynamicImage> {
    let format = free_functions::guess_format(buffer)?;
    load_from_memory_with_format(buffer, format)
}
#[inline(always)]
pub fn load_from_memory_with_format(buf: &[u8], format: ImageFormat) -> ImageResult<DynamicImage> {
    let b = io::Cursor::new(buf);
    free_functions::load(b, format)
}
#[cfg(test)]
mod bench {
    #[cfg(feature = "benchmarks")]
    use test;
    #[bench]
    #[cfg(feature = "benchmarks")]
    fn bench_conversion(b: &mut test::Bencher) {
        let a = super::DynamicImage::ImageRgb8(crate::ImageBuffer::new(1000, 1000));
        b.iter(|| a.to_luma());
        b.bytes = 1000 * 1000 * 3
    }
}
#[cfg(test)]
mod test {
    #[test]
    fn test_empty_file() {
        assert!(super::load_from_memory(b"").is_err());
    }
    #[cfg(feature = "jpeg")]
    #[test]
    fn image_dimensions() {
        let im_path = "./tests/images/jpg/progressive/cat.jpg";
        let dims = super::image_dimensions(im_path).unwrap();
        assert_eq!(dims, (320, 240));
    }
    #[cfg(feature = "png")]
    #[test]
    fn open_16bpc_png() {
        let im_path = "./tests/images/png/16bpc/basn6a16.png";
        let image = super::open(im_path).unwrap();
        assert_eq!(image.color(), super::color::ColorType::Rgba16);
    }
}