#![allow(dead_code)]
mod blocks;
#[doc(hidden)]
pub mod chroma;
#[doc(hidden)]
pub mod dct;
pub(crate) mod layout;
mod progressive;
pub(crate) mod scan_optimize;
#[doc(hidden)]
pub mod scan_script;
mod serialize;
#[doc(hidden)]
pub mod config;
pub(crate) mod linear_lut;
#[cfg(target_arch = "x86_64")]
#[doc(hidden)]
pub mod mage_simd;
#[cfg(target_arch = "aarch64")]
#[doc(hidden)]
pub mod arm_simd;
#[cfg(target_arch = "wasm32")]
#[doc(hidden)]
pub mod wasm_simd;
pub mod deringing;
#[cfg(feature = "parallel")]
#[doc(hidden)]
pub mod parallel;
#[doc(hidden)]
pub mod streaming;
#[doc(hidden)]
pub mod streaming_builder;
#[doc(hidden)]
pub mod strip;
pub mod byte_encoders;
pub mod encoder_config;
pub mod encoder_types;
pub mod exif;
pub mod extras;
pub mod request;
pub mod tables;
pub mod tuning;
#[cfg(feature = "trellis")]
pub mod trellis;
#[cfg(feature = "trellis")]
pub mod search;
#[doc(hidden)]
pub mod v2;
#[allow(unused_imports)] pub use blocks::HuffmanSymbolFrequencies;
pub(crate) use blocks::build_nonzero_mask;
#[allow(unused_imports)] pub use byte_encoders::{BytesEncoder, Pixel, RgbEncoder, YCbCrPlanarEncoder};
#[allow(unused_imports)] pub use encoder_config::EncoderConfig;
#[cfg(feature = "trellis")]
#[allow(unused_imports)] pub use encoder_types::ExpertConfig;
#[cfg(feature = "parallel")]
#[allow(unused_imports)] pub use encoder_types::ParallelEncoding;
#[allow(unused_imports)] pub use encoder_types::{
ChromaSubsampling, ColorMode, DownsamplingMethod, Effort, HuffmanStrategy, OptimizationPreset,
PixelLayout, ProgressiveScanMode, Quality, QuantTableConfig, QuantTableSource, ScanStrategy,
XybSubsampling, YCbCrPlanes,
};
pub use enough::Stop;
#[allow(unused_imports)] pub use exif::{Exif, ExifFields, Orientation};
#[allow(unused_imports)] pub use extras::{EncoderSegment, EncoderSegments, MpfImage};
#[allow(unused_imports)] pub use request::EncodeRequest;
#[allow(unused_imports)] pub use tables::presets::{MozjpegTables, QuantTablePreset};
use crate::error::Result;
pub(crate) use config::ProgressiveScan;
use crate::foundation::alloc::{try_alloc_zeroed_f32, try_clone_slice};
use crate::foundation::consts::{DCT_BLOCK_SIZE, JPEG_ZIGZAG_ORDER};
use crate::types::{EdgePadding, EdgePaddingConfig};
#[inline]
fn natural_to_zigzag_into(natural: &[i16; DCT_BLOCK_SIZE], dest: &mut [i16; DCT_BLOCK_SIZE]) {
for i in 0..DCT_BLOCK_SIZE {
dest[JPEG_ZIGZAG_ORDER[i] as usize] = natural[i];
}
}
#[inline]
fn get_padded_coord(coord: usize, size: usize, strategy: EdgePadding) -> usize {
if coord < size {
return coord;
}
match strategy {
EdgePadding::Replicate => size - 1,
EdgePadding::Mirror => {
let d = coord - size;
size.saturating_sub(1).saturating_sub(d)
}
EdgePadding::Wrap => coord % size,
}
}
pub(crate) fn pad_plane_f32(
plane: &[f32],
width: usize,
height: usize,
mcu_size: usize,
strategy: EdgePadding,
) -> Result<(Vec<f32>, usize, usize)> {
let padded_w = (width + mcu_size - 1) / mcu_size * mcu_size;
let padded_h = (height + mcu_size - 1) / mcu_size * mcu_size;
if padded_w == width && padded_h == height {
return Ok((
try_clone_slice(plane, "pad_plane_f32 clone")?,
width,
height,
));
}
let mut out = try_alloc_zeroed_f32(padded_w * padded_h, "pad_plane_f32 output")?;
for y in 0..padded_h {
let src_y = get_padded_coord(y, height, strategy);
for x in 0..padded_w {
let src_x = get_padded_coord(x, width, strategy);
out[y * padded_w + x] = plane[src_y * width + src_x];
}
}
Ok((out, padded_w, padded_h))
}
#[allow(clippy::type_complexity)]
#[allow(dead_code)]
pub(crate) fn pad_ycbcr_planes_subsampled(
y: &[f32],
width: usize,
height: usize,
cb: &[f32],
cr: &[f32],
c_width: usize,
c_height: usize,
mcu_size: usize,
config: EdgePaddingConfig,
) -> Result<((Vec<f32>, Vec<f32>, Vec<f32>), usize, usize, usize, usize)> {
let (y_padded, padded_w, padded_h) = pad_plane_f32(y, width, height, mcu_size, config.luma)?;
let (cb_padded, padded_cw, padded_ch) = pad_plane_f32(cb, c_width, c_height, 8, config.chroma)?;
let (cr_padded, _, _) = pad_plane_f32(cr, c_width, c_height, 8, config.chroma)?;
Ok((
(y_padded, cb_padded, cr_padded),
padded_w,
padded_h,
padded_cw,
padded_ch,
))
}
#[allow(dead_code)] pub(crate) fn pad_gray_plane(
y: &[f32],
width: usize,
height: usize,
mcu_size: usize,
config: EdgePaddingConfig,
) -> Result<(Vec<f32>, usize, usize)> {
pad_plane_f32(y, width, height, mcu_size, config.luma)
}