zune_image/
ops.rs

1/*
2 * Copyright (c) 2023.
3 *
4 * This software is free software;
5 *
6 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7 */
8
9//! Overloadable operators
10//!
11//! This module provides overloadable operators for the image struct
12//!
13//! The operations panic in case of the incompatibility between two images
14//! so it is best you ensure the image struct is the same
15//!
16use 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}