From 38ffd83820a97f20997cc11dd762a6994903a0e5 Mon Sep 17 00:00:00 2001 From: "Christopher N. Hesse" Date: Mon, 30 Jan 2023 21:48:18 +0100 Subject: [PATCH] Get rid of declarative macros Instead, make use of const generic parameters. This comes with the nice benefit of always knowing exactly which pixel type is being used at compile time. The same goes for better error messages. Using pure Rust code instead of macros should make for more readable code hopefully and encourage contributors. Signed-off-by: Christopher N. Hesse --- ffimage-yuv/src/yuv.rs | 148 ++++++++++++-------- ffimage-yuv/src/yuv422.rs | 63 ++++----- ffimage/benches/packed/convert.rs | 2 +- ffimage/src/color/bgr.rs | 70 ---------- ffimage/src/color/gray.rs | 81 +++++++---- ffimage/src/color/mod.rs | 3 - ffimage/src/color/rgb.rs | 217 ++++++++++++++++++++++++------ ffimage/src/lib.rs | 1 - ffimage/src/pixel.rs | 108 --------------- ffimage/tests/color/bgr.rs | 27 ---- ffimage/tests/color/gray.rs | 15 +-- ffimage/tests/color/mod.rs | 1 - ffimage/tests/color/rgb.rs | 9 +- ffimage/tests/packed/convert.rs | 8 +- ffimage/tests/packed/image.rs | 8 +- 15 files changed, 361 insertions(+), 400 deletions(-) delete mode 100644 ffimage/src/color/bgr.rs delete mode 100644 ffimage/src/pixel.rs delete mode 100644 ffimage/tests/color/bgr.rs diff --git a/ffimage-yuv/src/yuv.rs b/ffimage-yuv/src/yuv.rs index 4748a4d..efc13fc 100644 --- a/ffimage-yuv/src/yuv.rs +++ b/ffimage-yuv/src/yuv.rs @@ -1,67 +1,107 @@ +use core::{ + cmp::Ord, + ops::{Deref, DerefMut}, +}; + use num_traits::{AsPrimitive, FromPrimitive}; -use ffimage::color::bgr::*; use ffimage::color::rgb::*; use ffimage::traits::Pixel; -use ffimage::{create_pixel, define_pixel, impl_Pixel}; - -macro_rules! impl_from_rgb_to_yuv { - ($src:ident, $dst:ident, $r:expr, $g:expr, $b:expr) => { - impl, O: FromPrimitive> From<$src> for $dst { - fn from(pix: $src) -> Self { - let r = pix[$r].as_(); - let g = pix[$g].as_(); - let b = pix[$b].as_(); - - let y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16; - let u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; - let v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128; - - let y = O::from_i32(y).unwrap(); - let u = O::from_i32(u).unwrap(); - let v = O::from_i32(v).unwrap(); - $dst { 0: [y, u, v] } - } - } - }; + +/// YUV pixel +#[repr(C)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct Yuv(pub [T; 3]); + +impl Deref for Yuv { + type Target = [T; 3]; + + fn deref(&self) -> &Self::Target { + &self.0 + } } -macro_rules! impl_from_yuv_to_rgb { - ($src:ident, $dst:ident, $r:expr, $g:expr, $b:expr) => { - impl, O: Copy + FromPrimitive> From<$src> for $dst { - fn from(pix: $src) -> Self { - let y = pix[0].as_(); - let u = pix[1].as_(); - let v = pix[2].as_(); - let c = y - 16; - let d = u - 128; - let e = v - 128; - - let r = num_traits::clamp((298 * c + 409 * e + 128) >> 8, 0, 255); - let g = num_traits::clamp((298 * c - 100 * d - 208 * e + 128) >> 8, 0, 255); - let b = num_traits::clamp((298 * c + 516 * d + 128) >> 8, 0, 255); - - let r = O::from_i32(r).unwrap(); - let g = O::from_i32(g).unwrap(); - let b = O::from_i32(b).unwrap(); - - let mut result = $dst { 0: [r, g, b] }; - result[$r] = r; - result[$g] = g; - result[$b] = b; - result - } - } - }; +impl DerefMut for Yuv { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } } -create_pixel!(Yuv, 3, #[doc = "YUV pixel"]); +impl Pixel for Yuv +where + T: Copy, +{ + type T = T; + + fn channels() -> u8 { + 3 + } -impl_from_rgb_to_yuv!(Bgr, Yuv, 2, 1, 0); -impl_from_rgb_to_yuv!(Rgb, Yuv, 0, 1, 2); + fn subpixels() -> u8 { + 1 + } +} -impl_from_yuv_to_rgb!(Yuv, Bgr, 2, 1, 0); -impl_from_yuv_to_rgb!(Yuv, Rgb, 0, 1, 2); +impl< + T, + const Y: usize, + const U: usize, + const V: usize, + const R: usize, + const G: usize, + const B: usize, + > From> for Yuv +where + T: Copy + Default + AsPrimitive + FromPrimitive, +{ + fn from(rgb: Rgb) -> Self { + let r = rgb[R].as_(); + let g = rgb[G].as_(); + let b = rgb[B].as_(); + + let y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16; + let u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; + let v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128; + + let mut yuv = Yuv::::default(); + yuv[Y] = T::from_i32(y).unwrap(); + yuv[U] = T::from_i32(u).unwrap(); + yuv[V] = T::from_i32(v).unwrap(); + yuv + } +} + +impl< + T, + const R: usize, + const G: usize, + const B: usize, + const Y: usize, + const U: usize, + const V: usize, + > From> for Rgb +where + T: Copy + Default + AsPrimitive + FromPrimitive, +{ + fn from(yuv: Yuv) -> Self { + let y = yuv[Y].as_(); + let u = yuv[U].as_(); + let v = yuv[V].as_(); + let c = y - 16; + let d = u - 128; + let e = v - 128; + + let r = ((298 * c + 409 * e + 128) >> 8).min(255).max(0); + let g = ((298 * c - 100 * d - 208 * e + 128) >> 8).min(255).max(0); + let b = ((298 * c + 516 * d + 128) >> 8).min(255).max(0); + + let mut rgb = Rgb::::default(); + rgb[R] = T::from_i32(r).unwrap(); + rgb[G] = T::from_i32(g).unwrap(); + rgb[B] = T::from_i32(b).unwrap(); + rgb + } +} #[cfg(test)] mod tests { diff --git a/ffimage-yuv/src/yuv422.rs b/ffimage-yuv/src/yuv422.rs index 7d8170c..03a4686 100644 --- a/ffimage-yuv/src/yuv422.rs +++ b/ffimage-yuv/src/yuv422.rs @@ -1,7 +1,9 @@ +use core::ops::{Deref, DerefMut}; + use itertools::Itertools; use num_traits::{AsPrimitive, FromPrimitive}; -use ffimage::color::{Bgr, Rgb}; +use ffimage::color::Rgb; use ffimage::convert::MapPixels; use ffimage::traits::Pixel; @@ -13,26 +15,29 @@ pub type Uyvy = Yuv422; #[repr(C)] #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] -pub struct Yuv422(pub [T; 4]); - -impl Yuv422 { - /// Returns a new pixel - /// - /// # Arguments - /// - /// * `channels` - Channel values - pub fn new(channels: [T; 4]) -> Self { - Yuv422 { 0: channels } +pub struct Yuv422< + T, + const Y0: usize = 0, + const Y1: usize = 1, + const U: usize = 2, + const V: usize = 3, +>(pub [T; 4]); + +impl Deref + for Yuv422 +{ + type Target = [T; 4]; + + fn deref(&self) -> &Self::Target { + &self.0 } } -impl From<[T; 4]> +impl DerefMut for Yuv422 -where - T: Copy, { - fn from(array: [T; 4]) -> Self { - Yuv422 { 0: array } + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 } } @@ -52,24 +57,6 @@ where } } -impl core::ops::Index - for Yuv422 -{ - type Output = T; - - fn index(&self, i: usize) -> &Self::Output { - &self.0[i] - } -} - -impl core::ops::IndexMut - for Yuv422 -{ - fn index_mut(&mut self, i: usize) -> &mut Self::Output { - &mut self.0[i] - } -} - impl From> for [Yuv; 2] where @@ -168,14 +155,14 @@ where } impl - MapPixels, Bgr> for Yuv422 + MapPixels, Rgb> for Yuv422 where T: Copy + Default + AsPrimitive + FromPrimitive, { fn map_pixels<'a, I, O>(input: I, output: O) where I: IntoIterator>, - O: IntoIterator>, + O: IntoIterator>, T: 'a, { input @@ -183,8 +170,8 @@ where .zip(output.into_iter().tuples()) .for_each(|(t, (u1, u2))| { let yuv = <[Yuv; 2]>::from(*t); - *u1 = Bgr::::from(yuv[0]); - *u2 = Bgr::::from(yuv[1]); + *u1 = Rgb::::from(yuv[0]); + *u2 = Rgb::::from(yuv[1]); }) } } diff --git a/ffimage/benches/packed/convert.rs b/ffimage/benches/packed/convert.rs index 20c71d7..47eacb0 100644 --- a/ffimage/benches/packed/convert.rs +++ b/ffimage/benches/packed/convert.rs @@ -9,7 +9,7 @@ pub fn rgb_to_bgr(c: &mut Criterion) { for res in resolutions { let rgb = Image::, Vec>::new(res.0, res.1, 0u8); - let mut bgr = Image::, _>::new(res.0, res.1, 0u8); + let mut bgr = Image::, _>::new(res.0, res.1, 0u8); c.bench_function(&format!("Rgb[u8] -> Bgr[u8] ({}x{})", res.0, res.1), |b| { b.iter(|| rgb.convert(black_box(&mut bgr))) }); diff --git a/ffimage/src/color/bgr.rs b/ffimage/src/color/bgr.rs deleted file mode 100644 index b5f3bae..0000000 --- a/ffimage/src/color/bgr.rs +++ /dev/null @@ -1,70 +0,0 @@ -use num::traits::Bounded; -use num_traits::AsPrimitive; - -use crate::color::gray::*; -use crate::color::rgb::*; -use crate::traits::Pixel; -use crate::{create_pixel, define_pixel, impl_Pixel}; - -macro_rules! impl_from_pix_to_pix3 { - ($src:ident, $dst:ident, $_0:expr, $_1:expr, $_2:expr) => { - impl, O: Copy + 'static> From<$src> for $dst { - fn from(pix: $src) -> Self { - $dst { - 0: [pix[$_0].as_(), pix[$_1].as_(), pix[$_2].as_()], - } - } - } - }; -} - -macro_rules! impl_from_pix_to_pix4 { - ($src:ident, $dst:ident, $_0:expr, $_1:expr, $_2:expr) => { - impl, O: Copy + Bounded + 'static> From<$src> for $dst { - fn from(pix: $src) -> Self { - $dst { - 0: [ - pix[$_0].as_(), - pix[$_1].as_(), - pix[$_2].as_(), - O::max_value(), - ], - } - } - } - }; -} - -create_pixel!(Bgr, 3, #[doc = "BGR pixel"]); -create_pixel!(Bgra, 4, #[doc = "BGR pixel with alpha"]); - -impl_from_pix_to_pix4!(Bgr, Bgra, 0, 1, 2); -impl_from_pix_to_pix3!(Bgra, Bgr, 0, 1, 2); - -impl_from_pix_to_pix3!(Gray, Bgr, 0, 0, 0); -impl_from_pix_to_pix4!(Gray, Bgra, 0, 0, 0); - -impl_from_pix_to_pix3!(Rgb, Bgr, 2, 1, 0); -impl_from_pix_to_pix4!(Rgb, Bgra, 2, 1, 0); -impl_from_pix_to_pix3!(Rgba, Bgr, 2, 1, 0); -impl_from_pix_to_pix4!(Rgba, Bgra, 2, 1, 0); - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn channels() { - assert_eq!(Bgr::::channels(), 3); - assert_eq!(Bgra::::channels(), 4); - } - - #[test] - fn index_mut() { - let pix: Bgr = Bgr { 0: [1, 2, 3] }; - - assert_eq!(pix[0], 1); - assert_eq!(pix[1], 2); - assert_eq!(pix[2], 3); - } -} diff --git a/ffimage/src/color/gray.rs b/ffimage/src/color/gray.rs index 8a8304c..955e076 100644 --- a/ffimage/src/color/gray.rs +++ b/ffimage/src/color/gray.rs @@ -1,32 +1,67 @@ -use num_traits::{AsPrimitive, FromPrimitive}; +use core::ops::{Deref, DerefMut}; + +use num::FromPrimitive; -use crate::color::bgr::*; use crate::color::rgb::*; use crate::traits::Pixel; -use crate::{create_pixel, define_pixel, impl_Pixel}; - -macro_rules! impl_from_rgb_to_gray { - ($src:ident, $dst:ident, $r:expr, $g:expr, $b:expr) => { - impl, O: FromPrimitive> From<$src> for $dst { - fn from(pix: $src) -> Self { - // rec601 luma - let y = O::from_f32( - 0.2126 * pix[$r].as_() + 0.7152 * pix[$g].as_() + 0.0722 * pix[$b].as_(), - ) - .unwrap(); - - $dst { 0: [y] } - } - } - }; + +/// Grayscale pixel +#[repr(C)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct Gray(pub [T; 1]); + +impl Deref for Gray { + type Target = [T; 1]; + + fn deref(&self) -> &Self::Target { + &self.0 + } } -create_pixel!(Gray, 1, #[doc = "Grayscale pixel"]); +impl DerefMut for Gray { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Pixel for Gray +where + T: Copy, +{ + type T = T; + + fn channels() -> u8 { + 1 + } -impl_from_rgb_to_gray!(Rgb, Gray, 0, 1, 2); -impl_from_rgb_to_gray!(Rgba, Gray, 0, 1, 2); -impl_from_rgb_to_gray!(Bgr, Gray, 2, 1, 0); -impl_from_rgb_to_gray!(Bgra, Gray, 2, 1, 0); + fn subpixels() -> u8 { + 1 + } +} + +impl From> for Gray +where + T: Copy + FromPrimitive, + U: Copy + Into, +{ + fn from(rgb: Rgb) -> Self { + // rec601 luma + let y = + T::from_f32(0.2126 * rgb[R].into() + 0.7152 * rgb[G].into() + 0.0722 * rgb[B].into()) + .expect("could not convert from f32 to T"); + + Gray([y]) + } +} + +impl From> for Rgb +where + T: Copy, +{ + fn from(gray: Gray) -> Self { + Rgb([gray[0], gray[0], gray[0]]) + } +} #[cfg(test)] mod tests { diff --git a/ffimage/src/color/mod.rs b/ffimage/src/color/mod.rs index f696eb6..6af00b8 100644 --- a/ffimage/src/color/mod.rs +++ b/ffimage/src/color/mod.rs @@ -3,6 +3,3 @@ pub use gray::*; pub mod rgb; pub use rgb::*; - -pub mod bgr; -pub use bgr::*; diff --git a/ffimage/src/color/rgb.rs b/ffimage/src/color/rgb.rs index 14a753d..cece671 100644 --- a/ffimage/src/color/rgb.rs +++ b/ffimage/src/color/rgb.rs @@ -1,53 +1,182 @@ -use num::traits::Bounded; -use num_traits::AsPrimitive; +use core::ops::{Deref, DerefMut}; + +use num::FromPrimitive; -use crate::color::bgr::*; -use crate::color::gray::*; use crate::traits::Pixel; -use crate::{create_pixel, define_pixel, impl_Pixel}; - -macro_rules! impl_from_pix_to_pix3 { - ($src:ident, $dst:ident, $_0:expr, $_1:expr, $_2:expr) => { - impl, O: Copy + 'static> From<$src> for $dst { - fn from(pix: $src) -> Self { - $dst { - 0: [pix[$_0].as_(), pix[$_1].as_(), pix[$_2].as_()], - } - } - } - }; + +/// RGB pixel +#[repr(C)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct Rgb(pub [T; 3]); + +impl Deref for Rgb { + type Target = [T; 3]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Rgb { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Pixel for Rgb +where + T: Copy, +{ + type T = T; + + fn channels() -> u8 { + 3 + } + + fn subpixels() -> u8 { + 1 + } +} + +impl From> for Rgb +where + T: Copy + Default + From, + U: Copy, +{ + fn from(rgb: Rgb) -> Self { + Rgb::([T::from(rgb[2]), T::from(rgb[1]), T::from(rgb[0])]) + } +} + +impl From> for Rgb +where + T: Copy + Default + From, + U: Copy, +{ + fn from(rgb: Rgb) -> Self { + Rgb::([T::from(rgb[0]), T::from(rgb[1]), T::from(rgb[2])]) + } } -macro_rules! impl_from_pix_to_pix4 { - ($src:ident, $dst:ident, $_0:expr, $_1:expr, $_2:expr) => { - impl, O: Copy + Bounded + 'static> From<$src> for $dst { - fn from(pix: $src) -> Self { - $dst { - 0: [ - pix[$_0].as_(), - pix[$_1].as_(), - pix[$_2].as_(), - O::max_value(), - ], - } - } - } - }; +impl< + T, + U, + const R: usize, + const G: usize, + const B: usize, + const RGBA_R: usize, + const RGBA_G: usize, + const RGBA_B: usize, + const A: usize, + > From> for Rgb +where + T: Copy + Default + From, + U: Copy, +{ + fn from(rgba: Rgba) -> Self { + let mut rgb = Rgb::::default(); + rgb[R] = T::from(rgba[RGBA_R]); + rgb[G] = T::from(rgba[RGBA_G]); + rgb[B] = T::from(rgba[RGBA_B]); + rgb + } +} + +/// RGB pixel with alpha channel +#[repr(C)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct Rgba( + pub [T; 4], +); + +impl Deref + for Rgba +{ + type Target = [T; 4]; + + fn deref(&self) -> &Self::Target { + &self.0 + } } -create_pixel!(Rgb, 3, #[doc = "RGB pixel"]); -create_pixel!(Rgba, 4, #[doc = "RGB pixel with alpha"]); +impl DerefMut + for Rgba +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Pixel + for Rgba +where + T: Copy, +{ + type T = T; + + fn channels() -> u8 { + 4 + } -impl_from_pix_to_pix4!(Rgb, Rgba, 0, 1, 2); -impl_from_pix_to_pix3!(Rgba, Rgb, 0, 1, 2); + fn subpixels() -> u8 { + 1 + } +} + +impl From> for Rgba +where + T: Copy + Default + From, + U: Copy, +{ + fn from(rgba: Rgba) -> Self { + Rgba::([ + T::from(rgba[2]), + T::from(rgba[1]), + T::from(rgba[0]), + T::from(rgba[3]), + ]) + } +} -impl_from_pix_to_pix3!(Gray, Rgb, 0, 0, 0); -impl_from_pix_to_pix4!(Gray, Rgba, 0, 0, 0); +impl From> for Rgba +where + T: Copy + Default + From, + U: Copy, +{ + fn from(rgba: Rgba) -> Self { + Rgba::([ + T::from(rgba[0]), + T::from(rgba[1]), + T::from(rgba[2]), + T::from(rgba[3]), + ]) + } +} -impl_from_pix_to_pix3!(Bgr, Rgb, 2, 1, 0); -impl_from_pix_to_pix4!(Bgr, Rgba, 2, 1, 0); -impl_from_pix_to_pix3!(Bgra, Rgb, 2, 1, 0); -impl_from_pix_to_pix4!(Bgra, Rgba, 2, 1, 0); +impl< + T, + U, + const RGB_R: usize, + const RGB_G: usize, + const RGB_B: usize, + const R: usize, + const G: usize, + const B: usize, + const A: usize, + > From> for Rgba +where + T: Copy + Default + From + FromPrimitive, + U: Copy, +{ + fn from(rgb: Rgb) -> Self { + let mut rgba = Rgba::::default(); + rgba[R] = T::from(rgb[RGB_R]); + rgba[G] = T::from(rgb[RGB_G]); + rgba[B] = T::from(rgb[RGB_B]); + rgba[A] = T::from_u8(255).unwrap(); + rgba + } +} #[cfg(test)] mod tests { @@ -63,8 +192,8 @@ mod tests { fn index_mut() { let pix: Rgb = Rgb { 0: [1, 2, 3] }; - assert_eq!(pix[0], 1); - assert_eq!(pix[1], 2); - assert_eq!(pix[2], 3); + assert_eq!(pix.0[0], 1); + assert_eq!(pix.0[1], 2); + assert_eq!(pix.0[2], 3); } } diff --git a/ffimage/src/lib.rs b/ffimage/src/lib.rs index ce12221..f6fa837 100644 --- a/ffimage/src/lib.rs +++ b/ffimage/src/lib.rs @@ -54,7 +54,6 @@ //!``` pub mod error; -pub mod pixel; pub mod traits; pub mod color; diff --git a/ffimage/src/pixel.rs b/ffimage/src/pixel.rs deleted file mode 100644 index 821b6d9..0000000 --- a/ffimage/src/pixel.rs +++ /dev/null @@ -1,108 +0,0 @@ -#[macro_export] -/// Implement the Pixel trait for a pixel -macro_rules! impl_Pixel { - ($name:ident, $channels:expr, $subpixels:expr) => { - impl Pixel for $name { - type T = T; - - fn channels() -> u8 { - $channels - } - - fn subpixels() -> u8 { - $subpixels - } - } - - impl core::ops::Index for $name { - type Output = T; - - fn index(&self, i: usize) -> &Self::Output { - &self.0[i] - } - } - - impl core::ops::IndexMut for $name { - fn index_mut(&mut self, i: usize) -> &mut Self::Output { - &mut self.0[i] - } - } - }; -} - -#[macro_export] -/// Define a new pixel struct -macro_rules! define_pixel { - ($name:ident, $channels:expr, #[$doc:meta]) => { - #[repr(C)] - #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] - #[$doc] - pub struct $name(pub [T; $channels]); - - impl $name { - /// Returns a new pixel - pub fn new(channels: [T; $channels]) -> Self { - $name { 0: channels } - } - } - - impl From<[T; $channels]> for $name - where - T: Copy, - { - fn from(array: [T; $channels]) -> Self { - $name { 0: array } - } - } - }; -} - -#[macro_export] -/// Create a new pixel type -/// -/// A pixel is defined by its number of channels and the storage type (which is the same for each -/// channel). The memory layout is C compatible by default and the Debug, Copy and Clone traits -/// are derived. The Pixel trait is implemented automatically providing the basic building blocks -/// for higher level structures such as image view and buffer types. -/// -/// # Example -/// -/// ``` -/// use ffimage::{create_pixel, define_pixel, impl_Pixel}; -/// use ffimage::traits::Pixel; -/// -/// create_pixel!(Rgb, 3, #[doc = "RGB pixel"]); -/// ``` -macro_rules! create_pixel { - ($name:ident, $channels:expr, #[$doc:meta]) => { - define_pixel!($name, $channels, #[$doc]); - impl_Pixel!($name, $channels, 1); - }; -} - -#[macro_export] -/// Create a new macropixel type -/// -/// The term 'macropixel' does not seem to be defined as well as the 'pixel' term. We use it to -/// describe storage pixels used to store image buffers. To view or render such an image, one must -/// first convert from the macropixel representation to an image pixel (regular 'pixel') one. -/// -/// A famous application example is YUV chroma subsampling: the YUYV format samples 4:2:2, meaning -/// for each macropixel, there is a full chroma and two luma samples at half the bit width. -/// YUYV buffers are converted into YUV buffers (each YUYV macropixel ends up as two full YUV -/// pixels) for rendering. -/// -/// # Example -/// -/// ``` -/// use ffimage::{create_macropixel, create_pixel, define_pixel, impl_Pixel}; -/// use ffimage::traits::Pixel; -/// -/// create_macropixel!(Yuyv, 2, 2, #[doc = "YUYV macropixel"]); -/// ``` -macro_rules! create_macropixel { - ($name:ident, $channels:expr, $subpixels:expr, #[$doc:meta]) => { - define_pixel!($name, $channels, #[$doc]); - impl_Pixel!($name, $channels, $subpixels); - }; -} diff --git a/ffimage/tests/color/bgr.rs b/ffimage/tests/color/bgr.rs deleted file mode 100644 index ada6ad6..0000000 --- a/ffimage/tests/color/bgr.rs +++ /dev/null @@ -1,27 +0,0 @@ -extern crate ffimage; - -use ffimage::color::bgr::*; -use ffimage::color::gray::*; -use ffimage::color::rgb::*; - -#[test] -fn from_gray() { - let src_mem = [111u8; 1]; - let src = Gray::::from(src_mem); - let dst = Bgr::::from(src); - - assert_eq!(dst[0], src[0]); - assert_eq!(dst[1], src[0]); - assert_eq!(dst[2], src[0]); -} - -#[test] -fn from_rgb() { - let src_mem = [111u8; 3]; - let src = Rgb::::from(src_mem); - let dst = Bgr::::from(src); - - assert_eq!(dst[0], src[2]); - assert_eq!(dst[1], src[1]); - assert_eq!(dst[2], src[0]); -} diff --git a/ffimage/tests/color/gray.rs b/ffimage/tests/color/gray.rs index c1a9670..d4e80bc 100644 --- a/ffimage/tests/color/gray.rs +++ b/ffimage/tests/color/gray.rs @@ -2,25 +2,12 @@ extern crate ffimage; use num_traits::cast::FromPrimitive; -use ffimage::color::bgr::*; use ffimage::color::gray::*; use ffimage::color::rgb::*; #[test] fn from_rgb() { - let src_mem = [111u8; 3]; - let src = Rgb::::from(src_mem); - let dst = Gray::::from(src); - - let y = u8::from_f32(0.2126 * src[0] as f32 + 0.7152 * src[1] as f32 + 0.0722 * src[2] as f32) - .unwrap(); - assert_eq!(dst[0], y); -} - -#[test] -fn from_bgr() { - let src_mem = [111u8; 3]; - let src = Bgr::::from(src_mem); + let src = Rgb::([111u8; 3]); let dst = Gray::::from(src); let y = u8::from_f32(0.2126 * src[0] as f32 + 0.7152 * src[1] as f32 + 0.0722 * src[2] as f32) diff --git a/ffimage/tests/color/mod.rs b/ffimage/tests/color/mod.rs index 778ab6f..f6ca0e2 100644 --- a/ffimage/tests/color/mod.rs +++ b/ffimage/tests/color/mod.rs @@ -1,3 +1,2 @@ -mod bgr; mod gray; mod rgb; diff --git a/ffimage/tests/color/rgb.rs b/ffimage/tests/color/rgb.rs index 9573581..5f9733c 100644 --- a/ffimage/tests/color/rgb.rs +++ b/ffimage/tests/color/rgb.rs @@ -1,14 +1,12 @@ extern crate ffimage; -use ffimage::color::bgr::*; use ffimage::color::gray::*; use ffimage::color::rgb::*; #[test] fn from_gray() { - let src_mem = [111u8; 1]; - let src = Gray::::from(src_mem); - let dst = Rgb::::from(src); + let src = Gray([111u8]); + let dst: Rgb = Rgb::from(src); assert_eq!(dst[0], src[0]); assert_eq!(dst[1], src[0]); @@ -17,8 +15,7 @@ fn from_gray() { #[test] fn from_bgr() { - let src_mem = [111u8; 3]; - let src = Bgr::::from(src_mem); + let src = Rgb::([111u8; 3]); let dst = Rgb::::from(src); assert_eq!(dst[0], src[2]); diff --git a/ffimage/tests/packed/convert.rs b/ffimage/tests/packed/convert.rs index 44dc984..ca5f15d 100644 --- a/ffimage/tests/packed/convert.rs +++ b/ffimage/tests/packed/convert.rs @@ -19,7 +19,7 @@ fn convert_rgb_to_gray() { let y = (0.2126 * pix_in[0] as f32 + 0.7152 * pix_in[1] as f32 + 0.0722 * pix_in[2] as f32) as u8; - assert_eq!(pix_out, Gray::::new([y])); + assert_eq!(pix_out, Gray([y])); } } } @@ -35,7 +35,7 @@ fn convert_gray_to_rgb() { for j in 0..view.width() { let pix_in = view.pixel(j, i).unwrap(); let pix_out = buf.pixel(j, i).unwrap(); - assert_eq!(pix_out, Rgb::::new([pix_in[0], pix_in[0], pix_in[0]])); + assert_eq!(pix_out, Rgb([pix_in[0], pix_in[0], pix_in[0]])); } } } @@ -44,7 +44,7 @@ fn convert_gray_to_rgb() { fn convert_rgb_to_bgra() { let mem: [u8; 12] = [10, 20, 30, 11, 21, 31, 12, 22, 32, 13, 23, 33]; let view = Image::, _>::from_buf(&mem, 2, 2).unwrap(); - let mut buf = Image::, _>::new(2, 2, 0u8); + let mut buf = Image::, _>::new(2, 2, 0u8); view.convert(&mut buf); for i in 0..view.height() { @@ -53,7 +53,7 @@ fn convert_rgb_to_bgra() { let pix_out = buf.pixel(j, i).unwrap(); assert_eq!( pix_out, - Bgra::::new([pix_in[2], pix_in[1], pix_in[0], 255]) + Rgba::([pix_in[2], pix_in[1], pix_in[0], 255]) ); } } diff --git a/ffimage/tests/packed/image.rs b/ffimage/tests/packed/image.rs index 8dd26a1..985d9ae 100644 --- a/ffimage/tests/packed/image.rs +++ b/ffimage/tests/packed/image.rs @@ -72,17 +72,13 @@ fn pixel() { fn set_pixel() { let mut mem = vec![0; 27]; let mut image = Image::, _>::from_buf(&mut mem, 3, 3).unwrap(); - image - .set_pixel(0, 2, &Rgb::::new([10, 20, 30])) - .unwrap(); + image.set_pixel(0, 2, &Rgb::([10, 20, 30])).unwrap(); let pix = image.pixel(0, 2).unwrap(); assert_eq!(pix[0], 10); assert_eq!(pix[1], 20); assert_eq!(pix[2], 30); - image - .set_pixel(0, 2, &Rgb::::new([10, 20, 30])) - .unwrap(); + image.set_pixel(0, 2, &Rgb::([10, 20, 30])).unwrap(); let pix = image.pixel(0, 2).unwrap(); assert_eq!(pix[0], 10); assert_eq!(pix[1], 20);