#![allow(clippy::needless_borrow)]
#![allow(clippy::missing_safety_doc)]
#![allow(non_upper_case_globals)]
use crate::rustimpl::RGBA;
use std::fmt;
use std::io;
use std::num::NonZeroU8;
use std::os::raw::{c_uint, c_void};
#[cfg(not(unix))]
use std::path::PathBuf;
#[cfg(any(feature = "c_ffi", feature = "_deprecated_c_ffi_default_"))]
mod functions;
#[repr(C)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct ErrorCode(pub c_uint);
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ColorType {
GREY = 0,
RGB = 2,
PALETTE = 3,
GREY_ALPHA = 4,
RGBA = 6,
BGRA = 6 | 64,
BGR = 2 | 64,
BGRX = 3 | 64,
}
impl ColorType {
#[must_use]
pub fn bpp(&self, bitdepth: u32) -> u32 {
self.bpp_(bitdepth).get().into()
}
#[inline]
pub(crate) fn bpp_(self, bitdepth: u32) -> NonZeroU8 {
let bitdepth = bitdepth as u8;
let ch = self.channels();
NonZeroU8::new(if ch > 1 {
ch * if bitdepth == 8 {
8
} else {
16
}
} else {
debug_assert!((bitdepth > 0 && bitdepth <= 8) || bitdepth == 16, "{bitdepth}x{ch}");
bitdepth.max(1)
}).unwrap()
}
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct ColorMode {
pub colortype: ColorType,
pub(crate) bitdepth: c_uint,
pub(crate) palette: Option<Box<[RGBA; 256]>>,
pub(crate) palettesize: usize,
pub(crate) key_defined: c_uint,
pub(crate) key_r: c_uint,
pub(crate) key_g: c_uint,
pub(crate) key_b: c_uint,
}
pub type custom_compress_callback = Option<fn(input: &[u8], output: &mut dyn io::Write, context: &CompressSettings) -> Result<(), crate::Error>>;
pub type custom_decompress_callback = Option<fn(input: &[u8], output: &mut dyn io::Write, context: &DecompressSettings) -> Result<(), crate::Error>>;
#[repr(C)]
#[derive(Clone)]
pub struct DecompressSettings {
pub(crate) custom_zlib: custom_decompress_callback,
pub(crate) custom_inflate: custom_decompress_callback,
pub(crate) custom_context: *const c_void,
}
impl fmt::Debug for DecompressSettings {
#[cold]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = f.debug_struct("DecompressSettings");
s.field("custom_zlib", &self.custom_zlib.is_some());
s.field("custom_inflate", &self.custom_inflate.is_some());
s.field("custom_context", &self.custom_context);
s.finish()
}
}
#[repr(C)]
#[derive(Clone)]
pub struct CompressSettings {
#[deprecated]
pub windowsize: u32,
#[deprecated]
pub minmatch: u16,
#[deprecated]
pub nicematch: u16,
#[deprecated]
pub btype: u8,
#[deprecated]
pub use_lz77: bool,
#[deprecated]
pub lazymatching: bool,
#[deprecated(note = "use features of the flate2 crate instead")]
pub custom_zlib: custom_compress_callback,
#[deprecated(note = "use features of the flate2 crate instead")]
pub custom_deflate: custom_compress_callback,
pub custom_context: *const c_void,
}
impl CompressSettings {
#[allow(deprecated)]
pub fn set_level(&mut self, level: u8) {
self.use_lz77 = level != 0;
self.minmatch = level.into();
}
#[allow(deprecated)]
#[must_use]
pub fn level(&self) -> u8 {
if self.use_lz77 {
if self.minmatch > 0 && self.minmatch <= 9 {
self.minmatch as _
} else {
7
}
} else {
0
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct Time {
pub year: u16,
pub month: u8,
pub day: u8,
pub hour: u8,
pub minute: u8,
pub second: u8,
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct Info {
pub interlace_method: u8,
pub color: ColorMode,
pub background_defined: bool,
pub background_r: u16,
pub background_g: u16,
pub background_b: u16,
pub time_defined: bool,
pub time: Time,
pub phys_defined: bool,
pub phys_x: c_uint,
pub phys_y: c_uint,
pub phys_unit: u8,
#[allow(clippy::box_collection)]
pub(crate) unknown_chunks: [Box<Vec<u8>>; 3],
pub(crate) always_zero_for_ffi_hack: [usize; 3],
pub(crate) texts: Vec<LatinText>,
pub(crate) itexts: Vec<IntlText>,
}
#[derive(Debug, Clone)]
pub(crate) struct LatinText {
pub(crate) key: Box<[u8]>,
pub(crate) value: Box<[u8]>,
}
#[derive(Debug, Clone)]
pub(crate) struct IntlText {
pub(crate) key: Box<str>,
pub(crate) langtag: Box<str>,
pub(crate) transkey: Box<str>,
pub(crate) value: Box<str>,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct DecoderSettings {
pub zlibsettings: DecompressSettings,
pub ignore_crc: bool,
pub color_convert: bool,
pub read_text_chunks: bool,
pub remember_unknown_chunks: bool,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FilterStrategy {
ZERO = 0,
MINSUM,
ENTROPY,
BRUTE_FORCE,
PREDEFINED,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct EncoderSettings {
pub zlibsettings: CompressSettings,
pub auto_convert: bool,
pub filter_palette_zero: bool,
pub filter_strategy: FilterStrategy,
pub(crate) predefined_filters: *const u8,
pub force_palette: bool,
pub add_id: bool,
pub text_compression: bool,
}
unsafe impl Send for EncoderSettings {}
unsafe impl Sync for EncoderSettings {}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct State {
pub decoder: DecoderSettings,
pub encoder: EncoderSettings,
pub info_raw: ColorMode,
pub info_png: Info,
pub error: ErrorCode,
}
#[repr(C)]
#[derive(Debug)]
pub struct ColorProfile {
pub colored: bool,
pub key: bool,
pub key_r: u16,
pub key_g: u16,
pub key_b: u16,
pub alpha: bool,
pub bits: u8,
pub numcolors: u16,
pub palette: [crate::RGBA; 256],
}
impl fmt::Debug for CompressSettings {
#[allow(deprecated)]
#[cold]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = f.debug_struct("CompressSettings");
s.field("minmatch", &self.minmatch);
s.field("use_lz77", &self.use_lz77);
s.field("custom_zlib", &self.custom_zlib.is_some());
s.field("custom_deflate", &self.custom_deflate.is_some());
s.field("custom_context", &self.custom_context);
s.finish()
}
}