zune_jpeg/color_convert/
scalar.rs1use core::convert::TryInto;
10
11pub(crate) const Y_CF: i16 = 16384;
16pub(crate) const CR_CF: i16 = 22970;
17pub(crate) const CB_CF: i16 = 29032;
18pub(crate) const C_G_CR_COEF_1: i16 = -11700;
19pub(crate) const C_G_CB_COEF_2: i16 = -5638;
20pub(crate) const YUV_PREC: i16 = 14;
21pub(crate) const YUV_RND: i16 = (1 << (YUV_PREC - 1)) - 1;
23
24#[inline]
26#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss, dead_code)]
27fn clamp(a: i32) -> u8 {
28 a.clamp(0, 255) as u8
29}
30
31pub fn ycbcr_to_rgba_inner_16_scalar<const BGRA: bool>(
39 y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], output: &mut [u8], pos: &mut usize
40) {
41 let (_, output_position) = output.split_at_mut(*pos);
42
43 let opt: &mut [u8; 64] = output_position
45 .get_mut(0..64)
46 .expect("Slice to small cannot write")
47 .try_into()
48 .unwrap();
49 for ((&y, (cb, cr)), out) in y
50 .iter()
51 .zip(cb.iter().zip(cr.iter()))
52 .zip(opt.chunks_exact_mut(4))
53 {
54 let cr = cr - 128;
55 let cb = cb - 128;
56
57 let y0 = i32::from(y) * i32::from(Y_CF) + i32::from(YUV_RND);
58
59 let r = (y0 + i32::from(cr) * i32::from(CR_CF)) >> YUV_PREC;
60 let g = (y0
61 + i32::from(cr) * i32::from(C_G_CR_COEF_1)
62 + i32::from(cb) * i32::from(C_G_CB_COEF_2))
63 >> YUV_PREC;
64 let b = (y0 + i32::from(cb) * i32::from(CB_CF)) >> YUV_PREC;
65
66 if BGRA {
67 out[0] = clamp(b);
68 out[1] = clamp(g);
69 out[2] = clamp(r);
70 out[3] = 255;
71 } else {
72 out[0] = clamp(r);
73 out[1] = clamp(g);
74 out[2] = clamp(b);
75 out[3] = 255;
76 }
77 }
78 *pos += 64;
79}
80
81pub fn ycbcr_to_rgb_inner_16_scalar<const BGRA: bool>(
87 y: &[i16; 16], cb: &[i16; 16], cr: &[i16; 16], output: &mut [u8], pos: &mut usize
88) {
89 let (_, output_position) = output.split_at_mut(*pos);
90
91 let opt: &mut [u8; 48] = output_position
93 .get_mut(0..48)
94 .expect("Slice to small cannot write")
95 .try_into()
96 .unwrap();
97
98 for ((&y, (cb, cr)), out) in y
99 .iter()
100 .zip(cb.iter().zip(cr.iter()))
101 .zip(opt.chunks_exact_mut(3))
102 {
103 let cr = cr - 128;
104 let cb = cb - 128;
105
106 let y0 = i32::from(y) * i32::from(Y_CF) + i32::from(YUV_RND);
107
108 let r = (y0 + i32::from(cr) * i32::from(CR_CF)) >> YUV_PREC;
109 let g = (y0
110 + i32::from(cr) * i32::from(C_G_CR_COEF_1)
111 + i32::from(cb) * i32::from(C_G_CB_COEF_2))
112 >> YUV_PREC;
113 let b = (y0 + i32::from(cb) * i32::from(CB_CF)) >> YUV_PREC;
114
115 if BGRA {
116 out[0] = clamp(b);
117 out[1] = clamp(g);
118 out[2] = clamp(r);
119 } else {
120 out[0] = clamp(r);
121 out[1] = clamp(g);
122 out[2] = clamp(b);
123 }
124 }
125
126 *pos += 48;
128}
129
130pub fn ycbcr_to_grayscale(y: &[i16], width: usize, padded_width: usize, output: &mut [u8]) {
131 for (y_in, out) in y
132 .chunks_exact(padded_width)
133 .zip(output.chunks_exact_mut(width))
134 {
135 for (y, out) in y_in.iter().zip(out.iter_mut()) {
136 *out = *y as u8;
137 }
138 }
139}