1 use super::pixel::*; 2 use crate::alt::BGR; 3 use crate::alt::BGRA; 4 use crate::RGB; 5 use crate::RGBA; 6 use core::fmt; 7 8 impl<T> RGB<T> { 9 /// Convenience function for creating a new pixel 10 /// The order of arguments is R,G,B 11 #[inline(always)] new(r: T, g: T, b: T) -> Self12 pub const fn new(r: T, g: T, b: T) -> Self { 13 Self { r, g, b } 14 } 15 } 16 17 impl<T> BGR<T> { 18 /// Convenience function for creating a new pixel 19 /// Wargning: The order of arguments is R,G,B 20 #[deprecated(note="This function has a misleading order of arguments. Use BGR{} literal instead")] 21 #[inline(always)] new(r: T, g: T, b: T) -> Self22 pub const fn new(r: T, g: T, b: T) -> Self { 23 Self { b, g, r } 24 } 25 } 26 27 #[cfg(feature = "as-bytes")] 28 unsafe impl<T> crate::Pod for RGB<T> where T: crate::Pod {} 29 #[cfg(feature = "as-bytes")] 30 unsafe impl<T> crate::Pod for BGR<T> where T: crate::Pod {} 31 #[cfg(feature = "as-bytes")] 32 unsafe impl<T> crate::Zeroable for RGB<T> where T: crate::Zeroable {} 33 #[cfg(feature = "as-bytes")] 34 unsafe impl<T> crate::Zeroable for BGR<T> where T: crate::Zeroable {} 35 36 macro_rules! impl_rgb { 37 ($RGB:ident, $RGBA:ident) => { 38 impl<T: Clone> $RGB<T> { 39 /// Iterate over color components (R, G, and B) 40 #[inline(always)] 41 pub fn iter(&self) -> core::iter::Cloned<core::slice::Iter<'_, T>> { 42 self.as_slice().iter().cloned() 43 } 44 45 /// Convenience function for converting to RGBA 46 #[inline(always)] 47 pub fn alpha(&self, a: T) -> $RGBA<T> { 48 $RGBA { 49 r: self.r.clone(), 50 g: self.g.clone(), 51 b: self.b.clone(), 52 a, 53 } 54 } 55 56 /// Convenience function for converting to RGBA with alpha channel of a different type than type of the pixels 57 #[inline(always)] 58 pub fn new_alpha<A>(&self, a: A) -> $RGBA<T, A> { 59 $RGBA { 60 r: self.r.clone(), 61 g: self.g.clone(), 62 b: self.b.clone(), 63 a, 64 } 65 } 66 } 67 68 impl<T: Copy, B> ComponentMap<$RGB<B>, T, B> for $RGB<T> { 69 #[inline(always)] 70 fn map<F>(&self, mut f: F) -> $RGB<B> 71 where F: FnMut(T) -> B { 72 $RGB { 73 r:f(self.r), 74 g:f(self.g), 75 b:f(self.b), 76 } 77 } 78 } 79 80 impl<T: Copy, B> ColorComponentMap<$RGB<B>, T, B> for $RGB<T> { 81 #[inline(always)] 82 fn map_c<F>(&self, mut f: F) -> $RGB<B> 83 where F: FnMut(T) -> B { 84 $RGB { 85 r:f(self.r), 86 g:f(self.g), 87 b:f(self.b), 88 } 89 } 90 } 91 92 impl<T> ComponentSlice<T> for $RGB<T> { 93 #[inline(always)] 94 fn as_slice(&self) -> &[T] { 95 unsafe { 96 core::slice::from_raw_parts(self as *const Self as *const T, 3) 97 } 98 } 99 100 #[inline(always)] 101 fn as_mut_slice(&mut self) -> &mut [T] { 102 unsafe { 103 core::slice::from_raw_parts_mut(self as *mut Self as *mut T, 3) 104 } 105 } 106 } 107 108 impl<T> ComponentSlice<T> for [$RGB<T>] { 109 #[inline] 110 fn as_slice(&self) -> &[T] { 111 unsafe { 112 core::slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 3) 113 } 114 } 115 116 #[inline] 117 fn as_mut_slice(&mut self) -> &mut [T] { 118 unsafe { 119 core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut _, self.len() * 3) 120 } 121 } 122 } 123 124 #[cfg(feature = "as-bytes")] 125 impl<T: crate::Pod> ComponentBytes<T> for [$RGB<T>] {} 126 } 127 } 128 129 impl<T> core::iter::FromIterator<T> for RGB<T> { 130 /// Takes exactly 3 elements from the iterator and creates a new instance. 131 /// Panics if there are fewer elements in the iterator. 132 #[inline(always)] from_iter<I: IntoIterator<Item = T>>(into_iter: I) -> Self133 fn from_iter<I: IntoIterator<Item = T>>(into_iter: I) -> Self { 134 let mut iter = into_iter.into_iter(); 135 Self { 136 r: iter.next().unwrap(), 137 g: iter.next().unwrap(), 138 b: iter.next().unwrap(), 139 } 140 } 141 } 142 143 impl_rgb!{RGB, RGBA} 144 impl_rgb!{BGR, BGRA} 145 146 impl<T: fmt::Display> fmt::Display for RGB<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 148 write!(f,"rgb({},{},{})", self.r,self.g,self.b) 149 } 150 } 151 152 impl<T: fmt::UpperHex> fmt::UpperHex for RGB<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 154 write!(f,"RGB {{ #{:02X}{:02X}{:02X} }}", self.r, self.g, self.b) 155 } 156 } 157 158 impl<T: fmt::LowerHex> fmt::LowerHex for RGB<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 160 write!(f,"RGB {{ #{:02x}{:02x}{:02x} }}", self.r, self.g, self.b) 161 } 162 } 163 164 impl<T: fmt::Display> fmt::Display for BGR<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 166 write!(f,"bgr({},{},{})", self.b, self.g, self.r) 167 } 168 } 169 170 impl<T: fmt::UpperHex> fmt::UpperHex for BGR<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 172 write!(f,"BGR {{ #{:02X}{:02X}{:02X} }}", self.b, self.g, self.r) 173 } 174 } 175 176 impl<T: fmt::LowerHex> fmt::LowerHex for BGR<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 178 write!(f,"BGR {{ #{:02x}{:02x}{:02x} }}", self.b, self.g, self.r) 179 } 180 } 181 182 #[cfg(test)] 183 mod rgb_test { 184 use super::*; 185 use std; 186 #[test] sanity_check()187 fn sanity_check() { 188 let neg = RGB::new(1,2,3i32).map(|x| -x); 189 assert_eq!(neg.r, -1); 190 assert_eq!(neg.g, -2); 191 assert_eq!(neg.b, -3); 192 193 let mut px = RGB::new(3,4,5); 194 px.as_mut_slice()[1] = 111; 195 assert_eq!(111, px.g); 196 197 assert_eq!(RGBA::new(250,251,252,253), RGB::new(250,251,252).alpha(253)); 198 199 assert_eq!(RGB{r:1u8,g:2,b:3}, RGB::new(1u8,2,3)); 200 assert!(RGB{r:1u8,g:1,b:2} < RGB::new(2,1,1)); 201 202 let mut h = std::collections::HashSet::new(); 203 h.insert(px); 204 assert!(h.contains(&RGB::new(3,111,5))); 205 assert!(!h.contains(&RGB::new(111,5,3))); 206 207 208 #[cfg(feature = "as-bytes")] 209 { 210 let v = vec![RGB::new(1u8,2,3), RGB::new(4,5,6)]; 211 assert_eq!(&[1,2,3,4,5,6], v.as_bytes()); 212 } 213 214 assert_eq!(RGB::new(0u8,0,0), Default::default()); 215 } 216 217 #[test] 218 #[allow(deprecated)] test_fmt()219 fn test_fmt() { 220 let red_rgb = RGB::new(255, 0, 0); 221 let red_bgr = BGR::new(255, 0, 0); 222 assert_eq!("RGB { #FF0000 }", &format!("{:X}", red_rgb)); 223 assert_eq!("BGR { #0000FF }", &format!("{:X}", red_bgr)); 224 225 assert_eq!("RGB { #ff0000 }", &format!("{:x}", red_rgb)); 226 assert_eq!("BGR { #0000ff }", &format!("{:x}", red_bgr)); 227 228 assert_eq!("rgb(255,0,0)", &format!("{}", red_rgb)); 229 assert_eq!("bgr(0,0,255)", &format!("{}", red_bgr)); 230 } 231 } 232