core/scale: add options support
[nihav.git] / nihav-core / src / scale / repack.rs
index 4f2ce999b8f20fcde54da118932072a45aed6e4c..8cdb8ea91b164df63ecb22409fd196bdef12b4cf 100644 (file)
@@ -33,8 +33,8 @@ impl PackKernel {
 }
 
 impl Kernel for PackKernel {
-    fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo) -> ScaleResult<NABufferType> {
-        self.ncomps = in_fmt.fmt.components as usize;
+    fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, _options: &[(String, String)]) -> ScaleResult<NABufferType> {
+        self.ncomps = in_fmt.fmt.components.min(dest_fmt.fmt.components) as usize;
         for i in 0..self.ncomps {
             let ichr = in_fmt.fmt.comp_info[i].unwrap();
             let ochr = dest_fmt.fmt.comp_info[i].unwrap();
@@ -61,7 +61,7 @@ impl Kernel for PackKernel {
                     let ddata = dbuf.get_data_mut().unwrap();
                     for (src, dst) in sdata.chunks(istride).zip(ddata.chunks_mut(dstride)).take(h) {
                         for x in 0..w {
-                            dst[x * step + self.ooff[comp]] = convert_depth(src[x] as u32, self.depths[comp], self.osize[comp]) as u8;
+                            dst[x * step + self.ooff[comp]] = convert_depth(u32::from(src[x]), self.depths[comp], self.osize[comp]) as u8;
                         }
                     }
                 }
@@ -80,7 +80,7 @@ impl Kernel for PackKernel {
                     for x in 0..w {
                         let mut elem: u32 = 0;
                         for comp in 0..self.ncomps {
-                            let c = src[ioff[comp] + x] as u32;
+                            let c = u32::from(src[ioff[comp] + x]);
                             elem |= convert_depth(c, self.depths[comp], self.osize[comp]) << self.shifts[comp];
                         }
                         dst[x] = elem as u16;
@@ -102,7 +102,7 @@ unimplemented!();
     }
 }
 
-pub fn create_pack() -> Box<Kernel> {
+pub fn create_pack() -> Box<dyn Kernel> {
     Box::new(PackKernel::new())
 }
 
@@ -120,8 +120,17 @@ impl UnpackKernel {
 }
 
 impl Kernel for UnpackKernel {
-    fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo) -> ScaleResult<NABufferType> {
-        self.ncomps = in_fmt.fmt.components as usize;
+    fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, options: &[(String, String)]) -> ScaleResult<NABufferType> {
+        let mut debug = false;
+        for (name, value) in options.iter() {
+            match (name.as_str(), value.as_str()) {
+                ("debug", "")     => { debug = true; },
+                ("debug", "true") => { debug = true; },
+                _ => {},
+            }
+        }
+
+        self.ncomps = in_fmt.fmt.components.min(dest_fmt.fmt.components) as usize;
         let mut chr: Vec<Option<NAPixelChromaton>> = Vec::with_capacity(MAX_CHROMATONS);
         for i in 0..self.ncomps {
             let ichr = in_fmt.fmt.comp_info[i].unwrap();
@@ -143,17 +152,19 @@ impl Kernel for UnpackKernel {
             chr.push(Some(dchr));
         }
         let mut df = in_fmt.fmt;
-        for i in 0..self.ncomps {
-            df.comp_info[i] = chr[i];
+        df.comp_info[..self.ncomps].clone_from_slice(&chr[..self.ncomps]);
+        df.components = self.ncomps as u8;
+        df.palette = false;
+        if debug {
+            println!(" [intermediate format {}]", df);
         }
-println!(" [intermediate format {}]", df);
         let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3);
         if res.is_err() { return Err(ScaleError::AllocError); }
         Ok(res.unwrap())
     }
     fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) {
         if let Some(ref buf) = pic_in.get_vbuf() {
-            let step = buf.get_info().get_format().get_chromaton(0).unwrap().get_step() as usize;
+            let step = buf.get_info().get_format().elem_size as usize;
             let mut soff: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
             for i in 0..self.ncomps {
                 soff[i] = buf.get_info().get_format().get_chromaton(i).unwrap().get_offset() as usize;
@@ -163,6 +174,7 @@ println!(" [intermediate format {}]", df);
             let istride = buf.get_stride(0);
             let sdata1 = buf.get_data();
             let sdata = &sdata1[ioff..];
+            let ychr = buf.get_info().get_format().get_chromaton(0).unwrap();
             if let Some(ref mut dbuf) = pic_out.get_vbuf() {
                 let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
                 let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
@@ -171,13 +183,35 @@ println!(" [intermediate format {}]", df);
                     offs[i]    = dbuf.get_offset(i);
                 }
                 let dst = dbuf.get_data_mut().unwrap();
-                for src in sdata.chunks(istride).take(h) {
-                    for x in 0..w {
-                        for i in 0..self.ncomps {
-                            dst[offs[i] + x] = src[x * step + soff[i]];
+                if ychr.next_elem == 0 || usize::from(ychr.next_elem) == step {
+                    for src in sdata.chunks(istride).take(h) {
+                        for x in 0..w {
+                            for i in 0..self.ncomps {
+                                dst[offs[i] + x] = src[x * step + soff[i]];
+                            }
                         }
+                        for i in 0..self.ncomps { offs[i] += ostride[i]; }
+                    }
+                } else {
+                    let mut steps: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
+                    for i in 0..self.ncomps {
+                        steps[i] = buf.get_info().get_format().get_chromaton(i).unwrap().next_elem as usize;
+                    }
+
+                    for src in sdata.chunks(istride).take(h) {
+                        let mut x = offs;
+                        for piece in src.chunks(step) {
+                            for i in 0..self.ncomps {
+                                let mut co = soff[i];
+                                while co < step {
+                                    dst[x[i]] = piece[co];
+                                    x[i] += 1;
+                                    co += steps[i];
+                                }
+                            }
+                        }
+                        for i in 0..self.ncomps { offs[i] += ostride[i]; }
                     }
-                    for i in 0..self.ncomps { offs[i] += ostride[i]; }
                 }
             } else {
 unimplemented!();
@@ -198,7 +232,7 @@ unimplemented!();
                 let dst = dbuf.get_data_mut().unwrap();
                 for src in sdata.chunks(istride).take(h) {
                     for x in 0..w {
-                        let elem = src[x] as u32;
+                        let elem = u32::from(src[x]);
                         for i in 0..self.ncomps {
                             dst[offs[i] + x] = convert_depth((elem >> self.shifts[i]) & self.masks[i], self.depths[i], self.osize[i]) as u8;
                         }
@@ -216,7 +250,7 @@ unimplemented!();
     }
 }
 
-pub fn create_unpack() -> Box<Kernel> {
+pub fn create_unpack() -> Box<dyn Kernel> {
     Box::new(UnpackKernel::new())
 }
 
@@ -233,7 +267,16 @@ impl DepalKernel {
 }
 
 impl Kernel for DepalKernel {
-    fn init(&mut self, in_fmt: &ScaleInfo, _dest_fmt: &ScaleInfo) -> ScaleResult<NABufferType> {
+    fn init(&mut self, in_fmt: &ScaleInfo, _dest_fmt: &ScaleInfo, options: &[(String, String)]) -> ScaleResult<NABufferType> {
+        let mut debug = false;
+        for (name, value) in options.iter() {
+            match (name.as_str(), value.as_str()) {
+                ("debug", "")     => { debug = true; },
+                ("debug", "true") => { debug = true; },
+                _ => {},
+            }
+        }
+
 //todo select output more fitting for dest_fmt if possible
         self.ncomps = in_fmt.fmt.components as usize;
         let mut chr: Vec<Option<NAPixelChromaton>> = Vec::with_capacity(MAX_CHROMATONS);
@@ -252,10 +295,10 @@ impl Kernel for DepalKernel {
         }
         let mut df = in_fmt.fmt;
         df.palette = false;
-        for i in 0..self.ncomps {
-            df.comp_info[i] = chr[i];
+        df.comp_info[..self.ncomps].clone_from_slice(&chr[..self.ncomps]);
+        if debug {
+            println!(" [intermediate format {}]", df);
         }
-println!(" [intermediate format {}]", df);
         let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3);
         if res.is_err() { return Err(ScaleError::AllocError); }
         Ok(res.unwrap())
@@ -281,7 +324,7 @@ println!(" [intermediate format {}]", df);
                 for x in 0..w {
                     let palidx = src[x] as usize;
                     for i in 0..self.ncomps {
-                        let elem = pal[palidx * self.palstep + self.coffs[i]] as u32;
+                        let elem = u32::from(pal[palidx * self.palstep + self.coffs[i]]);
                         dst[offs[i] + x] = convert_depth(elem, self.depths[i], 8) as u8;
                     }
                 }
@@ -293,6 +336,6 @@ println!(" [intermediate format {}]", df);
     }
 }
 
-pub fn create_depal() -> Box<Kernel> {
+pub fn create_depal() -> Box<dyn Kernel> {
     Box::new(DepalKernel::new())
 }