cargo_memex/jpeg/decoder/
upsampler.rs1use 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 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 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 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}