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         for i in 0 .. output_width {
132             output[i] = input[i];
133         }
134     }
135 }
136 
137 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])138     fn upsample_row(&self,
139                     input: &[u8],
140                     input_width: usize,
141                     _input_height: usize,
142                     row_stride: usize,
143                     row: usize,
144                     _output_width: usize,
145                     output: &mut [u8]) {
146         let input = &input[row * row_stride ..];
147 
148         if input_width == 1 {
149             output[0] = input[0];
150             output[1] = input[0];
151             return;
152         }
153 
154         output[0] = input[0];
155         output[1] = ((input[0] as u32 * 3 + input[1] as u32 + 2) >> 2) as u8;
156 
157         for i in 1 .. input_width - 1 {
158             let sample = 3 * input[i] as u32 + 2;
159             output[i * 2]     = ((sample + input[i - 1] as u32) >> 2) as u8;
160             output[i * 2 + 1] = ((sample + input[i + 1] as u32) >> 2) as u8;
161         }
162 
163         output[(input_width - 1) * 2] = ((input[input_width - 1] as u32 * 3 + input[input_width - 2] as u32 + 2) >> 2) as u8;
164         output[(input_width - 1) * 2 + 1] = input[input_width - 1];
165     }
166 }
167 
168 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])169     fn upsample_row(&self,
170                     input: &[u8],
171                     _input_width: usize,
172                     input_height: usize,
173                     row_stride: usize,
174                     row: usize,
175                     output_width: usize,
176                     output: &mut [u8]) {
177         let row_near = row as f32 / 2.0;
178         // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we
179         // want it to be the next row.
180         let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32);
181 
182         let input_near = &input[row_near as usize * row_stride ..];
183         let input_far = &input[row_far as usize * row_stride ..];
184 
185         for i in 0 .. output_width {
186             output[i] = ((3 * input_near[i] as u32 + input_far[i] as u32 + 2) >> 2) as u8;
187         }
188     }
189 }
190 
191 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])192     fn upsample_row(&self,
193                     input: &[u8],
194                     input_width: usize,
195                     input_height: usize,
196                     row_stride: usize,
197                     row: usize,
198                     _output_width: usize,
199                     output: &mut [u8]) {
200         let row_near = row as f32 / 2.0;
201         // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we
202         // want it to be the next row.
203         let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32);
204 
205         let input_near = &input[row_near as usize * row_stride ..];
206         let input_far = &input[row_far as usize * row_stride ..];
207 
208         if input_width == 1 {
209             let value = ((3 * input_near[0] as u32 + input_far[0] as u32 + 2) >> 2) as u8;
210             output[0] = value;
211             output[1] = value;
212             return;
213         }
214 
215         let mut t1 = 3 * input_near[0] as u32 + input_far[0] as u32;
216         output[0] = ((t1 + 2) >> 2) as u8;
217 
218         for i in 1 .. input_width {
219             let t0 = t1;
220             t1 = 3 * input_near[i] as u32 + input_far[i] as u32;
221 
222             output[i * 2 - 1] = ((3 * t0 + t1 + 8) >> 4) as u8;
223             output[i * 2]     = ((3 * t1 + t0 + 8) >> 4) as u8;
224         }
225 
226         output[input_width * 2 - 1] = ((t1 + 2) >> 2) as u8;
227     }
228 }
229 
230 impl Upsample for UpsamplerGeneric {
231     // 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])232     fn upsample_row(&self,
233                     input: &[u8],
234                     input_width: usize,
235                     _input_height: usize,
236                     row_stride: usize,
237                     row: usize,
238                     _output_width: usize,
239                     output: &mut [u8]) {
240         let mut index = 0;
241         let start = (row / self.vertical_scaling_factor as usize) * row_stride;
242         let input = &input[start..(start + input_width)];
243         for val in input {
244             for _ in 0..self.horizontal_scaling_factor {
245                 output[index] = *val;
246                 index += 1;
247             }
248         }
249     }
250 }
251