1use core::fmt;
2use crate::alt::*;
3use crate::RGB;
4use crate::RGBA;
5use super::pixel::*;
6
7impl<T> RGBA<T> {
8 #[inline(always)]
9 /// Convenience function for creating a new pixel
10 /// The order of arguments is R,G,B,A
11 pub const fn new(r: T, g: T, b: T, a: T) -> Self {
12 Self {r,g,b,a}
13 }
14}
15
16impl<T, A> RGBA<T,A> {
17 #[inline(always)]
18 /// Convenience function for creating a new pixel
19 /// The order of arguments is R,G,B,A
20 pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self {
21 Self {r,g,b,a}
22 }
23}
24
25impl<T> BGRA<T> {
26 #[inline(always)]
27 /// Convenience function for creating a new pixel
28 /// Warning: The order of arguments is R,G,B,A
29 #[deprecated(note="This function has a misleading order of arguments. Use BGRA{} literal instead")]
30 pub const fn new(r: T, g: T, b: T, a: T) -> Self {
31 Self {r,g,b,a}
32 }
33}
34
35impl<T, A> BGRA<T,A> {
36 #[inline(always)]
37 /// Convenience function for creating a new pixel
38 /// Warning: The order of arguments is R,G,B,A
39 #[deprecated(note="This function has a misleading order of arguments. Use BGRA{} literal instead")]
40 pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self {
41 Self {r,g,b,a}
42 }
43}
44
45#[cfg(feature = "as-bytes")]
46unsafe impl<T, A> crate::Pod for RGBA<T, A> where T: crate::Pod, A: crate::Pod {}
47#[cfg(feature = "as-bytes")]
48unsafe impl<T, A> crate::Pod for BGRA<T, A> where T: crate::Pod, A: crate::Pod {}
49#[cfg(feature = "as-bytes")]
50unsafe impl<T, A> crate::Zeroable for RGBA<T, A> where T: crate::Zeroable, A: crate::Zeroable {}
51#[cfg(feature = "as-bytes")]
52unsafe impl<T, A> crate::Zeroable for BGRA<T, A> where T: crate::Zeroable, A: crate::Zeroable {}
53
54#[cfg(feature = "argb")]
55impl<T> ARGB<T> {
56 #[inline(always)]
57 /// Convenience function for creating a new pixel
58 /// The order of arguments is R,G,B,A
59 #[deprecated(note="This function has a misleading order of arguments. Use ARGB{} literal instead")]
60 pub const fn new(r: T, g: T, b: T, a: T) -> Self {
61 Self {r,g,b,a}
62 }
63}
64
65#[cfg(feature = "argb")]
66impl<T, A> ARGB<T,A> {
67 #[inline(always)]
68 /// Convenience function for creating a new pixel
69 /// The order of arguments is R,G,B,A
70 #[deprecated(note="This function has a misleading order of arguments. Use ARGB{} literal instead")]
71 pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self {
72 Self {r,g,b,a}
73 }
74}
75
76#[cfg(feature = "argb")]
77impl<T> ABGR<T> {
78 #[inline(always)]
79 /// Convenience function for creating a new pixel
80 /// The order of arguments is R,G,B,A
81 #[deprecated(note="This function has a misleading order of arguments. Use ABGR{} literal instead")]
82 pub const fn new(r: T, g: T, b: T, a: T) -> Self {
83 Self {r,g,b,a}
84 }
85}
86
87#[cfg(feature = "argb")]
88impl<T, A> ABGR<T,A> {
89 #[inline(always)]
90 /// Convenience function for creating a new pixel
91 /// The order of arguments is R,G,B,A
92 #[deprecated(note="This function has a misleading order of arguments. Use ABGR{} literal instead")]
93 pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self {
94 Self {r,g,b,a}
95 }
96}
97
98#[cfg(all(feature = "as-bytes", feature = "argb"))]
99unsafe impl<T, A> crate::Pod for ARGB<T, A> where T: crate::Pod, A: crate::Pod {}
100#[cfg(all(feature = "as-bytes", feature = "argb"))]
101unsafe impl<T, A> crate::Pod for ABGR<T, A> where T: crate::Pod, A: crate::Pod {}
102#[cfg(all(feature = "as-bytes", feature = "argb"))]
103unsafe impl<T, A> crate::Zeroable for ARGB<T, A> where T: crate::Zeroable, A: crate::Zeroable {}
104#[cfg(all(feature = "as-bytes", feature = "argb"))]
105unsafe impl<T, A> crate::Zeroable for ABGR<T, A> where T: crate::Zeroable, A: crate::Zeroable {}
106
107macro_rules! impl_rgba {
108 ($RGBA:ident) => {
109 impl<T: Clone> $RGBA<T> {
110 /// Iterate over all components (length=4)
111 #[inline(always)]
112 pub fn iter(&self) -> core::iter::Cloned<core::slice::Iter<'_, T>> {
113 self.as_slice().iter().cloned()
114 }
115 }
116
117 impl<T: Clone, A> $RGBA<T, A> {
118 /// Copy RGB components out of the RGBA struct
119 ///
120 /// Note: you can use `.into()` to convert between other types
121 #[inline(always)]
122 pub fn bgr(&self) -> BGR<T> {
123 BGR {r:self.r.clone(), g:self.g.clone(), b:self.b.clone()}
124 }
125 }
126
127 impl<T: Copy, A: Clone> $RGBA<T, A> {
128 /// Create new RGBA with the same alpha value, but different RGB values
129 #[inline(always)]
130 pub fn map_rgb<F, U, B>(&self, mut f: F) -> $RGBA<U, B>
131 where F: FnMut(T) -> U, U: Clone, B: From<A> + Clone
132 {
133 $RGBA {
134 r: f(self.r),
135 g: f(self.g),
136 b: f(self.b),
137 a: self.a.clone().into(),
138 }
139 }
140
141 #[inline(always)]
142 /// Create a new RGBA with the new alpha value, but same RGB values
143 pub fn alpha(&self, a: A) -> Self {
144 Self {
145 r: self.r, g: self.g, b: self.b, a,
146 }
147 }
148
149 /// Create a new RGBA with a new alpha value created by the callback.
150 /// Allows changing of the type used for the alpha channel.
151 #[inline]
152 pub fn map_alpha<F, B>(&self, f: F) -> $RGBA<T, B>
153 where F: FnOnce(A) -> B {
154 $RGBA {
155 r: self.r,
156 g: self.g,
157 b: self.b,
158 a: f(self.a.clone()),
159 }
160 }
161 }
162
163 impl<T: Copy, B> ComponentMap<$RGBA<B>, T, B> for $RGBA<T> {
164 #[inline(always)]
165 fn map<F>(&self, mut f: F) -> $RGBA<B>
166 where
167 F: FnMut(T) -> B,
168 {
169 $RGBA {
170 r: f(self.r),
171 g: f(self.g),
172 b: f(self.b),
173 a: f(self.a),
174 }
175 }
176 }
177
178 impl<T: Copy, A: Copy, B> ColorComponentMap<$RGBA<B, A>, T, B> for $RGBA<T, A> {
179 #[inline(always)]
180 fn map_c<F>(&self, mut f: F) -> $RGBA<B, A>
181 where
182 F: FnMut(T) -> B,
183 {
184 $RGBA {
185 r: f(self.r),
186 g: f(self.g),
187 b: f(self.b),
188 a: self.a,
189 }
190 }
191 }
192
193 impl<T> ComponentSlice<T> for $RGBA<T> {
194 #[inline(always)]
195 fn as_slice(&self) -> &[T] {
196 unsafe {
197 core::slice::from_raw_parts(self as *const Self as *const T, 4)
198 }
199 }
200
201 #[inline(always)]
202 fn as_mut_slice(&mut self) -> &mut [T] {
203 unsafe {
204 core::slice::from_raw_parts_mut(self as *mut Self as *mut T, 4)
205 }
206 }
207 }
208
209 impl<T> ComponentSlice<T> for [$RGBA<T>] {
210 #[inline]
211 fn as_slice(&self) -> &[T] {
212 unsafe {
213 core::slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 4)
214 }
215 }
216 #[inline]
217 fn as_mut_slice(&mut self) -> &mut [T] {
218 unsafe {
219 core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut _, self.len() * 4)
220 }
221 }
222 }
223
224 #[cfg(feature = "as-bytes")]
225 impl<T: crate::Pod> ComponentBytes<T> for [$RGBA<T>] {}
226 }
227}
228
229macro_rules! impl_alpha_conv {
230 ($RGB:ident, $RGBA:ident) => {
231 /// Assumes 255 is opaque
232 impl<T: Copy> From<$RGB<T>> for $RGBA<T, u8> {
233 #[inline(always)]
234 fn from(other: $RGB<T>) -> Self {
235 Self {
236 r: other.r,
237 g: other.g,
238 b: other.b,
239 a: 0xFF,
240 }
241 }
242 }
243
244 /// Assumes 65535 is opaque
245 impl<T: Copy> From<$RGB<T>> for $RGBA<T, u16> {
246 #[inline(always)]
247 fn from(other: $RGB<T>) -> Self {
248 Self {
249 r: other.r,
250 g: other.g,
251 b: other.b,
252 a: 0xFFFF,
253 }
254 }
255 }
256 }
257}
258
259impl<T, A> RGBA<T, A> {
260 /// Provide a mutable view of only RGB components (leaving out alpha).
261 /// Useful to change color without changing opacity.
262 #[inline(always)]
263 pub fn rgb_mut(&mut self) -> &mut RGB<T> {
264 unsafe {
265 &mut *(self as *mut _ as *mut RGB<T>)
266 }
267 }
268}
269
270impl<T, A> BGRA<T, A> {
271 /// Provide a mutable view of only RGB components (leaving out alpha).
272 /// Useful to change color without changing opacity.
273 #[inline(always)]
274 #[deprecated(note = "This function will change. Use bgr_mut()")]
275 pub fn rgb_mut(&mut self) -> &mut BGR<T> {
276 unsafe {
277 &mut *(self as *mut _ as *mut BGR<T>)
278 }
279 }
280
281 /// Provide a mutable view of only RGB components (leaving out alpha).
282 /// Useful to change color without changing opacity.
283 #[inline(always)]
284 pub fn bgr_mut(&mut self) -> &mut BGR<T> {
285 unsafe {
286 &mut *(self as *mut _ as *mut BGR<T>)
287 }
288 }
289}
290
291impl<T> core::iter::FromIterator<T> for RGBA<T> {
292 #[inline(always)]
293 /// Takes exactly 4 elements from the iterator and creates a new instance.
294 /// Panics if there are fewer elements in the iterator.
295 fn from_iter<I: IntoIterator<Item = T>>(into_iter: I) -> Self {
296 let mut iter: ::IntoIter = into_iter.into_iter();
297 Self {
298 r: iter.next().unwrap(),
299 g: iter.next().unwrap(),
300 b: iter.next().unwrap(),
301 a: iter.next().unwrap(),
302 }
303 }
304}
305
306impl<T: Clone, A> RGBA<T, A> {
307 /// Copy RGB components out of the RGBA struct
308 ///
309 /// Note: you can use `.into()` to convert between other types
310 #[inline(always)]
311 pub fn rgb(&self) -> RGB<T> {
312 RGB {r:self.r.clone(), g:self.g.clone(), b:self.b.clone()}
313 }
314}
315
316#[cfg(feature = "argb")]
317impl<T: Clone, A> ARGB<T, A> {
318 /// Copy RGB components out of the ARGB struct
319 ///
320 /// Note: you can use `.into()` to convert between other types
321 #[inline(always)]
322 pub fn rgb(&self) -> RGB<T> {
323 RGB {r:self.r.clone(), g:self.g.clone(), b:self.b.clone()}
324 }
325}
326
327impl<T: Clone, A> BGRA<T, A> {
328 /// Copy RGB components out of the RGBA struct
329 ///
330 /// Note: you can use `.into()` to convert between other types
331 #[inline(always)]
332 #[deprecated(note = "This function will change. Use bgr()")]
333 pub fn rgb(&self) -> BGR<T> {
334 BGR {r:self.r.clone(), g:self.g.clone(), b:self.b.clone()}
335 }
336}
337
338impl_rgba! {RGBA}
339impl_rgba! {BGRA}
340#[cfg(feature = "argb")]
341impl_rgba! {ARGB}
342#[cfg(feature = "argb")]
343impl_rgba! {ABGR}
344
345impl_alpha_conv! {BGR, BGRA}
346impl_alpha_conv! {RGB, BGRA}
347impl_alpha_conv! {BGR, RGBA}
348impl_alpha_conv! {RGB, RGBA}
349#[cfg(feature = "argb")]
350impl_alpha_conv! {BGR, ABGR}
351#[cfg(feature = "argb")]
352impl_alpha_conv! {RGB, ABGR}
353#[cfg(feature = "argb")]
354impl_alpha_conv! {BGR, ARGB}
355#[cfg(feature = "argb")]
356impl_alpha_conv! {RGB, ARGB}
357
358impl<T: fmt::Display, A: fmt::Display> fmt::Display for RGBA<T, A> {
359 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360 write!(f, "rgba({},{},{},{})", self.r, self.g, self.b, self.a)
361 }
362}
363
364impl<T: fmt::Display, A: fmt::Display> fmt::Display for BGRA<T, A> {
365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366 write!(f, "bgra({},{},{},{})", self.r, self.g, self.b, self.a)
367 }
368}
369
370#[test]
371fn rgba_test() {
372 let neg = RGBA::new(1,2,3i32,1000).map(|x| -x);
373 assert_eq!(neg.r, -1);
374 assert_eq!(neg.rgb().r, -1);
375 assert_eq!(neg.g, -2);
376 assert_eq!(neg.rgb().g, -2);
377 assert_eq!(neg.b, -3);
378 assert_eq!(neg.rgb().b, -3);
379 assert_eq!(neg.a, -1000);
380 assert_eq!(neg.map_alpha(|x| x+1).a, -999);
381 assert_eq!(neg, neg.as_slice().iter().cloned().collect());
382 assert!(neg < RGBA::new(0,0,0,0));
383
384 let neg = RGBA::new(1u8,2,3,4).map_rgb(|c| -(c as i16));
385 assert_eq!(-1i16, neg.r);
386 assert_eq!(4i16, neg.a);
387 let neg = RGBA::new(1u8,2,3,4).map_c(|c| -(c as i16));
388 assert_eq!(-1i16, neg.r);
389 assert_eq!(4u8, neg.a);
390
391 let mut px = RGBA{r:1,g:2,b:3,a:4};
392 px.as_mut_slice()[3] = 100;
393 assert_eq!(1, px.rgb_mut().r);
394 assert_eq!(2, px.rgb_mut().g);
395 px.rgb_mut().b = 4;
396 assert_eq!(4, px.rgb_mut().b);
397 assert_eq!(100, px.a);
398
399 #[cfg(feature = "as-bytes")]
400 {
401 let v = vec![RGBA::new(1u8,2,3,4), RGBA::new(5,6,7,8)];
402 assert_eq!(&[1,2,3,4,5,6,7,8], v.as_bytes());
403 }
404}
405
406#[test]
407#[cfg(feature = "argb")]
408fn abgr_test() {
409 let abgr = ABGR {r:1,g:2,b:3,a:4};
410 assert_eq!(4, abgr.as_slice()[0]);
411 use crate::AsPixels;
412 assert_eq!(abgr, [abgr].as_bytes().as_pixels()[0]);
413}
414
415#[test]
416#[allow(deprecated)]
417fn bgra_test() {
418 let neg = BGRA::new(1, 2, 3i32, 1000).map(|x| -x);
419 let _ = neg.as_slice();
420
421 #[cfg(feature = "as-bytes")]
422 {
423 let _ = [neg].as_bytes();
424 }
425 assert_eq!(neg.r, -1);
426 assert_eq!(neg.bgr().r, -1);
427 assert_eq!(neg.g, -2);
428 assert_eq!(neg.bgr().g, -2);
429 assert_eq!(neg.b, -3);
430 assert_eq!(neg.bgr().b, -3);
431 assert_eq!(neg.a, -1000);
432 assert_eq!(&[-3,-2,-1,-1000], neg.as_slice());
433 assert!(neg < BGRA::new(0, 0, 0, 0));
434
435 let neg = BGRA::new(1u8, 2u8, 3u8, 4u8).map_rgb(|c| -(c as i16));
436 assert_eq!(-1i16, neg.r);
437 assert_eq!(4i16, neg.a);
438 let neg = BGRA::new(1u8, 2u8, 3u8, 4u8).map_c(|c| -(c as i16));
439 assert_eq!(-1i16, neg.r);
440 assert_eq!(4u8, neg.a);
441
442 let mut px = BGRA{r:1,g:2,b:3,a:-9}.alpha(4);
443 px.as_mut_slice()[3] = 100;
444 assert_eq!(1, px.bgr_mut().r);
445 assert_eq!(2, px.bgr_mut().g);
446 px.bgr_mut().b = 4;
447 assert_eq!(4, px.bgr_mut().b);
448 assert_eq!(100, px.a);
449
450
451 #[cfg(feature = "as-bytes")]
452 {
453 let v = vec![BGRA::new(3u8, 2, 1, 4), BGRA::new(7, 6, 5, 8)];
454 assert_eq!(&[1,2,3,4,5,6,7,8], v.as_bytes());
455 }
456}
457