#![allow(clippy::zero_prefixed_literal)]
use crate::bit_depth::ByteEndian;
use crate::colorspace::ColorSpace;
fn decoder_strict_mode() -> DecoderFlags {
DecoderFlags {
inflate_confirm_adler: true,
png_confirm_crc: true,
jpg_error_on_non_conformance: true,
zune_use_unsafe: true,
zune_use_neon: true,
zune_use_avx: true,
zune_use_avx2: true,
zune_use_sse2: true,
zune_use_sse3: true,
zune_use_sse41: true,
png_add_alpha_channel: false,
png_strip_16_bit_to_8_bit: false,
png_decode_animated: true,
jxl_decode_animated: true
}
}
fn fast_options() -> DecoderFlags {
DecoderFlags {
inflate_confirm_adler: false,
png_confirm_crc: false,
jpg_error_on_non_conformance: false,
zune_use_unsafe: true,
zune_use_neon: true,
zune_use_avx: true,
zune_use_avx2: true,
zune_use_sse2: true,
zune_use_sse3: true,
zune_use_sse41: true,
png_add_alpha_channel: false,
png_strip_16_bit_to_8_bit: false,
png_decode_animated: true,
jxl_decode_animated: true
}
}
fn cmd_options() -> DecoderFlags {
DecoderFlags {
inflate_confirm_adler: false,
png_confirm_crc: false,
jpg_error_on_non_conformance: false,
zune_use_unsafe: true,
zune_use_neon: true,
zune_use_avx: true,
zune_use_avx2: true,
zune_use_sse2: true,
zune_use_sse3: true,
zune_use_sse41: true,
png_add_alpha_channel: false,
png_strip_16_bit_to_8_bit: false,
png_decode_animated: true,
jxl_decode_animated: true
}
}
#[derive(Copy, Debug, Clone, Default)]
pub struct DecoderFlags {
inflate_confirm_adler: bool,
png_confirm_crc: bool,
jpg_error_on_non_conformance: bool,
zune_use_unsafe: bool,
zune_use_sse2: bool,
zune_use_sse3: bool,
zune_use_sse41: bool,
zune_use_avx: bool,
zune_use_avx2: bool,
png_add_alpha_channel: bool,
zune_use_neon: bool,
png_strip_16_bit_to_8_bit: bool,
png_decode_animated: bool,
jxl_decode_animated: bool
}
#[derive(Debug, Copy, Clone)]
pub struct DecoderOptions {
max_width: usize,
max_height: usize,
out_colorspace: ColorSpace,
max_scans: usize,
deflate_limit: usize,
flags: DecoderFlags,
endianness: ByteEndian
}
impl DecoderOptions {
pub fn new_safe() -> DecoderOptions {
DecoderOptions::default()
}
pub fn new_fast() -> DecoderOptions {
let flag = fast_options();
DecoderOptions::default().set_decoder_flags(flag)
}
pub fn new_cmd() -> DecoderOptions {
let flag = cmd_options();
DecoderOptions::default().set_decoder_flags(flag)
}
}
impl DecoderOptions {
pub const fn get_max_width(&self) -> usize {
self.max_width
}
pub const fn get_max_height(&self) -> usize {
self.max_height
}
pub fn get_strict_mode(&self) -> bool {
self.flags.jpg_error_on_non_conformance
| self.flags.png_confirm_crc
| self.flags.inflate_confirm_adler
}
pub const fn get_use_unsafe(&self) -> bool {
self.flags.zune_use_unsafe
}
pub fn set_max_width(mut self, width: usize) -> Self {
self.max_width = width;
self
}
pub fn set_max_height(mut self, height: usize) -> Self {
self.max_height = height;
self
}
pub fn set_use_unsafe(mut self, yes: bool) -> Self {
self.flags.zune_use_unsafe = yes;
self
}
fn set_decoder_flags(mut self, flags: DecoderFlags) -> Self {
self.flags = flags;
self
}
pub fn set_strict_mode(mut self, yes: bool) -> Self {
self.flags.jpg_error_on_non_conformance = yes;
self.flags.png_confirm_crc = yes;
self.flags.inflate_confirm_adler = yes;
self
}
pub fn set_byte_endian(mut self, endian: ByteEndian) -> Self {
self.endianness = endian;
self
}
pub const fn get_byte_endian(&self) -> ByteEndian {
self.endianness
}
}
impl DecoderOptions {
pub const fn inflate_get_confirm_adler(&self) -> bool {
self.flags.inflate_confirm_adler
}
pub fn inflate_set_confirm_adler(mut self, yes: bool) -> Self {
self.flags.inflate_confirm_adler = yes;
self
}
pub const fn inflate_get_limit(&self) -> usize {
self.deflate_limit
}
#[must_use]
pub fn inflate_set_limit(mut self, limit: usize) -> Self {
self.deflate_limit = limit;
self
}
pub const fn png_get_confirm_crc(&self) -> bool {
self.flags.png_confirm_crc
}
#[must_use]
pub fn png_set_confirm_crc(mut self, yes: bool) -> Self {
self.flags.png_confirm_crc = yes;
self
}
pub fn png_set_add_alpha_channel(mut self, yes: bool) -> Self {
self.flags.png_add_alpha_channel = yes;
self
}
pub const fn png_get_add_alpha_channel(&self) -> bool {
self.flags.png_add_alpha_channel
}
pub fn png_set_strip_to_8bit(mut self, yes: bool) -> Self {
self.flags.png_strip_16_bit_to_8_bit = yes;
self
}
pub const fn png_get_strip_to_8bit(&self) -> bool {
self.flags.png_strip_16_bit_to_8_bit
}
pub const fn png_decode_animated(&self) -> bool {
self.flags.png_decode_animated
}
pub const fn png_set_decode_animated(mut self, yes: bool) -> Self {
self.flags.png_decode_animated = yes;
self
}
}
impl DecoderOptions {
pub const fn jpeg_get_max_scans(&self) -> usize {
self.max_scans
}
pub fn jpeg_set_max_scans(mut self, max_scans: usize) -> Self {
self.max_scans = max_scans;
self
}
pub const fn jpeg_get_out_colorspace(&self) -> ColorSpace {
self.out_colorspace
}
#[must_use]
pub fn jpeg_set_out_colorspace(mut self, colorspace: ColorSpace) -> Self {
self.out_colorspace = colorspace;
self
}
}
impl DecoderOptions {
#[allow(unreachable_code)]
pub fn use_sse2(&self) -> bool {
let opt = self.flags.zune_use_sse2 | self.flags.zune_use_unsafe;
if !opt {
return false;
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
{
#[cfg(feature = "std")]
{
if is_x86_feature_detected!("sse2") {
return true;
}
}
#[cfg(all(not(feature = "std"), target_feature = "sse2"))]
{
return true;
}
}
false
}
#[allow(unreachable_code)]
pub fn use_sse3(&self) -> bool {
let opt = self.flags.zune_use_sse3 | self.flags.zune_use_unsafe;
if !opt {
return false;
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
{
#[cfg(feature = "std")]
{
if is_x86_feature_detected!("sse3") {
return true;
}
}
#[cfg(all(not(feature = "std"), target_feature = "sse3"))]
{
return true;
}
}
false
}
#[allow(unreachable_code)]
pub fn use_sse41(&self) -> bool {
let opt = self.flags.zune_use_sse41 | self.flags.zune_use_unsafe;
if !opt {
return false;
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
{
#[cfg(feature = "std")]
{
if is_x86_feature_detected!("sse4.1") {
return true;
}
}
#[cfg(all(not(feature = "std"), target_feature = "sse4.1"))]
{
return true;
}
}
false
}
#[allow(unreachable_code)]
pub fn use_avx(&self) -> bool {
let opt = self.flags.zune_use_avx | self.flags.zune_use_unsafe;
if !opt {
return false;
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
{
#[cfg(feature = "std")]
{
if is_x86_feature_detected!("avx") {
return true;
}
}
#[cfg(all(not(feature = "std"), target_feature = "avx"))]
{
return true;
}
}
false
}
#[allow(unreachable_code)]
pub fn use_avx2(&self) -> bool {
let opt = self.flags.zune_use_avx2 | self.flags.zune_use_unsafe;
if !opt {
return false;
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
{
#[cfg(feature = "std")]
{
if is_x86_feature_detected!("avx2") {
return true;
}
}
#[cfg(all(not(feature = "std"), target_feature = "avx2"))]
{
return true;
}
}
false
}
#[allow(unreachable_code)]
pub fn use_neon(&self) -> bool {
let opt = self.flags.zune_use_neon | self.flags.zune_use_unsafe;
if !opt {
return false;
}
#[cfg(target_arch = "aarch64")]
{
return true;
}
false
}
}
impl DecoderOptions {
pub const fn jxl_decode_animated(&self) -> bool {
self.flags.jxl_decode_animated
}
pub const fn jxl_set_decode_animated(mut self, yes: bool) -> Self {
self.flags.jxl_decode_animated = yes;
self
}
}
impl Default for DecoderOptions {
fn default() -> Self {
Self {
out_colorspace: ColorSpace::RGB,
max_width: 1 << 14,
max_height: 1 << 14,
max_scans: 100,
deflate_limit: 1 << 30,
flags: decoder_strict_mode(),
endianness: ByteEndian::BE
}
}
}