Remove noise and color modules

These have now been moved to separate repositories:

  - https://github.com/bjz/noise-rs
  - https://github.com/bjz/color-rs
This commit is contained in:
Brendan Zabarauskas 2013-07-30 14:02:26 +10:00
parent 994b135bcd
commit c429ed839d
12 changed files with 1 additions and 1362 deletions

View file

@ -22,7 +22,7 @@ SRC_CRATE = $(TARGET).rs
EXTERN_DIR = $(ROOT_DIR)/extern
BUILD_DIR = $(ROOT_DIR)/lib
CFG = --cfg=bounds --cfg=color --cfg=noise --cfg=transform --cfg=space
CFG = --cfg=bounds --cfg=transform --cfg=space
TEST = $(TARGET)
TEST_BUILD_DIR = $(ROOT_DIR)/test

View file

@ -1,48 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! An example of using perlin noise
// Noise rendering based off rust/src/test/bench/noise.rs
extern mod lmath;
use std::uint::range;
use lmath::noise::perlin::Perlin;
static WIDTH: uint = 100;
static HEIGHT: uint = 100;
fn main() {
let symbols = [" ", "", "", "", "", ""];
let mut pixels = [[0f32, ..WIDTH], ..HEIGHT];
let perlin = Perlin::new::<f32>();
for range(0, HEIGHT) |y| {
for range(0, WIDTH) |x| {
pixels[y][x] = perlin.noise2([
x as f32 * 0.1f32, y as f32 * 0.1f32
]) * 0.5f32 + 0.5f32;
};
};
for range(0, HEIGHT) |y| {
for range(0, WIDTH) |x| {
print(symbols[pixels[y][x] / 0.2f32 as int]);
}
println("");
}
}

View file

@ -1,254 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Color channel conversions and utility methods
pub trait Channel: Primitive + Orderable {
priv fn from<T:Channel>(chan: T) -> Self;
pub fn to_channel<T:Channel>(&self) -> T;
pub fn to_channel_u8(&self) -> u8;
pub fn to_channel_u16(&self) -> u16;
pub fn to_channel_f32(&self) -> f32;
pub fn to_channel_f64(&self) -> f64;
pub fn invert_channel(&self) -> Self;
}
impl Channel for u8 {
#[inline] priv fn from<T:Channel>(chan: T) -> u8 { chan.to_channel_u8() }
#[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
#[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) }
#[inline] pub fn invert_channel(&self) -> u8 { !(*self) }
}
impl Channel for u16 {
#[inline] priv fn from<T:Channel>(chan: T) -> u16 { chan.to_channel_u16() }
#[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
#[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 }
#[inline] pub fn invert_channel(&self) -> u16 { !(*self) }
}
impl Channel for f32 {
#[inline] priv fn from<T:Channel>(chan: T) -> f32 { chan.to_channel_f32() }
#[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
#[inline] pub fn to_channel_u8(&self) -> u8 { (*self) * (0xFF as f32) as u8 }
#[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF as f32) as u16 }
#[inline] pub fn to_channel_f32(&self) -> f32 { (*self) }
#[inline] pub fn to_channel_f64(&self) -> f64 { (*self) as f64 }
#[inline] pub fn invert_channel(&self) -> f32 { 1.0 - (*self) }
}
impl Channel for f64 {
#[inline] priv fn from<T:Channel>(chan: T) -> f64 { chan.to_channel_f64() }
#[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
#[inline] pub fn to_channel_u8(&self) -> u8 { (*self) * (0xFF as f64) as u8 }
#[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF as f64) as u16 }
#[inline] pub fn to_channel_f32(&self) -> f32 { (*self) as f32 }
#[inline] pub fn to_channel_f64(&self) -> f64 { (*self) }
#[inline] pub fn invert_channel(&self) -> f64 { 1.0 - (*self) }
}
pub trait FloatChannel: Float + Channel {
pub fn normalize_channel(&self) -> Self;
pub fn normalize_degrees(&self) -> Self;
pub fn invert_degrees(&self) -> Self;
}
impl FloatChannel for f32 {
#[inline]
pub fn normalize_channel(&self) -> f32 {
self.clamp(&0.0, &1.0)
}
#[inline]
pub fn normalize_degrees(&self) -> f32 {
if (*self) < 0.0 {
(*self + 360.0) % 360.0
} else {
*self % 360.0
}
}
#[inline]
pub fn invert_degrees(&self) -> f32 {
(*self + 180.0).normalize_degrees()
}
}
impl FloatChannel for f64 {
#[inline]
pub fn normalize_channel(&self) -> f64 {
self.clamp(&0.0, &1.0)
}
#[inline]
pub fn normalize_degrees(&self) -> f64 {
if (*self) < 0.0 {
(*self + 360.0) % 360.0
} else {
*self % 360.0
}
}
#[inline]
pub fn invert_degrees(&self) -> f64 {
(*self + 180.0).normalize_degrees()
}
}
#[cfg(test)]
mod tests {
use color::Channel;
#[test]
fn test_to_channel_u8() {
assert_eq!(0x00_u8.to_channel_u8(), 0x00_u8);
assert_eq!(0x30_u8.to_channel_u8(), 0x30_u8);
assert_eq!(0x66_u8.to_channel_u8(), 0x66_u8);
assert_eq!(0xA0_u8.to_channel_u8(), 0xA0_u8);
assert_eq!(0xFF_u8.to_channel_u8(), 0xFF_u8);
assert_eq!(0x00_u8.to_channel_u16(), 0x0000_u16);
assert_eq!(0x30_u8.to_channel_u16(), 0x3030_u16);
assert_eq!(0x66_u8.to_channel_u16(), 0x6666_u16);
assert_eq!(0xA0_u8.to_channel_u16(), 0xA0A0_u16);
assert_eq!(0xFF_u8.to_channel_u16(), 0xFFFF_u16);
assert_eq!(0x00_u8.to_channel_f32(), 0f32);
assert_eq!(0xFF_u8.to_channel_f32(), 1f32);
assert_eq!(0x00_u8.to_channel_f64(), 0f64);
assert_eq!(0xFF_u8.to_channel_f64(), 1f64);
}
#[test]
fn test_invert_channel_u8() {
assert_eq!(0x00_u8.invert_channel(), 0xFF_u8);
assert_eq!(0x66_u8.invert_channel(), 0x99_u8);
assert_eq!(0xFF_u8.invert_channel(), 0x00_u8);
}
#[test]
fn test_to_channel_u16() {
assert_eq!(0x0000_u16.to_channel_u8(), 0x00_u8);
assert_eq!(0x3300_u16.to_channel_u8(), 0x33_u8);
assert_eq!(0x6666_u16.to_channel_u8(), 0x66_u8);
assert_eq!(0xAA00_u16.to_channel_u8(), 0xAA_u8);
assert_eq!(0xFFFF_u16.to_channel_u8(), 0xFF_u8);
assert_eq!(0x0000_u16.to_channel_u16(), 0x0000_u16);
assert_eq!(0x3300_u16.to_channel_u16(), 0x3300_u16);
assert_eq!(0x6666_u16.to_channel_u16(), 0x6666_u16);
assert_eq!(0xAA00_u16.to_channel_u16(), 0xAA00_u16);
assert_eq!(0xFFFF_u16.to_channel_u16(), 0xFFFF_u16);
assert_eq!(0x0000_u16.to_channel_f32(), 0f32);
assert_eq!(0xFFFF_u16.to_channel_f32(), 1f32);
assert_eq!(0x0000_u16.to_channel_f64(), 0f64);
assert_eq!(0xFFFF_u16.to_channel_f64(), 1f64);
}
#[test]
fn test_invert_channel_u16() {
assert_eq!(0x0000_u16.invert_channel(), 0xFFFF_u16);
assert_eq!(0x6666_u16.invert_channel(), 0x9999_u16);
assert_eq!(0xFFFF_u16.invert_channel(), 0x0000_u16);
}
#[test]
fn test_to_channel_f32() {
assert_eq!(0.00f32.to_channel_u8(), 0x00);
assert_eq!(0.25f32.to_channel_u8(), 0x3F);
assert_eq!(0.50f32.to_channel_u8(), 0x7F);
assert_eq!(0.75f32.to_channel_u8(), 0xBF);
assert_eq!(1.00f32.to_channel_u8(), 0xFF);
assert_eq!(0.00f32.to_channel_u16(), 0x0000);
assert_eq!(0.25f32.to_channel_u16(), 0x3FFF);
assert_eq!(0.50f32.to_channel_u16(), 0x7FFF);
assert_eq!(0.75f32.to_channel_u16(), 0xBFFF);
assert_eq!(1.00f32.to_channel_u16(), 0xFFFF);
assert_eq!(0.00f32.to_channel_f32(), 0.00f32);
assert_eq!(1.00f32.to_channel_f32(), 1.00f32);
assert_eq!(0.00f32.to_channel_f64(), 0.00f64);
assert_eq!(1.00f32.to_channel_f64(), 1.00f64);
}
#[test]
fn test_invert_channel_f32() {
assert_eq!(0.00f32.invert_channel(), 1.00f32);
assert_eq!(0.50f32.invert_channel(), 0.50f32);
assert_eq!(1.00f32.invert_channel(), 0.00f32);
}
#[test]
fn test_invert_degrees_f32() {
assert_eq!( 0.00f32.invert_degrees(), 180.00f32);
assert_eq!( 45.00f32.invert_degrees(), 225.00f32);
assert_eq!( 90.00f32.invert_degrees(), 270.00f32);
assert_eq!(360.00f32.invert_degrees(), 180.00f32);
assert_eq!(720.00f32.invert_degrees(), 180.00f32);
}
#[test]
fn test_to_channel_f64() {
assert_eq!(0.00f64.to_channel_u8(), 0x00);
assert_eq!(0.25f64.to_channel_u8(), 0x3F);
assert_eq!(0.50f64.to_channel_u8(), 0x7F);
assert_eq!(0.75f64.to_channel_u8(), 0xBF);
assert_eq!(1.00f64.to_channel_u8(), 0xFF);
assert_eq!(0.00f64.to_channel_u16(), 0x0000);
assert_eq!(0.25f64.to_channel_u16(), 0x3FFF);
assert_eq!(0.50f64.to_channel_u16(), 0x7FFF);
assert_eq!(0.75f64.to_channel_u16(), 0xBFFF);
assert_eq!(1.00f64.to_channel_u16(), 0xFFFF);
assert_eq!(0.00f64.to_channel_f32(), 0.00f32);
assert_eq!(1.00f64.to_channel_f32(), 1.00f32);
assert_eq!(0.00f64.to_channel_f64(), 0.00f64);
assert_eq!(1.00f64.to_channel_f64(), 1.00f64);
}
#[test]
fn test_invert_channel_f64() {
assert_eq!(0.00f64.invert_channel(), 1.00f64);
assert_eq!(0.50f64.invert_channel(), 0.50f64);
assert_eq!(1.00f64.invert_channel(), 0.00f64);
}
#[test]
fn test_invert_degrees_f64() {
assert_eq!( 0.00f64.invert_degrees(), 180.00f64);
assert_eq!( 45.00f64.invert_degrees(), 225.00f64);
assert_eq!( 90.00f64.invert_degrees(), 270.00f64);
assert_eq!(360.00f64.invert_degrees(), 180.00f64);
assert_eq!(720.00f64.invert_degrees(), 180.00f64);
}
}

View file

@ -1,42 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Color types, functions and conversions
pub use self::channel::{Channel, FloatChannel};
pub use self::hsv::{HSV, ToHSV, HSVA, ToHSVA};
pub use self::rgb::{RGB, ToRGB, RGBA, ToRGBA};
pub use self::srgb::{SRGB, SRGBA};
pub use self::ycbcr::YCbCr;
pub mod channel;
pub mod hsv;
pub mod rgb;
pub mod srgb;
pub mod ycbcr;
pub trait Color<T> {
pub fn clamp_s(&self, lo: T, hi: T) -> Self;
pub fn clamp_c(&self, lo: &Self, hi: &Self) -> Self;
pub fn inverse(&self) -> Self;
// pub fn mix(&self, other: &Self, value: T) -> Self;
// pub fn saturation(&self, value: T) -> Self;
// pub fn exposure(&self, value: T) -> Self;
// pub fn brightness(&self, value: T) -> Self;
}
pub trait FloatColor<T>: Color<T> {
pub fn normalize(&self) -> Self;
}

View file

@ -1,297 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::num;
use std::cast;
use math::*;
use color::{Color, FloatColor};
use color::{Channel, FloatChannel};
use color::{RGB, ToRGB, RGBA, ToRGBA};
#[deriving(Clone, Eq)]
pub struct HSV<T> { h: T, s: T, v: T }
impl_dimensioned!(HSV, T, 3)
impl_to_vec!(HSV, 3)
impl_as_vec!(HSV, 3)
impl_swap_components!(HSV)
impl_approx!(HSV { h, s, v })
impl<T:FloatChannel> HSV<T> {
pub fn new(h: T, s: T, v: T) -> HSV<T> {
HSV { h: h, s: s, v: v }
}
}
impl<T:FloatChannel> Color<T> for HSV<T> {
/// Clamps the components of the color to the range `(lo,hi)`.
#[inline]
pub fn clamp_s(&self, lo: T, hi: T) -> HSV<T> {
HSV::new(self.h.clamp(&lo, &hi), // Should the hue component be clamped?
self.s.clamp(&lo, &hi),
self.v.clamp(&lo, &hi))
}
/// Clamps the components of the color component-wise between `lo` and `hi`.
#[inline]
pub fn clamp_c(&self, lo: &HSV<T>, hi: &HSV<T>) -> HSV<T> {
HSV::new(self.h.clamp(&lo.h, &hi.h),
self.s.clamp(&lo.s, &hi.s),
self.v.clamp(&lo.v, &hi.v))
}
/// Inverts the color.
#[inline]
pub fn inverse(&self) -> HSV<T> {
HSV::new(self.h.invert_degrees(),
self.s.invert_channel(),
self.v.invert_channel())
}
}
impl<T:FloatChannel> FloatColor<T> for HSV<T> {
/// Normalizes the components of the color. Modulo `360` is applied to the
/// `h` component, and `s` and `v` are clamped to the range `(0,1)`.
#[inline]
pub fn normalize(&self) -> HSV<T> {
HSV::new(self.h.normalize_degrees(),
self.s.normalize_channel(),
self.v.normalize_channel())
}
}
pub trait ToHSV {
pub fn to_hsv<U:FloatChannel>(&self) -> HSV<U>;
}
impl ToHSV for u32 {
#[inline]
pub fn to_hsv<U:FloatChannel>(&self) -> HSV<U> {
fail!("Not yet implemented")
}
}
impl ToHSV for u64 {
#[inline]
pub fn to_hsv<U:FloatChannel>(&self) -> HSV<U> {
fail!("Not yet implemented")
}
}
impl<T:Clone + FloatChannel> ToHSV for HSV<T> {
#[inline]
pub fn to_hsv<U:FloatChannel>(&self) -> HSV<U> {
HSV::new(self.h.to_channel(),
self.s.to_channel(),
self.v.to_channel())
}
}
impl<T:Clone + FloatChannel> ToRGB for HSV<T> {
pub fn to_rgb<U:Channel>(&self) -> RGB<U> {
// Algorithm taken from the Wikipedia article on HSL and HSV:
// http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
let chr = self.v * self.s;
let h = self.h / num::cast(60);
// the 2nd largest component
let x = chr * (one!(T) - ((h % two!(T)) - one!(T)).abs());
let mut rgb = cond! (
(h < num::cast(1)) { RGB::new(chr.clone(), x, zero!(T)) }
(h < num::cast(2)) { RGB::new(x, chr.clone(), zero!(T)) }
(h < num::cast(3)) { RGB::new(zero!(T), chr.clone(), x) }
(h < num::cast(4)) { RGB::new(zero!(T), x, chr.clone()) }
(h < num::cast(5)) { RGB::new(x, zero!(T), chr.clone()) }
(h < num::cast(6)) { RGB::new(chr.clone(), zero!(T), x) }
_ { RGB::new(zero!(T), zero!(T), zero!(T)) }
);
// match the value by adding the same amount to each component
let mn = self.v - chr;
rgb.r = rgb.r + mn;
rgb.g = rgb.g + mn;
rgb.b = rgb.b + mn;
rgb.to_rgb::<U>()
}
}
#[deriving(Clone, Eq)]
pub struct HSVA<T> { h: T, s: T, v: T, a: T }
impl_dimensioned!(HSVA, T, 4)
impl_to_vec!(HSVA, 4)
impl_as_vec!(HSVA, 4)
impl_swap_components!(HSVA)
impl_approx!(HSVA { h, s, v, a })
impl<T:FloatChannel> HSVA<T> {
#[inline]
pub fn new(h: T, s: T, v: T, a: T) -> HSVA<T> {
HSVA { h: h, s: s, v: v, a: a }
}
#[inline]
pub fn from_hsv_a(hsv: HSV<T>, a: T) -> HSVA<T> {
unsafe { cast::transmute((hsv, a)) }
}
#[inline]
pub fn hsv<'a>(&'a self) -> &'a HSV<T> {
unsafe { cast::transmute(self) }
}
#[inline]
pub fn hsv_mut<'a>(&'a mut self) -> &'a mut HSV<T> {
unsafe { cast::transmute(self) }
}
}
impl<T:FloatChannel> Color<T> for HSVA<T> {
/// Clamps the components of the color to the range `(lo,hi)`.
#[inline]
pub fn clamp_s(&self, lo: T, hi: T) -> HSVA<T> {
HSVA::new(self.h.clamp(&lo, &hi), // Should the hue component be clamped?
self.s.clamp(&lo, &hi),
self.v.clamp(&lo, &hi),
self.a.clamp(&lo, &hi))
}
/// Clamps the components of the color component-wise between `lo` and `hi`.
#[inline]
pub fn clamp_c(&self, lo: &HSVA<T>, hi: &HSVA<T>) -> HSVA<T> {
HSVA::new(self.h.clamp(&lo.h, &hi.h),
self.s.clamp(&lo.s, &hi.s),
self.v.clamp(&lo.v, &hi.v),
self.a.clamp(&lo.a, &hi.a))
}
/// Inverts the color.
#[inline]
pub fn inverse(&self) -> HSVA<T> {
HSVA::new(self.h.invert_degrees(),
self.s.invert_channel(),
self.v.invert_channel(),
self.a.invert_channel())
}
}
impl<T:FloatChannel> FloatColor<T> for HSVA<T> {
/// Normalizes the components of the color. Modulo `360` is applied to the
/// `h` component, and `s`, `v` and `a` are clamped to the range `(0,1)`.
#[inline]
pub fn normalize(&self) -> HSVA<T> {
HSVA::new(self.h.normalize_degrees(),
self.s.normalize_channel(),
self.v.normalize_channel(),
self.a.normalize_channel())
}
}
pub trait ToHSVA {
pub fn to_hsva<U:FloatChannel>(&self) -> HSVA<U>;
}
impl ToHSVA for u32 {
#[inline]
pub fn to_hsva<U:FloatChannel>(&self) -> HSVA<U> {
fail!("Not yet implemented")
}
}
impl ToHSVA for u64 {
#[inline]
pub fn to_hsva<U:FloatChannel>(&self) -> HSVA<U> {
fail!("Not yet implemented")
}
}
impl<C: ToHSV, T:Clone + FloatChannel> ToHSVA for (C, T) {
#[inline]
pub fn to_hsva<U:FloatChannel>(&self) -> HSVA<U> {
match *self {
(ref hsv, ref a) => {
HSVA::from_hsv_a(hsv.to_hsv(), a.to_channel())
}
}
}
}
impl<T:Clone + FloatChannel> ToHSVA for HSVA<T> {
#[inline]
pub fn to_hsva<U:FloatChannel>(&self) -> HSVA<U> {
HSVA::new(self.h.to_channel(),
self.s.to_channel(),
self.v.to_channel(),
self.a.to_channel())
}
}
impl<T:Clone + FloatChannel> ToRGBA for HSVA<T> {
#[inline]
pub fn to_rgba<U:Channel>(&self) -> RGBA<U> {
RGBA::from_rgb_a(self.hsv().to_rgb(), self.a.to_channel())
}
}
#[cfg(test)]
mod tests {
use color::*;
#[test]
fn test_hsv_to_hsv() {
assert_eq!(HSV::new::<f64>(0.0, 0.0, 1.0).to_hsv::<f32>(), HSV::new::<f32>(0.0, 0.0, 1.0));
assert_eq!(HSV::new::<f64>(0.0, 1.0, 0.6).to_hsv::<f32>(), HSV::new::<f32>(0.0, 1.0, 0.6));
assert_eq!(HSV::new::<f64>(120.0, 1.0, 0.6).to_hsv::<f32>(), HSV::new::<f32>(120.0, 1.0, 0.6));
assert_eq!(HSV::new::<f64>(240.0, 1.0, 0.6).to_hsv::<f32>(), HSV::new::<f32>(240.0, 1.0, 0.6));
}
#[test]
fn test_hsv_to_rgb() {
assert_eq!(HSV::new::<f32>(0.0, 0.0, 1.0).to_rgb::<u8>(), RGB::new::<u8>(0xFF, 0xFF, 0xFF));
assert_eq!(HSV::new::<f32>(0.0, 1.0, 0.6).to_rgb::<u8>(), RGB::new::<u8>(0x99, 0x00, 0x00));
assert_eq!(HSV::new::<f32>(120.0, 1.0, 0.6).to_rgb::<u8>(), RGB::new::<u8>(0x00, 0x99, 0x00));
assert_eq!(HSV::new::<f32>(240.0, 1.0, 0.6).to_rgb::<u8>(), RGB::new::<u8>(0x00, 0x00, 0x99));
}
#[test]
fn test_tuple_to_hsva() {
assert_eq!((RGB::new::<u8>(0xFF, 0xFF, 0xFF), 0.5f32).to_hsva::<f32>(), HSVA::new::<f32>(0.0, 0.0, 1.0, 0.5));
assert_eq!((RGB::new::<u8>(0x99, 0x00, 0x00), 0.5f32).to_hsva::<f32>(), HSVA::new::<f32>(0.0, 1.0, 0.6, 0.5));
assert_eq!((RGB::new::<u8>(0x00, 0x99, 0x00), 0.5f32).to_hsva::<f32>(), HSVA::new::<f32>(120.0, 1.0, 0.6, 0.5));
assert_eq!((RGB::new::<u8>(0x00, 0x00, 0x99), 0.5f32).to_hsva::<f32>(), HSVA::new::<f32>(240.0, 1.0, 0.6, 0.5));
}
#[test]
fn test_hsva_to_hsva() {
assert_eq!(HSVA::new::<f64>(0.0, 0.0, 1.0, 0.5).to_hsva::<f32>(), HSVA::new::<f32>(0.0, 0.0, 1.0, 0.5));
assert_eq!(HSVA::new::<f64>(0.0, 1.0, 0.6, 0.5).to_hsva::<f32>(), HSVA::new::<f32>(0.0, 1.0, 0.6, 0.5));
assert_eq!(HSVA::new::<f64>(120.0, 1.0, 0.6, 0.5).to_hsva::<f32>(), HSVA::new::<f32>(120.0, 1.0, 0.6, 0.5));
assert_eq!(HSVA::new::<f64>(240.0, 1.0, 0.6, 0.5).to_hsva::<f32>(), HSVA::new::<f32>(240.0, 1.0, 0.6, 0.5));
}
#[test]
fn test_hsva_to_rgba() {
assert_eq!(HSVA::new::<f32>(0.0, 0.0, 1.0, 0.5).to_rgba::<u8>(), RGBA::new::<u8>(0xFF, 0xFF, 0xFF, 0x7F));
assert_eq!(HSVA::new::<f32>(0.0, 1.0, 0.6, 0.5).to_rgba::<u8>(), RGBA::new::<u8>(0x99, 0x00, 0x00, 0x7F));
assert_eq!(HSVA::new::<f32>(120.0, 1.0, 0.6, 0.5).to_rgba::<u8>(), RGBA::new::<u8>(0x00, 0x99, 0x00, 0x7F));
assert_eq!(HSVA::new::<f32>(240.0, 1.0, 0.6, 0.5).to_rgba::<u8>(), RGBA::new::<u8>(0x00, 0x00, 0x99, 0x7F));
}
}

View file

@ -1,434 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::num;
use std::cast;
use math::*;
use color::{Color, FloatColor};
use color::{Channel, FloatChannel};
use color::{HSV, ToHSV, HSVA, ToHSVA};
#[deriving(Clone, Eq)]
pub struct RGB<T> { r: T, g: T, b: T }
impl_dimensioned!(RGB, T, 3)
impl_to_vec!(RGB, 3)
impl_as_vec!(RGB, 3)
impl_swap_components!(RGB)
impl_approx!(RGB { r, g, b })
impl<T:Channel> RGB<T> {
#[inline]
pub fn new(r: T, g: T, b: T) -> RGB<T> {
RGB { r: r, g: g, b: b }
}
}
impl<T:Channel> Color<T> for RGB<T> {
/// Clamps the components of the color to the range `(lo,hi)`.
#[inline]
pub fn clamp_s(&self, lo: T, hi: T) -> RGB<T> {
RGB::new(self.r.clamp(&lo, &hi),
self.g.clamp(&lo, &hi),
self.b.clamp(&lo, &hi))
}
/// Clamps the components of the color component-wise between `lo` and `hi`.
#[inline]
pub fn clamp_c(&self, lo: &RGB<T>, hi: &RGB<T>) -> RGB<T> {
RGB::new(self.r.clamp(&lo.r, &hi.r),
self.g.clamp(&lo.g, &hi.g),
self.b.clamp(&lo.b, &hi.b))
}
/// Inverts the color.
#[inline]
pub fn inverse(&self) -> RGB<T> {
RGB::new(self.r.invert_channel(),
self.g.invert_channel(),
self.b.invert_channel())
}
}
impl<T:FloatChannel> FloatColor<T> for RGB<T> {
/// Normalizes the components of the color by clamping them to the range `(0,1)`.
#[inline]
pub fn normalize(&self) -> RGB<T> {
RGB::new(self.r.normalize_channel(),
self.g.normalize_channel(),
self.b.normalize_channel())
}
}
pub trait ToRGB {
pub fn to_rgb<U:Channel>(&self) -> RGB<U>;
}
impl ToRGB for u32 {
#[inline]
pub fn to_rgb<U:Channel>(&self) -> RGB<U> {
fail!("Not yet implemented")
}
}
impl ToRGB for u64 {
#[inline]
pub fn to_rgb<U:Channel>(&self) -> RGB<U> {
fail!("Not yet implemented")
}
}
impl<T:Clone + Channel> ToRGB for RGB<T> {
#[inline]
pub fn to_rgb<U:Channel>(&self) -> RGB<U> {
RGB::new(self.r.to_channel(),
self.g.to_channel(),
self.b.to_channel())
}
}
impl<T:Clone + Channel> ToHSV for RGB<T> {
#[inline]
pub fn to_hsv<U:FloatChannel>(&self) -> HSV<U> {
// Algorithm taken from the Wikipedia article on HSL and HSV:
// http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
let rgb_u = self.to_rgb::<U>();
let mx = rgb_u.r.max(&rgb_u.g).max(&rgb_u.b);
let mn = rgb_u.r.min(&rgb_u.g).min(&rgb_u.b);
let chr = mx - mn;
if chr != zero!(U) {
let h = cond! (
(rgb_u.r == mx) { ((rgb_u.g - rgb_u.b) / chr) % num::cast(6) }
(rgb_u.g == mx) { ((rgb_u.b - rgb_u.r) / chr) + num::cast(2) }
_ /* rgb_u.b == mx */ { ((rgb_u.r - rgb_u.g) / chr) + num::cast(4) }
) * num::cast(60);
let s = chr / mx;
HSV::new(h, s, mx)
} else {
HSV::new(zero!(U), zero!(U), mx)
}
}
}
#[deriving(Clone, Eq)]
pub struct RGBA<T> { r: T, g: T, b: T, a: T }
impl_dimensioned!(RGBA, T, 4)
impl_to_vec!(RGBA, 4)
impl_as_vec!(RGBA, 4)
impl_swap_components!(RGBA)
impl_approx!(RGBA { r, g, b, a })
impl<T:Channel> RGBA<T> {
#[inline]
pub fn new(r: T, g: T, b: T, a: T) -> RGBA<T> {
RGBA { r: r, g: g, b: b, a: a }
}
#[inline]
pub fn from_rgb_a(rgb: RGB<T>, a: T) -> RGBA<T> {
unsafe { cast::transmute((rgb, a)) }
}
#[inline]
pub fn rgb<'a>(&'a self) -> &'a RGB<T> {
unsafe { cast::transmute(self) }
}
#[inline]
pub fn rgb_mut<'a>(&'a mut self) -> &'a mut RGB<T> {
unsafe { cast::transmute(self) }
}
}
impl<T:Channel> Color<T> for RGBA<T> {
/// Clamps the components of the color to the range `(lo,hi)`.
#[inline]
pub fn clamp_s(&self, lo: T, hi: T) -> RGBA<T> {
RGBA::new(self.r.clamp(&lo, &hi),
self.g.clamp(&lo, &hi),
self.b.clamp(&lo, &hi),
self.a.clamp(&lo, &hi))
}
/// Clamps the components of the color component-wise between `lo` and `hi`.
#[inline]
pub fn clamp_c(&self, lo: &RGBA<T>, hi: &RGBA<T>) -> RGBA<T> {
RGBA::new(self.r.clamp(&lo.r, &hi.r),
self.g.clamp(&lo.g, &hi.g),
self.b.clamp(&lo.b, &hi.b),
self.a.clamp(&lo.a, &hi.a))
}
/// Inverts the color.
#[inline]
pub fn inverse(&self) -> RGBA<T> {
RGBA::new(self.r.invert_channel(),
self.g.invert_channel(),
self.b.invert_channel(),
self.a.invert_channel())
}
}
impl<T:FloatChannel> FloatColor<T> for RGBA<T> {
/// Normalizes the components of the color by clamping them to the range `(0,1)`.
#[inline]
pub fn normalize(&self) -> RGBA<T> {
RGBA::new(self.r.normalize_channel(),
self.g.normalize_channel(),
self.b.normalize_channel(),
self.a.normalize_channel())
}
}
pub trait ToRGBA {
pub fn to_rgba<U:Channel>(&self) -> RGBA<U>;
}
impl ToRGBA for u32 {
#[inline]
pub fn to_rgba<U:Channel>(&self) -> RGBA<U> {
fail!("Not yet implemented")
}
}
impl ToRGBA for u64 {
#[inline]
pub fn to_rgba<U:Channel>(&self) -> RGBA<U> {
fail!("Not yet implemented")
}
}
impl<C: ToRGB, T:Clone + Channel> ToRGBA for (C, T) {
#[inline]
pub fn to_rgba<U:Channel>(&self) -> RGBA<U> {
match *self {
(ref rgb, ref a) => {
RGBA::from_rgb_a(rgb.to_rgb(), a.to_channel())
}
}
}
}
impl<T:Clone + Channel> ToRGBA for RGBA<T> {
#[inline]
pub fn to_rgba<U:Channel>(&self) -> RGBA<U> {
RGBA::new(self.r.to_channel(),
self.g.to_channel(),
self.b.to_channel(),
self.a.to_channel())
}
}
impl<T:Clone + Channel> ToHSVA for RGBA<T> {
#[inline]
pub fn to_hsva<U:FloatChannel>(&self) -> HSVA<U> {
HSVA::from_hsv_a(self.rgb().to_hsv(), self.a.to_channel())
}
}
/// SVG 1.0 color constants: http://www.w3.org/TR/SVG/types.html#ColorKeywords
pub mod consts {
use color::RGB;
static ALICEBLUE: RGB<u8> = RGB { r: 0xF0, g: 0xF8, b: 0xFF };
static ANTIQUEWHITE: RGB<u8> = RGB { r: 0xFA, g: 0xEB, b: 0xD7 };
static AQUA: RGB<u8> = RGB { r: 0x00, g: 0xFF, b: 0xFF };
static AQUAMARINE: RGB<u8> = RGB { r: 0x7F, g: 0xFF, b: 0xD4 };
static AZURE: RGB<u8> = RGB { r: 0xF0, g: 0xFF, b: 0xFF };
static BEIGE: RGB<u8> = RGB { r: 0xF5, g: 0xF5, b: 0xDC };
static BISQUE: RGB<u8> = RGB { r: 0xFF, g: 0xE4, b: 0xC4 };
static BLACK: RGB<u8> = RGB { r: 0x00, g: 0x00, b: 0x00 };
static BLANCHEDALMOND: RGB<u8> = RGB { r: 0xFF, g: 0xEB, b: 0xCD };
static BLUE: RGB<u8> = RGB { r: 0x00, g: 0x00, b: 0xFF };
static BLUEVIOLET: RGB<u8> = RGB { r: 0x8A, g: 0x2B, b: 0xE2 };
static BROWN: RGB<u8> = RGB { r: 0xA5, g: 0x2A, b: 0x2A };
static BURLYWOOD: RGB<u8> = RGB { r: 0xDE, g: 0xB8, b: 0x87 };
static CADETBLUE: RGB<u8> = RGB { r: 0x5F, g: 0x9E, b: 0xA0 };
static CHARTREUSE: RGB<u8> = RGB { r: 0x7F, g: 0xFF, b: 0x00 };
static CHOCOLATE: RGB<u8> = RGB { r: 0xD2, g: 0x69, b: 0x1E };
static CORAL: RGB<u8> = RGB { r: 0xFF, g: 0x7F, b: 0x50 };
static CORNFLOWERBLUE: RGB<u8> = RGB { r: 0x64, g: 0x95, b: 0xED };
static CORNSILK: RGB<u8> = RGB { r: 0xFF, g: 0xF8, b: 0xDC };
static CRIMSON: RGB<u8> = RGB { r: 0xDC, g: 0x14, b: 0x3C };
static CYAN: RGB<u8> = RGB { r: 0x00, g: 0xFF, b: 0xFF };
static DARKBLUE: RGB<u8> = RGB { r: 0x00, g: 0x00, b: 0x8B };
static DARKCYAN: RGB<u8> = RGB { r: 0x00, g: 0x8B, b: 0x8B };
static DARKGOLDENROD: RGB<u8> = RGB { r: 0xB8, g: 0x86, b: 0x0B };
static DARKGRAY: RGB<u8> = RGB { r: 0xA9, g: 0xA9, b: 0xA9 };
static DARKGREEN: RGB<u8> = RGB { r: 0x00, g: 0x64, b: 0x00 };
static DARKKHAKI: RGB<u8> = RGB { r: 0xBD, g: 0xB7, b: 0x6B };
static DARKMAGENTA: RGB<u8> = RGB { r: 0x8B, g: 0x00, b: 0x8B };
static DARKOLIVEGREEN: RGB<u8> = RGB { r: 0x55, g: 0x6B, b: 0x2F };
static DARKORANGE: RGB<u8> = RGB { r: 0xFF, g: 0x8C, b: 0x00 };
static DARKORCHID: RGB<u8> = RGB { r: 0x99, g: 0x32, b: 0xCC };
static DARKRED: RGB<u8> = RGB { r: 0x8B, g: 0x00, b: 0x00 };
static DARKSALMON: RGB<u8> = RGB { r: 0xE9, g: 0x96, b: 0x7A };
static DARKSEAGREEN: RGB<u8> = RGB { r: 0x8F, g: 0xBC, b: 0x8F };
static DARKSLATEBLUE: RGB<u8> = RGB { r: 0x48, g: 0x3D, b: 0x8B };
static DARKSLATEGRAY: RGB<u8> = RGB { r: 0x2F, g: 0x4F, b: 0x4F };
static DARKTURQUOISE: RGB<u8> = RGB { r: 0x00, g: 0xCE, b: 0xD1 };
static DARKVIOLET: RGB<u8> = RGB { r: 0x94, g: 0x00, b: 0xD3 };
static DEEPPINK: RGB<u8> = RGB { r: 0xFF, g: 0x14, b: 0x93 };
static DEEPSKYBLUE: RGB<u8> = RGB { r: 0x00, g: 0xBF, b: 0xFF };
static DIMGRAY: RGB<u8> = RGB { r: 0x69, g: 0x69, b: 0x69 };
static DODGERBLUE: RGB<u8> = RGB { r: 0x1E, g: 0x90, b: 0xFF };
static FIREBRICK: RGB<u8> = RGB { r: 0xB2, g: 0x22, b: 0x22 };
static FLORALWHITE: RGB<u8> = RGB { r: 0xFF, g: 0xFA, b: 0xF0 };
static FORESTGREEN: RGB<u8> = RGB { r: 0x22, g: 0x8B, b: 0x22 };
static FUCHSIA: RGB<u8> = RGB { r: 0xFF, g: 0x00, b: 0xFF };
static GAINSBORO: RGB<u8> = RGB { r: 0xDC, g: 0xDC, b: 0xDC };
static GHOSTWHITE: RGB<u8> = RGB { r: 0xF8, g: 0xF8, b: 0xFF };
static GOLD: RGB<u8> = RGB { r: 0xFF, g: 0xD7, b: 0x00 };
static GOLDENROD: RGB<u8> = RGB { r: 0xDA, g: 0xA5, b: 0x20 };
static GRAY: RGB<u8> = RGB { r: 0x80, g: 0x80, b: 0x80 };
static GREEN: RGB<u8> = RGB { r: 0x00, g: 0x80, b: 0x00 };
static GREENYELLOW: RGB<u8> = RGB { r: 0xAD, g: 0xFF, b: 0x2F };
static HONEYDEW: RGB<u8> = RGB { r: 0xF0, g: 0xFF, b: 0xF0 };
static HOTPINK: RGB<u8> = RGB { r: 0xFF, g: 0x69, b: 0xB4 };
static INDIANRED: RGB<u8> = RGB { r: 0xCD, g: 0x5C, b: 0x5C };
static INDIGO: RGB<u8> = RGB { r: 0x4B, g: 0x00, b: 0x82 };
static IVORY: RGB<u8> = RGB { r: 0xFF, g: 0xFF, b: 0xF0 };
static KHAKI: RGB<u8> = RGB { r: 0xF0, g: 0xE6, b: 0x8C };
static LAVENDER: RGB<u8> = RGB { r: 0xE6, g: 0xE6, b: 0xFA };
static LAVENDERBLUSH: RGB<u8> = RGB { r: 0xFF, g: 0xF0, b: 0xF5 };
static LAWNGREEN: RGB<u8> = RGB { r: 0x7C, g: 0xFC, b: 0x00 };
static LEMONCHIFFON: RGB<u8> = RGB { r: 0xFF, g: 0xFA, b: 0xCD };
static LIGHTBLUE: RGB<u8> = RGB { r: 0xAD, g: 0xD8, b: 0xE6 };
static LIGHTCORAL: RGB<u8> = RGB { r: 0xF0, g: 0x80, b: 0x80 };
static LIGHTCYAN: RGB<u8> = RGB { r: 0xE0, g: 0xFF, b: 0xFF };
static LIGHTGOLDENRODYELLOW: RGB<u8> = RGB { r: 0xFA, g: 0xFA, b: 0xD2 };
static LIGHTGREEN: RGB<u8> = RGB { r: 0x90, g: 0xEE, b: 0x90 };
static LIGHTGREY: RGB<u8> = RGB { r: 0xD3, g: 0xD3, b: 0xD3 };
static LIGHTPINK: RGB<u8> = RGB { r: 0xFF, g: 0xB6, b: 0xC1 };
static LIGHTSALMON: RGB<u8> = RGB { r: 0xFF, g: 0xA0, b: 0x7A };
static LIGHTSEAGREEN: RGB<u8> = RGB { r: 0x20, g: 0xB2, b: 0xAA };
static LIGHTSKYBLUE: RGB<u8> = RGB { r: 0x87, g: 0xCE, b: 0xFA };
static LIGHTSLATEGRAY: RGB<u8> = RGB { r: 0x77, g: 0x88, b: 0x99 };
static LIGHTSTEELBLUE: RGB<u8> = RGB { r: 0xB0, g: 0xC4, b: 0xDE };
static LIGHTYELLOW: RGB<u8> = RGB { r: 0xFF, g: 0xFF, b: 0xE0 };
static LIME: RGB<u8> = RGB { r: 0x00, g: 0xFF, b: 0x00 };
static LIMEGREEN: RGB<u8> = RGB { r: 0x32, g: 0xCD, b: 0x32 };
static LINEN: RGB<u8> = RGB { r: 0xFA, g: 0xF0, b: 0xE6 };
static MAGENTA: RGB<u8> = RGB { r: 0xFF, g: 0x00, b: 0xFF };
static MAROON: RGB<u8> = RGB { r: 0x80, g: 0x00, b: 0x00 };
static MEDIUMAQUAMARINE: RGB<u8> = RGB { r: 0x66, g: 0xCD, b: 0xAA };
static MEDIUMBLUE: RGB<u8> = RGB { r: 0x00, g: 0x00, b: 0xCD };
static MEDIUMORCHID: RGB<u8> = RGB { r: 0xBA, g: 0x55, b: 0xD3 };
static MEDIUMPURPLE: RGB<u8> = RGB { r: 0x93, g: 0x70, b: 0xDB };
static MEDIUMSEAGREEN: RGB<u8> = RGB { r: 0x3C, g: 0xB3, b: 0x71 };
static MEDIUMSLATEBLUE: RGB<u8> = RGB { r: 0x7B, g: 0x68, b: 0xEE };
static MEDIUMSPRINGGREEN: RGB<u8> = RGB { r: 0x00, g: 0xFA, b: 0x9A };
static MEDIUMTURQUOISE: RGB<u8> = RGB { r: 0x48, g: 0xD1, b: 0xCC };
static MEDIUMVIOLETRED: RGB<u8> = RGB { r: 0xC7, g: 0x15, b: 0x85 };
static MIDNIGHTBLUE: RGB<u8> = RGB { r: 0x19, g: 0x19, b: 0x70 };
static MINTCREAM: RGB<u8> = RGB { r: 0xF5, g: 0xFF, b: 0xFA };
static MISTYROSE: RGB<u8> = RGB { r: 0xFF, g: 0xE4, b: 0xE1 };
static MOCCASIN: RGB<u8> = RGB { r: 0xFF, g: 0xE4, b: 0xB5 };
static NAVAJOWHITE: RGB<u8> = RGB { r: 0xFF, g: 0xDE, b: 0xAD };
static NAVY: RGB<u8> = RGB { r: 0x00, g: 0x00, b: 0x80 };
static OLDLACE: RGB<u8> = RGB { r: 0xFD, g: 0xF5, b: 0xE6 };
static OLIVE: RGB<u8> = RGB { r: 0x80, g: 0x80, b: 0x00 };
static OLIVEDRAB: RGB<u8> = RGB { r: 0x6B, g: 0x8E, b: 0x23 };
static ORANGE: RGB<u8> = RGB { r: 0xFF, g: 0xA5, b: 0x00 };
static ORANGERED: RGB<u8> = RGB { r: 0xFF, g: 0x45, b: 0x00 };
static ORCHID: RGB<u8> = RGB { r: 0xDA, g: 0x70, b: 0xD6 };
static PALEGOLDENROD: RGB<u8> = RGB { r: 0xEE, g: 0xE8, b: 0xAA };
static PALEGREEN: RGB<u8> = RGB { r: 0x98, g: 0xFB, b: 0x98 };
static PALEVIOLETRED: RGB<u8> = RGB { r: 0xDB, g: 0x70, b: 0x93 };
static PAPAYAWHIP: RGB<u8> = RGB { r: 0xFF, g: 0xEF, b: 0xD5 };
static PEACHPUFF: RGB<u8> = RGB { r: 0xFF, g: 0xDA, b: 0xB9 };
static PERU: RGB<u8> = RGB { r: 0xCD, g: 0x85, b: 0x3F };
static PINK: RGB<u8> = RGB { r: 0xFF, g: 0xC0, b: 0xCB };
static PLUM: RGB<u8> = RGB { r: 0xDD, g: 0xA0, b: 0xDD };
static POWDERBLUE: RGB<u8> = RGB { r: 0xB0, g: 0xE0, b: 0xE6 };
static PURPLE: RGB<u8> = RGB { r: 0x80, g: 0x00, b: 0x80 };
static RED: RGB<u8> = RGB { r: 0xFF, g: 0x00, b: 0x00 };
static ROSYBROWN: RGB<u8> = RGB { r: 0xBC, g: 0x8F, b: 0x8F };
static ROYALBLUE: RGB<u8> = RGB { r: 0x41, g: 0x69, b: 0xE1 };
static SADDLEBROWN: RGB<u8> = RGB { r: 0x8B, g: 0x45, b: 0x13 };
static SALMON: RGB<u8> = RGB { r: 0xFA, g: 0x80, b: 0x72 };
static SANDYBROWN: RGB<u8> = RGB { r: 0xFA, g: 0xA4, b: 0x60 };
static SEAGREEN: RGB<u8> = RGB { r: 0x2E, g: 0x8B, b: 0x57 };
static SEASHELL: RGB<u8> = RGB { r: 0xFF, g: 0xF5, b: 0xEE };
static SIENNA: RGB<u8> = RGB { r: 0xA0, g: 0x52, b: 0x2D };
static SILVER: RGB<u8> = RGB { r: 0xC0, g: 0xC0, b: 0xC0 };
static SKYBLUE: RGB<u8> = RGB { r: 0x87, g: 0xCE, b: 0xEB };
static SLATEBLUE: RGB<u8> = RGB { r: 0x6A, g: 0x5A, b: 0xCD };
static SLATEGRAY: RGB<u8> = RGB { r: 0x70, g: 0x80, b: 0x90 };
static SNOW: RGB<u8> = RGB { r: 0xFF, g: 0xFA, b: 0xFA };
static SPRINGGREEN: RGB<u8> = RGB { r: 0x00, g: 0xFF, b: 0x7F };
static STEELBLUE: RGB<u8> = RGB { r: 0x46, g: 0x82, b: 0xB4 };
static TAN: RGB<u8> = RGB { r: 0xD2, g: 0xB4, b: 0x8C };
static TEAL: RGB<u8> = RGB { r: 0x00, g: 0x80, b: 0x80 };
static THISTLE: RGB<u8> = RGB { r: 0xD8, g: 0xBF, b: 0xD8 };
static TOMATO: RGB<u8> = RGB { r: 0xFF, g: 0x63, b: 0x47 };
static TURQUOISE: RGB<u8> = RGB { r: 0x40, g: 0xE0, b: 0xD0 };
static VIOLET: RGB<u8> = RGB { r: 0xEE, g: 0x82, b: 0xEE };
static WHEAT: RGB<u8> = RGB { r: 0xF5, g: 0xDE, b: 0xB3 };
static WHITE: RGB<u8> = RGB { r: 0xFF, g: 0xFF, b: 0xFF };
static WHITESMOKE: RGB<u8> = RGB { r: 0xF5, g: 0xF5, b: 0xF5 };
static YELLOW: RGB<u8> = RGB { r: 0xFF, g: 0xFF, b: 0x00 };
static YELLOWGREEN: RGB<u8> = RGB { r: 0x9A, g: 0xCD, b: 0x32 };
}
#[cfg(test)]
mod tests {
use color::*;
#[test]
fn test_rgb_to_rgb() {
assert_eq!(RGB::new::<u8>(0xA0, 0xA0, 0xA0).to_rgb::<u8>(), RGB::new::<u8>(0xA0, 0xA0, 0xA0));
assert_eq!(RGB::new::<u8>(0xA0, 0xA0, 0xA0).to_rgb::<u16>(), RGB::new::<u16>(0xA0A0, 0xA0A0, 0xA0A0));
}
#[test]
fn test_rgb_to_hsv() {
assert_eq!(RGB::new::<u8>(0xFF, 0xFF, 0xFF).to_hsv::<f32>(), HSV::new::<f32>(0.0, 0.0, 1.0));
assert_eq!(RGB::new::<u8>(0x99, 0x00, 0x00).to_hsv::<f32>(), HSV::new::<f32>(0.0, 1.0, 0.6));
assert_eq!(RGB::new::<u8>(0x00, 0x99, 0x00).to_hsv::<f32>(), HSV::new::<f32>(120.0, 1.0, 0.6));
assert_eq!(RGB::new::<u8>(0x00, 0x00, 0x99).to_hsv::<f32>(), HSV::new::<f32>(240.0, 1.0, 0.6));
}
#[test]
fn test_tuple_to_rgba() {
assert_eq!((RGB::new::<f64>(1.0, 1.0, 1.0), 0xFFu8).to_rgba::<f32>(), RGBA::new::<f32>(1.0, 1.0, 1.0, 1.0));
assert_eq!((RGB::new::<f64>(1.0, 1.0, 1.0), 0xFFu8).to_rgba::<f32>(), RGBA::new::<f32>(1.0, 1.0, 1.0, 1.0));
assert_eq!((RGB::new::<f64>(1.0, 1.0, 1.0), 0xFFu8).to_rgba::<f32>(), RGBA::new::<f32>(1.0, 1.0, 1.0, 1.0));
assert_eq!((RGB::new::<f64>(1.0, 1.0, 1.0), 0xFFu8).to_rgba::<f32>(), RGBA::new::<f32>(1.0, 1.0, 1.0, 1.0));
}
#[test]
fn test_rgba_to_rgba() {
assert_eq!(RGBA::new::<u8>(0xA0, 0xA0, 0xA0, 0xA0).to_rgba::<u8>(), RGBA::new::<u8>(0xA0, 0xA0, 0xA0, 0xA0));
assert_eq!(RGBA::new::<u8>(0xA0, 0xA0, 0xA0, 0xA0).to_rgba::<u16>(), RGBA::new::<u16>(0xA0A0, 0xA0A0, 0xA0A0, 0xA0A0));
}
#[test]
fn test_rgba_to_hsva() {
assert_eq!(RGBA::new::<u8>(0xFF, 0xFF, 0xFF, 0xFF).to_hsva::<f32>(), HSVA::new::<f32>(0.0, 0.0, 1.0, 1.0));
assert_eq!(RGBA::new::<u8>(0x99, 0x00, 0x00, 0xFF).to_hsva::<f32>(), HSVA::new::<f32>(0.0, 1.0, 0.6, 1.0));
assert_eq!(RGBA::new::<u8>(0x00, 0x99, 0x00, 0xFF).to_hsva::<f32>(), HSVA::new::<f32>(120.0, 1.0, 0.6, 1.0));
assert_eq!(RGBA::new::<u8>(0x00, 0x00, 0x99, 0xFF).to_hsva::<f32>(), HSVA::new::<f32>(240.0, 1.0, 0.6, 1.0));
}
}

View file

@ -1,48 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use math::*;
#[deriving(Clone, Eq)]
pub struct SRGB<T> { r: T, g: T, b: T }
impl<T> SRGB<T> {
#[inline]
pub fn new(r: T, g: T, b: T) -> SRGB<T> {
SRGB { r: r, g: g, b: b }
}
}
impl_dimensioned!(SRGB, T, 3)
impl_to_vec!(SRGB, 3)
impl_as_vec!(SRGB, 3)
impl_swap_components!(SRGB)
impl_approx!(SRGB { r, g, b })
#[deriving(Clone, Eq)]
pub struct SRGBA<T> { r: T, g: T, b: T, a: T }
impl_dimensioned!(SRGBA, T, 4)
impl_to_vec!(SRGBA, 4)
impl_as_vec!(SRGBA, 4)
impl_swap_components!(SRGBA)
impl_approx!(SRGBA { r, g, b, a })
impl<T> SRGBA<T> {
#[inline]
pub fn new(r: T, g: T, b: T, a: T) -> SRGBA<T> {
SRGBA { r: r, g: g, b: b, a: a }
}
}

View file

@ -1,34 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// http://en.wikipedia.org/wiki/YCbCr
use math::*;
#[deriving(Clone, Eq)]
pub struct YCbCr<T> { y: T, cb: T, cr: T }
impl_dimensioned!(YCbCr, T, 3)
impl_to_vec!(YCbCr, 3)
impl_as_vec!(YCbCr, 3)
impl_swap_components!(YCbCr)
impl_approx!(YCbCr { y, cb, cr })
impl<T> YCbCr<T> {
#[inline]
pub fn new(y: T, cb: T, cr: T) -> YCbCr<T> {
YCbCr { y: y, cb: cb, cr: cr }
}
}

View file

@ -36,14 +36,6 @@ pub mod math;
#[path = "bounds/bounds.rs"]
pub mod bounds;
#[cfg(color)]
#[path = "color/color.rs"]
pub mod color;
#[cfg(noise)]
#[path = "noise/noise.rs"]
pub mod noise;
#[cfg(transform)]
#[path = "transform/transform.rs"]
pub mod transform;

View file

@ -1,22 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Procedural noise generation utility types
pub use self::perlin::Perlin;
pub use self::simplex::Simplex;
pub mod perlin;
pub mod simplex;

View file

@ -1,138 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! An implementation of Ken Perlin's [Improved Noise]
//! (http://mrl.nyu.edu/~perlin/noise/) algorithm.
use std::num::cast;
use math::Dimensioned;
pub struct Perlin<T> {
// permutation table
priv ptable: [uint, ..512],
}
impl<T:Clone + Float> Perlin<T> {
pub fn new() -> Perlin<T> {
// TODO: generate random permutation table
Perlin { ptable: P }
}
pub fn noise1<V:Dimensioned<T,[T,..1]>>(&self, v: V) -> T {
self.noise3([v.i(0).clone(), zero!(T), zero!(T)])
}
pub fn noise2<V:Dimensioned<T,[T,..2]>>(&self, v: V) -> T {
self.noise3([v.i(0).clone(), v.i(1).clone(), zero!(T)])
}
pub fn noise3<V:Dimensioned<T,[T,..3]>>(&self, v: V) -> T {
// Find the unit cube that contains the point
let X = v.i(0).floor().to_uint() & 255;
let Y = v.i(1).floor().to_uint() & 255;
let Z = v.i(2).floor().to_uint() & 255;
// Find the relative X, Y, Z of point in the cube
let x = *v.i(0) - v.i(0).floor();
let y = *v.i(1) - v.i(1).floor();
let z = *v.i(2) - v.i(2).floor();
// Compute the fade curves for X, Y, Z
let u = fade(x.clone());
let v = fade(y.clone());
let w = fade(z.clone());
// Hash coordinates of the 8 cube corners
let A = self.ptable[X ] + Y;
let AA = self.ptable[A ] + Z;
let AB = self.ptable[A + 1] + Z;
let B = self.ptable[X + 1] + Y;
let BA = self.ptable[B ] + Z;
let BB = self.ptable[B + 1] + Z;
// Add the blended results from the 8 corners of the cube
lerp(w, lerp(v.clone(), lerp(u.clone(), grad(self.ptable[AA ], x.clone(), y.clone(), z.clone()),
grad(self.ptable[BA ], x-one!(T), y.clone(), z.clone())),
lerp(u.clone(), grad(self.ptable[AB ], x.clone(), y-one!(T), z.clone()),
grad(self.ptable[BB ], x-one!(T), y-one!(T), z.clone()))),
lerp(v.clone(), lerp(u.clone(), grad(self.ptable[AA + 1], x.clone(), y.clone(), z-one!(T)),
grad(self.ptable[BA + 1], x-one!(T), y.clone(), z-one!(T))),
lerp(u.clone(), grad(self.ptable[AB + 1], x.clone(), y-one!(T), z-one!(T)),
grad(self.ptable[BB + 1], x-one!(T), y-one!(T), z-one!(T)))))
}
}
fn fade<T:Num + NumCast>(t: T) -> T {
t * t * t * (t * (t * cast(6) - cast(15)) + cast(10))
}
fn lerp<T:Num + NumCast>(t: T, a: T, b: T) -> T {
a + t * (b - a)
}
fn grad<T:Clone + Num + NumCast>(hash: uint, x: T, y: T, z: T) -> T {
let h = hash & 15;
let u = match h {
0..7 => x.clone(),
_ => y.clone(),
};
let v = match h {
0..3 => y.clone(),
12 | 14 => x.clone(),
_ => z.clone(),
};
(if (h & 1) == 0 { u } else { -u }) +
(if (h & 2) == 0 { v } else { -v })
}
/// Permutation table
static P: [uint, ..512] = [
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,
140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148,
247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32,
57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54,
65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169,
200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64,
52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212,
207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,
140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148,
247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32,
57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54,
65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169,
200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64,
52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212,
207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
];

View file

@ -1,36 +0,0 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use math::Dimensioned;
pub struct Simplex<T>;
impl<T> Simplex<T> {
pub fn new() -> Simplex<T> {
fail!("Not yet implemented!")
}
pub fn noise2<V:Dimensioned<T,[T,..2]>>(&self, _v: V) -> T {
fail!("Not yet implemented!")
}
pub fn noise3<V:Dimensioned<T,[T,..3]>>(&self, _v: V) -> T {
fail!("Not yet implemented!")
}
pub fn noise4<V:Dimensioned<T,[T,..4]>>(&self, _v: V) -> T {
fail!("Not yet implemented!")
}
}