1use crate::yuv_error::{
30 check_chroma_channel, check_interleaved_chroma_channel, check_rgba_destination,
31 check_y8_channel, check_yuv_packed422,
32};
33use crate::yuv_support::YuvChromaSubsampling;
34use crate::YuvError;
35use std::fmt::Debug;
36
37#[derive(Debug)]
38pub enum BufferStoreMut<'a, T: Copy + Debug> {
40 Borrowed(&'a mut [T]),
41 Owned(Vec<T>),
42}
43
44impl<T: Copy + Debug> BufferStoreMut<'_, T> {
45 #[allow(clippy::should_implement_trait)]
46 pub fn borrow(&self) -> &[T] {
47 match self {
48 Self::Borrowed(p_ref) => p_ref,
49 Self::Owned(vec) => vec,
50 }
51 }
52
53 #[allow(clippy::should_implement_trait)]
54 pub fn borrow_mut(&mut self) -> &mut [T] {
55 match self {
56 Self::Borrowed(p_ref) => p_ref,
57 Self::Owned(vec) => vec,
58 }
59 }
60}
61
62#[derive(Debug, Clone)]
63pub struct YuvBiPlanarImage<'a, T>
65where
66 T: Copy + Debug,
67{
68 pub y_plane: &'a [T],
69 pub y_stride: u32,
71 pub uv_plane: &'a [T],
72 pub uv_stride: u32,
74 pub width: u32,
75 pub height: u32,
76}
77
78impl<T> YuvBiPlanarImage<'_, T>
79where
80 T: Copy + Debug,
81{
82 pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
83 check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
84 check_interleaved_chroma_channel(
85 self.uv_plane,
86 self.uv_stride,
87 self.width,
88 self.height,
89 subsampling,
90 )?;
91 Ok(())
92 }
93}
94
95#[derive(Debug)]
96pub struct YuvBiPlanarImageMut<'a, T>
98where
99 T: Copy + Debug,
100{
101 pub y_plane: BufferStoreMut<'a, T>,
102 pub y_stride: u32,
104 pub uv_plane: BufferStoreMut<'a, T>,
105 pub uv_stride: u32,
107 pub width: u32,
108 pub height: u32,
109}
110
111impl<T> YuvBiPlanarImageMut<'_, T>
112where
113 T: Copy + Debug,
114{
115 pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
116 check_y8_channel(
117 self.y_plane.borrow(),
118 self.y_stride,
119 self.width,
120 self.height,
121 )?;
122 check_interleaved_chroma_channel(
123 self.uv_plane.borrow(),
124 self.uv_stride,
125 self.width,
126 self.height,
127 subsampling,
128 )?;
129 Ok(())
130 }
131}
132
133impl<'a, T> YuvBiPlanarImageMut<'a, T>
134where
135 T: Default + Clone + Copy + Debug,
136{
137 pub fn alloc(width: u32, height: u32, subsampling: YuvChromaSubsampling) -> Self {
139 let chroma_width = match subsampling {
140 YuvChromaSubsampling::Yuv420 | YuvChromaSubsampling::Yuv422 => {
141 (width as usize).div_ceil(2) * 2
142 }
143 YuvChromaSubsampling::Yuv444 => width as usize * 2,
144 };
145 let chroma_height = match subsampling {
146 YuvChromaSubsampling::Yuv420 => (height as usize).div_ceil(2),
147 YuvChromaSubsampling::Yuv422 | YuvChromaSubsampling::Yuv444 => height as usize,
148 };
149 let y_target = vec![T::default(); width as usize * height as usize];
150 let chroma_target = vec![T::default(); chroma_width * chroma_height];
151 YuvBiPlanarImageMut {
152 y_plane: BufferStoreMut::Owned(y_target),
153 y_stride: width,
154 uv_plane: BufferStoreMut::Owned(chroma_target),
155 uv_stride: chroma_width as u32,
156 width,
157 height,
158 }
159 }
160
161 pub fn to_fixed(&'a self) -> YuvBiPlanarImage<'a, T> {
162 YuvBiPlanarImage {
163 y_plane: self.y_plane.borrow(),
164 y_stride: self.y_stride,
165 uv_plane: self.uv_plane.borrow(),
166 uv_stride: self.uv_stride,
167 width: self.width,
168 height: self.height,
169 }
170 }
171}
172
173impl<'a, T> YuvBiPlanarImage<'a, T>
174where
175 T: Default + Clone + Copy + Debug,
176{
177 pub fn from_mut(bi_planar_mut: &'a YuvBiPlanarImageMut<T>) -> Self {
178 YuvBiPlanarImage::<'a, T> {
179 y_plane: bi_planar_mut.y_plane.borrow(),
180 y_stride: bi_planar_mut.y_stride,
181 uv_plane: bi_planar_mut.uv_plane.borrow(),
182 uv_stride: bi_planar_mut.uv_stride,
183 width: bi_planar_mut.width,
184 height: bi_planar_mut.height,
185 }
186 }
187}
188
189#[derive(Debug)]
190pub struct YuvGrayImage<'a, T>
192where
193 T: Copy + Debug,
194{
195 pub y_plane: &'a [T],
196 pub y_stride: u32,
198 pub width: u32,
199 pub height: u32,
200}
201
202impl<T> YuvGrayImage<'_, T>
203where
204 T: Copy + Debug,
205{
206 pub fn check_constraints(&self) -> Result<(), YuvError> {
207 check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
208 Ok(())
209 }
210}
211
212#[derive(Debug)]
213pub struct YuvGrayImageMut<'a, T>
215where
216 T: Copy + Debug,
217{
218 pub y_plane: BufferStoreMut<'a, T>,
219 pub y_stride: u32,
221 pub width: u32,
222 pub height: u32,
223}
224
225impl<'a, T> YuvGrayImageMut<'a, T>
226where
227 T: Copy + Debug,
228{
229 pub fn check_constraints(&self) -> Result<(), YuvError> {
230 check_y8_channel(
231 self.y_plane.borrow(),
232 self.y_stride,
233 self.width,
234 self.height,
235 )?;
236 Ok(())
237 }
238
239 pub fn to_fixed(&'a self) -> YuvGrayImage<'a, T> {
240 YuvGrayImage {
241 y_plane: self.y_plane.borrow(),
242 y_stride: self.y_stride,
243 width: self.width,
244 height: self.height,
245 }
246 }
247}
248
249impl<T> YuvGrayImageMut<'_, T>
250where
251 T: Copy + Debug + Clone + Default,
252{
253 pub fn alloc(width: u32, height: u32) -> Self {
255 let y_target = vec![T::default(); width as usize * height as usize];
256 Self {
257 y_plane: BufferStoreMut::Owned(y_target),
258 y_stride: width,
259 width,
260 height,
261 }
262 }
263}
264
265#[derive(Debug)]
266pub struct YuvGrayAlphaImage<'a, T>
268where
269 T: Copy + Debug,
270{
271 pub y_plane: &'a [T],
272 pub y_stride: u32,
274 pub a_plane: &'a [T],
275 pub a_stride: u32,
277 pub width: u32,
278 pub height: u32,
279}
280
281impl<T> YuvGrayAlphaImage<'_, T>
282where
283 T: Copy + Debug,
284{
285 pub fn check_constraints(&self) -> Result<(), YuvError> {
286 check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
287 check_y8_channel(self.a_plane, self.a_stride, self.width, self.height)?;
288 Ok(())
289 }
290}
291
292#[derive(Debug, Clone)]
293pub struct YuvPlanarImage<'a, T>
295where
296 T: Copy + Debug,
297{
298 pub y_plane: &'a [T],
299 pub y_stride: u32,
301 pub u_plane: &'a [T],
302 pub u_stride: u32,
304 pub v_plane: &'a [T],
305 pub v_stride: u32,
307 pub width: u32,
308 pub height: u32,
309}
310
311impl<T> YuvPlanarImage<'_, T>
312where
313 T: Copy + Debug,
314{
315 pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
316 check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
317 check_chroma_channel(
318 self.u_plane,
319 self.u_stride,
320 self.width,
321 self.height,
322 subsampling,
323 )?;
324 check_chroma_channel(
325 self.v_plane,
326 self.v_stride,
327 self.width,
328 self.height,
329 subsampling,
330 )?;
331 Ok(())
332 }
333}
334
335#[derive(Debug)]
336pub struct YuvPlanarImageMut<'a, T>
338where
339 T: Copy + Debug,
340{
341 pub y_plane: BufferStoreMut<'a, T>,
342 pub y_stride: u32,
344 pub u_plane: BufferStoreMut<'a, T>,
345 pub u_stride: u32,
347 pub v_plane: BufferStoreMut<'a, T>,
348 pub v_stride: u32,
350 pub width: u32,
351 pub height: u32,
352}
353
354impl<T> YuvPlanarImageMut<'_, T>
355where
356 T: Copy + Debug,
357{
358 pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
359 check_y8_channel(
360 self.y_plane.borrow(),
361 self.y_stride,
362 self.width,
363 self.height,
364 )?;
365 check_chroma_channel(
366 self.u_plane.borrow(),
367 self.u_stride,
368 self.width,
369 self.height,
370 subsampling,
371 )?;
372 check_chroma_channel(
373 self.v_plane.borrow(),
374 self.v_stride,
375 self.width,
376 self.height,
377 subsampling,
378 )?;
379 Ok(())
380 }
381}
382
383impl<'a, T> YuvPlanarImageMut<'a, T>
384where
385 T: Default + Clone + Copy + Debug,
386{
387 pub fn alloc(width: u32, height: u32, subsampling: YuvChromaSubsampling) -> Self {
389 let chroma_width = match subsampling {
390 YuvChromaSubsampling::Yuv420 | YuvChromaSubsampling::Yuv422 => {
391 (width as usize).div_ceil(2)
392 }
393 YuvChromaSubsampling::Yuv444 => width as usize,
394 };
395 let chroma_height = match subsampling {
396 YuvChromaSubsampling::Yuv420 => (height as usize).div_ceil(2),
397 YuvChromaSubsampling::Yuv422 | YuvChromaSubsampling::Yuv444 => height as usize,
398 };
399 let y_target = vec![T::default(); width as usize * height as usize];
400 let u_target = vec![T::default(); chroma_width * chroma_height];
401 let v_target = vec![T::default(); chroma_width * chroma_height];
402 Self {
403 y_plane: BufferStoreMut::Owned(y_target),
404 y_stride: width,
405 u_plane: BufferStoreMut::Owned(u_target),
406 u_stride: chroma_width as u32,
407 v_plane: BufferStoreMut::Owned(v_target),
408 v_stride: chroma_width as u32,
409 width,
410 height,
411 }
412 }
413
414 pub fn to_fixed(&'a self) -> YuvPlanarImage<'a, T> {
415 YuvPlanarImage {
416 y_plane: self.y_plane.borrow(),
417 y_stride: self.y_stride,
418 u_plane: self.u_plane.borrow(),
419 u_stride: self.u_stride,
420 v_plane: self.v_plane.borrow(),
421 v_stride: self.v_stride,
422 width: self.width,
423 height: self.height,
424 }
425 }
426}
427
428#[derive(Debug)]
429pub struct YuvPlanarImageWithAlpha<'a, T>
431where
432 T: Copy + Debug,
433{
434 pub y_plane: &'a [T],
435 pub y_stride: u32,
437 pub u_plane: &'a [T],
438 pub u_stride: u32,
440 pub v_plane: &'a [T],
441 pub v_stride: u32,
443 pub a_plane: &'a [T],
444 pub a_stride: u32,
446 pub width: u32,
447 pub height: u32,
448}
449
450impl<T> YuvPlanarImageWithAlpha<'_, T>
451where
452 T: Copy + Debug,
453{
454 pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
455 check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
456 check_y8_channel(self.a_plane, self.a_stride, self.width, self.height)?;
457 check_chroma_channel(
458 self.u_plane,
459 self.u_stride,
460 self.width,
461 self.height,
462 subsampling,
463 )?;
464 check_chroma_channel(
465 self.v_plane,
466 self.v_stride,
467 self.width,
468 self.height,
469 subsampling,
470 )?;
471 Ok(())
472 }
473}
474
475#[derive(Debug)]
476pub struct YuvPackedImage<'a, T>
478where
479 T: Copy + Debug,
480{
481 pub yuy: &'a [T],
482 pub yuy_stride: u32,
484 pub width: u32,
485 pub height: u32,
486}
487
488impl<T> YuvPackedImage<'_, T>
489where
490 T: Copy + Debug,
491{
492 pub fn check_constraints(&self) -> Result<(), YuvError> {
493 check_yuv_packed422(self.yuy, self.yuy_stride, self.width, self.height)?;
494 Ok(())
495 }
496
497 pub fn check_constraints444(&self) -> Result<(), YuvError> {
498 check_rgba_destination(self.yuy, self.yuy_stride, self.width, self.height, 4)?;
499 Ok(())
500 }
501}
502
503#[derive(Debug)]
504pub struct YuvPackedImageMut<'a, T>
506where
507 T: Copy + Debug,
508{
509 pub yuy: BufferStoreMut<'a, T>,
510 pub yuy_stride: u32,
512 pub width: u32,
513 pub height: u32,
514}
515
516impl<T> YuvPackedImageMut<'_, T>
517where
518 T: Copy + Debug,
519{
520 pub fn check_constraints(&self) -> Result<(), YuvError> {
521 check_yuv_packed422(self.yuy.borrow(), self.yuy_stride, self.width, self.height)?;
522 Ok(())
523 }
524
525 pub fn to_fixed(&self) -> YuvPackedImage<T> {
526 YuvPackedImage {
527 yuy: self.yuy.borrow(),
528 yuy_stride: self.yuy_stride,
529 width: self.width,
530 height: self.height,
531 }
532 }
533}