1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| use std::{ fs::File, io::{Read, Seek, SeekFrom}, };
use image::RgbImage;
fn read_ycbcr(filename: &str, capacity: usize) -> Vec<u8> { let mut buf = Vec::with_capacity(capacity); let mut file = File::open(filename).unwrap(); file.seek(SeekFrom::Start(0)).unwrap(); file.read_to_end(&mut buf).unwrap(); buf }
fn write_rgb(filename: &str, buf: Vec<u8>, w: usize, h: usize) { let rgb = RgbImage::from_vec(w as u32, h as u32, buf).unwrap(); rgb.save(filename).unwrap(); }
fn csc( y: impl Iterator<Item = u8>, u: impl Iterator<Item = u8>, v: impl Iterator<Item = u8>, ) -> Vec<u8> { y.zip(u.zip(v)) .flat_map(|(y, (u, v))| { [ (y as f32 + 1.280 * (v as f32 - 128.)) as u8, (y as f32 - 0.215 * (u as f32 - 128.) - 0.380 * (v as f32 - 128.)) as u8, (y as f32 + 2.128 * (u as f32 - 128.)) as u8, ] }) .collect() }
pub fn nv12_to_rgb(nv12: &str, rgb: &str, w: usize, h: usize) { let buf = read_ycbcr(nv12, w * h * 3 / 2); let y = buf[..w * h].iter().copied(); let u = buf[w * h..] .chunks_exact(w) .flat_map(|line| [line, line]) .flatten() .step_by(2) .flat_map(|u| [u, u]) .copied(); let v = buf[w * h..] .chunks_exact(w) .flat_map(|line| [line, line]) .flatten() .skip(1) .step_by(2) .flat_map(|v| [v, v]) .copied();
write_rgb(rgb, csc(y, u, v), w, h); }
pub fn nv16_to_rgb(nv16: &str, rgb: &str, w: usize, h: usize) { let buf = read_ycbcr(nv16, w * h * 2); let y = buf[..w * h].iter().copied(); let u = buf[w * h..].iter().step_by(2).flat_map(|u| [u, u]).copied(); let v = buf[w * h + 1..] .iter() .step_by(2) .flat_map(|v| [v, v]) .copied();
write_rgb(rgb, csc(y, u, v), w, h); }
pub fn yuyv_to_rgb(yuyv: &str, rgb: &str, w: usize, h: usize) { let buf = read_ycbcr(yuyv, w * h * 2); let y = buf.iter().step_by(2).copied(); let u = buf[1..].iter().step_by(4).flat_map(|v| [v, v]).copied(); let v = buf[3..].iter().step_by(4).flat_map(|v| [v, v]).copied();
write_rgb(rgb, csc(y, u, v), w, h); }
fn main() { let (w, h) = (2560, 1440);
nv12_to_rgb("nv12.yuv", "nv12.jpg", w, h); nv16_to_rgb("nv16.yuv", "nv16.jpg", w, h); yuyv_to_rgb("yuyv.yuv", "yuyv.jpg", w, h); }
|