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