1use crate::*;
2
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5#[derive(Debug, Clone, PartialEq, PartialOrd)]
6pub struct Pixel<C: Color>(Box<[f64]>, std::marker::PhantomData<C>);
7
8impl<C: Color> AsRef<[f64]> for Pixel<C> {
9 fn as_ref(&self) -> &[f64] {
10 self.0.as_ref()
11 }
12}
13
14impl<C: Color> AsMut<[f64]> for Pixel<C> {
15 fn as_mut(&mut self) -> &mut [f64] {
16 self.0.as_mut()
17 }
18}
19
20impl<C: Color> Default for Pixel<C> {
21 fn default() -> Self {
22 Pixel::new()
23 }
24}
25
26impl<C: Color> From<&[f64]> for Pixel<C> {
27 fn from(data: &[f64]) -> Self {
28 let mut px = Pixel::new();
29 px.copy_from_slice(data);
30 px
31 }
32}
33
34impl<C: Color> From<Vec<f64>> for Pixel<C> {
35 fn from(data: Vec<f64>) -> Self {
36 let data = data.into_boxed_slice();
37 Pixel(data, std::marker::PhantomData)
38 }
39}
40
41impl<C: Color> Pixel<C> {
42 pub fn new() -> Pixel<C> {
44 let data = match C::CHANNELS {
45 1 => Box::new([0.0; 1]) as Box<[f64]>,
46 2 => Box::new([0.0; 2]),
47 3 => Box::new([0.0; 3]),
48 4 => Box::new([0.0; 4]),
49 5 => Box::new([0.0; 5]),
50 _ => vec![0.0; C::CHANNELS].into_boxed_slice(),
51 };
52
53 let mut px = Pixel(data, std::marker::PhantomData);
54 px.with_alpha(1.0);
55 px
56 }
57
58 pub fn with_color<D: Color>(self) -> Pixel<D> {
60 assert!(C::CHANNELS == D::CHANNELS);
61 Pixel(self.0, std::marker::PhantomData)
62 }
63
64 pub fn data(&self) -> Data<f64, C> {
66 Data::new(self.as_ref())
67 }
68
69 pub fn data_mut(&mut self) -> DataMut<f64, C> {
71 DataMut::new(self.as_mut())
72 }
73
74 pub fn into_vec(self) -> Vec<f64> {
76 self.0.into_vec()
77 }
78
79 pub fn to_vec(&self) -> Vec<f64> {
81 self.0.to_vec()
82 }
83
84 pub fn fill<T: Type>(&mut self, x: T) -> &mut Self {
86 self.0.iter_mut().for_each(|a| *a = x.to_norm());
87 self
88 }
89
90 pub fn len(&self) -> Channel {
92 C::CHANNELS
93 }
94
95 pub fn is_empty(&self) -> bool {
97 self.len() == 0
98 }
99
100 pub fn clamp(&mut self) -> &mut Self {
102 self.map(|x| x.clamp(0., 1.))
103 }
104
105 pub fn clamped(mut self) -> Self {
107 self.clamp();
108 self
109 }
110
111 pub fn is_alpha(&self, index: Channel) -> bool {
113 if let Some(alpha) = C::ALPHA {
114 return alpha == index;
115 }
116
117 false
118 }
119
120 pub fn alpha(&self) -> Option<f64> {
122 C::ALPHA.map(|x| self[x])
123 }
124
125 pub fn with_alpha(&mut self, value: f64) -> &mut Self {
127 if let Some(alpha) = C::ALPHA {
128 (*self)[alpha] = value
129 }
130 self
131 }
132
133 pub fn convert_to<D: Color>(&self, dest: &mut Pixel<D>) {
135 let mut tmp = Pixel::new();
136 C::to_rgb(self, &mut tmp);
137 D::from_rgb(&tmp, dest);
138 }
139
140 pub fn convert<D: Color>(&self) -> Pixel<D> {
142 let mut dest = Pixel::new();
143 self.convert_to(&mut dest);
144 dest
145 }
146
147 #[inline]
149 pub fn copy_from_slice<T: Type>(&mut self, data: impl AsRef<[T]>) -> &mut Self {
150 let data = data.as_ref();
151 self.0.iter_mut().enumerate().for_each(|(i, x)| {
152 *x = data[i].to_norm();
153 });
154 self
155 }
156
157 #[inline]
159 pub fn copy_from_data<T: Type>(&mut self, data: &Data<T, C>) -> &mut Self {
160 let data = data.as_ref();
161 self.0.iter_mut().enumerate().for_each(|(i, x)| {
162 *x = data[i].to_norm();
163 });
164 self
165 }
166
167 pub fn convert_from_data<T: Type, D: Color>(&mut self, data: &Data<T, D>) {
169 Pixel::from_data(data).convert_to(self)
170 }
171
172 pub fn convert_to_data<T: Type, D: Color>(&self, data: &mut DataMut<T, D>) {
174 let d = self.convert::<D>();
175 d.copy_to_slice(data)
176 }
177
178 pub fn copy_to_slice<T: Type>(&self, mut data: impl AsMut<[T]>) {
180 let data = data.as_mut();
181 self.0.iter().enumerate().for_each(|(i, x)| {
182 data[i] = T::from_norm(*x);
183 });
184 }
185
186 pub fn from_slice<T: Type>(data: impl AsRef<[T]>) -> Pixel<C> {
188 let mut px = Pixel::new();
189 px.copy_from_slice(data);
190 px
191 }
192
193 pub fn from_data<T: Type>(data: &Data<T, C>) -> Pixel<C> {
195 let mut px = Pixel::new();
196 px.copy_from_slice(data);
197 px
198 }
199
200 pub fn copy_from(&mut self, other: &Pixel<C>) -> &mut Self {
202 self.map2(other, |_, b| b)
203 }
204
205 pub fn blend_alpha(&mut self) -> &mut Self {
207 if let Some(index) = C::ALPHA {
208 let alpha = self[index];
209
210 self.map(|x| x * alpha);
211 (*self)[index] = 1.0;
212 }
213
214 self
215 }
216
217 pub fn map(&mut self, f: impl Fn(f64) -> f64) -> &mut Self {
219 self.iter_mut().for_each(|x| *x = f(*x));
220 self
221 }
222
223 pub fn map2(&mut self, other: &Pixel<C>, f: impl Fn(f64, f64) -> f64) -> &mut Self {
225 self.iter_mut()
226 .zip(other.iter())
227 .for_each(|(x, y)| *x = f(*x, *y));
228 self
229 }
230
231 pub fn for_each(&self, mut f: impl FnMut(usize, f64)) {
233 for i in 0..self.len() {
234 f(i, self[i])
235 }
236 }
237
238 pub fn iter(&self) -> impl Iterator<Item = &f64> {
240 let iter = self.0.iter();
241
242 let alpha = C::ALPHA.unwrap_or(std::usize::MAX);
243 iter.enumerate()
244 .filter_map(move |(idx, item)| if idx != alpha { Some(item) } else { None })
245 }
246
247 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut f64> {
249 let iter = self.0.iter_mut();
250 let alpha = C::ALPHA.unwrap_or(std::usize::MAX);
251 iter.enumerate()
252 .filter_map(move |(idx, item)| if idx != alpha { Some(item) } else { None })
253 }
254
255 pub fn gamma(&mut self, value: f64) -> &mut Self {
257 self.map(|x| x.powf(value))
258 }
259
260 pub fn gamma_log(&mut self) -> &mut Self {
262 self.gamma(1. / 2.2)
263 }
264
265 pub fn gamma_lin(&mut self) -> &mut Self {
267 self.gamma(2.2)
268 }
269}
270
271impl<T: Type, C: Color> std::iter::FromIterator<T> for Pixel<C> {
272 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
273 Pixel(
274 iter.into_iter().map(|x| x.to_norm()).collect(),
275 std::marker::PhantomData,
276 )
277 }
278}
279
280impl<C: Color> IntoIterator for Pixel<C> {
281 type Item = f64;
282 type IntoIter = std::vec::IntoIter<Self::Item>;
283
284 fn into_iter(self) -> Self::IntoIter {
285 self.0.into_vec().into_iter()
286 }
287}
288
289impl<C: Color> std::ops::Index<Channel> for Pixel<C> {
290 type Output = f64;
291 fn index(&self, index: Channel) -> &f64 {
292 &self.0[index]
293 }
294}
295
296impl<'a, C: Color> std::ops::Index<Channel> for &'a Pixel<C> {
297 type Output = f64;
298 fn index(&self, index: Channel) -> &f64 {
299 &self.0[index]
300 }
301}
302
303impl<'a, C: Color> std::ops::Index<Channel> for &'a mut Pixel<C> {
304 type Output = f64;
305 fn index(&self, index: Channel) -> &f64 {
306 &self.0[index]
307 }
308}
309
310impl<C: Color> std::ops::IndexMut<Channel> for Pixel<C> {
311 fn index_mut(&mut self, index: Channel) -> &mut f64 {
312 &mut self.0[index]
313 }
314}
315
316impl<'a, C: Color> std::ops::IndexMut<Channel> for &'a mut Pixel<C> {
317 fn index_mut(&mut self, index: Channel) -> &mut f64 {
318 &mut self.0[index]
319 }
320}
321
322impl<T: Type, C: Color> std::ops::Add<T> for Pixel<C> {
323 type Output = Pixel<C>;
324
325 fn add(mut self, other: T) -> Pixel<C> {
326 self.map(|x| x + other.to_norm());
327 self
328 }
329}
330
331impl<'a, T: Type, C: Color> std::ops::Add<T> for &'a Pixel<C> {
332 type Output = Pixel<C>;
333
334 fn add(self, other: T) -> Pixel<C> {
335 let mut dest = self.clone();
336 dest.map(|x| x + other.to_norm());
337 dest
338 }
339}
340
341impl<'a, C: Color> std::ops::Add<&'a Pixel<C>> for Pixel<C> {
342 type Output = Pixel<C>;
343
344 fn add(mut self, other: &'a Pixel<C>) -> Pixel<C> {
345 self.map2(other, |x, y| x + y);
346 self
347 }
348}
349
350impl<'a, C: Color> std::ops::Add<&'a Pixel<C>> for &'a Pixel<C> {
351 type Output = Pixel<C>;
352
353 fn add(self, other: &'a Pixel<C>) -> Pixel<C> {
354 let mut dest = self.clone();
355 dest.map2(other, |x, y| x + y);
356 dest
357 }
358}
359
360impl<C: Color> std::ops::Add<Pixel<C>> for Pixel<C> {
361 type Output = Pixel<C>;
362
363 fn add(mut self, other: Pixel<C>) -> Pixel<C> {
364 self.map2(&other, |x, y| x + y);
365 self
366 }
367}
368
369impl<C: Color> std::ops::Add<Pixel<C>> for f64 {
370 type Output = Pixel<C>;
371
372 fn add(self, mut px: Pixel<C>) -> Pixel<C> {
373 px.map(|x| self + x);
374 px
375 }
376}
377
378impl<'a, C: Color> std::ops::Add<&'a Pixel<C>> for f64 {
379 type Output = Pixel<C>;
380
381 fn add(self, px: &'a Pixel<C>) -> Pixel<C> {
382 let mut px = px.clone();
383 px.map(|x| self + x);
384 px
385 }
386}
387
388impl<T: Type, C: Color> std::ops::Sub<T> for Pixel<C> {
389 type Output = Pixel<C>;
390
391 fn sub(mut self, other: T) -> Pixel<C> {
392 self.map(|x| x - other.to_norm());
393 self
394 }
395}
396
397impl<'a, T: Type, C: Color> std::ops::Sub<T> for &'a Pixel<C> {
398 type Output = Pixel<C>;
399
400 fn sub(self, other: T) -> Pixel<C> {
401 let mut dest = self.clone();
402 dest.map(|x| x - other.to_norm());
403 dest
404 }
405}
406
407impl<'a, C: Color> std::ops::Sub<&'a Pixel<C>> for &'a Pixel<C> {
408 type Output = Pixel<C>;
409
410 fn sub(self, other: &'a Pixel<C>) -> Pixel<C> {
411 let mut dest = self.clone();
412 dest.map2(other, |x, y| x - y);
413 dest
414 }
415}
416
417impl<'a, C: Color> std::ops::Sub<&'a Pixel<C>> for Pixel<C> {
418 type Output = Pixel<C>;
419
420 fn sub(mut self, other: &'a Pixel<C>) -> Pixel<C> {
421 self.map2(other, |x, y| x - y);
422 self
423 }
424}
425
426impl<C: Color> std::ops::Sub<Pixel<C>> for Pixel<C> {
427 type Output = Pixel<C>;
428
429 fn sub(mut self, other: Pixel<C>) -> Pixel<C> {
430 self.map2(&other, |x, y| x - y);
431 self
432 }
433}
434
435impl<C: Color> std::ops::Sub<Pixel<C>> for f64 {
436 type Output = Pixel<C>;
437
438 fn sub(self, mut px: Pixel<C>) -> Pixel<C> {
439 px.map(|x| self - x);
440 px
441 }
442}
443
444impl<'a, C: Color> std::ops::Sub<&'a Pixel<C>> for f64 {
445 type Output = Pixel<C>;
446
447 fn sub(self, px: &'a Pixel<C>) -> Pixel<C> {
448 let mut px = px.clone();
449 px.map(|x| self - x);
450 px
451 }
452}
453
454impl<T: Type, C: Color> std::ops::Mul<T> for Pixel<C> {
455 type Output = Pixel<C>;
456
457 fn mul(mut self, other: T) -> Pixel<C> {
458 self.map(|x| x * other.to_norm());
459 self
460 }
461}
462
463impl<'a, T: Type, C: Color> std::ops::Mul<T> for &'a Pixel<C> {
464 type Output = Pixel<C>;
465
466 fn mul(self, other: T) -> Pixel<C> {
467 let mut dest = self.clone();
468 dest.map(|x| x * other.to_norm());
469 dest
470 }
471}
472
473impl<'a, C: Color> std::ops::Mul<&'a Pixel<C>> for &'a Pixel<C> {
474 type Output = Pixel<C>;
475
476 fn mul(self, other: &'a Pixel<C>) -> Pixel<C> {
477 let mut dest = self.clone();
478 dest.map2(other, |x, y| x * y);
479 dest
480 }
481}
482
483impl<'a, C: Color> std::ops::Mul<&'a Pixel<C>> for Pixel<C> {
484 type Output = Pixel<C>;
485
486 fn mul(mut self, other: &'a Pixel<C>) -> Pixel<C> {
487 self.map2(other, |x, y| x * y).clone()
488 }
489}
490
491impl<C: Color> std::ops::Mul<Pixel<C>> for Pixel<C> {
492 type Output = Pixel<C>;
493
494 fn mul(mut self, other: Pixel<C>) -> Pixel<C> {
495 self.map2(&other, |x, y| x * y).clone()
496 }
497}
498
499impl<C: Color> std::ops::Mul<Pixel<C>> for f64 {
500 type Output = Pixel<C>;
501
502 fn mul(self, mut px: Pixel<C>) -> Pixel<C> {
503 px.map(|x| self * x);
504 px
505 }
506}
507
508impl<'a, C: Color> std::ops::Mul<&'a Pixel<C>> for f64 {
509 type Output = Pixel<C>;
510
511 fn mul(self, px: &'a Pixel<C>) -> Pixel<C> {
512 let mut px = px.clone();
513 px.map(|x| self * x);
514 px
515 }
516}
517
518impl<T: Type, C: Color> std::ops::Div<T> for Pixel<C> {
519 type Output = Pixel<C>;
520
521 fn div(mut self, other: T) -> Pixel<C> {
522 self.map(|x| x / other.to_norm());
523 self
524 }
525}
526
527impl<'a, T: Type, C: Color> std::ops::Div<T> for &'a Pixel<C> {
528 type Output = Pixel<C>;
529
530 fn div(self, other: T) -> Pixel<C> {
531 let mut dest = self.clone();
532 dest.map(|x| x / other.to_norm());
533 dest
534 }
535}
536
537impl<'a, C: Color> std::ops::Div<&'a Pixel<C>> for Pixel<C> {
538 type Output = Pixel<C>;
539
540 fn div(mut self, other: &'a Pixel<C>) -> Pixel<C> {
541 self.map2(other, |x, y| x / y);
542 self
543 }
544}
545
546impl<'a, C: Color> std::ops::Div<&'a Pixel<C>> for &'a Pixel<C> {
547 type Output = Pixel<C>;
548
549 fn div(self, other: &'a Pixel<C>) -> Pixel<C> {
550 let mut dest = self.clone();
551 dest.map2(other, |x, y| x / y);
552 dest
553 }
554}
555
556impl<C: Color> std::ops::Div<Pixel<C>> for Pixel<C> {
557 type Output = Pixel<C>;
558
559 fn div(mut self, other: Pixel<C>) -> Pixel<C> {
560 self.map2(&other, |x, y| x / y);
561 self
562 }
563}
564
565impl<C: Color> std::ops::Div<Pixel<C>> for f64 {
566 type Output = Pixel<C>;
567
568 fn div(self, mut px: Pixel<C>) -> Pixel<C> {
569 px.map(|x| self / x);
570 px
571 }
572}
573
574impl<'a, C: Color> std::ops::Div<&'a Pixel<C>> for f64 {
575 type Output = Pixel<C>;
576
577 fn div(self, px: &'a Pixel<C>) -> Pixel<C> {
578 let mut px = px.clone();
579 px.map(|x| self / x);
580 px
581 }
582}
583
584impl<T: Type, C: Color> std::ops::Rem<T> for Pixel<C> {
585 type Output = Pixel<C>;
586
587 fn rem(mut self, other: T) -> Pixel<C> {
588 self.map(|x| x % other.to_norm());
589 self
590 }
591}
592
593impl<'a, T: Type, C: Color> std::ops::Rem<T> for &'a Pixel<C> {
594 type Output = Pixel<C>;
595
596 fn rem(self, other: T) -> Pixel<C> {
597 let mut dest = self.clone();
598 dest.map(|x| x % other.to_norm());
599 dest
600 }
601}
602
603impl<'a, C: Color> std::ops::Rem<&'a Pixel<C>> for &'a Pixel<C> {
604 type Output = Pixel<C>;
605
606 fn rem(self, other: &'a Pixel<C>) -> Pixel<C> {
607 let mut dest = self.clone();
608 dest.map2(other, |x, y| x % y);
609 dest
610 }
611}
612
613impl<'a, C: Color> std::ops::Rem<&'a Pixel<C>> for Pixel<C> {
614 type Output = Pixel<C>;
615
616 fn rem(mut self, other: &'a Pixel<C>) -> Pixel<C> {
617 self.map2(other, |x, y| x % y);
618 self
619 }
620}
621
622impl<C: Color> std::ops::Rem<Pixel<C>> for Pixel<C> {
623 type Output = Pixel<C>;
624
625 fn rem(mut self, other: Pixel<C>) -> Pixel<C> {
626 self.map2(&other, |x, y| x % y);
627 self
628 }
629}
630
631impl<C: Color> std::ops::Rem<Pixel<C>> for f64 {
632 type Output = Pixel<C>;
633
634 fn rem(self, mut px: Pixel<C>) -> Pixel<C> {
635 px.map(|x| self % x);
636 px
637 }
638}
639
640impl<'a, C: Color> std::ops::Rem<&'a Pixel<C>> for f64 {
641 type Output = Pixel<C>;
642
643 fn rem(self, px: &'a Pixel<C>) -> Pixel<C> {
644 let mut px = px.clone();
645 px.map(|x| self % x);
646 px
647 }
648}
649
650impl<T: Type, C: Color> std::ops::AddAssign<T> for Pixel<C> {
651 fn add_assign(&mut self, other: T) {
652 self.map(|x| x + other.to_norm());
653 }
654}
655
656impl<C: Color> std::ops::AddAssign<Pixel<C>> for Pixel<C> {
657 fn add_assign(&mut self, other: Pixel<C>) {
658 self.map2(&other, |x, y| x + y);
659 }
660}
661
662impl<'a, C: Color> std::ops::AddAssign<&'a Pixel<C>> for Pixel<C> {
663 fn add_assign(&mut self, other: &'a Pixel<C>) {
664 self.map2(other, |x, y| x + y);
665 }
666}
667
668impl<T: Type, C: Color> std::ops::SubAssign<T> for Pixel<C> {
669 fn sub_assign(&mut self, other: T) {
670 self.map(|x| x - other.to_norm());
671 }
672}
673
674impl<C: Color> std::ops::SubAssign<Pixel<C>> for Pixel<C> {
675 fn sub_assign(&mut self, other: Pixel<C>) {
676 self.map2(&other, |x, y| x - y);
677 }
678}
679
680impl<'a, C: Color> std::ops::SubAssign<&'a Pixel<C>> for Pixel<C> {
681 fn sub_assign(&mut self, other: &'a Pixel<C>) {
682 self.map2(other, |x, y| x - y);
683 }
684}
685
686impl<T: Type, C: Color> std::ops::MulAssign<T> for Pixel<C> {
687 fn mul_assign(&mut self, other: T) {
688 self.map(|x| x * other.to_norm());
689 }
690}
691
692impl<C: Color> std::ops::MulAssign<Pixel<C>> for Pixel<C> {
693 fn mul_assign(&mut self, other: Pixel<C>) {
694 self.map2(&other, |x, y| x * y);
695 }
696}
697
698impl<'a, C: Color> std::ops::MulAssign<&'a Pixel<C>> for Pixel<C> {
699 fn mul_assign(&mut self, other: &'a Pixel<C>) {
700 self.map2(other, |x, y| x * y);
701 }
702}
703
704impl<T: Type, C: Color> std::ops::DivAssign<T> for Pixel<C> {
705 fn div_assign(&mut self, other: T) {
706 self.map(|x| x / other.to_norm());
707 }
708}
709
710impl<C: Color> std::ops::DivAssign<Pixel<C>> for Pixel<C> {
711 fn div_assign(&mut self, other: Pixel<C>) {
712 self.map2(&other, |x, y| x / y);
713 }
714}
715
716impl<'a, C: Color> std::ops::DivAssign<&'a Pixel<C>> for Pixel<C> {
717 fn div_assign(&mut self, other: &'a Pixel<C>) {
718 self.map2(other, |x, y| x / y);
719 }
720}
721
722impl<T: Type, C: Color> std::ops::RemAssign<T> for Pixel<C> {
723 fn rem_assign(&mut self, other: T) {
724 self.map(|x| x % other.to_norm());
725 }
726}
727
728impl<C: Color> std::ops::RemAssign<Pixel<C>> for Pixel<C> {
729 fn rem_assign(&mut self, other: Pixel<C>) {
730 self.map2(&other, |x, y| x % y);
731 }
732}
733
734impl<'a, C: Color> std::ops::RemAssign<&'a Pixel<C>> for Pixel<C> {
735 fn rem_assign(&mut self, other: &'a Pixel<C>) {
736 self.map2(other, |x, y| x % y);
737 }
738}