1use alloc::vec::Vec;
15use alloc::{format, vec};
16
17use zune_core::log::trace;
18
19use crate::decoder::MAX_COMPONENTS;
20use crate::errors::DecodeErrors;
21use crate::upsampler::upsample_no_op;
22
23pub type UpSampler = fn(
27    input: &[i16],
28    in_near: &[i16],
29    in_far: &[i16],
30    scratch_space: &mut [i16],
31    output: &mut [i16]
32);
33
34#[derive(Clone)]
36pub(crate) struct Components {
37    pub component_id: ComponentID,
39    pub vertical_sample: usize,
41    pub horizontal_sample: usize,
43    pub dc_huff_table: usize,
45    pub ac_huff_table: usize,
47    pub quantization_table_number: u8,
49    pub quantization_table: [i32; 64],
51    pub dc_pred: i32,
53    pub up_sampler: UpSampler,
56    pub width_stride: usize,
58    pub id: u8,
60    pub needed: bool,
62    pub raw_coeff: Vec<i16>,
64    pub upsample_dest: Vec<i16>,
66    pub row_up: Vec<i16>,
68    pub row: Vec<i16>,
70    pub first_row_upsample_dest: Vec<i16>,
71    pub idct_pos: usize,
72    pub x: usize,
73    pub w2: usize,
74    pub y: usize,
75    pub sample_ratio: SampleRatios,
76    pub fix_an_annoying_bug: usize
78}
79
80impl Components {
81    #[inline]
83    pub fn from(a: [u8; 3], pos: u8) -> Result<Components, DecodeErrors> {
84        let id = match pos {
92            0 => ComponentID::Y,
93            1 => ComponentID::Cb,
94            2 => ComponentID::Cr,
95            3 => ComponentID::Q,
96            _ => {
97                return Err(DecodeErrors::Format(format!(
98                    "Unknown component id found,{pos}, expected value between 1 and 4"
99                )))
100            }
101        };
102
103        let horizontal_sample = (a[1] >> 4) as usize;
104        let vertical_sample = (a[1] & 0x0f) as usize;
105        let quantization_table_number = a[2];
106        if usize::from(quantization_table_number) >= MAX_COMPONENTS {
108            return Err(DecodeErrors::Format(format!(
109                "Too large quantization number :{quantization_table_number}, expected value between 0 and {MAX_COMPONENTS}"
110            )));
111        }
112        if !horizontal_sample.is_power_of_two() {
115            return Err(DecodeErrors::Format(format!(
116                "Horizontal sample is not a power of two({horizontal_sample}) cannot decode"
117            )));
118        }
119
120        if !vertical_sample.is_power_of_two() {
121            return Err(DecodeErrors::Format(format!(
122                "Vertical sub-sample is not power of two({vertical_sample}) cannot decode"
123            )));
124        }
125
126        trace!(
127            "Component ID:{:?} \tHS:{} VS:{} QT:{}",
128            id,
129            horizontal_sample,
130            vertical_sample,
131            quantization_table_number
132        );
133
134        Ok(Components {
135            component_id: id,
136            vertical_sample,
137            horizontal_sample,
138            quantization_table_number,
139            first_row_upsample_dest: vec![],
140            dc_huff_table: 0,
142            ac_huff_table: 0,
143            quantization_table: [0; 64],
144            dc_pred: 0,
145            up_sampler: upsample_no_op,
146            width_stride: horizontal_sample,
148            id: a[0],
149            needed: true,
150            raw_coeff: vec![],
151            upsample_dest: vec![],
152            row_up: vec![],
153            row: vec![],
154            idct_pos: 0,
155            x: 0,
156            y: 0,
157            w2: 0,
158            sample_ratio: SampleRatios::None,
159            fix_an_annoying_bug: 1
160        })
161    }
162    pub fn setup_upsample_scanline(&mut self) {
173        self.row = vec![0; self.width_stride * self.vertical_sample];
174        self.row_up = vec![0; self.width_stride * self.vertical_sample];
175        self.first_row_upsample_dest =
176            vec![128; self.vertical_sample * self.width_stride * self.sample_ratio.sample()];
177        self.upsample_dest =
178            vec![0; self.width_stride * self.sample_ratio.sample() * self.fix_an_annoying_bug * 8];
179    }
180}
181
182#[derive(Copy, Debug, Clone, PartialEq, Eq)]
184pub enum ComponentID {
185    Y,
187    Cb,
189    Cr,
191    Q
193}
194
195#[derive(Copy, Debug, Clone, PartialEq, Eq)]
196pub enum SampleRatios {
197    HV,
198    V,
199    H,
200    Generic(usize, usize),
201    None
202}
203
204impl SampleRatios {
205    pub fn sample(self) -> usize {
206        match self {
207            SampleRatios::HV => 4,
208            SampleRatios::V | SampleRatios::H => 2,
209            SampleRatios::Generic(a, b) => a * b,
210            SampleRatios::None => 1
211        }
212    }
213}