1use crate::error::{ImageError, ImageResult, ParameterError, ParameterErrorKind};
2use crate::math::Rect;
3use crate::traits::Pixel;
4use crate::{ImageBuffer, SubImage};
5
6pub trait GenericImageView {
15 type Pixel: Pixel;
17
18 fn dimensions(&self) -> (u32, u32);
20
21 fn width(&self) -> u32 {
23 let (w, _) = self.dimensions();
24 w
25 }
26
27 fn height(&self) -> u32 {
29 let (_, h) = self.dimensions();
30 h
31 }
32
33 fn in_bounds(&self, x: u32, y: u32) -> bool {
35 let (width, height) = self.dimensions();
36 x < width && y < height
37 }
38
39 fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel;
45
46 unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
55 self.get_pixel(x, y)
56 }
57
58 fn pixels(&self) -> Pixels<'_, Self>
62 where
63 Self: Sized,
64 {
65 let (width, height) = self.dimensions();
66
67 Pixels {
68 image: self,
69 x: 0,
70 y: 0,
71 width,
72 height,
73 }
74 }
75
76 fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self>
84 where
85 Self: Sized,
86 {
87 assert!(u64::from(x) + u64::from(width) <= u64::from(self.width()));
88 assert!(u64::from(y) + u64::from(height) <= u64::from(self.height()));
89 SubImage::new(self, x, y, width, height)
90 }
91
92 fn try_view(
95 &self,
96 x: u32,
97 y: u32,
98 width: u32,
99 height: u32,
100 ) -> Result<SubImage<&Self>, ImageError>
101 where
102 Self: Sized,
103 {
104 if u64::from(x) + u64::from(width) > u64::from(self.width())
105 || u64::from(y) + u64::from(height) > u64::from(self.height())
106 {
107 Err(ImageError::Parameter(ParameterError::from_kind(
108 ParameterErrorKind::DimensionMismatch,
109 )))
110 } else {
111 Ok(SubImage::new(self, x, y, width, height))
112 }
113 }
114
115 fn buffer_like(&self) -> ImageBuffer<Self::Pixel, Vec<<Self::Pixel as Pixel>::Subpixel>> {
124 let (w, h) = self.dimensions();
125 self.buffer_with_dimensions(w, h)
126 }
127
128 fn buffer_with_dimensions(
135 &self,
136 width: u32,
137 height: u32,
138 ) -> ImageBuffer<Self::Pixel, Vec<<Self::Pixel as Pixel>::Subpixel>> {
139 ImageBuffer::new(width, height)
140 }
141}
142
143#[derive(Debug)]
145pub struct Pixels<'a, I: ?Sized + 'a> {
146 image: &'a I,
147 x: u32,
148 y: u32,
149 width: u32,
150 height: u32,
151}
152
153impl<I: GenericImageView> Iterator for Pixels<'_, I> {
154 type Item = (u32, u32, I::Pixel);
155
156 fn next(&mut self) -> Option<(u32, u32, I::Pixel)> {
157 if self.x >= self.width {
158 self.x = 0;
159 self.y += 1;
160 }
161
162 if self.y >= self.height {
163 None
164 } else {
165 let pixel = self.image.get_pixel(self.x, self.y);
166 let p = (self.x, self.y, pixel);
167
168 self.x += 1;
169
170 Some(p)
171 }
172 }
173}
174
175impl<I: ?Sized> Clone for Pixels<'_, I> {
176 fn clone(&self) -> Self {
177 Pixels { ..*self }
178 }
179}
180
181pub trait GenericImage: GenericImageView {
183 #[deprecated(since = "0.24.0", note = "Use `get_pixel` and `put_pixel` instead.")]
204 fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel;
205
206 fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
212
213 unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
222 self.put_pixel(x, y, pixel);
223 }
224
225 #[deprecated(
227 since = "0.24.0",
228 note = "Use iterator `pixels_mut` to blend the pixels directly"
229 )]
230 fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
231
232 fn copy_from<O>(&mut self, other: &O, x: u32, y: u32) -> ImageResult<()>
248 where
249 O: GenericImageView<Pixel = Self::Pixel>,
250 {
251 if self.width() < other.width() + x || self.height() < other.height() + y {
254 return Err(ImageError::Parameter(ParameterError::from_kind(
255 ParameterErrorKind::DimensionMismatch,
256 )));
257 }
258
259 for k in 0..other.height() {
260 for i in 0..other.width() {
261 let p = other.get_pixel(i, k);
262 self.put_pixel(i + x, k + y, p);
263 }
264 }
265 Ok(())
266 }
267
268 fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool {
276 let Rect {
277 x: sx,
278 y: sy,
279 width,
280 height,
281 } = source;
282 let dx = x;
283 let dy = y;
284 assert!(sx < self.width() && dx < self.width());
285 assert!(sy < self.height() && dy < self.height());
286 if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height {
287 return false;
288 }
289 macro_rules! copy_within_impl_ {
292 ($xiter:expr, $yiter:expr) => {
293 for y in $yiter {
294 let sy = sy + y;
295 let dy = dy + y;
296 for x in $xiter {
297 let sx = sx + x;
298 let dx = dx + x;
299 let pixel = self.get_pixel(sx, sy);
300 self.put_pixel(dx, dy, pixel);
301 }
302 }
303 };
304 }
305 match (sx < dx, sy < dy) {
307 (true, true) => copy_within_impl_!((0..width).rev(), (0..height).rev()),
308 (true, false) => copy_within_impl_!((0..width).rev(), 0..height),
309 (false, true) => copy_within_impl_!(0..width, (0..height).rev()),
310 (false, false) => copy_within_impl_!(0..width, 0..height),
311 }
312 true
313 }
314
315 fn sub_image(&mut self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&mut Self>
319 where
320 Self: Sized,
321 {
322 assert!(u64::from(x) + u64::from(width) <= u64::from(self.width()));
323 assert!(u64::from(y) + u64::from(height) <= u64::from(self.height()));
324 SubImage::new(self, x, y, width, height)
325 }
326}
327
328#[cfg(test)]
329mod tests {
330 use super::{GenericImage, GenericImageView};
331
332 use crate::color::Rgba;
333 use crate::math::Rect;
334 use crate::{GrayImage, ImageBuffer};
335
336 #[test]
337 #[allow(deprecated)]
338 fn test_image_alpha_blending() {
340 let mut target = ImageBuffer::new(1, 1);
341 target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
342 assert!(*target.get_pixel(0, 0) == Rgba([255, 0, 0, 255]));
343 target.blend_pixel(0, 0, Rgba([0, 255, 0, 255]));
344 assert!(*target.get_pixel(0, 0) == Rgba([0, 255, 0, 255]));
345
346 target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
348 assert!(*target.get_pixel(0, 0) == Rgba([127, 127, 0, 255]));
349
350 target.put_pixel(0, 0, Rgba([0, 255, 0, 127]));
352 target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
353 assert!(*target.get_pixel(0, 0) == Rgba([169, 85, 0, 190]));
354 }
355
356 #[test]
357 fn test_in_bounds() {
358 let mut target = ImageBuffer::new(2, 2);
359 target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
360
361 assert!(target.in_bounds(0, 0));
362 assert!(target.in_bounds(1, 0));
363 assert!(target.in_bounds(0, 1));
364 assert!(target.in_bounds(1, 1));
365
366 assert!(!target.in_bounds(2, 0));
367 assert!(!target.in_bounds(0, 2));
368 assert!(!target.in_bounds(2, 2));
369 }
370
371 #[test]
372 fn test_can_subimage_clone_nonmut() {
373 let mut source = ImageBuffer::new(3, 3);
374 source.put_pixel(1, 1, Rgba([255u8, 0, 0, 255]));
375
376 let source = source.clone();
378
379 let cloned = source.view(1, 1, 1, 1).to_image();
381
382 assert!(cloned.get_pixel(0, 0) == source.get_pixel(1, 1));
383 }
384
385 #[test]
386 fn test_can_nest_views() {
387 let mut source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
388
389 {
390 let mut sub1 = source.sub_image(0, 0, 2, 2);
391 let mut sub2 = sub1.sub_image(1, 1, 1, 1);
392 sub2.put_pixel(0, 0, Rgba([0, 0, 0, 0]));
393 }
394
395 assert_eq!(*source.get_pixel(1, 1), Rgba([0, 0, 0, 0]));
396
397 let view1 = source.view(0, 0, 2, 2);
398 assert_eq!(*source.get_pixel(1, 1), view1.get_pixel(1, 1));
399
400 let view2 = view1.view(1, 1, 1, 1);
401 assert_eq!(*source.get_pixel(1, 1), view2.get_pixel(0, 0));
402 }
403
404 #[test]
405 #[should_panic]
406 fn test_view_out_of_bounds() {
407 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
408 source.view(1, 1, 3, 3);
409 }
410
411 #[test]
412 #[should_panic]
413 fn test_view_coordinates_out_of_bounds() {
414 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
415 source.view(3, 3, 3, 3);
416 }
417
418 #[test]
419 #[should_panic]
420 fn test_view_width_out_of_bounds() {
421 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
422 source.view(1, 1, 3, 2);
423 }
424
425 #[test]
426 #[should_panic]
427 fn test_view_height_out_of_bounds() {
428 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
429 source.view(1, 1, 2, 3);
430 }
431
432 #[test]
433 #[should_panic]
434 fn test_view_x_out_of_bounds() {
435 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
436 source.view(3, 1, 3, 3);
437 }
438
439 #[test]
440 #[should_panic]
441 fn test_view_y_out_of_bounds() {
442 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
443 source.view(1, 3, 3, 3);
444 }
445
446 #[test]
447 fn test_view_in_bounds() {
448 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
449 source.view(0, 0, 3, 3);
450 source.view(1, 1, 2, 2);
451 source.view(2, 2, 0, 0);
452 }
453
454 #[test]
455 fn test_copy_sub_image() {
456 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
457 let view = source.view(0, 0, 3, 3);
458 let _view2 = view;
459 view.to_image();
460 }
461
462 #[test]
463 fn test_generic_image_copy_within_oob() {
464 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap();
465 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
466 Rect {
467 x: 0,
468 y: 0,
469 width: 5,
470 height: 4
471 },
472 0,
473 0
474 ));
475 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
476 Rect {
477 x: 0,
478 y: 0,
479 width: 4,
480 height: 5
481 },
482 0,
483 0
484 ));
485 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
486 Rect {
487 x: 1,
488 y: 0,
489 width: 4,
490 height: 4
491 },
492 0,
493 0
494 ));
495 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
496 Rect {
497 x: 0,
498 y: 0,
499 width: 4,
500 height: 4
501 },
502 1,
503 0
504 ));
505 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
506 Rect {
507 x: 0,
508 y: 1,
509 width: 4,
510 height: 4
511 },
512 0,
513 0
514 ));
515 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
516 Rect {
517 x: 0,
518 y: 0,
519 width: 4,
520 height: 4
521 },
522 0,
523 1
524 ));
525 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
526 Rect {
527 x: 1,
528 y: 1,
529 width: 4,
530 height: 4
531 },
532 0,
533 0
534 ));
535 }
536
537 #[test]
538 fn test_generic_image_copy_within_tl() {
539 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
540 let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10];
541 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
542 assert!(image.sub_image(0, 0, 4, 4).copy_within(
543 Rect {
544 x: 0,
545 y: 0,
546 width: 3,
547 height: 3
548 },
549 1,
550 1
551 ));
552 assert_eq!(&image.into_raw(), &expected);
553 }
554
555 #[test]
556 fn test_generic_image_copy_within_tr() {
557 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
558 let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15];
559 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
560 assert!(image.sub_image(0, 0, 4, 4).copy_within(
561 Rect {
562 x: 1,
563 y: 0,
564 width: 3,
565 height: 3
566 },
567 0,
568 1
569 ));
570 assert_eq!(&image.into_raw(), &expected);
571 }
572
573 #[test]
574 fn test_generic_image_copy_within_bl() {
575 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
576 let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15];
577 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
578 assert!(image.sub_image(0, 0, 4, 4).copy_within(
579 Rect {
580 x: 0,
581 y: 1,
582 width: 3,
583 height: 3
584 },
585 1,
586 0
587 ));
588 assert_eq!(&image.into_raw(), &expected);
589 }
590
591 #[test]
592 fn test_generic_image_copy_within_br() {
593 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
594 let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15];
595 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
596 assert!(image.sub_image(0, 0, 4, 4).copy_within(
597 Rect {
598 x: 1,
599 y: 1,
600 width: 3,
601 height: 3
602 },
603 0,
604 0
605 ));
606 assert_eq!(&image.into_raw(), &expected);
607 }
608}