diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml new file mode 100644 index 0000000..df2c89c --- /dev/null +++ b/.github/workflows/clippy.yml @@ -0,0 +1,96 @@ +name: Clippy + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + CARGO_TERM_COLOR: always + +jobs: + clippy-all-features: + name: Clippy (all features) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Run clippy with all features + run: cargo clippy --all-features -- -D warnings + + build-individual-features: + name: Build (feature ${{ matrix.feature }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + feature: + - I420 + - I422 + - I444 + - I010 + - I012 + - I210 + - I212 + - I410 + - I412 + - NV12 + - P010 + - P012 + - YUYV + - RGBA + - BGRA + - ARGB + - ABGR + - RGB + - BGR + steps: + - uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ matrix.feature }}-${{ hashFiles('**/Cargo.lock') }} + + - name: Build with feature ${{ matrix.feature }} + run: cargo build --features ${{ matrix.feature }} diff --git a/Cargo.toml b/Cargo.toml index b3234ce..4ff7c7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ num_cpus = { version = "1", optional = true } fir = { package = "fast_image_resize", version = "5", optional = true } [features] -default = ["multi-thread", "resize"] +default = ["multi-thread", "resize", "all-formats"] # Enable multi threading for image conversion multi-thread = ["dep:rayon", "dep:num_cpus"] @@ -28,6 +28,50 @@ multi-thread = ["dep:rayon", "dep:num_cpus"] # Include Resizer using fast_image_resize resize = ["dep:fir"] +# Formats +all-formats = [ + "I420", + "I422", + "I444", + "I010", + "I012", + "I210", + "I212", + "I410", + "I412", + "NV12", + "P010", + "P012", + "YUYV", + "RGBA", + "BGRA", + "ARGB", + "ABGR", + "RGB", + "BGR", +] + +I420 = [] +I422 = [] +I444 = [] +I010 = [] +I012 = [] +I210 = [] +I212 = [] +I410 = [] +I412 = [] +NV12 = [] +P010 = [] +P012 = [] +YUYV = [] +RGBA = [] +BGRA = [] +ARGB = [] +ABGR = [] +RGB = [] +BGR = [] + + [dev-dependencies] image = { version = "0.25", default-features = false, features = ["png"] } nalgebra = "0.34" diff --git a/src/formats/dyn_rgba_src.rs b/src/formats/dyn_rgba_src.rs index ee3cd08..4fa57aa 100644 --- a/src/formats/dyn_rgba_src.rs +++ b/src/formats/dyn_rgba_src.rs @@ -1,5 +1,8 @@ -use crate::vector::Vector; -use crate::{RgbaBlock, RgbaSrc}; +use crate::{ + arch::*, + formats::rgb::{RgbaBlock, RgbaSrc}, + vector::Vector, +}; pub(crate) trait DynRgbaReaderSpec { unsafe fn dyn_read(&mut self, x: usize, y: usize) -> RgbaBlock; @@ -9,8 +12,7 @@ pub(crate) use platform::DynRgbaReader; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod platform { - use super::DynRgbaReaderSpec; - use crate::{RgbaBlock, RgbaSrc, arch::*}; + use super::*; pub(crate) trait DynRgbaReader: DynRgbaReaderSpec + DynRgbaReaderSpec<__m256> + DynRgbaReaderSpec<__m512> @@ -40,8 +42,7 @@ mod platform { // aarch64 #[cfg(target_arch = "aarch64")] mod platform { - use super::DynRgbaReaderSpec; - use crate::{RgbaBlock, RgbaSrc, arch::*}; + use super::*; pub(crate) trait DynRgbaReader: DynRgbaReaderSpec + DynRgbaReaderSpec diff --git a/src/formats/i420/mod.rs b/src/formats/i420/mod.rs deleted file mode 100644 index 7df7a9f..0000000 --- a/src/formats/i420/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::vector::Vector; - -mod from_rgb; -mod read; -mod to_rgb; -mod write; - -pub(crate) use from_rgb::RgbToI420; -pub(crate) use read::I420Reader; -pub(crate) use to_rgb::I420ToRgb; -pub(crate) use write::I420Writer; - -pub(crate) struct I420Block { - pub(crate) y00: V, - pub(crate) y01: V, - pub(crate) y10: V, - pub(crate) y11: V, - - pub(crate) u: V, - pub(crate) v: V, -} - -pub(crate) trait I420Src { - unsafe fn read(&mut self, x: usize, y: usize) -> I420Block; -} diff --git a/src/formats/i422/mod.rs b/src/formats/i422/mod.rs deleted file mode 100644 index a7a45da..0000000 --- a/src/formats/i422/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::vector::Vector; - -mod from_rgb; -mod read; -mod to_rgb; -mod write; - -pub(crate) use from_rgb::RgbToI422; -pub(crate) use read::I422Reader; -pub(crate) use to_rgb::I422ToRgb; -pub(crate) use write::I422Writer; - -pub(crate) struct I422Block { - pub(crate) y00: V, - pub(crate) y01: V, - pub(crate) y10: V, - pub(crate) y11: V, - - pub(crate) u0: V, - pub(crate) u1: V, - pub(crate) v0: V, - pub(crate) v1: V, -} - -pub(crate) trait I422Src { - unsafe fn read(&mut self, x: usize, y: usize) -> I422Block; -} diff --git a/src/formats/i444/mod.rs b/src/formats/i444/mod.rs deleted file mode 100644 index c419e6d..0000000 --- a/src/formats/i444/mod.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::vector::Vector; - -mod from_rgb; -mod read; -mod to_rgb; -mod write; - -pub(crate) use from_rgb::RgbToI444; -pub(crate) use read::I444Reader; -pub(crate) use to_rgb::I444ToRgb; -pub(crate) use write::I444Writer; - -pub(crate) struct I444Block { - pub(crate) px00: I444Pixel, - pub(crate) px01: I444Pixel, - pub(crate) px10: I444Pixel, - pub(crate) px11: I444Pixel, -} - -pub(crate) struct I444Pixel { - pub(crate) y: V, - pub(crate) u: V, - pub(crate) v: V, -} - -pub(crate) trait I444Src { - unsafe fn read(&mut self, x: usize, y: usize) -> I444Block; -} diff --git a/src/formats/mod.rs b/src/formats/mod.rs index 61328da..f391149 100644 --- a/src/formats/mod.rs +++ b/src/formats/mod.rs @@ -1,26 +1,28 @@ -#[macro_use] -mod rgba; mod dyn_rgba_src; -mod i420; -mod i422; -mod i444; -mod nv12; -mod rgb; mod transfer_and_primaries_convert; mod visit_2x2; -mod yuyv; -pub(crate) use dyn_rgba_src::{DynRgbaReader, DynRgbaReaderSpec}; -pub(crate) use i420::*; -pub(crate) use i422::*; -pub(crate) use i444::*; -pub(crate) use nv12::*; -pub(crate) use rgb::*; -pub(crate) use rgba::*; +#[cfg(any( + feature = "I420", + feature = "I010", + feature = "I012", + feature = "NV12", + feature = "P010", + feature = "P012" +))] +pub(crate) mod yuv420; +#[cfg(any(feature = "I422", feature = "I210", feature = "I212", feature = "YUYV"))] +pub(crate) mod yuv422; +#[cfg(any(feature = "I444", feature = "I410", feature = "I412"))] +pub(crate) mod yuv444; + +pub(crate) mod rgb; + pub(crate) use transfer_and_primaries_convert::{ TransferAndPrimariesConvert, need_transfer_and_primaries_convert, }; -pub(crate) use yuyv::*; + +pub(crate) use dyn_rgba_src::{DynRgbaReader, DynRgbaReaderSpec}; fn max_value_for_bits(bits: usize) -> f32 { ((1 << bits) - 1) as f32 diff --git a/src/formats/nv12/mod.rs b/src/formats/nv12/mod.rs deleted file mode 100644 index a8171f6..0000000 --- a/src/formats/nv12/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod read; -mod write; - -pub(crate) use read::NV12Reader; -pub(crate) use write::NV12Writer; diff --git a/src/formats/rgb/mod.rs b/src/formats/rgb/mod.rs index f8dc662..6dc549f 100644 --- a/src/formats/rgb/mod.rs +++ b/src/formats/rgb/mod.rs @@ -1,5 +1,65 @@ -mod read; -mod write; +use crate::vector::Vector; -pub(crate) use read::RgbReader; -pub(crate) use write::RgbWriter; +mod read_rgb; +mod read_rgba; +mod write_rgb; +mod write_rgba; + +pub(crate) type ReadRgba<'a, P> = read_rgba::ReadRgba<'a, SWIZZLE_RGBA, P>; +pub(crate) type ReadBgra<'a, P> = read_rgba::ReadRgba<'a, SWIZZLE_BGRA, P>; +pub(crate) type ReadArgb<'a, P> = read_rgba::ReadRgba<'a, SWIZZLE_ARGB, P>; +pub(crate) type ReadAbgr<'a, P> = read_rgba::ReadRgba<'a, SWIZZLE_ABGR, P>; + +pub(crate) type WriteRgba<'a, P, S> = write_rgba::WriteRgba<'a, SWIZZLE_RGBA, P, S>; +pub(crate) type WriteBgra<'a, P, S> = write_rgba::WriteRgba<'a, SWIZZLE_BGRA, P, S>; +pub(crate) type WriteArgb<'a, P, S> = write_rgba::WriteRgba<'a, SWIZZLE_ARGB, P, S>; +pub(crate) type WriteAbgr<'a, P, S> = write_rgba::WriteRgba<'a, SWIZZLE_ABGR, P, S>; + +pub(crate) type ReadRgb<'a, P> = read_rgb::ReadRgb<'a, SWIZZLE_RGBA, P>; +pub(crate) type ReadBgr<'a, P> = read_rgb::ReadRgb<'a, SWIZZLE_BGRA, P>; + +pub(crate) type WriteRgb<'a, P, S> = write_rgb::WriteRgb<'a, SWIZZLE_RGBA, P, S>; +pub(crate) type WriteBgr<'a, P, S> = write_rgb::WriteRgb<'a, SWIZZLE_BGRA, P, S>; + +const SWIZZLE_RGBA: u8 = 0; +const SWIZZLE_BGRA: u8 = 1; +const SWIZZLE_ARGB: u8 = 2; +const SWIZZLE_ABGR: u8 = 3; + +#[derive(Debug, Clone, Copy)] +pub(crate) struct RgbaPixel { + pub(crate) r: V, + pub(crate) g: V, + pub(crate) b: V, + pub(crate) a: V, +} + +impl RgbaPixel { + #[inline(always)] + fn new(r: V, g: V, b: V, a: V) -> Self { + Self { r, g, b, a } + } + + #[inline(always)] + pub(crate) unsafe fn from_components(c0: V, c1: V, c2: V, c3: V) -> Self { + match SWIZZLE { + SWIZZLE_RGBA => Self::new(c0, c1, c2, c3), + SWIZZLE_BGRA => Self::new(c2, c1, c0, c3), + SWIZZLE_ARGB => Self::new(c1, c2, c3, c0), + SWIZZLE_ABGR => Self::new(c3, c2, c1, c0), + _ => unreachable!("unknown swizzle {SWIZZLE}"), + } + } +} + +#[derive(Debug, Clone, Copy)] +pub(crate) struct RgbaBlock { + pub(crate) px00: RgbaPixel, + pub(crate) px01: RgbaPixel, + pub(crate) px10: RgbaPixel, + pub(crate) px11: RgbaPixel, +} + +pub(crate) trait RgbaSrc { + unsafe fn read(&mut self, x: usize, y: usize) -> RgbaBlock; +} diff --git a/src/formats/rgb/read.rs b/src/formats/rgb/read_rgb.rs similarity index 88% rename from src/formats/rgb/read.rs rename to src/formats/rgb/read_rgb.rs index 5c3301b..13d32e7 100644 --- a/src/formats/rgb/read.rs +++ b/src/formats/rgb/read_rgb.rs @@ -1,11 +1,11 @@ -use crate::formats::rgba::{RgbaBlock, RgbaPixel, RgbaSrc}; +use crate::formats::rgb::{RgbaBlock, RgbaPixel, RgbaSrc}; use crate::planes::read_planes; use crate::primitive::Primitive; use crate::vector::Vector; use crate::{ConvertError, ImageRef, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct RgbReader<'a, const SWIZZLE: u8, P: Primitive> { +pub(crate) struct ReadRgb<'a, const SWIZZLE: u8, P: Primitive> { rgb: &'a [u8], rgb_stride: usize, @@ -15,7 +15,7 @@ pub(crate) struct RgbReader<'a, const SWIZZLE: u8, P: Primitive> { _m: PhantomData<&'a [P]>, } -impl<'a, const SWIZZLE: u8, P: Primitive> RgbReader<'a, SWIZZLE, P> { +impl<'a, const SWIZZLE: u8, P: Primitive> ReadRgb<'a, SWIZZLE, P> { pub(crate) fn new(src: &'a dyn ImageRef) -> Result { src.bounds_check()?; @@ -30,7 +30,7 @@ impl<'a, const SWIZZLE: u8, P: Primitive> RgbReader<'a, SWIZZLE, P> { } } -impl RgbaSrc for RgbReader<'_, SWIZZLE, P> { +impl RgbaSrc for ReadRgb<'_, SWIZZLE, P> { #[inline(always)] unsafe fn read(&mut self, x: usize, y: usize) -> RgbaBlock { let rgb00offset = y * self.rgb_stride + x * 3 * P::SIZE; diff --git a/src/formats/rgba/read.rs b/src/formats/rgb/read_rgba.rs similarity index 91% rename from src/formats/rgba/read.rs rename to src/formats/rgb/read_rgba.rs index feefe12..306e280 100644 --- a/src/formats/rgba/read.rs +++ b/src/formats/rgb/read_rgba.rs @@ -5,7 +5,7 @@ use crate::vector::Vector; use crate::{ConvertError, ImageRef, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct RgbaReader<'a, const SWIZZLE: u8, P: Primitive> { +pub(crate) struct ReadRgba<'a, const SWIZZLE: u8, P: Primitive> { rgba: &'a [u8], rgba_stride: usize, @@ -15,7 +15,7 @@ pub(crate) struct RgbaReader<'a, const SWIZZLE: u8, P: Primitive> { _m: PhantomData<&'a [P]>, } -impl<'a, const SWIZZLE: u8, P: Primitive> RgbaReader<'a, SWIZZLE, P> { +impl<'a, const SWIZZLE: u8, P: Primitive> ReadRgba<'a, SWIZZLE, P> { pub(crate) fn new(src: &'a dyn ImageRef) -> Result { src.bounds_check()?; @@ -30,7 +30,7 @@ impl<'a, const SWIZZLE: u8, P: Primitive> RgbaReader<'a, SWIZZLE, P> { } } -impl RgbaSrc for RgbaReader<'_, SWIZZLE, P> { +impl RgbaSrc for ReadRgba<'_, SWIZZLE, P> { #[inline(always)] unsafe fn read(&mut self, x: usize, y: usize) -> RgbaBlock { let rgba00offset = y * self.rgba_stride + x * 4 * P::SIZE; diff --git a/src/formats/rgb/write.rs b/src/formats/rgb/write_rgb.rs similarity index 87% rename from src/formats/rgb/write.rs rename to src/formats/rgb/write_rgb.rs index e649507..ad4f091 100644 --- a/src/formats/rgb/write.rs +++ b/src/formats/rgb/write_rgb.rs @@ -1,12 +1,12 @@ +use crate::formats::rgb::{RgbaPixel, RgbaSrc, SWIZZLE_BGRA, SWIZZLE_RGBA}; use crate::formats::visit_2x2::{Image2x2Visitor, visit}; -use crate::formats::{SWIZZLE_BGRA, SWIZZLE_RGBA}; use crate::planes::read_planes_mut; use crate::primitive::Primitive; use crate::vector::Vector; -use crate::{ConvertError, ImageMut, ImageRefExt, RgbaPixel, RgbaSrc}; +use crate::{ConvertError, ImageMut, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct RgbWriter<'a, const SWIZZLE: u8, P, S> +pub(crate) struct WriteRgb<'a, const SWIZZLE: u8, P, S> where P: Primitive, S: RgbaSrc, @@ -22,7 +22,7 @@ where _m: PhantomData<&'a mut [P]>, } -impl<'a, const SWIZZLE: u8, P, S> RgbWriter<'a, SWIZZLE, P, S> +impl<'a, const SWIZZLE: u8, P, S> WriteRgb<'a, SWIZZLE, P, S> where P: Primitive, S: RgbaSrc, @@ -52,7 +52,7 @@ where } } -impl Image2x2Visitor for RgbWriter<'_, SWIZZLE, P, S> +impl Image2x2Visitor for WriteRgb<'_, SWIZZLE, P, S> where P: Primitive, S: RgbaSrc, diff --git a/src/formats/rgba/write.rs b/src/formats/rgb/write_rgba.rs similarity index 92% rename from src/formats/rgba/write.rs rename to src/formats/rgb/write_rgba.rs index 5eb4263..5eecf81 100644 --- a/src/formats/rgba/write.rs +++ b/src/formats/rgb/write_rgba.rs @@ -6,7 +6,7 @@ use crate::vector::Vector; use crate::{ConvertError, ImageMut, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct RgbaWriter<'a, const SWIZZLE: u8, P, S> +pub(crate) struct WriteRgba<'a, const SWIZZLE: u8, P, S> where P: Primitive, S: RgbaSrc, @@ -22,7 +22,7 @@ where _m: PhantomData<&'a mut [P]>, } -impl<'a, const SWIZZLE: u8, P, S> RgbaWriter<'a, SWIZZLE, P, S> +impl<'a, const SWIZZLE: u8, P, S> WriteRgba<'a, SWIZZLE, P, S> where P: Primitive, S: RgbaSrc, @@ -52,7 +52,7 @@ where } } -impl Image2x2Visitor for RgbaWriter<'_, SWIZZLE, P, S> +impl Image2x2Visitor for WriteRgba<'_, SWIZZLE, P, S> where P: Primitive, S: RgbaSrc, diff --git a/src/formats/rgba/mod.rs b/src/formats/rgba/mod.rs deleted file mode 100644 index a5a4235..0000000 --- a/src/formats/rgba/mod.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::vector::Vector; - -mod read; -mod write; - -pub(crate) use read::RgbaReader; -pub(crate) use write::RgbaWriter; - -pub(crate) const SWIZZLE_RGBA: u8 = 0; -pub(crate) const SWIZZLE_BGRA: u8 = 1; -pub(crate) const SWIZZLE_ARGB: u8 = 2; -pub(crate) const SWIZZLE_ABGR: u8 = 3; - -#[derive(Debug, Clone, Copy)] -pub(crate) struct RgbaPixel { - pub(crate) r: V, - pub(crate) g: V, - pub(crate) b: V, - pub(crate) a: V, -} - -impl RgbaPixel { - #[inline(always)] - fn new(r: V, g: V, b: V, a: V) -> Self { - Self { r, g, b, a } - } - - #[inline(always)] - pub(crate) unsafe fn from_components(c0: V, c1: V, c2: V, c3: V) -> Self { - match SWIZZLE { - SWIZZLE_RGBA => Self::new(c0, c1, c2, c3), - SWIZZLE_BGRA => Self::new(c2, c1, c0, c3), - SWIZZLE_ARGB => Self::new(c1, c2, c3, c0), - SWIZZLE_ABGR => Self::new(c3, c2, c1, c0), - _ => unreachable!("unknown swizzle {SWIZZLE}"), - } - } -} - -#[derive(Debug, Clone, Copy)] -pub(crate) struct RgbaBlock { - pub(crate) px00: RgbaPixel, - pub(crate) px01: RgbaPixel, - pub(crate) px10: RgbaPixel, - pub(crate) px11: RgbaPixel, -} - -pub(crate) trait RgbaSrc { - unsafe fn read(&mut self, x: usize, y: usize) -> RgbaBlock; -} diff --git a/src/formats/transfer_and_primaries_convert.rs b/src/formats/transfer_and_primaries_convert.rs index 1d279c7..611cf4d 100644 --- a/src/formats/transfer_and_primaries_convert.rs +++ b/src/formats/transfer_and_primaries_convert.rs @@ -1,4 +1,4 @@ -use super::rgba::{RgbaBlock, RgbaSrc}; +use super::rgb::{RgbaBlock, RgbaSrc}; use crate::ColorTransfer; use crate::color::ColorInfo; use crate::color::primaries::{rgb_to_xyz, xyz_to_rgb}; diff --git a/src/formats/i420/from_rgb.rs b/src/formats/yuv420/from_rgb.rs similarity index 88% rename from src/formats/i420/from_rgb.rs rename to src/formats/yuv420/from_rgb.rs index 9f23462..25cdb23 100644 --- a/src/formats/i420/from_rgb.rs +++ b/src/formats/yuv420/from_rgb.rs @@ -1,10 +1,11 @@ -use super::{I420Block, I420Src}; +use super::{Yuv420Block, Yuv420Src}; use crate::color::ColorInfo; -use crate::formats::rgba::{RgbaBlock, RgbaSrc}; +use crate::formats::rgb::{RgbaBlock, RgbaSrc}; use crate::vector::Vector; use crate::{ColorSpace, ColorTransfer, ConvertError}; -pub(crate) struct RgbToI420 { +/// RGB to YUV420 converter source +pub(crate) struct FromRgb { rgba_src: S, space: ColorSpace, transfer: ColorTransfer, @@ -12,7 +13,7 @@ pub(crate) struct RgbToI420 { full_range: bool, } -impl RgbToI420 { +impl FromRgb { pub(crate) fn new(color: &ColorInfo, rgba_src: S) -> Result { let ColorInfo::YUV(yuv) = color else { return Err(ConvertError::InvalidColorInfo); @@ -28,9 +29,9 @@ impl RgbToI420 { } } -impl I420Src for RgbToI420 { +impl Yuv420Src for FromRgb { #[inline(always)] - unsafe fn read(&mut self, x: usize, y: usize) -> I420Block { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv420Block { let RgbaBlock { px00, px01, @@ -69,7 +70,7 @@ impl I420Src for RgbToI420 { (y00, y01, y10, y11, u, v) }; - I420Block { + Yuv420Block { y00, y01, y10, diff --git a/src/formats/yuv420/mod.rs b/src/formats/yuv420/mod.rs new file mode 100644 index 0000000..9afc855 --- /dev/null +++ b/src/formats/yuv420/mod.rs @@ -0,0 +1,29 @@ +use crate::vector::Vector; + +mod from_rgb; +mod read_2plane; +mod read_3plane; +mod to_rgb; +mod write_2plane; +mod write_3plane; + +pub(crate) use from_rgb::FromRgb; +pub(crate) use read_2plane::Read2Plane; +pub(crate) use read_3plane::Read3Plane; +pub(crate) use to_rgb::ToRgb; +pub(crate) use write_2plane::Write2Plane; +pub(crate) use write_3plane::Write3Plane; + +pub(crate) struct Yuv420Block { + pub(crate) y00: V, + pub(crate) y01: V, + pub(crate) y10: V, + pub(crate) y11: V, + + pub(crate) u: V, + pub(crate) v: V, +} + +pub(crate) trait Yuv420Src { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv420Block; +} diff --git a/src/formats/nv12/read.rs b/src/formats/yuv420/read_2plane.rs similarity index 88% rename from src/formats/nv12/read.rs rename to src/formats/yuv420/read_2plane.rs index cee240b..253211c 100644 --- a/src/formats/nv12/read.rs +++ b/src/formats/yuv420/read_2plane.rs @@ -1,11 +1,11 @@ -use crate::formats::{I420Block, I420Src}; +use crate::formats::yuv420::{Yuv420Block, Yuv420Src}; use crate::planes::read_planes; use crate::primitive::Primitive; use crate::vector::Vector; use crate::{ConvertError, ImageRef, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct NV12Reader<'a, P: Primitive> { +pub(crate) struct Read2Plane<'a, P: Primitive> { y: &'a [u8], uv: &'a [u8], @@ -17,7 +17,7 @@ pub(crate) struct NV12Reader<'a, P: Primitive> { _m: PhantomData<&'a [P]>, } -impl<'a, P: Primitive> NV12Reader<'a, P> { +impl<'a, P: Primitive> Read2Plane<'a, P> { pub(crate) fn new(src: &'a dyn ImageRef) -> Result { src.bounds_check()?; @@ -34,9 +34,9 @@ impl<'a, P: Primitive> NV12Reader<'a, P> { } } -impl I420Src for NV12Reader<'_, P> { +impl Yuv420Src for Read2Plane<'_, P> { #[inline(always)] - unsafe fn read(&mut self, x: usize, y: usize) -> I420Block { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv420Block { let y00_offset = y * self.y_stride + x * P::SIZE; let y10_offset = (y + 1) * self.y_stride + x * P::SIZE; @@ -63,7 +63,7 @@ impl I420Src for NV12Reader<'_, P> { let u = u.vdivf(self.max_value); let v = v.vdivf(self.max_value); - I420Block { + Yuv420Block { y00, y01, y10, diff --git a/src/formats/i420/read.rs b/src/formats/yuv420/read_3plane.rs similarity index 89% rename from src/formats/i420/read.rs rename to src/formats/yuv420/read_3plane.rs index 02398d0..360415f 100644 --- a/src/formats/i420/read.rs +++ b/src/formats/yuv420/read_3plane.rs @@ -1,11 +1,11 @@ -use super::{I420Block, I420Src}; +use crate::formats::yuv420::{Yuv420Block, Yuv420Src}; use crate::planes::read_planes; use crate::primitive::Primitive; use crate::vector::Vector; use crate::{ConvertError, ImageRef, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct I420Reader<'a, P: Primitive> { +pub(crate) struct Read3Plane<'a, P: Primitive> { y: &'a [u8], u: &'a [u8], v: &'a [u8], @@ -19,7 +19,7 @@ pub(crate) struct I420Reader<'a, P: Primitive> { _m: PhantomData<&'a [P]>, } -impl<'a, P: Primitive> I420Reader<'a, P> { +impl<'a, P: Primitive> Read3Plane<'a, P> { pub(crate) fn new(src: &'a dyn ImageRef) -> Result { src.bounds_check()?; @@ -38,9 +38,9 @@ impl<'a, P: Primitive> I420Reader<'a, P> { } } -impl I420Src for I420Reader<'_, P> { +impl Yuv420Src for Read3Plane<'_, P> { #[inline(always)] - unsafe fn read(&mut self, x: usize, y: usize) -> I420Block { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv420Block { let y00_offset = (y * self.y_stride) + x * P::SIZE; let y10_offset = ((y + 1) * self.y_stride) + x * P::SIZE; @@ -66,7 +66,7 @@ impl I420Src for I420Reader<'_, P> { let u = u.vdivf(self.max_value); let v = v.vdivf(self.max_value); - I420Block { + Yuv420Block { y00, y01, y10, diff --git a/src/formats/i420/to_rgb.rs b/src/formats/yuv420/to_rgb.rs similarity index 85% rename from src/formats/i420/to_rgb.rs rename to src/formats/yuv420/to_rgb.rs index 04decc0..0414456 100644 --- a/src/formats/i420/to_rgb.rs +++ b/src/formats/yuv420/to_rgb.rs @@ -1,10 +1,11 @@ -use super::{I420Block, I420Src}; -use crate::formats::rgba::{RgbaBlock, RgbaPixel, RgbaSrc}; +use super::{Yuv420Block, Yuv420Src}; +use crate::formats::rgb::{RgbaBlock, RgbaPixel, RgbaSrc}; use crate::vector::Vector; use crate::{ColorInfo, ColorSpace, ColorTransfer, ConvertError}; -pub(crate) struct I420ToRgb { - i420_src: S, +/// YUV 420 to RGB converter source +pub(crate) struct ToRgb { + yuv420_src: S, space: ColorSpace, transfer: ColorTransfer, @@ -12,14 +13,14 @@ pub(crate) struct I420ToRgb { full_range: bool, } -impl I420ToRgb { - pub(crate) fn new(color: &ColorInfo, i420_src: S) -> Result { +impl ToRgb { + pub(crate) fn new(color: &ColorInfo, yuv420_src: S) -> Result { let ColorInfo::YUV(yuv) = color else { return Err(ConvertError::InvalidColorInfo); }; Ok(Self { - i420_src, + yuv420_src, space: yuv.space, transfer: yuv.transfer, xyz_to_rgb: yuv.primaries.xyz_to_rgb_mat(), @@ -28,17 +29,17 @@ impl I420ToRgb { } } -impl RgbaSrc for I420ToRgb { +impl RgbaSrc for ToRgb { #[inline(always)] unsafe fn read(&mut self, x: usize, y: usize) -> RgbaBlock { - let I420Block { + let Yuv420Block { mut y00, mut y01, mut y10, mut y11, mut u, mut v, - } = self.i420_src.read::(x, y); + } = self.yuv420_src.read::(x, y); // If the YUV components don't use the full range of u8 scale them to the full range // Y 16..=235 -> 0..255 Y = (1.164 * (Y - 16)) diff --git a/src/formats/nv12/write.rs b/src/formats/yuv420/write_2plane.rs similarity index 88% rename from src/formats/nv12/write.rs rename to src/formats/yuv420/write_2plane.rs index c079b29..def16c6 100644 --- a/src/formats/nv12/write.rs +++ b/src/formats/yuv420/write_2plane.rs @@ -1,15 +1,15 @@ use crate::formats::visit_2x2::{Image2x2Visitor, visit}; -use crate::formats::{I420Block, I420Src}; +use crate::formats::yuv420::{Yuv420Block, Yuv420Src}; use crate::planes::read_planes_mut; use crate::primitive::Primitive; use crate::vector::Vector; use crate::{ConvertError, ImageMut, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct NV12Writer<'a, P, S> +pub(crate) struct Write2Plane<'a, P, S> where P: Primitive, - S: I420Src, + S: Yuv420Src, { y: &'a mut [u8], uv: &'a mut [u8], @@ -24,10 +24,10 @@ where _m: PhantomData<&'a mut [P]>, } -impl<'a, P, S> NV12Writer<'a, P, S> +impl<'a, P, S> Write2Plane<'a, P, S> where P: Primitive, - S: I420Src, + S: Yuv420Src, { pub(crate) fn write(dst: &'a mut dyn ImageMut, i420_src: S) -> Result<(), ConvertError> { dst.bounds_check()?; @@ -56,14 +56,14 @@ where } } -impl Image2x2Visitor for NV12Writer<'_, P, S> +impl Image2x2Visitor for Write2Plane<'_, P, S> where P: Primitive, - S: I420Src, + S: Yuv420Src, { #[inline(always)] unsafe fn visit(&mut self, x: usize, y: usize) { - let I420Block { + let Yuv420Block { y00, y01, y10, diff --git a/src/formats/i420/write.rs b/src/formats/yuv420/write_3plane.rs similarity index 89% rename from src/formats/i420/write.rs rename to src/formats/yuv420/write_3plane.rs index 7161227..06ca3d8 100644 --- a/src/formats/i420/write.rs +++ b/src/formats/yuv420/write_3plane.rs @@ -1,15 +1,15 @@ -use super::{I420Block, I420Src}; use crate::formats::visit_2x2::{Image2x2Visitor, visit}; +use crate::formats::yuv420::{Yuv420Block, Yuv420Src}; use crate::planes::read_planes_mut; use crate::primitive::Primitive; use crate::vector::Vector; use crate::{ConvertError, ImageMut, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct I420Writer<'a, P, S> +pub(crate) struct Write3Plane<'a, P, S> where P: Primitive, - S: I420Src, + S: Yuv420Src, { y: &'a mut [u8], u: &'a mut [u8], @@ -26,10 +26,10 @@ where _m: PhantomData<&'a mut [P]>, } -impl<'a, P, S> I420Writer<'a, P, S> +impl<'a, P, S> Write3Plane<'a, P, S> where P: Primitive, - S: I420Src, + S: Yuv420Src, { pub(crate) fn write(dst: &'a mut dyn ImageMut, i420_src: S) -> Result<(), ConvertError> { dst.bounds_check()?; @@ -60,14 +60,14 @@ where } } -impl Image2x2Visitor for I420Writer<'_, P, S> +impl Image2x2Visitor for Write3Plane<'_, P, S> where P: Primitive, - S: I420Src, + S: Yuv420Src, { #[inline(always)] unsafe fn visit(&mut self, x: usize, y: usize) { - let I420Block { + let Yuv420Block { y00, y01, y10, diff --git a/src/formats/i422/from_rgb.rs b/src/formats/yuv422/from_rgb.rs similarity index 88% rename from src/formats/i422/from_rgb.rs rename to src/formats/yuv422/from_rgb.rs index 5a07efb..01ba4d2 100644 --- a/src/formats/i422/from_rgb.rs +++ b/src/formats/yuv422/from_rgb.rs @@ -1,9 +1,11 @@ -use super::{I422Block, I422Src}; -use crate::formats::rgba::{RgbaBlock, RgbaPixel, RgbaSrc}; +use super::Yuv422Block; +use crate::formats::rgb::{RgbaBlock, RgbaPixel, RgbaSrc}; +use crate::formats::yuv422::Yuv422Src; use crate::vector::Vector; use crate::{ColorInfo, ColorSpace, ColorTransfer, ConvertError}; -pub(crate) struct RgbToI422 { +/// RGB to YUV422 converter source +pub(crate) struct FromRgb { rgba_src: S, space: ColorSpace, transfer: ColorTransfer, @@ -11,7 +13,7 @@ pub(crate) struct RgbToI422 { full_range: bool, } -impl RgbToI422 { +impl FromRgb { pub(crate) fn new(color: &ColorInfo, rgba_src: S) -> Result { let ColorInfo::YUV(yuv) = color else { return Err(ConvertError::InvalidColorInfo); @@ -67,9 +69,9 @@ impl RgbToI422 { } } -impl I422Src for RgbToI422 { +impl Yuv422Src for FromRgb { #[inline(always)] - unsafe fn read(&mut self, x: usize, y: usize) -> I422Block { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv422Block { let RgbaBlock { px00, px01, @@ -80,7 +82,7 @@ impl I422Src for RgbToI422 { let ([y00, y01], u0, v0) = self.convert_rgb_to_yuv(px00, px01); let ([y10, y11], u1, v1) = self.convert_rgb_to_yuv(px10, px11); - I422Block { + Yuv422Block { y00, y01, y10, diff --git a/src/formats/yuv422/mod.rs b/src/formats/yuv422/mod.rs new file mode 100644 index 0000000..ef93b3d --- /dev/null +++ b/src/formats/yuv422/mod.rs @@ -0,0 +1,31 @@ +use crate::vector::Vector; + +mod from_rgb; +mod read_1plane; +mod read_3plane; +mod to_rgb; +mod write_1plane; +mod write_3plane; + +pub(crate) use from_rgb::FromRgb; +pub(crate) use read_1plane::Read1Plane; +pub(crate) use read_3plane::Read3Plane; +pub(crate) use to_rgb::ToRgb; +pub(crate) use write_1plane::Write1Plane; +pub(crate) use write_3plane::Write3Plane; + +pub(crate) struct Yuv422Block { + pub(crate) y00: V, + pub(crate) y01: V, + pub(crate) y10: V, + pub(crate) y11: V, + + pub(crate) u0: V, + pub(crate) u1: V, + pub(crate) v0: V, + pub(crate) v1: V, +} + +pub(crate) trait Yuv422Src { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv422Block; +} diff --git a/src/formats/yuyv/read.rs b/src/formats/yuv422/read_1plane.rs similarity index 87% rename from src/formats/yuyv/read.rs rename to src/formats/yuv422/read_1plane.rs index f59dddd..c327f05 100644 --- a/src/formats/yuyv/read.rs +++ b/src/formats/yuv422/read_1plane.rs @@ -1,10 +1,11 @@ +use crate::formats::yuv422::{Yuv422Block, Yuv422Src}; use crate::planes::read_planes; use crate::primitive::Primitive; use crate::vector::Vector; -use crate::{ConvertError, I422Block, I422Src, ImageRef, ImageRefExt}; +use crate::{ConvertError, ImageRef, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct YUYVReader<'a, P: Primitive> { +pub(crate) struct Read1Plane<'a, P: Primitive> { yuyv: &'a [u8], yuyv_stride: usize, @@ -14,7 +15,7 @@ pub(crate) struct YUYVReader<'a, P: Primitive> { _m: PhantomData<&'a [P]>, } -impl<'a, P: Primitive> YUYVReader<'a, P> { +impl<'a, P: Primitive> Read1Plane<'a, P> { pub(crate) fn new(src: &'a dyn ImageRef) -> Result { src.bounds_check()?; @@ -36,9 +37,9 @@ impl<'a, P: Primitive> YUYVReader<'a, P> { } } -impl I422Src for YUYVReader<'_, P> { +impl Yuv422Src for Read1Plane<'_, P> { #[inline(always)] - unsafe fn read(&mut self, x: usize, y: usize) -> I422Block { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv422Block { let offset0 = y * self.yuyv_stride + x * 2 * P::SIZE; let offset1 = (y + 1) * self.yuyv_stride + x * 2 * P::SIZE; @@ -62,7 +63,7 @@ impl I422Src for YUYVReader<'_, P> { let v0 = v0.vdivf(self.max_value); let v1 = v1.vdivf(self.max_value); - I422Block { + Yuv422Block { y00, y01, y10, diff --git a/src/formats/i422/read.rs b/src/formats/yuv422/read_3plane.rs similarity index 90% rename from src/formats/i422/read.rs rename to src/formats/yuv422/read_3plane.rs index 4e7a8ca..db06d71 100644 --- a/src/formats/i422/read.rs +++ b/src/formats/yuv422/read_3plane.rs @@ -1,11 +1,11 @@ -use super::{I422Block, I422Src}; +use crate::formats::yuv422::{Yuv422Block, Yuv422Src}; use crate::planes::read_planes; use crate::primitive::Primitive; use crate::vector::Vector; use crate::{ConvertError, ImageRef, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct I422Reader<'a, P: Primitive> { +pub(crate) struct Read3Plane<'a, P: Primitive> { y: &'a [u8], u: &'a [u8], v: &'a [u8], @@ -19,7 +19,7 @@ pub(crate) struct I422Reader<'a, P: Primitive> { _m: PhantomData<&'a [P]>, } -impl<'a, P: Primitive> I422Reader<'a, P> { +impl<'a, P: Primitive> Read3Plane<'a, P> { pub(crate) fn new(src: &'a dyn ImageRef) -> Result { src.bounds_check()?; @@ -38,9 +38,9 @@ impl<'a, P: Primitive> I422Reader<'a, P> { } } -impl I422Src for I422Reader<'_, P> { +impl Yuv422Src for Read3Plane<'_, P> { #[inline(always)] - unsafe fn read(&mut self, x: usize, y: usize) -> I422Block { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv422Block { let y00_offset = (y * self.y_stride) + x * P::SIZE; let y10_offset = ((y + 1) * self.y_stride) + x * P::SIZE; @@ -74,7 +74,7 @@ impl I422Src for I422Reader<'_, P> { let v0 = v0.vdivf(self.max_value); let v1 = v1.vdivf(self.max_value); - I422Block { + Yuv422Block { y00, y01, y10, diff --git a/src/formats/i422/to_rgb.rs b/src/formats/yuv422/to_rgb.rs similarity index 87% rename from src/formats/i422/to_rgb.rs rename to src/formats/yuv422/to_rgb.rs index 11697e0..a265b8b 100644 --- a/src/formats/i422/to_rgb.rs +++ b/src/formats/yuv422/to_rgb.rs @@ -1,10 +1,12 @@ -use super::{I422Block, I422Src}; -use crate::formats::rgba::{RgbaBlock, RgbaPixel, RgbaSrc}; +use super::Yuv422Block; +use crate::formats::rgb::{RgbaBlock, RgbaPixel, RgbaSrc}; +use crate::formats::yuv422::Yuv422Src; use crate::vector::Vector; use crate::{ColorInfo, ColorSpace, ColorTransfer, ConvertError}; -pub(crate) struct I422ToRgb { - i422_src: S, +/// YUV 422 to RGB converter source +pub(crate) struct ToRgb { + yuv422_src: S, space: ColorSpace, transfer: ColorTransfer, @@ -12,14 +14,14 @@ pub(crate) struct I422ToRgb { full_range: bool, } -impl I422ToRgb { - pub(crate) fn new(color: &ColorInfo, i422_src: S) -> Result { +impl ToRgb { + pub(crate) fn new(color: &ColorInfo, yuv422_src: S) -> Result { let ColorInfo::YUV(yuv) = color else { return Err(ConvertError::InvalidColorInfo); }; Ok(Self { - i422_src, + yuv422_src, space: yuv.space, transfer: yuv.transfer, xyz_to_rgb: yuv.primaries.xyz_to_rgb_mat(), @@ -28,10 +30,10 @@ impl I422ToRgb { } } -impl RgbaSrc for I422ToRgb { +impl RgbaSrc for ToRgb { #[inline(always)] unsafe fn read(&mut self, x: usize, y: usize) -> RgbaBlock { - let I422Block { + let Yuv422Block { mut y00, mut y01, mut y10, @@ -40,7 +42,7 @@ impl RgbaSrc for I422ToRgb { mut u1, mut v0, mut v1, - } = self.i422_src.read::(x, y); + } = self.yuv422_src.read::(x, y); // If the YUV components don't use the full range of u8 scale them to the full range // Y 16..=235 -> 0..255 Y = (1.164 * (Y - 16)) diff --git a/src/formats/yuyv/write.rs b/src/formats/yuv422/write_1plane.rs similarity index 88% rename from src/formats/yuyv/write.rs rename to src/formats/yuv422/write_1plane.rs index 36b5093..b5fcebd 100644 --- a/src/formats/yuyv/write.rs +++ b/src/formats/yuv422/write_1plane.rs @@ -1,14 +1,15 @@ use crate::formats::visit_2x2::{Image2x2Visitor, visit}; +use crate::formats::yuv422::{Yuv422Block, Yuv422Src}; use crate::planes::read_planes_mut; use crate::primitive::Primitive; use crate::vector::Vector; -use crate::{ConvertError, I422Block, I422Src, ImageMut, ImageRefExt}; +use crate::{ConvertError, ImageMut, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct YUYVWriter<'a, P, S> +pub(crate) struct Write1Plane<'a, P, S> where P: Primitive, - S: I422Src, + S: Yuv422Src, { yuyv: &'a mut [u8], @@ -21,10 +22,10 @@ where _m: PhantomData<&'a mut [P]>, } -impl<'a, P, S> YUYVWriter<'a, P, S> +impl<'a, P, S> Write1Plane<'a, P, S> where P: Primitive, - S: I422Src, + S: Yuv422Src, { pub(crate) fn write(dst: &'a mut dyn ImageMut, i422_src: S) -> Result<(), ConvertError> { dst.bounds_check()?; @@ -60,14 +61,14 @@ where } } -impl Image2x2Visitor for YUYVWriter<'_, P, S> +impl Image2x2Visitor for Write1Plane<'_, P, S> where P: Primitive, - S: I422Src, + S: Yuv422Src, { #[inline(always)] unsafe fn visit(&mut self, x: usize, y: usize) { - let I422Block { + let Yuv422Block { y00, y01, y10, diff --git a/src/formats/i422/write.rs b/src/formats/yuv422/write_3plane.rs similarity index 90% rename from src/formats/i422/write.rs rename to src/formats/yuv422/write_3plane.rs index 4367433..4b34e3a 100644 --- a/src/formats/i422/write.rs +++ b/src/formats/yuv422/write_3plane.rs @@ -1,15 +1,15 @@ -use super::{I422Block, I422Src}; use crate::formats::visit_2x2::{Image2x2Visitor, visit}; +use crate::formats::yuv422::{Yuv422Block, Yuv422Src}; use crate::planes::read_planes_mut; use crate::primitive::Primitive; use crate::vector::Vector; use crate::{ConvertError, ImageMut, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct I422Writer<'a, P, S> +pub(crate) struct Write3Plane<'a, P, S> where P: Primitive, - S: I422Src, + S: Yuv422Src, { y: &'a mut [u8], u: &'a mut [u8], @@ -26,10 +26,10 @@ where _m: PhantomData<&'a mut [P]>, } -impl<'a, P, S> I422Writer<'a, P, S> +impl<'a, P, S> Write3Plane<'a, P, S> where P: Primitive, - S: I422Src, + S: Yuv422Src, { pub(crate) fn write(dst: &'a mut dyn ImageMut, i422_src: S) -> Result<(), ConvertError> { dst.bounds_check()?; @@ -60,14 +60,14 @@ where } } -impl Image2x2Visitor for I422Writer<'_, P, S> +impl Image2x2Visitor for Write3Plane<'_, P, S> where P: Primitive, - S: I422Src, + S: Yuv422Src, { #[inline(always)] unsafe fn visit(&mut self, x: usize, y: usize) { - let I422Block { + let Yuv422Block { y00, y01, y10, diff --git a/src/formats/i444/from_rgb.rs b/src/formats/yuv444/from_rgb.rs similarity index 82% rename from src/formats/i444/from_rgb.rs rename to src/formats/yuv444/from_rgb.rs index 152454e..cf75360 100644 --- a/src/formats/i444/from_rgb.rs +++ b/src/formats/yuv444/from_rgb.rs @@ -1,11 +1,12 @@ -use super::{I444Block, I444Src}; +use super::{Yuv444Block, Yuv444Src}; use crate::color::ColorInfo; -use crate::formats::i444::I444Pixel; -use crate::formats::rgba::{RgbaPixel, RgbaSrc}; +use crate::formats::rgb::{RgbaPixel, RgbaSrc}; +use crate::formats::yuv444::Yuv444Pixel; use crate::vector::Vector; use crate::{ColorSpace, ColorTransfer, ConvertError}; -pub(crate) struct RgbToI444 { +/// RGB to YUV444 converter source +pub(crate) struct FromRgb { rgba_src: S, space: ColorSpace, transfer: ColorTransfer, @@ -13,7 +14,7 @@ pub(crate) struct RgbToI444 { full_range: bool, } -impl RgbToI444 { +impl FromRgb { pub(crate) fn new(color: &ColorInfo, rgba_src: S) -> Result { let ColorInfo::YUV(yuv) = color else { return Err(ConvertError::InvalidColorInfo); @@ -29,7 +30,7 @@ impl RgbToI444 { } #[inline(always)] - unsafe fn convert_rgb_to_yuv(&self, px: RgbaPixel) -> I444Pixel { + unsafe fn convert_rgb_to_yuv(&self, px: RgbaPixel) -> Yuv444Pixel { let (mut y, mut u, mut v) = self.space .rgb_to_yuv(self.transfer, self.rgb_to_xyz, px.r, px.g, px.b); @@ -50,16 +51,16 @@ impl RgbToI444 { v = v16.vadd(v.vmul(uv_scale)); } - I444Pixel { y, u, v } + Yuv444Pixel { y, u, v } } } -impl I444Src for RgbToI444 { +impl Yuv444Src for FromRgb { #[inline(always)] - unsafe fn read(&mut self, x: usize, y: usize) -> I444Block { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv444Block { let block = self.rgba_src.read(x, y); - I444Block { + Yuv444Block { px00: self.convert_rgb_to_yuv(block.px00), px01: self.convert_rgb_to_yuv(block.px01), px10: self.convert_rgb_to_yuv(block.px10), diff --git a/src/formats/yuv444/mod.rs b/src/formats/yuv444/mod.rs new file mode 100644 index 0000000..c242511 --- /dev/null +++ b/src/formats/yuv444/mod.rs @@ -0,0 +1,29 @@ +use crate::vector::Vector; + +mod from_rgb; +mod to_rgb; + +mod read_3plane; +mod write_3plane; + +pub(crate) use from_rgb::FromRgb; +pub(crate) use read_3plane::Read3Plane; +pub(crate) use to_rgb::ToRgb; +pub(crate) use write_3plane::Write3Plane; + +pub(crate) struct Yuv444Block { + pub(crate) px00: Yuv444Pixel, + pub(crate) px01: Yuv444Pixel, + pub(crate) px10: Yuv444Pixel, + pub(crate) px11: Yuv444Pixel, +} + +pub(crate) struct Yuv444Pixel { + pub(crate) y: V, + pub(crate) u: V, + pub(crate) v: V, +} + +pub(crate) trait Yuv444Src { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv444Block; +} diff --git a/src/formats/i444/read.rs b/src/formats/yuv444/read_3plane.rs similarity index 87% rename from src/formats/i444/read.rs rename to src/formats/yuv444/read_3plane.rs index e495f0d..79d90fa 100644 --- a/src/formats/i444/read.rs +++ b/src/formats/yuv444/read_3plane.rs @@ -1,11 +1,11 @@ -use super::{I444Block, I444Src}; +use crate::formats::yuv444::{Yuv444Block, Yuv444Pixel, Yuv444Src}; use crate::planes::read_planes; use crate::primitive::Primitive; use crate::vector::Vector; -use crate::{ConvertError, I444Pixel, ImageRef, ImageRefExt}; +use crate::{ConvertError, ImageRef, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct I444Reader<'a, P: Primitive> { +pub(crate) struct Read3Plane<'a, P: Primitive> { y: &'a [u8], u: &'a [u8], v: &'a [u8], @@ -19,7 +19,7 @@ pub(crate) struct I444Reader<'a, P: Primitive> { _m: PhantomData<&'a [P]>, } -impl<'a, P: Primitive> I444Reader<'a, P> { +impl<'a, P: Primitive> Read3Plane<'a, P> { pub(crate) fn new(src: &'a dyn ImageRef) -> Result { src.bounds_check()?; @@ -38,9 +38,9 @@ impl<'a, P: Primitive> I444Reader<'a, P> { } } -impl I444Src for I444Reader<'_, P> { +impl Yuv444Src for Read3Plane<'_, P> { #[inline(always)] - unsafe fn read(&mut self, x: usize, y: usize) -> I444Block { + unsafe fn read(&mut self, x: usize, y: usize) -> Yuv444Block { let y00_offset = (y * self.y_stride) + x * P::SIZE; let y10_offset = ((y + 1) * self.y_stride) + x * P::SIZE; @@ -84,23 +84,23 @@ impl I444Src for I444Reader<'_, P> { let v10 = v10.vdivf(self.max_value); let v11 = v11.vdivf(self.max_value); - I444Block { - px00: I444Pixel { + Yuv444Block { + px00: Yuv444Pixel { y: y00, u: u00, v: v00, }, - px01: I444Pixel { + px01: Yuv444Pixel { y: y01, u: u01, v: v01, }, - px10: I444Pixel { + px10: Yuv444Pixel { y: y10, u: u10, v: v10, }, - px11: I444Pixel { + px11: Yuv444Pixel { y: y11, u: u11, v: v11, diff --git a/src/formats/i444/to_rgb.rs b/src/formats/yuv444/to_rgb.rs similarity index 77% rename from src/formats/i444/to_rgb.rs rename to src/formats/yuv444/to_rgb.rs index a8d3982..e86bda6 100644 --- a/src/formats/i444/to_rgb.rs +++ b/src/formats/yuv444/to_rgb.rs @@ -1,11 +1,12 @@ -use super::{I444Block, I444Pixel, I444Src}; +use super::{Yuv444Block, Yuv444Pixel, Yuv444Src}; use crate::color::ColorInfo; -use crate::formats::rgba::{RgbaBlock, RgbaPixel, RgbaSrc}; +use crate::formats::rgb::{RgbaBlock, RgbaPixel, RgbaSrc}; use crate::vector::Vector; use crate::{ColorSpace, ColorTransfer, ConvertError}; -pub(crate) struct I444ToRgb { - i444_src: S, +/// YUV 444 to RGB converter source +pub(crate) struct ToRgb { + yuv444_src: S, space: ColorSpace, transfer: ColorTransfer, @@ -13,14 +14,14 @@ pub(crate) struct I444ToRgb { full_range: bool, } -impl I444ToRgb { - pub(crate) fn new(color: &ColorInfo, i444_src: S) -> Result { +impl ToRgb { + pub(crate) fn new(color: &ColorInfo, yuv444_src: S) -> Result { let ColorInfo::YUV(yuv) = color else { return Err(ConvertError::InvalidColorInfo); }; Ok(Self { - i444_src, + yuv444_src, space: yuv.space, transfer: yuv.transfer, xyz_to_rgb: yuv.primaries.xyz_to_rgb_mat(), @@ -29,8 +30,8 @@ impl I444ToRgb { } #[inline(always)] - unsafe fn convert_yuv_to_rgb(&self, px: I444Pixel) -> RgbaPixel { - let I444Pixel { + unsafe fn convert_yuv_to_rgb(&self, px: Yuv444Pixel) -> RgbaPixel { + let Yuv444Pixel { mut y, mut u, mut v, @@ -70,15 +71,15 @@ impl I444ToRgb { } } -impl RgbaSrc for I444ToRgb { +impl RgbaSrc for ToRgb { #[inline(always)] unsafe fn read(&mut self, x: usize, y: usize) -> RgbaBlock { - let I444Block { + let Yuv444Block { px00, px01, px10, px11, - } = self.i444_src.read::(x, y); + } = self.yuv444_src.read::(x, y); RgbaBlock { px00: self.convert_yuv_to_rgb(px00), diff --git a/src/formats/i444/write.rs b/src/formats/yuv444/write_3plane.rs similarity index 87% rename from src/formats/i444/write.rs rename to src/formats/yuv444/write_3plane.rs index 7dd0550..1cf9440 100644 --- a/src/formats/i444/write.rs +++ b/src/formats/yuv444/write_3plane.rs @@ -1,15 +1,15 @@ -use super::{I444Block, I444Src}; use crate::formats::visit_2x2::{Image2x2Visitor, visit}; +use crate::formats::yuv444::{Yuv444Block, Yuv444Src}; use crate::planes::read_planes_mut; use crate::primitive::Primitive; use crate::vector::Vector; use crate::{ConvertError, ImageMut, ImageRefExt}; use std::marker::PhantomData; -pub(crate) struct I444Writer<'a, P, S> +pub(crate) struct Write3Plane<'a, P, S> where P: Primitive, - S: I444Src, + S: Yuv444Src, { y: &'a mut [u8], u: &'a mut [u8], @@ -21,15 +21,15 @@ where max_value: f32, - i444_src: S, + yuv444_src: S, _m: PhantomData<&'a mut [P]>, } -impl<'a, P, S> I444Writer<'a, P, S> +impl<'a, P, S> Write3Plane<'a, P, S> where P: Primitive, - S: I444Src, + S: Yuv444Src, { pub(crate) fn write(dst: &'a mut dyn ImageMut, i444_src: S) -> Result<(), ConvertError> { dst.bounds_check()?; @@ -51,7 +51,7 @@ where u_stride, v_stride, max_value: crate::formats::max_value_for_bits(dst_format.bits_per_component()), - i444_src, + yuv444_src: i444_src, _m: PhantomData, }, ); @@ -60,16 +60,16 @@ where } } -impl Image2x2Visitor for I444Writer<'_, P, S> +impl Image2x2Visitor for Write3Plane<'_, P, S> where P: Primitive, - S: I444Src, + S: Yuv444Src, { #[inline(always)] unsafe fn visit(&mut self, x: usize, y: usize) { - let block = self.i444_src.read::(x, y); + let block = self.yuv444_src.read::(x, y); - let I444Block { + let Yuv444Block { px00, px01, px10, diff --git a/src/formats/yuyv/mod.rs b/src/formats/yuyv/mod.rs deleted file mode 100644 index 621dd67..0000000 --- a/src/formats/yuyv/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod read; -mod write; - -pub(crate) use read::YUYVReader; -pub(crate) use write::YUYVWriter; diff --git a/src/lib.rs b/src/lib.rs index 2f5aa17..8413034 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,32 @@ #![doc = include_str!("../README.md")] #![warn(unreachable_pub)] #![allow(unsafe_op_in_unsafe_fn)] +// TODO: actually feature gating every single function and use is impossible right now, so until then warnings +// for unused items are only enabled when all-formats is activated +#![cfg_attr(not(feature = "all-formats"), allow(unused))] + +#[cfg(not(any( + feature = "I420", + feature = "I422", + feature = "I444", + feature = "I010", + feature = "I012", + feature = "I210", + feature = "I212", + feature = "I410", + feature = "I412", + feature = "NV12", + feature = "P010", + feature = "P012", + feature = "YUYV", + feature = "RGBA", + feature = "BGRA", + feature = "ARGB", + feature = "ABGR", + feature = "RGB", + feature = "BGR", +)))] +compile_error!("At least one image format feature must be enabled"); use formats::*; @@ -96,76 +122,131 @@ fn read_any_to_rgba<'a>( use PixelFormat::*; match src.format() { - I420 => Ok(Box::new(I420ToRgb::new( + #[cfg(feature = "I420")] + I420 => Ok(Box::new(yuv420::ToRgb::new( &src.color(), - I420Reader::::new(src)?, + yuv420::Read3Plane::::new(src)?, )?)), - I422 => Ok(Box::new(I422ToRgb::new( + #[cfg(feature = "I422")] + I422 => Ok(Box::new(yuv422::ToRgb::new( &src.color(), - I422Reader::::new(src)?, + yuv422::Read3Plane::::new(src)?, )?)), - I444 => Ok(Box::new(I444ToRgb::new( + #[cfg(feature = "I444")] + I444 => Ok(Box::new(yuv444::ToRgb::new( &src.color(), - I444Reader::::new(src)?, + yuv444::Read3Plane::::new(src)?, )?)), - - I010 | I012 => Ok(Box::new(I420ToRgb::new( + #[cfg(feature = "I010")] + I010 => Ok(Box::new(yuv420::ToRgb::new( &src.color(), - I420Reader::::new(src)?, + yuv420::Read3Plane::::new(src)?, )?)), - I210 | I212 => Ok(Box::new(I422ToRgb::new( + #[cfg(feature = "I012")] + I012 => Ok(Box::new(yuv420::ToRgb::new( &src.color(), - I422Reader::::new(src)?, + yuv420::Read3Plane::::new(src)?, )?)), - I410 | I412 => Ok(Box::new(I444ToRgb::new( + #[cfg(feature = "I210")] + I210 => Ok(Box::new(yuv422::ToRgb::new( &src.color(), - I444Reader::::new(src)?, + yuv422::Read3Plane::::new(src)?, )?)), - - NV12 => Ok(Box::new(I420ToRgb::new( + #[cfg(feature = "I212")] + I212 => Ok(Box::new(yuv422::ToRgb::new( &src.color(), - NV12Reader::::new(src)?, + yuv422::Read3Plane::::new(src)?, )?)), - P010 | P012 => Ok(Box::new(I420ToRgb::new( + #[cfg(feature = "I410")] + I410 => Ok(Box::new(yuv444::ToRgb::new( &src.color(), - NV12Reader::::new(src)?, + yuv444::Read3Plane::::new(src)?, )?)), - YUYV => Ok(Box::new(I422ToRgb::new( + #[cfg(feature = "I412")] + I412 => Ok(Box::new(yuv444::ToRgb::new( &src.color(), - YUYVReader::::new(src)?, + yuv444::Read3Plane::::new(src)?, )?)), - - RGBA => Ok(Box::new(RgbaReader::::new(src)?)), - BGRA => Ok(Box::new(RgbaReader::::new(src)?)), - ARGB => Ok(Box::new(RgbaReader::::new(src)?)), - ABGR => Ok(Box::new(RgbaReader::::new(src)?)), - RGB => Ok(Box::new(RgbReader::::new(src)?)), - BGR => Ok(Box::new(RgbReader::::new(src)?)), + #[cfg(feature = "NV12")] + NV12 => Ok(Box::new(yuv420::ToRgb::new( + &src.color(), + yuv420::Read2Plane::::new(src)?, + )?)), + #[cfg(feature = "P010")] + P010 => Ok(Box::new(yuv420::ToRgb::new( + &src.color(), + yuv420::Read2Plane::::new(src)?, + )?)), + #[cfg(feature = "P012")] + P012 => Ok(Box::new(yuv420::ToRgb::new( + &src.color(), + yuv420::Read2Plane::::new(src)?, + )?)), + #[cfg(feature = "YUYV")] + YUYV => Ok(Box::new(yuv422::ToRgb::new( + &src.color(), + yuv422::Read1Plane::::new(src)?, + )?)), + #[cfg(feature = "RGBA")] + RGBA => Ok(Box::new(rgb::ReadRgba::::new(src)?)), + #[cfg(feature = "BGRA")] + BGRA => Ok(Box::new(rgb::ReadBgra::::new(src)?)), + #[cfg(feature = "ARGB")] + ARGB => Ok(Box::new(rgb::ReadArgb::::new(src)?)), + #[cfg(feature = "ABGR")] + ABGR => Ok(Box::new(rgb::ReadAbgr::::new(src)?)), + #[cfg(feature = "RGB")] + RGB => Ok(Box::new(rgb::ReadRgb::::new(src)?)), + #[cfg(feature = "BGR")] + BGR => Ok(Box::new(rgb::ReadBgr::::new(src)?)), } } #[inline(never)] -fn rgba_to_any(dst: &mut dyn ImageMut, reader: impl RgbaSrc) -> Result<(), ConvertError> { +fn rgba_to_any(dst: &mut dyn ImageMut, reader: impl rgb::RgbaSrc) -> Result<(), ConvertError> { use PixelFormat::*; - let dst_color = dst.color(); + let color = dst.color(); match dst.format() { - I420 => I420Writer::::write(dst, RgbToI420::new(&dst_color, reader)?), - I422 => I422Writer::::write(dst, RgbToI422::new(&dst_color, reader)?), - I444 => I444Writer::::write(dst, RgbToI444::new(&dst_color, reader)?), - I010 | I012 => I420Writer::::write(dst, RgbToI420::new(&dst_color, reader)?), - I210 | I212 => I422Writer::::write(dst, RgbToI422::new(&dst_color, reader)?), - I410 | I412 => I444Writer::::write(dst, RgbToI444::new(&dst_color, reader)?), - NV12 => NV12Writer::::write(dst, RgbToI420::new(&dst_color, reader)?), - P010 | P012 => NV12Writer::::write(dst, RgbToI420::new(&dst_color, reader)?), - YUYV => YUYVWriter::::write(dst, RgbToI422::new(&dst_color, reader)?), - RGBA => RgbaWriter::::write(dst, reader), - BGRA => RgbaWriter::::write(dst, reader), - ARGB => RgbaWriter::::write(dst, reader), - ABGR => RgbaWriter::::write(dst, reader), - RGB => RgbWriter::::write(dst, reader), - BGR => RgbWriter::::write(dst, reader), + #[cfg(feature = "I420")] + I420 => yuv420::Write3Plane::::write(dst, yuv420::FromRgb::new(&color, reader)?), + #[cfg(feature = "I422")] + I422 => yuv422::Write3Plane::::write(dst, yuv422::FromRgb::new(&color, reader)?), + #[cfg(feature = "I444")] + I444 => yuv444::Write3Plane::::write(dst, yuv444::FromRgb::new(&color, reader)?), + #[cfg(feature = "I010")] + I010 => yuv420::Write3Plane::::write(dst, yuv420::FromRgb::new(&color, reader)?), + #[cfg(feature = "I012")] + I012 => yuv420::Write3Plane::::write(dst, yuv420::FromRgb::new(&color, reader)?), + #[cfg(feature = "I210")] + I210 => yuv422::Write3Plane::::write(dst, yuv422::FromRgb::new(&color, reader)?), + #[cfg(feature = "I212")] + I212 => yuv422::Write3Plane::::write(dst, yuv422::FromRgb::new(&color, reader)?), + #[cfg(feature = "I410")] + I410 => yuv444::Write3Plane::::write(dst, yuv444::FromRgb::new(&color, reader)?), + #[cfg(feature = "I412")] + I412 => yuv444::Write3Plane::::write(dst, yuv444::FromRgb::new(&color, reader)?), + #[cfg(feature = "NV12")] + NV12 => yuv420::Write2Plane::::write(dst, yuv420::FromRgb::new(&color, reader)?), + #[cfg(feature = "P010")] + P010 => yuv420::Write2Plane::::write(dst, yuv420::FromRgb::new(&color, reader)?), + #[cfg(feature = "P012")] + P012 => yuv420::Write2Plane::::write(dst, yuv420::FromRgb::new(&color, reader)?), + #[cfg(feature = "YUYV")] + YUYV => yuv422::Write1Plane::::write(dst, yuv422::FromRgb::new(&color, reader)?), + #[cfg(feature = "RGBA")] + RGBA => rgb::WriteRgba::::write(dst, reader), + #[cfg(feature = "BGRA")] + BGRA => rgb::WriteBgra::::write(dst, reader), + #[cfg(feature = "ARGB")] + ARGB => rgb::WriteArgb::::write(dst, reader), + #[cfg(feature = "ABGR")] + ABGR => rgb::WriteAbgr::::write(dst, reader), + #[cfg(feature = "RGB")] + RGB => rgb::WriteRgb::::write(dst, reader), + #[cfg(feature = "BGR")] + BGR => rgb::WriteBgr::::write(dst, reader), } } diff --git a/src/pixel_format.rs b/src/pixel_format.rs index b8afa7a..be9475a 100644 --- a/src/pixel_format.rs +++ b/src/pixel_format.rs @@ -4,60 +4,79 @@ use crate::{InvalidNumberOfPlanesError, StrictApi as _, plane_decs::*, planes::r #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum PixelFormat { /// Y, U and V planes, 4:2:0 sub sampling, 8 bits per sample + #[cfg(feature = "I420")] I420, /// Y, U and V planes, 4:2:2 sub sampling, 8 bits per sample + #[cfg(feature = "I422")] I422, /// Y, U and V planes, 4:4:4 sub sampling, 8 bits per sample + #[cfg(feature = "I444")] I444, /// Y, U, and V planes, 4:2:0 sub sampling, 10 bits per sample + #[cfg(feature = "I010")] I010, /// Y, U, and V planes, 4:2:0 sub sampling, 12 bits per sample + #[cfg(feature = "I012")] I012, /// Y, U, and V planes, 4:2:2 sub sampling, 10 bits per sample + #[cfg(feature = "I210")] I210, /// Y, U, and V planes, 4:2:2 sub sampling, 10 bits per sample + #[cfg(feature = "I212")] I212, /// Y, U, and V planes, 4:4:4 sub sampling, 10 bits per sample + #[cfg(feature = "I410")] I410, /// Y, U, and V planes, 4:4:4 sub sampling, 12 bits per sample + #[cfg(feature = "I412")] I412, /// Y and interleaved UV planes, 4:2:0 sub sampling, 8 bits per sample + #[cfg(feature = "NV12")] NV12, /// Y and interleaved UV planes, 4:2:0 sub sampling, 10 bits per sample + #[cfg(feature = "P010")] P010, /// Y and interleaved UV planes, 4:2:0 sub sampling, 12 bits per sample + #[cfg(feature = "P012")] P012, /// Single YUYV, 4:2:2 sub sampling + #[cfg(feature = "YUYV")] YUYV, /// Single RGBA interleaved plane + #[cfg(feature = "RGBA")] RGBA, /// Single BGRA interleaved plane + #[cfg(feature = "BGRA")] BGRA, /// Single ARGB interleaved plane + #[cfg(feature = "ARGB")] ARGB, /// Single ABGR interleaved plane + #[cfg(feature = "ABGR")] ABGR, /// Single RGB interleaved plane + #[cfg(feature = "RGB")] RGB, /// Single BGR interleaved plane + #[cfg(feature = "BGR")] BGR, } @@ -140,42 +159,86 @@ impl PixelFormat { } match self { + #[cfg(feature = "I420")] I420 => bounds_check(I420_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "I422")] I422 => bounds_check(I422_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "I444")] I444 => bounds_check(I444_PLANES, read_planes(planes)?, width, height), - I010 | I012 => bounds_check(I01X_PLANES, read_planes(planes)?, width, height), - I210 | I212 => bounds_check(I21X_PLANES, read_planes(planes)?, width, height), - I410 | I412 => bounds_check(I41X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "I010")] + I010 => bounds_check(I01X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "I012")] + I012 => bounds_check(I01X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "I210")] + I210 => bounds_check(I21X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "I212")] + I212 => bounds_check(I21X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "I410")] + I410 => bounds_check(I41X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "I412")] + I412 => bounds_check(I41X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "NV12")] NV12 => bounds_check(NV12_PLANES, read_planes(planes)?, width, height), - P010 | P012 => bounds_check(P01X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "P010")] + P010 => bounds_check(P01X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "P012")] + P012 => bounds_check(P01X_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "YUYV")] YUYV => bounds_check(YUYV_PLANES, read_planes(planes)?, width, height), - RGBA | BGRA | ARGB | ABGR => { - bounds_check(RGBA_PLANES, read_planes(planes)?, width, height) - } - RGB | BGR => bounds_check(RGB_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "RGBA")] + RGBA => bounds_check(RGBA_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "BGRA")] + BGRA => bounds_check(RGBA_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "ARGB")] + ARGB => bounds_check(RGBA_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "ABGR")] + ABGR => bounds_check(RGBA_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "RGB")] + RGB => bounds_check(RGB_PLANES, read_planes(planes)?, width, height), + #[cfg(feature = "BGR")] + BGR => bounds_check(RGB_PLANES, read_planes(planes)?, width, height), } } pub fn bits_per_component(&self) -> usize { match self { + #[cfg(feature = "I420")] PixelFormat::I420 => 8, + #[cfg(feature = "I422")] PixelFormat::I422 => 8, + #[cfg(feature = "I444")] PixelFormat::I444 => 8, + #[cfg(feature = "I010")] PixelFormat::I010 => 10, + #[cfg(feature = "I012")] PixelFormat::I012 => 12, + #[cfg(feature = "I210")] PixelFormat::I210 => 10, + #[cfg(feature = "I212")] PixelFormat::I212 => 12, + #[cfg(feature = "I410")] PixelFormat::I410 => 10, + #[cfg(feature = "I412")] PixelFormat::I412 => 12, + #[cfg(feature = "NV12")] PixelFormat::NV12 => 8, + #[cfg(feature = "P010")] PixelFormat::P010 => 10, + #[cfg(feature = "P012")] PixelFormat::P012 => 12, + #[cfg(feature = "YUYV")] PixelFormat::YUYV => 8, + #[cfg(feature = "RGBA")] PixelFormat::RGBA => 8, + #[cfg(feature = "BGRA")] PixelFormat::BGRA => 8, + #[cfg(feature = "ARGB")] PixelFormat::ARGB => 8, + #[cfg(feature = "ABGR")] PixelFormat::ABGR => 8, + #[cfg(feature = "RGB")] PixelFormat::RGB => 8, + #[cfg(feature = "BGR")] PixelFormat::BGR => 8, } } @@ -184,17 +247,44 @@ impl PixelFormat { use PixelFormat::*; match self { + #[cfg(feature = "I420")] I420 => &I420_PLANES, + #[cfg(feature = "I422")] I422 => &I422_PLANES, + #[cfg(feature = "I444")] I444 => &I444_PLANES, - I010 | I012 => &I01X_PLANES, - I210 | I212 => &I21X_PLANES, - I410 | I412 => &I41X_PLANES, + #[cfg(feature = "I010")] + I010 => &I01X_PLANES, + #[cfg(feature = "I012")] + I012 => &I01X_PLANES, + #[cfg(feature = "I210")] + I210 => &I21X_PLANES, + #[cfg(feature = "I212")] + I212 => &I21X_PLANES, + #[cfg(feature = "I410")] + I410 => &I41X_PLANES, + #[cfg(feature = "I412")] + I412 => &I41X_PLANES, + #[cfg(feature = "NV12")] NV12 => &NV12_PLANES, - P010 | P012 => &P01X_PLANES, + #[cfg(feature = "P010")] + P010 => &P01X_PLANES, + #[cfg(feature = "P012")] + P012 => &P01X_PLANES, + #[cfg(feature = "YUYV")] YUYV => &YUYV_PLANES, - RGBA | BGRA | ARGB | ABGR => &RGBA_PLANES, - RGB | BGR => &RGB_PLANES, + #[cfg(feature = "RGBA")] + RGBA => &RGBA_PLANES, + #[cfg(feature = "BGRA")] + BGRA => &RGBA_PLANES, + #[cfg(feature = "ARGB")] + ARGB => &RGBA_PLANES, + #[cfg(feature = "ABGR")] + ABGR => &RGBA_PLANES, + #[cfg(feature = "RGB")] + RGB => &RGB_PLANES, + #[cfg(feature = "BGR")] + BGR => &RGB_PLANES, } } @@ -202,8 +292,44 @@ impl PixelFormat { use PixelFormat::*; [ - I420, I422, I444, I010, I012, I210, I212, I410, I412, NV12, P010, P012, YUYV, RGBA, - BGRA, ARGB, ABGR, RGB, BGR, + #[cfg(feature = "I420")] + I420, + #[cfg(feature = "I422")] + I422, + #[cfg(feature = "I444")] + I444, + #[cfg(feature = "I010")] + I010, + #[cfg(feature = "I012")] + I012, + #[cfg(feature = "I210")] + I210, + #[cfg(feature = "I212")] + I212, + #[cfg(feature = "I410")] + I410, + #[cfg(feature = "I412")] + I412, + #[cfg(feature = "NV12")] + NV12, + #[cfg(feature = "P010")] + P010, + #[cfg(feature = "P012")] + P012, + #[cfg(feature = "YUYV")] + YUYV, + #[cfg(feature = "RGBA")] + RGBA, + #[cfg(feature = "BGRA")] + BGRA, + #[cfg(feature = "ARGB")] + ARGB, + #[cfg(feature = "ABGR")] + ABGR, + #[cfg(feature = "RGB")] + RGB, + #[cfg(feature = "BGR")] + BGR, ] } } diff --git a/src/planes.rs b/src/planes.rs index ba324ff..4673427 100644 --- a/src/planes.rs +++ b/src/planes.rs @@ -59,27 +59,44 @@ pub fn infer( strides: Option<&[usize]>, ) -> impl Iterator { match format { + #[cfg(feature = "I420")] PixelFormat::I420 => ArrayIter::from(infer_i420(buf, width, height, strides)), + #[cfg(feature = "I422")] PixelFormat::I422 => ArrayIter::from(infer_i422(buf, width, height, strides)), + #[cfg(feature = "I444")] PixelFormat::I444 => ArrayIter::from(infer_i444(buf, width, height, strides)), - PixelFormat::I010 | PixelFormat::I012 => { - ArrayIter::from(infer_i01x(buf, width, height, strides)) - } - PixelFormat::I210 | PixelFormat::I212 => { - ArrayIter::from(infer_i21x(buf, width, height, strides)) - } - PixelFormat::I410 | PixelFormat::I412 => { - ArrayIter::from(infer_i41x(buf, width, height, strides)) - } + #[cfg(feature = "I010")] + PixelFormat::I010 => ArrayIter::from(infer_i01x(buf, width, height, strides)), + #[cfg(feature = "I012")] + PixelFormat::I012 => ArrayIter::from(infer_i01x(buf, width, height, strides)), + #[cfg(feature = "I210")] + PixelFormat::I210 => ArrayIter::from(infer_i21x(buf, width, height, strides)), + #[cfg(feature = "I212")] + PixelFormat::I212 => ArrayIter::from(infer_i21x(buf, width, height, strides)), + #[cfg(feature = "I410")] + PixelFormat::I410 => ArrayIter::from(infer_i41x(buf, width, height, strides)), + #[cfg(feature = "I412")] + PixelFormat::I412 => ArrayIter::from(infer_i41x(buf, width, height, strides)), + #[cfg(feature = "NV12")] PixelFormat::NV12 => ArrayIter::from(infer_nv12(buf, width, height, strides)), - PixelFormat::P010 | PixelFormat::P012 => { - ArrayIter::from(infer_p01x(buf, width, height, strides)) - } + #[cfg(feature = "P010")] + PixelFormat::P010 => ArrayIter::from(infer_p01x(buf, width, height, strides)), + #[cfg(feature = "P012")] + PixelFormat::P012 => ArrayIter::from(infer_p01x(buf, width, height, strides)), + #[cfg(feature = "YUYV")] PixelFormat::YUYV => ArrayIter::from([buf]), - PixelFormat::RGBA | PixelFormat::BGRA | PixelFormat::ARGB | PixelFormat::ABGR => { - ArrayIter::from([buf]) - } - PixelFormat::RGB | PixelFormat::BGR => ArrayIter::from([buf]), + #[cfg(feature = "RGBA")] + PixelFormat::RGBA => ArrayIter::from([buf]), + #[cfg(feature = "BGRA")] + PixelFormat::BGRA => ArrayIter::from([buf]), + #[cfg(feature = "ARGB")] + PixelFormat::ARGB => ArrayIter::from([buf]), + #[cfg(feature = "ABGR")] + PixelFormat::ABGR => ArrayIter::from([buf]), + #[cfg(feature = "RGB")] + PixelFormat::RGB => ArrayIter::from([buf]), + #[cfg(feature = "BGR")] + PixelFormat::BGR => ArrayIter::from([buf]), } } diff --git a/src/vector/avx2.rs b/src/vector/avx2.rs index 3373376..670a1b1 100644 --- a/src/vector/avx2.rs +++ b/src/vector/avx2.rs @@ -1,5 +1,5 @@ use super::Vector; -use crate::{DynRgbaReader, DynRgbaReaderSpec, RgbaBlock, arch::*}; +use crate::{DynRgbaReader, DynRgbaReaderSpec, arch::*, formats::rgb::RgbaBlock}; use std::mem::transmute; unsafe impl Vector for __m256 { diff --git a/src/vector/avx512.rs b/src/vector/avx512.rs index 394898b..94f77ec 100644 --- a/src/vector/avx512.rs +++ b/src/vector/avx512.rs @@ -1,5 +1,5 @@ use super::Vector; -use crate::{DynRgbaReader, DynRgbaReaderSpec, RgbaBlock, arch::*}; +use crate::{DynRgbaReader, DynRgbaReaderSpec, arch::*, formats::rgb::RgbaBlock}; use std::mem::transmute; unsafe impl Vector for __m512 { diff --git a/src/vector/mod.rs b/src/vector/mod.rs index 5c091fd..e716d38 100644 --- a/src/vector/mod.rs +++ b/src/vector/mod.rs @@ -1,4 +1,4 @@ -use crate::{DynRgbaReader, DynRgbaReaderSpec, RgbaBlock}; +use crate::{DynRgbaReader, DynRgbaReaderSpec, formats::rgb::RgbaBlock}; use std::fmt::Debug; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]