1mod error;
7mod surface;
8mod utils;
9#[cfg(feature = "image")]
10pub use arena::ImageEditor;
11pub use error::SurfaceError;
12pub use surface::{BlendMode, ColorChannel, CompositeOperator, Surface};
13pub use utils::get_resource_path;
14
15#[cfg(feature = "image")]
17pub mod arena {
18 use std::{
19 panic,
20 path::{Path, PathBuf},
21 };
22
23 use image::{DynamicImage, ImageBuffer, ImageReader, ImageResult};
24
25 use crate::{BlendMode, CompositeOperator, Surface};
26
27 #[derive(Debug)]
47 pub struct ImageEditor {
48 input_image_path: PathBuf,
49 input_image: DynamicImage,
50 output_image: DynamicImage,
51 }
52
53 impl ImageEditor {
55 pub fn open(input_image_path: impl AsRef<Path>) -> Self {
58 let input_image_path = input_image_path.as_ref().to_owned();
59 let input_image = Self::open_image(&input_image_path);
60 let output_image = Self::temp_output_image(input_image.width(), input_image.height());
61 Self {
62 input_image_path,
63 input_image,
64 output_image,
65 }
66 }
67
68 fn temp_output_image(width: u32, height: u32) -> DynamicImage {
69 let output_pixels =
70 ImageBuffer::from_vec(width, height, vec![0u8; (4 * width * height) as usize])
71 .unwrap();
72 DynamicImage::ImageRgba8(output_pixels)
73 }
74
75 fn open_image(image_path: &Path) -> DynamicImage {
77 if !image_path.exists() {
78 panic!("Unable to find image path.");
79 }
80 let image_buffer = match ImageReader::open(image_path) {
81 Ok(image) => match image.decode() {
82 Ok(image) => image,
83 Err(err) => panic!("Unable to decode image: {err}"),
84 },
85 Err(err) => panic!("Unable to open Image: {err}"),
86 };
87 let rgba8_image_buffer = image_buffer.into_rgba8();
88 DynamicImage::ImageRgba8(rgba8_image_buffer)
89 }
90
91 pub fn save_to(self, output_path: impl AsRef<Path>) -> ImageResult<()> {
93 let output_path = output_path.as_ref();
94 self.output_image.save(output_path)
95 }
96
97 pub fn save(self) -> ImageResult<()> {
99 self.output_image.save(&self.input_image_path)
100 }
101
102 pub fn color_transform_inplace(mut self, matrix: [f32; 20]) -> Self {
103 let mut input_surface = Surface::from_image(&mut self.input_image);
104 let mut output_surface = Surface::from_image(&mut self.output_image);
105 Surface::color_transform(&mut input_surface, &mut output_surface, matrix);
106 Surface::copy_output_into_input(&mut input_surface, &output_surface);
107 self
108 }
109
110 pub fn color_transform(mut self, matrix: [f32; 20]) -> Self {
111 let mut input_surface = Surface::from_image(&mut self.input_image);
112 let mut output_surface = Surface::from_image(&mut self.output_image);
113 Surface::color_transform(&mut input_surface, &mut output_surface, matrix);
114 self
115 }
116
117 pub fn color_transform_opacity_inplace(mut self, amount: f32) -> Self {
118 let mut input_surface = Surface::from_image(&mut self.input_image);
119 let mut output_surface = Surface::from_image(&mut self.output_image);
120 Surface::color_transform_opacity(&mut input_surface, &mut output_surface, amount);
121 Surface::copy_output_into_input(&mut input_surface, &output_surface);
122 self
123 }
124
125 pub fn color_transform_opacity(mut self, amount: f32) -> Self {
126 let mut input_surface = Surface::from_image(&mut self.input_image);
127 let mut output_surface = Surface::from_image(&mut self.output_image);
128 Surface::color_transform_opacity(&mut input_surface, &mut output_surface, amount);
129 self
130 }
131
132 pub fn color_transform_brightness_inplace(mut self, amount: f32) -> Self {
133 let mut input_surface = Surface::from_image(&mut self.input_image);
134 let mut output_surface = Surface::from_image(&mut self.output_image);
135 Surface::color_transform_brightness(&mut input_surface, &mut output_surface, amount);
136 Surface::copy_output_into_input(&mut input_surface, &output_surface);
137 self
138 }
139
140 pub fn color_transform_brightness(mut self, amount: f32) -> Self {
141 let mut input_surface = Surface::from_image(&mut self.input_image);
142 let mut output_surface = Surface::from_image(&mut self.output_image);
143 Surface::color_transform_brightness(&mut input_surface, &mut output_surface, amount);
144 self
145 }
146
147 pub fn color_transform_invert_inplace(mut self, amount: f32) -> Self {
148 let mut input_surface = Surface::from_image(&mut self.input_image);
149 let mut output_surface = Surface::from_image(&mut self.output_image);
150 Surface::color_transform_invert(&mut input_surface, &mut output_surface, amount);
151 Surface::copy_output_into_input(&mut input_surface, &output_surface);
152 self
153 }
154
155 pub fn color_transform_invert(mut self, amount: f32) -> Self {
156 let mut input_surface = Surface::from_image(&mut self.input_image);
157 let mut output_surface = Surface::from_image(&mut self.output_image);
158 Surface::color_transform_invert(&mut input_surface, &mut output_surface, amount);
159 self
160 }
161
162 pub fn color_transform_contrast_inplace(mut self, amount: f32) -> Self {
163 let mut input_surface = Surface::from_image(&mut self.input_image);
164 let mut output_surface = Surface::from_image(&mut self.output_image);
165 Surface::color_transform_contrast(&mut input_surface, &mut output_surface, amount);
166 Surface::copy_output_into_input(&mut input_surface, &output_surface);
167 self
168 }
169
170 pub fn color_transform_contrast(mut self, amount: f32) -> Self {
171 let mut input_surface = Surface::from_image(&mut self.input_image);
172 let mut output_surface = Surface::from_image(&mut self.output_image);
173 Surface::color_transform_contrast(&mut input_surface, &mut output_surface, amount);
174 self
175 }
176
177 pub fn color_transform_saturate_inplace(mut self, amount: f32) -> Self {
178 let mut input_surface = Surface::from_image(&mut self.input_image);
179 let mut output_surface = Surface::from_image(&mut self.output_image);
180 Surface::color_transform_saturate(&mut input_surface, &mut output_surface, amount);
181 Surface::copy_output_into_input(&mut input_surface, &output_surface);
182 self
183 }
184
185 pub fn color_transform_saturate(mut self, amount: f32) -> Self {
186 let mut input_surface = Surface::from_image(&mut self.input_image);
187 let mut output_surface = Surface::from_image(&mut self.output_image);
188 Surface::color_transform_saturate(&mut input_surface, &mut output_surface, amount);
189 self
190 }
191
192 pub fn color_transform_grayscale_inplace(mut self, amount: f32) -> Self {
193 let mut input_surface = Surface::from_image(&mut self.input_image);
194 let mut output_surface = Surface::from_image(&mut self.output_image);
195 Surface::color_transform_grayscale(&mut input_surface, &mut output_surface, amount);
196 Surface::copy_output_into_input(&mut input_surface, &output_surface);
197 self
198 }
199
200 pub fn color_transform_grayscale(mut self, amount: f32) -> Self {
201 let mut input_surface = Surface::from_image(&mut self.input_image);
202 let mut output_surface = Surface::from_image(&mut self.output_image);
203 Surface::color_transform_grayscale(&mut input_surface, &mut output_surface, amount);
204 self
205 }
206
207 pub fn color_transform_sepia_inplace(mut self, amount: f32) -> Self {
208 let mut input_surface = Surface::from_image(&mut self.input_image);
209 let mut output_surface = Surface::from_image(&mut self.output_image);
210 Surface::color_transform_sepia(&mut input_surface, &mut output_surface, amount);
211 Surface::copy_output_into_input(&mut input_surface, &output_surface);
212 self
213 }
214
215 pub fn color_transform_sepia(mut self, amount: f32) -> Self {
216 let mut input_surface = Surface::from_image(&mut self.input_image);
217 let mut output_surface = Surface::from_image(&mut self.output_image);
218 Surface::color_transform_sepia(&mut input_surface, &mut output_surface, amount);
219 self
220 }
221
222 pub fn color_transform_hue_rotate_inplace(mut self, angle: f32) -> Self {
223 let mut input_surface = Surface::from_image(&mut self.input_image);
224 let mut output_surface = Surface::from_image(&mut self.output_image);
225 Surface::color_transform_hue_rotate(&mut input_surface, &mut output_surface, angle);
226 Surface::copy_output_into_input(&mut input_surface, &output_surface);
227 self
228 }
229
230 pub fn color_transform_hue_rotate(mut self, angle: f32) -> Self {
231 let mut input_surface = Surface::from_image(&mut self.input_image);
232 let mut output_surface = Surface::from_image(&mut self.output_image);
233 Surface::color_transform_hue_rotate(&mut input_surface, &mut output_surface, angle);
234 self
235 }
236
237 pub fn color_transform_luminance_to_alpha_inplace(mut self) -> Self {
238 let mut input_surface = Surface::from_image(&mut self.input_image);
239 let mut output_surface = Surface::from_image(&mut self.output_image);
240 Surface::color_transform_luminance_to_alpha(&mut input_surface, &mut output_surface);
241 Surface::copy_output_into_input(&mut input_surface, &output_surface);
242 self
243 }
244
245 pub fn color_transform_luminance_to_alpha(mut self) -> Self {
246 let mut input_surface = Surface::from_image(&mut self.input_image);
247 let mut output_surface = Surface::from_image(&mut self.output_image);
248 Surface::color_transform_luminance_to_alpha(&mut input_surface, &mut output_surface);
249 self
250 }
251
252 pub fn color_transform_srgb_to_linear_rgb_inplace(mut self) -> Self {
253 let mut input_surface = Surface::from_image(&mut self.input_image);
254 let mut output_surface = Surface::from_image(&mut self.output_image);
255 Surface::color_transform_srgb_to_linear_rgb(&mut input_surface, &mut output_surface);
256 Surface::copy_output_into_input(&mut input_surface, &output_surface);
257 self
258 }
259
260 pub fn color_transform_srgb_to_linear_rgb(mut self) -> Self {
261 let mut input_surface = Surface::from_image(&mut self.input_image);
262 let mut output_surface = Surface::from_image(&mut self.output_image);
263 Surface::color_transform_srgb_to_linear_rgb(&mut input_surface, &mut output_surface);
264 self
265 }
266
267 pub fn color_transform_linear_rgb_to_srgb_inplace(mut self) -> Self {
268 let mut input_surface = Surface::from_image(&mut self.input_image);
269 let mut output_surface = Surface::from_image(&mut self.output_image);
270 Surface::color_transform_linear_rgb_to_srgb(&mut input_surface, &mut output_surface);
271 Surface::copy_output_into_input(&mut input_surface, &output_surface);
272 self
273 }
274
275 pub fn color_transform_linear_rgb_to_srgb(mut self) -> Self {
276 let mut input_surface = Surface::from_image(&mut self.input_image);
277 let mut output_surface = Surface::from_image(&mut self.output_image);
278 Surface::color_transform_linear_rgb_to_srgb(&mut input_surface, &mut output_surface);
279 self
280 }
281
282 pub fn gaussian_blur_inplace(mut self, std_deviation_x: f32, std_deviation_y: f32) -> Self {
283 let mut input_surface = Surface::from_image(&mut self.input_image);
284 let mut output_surface = Surface::from_image(&mut self.output_image);
285 Surface::gaussian_blur(
286 &mut input_surface,
287 &mut output_surface,
288 std_deviation_x,
289 std_deviation_y,
290 );
291 Surface::copy_output_into_input(&mut input_surface, &output_surface);
292 self
293 }
294 pub fn gaussian_blur(mut self, std_deviation_x: f32, std_deviation_y: f32) -> Self {
295 let mut input_surface = Surface::from_image(&mut self.input_image);
296 let mut output_surface = Surface::from_image(&mut self.output_image);
297 Surface::gaussian_blur(
298 &mut input_surface,
299 &mut output_surface,
300 std_deviation_x,
301 std_deviation_y,
302 );
303 self
304 }
305
306 pub fn blend_inplace(mut self, blend_image: impl AsRef<Path>, mode: BlendMode) -> Self {
307 let mut input_surface = Surface::from_image(&mut self.input_image);
308 let mut output_surface = Surface::from_image(&mut self.output_image);
309
310 let mut blend_input_image = Self::open_image(blend_image.as_ref());
311 let mut blend_surface = Surface::from_image(&mut blend_input_image);
312 Surface::blend(
313 &mut input_surface,
314 &mut blend_surface,
315 &mut output_surface,
316 mode,
317 );
318 Surface::copy_output_into_input(&mut input_surface, &output_surface);
319 self
320 }
321
322 pub fn blend(mut self, blend_image: impl AsRef<Path>, mode: BlendMode) -> Self {
323 let mut input_surface = Surface::from_image(&mut self.input_image);
324 let mut output_surface = Surface::from_image(&mut self.output_image);
325
326 let mut blend_input_image = Self::open_image(blend_image.as_ref());
327 let mut blend_surface = Surface::from_image(&mut blend_input_image);
328 Surface::blend(
329 &mut input_surface,
330 &mut blend_surface,
331 &mut output_surface,
332 mode,
333 );
334 self
335 }
336 pub fn composite_inplace(
337 mut self,
338 composite_image: impl AsRef<Path>,
339 op: CompositeOperator,
340 ) -> Self {
341 let mut input_surface = Surface::from_image(&mut self.input_image);
342 let mut output_surface = Surface::from_image(&mut self.output_image);
343
344 let mut composite_input_image = Self::open_image(composite_image.as_ref());
345 let mut composite_surface = Surface::from_image(&mut composite_input_image);
346 Surface::composite(
347 &mut input_surface,
348 &mut composite_surface,
349 &mut output_surface,
350 op,
351 );
352 Surface::copy_output_into_input(&mut input_surface, &output_surface);
353 self
354 }
355
356 pub fn composite(
357 mut self,
358 composite_image: impl AsRef<Path>,
359 op: CompositeOperator,
360 ) -> Self {
361 let mut input_surface = Surface::from_image(&mut self.input_image);
362 let mut output_surface = Surface::from_image(&mut self.output_image);
363
364 let mut composite_input_image = Self::open_image(composite_image.as_ref());
365 let mut composite_surface = Surface::from_image(&mut composite_input_image);
366 Surface::composite(
367 &mut input_surface,
368 &mut composite_surface,
369 &mut output_surface,
370 op,
371 );
372 self
373 }
374 pub fn composite_arithmetic_inplace(
375 mut self,
376 composite_image: impl AsRef<Path>,
377 k1: f32,
378 k2: f32,
379 k3: f32,
380 k4: f32,
381 ) -> Self {
382 let mut input_surface = Surface::from_image(&mut self.input_image);
383 let mut output_surface = Surface::from_image(&mut self.output_image);
384
385 let mut composite_input_image = Self::open_image(composite_image.as_ref());
386 let mut composite_surface = Surface::from_image(&mut composite_input_image);
387 Surface::composite_arithmetic(
388 &mut input_surface,
389 &mut composite_surface,
390 &mut output_surface,
391 k1,
392 k2,
393 k3,
394 k4,
395 );
396 Surface::copy_output_into_input(&mut input_surface, &output_surface);
397 self
398 }
399 pub fn composite_arithmetic(
400 mut self,
401 composite_image: impl AsRef<Path>,
402 k1: f32,
403 k2: f32,
404 k3: f32,
405 k4: f32,
406 ) -> Self {
407 let mut input_surface = Surface::from_image(&mut self.input_image);
408 let mut output_surface = Surface::from_image(&mut self.output_image);
409
410 let mut composite_input_image = Self::open_image(composite_image.as_ref());
411 let mut composite_surface = Surface::from_image(&mut composite_input_image);
412 Surface::composite_arithmetic(
413 &mut input_surface,
414 &mut composite_surface,
415 &mut output_surface,
416 k1,
417 k2,
418 k3,
419 k4,
420 );
421 self
422 }
423 }
424}