1use core::ops::*;
17
18use zune_core::bit_depth::BitType;
19
20use crate::image::Image;
21
22#[track_caller]
23fn check_full_compatibility(img1: &Image, img2: &Image) {
24 assert_eq!(
25 img1.depth(),
26 img2.depth(),
27 "Image depth mismatch cannot continue {:?}!={:?}",
28 img1.depth(),
29 img2.depth()
30 );
31
32 assert_eq!(
33 img1.dimensions(),
34 img2.dimensions(),
35 "Dimensions mismatch, {:?} != {:?}",
36 img1.dimensions(),
37 img2.dimensions()
38 );
39
40 assert_eq!(
41 img1.colorspace(),
42 img2.colorspace(),
43 "Colorspace mismatch, {:?} != {:?}",
44 img1.colorspace(),
45 img2.colorspace()
46 );
47}
48
49impl Add for Image {
50 type Output = Image;
51
52 fn add(self, rhs: Image) -> Self::Output {
53 check_full_compatibility(&self, &rhs);
54
55 let mut new_img = self;
56
57 match new_img.depth().bit_type() {
58 BitType::U8 => {
59 for (prev, rhs_c) in new_img
60 .channels_mut(true)
61 .iter_mut()
62 .zip(rhs.channels_ref(true))
63 {
64 let channel_px = prev.reinterpret_as_mut::<u8>().unwrap();
65 let channel_rhs = rhs_c.reinterpret_as::<u8>().unwrap();
66
67 channel_px
68 .iter_mut()
69 .zip(channel_rhs.iter())
70 .for_each(|(x, y)| *x = x.saturating_add(*y));
71 }
72 }
73 BitType::U16 => {
74 for (prev, rhs_c) in new_img
75 .channels_mut(true)
76 .iter_mut()
77 .zip(rhs.channels_ref(true))
78 {
79 let channel_px = prev.reinterpret_as_mut::<u16>().unwrap();
80 let channel_rhs = rhs_c.reinterpret_as::<u16>().unwrap();
81
82 channel_px
83 .iter_mut()
84 .zip(channel_rhs.iter())
85 .for_each(|(x, y)| *x = x.saturating_add(*y));
86 }
87 }
88 BitType::F32 => {
89 for (prev, rhs_c) in new_img
90 .channels_mut(true)
91 .iter_mut()
92 .zip(rhs.channels_ref(true))
93 {
94 let channel_px = prev.reinterpret_as_mut::<f32>().unwrap();
95 let channel_rhs = rhs_c.reinterpret_as::<f32>().unwrap();
96
97 channel_px
98 .iter_mut()
99 .zip(channel_rhs.iter())
100 .for_each(|(x, y)| *x += *y);
101 }
102 }
103 d => unimplemented!("Unimplemented for {:?}", d)
104 }
105 new_img
106 }
107}
108
109impl Sub for Image {
110 type Output = Image;
111
112 fn sub(self, rhs: Image) -> Self::Output {
113 check_full_compatibility(&self, &rhs);
114
115 let mut new_img = self;
116
117 match new_img.depth().bit_type() {
118 BitType::U8 => {
119 for (prev, rhs_c) in new_img
120 .channels_mut(true)
121 .iter_mut()
122 .zip(rhs.channels_ref(true))
123 {
124 let channel_px = prev.reinterpret_as_mut::<u8>().unwrap();
125 let channel_rhs = rhs_c.reinterpret_as::<u8>().unwrap();
126
127 channel_px
128 .iter_mut()
129 .zip(channel_rhs.iter())
130 .for_each(|(x, y)| *x = x.saturating_sub(*y));
131 }
132 }
133 BitType::U16 => {
134 for (prev, rhs_c) in new_img
135 .channels_mut(true)
136 .iter_mut()
137 .zip(rhs.channels_ref(true))
138 {
139 let channel_px = prev.reinterpret_as_mut::<u16>().unwrap();
140 let channel_rhs = rhs_c.reinterpret_as::<u16>().unwrap();
141
142 channel_px
143 .iter_mut()
144 .zip(channel_rhs.iter())
145 .for_each(|(x, y)| *x = x.saturating_sub(*y));
146 }
147 }
148 BitType::F32 => {
149 for (prev, rhs_c) in new_img
150 .channels_mut(true)
151 .iter_mut()
152 .zip(rhs.channels_ref(true))
153 {
154 let channel_px = prev.reinterpret_as_mut::<f32>().unwrap();
155 let channel_rhs = rhs_c.reinterpret_as::<f32>().unwrap();
156
157 channel_px
158 .iter_mut()
159 .zip(channel_rhs.iter())
160 .for_each(|(x, y)| *x -= *y);
161 }
162 }
163 d => unimplemented!("Unimplemented for {:?}", d)
164 }
165 new_img
166 }
167}
168
169#[test]
170fn add() {
171 let im = Image::fill(0_u8, zune_core::colorspace::ColorSpace::RGBA, 100, 100);
172 let _ = im.clone() + im;
173}