From d65aa944b93a4f5c33fadbf4f027a66ae97957e9 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 9 Jul 2013 22:50:20 +1000 Subject: [PATCH] Simplify color::channel traits --- src/color/channel.rs | 171 ++++++------------------------------------- src/color/color.rs | 3 +- src/color/hsv.rs | 26 +++---- src/color/rgb.rs | 17 +++-- 4 files changed, 45 insertions(+), 172 deletions(-) diff --git a/src/color/channel.rs b/src/color/channel.rs index a0822bd..da843bd 100644 --- a/src/color/channel.rs +++ b/src/color/channel.rs @@ -13,176 +13,47 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// A color channel -pub trait Channel: Num + ToChannel { - /// Convert a channel to the enclosing type - /// - /// # Example - /// - /// ~~~ - /// let chan: f32 = Channel::from(0xFFFFu16); - /// assert chan == 1.0f32; - /// ~~~ - pub fn from(val: T) -> Self; -} +pub trait Channel: Num { + pub fn from(chan: T) -> Self; -impl Channel for u8 { - #[inline] pub fn from(val: T) -> u8 { val.to_channel_u8() } -} - -impl Channel for u16 { - #[inline] pub fn from(val: T) -> u16 { val.to_channel_u16() } -} - -impl Channel for u32 { - #[inline] pub fn from(val: T) -> u32 { val.to_channel_u32() } -} - -impl Channel for u64 { - #[inline] pub fn from(val: T) -> u64 { val.to_channel_u64() } -} - -impl Channel for f32 { - #[inline] pub fn from(val: T) -> f32 { val.to_channel_f32() } -} - -impl Channel for f64 { - #[inline] pub fn from(val: T) -> f64 { val.to_channel_f64() } -} - -pub trait ToChannel: ToIntChannel + ToFloatChannel {} - -impl ToChannel for u8 {} - -impl ToChannel for u16 {} - -impl ToChannel for u32 {} - -impl ToChannel for u64 {} - -impl ToChannel for f32 {} - -impl ToChannel for f64 {} - -pub trait IntChannel: Int + Channel + ToIntChannel { - pub fn from(val: T) -> Self; -} - -impl IntChannel for u8 { - #[inline] pub fn from(val: T) -> u8 { val.to_channel_u8() } -} - -impl IntChannel for u16 { - #[inline] pub fn from(val: T) -> u16 { val.to_channel_u16() } -} - -impl IntChannel for u32 { - #[inline] pub fn from(val: T) -> u32 { val.to_channel_u32() } -} - -impl IntChannel for u64 { - #[inline] pub fn from(val: T) -> u64 { val.to_channel_u64() } -} - -pub trait ToIntChannel { pub fn to_channel_u8(&self) -> u8; pub fn to_channel_u16(&self) -> u16; - pub fn to_channel_u32(&self) -> u32; - pub fn to_channel_u64(&self) -> u64; -} - -impl ToIntChannel for u8 { - #[inline] pub fn to_channel_u8(&self) -> u8 { (*self) } - #[inline] pub fn to_channel_u16(&self) -> u16 { (*self as u16 << 8) | (*self) as u16 } - #[inline] pub fn to_channel_u32(&self) -> u32 { (self.to_channel_u16() as u32 << 16) | self.to_channel_u16() as u32 } - #[inline] pub fn to_channel_u64(&self) -> u64 { (self.to_channel_u32() as u64 << 32) | self.to_channel_u32() as u64 } -} - -impl ToIntChannel for u16 { - #[inline] pub fn to_channel_u8(&self) -> u8 { (*self >> 8) as u8 } // this is the equivalent of `self/256`. Some folks prefer to do `self/257` - #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) } - #[inline] pub fn to_channel_u32(&self) -> u32 { (*self as u32 << 16) | (*self) as u32 } - #[inline] pub fn to_channel_u64(&self) -> u64 { (self.to_channel_u32() as u64 << 32) | self.to_channel_u32() as u64 } -} - -impl ToIntChannel for u32 { - #[inline] pub fn to_channel_u8(&self) -> u8 { (*self >> 24) as u8 } - #[inline] pub fn to_channel_u16(&self) -> u16 { (*self >> 16) as u16 } - #[inline] pub fn to_channel_u32(&self) -> u32 { (*self) } - #[inline] pub fn to_channel_u64(&self) -> u64 { (*self as u64 << 32) | (*self) as u64 } -} - -impl ToIntChannel for u64 { - #[inline] pub fn to_channel_u8(&self) -> u8 { (*self >> 56) as u8 } - #[inline] pub fn to_channel_u16(&self) -> u16 { (*self >> 48) as u16 } - #[inline] pub fn to_channel_u32(&self) -> u32 { (*self >> 32) as u32 } - #[inline] pub fn to_channel_u64(&self) -> u64 { (*self) } -} - -impl ToIntChannel for f32 { - #[inline] pub fn to_channel_u8(&self) -> u8 { (*self) * (0xFF_u8 as f32) as u8 } - #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as f32) as u16 } - #[inline] pub fn to_channel_u32(&self) -> u32 { fail!(~"to_channel_u32 not yet implemented for f32") } - #[inline] pub fn to_channel_u64(&self) -> u64 { fail!(~"to_channel_u64 not yet implemented for f32") } -} - -impl ToIntChannel for f64 { - #[inline] pub fn to_channel_u8(&self) -> u8 { (*self) * (0xFF_u8 as f64) as u8 } - #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as f64) as u16 } - #[inline] pub fn to_channel_u32(&self) -> u32 { fail!(~"to_channel_u32 not yet implemented for f64") } - #[inline] pub fn to_channel_u64(&self) -> u64 { fail!(~"to_channel_u64 not yet implemented for f64") } -} - -impl ToIntChannel for float { - #[inline] pub fn to_channel_u8(&self) -> u8 { (*self) * (0xFF_u8 as float) as u8 } - #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as float) as u16 } - #[inline] pub fn to_channel_u32(&self) -> u32 { fail!(~"to_channel_u32 not yet implemented for float") } - #[inline] pub fn to_channel_u64(&self) -> u64 { fail!(~"to_channel_u64 not yet implemented for float") } -} - -pub trait FloatChannel: Float + Channel + ToFloatChannel { - pub fn from(val: T) -> Self; -} - -impl FloatChannel for f32 { - #[inline] pub fn from(val: T) -> f32 { val.to_channel_f32() } -} - -impl FloatChannel for f64 { - #[inline] pub fn from(val: T) -> f64 { val.to_channel_f64() } -} - -pub trait ToFloatChannel { pub fn to_channel_f32(&self) -> f32; pub fn to_channel_f64(&self) -> f64; } -impl ToFloatChannel for u8 { +impl Channel for u8 { + #[inline] pub fn from(chan: T) -> u8 { chan.to_channel_u8() } + + #[inline] pub fn to_channel_u8(&self) -> u8 { (*self) } + #[inline] pub fn to_channel_u16(&self) -> u16 { (*self as u16 << 8) | (*self) as u16 } #[inline] pub fn to_channel_f32(&self) -> f32 { (*self as f32) / (0xFF as f32) } #[inline] pub fn to_channel_f64(&self) -> f64 { (*self as f64) / (0xFF as f64) } } -impl ToFloatChannel for u16 { +impl Channel for u16 { + #[inline] pub fn from(chan: T) -> u16 { chan.to_channel_u16() } + + #[inline] pub fn to_channel_u8(&self) -> u8 { (*self >> 8) as u8 } + #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) } #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) / 0xFFFF as f32 } #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) / 0xFFFF as f64 } } -impl ToFloatChannel for u32 { - #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) / 0xFFFF_FFFF as f32 } - #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) / 0xFFFF_FFFF as f64 } -} +impl Channel for f32 { + #[inline] pub fn from(chan: T) -> f32 { chan.to_channel_f32() } -impl ToFloatChannel for u64 { - #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) / 0xFFFF_FFFF_FFFF_FFFF_u64 as f32 } - #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) / 0xFFFF_FFFF_FFFF_FFFF_u64 as f64 } -} - -impl ToFloatChannel for f32 { + #[inline] pub fn to_channel_u8(&self) -> u8 { (*self) * (0xFF_u8 as f32) as u8 } + #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as f32) as u16 } #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) } #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) as f64 } } -impl ToFloatChannel for f64 { +impl Channel for f64 { + #[inline] pub fn from(chan: T) -> f64 { chan.to_channel_f64() } + + #[inline] pub fn to_channel_u8(&self) -> u8 { (*self) * (0xFF_u8 as f64) as u8 } + #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as f64) as u16 } #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) as f32 } #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) } } diff --git a/src/color/color.rs b/src/color/color.rs index e73a5bb..260ad01 100644 --- a/src/color/color.rs +++ b/src/color/color.rs @@ -13,8 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use self::channel::{Channel, IntChannel, FloatChannel}; -pub use self::channel::{ToChannel, ToIntChannel, ToFloatChannel}; +pub use self::channel::Channel; pub use self::hsv::{HSV, ToHSV, HSVA, ToHSVA}; pub use self::rgb::{RGB, ToRGB, RGBA, ToRGBA}; pub use self::srgb::{SRGB, SRGBA}; diff --git a/src/color/hsv.rs b/src/color/hsv.rs index af3d7c8..a415cc0 100644 --- a/src/color/hsv.rs +++ b/src/color/hsv.rs @@ -16,7 +16,7 @@ use std::num; use std::cast; -use color::{Channel, ToChannel, FloatChannel, ToFloatChannel}; +use color::Channel; use color::{RGB, ToRGB, RGBA, ToRGBA}; #[path = "../num_macros.rs"] @@ -32,19 +32,19 @@ impl HSV { } pub trait ToHSV { - pub fn to_hsv(&self) -> HSV; + pub fn to_hsv(&self) -> HSV; } -impl ToHSV for HSV { +impl ToHSV for HSV { #[inline] - pub fn to_hsv(&self) -> HSV { - HSV::new(FloatChannel::from((*self).h.clone()), - FloatChannel::from((*self).s.clone()), - FloatChannel::from((*self).v.clone())) + pub fn to_hsv(&self) -> HSV { + HSV::new(Channel::from((*self).h.clone()), + Channel::from((*self).s.clone()), + Channel::from((*self).v.clone())) } } -impl ToRGB for HSV { +impl ToRGB for HSV { pub fn to_rgb(&self) -> RGB { // Algorithm taken from the Wikipedia article on HSL and HSV: // http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV @@ -102,24 +102,24 @@ impl HSVA { } pub trait ToHSVA { - pub fn to_hsva(&self) -> HSVA; + pub fn to_hsva(&self) -> HSVA; } -impl ToHSVA for (C, T) { +impl ToHSVA for (C, T) { #[inline] - pub fn to_hsva(&self) -> HSVA { + pub fn to_hsva(&self) -> HSVA { match *self { (ref hsv, ref a) => { HSVA::from_hsv_a( hsv.to_hsv(), - FloatChannel::from(a.clone()) + Channel::from(a.clone()) ) } } } } -impl ToRGBA for HSVA { +impl ToRGBA for HSVA { #[inline] pub fn to_rgba(&self) -> RGBA { RGBA::from_rgb_a( diff --git a/src/color/rgb.rs b/src/color/rgb.rs index 240b0e7..90dff74 100644 --- a/src/color/rgb.rs +++ b/src/color/rgb.rs @@ -16,7 +16,7 @@ use std::num; use std::cast; -use color::{Channel, ToChannel, FloatChannel}; +use color::Channel; use color::{HSV, ToHSV, HSVA, ToHSVA}; #[path = "../num_macros.rs"] @@ -36,7 +36,7 @@ pub trait ToRGB { pub fn to_rgb(&self) -> RGB; } -impl ToRGB for RGB { +impl ToRGB for RGB { #[inline] pub fn to_rgb(&self) -> RGB { RGB::new(Channel::from((*self).r.clone()), @@ -45,9 +45,9 @@ impl ToRGB for RGB { } } -impl ToHSV for RGB { +impl ToHSV for RGB { #[inline] - pub fn to_hsv(&self) -> HSV { + pub fn to_hsv(&self) -> HSV { // Algorithm taken from the Wikipedia article on HSL and HSV: // http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV @@ -103,7 +103,7 @@ pub trait ToRGBA { pub fn to_rgba(&self) -> RGBA; } -impl ToRGBA for (C, T) { +impl ToRGBA for (C, T) { #[inline] pub fn to_rgba(&self) -> RGBA { match *self { @@ -114,12 +114,15 @@ impl ToRGBA for (C, T) { } } -impl ToHSVA for RGBA { +impl ToHSVA for RGBA { #[inline] - pub fn to_hsva(&self) -> HSVA { + pub fn to_hsva(&self) -> HSVA { HSVA::from_hsv_a( self.rgb().to_hsv(), Channel::from((*self).a.clone()) ) } } + +// 0xFF_FF_FF_FF_u32 +// 0xFFFF_FFFF_FFFF_FFFF_u64