]>
Commit | Line | Data |
---|---|---|
03accf76 KS |
1 | use crate::formats::*; |
2 | use super::*; | |
3 | use super::kernel::Kernel; | |
4 | ||
5 | fn convert_depth(val: u32, indepth: u8, outdepth: u8) -> u32 { | |
6 | if indepth >= outdepth { | |
7 | val >> (indepth - outdepth) | |
8 | } else { | |
9 | let mut val2 = val << (outdepth - indepth); | |
10 | let mut shift = outdepth - indepth; | |
11 | while shift >= indepth { | |
12 | shift -= indepth; | |
13 | val2 |= val << shift; | |
14 | } | |
15 | if shift > 0 { | |
16 | val2 |= val >> (indepth - shift); | |
17 | } | |
18 | val2 | |
19 | } | |
20 | } | |
21 | ||
22 | #[derive(Default)] | |
23 | struct PackKernel { | |
24 | shifts: [u8; MAX_CHROMATONS], | |
25 | depths: [u8; MAX_CHROMATONS], | |
26 | ncomps: usize, | |
27 | osize: [u8; MAX_CHROMATONS], | |
28 | ooff: [usize; MAX_CHROMATONS], | |
29 | } | |
30 | ||
31 | impl PackKernel { | |
32 | fn new() -> Self { Self::default() } | |
33 | } | |
34 | ||
35 | impl Kernel for PackKernel { | |
25e0bf9a | 36 | fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, _options: &[(String, String)]) -> ScaleResult<NABufferType> { |
4997179d | 37 | self.ncomps = in_fmt.fmt.components.min(dest_fmt.fmt.components) as usize; |
03accf76 KS |
38 | for i in 0..self.ncomps { |
39 | let ichr = in_fmt.fmt.comp_info[i].unwrap(); | |
40 | let ochr = dest_fmt.fmt.comp_info[i].unwrap(); | |
41 | self.shifts[i] = ochr.shift; | |
42 | self.osize[i] = ochr.depth; | |
43 | self.depths[i] = ichr.depth; | |
44 | self.ooff[i] = ochr.comp_offs as usize; | |
45 | } | |
46 | let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, dest_fmt.fmt), 3); | |
47 | if res.is_err() { return Err(ScaleError::AllocError); } | |
48 | Ok(res.unwrap()) | |
49 | } | |
50 | fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) { | |
51 | if let Some(ref buf) = pic_in.get_vbuf() { | |
52 | if let Some(ref mut dbuf) = pic_out.get_vbuf() { | |
53 | let dstride = dbuf.get_stride(0); | |
54 | for comp in 0..self.ncomps { | |
55 | let ioff = buf.get_offset(comp); | |
56 | let istride = buf.get_stride(comp); | |
57 | let step = dbuf.get_info().get_format().get_chromaton(comp).unwrap().get_step() as usize; | |
58 | let (w, h) = dbuf.get_dimensions(comp); | |
59 | let sdata = buf.get_data(); | |
60 | let sdata = &sdata[ioff..]; | |
61 | let ddata = dbuf.get_data_mut().unwrap(); | |
62 | for (src, dst) in sdata.chunks(istride).zip(ddata.chunks_mut(dstride)).take(h) { | |
63 | for x in 0..w { | |
e243ceb4 | 64 | dst[x * step + self.ooff[comp]] = convert_depth(u32::from(src[x]), self.depths[comp], self.osize[comp]) as u8; |
03accf76 KS |
65 | } |
66 | } | |
67 | } | |
68 | } else if let Some(ref mut dbuf) = pic_out.get_vbuf16() { | |
69 | let (w, h) = dbuf.get_dimensions(0); | |
70 | let dstride = dbuf.get_stride(0); | |
71 | let ddata = dbuf.get_data_mut().unwrap(); | |
72 | let src = buf.get_data(); | |
73 | let mut ioff: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
74 | let mut istride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
75 | for comp in 0..self.ncomps { | |
76 | ioff[comp] = buf.get_offset(comp); | |
77 | istride[comp] = buf.get_stride(comp); | |
78 | } | |
79 | for dst in ddata.chunks_mut(dstride).take(h) { | |
80 | for x in 0..w { | |
81 | let mut elem: u32 = 0; | |
82 | for comp in 0..self.ncomps { | |
e243ceb4 | 83 | let c = u32::from(src[ioff[comp] + x]); |
03accf76 KS |
84 | elem |= convert_depth(c, self.depths[comp], self.osize[comp]) << self.shifts[comp]; |
85 | } | |
86 | dst[x] = elem as u16; | |
87 | } | |
88 | for comp in 0..self.ncomps { | |
89 | ioff[comp] += istride[comp]; | |
90 | } | |
91 | } | |
92 | } else { | |
93 | unimplemented!(); | |
94 | } | |
95 | } else if let Some(ref _buf) = pic_in.get_vbuf16() { | |
96 | unimplemented!(); | |
97 | } else if let Some(ref _buf) = pic_in.get_vbuf32() { | |
98 | unimplemented!(); | |
99 | } else { | |
100 | unreachable!(); | |
101 | } | |
102 | } | |
103 | } | |
104 | ||
6011e201 | 105 | pub fn create_pack() -> Box<dyn Kernel> { |
03accf76 KS |
106 | Box::new(PackKernel::new()) |
107 | } | |
108 | ||
109 | #[derive(Default)] | |
110 | struct UnpackKernel { | |
111 | shifts: [u8; MAX_CHROMATONS], | |
112 | masks: [u32; MAX_CHROMATONS], | |
113 | depths: [u8; MAX_CHROMATONS], | |
114 | ncomps: usize, | |
115 | osize: [u8; MAX_CHROMATONS], | |
116 | } | |
117 | ||
118 | impl UnpackKernel { | |
119 | fn new() -> Self { Self::default() } | |
120 | } | |
121 | ||
122 | impl Kernel for UnpackKernel { | |
25e0bf9a KS |
123 | fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, options: &[(String, String)]) -> ScaleResult<NABufferType> { |
124 | let mut debug = false; | |
125 | for (name, value) in options.iter() { | |
126 | match (name.as_str(), value.as_str()) { | |
127 | ("debug", "") => { debug = true; }, | |
128 | ("debug", "true") => { debug = true; }, | |
129 | _ => {}, | |
130 | } | |
131 | } | |
132 | ||
4997179d | 133 | self.ncomps = in_fmt.fmt.components.min(dest_fmt.fmt.components) as usize; |
03accf76 KS |
134 | let mut chr: Vec<Option<NAPixelChromaton>> = Vec::with_capacity(MAX_CHROMATONS); |
135 | for i in 0..self.ncomps { | |
136 | let ichr = in_fmt.fmt.comp_info[i].unwrap(); | |
137 | let ochr = dest_fmt.fmt.comp_info[i].unwrap(); | |
138 | self.shifts[i] = ichr.shift; | |
139 | self.masks[i] = (1 << ichr.depth) - 1; | |
140 | if ochr.depth > ichr.depth { | |
141 | self.osize[i] = ochr.depth; | |
142 | } else { | |
143 | self.osize[i] = (ichr.depth + 7) & !7; | |
144 | } | |
145 | self.depths[i] = ichr.depth; | |
146 | let mut dchr = ichr; | |
147 | dchr.packed = false; | |
148 | dchr.depth = self.osize[i]; | |
149 | dchr.shift = 0; | |
150 | dchr.comp_offs = 0; | |
151 | dchr.next_elem = 0; | |
152 | chr.push(Some(dchr)); | |
153 | } | |
154 | let mut df = in_fmt.fmt; | |
b36f412c | 155 | df.comp_info[..self.ncomps].clone_from_slice(&chr[..self.ncomps]); |
4997179d | 156 | df.components = self.ncomps as u8; |
4b459d0b | 157 | df.palette = false; |
25e0bf9a KS |
158 | if debug { |
159 | println!(" [intermediate format {}]", df); | |
160 | } | |
03accf76 KS |
161 | let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3); |
162 | if res.is_err() { return Err(ScaleError::AllocError); } | |
163 | Ok(res.unwrap()) | |
164 | } | |
165 | fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) { | |
166 | if let Some(ref buf) = pic_in.get_vbuf() { | |
871c9432 | 167 | let step = buf.get_info().get_format().elem_size as usize; |
03accf76 KS |
168 | let mut soff: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; |
169 | for i in 0..self.ncomps { | |
170 | soff[i] = buf.get_info().get_format().get_chromaton(i).unwrap().get_offset() as usize; | |
171 | } | |
172 | let (w, h) = buf.get_dimensions(0); | |
173 | let ioff = buf.get_offset(0); | |
174 | let istride = buf.get_stride(0); | |
175 | let sdata1 = buf.get_data(); | |
176 | let sdata = &sdata1[ioff..]; | |
871c9432 | 177 | let ychr = buf.get_info().get_format().get_chromaton(0).unwrap(); |
03accf76 KS |
178 | if let Some(ref mut dbuf) = pic_out.get_vbuf() { |
179 | let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
180 | let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
181 | for i in 0..self.ncomps { | |
182 | ostride[i] = dbuf.get_stride(i); | |
183 | offs[i] = dbuf.get_offset(i); | |
184 | } | |
185 | let dst = dbuf.get_data_mut().unwrap(); | |
871c9432 KS |
186 | if ychr.next_elem == 0 || usize::from(ychr.next_elem) == step { |
187 | for src in sdata.chunks(istride).take(h) { | |
188 | for x in 0..w { | |
189 | for i in 0..self.ncomps { | |
190 | dst[offs[i] + x] = src[x * step + soff[i]]; | |
191 | } | |
192 | } | |
193 | for i in 0..self.ncomps { offs[i] += ostride[i]; } | |
194 | } | |
195 | } else { | |
196 | let mut steps: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
197 | for i in 0..self.ncomps { | |
198 | steps[i] = buf.get_info().get_format().get_chromaton(i).unwrap().next_elem as usize; | |
199 | } | |
200 | ||
201 | for src in sdata.chunks(istride).take(h) { | |
202 | let mut x = offs; | |
203 | for piece in src.chunks(step) { | |
204 | for i in 0..self.ncomps { | |
205 | let mut co = soff[i]; | |
206 | while co < step { | |
207 | dst[x[i]] = piece[co]; | |
208 | x[i] += 1; | |
209 | co += steps[i]; | |
210 | } | |
211 | } | |
03accf76 | 212 | } |
871c9432 | 213 | for i in 0..self.ncomps { offs[i] += ostride[i]; } |
03accf76 | 214 | } |
03accf76 KS |
215 | } |
216 | } else { | |
217 | unimplemented!(); | |
218 | } | |
219 | } else if let Some(ref buf) = pic_in.get_vbuf16() { | |
220 | let (w, h) = buf.get_dimensions(0); | |
221 | let ioff = buf.get_offset(0); | |
222 | let istride = buf.get_stride(0); | |
223 | let sdata1 = buf.get_data(); | |
224 | let sdata = &sdata1[ioff..]; | |
225 | if let Some(ref mut dbuf) = pic_out.get_vbuf() { | |
226 | let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
227 | let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
228 | for i in 0..self.ncomps { | |
229 | ostride[i] = dbuf.get_stride(i); | |
230 | offs[i] = dbuf.get_offset(i); | |
231 | } | |
232 | let dst = dbuf.get_data_mut().unwrap(); | |
233 | for src in sdata.chunks(istride).take(h) { | |
234 | for x in 0..w { | |
e243ceb4 | 235 | let elem = u32::from(src[x]); |
03accf76 KS |
236 | for i in 0..self.ncomps { |
237 | dst[offs[i] + x] = convert_depth((elem >> self.shifts[i]) & self.masks[i], self.depths[i], self.osize[i]) as u8; | |
238 | } | |
239 | } | |
240 | for i in 0..self.ncomps { offs[i] += ostride[i]; } | |
241 | } | |
242 | } else { | |
243 | unimplemented!(); | |
244 | } | |
245 | } else if let Some(ref _buf) = pic_in.get_vbuf32() { | |
246 | unimplemented!(); | |
247 | } else { | |
248 | unreachable!(); | |
249 | } | |
250 | } | |
251 | } | |
252 | ||
6011e201 | 253 | pub fn create_unpack() -> Box<dyn Kernel> { |
03accf76 KS |
254 | Box::new(UnpackKernel::new()) |
255 | } | |
256 | ||
257 | #[derive(Default)] | |
258 | struct DepalKernel { | |
259 | depths: [u8; MAX_CHROMATONS], | |
260 | coffs: [usize; MAX_CHROMATONS], | |
261 | ncomps: usize, | |
262 | palstep: usize, | |
263 | } | |
264 | ||
265 | impl DepalKernel { | |
266 | fn new() -> Self { Self::default() } | |
267 | } | |
268 | ||
269 | impl Kernel for DepalKernel { | |
25e0bf9a KS |
270 | fn init(&mut self, in_fmt: &ScaleInfo, _dest_fmt: &ScaleInfo, options: &[(String, String)]) -> ScaleResult<NABufferType> { |
271 | let mut debug = false; | |
272 | for (name, value) in options.iter() { | |
273 | match (name.as_str(), value.as_str()) { | |
274 | ("debug", "") => { debug = true; }, | |
275 | ("debug", "true") => { debug = true; }, | |
276 | _ => {}, | |
277 | } | |
278 | } | |
279 | ||
03accf76 KS |
280 | //todo select output more fitting for dest_fmt if possible |
281 | self.ncomps = in_fmt.fmt.components as usize; | |
282 | let mut chr: Vec<Option<NAPixelChromaton>> = Vec::with_capacity(MAX_CHROMATONS); | |
283 | self.palstep = in_fmt.fmt.elem_size as usize; | |
284 | for i in 0..self.ncomps { | |
285 | let ichr = in_fmt.fmt.comp_info[i].unwrap(); | |
286 | self.coffs[i] = ichr.comp_offs as usize; | |
287 | self.depths[i] = ichr.depth; | |
288 | let mut dchr = ichr; | |
289 | dchr.packed = false; | |
290 | dchr.depth = 8; | |
291 | dchr.shift = 0; | |
292 | dchr.comp_offs = i as u8; | |
293 | dchr.next_elem = 0; | |
294 | chr.push(Some(dchr)); | |
295 | } | |
296 | let mut df = in_fmt.fmt; | |
297 | df.palette = false; | |
b36f412c | 298 | df.comp_info[..self.ncomps].clone_from_slice(&chr[..self.ncomps]); |
25e0bf9a KS |
299 | if debug { |
300 | println!(" [intermediate format {}]", df); | |
301 | } | |
03accf76 KS |
302 | let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3); |
303 | if res.is_err() { return Err(ScaleError::AllocError); } | |
304 | Ok(res.unwrap()) | |
305 | } | |
306 | fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) { | |
307 | if let (Some(ref sbuf), Some(ref mut dbuf)) = (pic_in.get_vbuf(), pic_out.get_vbuf()) { | |
308 | let ioff = sbuf.get_offset(0); | |
309 | let paloff = sbuf.get_offset(1); | |
310 | let (w, h) = sbuf.get_dimensions(0); | |
311 | let istride = sbuf.get_stride(0); | |
312 | let sdata1 = sbuf.get_data(); | |
313 | let sdata = &sdata1[ioff..]; | |
314 | let pal = &sdata1[paloff..]; | |
315 | ||
316 | let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
317 | let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS]; | |
318 | for i in 0..self.ncomps { | |
319 | ostride[i] = dbuf.get_stride(i); | |
320 | offs[i] = dbuf.get_offset(i); | |
321 | } | |
322 | let dst = dbuf.get_data_mut().unwrap(); | |
323 | for src in sdata.chunks(istride).take(h) { | |
324 | for x in 0..w { | |
325 | let palidx = src[x] as usize; | |
326 | for i in 0..self.ncomps { | |
e243ceb4 | 327 | let elem = u32::from(pal[palidx * self.palstep + self.coffs[i]]); |
03accf76 KS |
328 | dst[offs[i] + x] = convert_depth(elem, self.depths[i], 8) as u8; |
329 | } | |
330 | } | |
331 | for i in 0..self.ncomps { offs[i] += ostride[i]; } | |
332 | } | |
333 | } else { | |
334 | unreachable!(); | |
335 | } | |
336 | } | |
337 | } | |
338 | ||
6011e201 | 339 | pub fn create_depal() -> Box<dyn Kernel> { |
03accf76 KS |
340 | Box::new(DepalKernel::new()) |
341 | } |