Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Lchuv support #223

Merged
merged 3 commits into from May 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion palette/src/equality.rs
Expand Up @@ -2,7 +2,9 @@ use approx::{AbsDiffEq, RelativeEq, UlpsEq};

use crate::float::Float;
use crate::white_point::WhitePoint;
use crate::{from_f64, FloatComponent, FromF64, Lab, LabHue, Lch, Luv, RgbHue, Xyz, Yxy};
use crate::{
from_f64, FloatComponent, FromF64, Lab, LabHue, Lch, Lchuv, Luv, LuvHue, RgbHue, Xyz, Yxy,
};

macro_rules! impl_eq {
( $self_ty: ident , [$($element: ident),+]) => {
Expand Down Expand Up @@ -66,6 +68,7 @@ impl_eq!(Yxy, [y, x, luma]);
impl_eq!(Lab, [l, a, b]);
impl_eq!(Luv, [l, u, v]);
impl_eq!(Lch, [l, chroma, hue]);
impl_eq!(Lchuv, [l, chroma, hue]);

// For hues, the difference is calculated and compared to zero. However due to
// the way floating point's work this is not so simple.
Expand Down Expand Up @@ -147,3 +150,4 @@ macro_rules! impl_eq_hue {

impl_eq_hue!(LabHue);
impl_eq_hue!(RgbHue);
impl_eq_hue!(LuvHue);
202 changes: 70 additions & 132 deletions palette/src/hues.rs
Expand Up @@ -256,7 +256,7 @@ macro_rules! make_hues {
Standard: Distribution<T>,
{
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $name<T> {
$name(rng.gen() * from_f64(360.0))
$name(rng.gen() * from_f64(360.0))
}
}
)+)
Expand Down Expand Up @@ -293,146 +293,84 @@ fn normalize_angle_positive<T: Float + FromF64>(deg: T) -> T {
deg - ((deg / c360).floor() * c360)
}

#[cfg(feature = "random")]
pub struct UniformLabHue<T>
where
T: Float + FromF64 + SampleUniform,
{
hue: Uniform<T>,
}

#[cfg(feature = "random")]
impl<T> SampleUniform for LabHue<T>
where
T: Float + FromF64 + SampleUniform,
{
type Sampler = UniformLabHue<T>;
}

#[cfg(feature = "random")]
impl<T> UniformSampler for UniformLabHue<T>
where
T: Float + FromF64 + SampleUniform,
{
type X = LabHue<T>;

fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let normalized_low = LabHue::to_positive_degrees(low);
let high = *high_b.borrow();
let normalized_high = LabHue::to_positive_degrees(high);

let normalized_high = if normalized_low >= normalized_high && low.0 < high.0 {
normalized_high + from_f64(360.0)
} else {
normalized_high
};

UniformLabHue {
hue: Uniform::new(normalized_low, normalized_high),
macro_rules! impl_uniform {
( $uni_ty: ident , $base_ty: ident) => {
#[cfg(feature = "random")]
pub struct $uni_ty<T>
where
T: Float + FromF64 + SampleUniform,
{
hue: Uniform<T>,
}
}

fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let normalized_low = LabHue::to_positive_degrees(low);
let high = *high_b.borrow();
let normalized_high = LabHue::to_positive_degrees(high);

let normalized_high = if normalized_low >= normalized_high && low.0 < high.0 {
normalized_high + from_f64(360.0)
} else {
normalized_high
};

UniformLabHue {
hue: Uniform::new_inclusive(normalized_low, normalized_high),
#[cfg(feature = "random")]
impl<T> SampleUniform for $base_ty<T>
where
T: Float + FromF64 + SampleUniform,
{
type Sampler = $uni_ty<T>;
}
}

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> LabHue<T> {
LabHue::from(self.hue.sample(rng) * from_f64(360.0))
}
}

#[cfg(feature = "random")]
pub struct UniformRgbHue<T>
where
T: Float + FromF64 + SampleUniform,
{
hue: Uniform<T>,
}

#[cfg(feature = "random")]
impl<T> SampleUniform for RgbHue<T>
where
T: Float + FromF64 + SampleUniform,
{
type Sampler = UniformRgbHue<T>;
}
#[cfg(feature = "random")]
impl<T> UniformSampler for $uni_ty<T>
where
T: Float + FromF64 + SampleUniform,
{
type X = $base_ty<T>;

fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let normalized_low = $base_ty::to_positive_degrees(low);
let high = *high_b.borrow();
let normalized_high = $base_ty::to_positive_degrees(high);

let normalized_high = if normalized_low >= normalized_high && low.0 < high.0 {
normalized_high + from_f64(360.0)
} else {
normalized_high
};

$uni_ty {
hue: Uniform::new(normalized_low, normalized_high),
}
}

#[cfg(feature = "random")]
impl<T> UniformSampler for UniformRgbHue<T>
where
T: Float + FromF64 + SampleUniform,
{
type X = RgbHue<T>;

fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let normalized_low = RgbHue::to_positive_degrees(low);
let high = *high_b.borrow();
let normalized_high = RgbHue::to_positive_degrees(high);

let normalized_high = if normalized_low >= normalized_high && low.0 < high.0 {
normalized_high + from_f64(360.0)
} else {
normalized_high
};

UniformRgbHue {
hue: Uniform::new(normalized_low, normalized_high),
}
}
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let normalized_low = $base_ty::to_positive_degrees(low);
let high = *high_b.borrow();
let normalized_high = $base_ty::to_positive_degrees(high);

let normalized_high = if normalized_low >= normalized_high && low.0 < high.0 {
normalized_high + from_f64(360.0)
} else {
normalized_high
};

$uni_ty {
hue: Uniform::new_inclusive(normalized_low, normalized_high),
}
}

fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let low = *low_b.borrow();
let normalized_low = RgbHue::to_positive_degrees(low);
let high = *high_b.borrow();
let normalized_high = RgbHue::to_positive_degrees(high);

let normalized_high = if normalized_low >= normalized_high && low.0 < high.0 {
normalized_high + from_f64(360.0)
} else {
normalized_high
};

UniformRgbHue {
hue: Uniform::new_inclusive(normalized_low, normalized_high),
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $base_ty<T> {
$base_ty::from(self.hue.sample(rng) * from_f64(360.0))
}
}
}

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> RgbHue<T> {
RgbHue::from(self.hue.sample(rng) * from_f64(360.0))
}
};
}

impl_uniform!(UniformLabHue, LabHue);
impl_uniform!(UniformRgbHue, RgbHue);
impl_uniform!(UniformLuvHue, LuvHue);

#[cfg(test)]
mod test {
use super::{normalize_angle, normalize_angle_positive};
Expand Down