#![allow(dead_code)]
use std::fmt;
use std::io::{BufReader, Read};
use crate::errors::DecodeErrors;
pub const START_OF_FRAME_BASE: u16 = 0xffc0;
pub const START_OF_FRAME_EXT_SEQ: u16 = 0xffc1;
pub const START_OF_FRAME_PROG_DCT: u16 = 0xffc2;
pub const START_OF_FRAME_LOS_SEQ: u16 = 0xffc3;
pub const START_OF_FRAME_EXT_AR: u16 = 0xffc9;
pub const START_OF_FRAME_PROG_DCT_AR: u16 = 0xffca;
pub const START_OF_FRAME_LOS_SEQ_AR: u16 = 0xffcb;
#[rustfmt::skip]
pub const UN_ZIGZAG: [usize; 64 + 16] = [
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63
];
#[repr(align(16))]
#[derive(Clone)]
pub struct Aligned16<T: ?Sized>(pub T);
impl<T> Default for Aligned16<T>
where
T: Default,
{
fn default() -> Self
{
Aligned16(T::default())
}
}
#[repr(align(32))]
#[derive(Clone)]
pub struct Aligned32<T: ?Sized>(pub T);
impl<T> Default for Aligned32<T>
where
T: Default,
{
fn default() -> Self
{
Aligned32(T::default())
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ColorSpace
{
RGB,
GRAYSCALE,
YCbCr,
CMYK,
YCCK,
RGBA,
RGBX,
}
impl ColorSpace
{
#[must_use]
#[inline]
pub const fn num_components(self) -> usize
{
match self
{
Self::RGB | Self::YCbCr => 3,
Self::CMYK | Self::RGBA | Self::RGBX | Self::YCCK => 4,
Self::GRAYSCALE => 1,
}
}
}
impl Default for ColorSpace
{
fn default() -> Self
{
ColorSpace::RGB
}
}
#[derive(Eq, PartialEq, Copy, Clone)]
#[allow(clippy::upper_case_acronyms)]
pub enum SOFMarkers
{
BaselineDct,
ExtendedSequentialHuffman,
ProgressiveDctHuffman,
LosslessHuffman,
ExtendedSequentialDctArithmetic,
ProgressiveDctArithmetic,
LosslessArithmetic,
}
impl Default for SOFMarkers
{
fn default() -> Self
{
Self::BaselineDct
}
}
impl SOFMarkers
{
pub fn is_sequential_dct(self) -> bool
{
matches!(
self,
Self::BaselineDct
| Self::ExtendedSequentialHuffman
| Self::ExtendedSequentialDctArithmetic
)
}
pub fn is_lossless(self) -> bool
{
matches!(self, Self::LosslessHuffman | Self::LosslessArithmetic)
}
pub fn is_progressive(self) -> bool
{
matches!(
self,
Self::ProgressiveDctHuffman | Self::ProgressiveDctArithmetic
)
}
pub fn from_int(int: u16) -> Option<SOFMarkers>
{
match int
{
START_OF_FRAME_BASE => Some(Self::BaselineDct),
START_OF_FRAME_PROG_DCT => Some(Self::ProgressiveDctHuffman),
START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic),
START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman),
START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic),
START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman),
START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic),
_ => None,
}
}
}
impl fmt::Debug for SOFMarkers
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
match &self
{
Self::BaselineDct => write!(f, "Baseline DCT"),
Self::ExtendedSequentialHuffman =>
{
write!(f, "Extended sequential DCT, Huffman Coding")
}
Self::ProgressiveDctHuffman => write!(f, "Progressive DCT,Huffman Encoding"),
Self::LosslessHuffman => write!(f, "Lossless (sequential) Huffman encoding"),
Self::ExtendedSequentialDctArithmetic =>
{
write!(f, "Extended sequential DCT, arithmetic coding")
}
Self::ProgressiveDctArithmetic => write!(f, "Progressive DCT, arithmetic coding"),
Self::LosslessArithmetic => write!(f, "Lossless (sequential) arithmetic coding"),
}
}
}
#[inline]
#[allow(clippy::unused_io_amount)]
pub fn read_byte<R>(reader: &mut R) -> Result<u8, DecodeErrors>
where
R: Read,
{
let mut tmp = [0; 1];
reader.read_exact(&mut tmp)?;
Ok(tmp[0])
}
#[inline]
pub fn read_u16_be<R>(reader: &mut R) -> Result<u16, DecodeErrors>
where
R: Read,
{
let mut tmp: [u8; 2] = [0, 0];
if reader.read(&mut tmp)? != 2
{
return Err(DecodeErrors::ExhaustedData);
};
let v = u16::from_be_bytes(tmp);
Ok(v)
}
#[inline]
pub fn read_u16_into<R>(reader: &mut BufReader<R>, buf: &mut [u16]) -> Result<(), DecodeErrors>
where
R: Read,
{
let mut reader = reader;
for i in buf
{
*i = read_u16_be(&mut reader)?;
}
Ok(())
}