1use crate::error::{ImageError, ImageResult};
2use crate::flat::ViewOfPixel;
3use crate::math::Rect;
4use crate::traits::Pixel;
5use crate::{ImageBuffer, SubImage};
6
7pub trait GenericImageView {
16 type Pixel: Pixel;
18
19 fn dimensions(&self) -> (u32, u32);
21
22 fn width(&self) -> u32 {
24 let (w, _) = self.dimensions();
25 w
26 }
27
28 fn height(&self) -> u32 {
30 let (_, h) = self.dimensions();
31 h
32 }
33
34 fn in_bounds(&self, x: u32, y: u32) -> bool {
36 let (width, height) = self.dimensions();
37 x < width && y < height
38 }
39
40 fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel;
46
47 unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
56 self.get_pixel(x, y)
57 }
58
59 fn pixels(&self) -> Pixels<'_, Self>
63 where
64 Self: Sized,
65 {
66 let (width, height) = self.dimensions();
67
68 Pixels {
69 image: self,
70 x: 0,
71 y: 0,
72 width,
73 height,
74 }
75 }
76
77 fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self>
85 where
86 Self: Sized,
87 {
88 assert!(u64::from(x) + u64::from(width) <= u64::from(self.width()));
89 assert!(u64::from(y) + u64::from(height) <= u64::from(self.height()));
90 SubImage::new(self, x, y, width, height)
91 }
92
93 fn try_view(
96 &self,
97 x: u32,
98 y: u32,
99 width: u32,
100 height: u32,
101 ) -> Result<SubImage<&Self>, ImageError>
102 where
103 Self: Sized,
104 {
105 let rect = Rect {
106 x,
107 y,
108 width,
109 height,
110 };
111
112 rect.test_in_bounds(self)?;
113 Ok(SubImage::new(self, x, y, width, height))
114 }
115
116 fn buffer_like(&self) -> ImageBuffer<Self::Pixel, Vec<<Self::Pixel as Pixel>::Subpixel>> {
125 let (w, h) = self.dimensions();
126 self.buffer_with_dimensions(w, h)
127 }
128
129 fn buffer_with_dimensions(
136 &self,
137 width: u32,
138 height: u32,
139 ) -> ImageBuffer<Self::Pixel, Vec<<Self::Pixel as Pixel>::Subpixel>> {
140 ImageBuffer::new(width, height)
141 }
142
143 fn to_pixel_view(&self) -> Option<ViewOfPixel<'_, Self::Pixel>> {
154 None
155 }
156}
157
158#[derive(Debug)]
160pub struct Pixels<'a, I: ?Sized + 'a> {
161 image: &'a I,
162 x: u32,
163 y: u32,
164 width: u32,
165 height: u32,
166}
167
168impl<I: GenericImageView> Iterator for Pixels<'_, I> {
169 type Item = (u32, u32, I::Pixel);
170
171 fn next(&mut self) -> Option<(u32, u32, I::Pixel)> {
172 if self.x >= self.width {
173 self.x = 0;
174 self.y += 1;
175 }
176
177 if self.y >= self.height {
178 None
179 } else {
180 let pixel = self.image.get_pixel(self.x, self.y);
181 let p = (self.x, self.y, pixel);
182
183 self.x += 1;
184
185 Some(p)
186 }
187 }
188}
189
190impl<I: ?Sized> Clone for Pixels<'_, I> {
191 fn clone(&self) -> Self {
192 Pixels { ..*self }
193 }
194}
195
196pub trait GenericImage: GenericImageView {
198 #[deprecated(since = "0.24.0", note = "Use `get_pixel` and `put_pixel` instead.")]
219 fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel;
220
221 fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
227
228 unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
237 self.put_pixel(x, y, pixel);
238 }
239
240 #[deprecated(
242 since = "0.24.0",
243 note = "Use iterator `pixels_mut` to blend the pixels directly"
244 )]
245 fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
246
247 fn copy_from<O>(&mut self, other: &O, x: u32, y: u32) -> ImageResult<()>
263 where
264 O: GenericImageView<Pixel = Self::Pixel>,
265 {
266 if let Some(flat) = other.to_pixel_view() {
267 return self.copy_from_samples(flat, x, y);
268 }
269
270 Rect::from_image_at(other, x, y).test_in_bounds(self)?;
273
274 for k in 0..other.height() {
275 for i in 0..other.width() {
276 let p = other.get_pixel(i, k);
277 self.put_pixel(i + x, k + y, p);
278 }
279 }
280
281 Ok(())
282 }
283
284 fn copy_from_samples(
286 &mut self,
287 samples: ViewOfPixel<'_, Self::Pixel>,
288 x: u32,
289 y: u32,
290 ) -> ImageResult<()> {
291 Rect::from_image_at(&samples, x, y).test_in_bounds(self)?;
294
295 for k in 0..samples.height() {
296 for i in 0..samples.width() {
297 let p = samples.get_pixel(i, k);
298 self.put_pixel(i + x, k + y, p);
299 }
300 }
301
302 Ok(())
303 }
304
305 fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool {
313 let Rect {
314 x: sx,
315 y: sy,
316 width,
317 height,
318 } = source;
319 let dx = x;
320 let dy = y;
321 assert!(sx < self.width() && dx < self.width());
322 assert!(sy < self.height() && dy < self.height());
323 if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height {
324 return false;
325 }
326 macro_rules! copy_within_impl_ {
329 ($xiter:expr, $yiter:expr) => {
330 for y in $yiter {
331 let sy = sy + y;
332 let dy = dy + y;
333 for x in $xiter {
334 let sx = sx + x;
335 let dx = dx + x;
336 let pixel = self.get_pixel(sx, sy);
337 self.put_pixel(dx, dy, pixel);
338 }
339 }
340 };
341 }
342 match (sx < dx, sy < dy) {
344 (true, true) => copy_within_impl_!((0..width).rev(), (0..height).rev()),
345 (true, false) => copy_within_impl_!((0..width).rev(), 0..height),
346 (false, true) => copy_within_impl_!(0..width, (0..height).rev()),
347 (false, false) => copy_within_impl_!(0..width, 0..height),
348 }
349 true
350 }
351
352 fn sub_image(&mut self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&mut Self>
356 where
357 Self: Sized,
358 {
359 assert!(u64::from(x) + u64::from(width) <= u64::from(self.width()));
360 assert!(u64::from(y) + u64::from(height) <= u64::from(self.height()));
361 SubImage::new(self, x, y, width, height)
362 }
363}
364
365#[cfg(test)]
366mod tests {
367 use super::{GenericImage, GenericImageView};
368
369 use crate::color::Rgba;
370 use crate::math::Rect;
371 use crate::{GrayImage, ImageBuffer};
372
373 #[test]
374 #[allow(deprecated)]
375 fn test_image_alpha_blending() {
377 let mut target = ImageBuffer::new(1, 1);
378 target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
379 assert!(*target.get_pixel(0, 0) == Rgba([255, 0, 0, 255]));
380 target.blend_pixel(0, 0, Rgba([0, 255, 0, 255]));
381 assert!(*target.get_pixel(0, 0) == Rgba([0, 255, 0, 255]));
382
383 target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
385 assert!(*target.get_pixel(0, 0) == Rgba([127, 127, 0, 255]));
386
387 target.put_pixel(0, 0, Rgba([0, 255, 0, 127]));
389 target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
390 assert!(*target.get_pixel(0, 0) == Rgba([169, 85, 0, 190]));
391 }
392
393 #[test]
394 fn test_in_bounds() {
395 let mut target = ImageBuffer::new(2, 2);
396 target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
397
398 assert!(target.in_bounds(0, 0));
399 assert!(target.in_bounds(1, 0));
400 assert!(target.in_bounds(0, 1));
401 assert!(target.in_bounds(1, 1));
402
403 assert!(!target.in_bounds(2, 0));
404 assert!(!target.in_bounds(0, 2));
405 assert!(!target.in_bounds(2, 2));
406 }
407
408 #[test]
409 fn test_can_subimage_clone_nonmut() {
410 let mut source = ImageBuffer::new(3, 3);
411 source.put_pixel(1, 1, Rgba([255u8, 0, 0, 255]));
412
413 let source = source.clone();
415
416 let cloned = source.view(1, 1, 1, 1).to_image();
418
419 assert!(cloned.get_pixel(0, 0) == source.get_pixel(1, 1));
420 }
421
422 #[test]
423 fn test_can_nest_views() {
424 let mut source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
425
426 {
427 let mut sub1 = source.sub_image(0, 0, 2, 2);
428 let mut sub2 = sub1.sub_image(1, 1, 1, 1);
429 sub2.put_pixel(0, 0, Rgba([0, 0, 0, 0]));
430 }
431
432 assert_eq!(*source.get_pixel(1, 1), Rgba([0, 0, 0, 0]));
433
434 let view1 = source.view(0, 0, 2, 2);
435 assert_eq!(*source.get_pixel(1, 1), view1.get_pixel(1, 1));
436
437 let view2 = view1.view(1, 1, 1, 1);
438 assert_eq!(*source.get_pixel(1, 1), view2.get_pixel(0, 0));
439 }
440
441 #[test]
442 #[should_panic]
443 fn test_view_out_of_bounds() {
444 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
445 source.view(1, 1, 3, 3);
446 }
447
448 #[test]
449 #[should_panic]
450 fn test_view_coordinates_out_of_bounds() {
451 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
452 source.view(3, 3, 3, 3);
453 }
454
455 #[test]
456 #[should_panic]
457 fn test_view_width_out_of_bounds() {
458 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
459 source.view(1, 1, 3, 2);
460 }
461
462 #[test]
463 #[should_panic]
464 fn test_view_height_out_of_bounds() {
465 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
466 source.view(1, 1, 2, 3);
467 }
468
469 #[test]
470 #[should_panic]
471 fn test_view_x_out_of_bounds() {
472 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
473 source.view(3, 1, 3, 3);
474 }
475
476 #[test]
477 #[should_panic]
478 fn test_view_y_out_of_bounds() {
479 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
480 source.view(1, 3, 3, 3);
481 }
482
483 #[test]
484 fn test_view_in_bounds() {
485 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
486 source.view(0, 0, 3, 3);
487 source.view(1, 1, 2, 2);
488 source.view(2, 2, 0, 0);
489 }
490
491 #[test]
492 fn test_copy_sub_image() {
493 let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
494 let view = source.view(0, 0, 3, 3);
495 let _view2 = view;
496 view.to_image();
497 }
498
499 #[test]
500 fn test_generic_image_copy_within_oob() {
501 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap();
502 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
503 Rect {
504 x: 0,
505 y: 0,
506 width: 5,
507 height: 4
508 },
509 0,
510 0
511 ));
512 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
513 Rect {
514 x: 0,
515 y: 0,
516 width: 4,
517 height: 5
518 },
519 0,
520 0
521 ));
522 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
523 Rect {
524 x: 1,
525 y: 0,
526 width: 4,
527 height: 4
528 },
529 0,
530 0
531 ));
532 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
533 Rect {
534 x: 0,
535 y: 0,
536 width: 4,
537 height: 4
538 },
539 1,
540 0
541 ));
542 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
543 Rect {
544 x: 0,
545 y: 1,
546 width: 4,
547 height: 4
548 },
549 0,
550 0
551 ));
552 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
553 Rect {
554 x: 0,
555 y: 0,
556 width: 4,
557 height: 4
558 },
559 0,
560 1
561 ));
562 assert!(!image.sub_image(0, 0, 4, 4).copy_within(
563 Rect {
564 x: 1,
565 y: 1,
566 width: 4,
567 height: 4
568 },
569 0,
570 0
571 ));
572 }
573
574 #[test]
575 fn test_generic_image_copy_within_tl() {
576 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
577 let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10];
578 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
579 assert!(image.sub_image(0, 0, 4, 4).copy_within(
580 Rect {
581 x: 0,
582 y: 0,
583 width: 3,
584 height: 3
585 },
586 1,
587 1
588 ));
589 assert_eq!(&image.into_raw(), &expected);
590 }
591
592 #[test]
593 fn test_generic_image_copy_within_tr() {
594 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
595 let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15];
596 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
597 assert!(image.sub_image(0, 0, 4, 4).copy_within(
598 Rect {
599 x: 1,
600 y: 0,
601 width: 3,
602 height: 3
603 },
604 0,
605 1
606 ));
607 assert_eq!(&image.into_raw(), &expected);
608 }
609
610 #[test]
611 fn test_generic_image_copy_within_bl() {
612 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
613 let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15];
614 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
615 assert!(image.sub_image(0, 0, 4, 4).copy_within(
616 Rect {
617 x: 0,
618 y: 1,
619 width: 3,
620 height: 3
621 },
622 1,
623 0
624 ));
625 assert_eq!(&image.into_raw(), &expected);
626 }
627
628 #[test]
629 fn test_generic_image_copy_within_br() {
630 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
631 let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15];
632 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
633 assert!(image.sub_image(0, 0, 4, 4).copy_within(
634 Rect {
635 x: 1,
636 y: 1,
637 width: 3,
638 height: 3
639 },
640 0,
641 0
642 ));
643 assert_eq!(&image.into_raw(), &expected);
644 }
645}