]> git.nihav.org Git - nihav.git/commitdiff
nihav_core/scale: add a stage for high- to 8-bit image conversion master
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 7 Mar 2026 19:44:35 +0000 (20:44 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 7 Mar 2026 19:52:06 +0000 (20:52 +0100)
nihav-core/src/scale/depth.rs [new file with mode: 0644]
nihav-core/src/scale/mod.rs

diff --git a/nihav-core/src/scale/depth.rs b/nihav-core/src/scale/depth.rs
new file mode 100644 (file)
index 0000000..a44e324
--- /dev/null
@@ -0,0 +1,53 @@
+use super::*;
+use super::kernel::Kernel;
+
+#[derive(Default)]
+struct ShallowKernel {
+}
+
+impl ShallowKernel {
+    fn new() -> Self { Self::default() }
+}
+
+impl Kernel for ShallowKernel {
+    fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, _options: &[(String, String)]) -> ScaleResult<NABufferType> {
+        let mut wrk_fmt = in_fmt.fmt;
+        for (comp, tcomp) in wrk_fmt.comp_info.iter_mut().zip(dest_fmt.fmt.comp_info.iter()) {
+            if let (Some(ref mut wcomp), Some(ref tgtcomp)) = (comp, tcomp) {
+                wcomp.depth = tgtcomp.depth;
+            }
+        }
+        let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, wrk_fmt), 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), Some(ref mut dbuf)) = (pic_in.get_vbuf16(), pic_out.get_vbuf()) {
+            let ncomps = buf.get_info().get_format().get_num_comp();
+            for comp in 0..ncomps {
+                let ioff = buf.get_offset(comp);
+                let istride = buf.get_stride(comp);
+                let idepth = buf.get_info().get_format().get_chromaton(comp).unwrap().get_depth();
+                let ddepth = dbuf.get_info().get_format().get_chromaton(comp).unwrap().get_depth();
+                let dshift = idepth - ddepth;
+                let (w, h) = dbuf.get_dimensions(comp);
+                let sdata = buf.get_data();
+                let sdata = &sdata[ioff..];
+                let doff = dbuf.get_offset(comp);
+                let dstride = dbuf.get_stride(comp);
+                let ddata = dbuf.get_data_mut().unwrap();
+                for (sline, dline) in sdata.chunks(istride).zip(ddata[doff..].chunks_mut(dstride)).take(h) {
+                    for (&src, dst) in sline.iter().zip(dline.iter_mut()).take(w) {
+                        *dst = (src >> dshift) as u8;
+                    }
+                }
+            }
+        } else {
+            unimplemented!("shallower not on 16->8");
+        }
+    }
+}
+
+pub fn create_shallow() -> Box<dyn Kernel> {
+    Box::new(ShallowKernel::new())
+}
index 85f7b83274854036aecc65b07513b96d99265d21..4ccdb9e84006ed3376b717b0a8277b8d2a2c5721 100644 (file)
@@ -20,6 +20,7 @@ use crate::frame::*;
 mod kernel;
 
 mod colorcvt;
+mod depth;
 mod fill;
 mod repack;
 #[allow(clippy::module_inception)]
@@ -92,6 +93,7 @@ const KERNELS: &[KernelDesc] = &[
     KernelDesc { name: "depal",         create: repack::create_depal },
     KernelDesc { name: "palette",       create: palette::create_palettise },
     KernelDesc { name: "scale",         create: scale::create_scale },
+    KernelDesc { name: "shallow",       create: depth::create_shallow },
     KernelDesc { name: "fill",          create: fill::create_fill },
     KernelDesc { name: "rgb_to_yuv",    create: colorcvt::create_rgb2yuv },
     KernelDesc { name: "yuv_to_rgb",    create: colorcvt::create_yuv2rgb },
@@ -362,6 +364,16 @@ fn build_pipeline(ifmt: &ScaleInfo, ofmt: &ScaleInfo, just_convert: bool, option
         cur_fmt = new_stage.fmt_out;
         add_stage!(stages, new_stage);
     }
+    let is_in_high_bd = cur_fmt.fmt.get_max_depth() > 8;
+    let is_out_high_bd = ofmt.fmt.get_max_depth() > 8;
+    if is_in_high_bd && !is_out_high_bd {
+        if debug {
+            println!("[adding shallow]");
+        }
+        let new_stage = Stage::new("shallow", &cur_fmt, ofmt, options)?;
+        cur_fmt = new_stage.fmt_out;
+        add_stage!(stages, new_stage);
+    }
     let icomponents = cur_fmt.fmt.components - if cur_fmt.fmt.alpha { 1 } else { 0 };
     let ocomponents = ofmt.fmt.components - if ofmt.fmt.alpha { 1 } else { 0 };
     if !needs_palettise && ((!cur_fmt.fmt.alpha && ofmt.fmt.alpha) || (icomponents < ocomponents)) {