Skip to content

Commit

Permalink
Merge #98
Browse files Browse the repository at this point in the history
98: Add conversion to and from component tuples r=Ogeon a=Ogeon

I took the opportunity to generalize some Alpha implementations as well.

Closes #87.

Co-authored-by: Erik Hedvall <[email protected]>
  • Loading branch information
bors[bot] and Ogeon committed May 26, 2018
2 parents a41f194 + 4d6e0fd commit 1d56a48
Show file tree
Hide file tree
Showing 9 changed files with 650 additions and 165 deletions.
86 changes: 68 additions & 18 deletions palette/src/hsl.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use num_traits::Float;
use approx::ApproxEq;
use num_traits::Float;

use std::ops::{Add, Sub};
use std::marker::PhantomData;
use std::any::TypeId;
use std::marker::PhantomData;
use std::ops::{Add, Sub};

use {cast, clamp, Alpha, Component, FromColor, GetHue, Hsv, Hue, IntoColor, Limited, Mix, Pixel,
RgbHue, Saturate, Shade, Xyz};
use rgb::{Rgb, RgbSpace};
use encoding::{Linear, Srgb};
use encoding::pixel::RawPixel;
use encoding::{Linear, Srgb};
use rgb::{Rgb, RgbSpace};
use {
cast, clamp, Alpha, Component, FromColor, GetHue, Hsv, Hue, IntoColor, Limited, Mix, Pixel,
RgbHue, Saturate, Shade, Xyz,
};

/// Linear HSL with an alpha component. See the [`Hsla` implementation in
/// `Alpha`](struct.Alpha.html#Hsla).
Expand All @@ -24,7 +26,8 @@ pub type Hsla<S = Srgb, T = f32> = Alpha<Hsl<S, T>, T>;
///especially good for operations like changing green to red, making a color
///more gray, or making it darker.
///
///See [HSV](struct.Hsv.html) for a very similar color space, with brightness instead of lightness.
///See [HSV](struct.Hsv.html) for a very similar color space, with brightness
/// instead of lightness.
#[derive(Debug, PartialEq, FromColor, Pixel)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[palette_internal]
Expand Down Expand Up @@ -105,6 +108,16 @@ where
}
}

/// Convert to a `(hue, saturation, lightness)` tuple.
pub fn into_components(self) -> (RgbHue<T>, T, T) {
(self.hue, self.saturation, self.lightness)
}

/// Convert from a `(hue, saturation, lightness)` tuple.
pub fn from_components<H: Into<RgbHue<T>>>((hue, saturation, lightness): (H, T, T)) -> Self {
Self::with_wp(hue, saturation, lightness)
}

fn from_hsl_internal<Sp: RgbSpace<WhitePoint = S::WhitePoint>>(hsl: Hsl<Sp, T>) -> Self {
if TypeId::of::<Sp::Primaries>() == TypeId::of::<S::Primaries>() {
hsl.reinterpret_as()
Expand Down Expand Up @@ -171,12 +184,13 @@ where
}

///<span id="Hsla"></span>[`Hsla`](type.Hsla.html) implementations.
impl<T> Alpha<Hsl<Srgb, T>, T>
impl<T, A> Alpha<Hsl<Srgb, T>, A>
where
T: Component + Float,
A: Component,
{
///HSL and transparency for linear sRGB.
pub fn new<H: Into<RgbHue<T>>>(hue: H, saturation: T, lightness: T, alpha: T) -> Hsla<Srgb, T> {
pub fn new<H: Into<RgbHue<T>>>(hue: H, saturation: T, lightness: T, alpha: A) -> Self {
Alpha {
color: Hsl::new(hue, saturation, lightness),
alpha: alpha,
Expand All @@ -185,23 +199,31 @@ where
}

///<span id="Hsla"></span>[`Hsla`](type.Hsla.html) implementations.
impl<S, T> Alpha<Hsl<S, T>, T>
impl<S, T, A> Alpha<Hsl<S, T>, A>
where
T: Component + Float,
A: Component,
S: RgbSpace,
{
///Linear HSL and transparency.
pub fn with_wp<H: Into<RgbHue<T>>>(
hue: H,
saturation: T,
lightness: T,
alpha: T,
) -> Hsla<S, T> {
pub fn with_wp<H: Into<RgbHue<T>>>(hue: H, saturation: T, lightness: T, alpha: A) -> Self {
Alpha {
color: Hsl::with_wp(hue, saturation, lightness),
alpha: alpha,
}
}

/// Convert to a `(hue, saturation, lightness, alpha)` tuple.
pub fn into_components(self) -> (RgbHue<T>, T, T, A) {
(self.hue, self.saturation, self.lightness, self.alpha)
}

/// Convert from a `(hue, saturation, lightness, alpha)` tuple.
pub fn from_components<H: Into<RgbHue<T>>>(
(hue, saturation, lightness, alpha): (H, T, T, A),
) -> Self {
Self::with_wp(hue, saturation, lightness, alpha)
}
}

impl<S, T> From<Xyz<S::WhitePoint, T>> for Hsl<S, T>
Expand Down Expand Up @@ -251,6 +273,34 @@ where
}
}

impl<S: RgbSpace, T: Component + Float, H: Into<RgbHue<T>>> From<(H, T, T)> for Hsl<S, T> {
fn from(components: (H, T, T)) -> Self {
Self::from_components(components)
}
}

impl<S: RgbSpace, T: Component + Float> Into<(RgbHue<T>, T, T)> for Hsl<S, T> {
fn into(self) -> (RgbHue<T>, T, T) {
self.into_components()
}
}

impl<S: RgbSpace, T: Component + Float, H: Into<RgbHue<T>>, A: Component> From<(H, T, T, A)>
for Alpha<Hsl<S, T>, A>
{
fn from(components: (H, T, T, A)) -> Self {
Self::from_components(components)
}
}

impl<S: RgbSpace, T: Component + Float, A: Component> Into<(RgbHue<T>, T, T, A)>
for Alpha<Hsl<S, T>, A>
{
fn into(self) -> (RgbHue<T>, T, T, A) {
self.into_components()
}
}

impl<S, T> Limited for Hsl<S, T>
where
T: Component + Float,
Expand Down Expand Up @@ -508,8 +558,8 @@ where
#[cfg(test)]
mod test {
use super::Hsl;
use {Hsv, LinSrgb};
use encoding::Srgb;
use {Hsv, LinSrgb};

#[test]
fn red() {
Expand Down
79 changes: 66 additions & 13 deletions palette/src/hsv.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use num_traits::Float;
use approx::ApproxEq;
use num_traits::Float;

use std::ops::{Add, Sub};
use std::marker::PhantomData;
use std::any::TypeId;
use std::marker::PhantomData;
use std::ops::{Add, Sub};

use encoding::pixel::RawPixel;
use encoding::{Linear, Srgb};
use rgb::{Rgb, RgbSpace};
use {cast, clamp};
use {Alpha, Hsl, Hwb, Xyz};
use {Component, FromColor, GetHue, Hue, Limited, Mix, Pixel, RgbHue, Saturate, Shade};
use {cast, clamp};
use rgb::{Rgb, RgbSpace};
use encoding::{Linear, Srgb};
use encoding::pixel::RawPixel;

/// Linear HSV with an alpha component. See the [`Hsva` implementation in
/// `Alpha`](struct.Alpha.html#Hsva).
Expand Down Expand Up @@ -105,6 +105,16 @@ where
}
}

/// Convert to a `(hue, saturation, value)` tuple.
pub fn into_components(self) -> (RgbHue<T>, T, T) {
(self.hue, self.saturation, self.value)
}

/// Convert from a `(hue, saturation, value)` tuple.
pub fn from_components<H: Into<RgbHue<T>>>((hue, saturation, value): (H, T, T)) -> Self {
Self::with_wp(hue, saturation, value)
}

fn from_hsv_internal<Sp: RgbSpace<WhitePoint = S::WhitePoint>>(hsv: Hsv<Sp, T>) -> Self {
if TypeId::of::<Sp::Primaries>() == TypeId::of::<S::Primaries>() {
hsv.reinterpret_as()
Expand Down Expand Up @@ -166,12 +176,13 @@ where
}

///<span id="Hsva"></span>[`Hsva`](type.Hsva.html) implementations.
impl<T> Alpha<Hsv<Srgb, T>, T>
impl<T, A> Alpha<Hsv<Srgb, T>, A>
where
T: Component + Float,
A: Component,
{
///HSV and transparency for linear sRGB.
pub fn new<H: Into<RgbHue<T>>>(hue: H, saturation: T, value: T, alpha: T) -> Hsva<Srgb, T> {
pub fn new<H: Into<RgbHue<T>>>(hue: H, saturation: T, value: T, alpha: A) -> Self {
Alpha {
color: Hsv::new(hue, saturation, value),
alpha: alpha,
Expand All @@ -180,18 +191,31 @@ where
}

///<span id="Hsva"></span>[`Hsva`](type.Hsva.html) implementations.
impl<S, T> Alpha<Hsv<S, T>, T>
impl<S, T, A> Alpha<Hsv<S, T>, A>
where
T: Component + Float,
A: Component,
S: RgbSpace,
{
///Linear HSV and transparency.
pub fn with_wp<H: Into<RgbHue<T>>>(hue: H, saturation: T, value: T, alpha: T) -> Hsva<S, T> {
pub fn with_wp<H: Into<RgbHue<T>>>(hue: H, saturation: T, value: T, alpha: A) -> Self {
Alpha {
color: Hsv::with_wp(hue, saturation, value),
alpha: alpha,
}
}

/// Convert to a `(hue, saturation, value, alpha)` tuple.
pub fn into_components(self) -> (RgbHue<T>, T, T, A) {
(self.hue, self.saturation, self.value, self.alpha)
}

/// Convert from a `(hue, saturation, value, alpha)` tuple.
pub fn from_components<H: Into<RgbHue<T>>>(
(hue, saturation, value, alpha): (H, T, T, A),
) -> Self {
Self::with_wp(hue, saturation, value, alpha)
}
}

impl<S, T> From<Xyz<S::WhitePoint, T>> for Hsv<S, T>
Expand Down Expand Up @@ -260,6 +284,34 @@ where
}
}

impl<S: RgbSpace, T: Component + Float, H: Into<RgbHue<T>>> From<(H, T, T)> for Hsv<S, T> {
fn from(components: (H, T, T)) -> Self {
Self::from_components(components)
}
}

impl<S: RgbSpace, T: Component + Float> Into<(RgbHue<T>, T, T)> for Hsv<S, T> {
fn into(self) -> (RgbHue<T>, T, T) {
self.into_components()
}
}

impl<S: RgbSpace, T: Component + Float, H: Into<RgbHue<T>>, A: Component> From<(H, T, T, A)>
for Alpha<Hsv<S, T>, A>
{
fn from(components: (H, T, T, A)) -> Self {
Self::from_components(components)
}
}

impl<S: RgbSpace, T: Component + Float, A: Component> Into<(RgbHue<T>, T, T, A)>
for Alpha<Hsv<S, T>, A>
{
fn into(self) -> (RgbHue<T>, T, T, A) {
self.into_components()
}
}

impl<S, T> Limited for Hsv<S, T>
where
T: Component + Float,
Expand Down Expand Up @@ -517,8 +569,8 @@ where
#[cfg(test)]
mod test {
use super::Hsv;
use {Hsl, LinSrgb};
use encoding::Srgb;
use {Hsl, LinSrgb};

#[test]
fn red() {
Expand Down Expand Up @@ -599,7 +651,8 @@ mod test {
#[cfg(feature = "serde")]
#[test]
fn deserialize() {
let deserialized: Hsv = ::serde_json::from_str(r#"{"hue":0.3,"saturation":0.8,"value":0.1}"#).unwrap();
let deserialized: Hsv =
::serde_json::from_str(r#"{"hue":0.3,"saturation":0.8,"value":0.1}"#).unwrap();

assert_eq!(deserialized, Hsv::new(0.3, 0.8, 0.1));
}
Expand Down
Loading

0 comments on commit 1d56a48

Please sign in to comment.