Skip to content

Commit

Permalink
Implement grb
Browse files Browse the repository at this point in the history
Fixes #55
  • Loading branch information
kornelski committed Feb 7, 2023
1 parent 905adc6 commit fb667cc
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 27 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ default = ["as-bytes"]
# safe as_bytes() casts require a marker trait for non-padded, non-pointery types.
as-bytes = ["bytemuck"]
argb = []
grb = []

[badges]
travis-ci = { repository = "kornelski/rust-rgb" }
Expand Down
22 changes: 20 additions & 2 deletions src/alt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ pub struct BGRA<ComponentType, AlphaComponentType = ComponentType> {
pub a: AlphaComponentType,
}

#[cfg(feature = "argb")]
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg(feature = "argb")]
/// A+BGR
pub struct ABGR<ComponentType, AlphaComponentType = ComponentType> {
/// Alpha first
Expand All @@ -46,10 +46,10 @@ pub struct ABGR<ComponentType, AlphaComponentType = ComponentType> {
pub r: ComponentType,
}

#[cfg(feature = "argb")]
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg(feature = "argb")]
/// A+RGB
pub struct ARGB<ComponentType, AlphaComponentType = ComponentType> {
/// Alpha first
Expand Down Expand Up @@ -90,6 +90,24 @@ pub type ABGR16 = ABGR<u16>;
#[cfg(feature = "argb")]
pub type ARGB16 = ARGB<u16>;

#[cfg(feature = "grb")]
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
/// RGB with red-green swapped (may be useful for LEDs)
pub struct GRB<ComponentType> {
/// Green first
pub g: ComponentType,
/// Red
pub r: ComponentType,
/// Blue last
pub b: ComponentType,
}

/// 8-bit GRB
#[cfg(feature = "grb")]
pub type GRB8 = GRB<u8>;

////////////////////////////////////////

#[repr(C)]
Expand Down
4 changes: 4 additions & 0 deletions src/internal/convert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ as_pixels_impl!{RGB, 3}
as_pixels_impl!{RGBA, 4}
as_pixels_impl!{BGR, 3}
as_pixels_impl!{BGRA, 4}
#[cfg(feature = "grb")]
as_pixels_impl!{GRB, 3}
as_pixels_impl!{Gray, 1}
as_pixels_impl!{GrayAlpha, 2}
#[cfg(feature = "argb")]
Expand Down Expand Up @@ -288,6 +290,8 @@ reorder_impl_from!(@rgb RGB, BGR);
reorder_impl_from!(@rgba BGRA, RGBA);
#[cfg(feature = "argb")]
reorder_impl_from!(@rgba ABGR, RGBA);
#[cfg(feature = "grb")]
reorder_impl_from!(@rgb RGB, GRB);

impl<T: Clone> From<Gray<T>> for RGB<T> {
#[inline(always)]
Expand Down
6 changes: 6 additions & 0 deletions src/internal/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use core::ops::*;
use core::iter::Sum;
#[cfg(feature = "argb")]
use crate::alt::ARGB;
#[cfg(feature = "grb")]
use crate::alt::GRB;

macro_rules! impl_struct_ops_opaque {
($ty:ident => $($field:tt)+) => {
Expand Down Expand Up @@ -268,10 +270,14 @@ impl_scalar!{RGB}
impl_scalar!{RGBA}
#[cfg(feature = "argb")]
impl_scalar!{ARGB}
#[cfg(feature = "grb")]
impl_scalar!{GRB}
impl_scalar!{Gray}
impl_scalar!{GrayAlpha}

impl_struct_ops_opaque! {RGB => r g b}
#[cfg(feature = "grb")]
impl_struct_ops_opaque! {GRB => g r b}
impl_struct_ops_opaque! {Gray => 0}

impl_struct_ops_alpha! {RGBA => r g b a}
Expand Down
72 changes: 47 additions & 25 deletions src/internal/rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use crate::alt::BGRA;
use crate::RGB;
use crate::RGBA;
use core::fmt;
#[cfg(feature = "grb")]
use crate::alt::GRB;

impl<T> RGB<T> {
/// Convenience function for creating a new pixel
Expand Down Expand Up @@ -34,35 +36,13 @@ unsafe impl<T> crate::Zeroable for RGB<T> where T: crate::Zeroable {}
unsafe impl<T> crate::Zeroable for BGR<T> where T: crate::Zeroable {}

macro_rules! impl_rgb {
($RGB:ident, $RGBA:ident) => {
($RGB:ident) => {
impl<T: Clone> $RGB<T> {
/// Iterate over color components (R, G, and B)
#[inline(always)]
pub fn iter(&self) -> core::iter::Cloned<core::slice::Iter<'_, T>> {
self.as_slice().iter().cloned()
}

/// Convenience function for converting to RGBA
#[inline(always)]
pub fn alpha(&self, a: T) -> $RGBA<T> {
$RGBA {
r: self.r.clone(),
g: self.g.clone(),
b: self.b.clone(),
a,
}
}

/// Convenience function for converting to RGBA with alpha channel of a different type than type of the pixels
#[inline(always)]
pub fn new_alpha<A>(&self, a: A) -> $RGBA<T, A> {
$RGBA {
r: self.r.clone(),
g: self.g.clone(),
b: self.b.clone(),
a,
}
}
}

impl<T: Copy, B> ComponentMap<$RGB<B>, T, B> for $RGB<T> {
Expand Down Expand Up @@ -126,6 +106,35 @@ macro_rules! impl_rgb {
}
}

macro_rules! impl_rgb_to_alpha {
($RGB:ident, $RGBA:ident) => {
impl<T: Clone> $RGB<T> {
/// Convenience function for converting to RGBA
#[inline(always)]
pub fn alpha(&self, a: T) -> $RGBA<T> {
$RGBA {
r: self.r.clone(),
g: self.g.clone(),
b: self.b.clone(),
a,
}
}

/// Convenience function for converting to RGBA with alpha channel of a different type than type of the pixels
#[inline(always)]
pub fn new_alpha<A>(&self, a: A) -> $RGBA<T, A> {
$RGBA {
r: self.r.clone(),
g: self.g.clone(),
b: self.b.clone(),
a,
}
}
}
}
}


impl<T> core::iter::FromIterator<T> for RGB<T> {
/// Takes exactly 3 elements from the iterator and creates a new instance.
/// Panics if there are fewer elements in the iterator.
Expand All @@ -140,8 +149,12 @@ impl<T> core::iter::FromIterator<T> for RGB<T> {
}
}

impl_rgb!{RGB, RGBA}
impl_rgb!{BGR, BGRA}
impl_rgb!{RGB}
impl_rgb_to_alpha!{RGB, RGBA}
impl_rgb!{BGR}
impl_rgb_to_alpha!{BGR, BGRA}
#[cfg(feature = "grb")]
impl_rgb!{GRB}

impl<T: fmt::Display> fmt::Display for RGB<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down Expand Up @@ -183,6 +196,15 @@ impl<T: fmt::LowerHex> fmt::LowerHex for BGR<T> {
mod rgb_test {
use super::*;
use std;

#[test]
#[cfg(feature = "grb")]
fn grb_test() {
let grb = GRB {g:1,r:2,b:3}.map(|c| c * 2) + 1;
let rgb: crate::RGB8 = grb.into();
assert_eq!(rgb, RGB::new(5,3,7));
}

#[test]
fn sanity_check() {
let neg = RGB::new(1,2,3i32).map(|x| -x);
Expand Down

0 comments on commit fb667cc

Please sign in to comment.