use crate::{
structs::tags::{Predictor, SampleFormat},
util::fix_endianness,
ByteOrder, ColorType,
};
mod reader;
pub use reader::{CogReader, EndianReader};
mod chunk_decoder;
pub use chunk_decoder::ChunkDecoder;
#[allow(clippy::module_inception)]
mod decoder;
pub use decoder::{Decoder, IfdBuffer, IfdCache};
mod image_decoder;
pub use image_decoder::ImageDecoder;
mod decoding_result;
pub use decoding_result::DecodingResult;
mod cogreader_impls;
fn rev_hpredict_nsamp(buf: &mut [u8], bit_depth: u8, samples: usize) {
match bit_depth {
0..=8 => {
for i in samples..buf.len() {
buf[i] = buf[i].wrapping_add(buf[i - samples]);
}
}
9..=16 => {
for i in (samples * 2..buf.len()).step_by(2) {
let v = u16::from_ne_bytes(buf[i..][..2].try_into().unwrap());
let p = u16::from_ne_bytes(buf[i - 2 * samples..][..2].try_into().unwrap());
buf[i..][..2].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
}
}
17..=32 => {
for i in (samples * 4..buf.len()).step_by(4) {
let v = u32::from_ne_bytes(buf[i..][..4].try_into().unwrap());
let p = u32::from_ne_bytes(buf[i - 4 * samples..][..4].try_into().unwrap());
buf[i..][..4].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
}
}
33..=64 => {
for i in (samples * 8..buf.len()).step_by(8) {
let v = u64::from_ne_bytes(buf[i..][..8].try_into().unwrap());
let p = u64::from_ne_bytes(buf[i - 8 * samples..][..8].try_into().unwrap());
buf[i..][..8].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
}
}
_ => {
unreachable!("Caller should have validated arguments. Please file a bug.")
}
}
}
pub fn predict_f32(input: &mut [u8], output: &mut [u8], samples: usize) {
for i in samples..input.len() {
input[i] = input[i].wrapping_add(input[i - samples]);
}
for (i, chunk) in output.chunks_mut(4).enumerate() {
chunk.copy_from_slice(&u32::to_ne_bytes(
u32::from_be_bytes([
input[i],
input[input.len() / 4 + i],
input[input.len() / 4 * 2 + i],
input[input.len() / 4 * 3 + i],
]),
));
}
}
fn predict_f64(input: &mut [u8], output: &mut [u8], samples: usize) {
for i in samples..input.len() {
input[i] = input[i].wrapping_add(input[i - samples]);
}
for (i, chunk) in output.chunks_mut(8).enumerate() {
chunk.copy_from_slice(&u64::to_ne_bytes(u64::from_be_bytes([
input[i],
input[input.len() / 8 + i],
input[input.len() / 8 * 2 + i],
input[input.len() / 8 * 3 + i],
input[input.len() / 8 * 4 + i],
input[input.len() / 8 * 5 + i],
input[input.len() / 8 * 6 + i],
input[input.len() / 8 * 7 + i],
])));
}
}
fn fix_endianness_and_predict(
buf: &mut [u8],
bit_depth: u8,
samples: usize,
byte_order: ByteOrder,
predictor: Predictor,
) {
match predictor {
Predictor::None => {
fix_endianness(buf, byte_order, bit_depth);
}
Predictor::Horizontal => {
fix_endianness(buf, byte_order, bit_depth);
rev_hpredict_nsamp(buf, bit_depth, samples);
}
Predictor::FloatingPoint => {
let mut buffer_copy = buf.to_vec();
match bit_depth {
32 => predict_f32(&mut buffer_copy, buf, samples),
64 => predict_f64(&mut buffer_copy, buf, samples),
_ => unreachable!("Caller should have validated arguments. Please file a bug."),
}
}
}
}
fn invert_colors(buf: &mut [u8], color_type: ColorType, sample_format: SampleFormat) {
match (color_type, sample_format) {
(ColorType::Gray(8), SampleFormat::Uint) => {
for x in buf {
*x = 0xff - *x;
}
}
(ColorType::Gray(16), SampleFormat::Uint) => {
for x in buf.chunks_mut(2) {
let v = u16::from_ne_bytes(x.try_into().unwrap());
x.copy_from_slice(&(0xffff - v).to_ne_bytes());
}
}
(ColorType::Gray(32), SampleFormat::Uint) => {
for x in buf.chunks_mut(4) {
let v = u32::from_ne_bytes(x.try_into().unwrap());
x.copy_from_slice(&(0xffff_ffff - v).to_ne_bytes());
}
}
(ColorType::Gray(64), SampleFormat::Uint) => {
for x in buf.chunks_mut(8) {
let v = u64::from_ne_bytes(x.try_into().unwrap());
x.copy_from_slice(&(0xffff_ffff_ffff_ffff - v).to_ne_bytes());
}
}
(ColorType::Gray(32), SampleFormat::IEEEFP) => {
for x in buf.chunks_mut(4) {
let v = f32::from_ne_bytes(x.try_into().unwrap());
x.copy_from_slice(&(1.0 - v).to_ne_bytes());
}
}
(ColorType::Gray(64), SampleFormat::IEEEFP) => {
for x in buf.chunks_mut(8) {
let v = f64::from_ne_bytes(x.try_into().unwrap());
x.copy_from_slice(&(1.0 - v).to_ne_bytes());
}
}
_ => {}
}
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct Limits {
pub decoding_buffer_size: usize,
pub ifd_value_size: usize,
pub intermediate_buffer_size: usize,
}
impl Limits {
pub fn unlimited() -> Limits {
Limits {
decoding_buffer_size: usize::MAX,
ifd_value_size: usize::MAX,
intermediate_buffer_size: usize::MAX,
}
}
}
impl Default for Limits {
fn default() -> Limits {
Limits {
decoding_buffer_size: 256 * 1024 * 1024,
intermediate_buffer_size: 128 * 1024 * 1024,
ifd_value_size: 64 * 1024 * 1024,
}
}
}