cargo_memex/jpeg/decoder/
upsampler.rs

1use super::*;
2use parser::Component;
3
4pub struct Upsampler {
5    components: Vec<UpsamplerComponent>,
6    line_buffer_size: usize,
7}
8
9struct UpsamplerComponent {
10    upsampler: Box<dyn Upsample + Sync>,
11    width: usize,
12    height: usize,
13    row_stride: usize,
14}
15
16impl Upsampler {
17    pub fn new(
18        components: &[Component],
19        output_width: u16,
20        output_height: u16,
21    ) -> error::Result<Upsampler> {
22        let h_max = components
23            .iter()
24            .map(|c| c.horizontal_sampling_factor)
25            .max()
26            .unwrap();
27        let v_max = components
28            .iter()
29            .map(|c| c.vertical_sampling_factor)
30            .max()
31            .unwrap();
32        let mut upsampler_components = Vec::with_capacity(components.len());
33
34        for component in components {
35            let upsampler = choose_upsampler(
36                (
37                    component.horizontal_sampling_factor,
38                    component.vertical_sampling_factor,
39                ),
40                (h_max, v_max),
41                output_width,
42                output_height,
43            )?;
44            upsampler_components.push(UpsamplerComponent {
45                upsampler: upsampler,
46                width: component.size.width as usize,
47                height: component.size.height as usize,
48                row_stride: component.block_size.width as usize * component.dct_scale,
49            });
50        }
51
52        let buffer_size =
53            components.iter().map(|c| c.size.width).max().unwrap() as usize * h_max as usize;
54
55        Ok(Upsampler {
56            components: upsampler_components,
57            line_buffer_size: buffer_size,
58        })
59    }
60
61    pub fn upsample_and_interleave_row(
62        &self,
63        component_data: &[Vec<u8>],
64        row: usize,
65        output_width: usize,
66        output: &mut [u8],
67    ) {
68        let component_count = component_data.len();
69        let mut line_buffer = vec![0u8; self.line_buffer_size];
70
71        debug_assert_eq!(component_count, self.components.len());
72
73        for (i, component) in self.components.iter().enumerate() {
74            component.upsampler.upsample_row(
75                &component_data[i],
76                component.width,
77                component.height,
78                component.row_stride,
79                row,
80                output_width,
81                &mut line_buffer,
82            );
83            for x in 0..output_width {
84                output[x * component_count + i] = line_buffer[x];
85            }
86        }
87    }
88}
89
90struct UpsamplerH1V1;
91struct UpsamplerH2V1;
92struct UpsamplerH1V2;
93struct UpsamplerH2V2;
94
95struct UpsamplerGeneric {
96    horizontal_scaling_factor: u8,
97    vertical_scaling_factor: u8,
98}
99
100fn choose_upsampler(
101    sampling_factors: (u8, u8),
102    max_sampling_factors: (u8, u8),
103    output_width: u16,
104    output_height: u16,
105) -> error::Result<Box<dyn Upsample + Sync>> {
106    let h1 = sampling_factors.0 == max_sampling_factors.0 || output_width == 1;
107    let v1 = sampling_factors.1 == max_sampling_factors.1 || output_height == 1;
108    let h2 = sampling_factors.0 * 2 == max_sampling_factors.0;
109    let v2 = sampling_factors.1 * 2 == max_sampling_factors.1;
110
111    if h1 && v1 {
112        Ok(Box::new(UpsamplerH1V1))
113    } else if h2 && v1 {
114        Ok(Box::new(UpsamplerH2V1))
115    } else if h1 && v2 {
116        Ok(Box::new(UpsamplerH1V2))
117    } else if h2 && v2 {
118        Ok(Box::new(UpsamplerH2V2))
119    } else {
120        if max_sampling_factors.0 % sampling_factors.0 != 0
121            || max_sampling_factors.1 % sampling_factors.1 != 0
122        {
123            Err(Error::Unsupported(
124                UnsupportedFeature::NonIntegerSubsamplingRatio,
125            ))
126        } else {
127            Ok(Box::new(UpsamplerGeneric {
128                horizontal_scaling_factor: max_sampling_factors.0 / sampling_factors.0,
129                vertical_scaling_factor: max_sampling_factors.1 / sampling_factors.1,
130            }))
131        }
132    }
133}
134
135trait Upsample {
136    fn upsample_row(
137        &self,
138        input: &[u8],
139        input_width: usize,
140        input_height: usize,
141        row_stride: usize,
142        row: usize,
143        output_width: usize,
144        output: &mut [u8],
145    );
146}
147
148impl Upsample for UpsamplerH1V1 {
149    fn upsample_row(
150        &self,
151        input: &[u8],
152        _input_width: usize,
153        _input_height: usize,
154        row_stride: usize,
155        row: usize,
156        output_width: usize,
157        output: &mut [u8],
158    ) {
159        let input = &input[row * row_stride..];
160
161        output[..output_width].copy_from_slice(&input[..output_width]);
162    }
163}
164
165impl Upsample for UpsamplerH2V1 {
166    fn upsample_row(
167        &self,
168        input: &[u8],
169        input_width: usize,
170        _input_height: usize,
171        row_stride: usize,
172        row: usize,
173        _output_width: usize,
174        output: &mut [u8],
175    ) {
176        let input = &input[row * row_stride..];
177
178        if input_width == 1 {
179            output[0] = input[0];
180            output[1] = input[0];
181            return;
182        }
183
184        output[0] = input[0];
185        output[1] = ((input[0] as u32 * 3 + input[1] as u32 + 2) >> 2) as u8;
186
187        for i in 1..input_width - 1 {
188            let sample = 3 * input[i] as u32 + 2;
189            output[i * 2] = ((sample + input[i - 1] as u32) >> 2) as u8;
190            output[i * 2 + 1] = ((sample + input[i + 1] as u32) >> 2) as u8;
191        }
192
193        output[(input_width - 1) * 2] =
194            ((input[input_width - 1] as u32 * 3 + input[input_width - 2] as u32 + 2) >> 2) as u8;
195        output[(input_width - 1) * 2 + 1] = input[input_width - 1];
196    }
197}
198
199impl Upsample for UpsamplerH1V2 {
200    fn upsample_row(
201        &self,
202        input: &[u8],
203        _input_width: usize,
204        input_height: usize,
205        row_stride: usize,
206        row: usize,
207        output_width: usize,
208        output: &mut [u8],
209    ) {
210        let row_near = row as f32 / 2.0;
211        // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we
212        // want it to be the next row.
213        let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32);
214
215        let input_near = &input[row_near as usize * row_stride..];
216        let input_far = &input[row_far as usize * row_stride..];
217
218        for i in 0..output_width {
219            output[i] = ((3 * input_near[i] as u32 + input_far[i] as u32 + 2) >> 2) as u8;
220        }
221    }
222}
223
224impl Upsample for UpsamplerH2V2 {
225    fn upsample_row(
226        &self,
227        input: &[u8],
228        input_width: usize,
229        input_height: usize,
230        row_stride: usize,
231        row: usize,
232        _output_width: usize,
233        output: &mut [u8],
234    ) {
235        let row_near = row as f32 / 2.0;
236        // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we
237        // want it to be the next row.
238        let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32);
239
240        let input_near = &input[row_near as usize * row_stride..];
241        let input_far = &input[row_far as usize * row_stride..];
242
243        if input_width == 1 {
244            let value = ((3 * input_near[0] as u32 + input_far[0] as u32 + 2) >> 2) as u8;
245            output[0] = value;
246            output[1] = value;
247            return;
248        }
249
250        let mut t1 = 3 * input_near[0] as u32 + input_far[0] as u32;
251        output[0] = ((t1 + 2) >> 2) as u8;
252
253        for i in 1..input_width {
254            let t0 = t1;
255            t1 = 3 * input_near[i] as u32 + input_far[i] as u32;
256
257            output[i * 2 - 1] = ((3 * t0 + t1 + 8) >> 4) as u8;
258            output[i * 2] = ((3 * t1 + t0 + 8) >> 4) as u8;
259        }
260
261        output[input_width * 2 - 1] = ((t1 + 2) >> 2) as u8;
262    }
263}
264
265impl Upsample for UpsamplerGeneric {
266    // Uses nearest neighbor sampling
267    fn upsample_row(
268        &self,
269        input: &[u8],
270        input_width: usize,
271        _input_height: usize,
272        row_stride: usize,
273        row: usize,
274        _output_width: usize,
275        output: &mut [u8],
276    ) {
277        let mut index = 0;
278        let start = (row / self.vertical_scaling_factor as usize) * row_stride;
279        let input = &input[start..(start + input_width)];
280        for val in input {
281            for _ in 0..self.horizontal_scaling_factor {
282                output[index] = *val;
283                index += 1;
284            }
285        }
286    }
287}