1use num_traits::Zero;
3use std::fmt;
4use std::marker::PhantomData;
5use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
6use std::path::Path;
7use std::slice::{ChunksExact, ChunksExactMut};
8
9use crate::color::{FromColor, Luma, LumaA, Rgb, Rgba};
10use crate::dynimage::{save_buffer, save_buffer_with_format, write_buffer_with_format};
11use crate::error::ImageResult;
12use crate::flat::{FlatSamples, SampleLayout};
13use crate::image::{GenericImage, GenericImageView, ImageEncoder, ImageFormat};
14use crate::math::Rect;
15use crate::traits::{EncodableLayout, Pixel, PixelWithColorType};
16use crate::utils::expand_packed;
17use crate::DynamicImage;
18
19pub struct Pixels<'a, P: Pixel + 'a>
21where
22 P::Subpixel: 'a,
23{
24 chunks: ChunksExact<'a, P::Subpixel>,
25}
26
27impl<'a, P: Pixel + 'a> Iterator for Pixels<'a, P>
28where
29 P::Subpixel: 'a,
30{
31 type Item = &'a P;
32
33 #[inline(always)]
34 fn next(&mut self) -> Option<&'a P> {
35 self.chunks.next().map(|v| <P as Pixel>::from_slice(v))
36 }
37
38 #[inline(always)]
39 fn size_hint(&self) -> (usize, Option<usize>) {
40 let len = self.len();
41 (len, Some(len))
42 }
43}
44
45impl<'a, P: Pixel + 'a> ExactSizeIterator for Pixels<'a, P>
46where
47 P::Subpixel: 'a,
48{
49 fn len(&self) -> usize {
50 self.chunks.len()
51 }
52}
53
54impl<'a, P: Pixel + 'a> DoubleEndedIterator for Pixels<'a, P>
55where
56 P::Subpixel: 'a,
57{
58 #[inline(always)]
59 fn next_back(&mut self) -> Option<&'a P> {
60 self.chunks.next_back().map(|v| <P as Pixel>::from_slice(v))
61 }
62}
63
64impl<P: Pixel> Clone for Pixels<'_, P> {
65 fn clone(&self) -> Self {
66 Pixels {
67 chunks: self.chunks.clone(),
68 }
69 }
70}
71
72impl<P: Pixel> fmt::Debug for Pixels<'_, P>
73where
74 P::Subpixel: fmt::Debug,
75{
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 f.debug_struct("Pixels")
78 .field("chunks", &self.chunks)
79 .finish()
80 }
81}
82
83pub struct PixelsMut<'a, P: Pixel + 'a>
85where
86 P::Subpixel: 'a,
87{
88 chunks: ChunksExactMut<'a, P::Subpixel>,
89}
90
91impl<'a, P: Pixel + 'a> Iterator for PixelsMut<'a, P>
92where
93 P::Subpixel: 'a,
94{
95 type Item = &'a mut P;
96
97 #[inline(always)]
98 fn next(&mut self) -> Option<&'a mut P> {
99 self.chunks.next().map(|v| <P as Pixel>::from_slice_mut(v))
100 }
101
102 #[inline(always)]
103 fn size_hint(&self) -> (usize, Option<usize>) {
104 let len = self.len();
105 (len, Some(len))
106 }
107}
108
109impl<'a, P: Pixel + 'a> ExactSizeIterator for PixelsMut<'a, P>
110where
111 P::Subpixel: 'a,
112{
113 fn len(&self) -> usize {
114 self.chunks.len()
115 }
116}
117
118impl<'a, P: Pixel + 'a> DoubleEndedIterator for PixelsMut<'a, P>
119where
120 P::Subpixel: 'a,
121{
122 #[inline(always)]
123 fn next_back(&mut self) -> Option<&'a mut P> {
124 self.chunks
125 .next_back()
126 .map(|v| <P as Pixel>::from_slice_mut(v))
127 }
128}
129
130impl<P: Pixel> fmt::Debug for PixelsMut<'_, P>
131where
132 P::Subpixel: fmt::Debug,
133{
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 f.debug_struct("PixelsMut")
136 .field("chunks", &self.chunks)
137 .finish()
138 }
139}
140
141pub struct Rows<'a, P: Pixel + 'a>
147where
148 <P as Pixel>::Subpixel: 'a,
149{
150 pixels: ChunksExact<'a, P::Subpixel>,
151}
152
153impl<'a, P: Pixel + 'a> Rows<'a, P> {
154 fn with_image(pixels: &'a [P::Subpixel], width: u32, height: u32) -> Self {
157 let row_len = (width as usize) * usize::from(<P as Pixel>::CHANNEL_COUNT);
158 if row_len == 0 {
159 Rows {
160 pixels: [].chunks_exact(1),
161 }
162 } else {
163 let pixels = pixels
164 .get(..row_len * height as usize)
165 .expect("Pixel buffer has too few subpixels");
166 Rows {
169 pixels: pixels.chunks_exact(row_len),
170 }
171 }
172 }
173}
174
175impl<'a, P: Pixel + 'a> Iterator for Rows<'a, P>
176where
177 P::Subpixel: 'a,
178{
179 type Item = Pixels<'a, P>;
180
181 #[inline(always)]
182 fn next(&mut self) -> Option<Pixels<'a, P>> {
183 let row = self.pixels.next()?;
184 Some(Pixels {
185 chunks: row.chunks_exact(<P as Pixel>::CHANNEL_COUNT as usize),
187 })
188 }
189
190 #[inline(always)]
191 fn size_hint(&self) -> (usize, Option<usize>) {
192 let len = self.len();
193 (len, Some(len))
194 }
195}
196
197impl<'a, P: Pixel + 'a> ExactSizeIterator for Rows<'a, P>
198where
199 P::Subpixel: 'a,
200{
201 fn len(&self) -> usize {
202 self.pixels.len()
203 }
204}
205
206impl<'a, P: Pixel + 'a> DoubleEndedIterator for Rows<'a, P>
207where
208 P::Subpixel: 'a,
209{
210 #[inline(always)]
211 fn next_back(&mut self) -> Option<Pixels<'a, P>> {
212 let row = self.pixels.next_back()?;
213 Some(Pixels {
214 chunks: row.chunks_exact(<P as Pixel>::CHANNEL_COUNT as usize),
216 })
217 }
218}
219
220impl<P: Pixel> Clone for Rows<'_, P> {
221 fn clone(&self) -> Self {
222 Rows {
223 pixels: self.pixels.clone(),
224 }
225 }
226}
227
228impl<P: Pixel> fmt::Debug for Rows<'_, P>
229where
230 P::Subpixel: fmt::Debug,
231{
232 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
233 f.debug_struct("Rows")
234 .field("pixels", &self.pixels)
235 .finish()
236 }
237}
238
239pub struct RowsMut<'a, P: Pixel + 'a>
245where
246 <P as Pixel>::Subpixel: 'a,
247{
248 pixels: ChunksExactMut<'a, P::Subpixel>,
249}
250
251impl<'a, P: Pixel + 'a> RowsMut<'a, P> {
252 fn with_image(pixels: &'a mut [P::Subpixel], width: u32, height: u32) -> Self {
255 let row_len = (width as usize) * usize::from(<P as Pixel>::CHANNEL_COUNT);
256 if row_len == 0 {
257 RowsMut {
258 pixels: [].chunks_exact_mut(1),
259 }
260 } else {
261 let pixels = pixels
262 .get_mut(..row_len * height as usize)
263 .expect("Pixel buffer has too few subpixels");
264 RowsMut {
267 pixels: pixels.chunks_exact_mut(row_len),
268 }
269 }
270 }
271}
272
273impl<'a, P: Pixel + 'a> Iterator for RowsMut<'a, P>
274where
275 P::Subpixel: 'a,
276{
277 type Item = PixelsMut<'a, P>;
278
279 #[inline(always)]
280 fn next(&mut self) -> Option<PixelsMut<'a, P>> {
281 let row = self.pixels.next()?;
282 Some(PixelsMut {
283 chunks: row.chunks_exact_mut(<P as Pixel>::CHANNEL_COUNT as usize),
285 })
286 }
287
288 #[inline(always)]
289 fn size_hint(&self) -> (usize, Option<usize>) {
290 let len = self.len();
291 (len, Some(len))
292 }
293}
294
295impl<'a, P: Pixel + 'a> ExactSizeIterator for RowsMut<'a, P>
296where
297 P::Subpixel: 'a,
298{
299 fn len(&self) -> usize {
300 self.pixels.len()
301 }
302}
303
304impl<'a, P: Pixel + 'a> DoubleEndedIterator for RowsMut<'a, P>
305where
306 P::Subpixel: 'a,
307{
308 #[inline(always)]
309 fn next_back(&mut self) -> Option<PixelsMut<'a, P>> {
310 let row = self.pixels.next_back()?;
311 Some(PixelsMut {
312 chunks: row.chunks_exact_mut(<P as Pixel>::CHANNEL_COUNT as usize),
314 })
315 }
316}
317
318impl<P: Pixel> fmt::Debug for RowsMut<'_, P>
319where
320 P::Subpixel: fmt::Debug,
321{
322 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
323 f.debug_struct("RowsMut")
324 .field("pixels", &self.pixels)
325 .finish()
326 }
327}
328
329pub struct EnumeratePixels<'a, P: Pixel + 'a>
331where
332 <P as Pixel>::Subpixel: 'a,
333{
334 pixels: Pixels<'a, P>,
335 x: u32,
336 y: u32,
337 width: u32,
338}
339
340impl<'a, P: Pixel + 'a> Iterator for EnumeratePixels<'a, P>
341where
342 P::Subpixel: 'a,
343{
344 type Item = (u32, u32, &'a P);
345
346 #[inline(always)]
347 fn next(&mut self) -> Option<(u32, u32, &'a P)> {
348 if self.x >= self.width {
349 self.x = 0;
350 self.y += 1;
351 }
352 let (x, y) = (self.x, self.y);
353 self.x += 1;
354 self.pixels.next().map(|p| (x, y, p))
355 }
356
357 #[inline(always)]
358 fn size_hint(&self) -> (usize, Option<usize>) {
359 let len = self.len();
360 (len, Some(len))
361 }
362}
363
364impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixels<'a, P>
365where
366 P::Subpixel: 'a,
367{
368 fn len(&self) -> usize {
369 self.pixels.len()
370 }
371}
372
373impl<P: Pixel> Clone for EnumeratePixels<'_, P> {
374 fn clone(&self) -> Self {
375 EnumeratePixels {
376 pixels: self.pixels.clone(),
377 ..*self
378 }
379 }
380}
381
382impl<P: Pixel> fmt::Debug for EnumeratePixels<'_, P>
383where
384 P::Subpixel: fmt::Debug,
385{
386 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
387 f.debug_struct("EnumeratePixels")
388 .field("pixels", &self.pixels)
389 .field("x", &self.x)
390 .field("y", &self.y)
391 .field("width", &self.width)
392 .finish()
393 }
394}
395
396pub struct EnumerateRows<'a, P: Pixel + 'a>
398where
399 <P as Pixel>::Subpixel: 'a,
400{
401 rows: Rows<'a, P>,
402 y: u32,
403 width: u32,
404}
405
406impl<'a, P: Pixel + 'a> Iterator for EnumerateRows<'a, P>
407where
408 P::Subpixel: 'a,
409{
410 type Item = (u32, EnumeratePixels<'a, P>);
411
412 #[inline(always)]
413 fn next(&mut self) -> Option<(u32, EnumeratePixels<'a, P>)> {
414 let y = self.y;
415 self.y += 1;
416 self.rows.next().map(|r| {
417 (
418 y,
419 EnumeratePixels {
420 x: 0,
421 y,
422 width: self.width,
423 pixels: r,
424 },
425 )
426 })
427 }
428
429 #[inline(always)]
430 fn size_hint(&self) -> (usize, Option<usize>) {
431 let len = self.len();
432 (len, Some(len))
433 }
434}
435
436impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRows<'a, P>
437where
438 P::Subpixel: 'a,
439{
440 fn len(&self) -> usize {
441 self.rows.len()
442 }
443}
444
445impl<P: Pixel> Clone for EnumerateRows<'_, P> {
446 fn clone(&self) -> Self {
447 EnumerateRows {
448 rows: self.rows.clone(),
449 ..*self
450 }
451 }
452}
453
454impl<P: Pixel> fmt::Debug for EnumerateRows<'_, P>
455where
456 P::Subpixel: fmt::Debug,
457{
458 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
459 f.debug_struct("EnumerateRows")
460 .field("rows", &self.rows)
461 .field("y", &self.y)
462 .field("width", &self.width)
463 .finish()
464 }
465}
466
467pub struct EnumeratePixelsMut<'a, P: Pixel + 'a>
469where
470 <P as Pixel>::Subpixel: 'a,
471{
472 pixels: PixelsMut<'a, P>,
473 x: u32,
474 y: u32,
475 width: u32,
476}
477
478impl<'a, P: Pixel + 'a> Iterator for EnumeratePixelsMut<'a, P>
479where
480 P::Subpixel: 'a,
481{
482 type Item = (u32, u32, &'a mut P);
483
484 #[inline(always)]
485 fn next(&mut self) -> Option<(u32, u32, &'a mut P)> {
486 if self.x >= self.width {
487 self.x = 0;
488 self.y += 1;
489 }
490 let (x, y) = (self.x, self.y);
491 self.x += 1;
492 self.pixels.next().map(|p| (x, y, p))
493 }
494
495 #[inline(always)]
496 fn size_hint(&self) -> (usize, Option<usize>) {
497 let len = self.len();
498 (len, Some(len))
499 }
500}
501
502impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixelsMut<'a, P>
503where
504 P::Subpixel: 'a,
505{
506 fn len(&self) -> usize {
507 self.pixels.len()
508 }
509}
510
511impl<P: Pixel> fmt::Debug for EnumeratePixelsMut<'_, P>
512where
513 P::Subpixel: fmt::Debug,
514{
515 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
516 f.debug_struct("EnumeratePixelsMut")
517 .field("pixels", &self.pixels)
518 .field("x", &self.x)
519 .field("y", &self.y)
520 .field("width", &self.width)
521 .finish()
522 }
523}
524
525pub struct EnumerateRowsMut<'a, P: Pixel + 'a>
527where
528 <P as Pixel>::Subpixel: 'a,
529{
530 rows: RowsMut<'a, P>,
531 y: u32,
532 width: u32,
533}
534
535impl<'a, P: Pixel + 'a> Iterator for EnumerateRowsMut<'a, P>
536where
537 P::Subpixel: 'a,
538{
539 type Item = (u32, EnumeratePixelsMut<'a, P>);
540
541 #[inline(always)]
542 fn next(&mut self) -> Option<(u32, EnumeratePixelsMut<'a, P>)> {
543 let y = self.y;
544 self.y += 1;
545 self.rows.next().map(|r| {
546 (
547 y,
548 EnumeratePixelsMut {
549 x: 0,
550 y,
551 width: self.width,
552 pixels: r,
553 },
554 )
555 })
556 }
557
558 #[inline(always)]
559 fn size_hint(&self) -> (usize, Option<usize>) {
560 let len = self.len();
561 (len, Some(len))
562 }
563}
564
565impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRowsMut<'a, P>
566where
567 P::Subpixel: 'a,
568{
569 fn len(&self) -> usize {
570 self.rows.len()
571 }
572}
573
574impl<P: Pixel> fmt::Debug for EnumerateRowsMut<'_, P>
575where
576 P::Subpixel: fmt::Debug,
577{
578 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
579 f.debug_struct("EnumerateRowsMut")
580 .field("rows", &self.rows)
581 .field("y", &self.y)
582 .field("width", &self.width)
583 .finish()
584 }
585}
586
587#[derive(Debug, Hash, PartialEq, Eq)]
656pub struct ImageBuffer<P: Pixel, Container> {
657 width: u32,
658 height: u32,
659 _phantom: PhantomData<P>,
660 data: Container,
661}
662
663impl<P, Container> ImageBuffer<P, Container>
665where
666 P: Pixel,
667 Container: Deref<Target = [P::Subpixel]>,
668{
669 pub fn from_raw(width: u32, height: u32, buf: Container) -> Option<ImageBuffer<P, Container>> {
675 if Self::check_image_fits(width, height, buf.len()) {
676 Some(ImageBuffer {
677 data: buf,
678 width,
679 height,
680 _phantom: PhantomData,
681 })
682 } else {
683 None
684 }
685 }
686
687 pub fn into_raw(self) -> Container {
689 self.data
690 }
691
692 pub fn as_raw(&self) -> &Container {
694 &self.data
695 }
696
697 pub fn dimensions(&self) -> (u32, u32) {
699 (self.width, self.height)
700 }
701
702 pub fn width(&self) -> u32 {
704 self.width
705 }
706
707 pub fn height(&self) -> u32 {
709 self.height
710 }
711
712 pub(crate) fn inner_pixels(&self) -> &[P::Subpixel] {
714 let len = Self::image_buffer_len(self.width, self.height).unwrap();
715 &self.data[..len]
716 }
717
718 pub fn pixels(&self) -> Pixels<P> {
721 Pixels {
722 chunks: self
723 .inner_pixels()
724 .chunks_exact(<P as Pixel>::CHANNEL_COUNT as usize),
725 }
726 }
727
728 pub fn rows(&self) -> Rows<P> {
734 Rows::with_image(&self.data, self.width, self.height)
735 }
736
737 pub fn enumerate_pixels(&self) -> EnumeratePixels<P> {
743 EnumeratePixels {
744 pixels: self.pixels(),
745 x: 0,
746 y: 0,
747 width: self.width,
748 }
749 }
750
751 pub fn enumerate_rows(&self) -> EnumerateRows<P> {
755 EnumerateRows {
756 rows: self.rows(),
757 y: 0,
758 width: self.width,
759 }
760 }
761
762 #[inline]
768 #[track_caller]
769 pub fn get_pixel(&self, x: u32, y: u32) -> &P {
770 match self.pixel_indices(x, y) {
771 None => panic!(
772 "Image index {:?} out of bounds {:?}",
773 (x, y),
774 (self.width, self.height)
775 ),
776 Some(pixel_indices) => <P as Pixel>::from_slice(&self.data[pixel_indices]),
777 }
778 }
779
780 pub fn get_pixel_checked(&self, x: u32, y: u32) -> Option<&P> {
783 if x >= self.width {
784 return None;
785 }
786 let num_channels = <P as Pixel>::CHANNEL_COUNT as usize;
787 let i = (y as usize)
788 .saturating_mul(self.width as usize)
789 .saturating_add(x as usize)
790 .saturating_mul(num_channels);
791
792 self.data
793 .get(i..i.checked_add(num_channels)?)
794 .map(|pixel_indices| <P as Pixel>::from_slice(pixel_indices))
795 }
796
797 fn check_image_fits(width: u32, height: u32, len: usize) -> bool {
803 let checked_len = Self::image_buffer_len(width, height);
804 checked_len.map_or(false, |min_len| min_len <= len)
805 }
806
807 fn image_buffer_len(width: u32, height: u32) -> Option<usize> {
808 Some(<P as Pixel>::CHANNEL_COUNT as usize)
809 .and_then(|size| size.checked_mul(width as usize))
810 .and_then(|size| size.checked_mul(height as usize))
811 }
812
813 #[inline(always)]
814 fn pixel_indices(&self, x: u32, y: u32) -> Option<Range<usize>> {
815 if x >= self.width || y >= self.height {
816 return None;
817 }
818
819 Some(self.pixel_indices_unchecked(x, y))
820 }
821
822 #[inline(always)]
823 fn pixel_indices_unchecked(&self, x: u32, y: u32) -> Range<usize> {
824 let no_channels = <P as Pixel>::CHANNEL_COUNT as usize;
825 let min_index = (y as usize * self.width as usize + x as usize) * no_channels;
827 min_index..min_index + no_channels
828 }
829
830 pub fn sample_layout(&self) -> SampleLayout {
832 SampleLayout::row_major_packed(<P as Pixel>::CHANNEL_COUNT, self.width, self.height)
834 }
835
836 pub fn into_flat_samples(self) -> FlatSamples<Container>
843 where
844 Container: AsRef<[P::Subpixel]>,
845 {
846 let layout = self.sample_layout();
848 FlatSamples {
849 samples: self.data,
850 layout,
851 color_hint: None, }
853 }
854
855 pub fn as_flat_samples(&self) -> FlatSamples<&[P::Subpixel]>
859 where
860 Container: AsRef<[P::Subpixel]>,
861 {
862 let layout = self.sample_layout();
863 FlatSamples {
864 samples: self.data.as_ref(),
865 layout,
866 color_hint: None, }
868 }
869
870 pub fn as_flat_samples_mut(&mut self) -> FlatSamples<&mut [P::Subpixel]>
874 where
875 Container: AsMut<[P::Subpixel]>,
876 {
877 let layout = self.sample_layout();
878 FlatSamples {
879 samples: self.data.as_mut(),
880 layout,
881 color_hint: None, }
883 }
884}
885
886impl<P, Container> ImageBuffer<P, Container>
887where
888 P: Pixel,
889 Container: Deref<Target = [P::Subpixel]> + DerefMut,
890{
891 pub(crate) fn inner_pixels_mut(&mut self) -> &mut [P::Subpixel] {
893 let len = Self::image_buffer_len(self.width, self.height).unwrap();
894 &mut self.data[..len]
895 }
896
897 pub fn pixels_mut(&mut self) -> PixelsMut<P> {
899 PixelsMut {
900 chunks: self
901 .inner_pixels_mut()
902 .chunks_exact_mut(<P as Pixel>::CHANNEL_COUNT as usize),
903 }
904 }
905
906 pub fn rows_mut(&mut self) -> RowsMut<P> {
912 RowsMut::with_image(&mut self.data, self.width, self.height)
913 }
914
915 pub fn enumerate_pixels_mut(&mut self) -> EnumeratePixelsMut<P> {
919 let width = self.width;
920 EnumeratePixelsMut {
921 pixels: self.pixels_mut(),
922 x: 0,
923 y: 0,
924 width,
925 }
926 }
927
928 pub fn enumerate_rows_mut(&mut self) -> EnumerateRowsMut<P> {
932 let width = self.width;
933 EnumerateRowsMut {
934 rows: self.rows_mut(),
935 y: 0,
936 width,
937 }
938 }
939
940 #[inline]
946 #[track_caller]
947 pub fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
948 match self.pixel_indices(x, y) {
949 None => panic!(
950 "Image index {:?} out of bounds {:?}",
951 (x, y),
952 (self.width, self.height)
953 ),
954 Some(pixel_indices) => <P as Pixel>::from_slice_mut(&mut self.data[pixel_indices]),
955 }
956 }
957
958 pub fn get_pixel_mut_checked(&mut self, x: u32, y: u32) -> Option<&mut P> {
961 if x >= self.width {
962 return None;
963 }
964 let num_channels = <P as Pixel>::CHANNEL_COUNT as usize;
965 let i = (y as usize)
966 .saturating_mul(self.width as usize)
967 .saturating_add(x as usize)
968 .saturating_mul(num_channels);
969
970 self.data
971 .get_mut(i..i.checked_add(num_channels)?)
972 .map(|pixel_indices| <P as Pixel>::from_slice_mut(pixel_indices))
973 }
974
975 #[inline]
981 #[track_caller]
982 pub fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
983 *self.get_pixel_mut(x, y) = pixel;
984 }
985}
986
987impl<P, Container> ImageBuffer<P, Container>
988where
989 P: Pixel,
990 [P::Subpixel]: EncodableLayout,
991 Container: Deref<Target = [P::Subpixel]>,
992{
993 pub fn save<Q>(&self, path: Q) -> ImageResult<()>
997 where
998 Q: AsRef<Path>,
999 P: PixelWithColorType,
1000 {
1001 save_buffer(
1002 path,
1003 self.inner_pixels().as_bytes(),
1004 self.width(),
1005 self.height(),
1006 <P as PixelWithColorType>::COLOR_TYPE,
1007 )
1008 }
1009}
1010
1011impl<P, Container> ImageBuffer<P, Container>
1012where
1013 P: Pixel,
1014 [P::Subpixel]: EncodableLayout,
1015 Container: Deref<Target = [P::Subpixel]>,
1016{
1017 pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> ImageResult<()>
1023 where
1024 Q: AsRef<Path>,
1025 P: PixelWithColorType,
1026 {
1027 save_buffer_with_format(
1029 path,
1030 self.inner_pixels().as_bytes(),
1031 self.width(),
1032 self.height(),
1033 <P as PixelWithColorType>::COLOR_TYPE,
1034 format,
1035 )
1036 }
1037}
1038
1039impl<P, Container> ImageBuffer<P, Container>
1040where
1041 P: Pixel,
1042 [P::Subpixel]: EncodableLayout,
1043 Container: Deref<Target = [P::Subpixel]>,
1044{
1045 pub fn write_to<W>(&self, writer: &mut W, format: ImageFormat) -> ImageResult<()>
1050 where
1051 W: std::io::Write + std::io::Seek,
1052 P: PixelWithColorType,
1053 {
1054 write_buffer_with_format(
1056 writer,
1057 self.inner_pixels().as_bytes(),
1058 self.width(),
1059 self.height(),
1060 <P as PixelWithColorType>::COLOR_TYPE,
1061 format,
1062 )
1063 }
1064}
1065
1066impl<P, Container> ImageBuffer<P, Container>
1067where
1068 P: Pixel,
1069 [P::Subpixel]: EncodableLayout,
1070 Container: Deref<Target = [P::Subpixel]>,
1071{
1072 pub fn write_with_encoder<E>(&self, encoder: E) -> ImageResult<()>
1074 where
1075 E: ImageEncoder,
1076 P: PixelWithColorType,
1077 {
1078 encoder.write_image(
1080 self.inner_pixels().as_bytes(),
1081 self.width(),
1082 self.height(),
1083 <P as PixelWithColorType>::COLOR_TYPE,
1084 )
1085 }
1086}
1087
1088impl<P, Container> Default for ImageBuffer<P, Container>
1089where
1090 P: Pixel,
1091 Container: Default,
1092{
1093 fn default() -> Self {
1094 Self {
1095 width: 0,
1096 height: 0,
1097 _phantom: PhantomData,
1098 data: Default::default(),
1099 }
1100 }
1101}
1102
1103impl<P, Container> Deref for ImageBuffer<P, Container>
1104where
1105 P: Pixel,
1106 Container: Deref<Target = [P::Subpixel]>,
1107{
1108 type Target = [P::Subpixel];
1109
1110 fn deref(&self) -> &<Self as Deref>::Target {
1111 &self.data
1112 }
1113}
1114
1115impl<P, Container> DerefMut for ImageBuffer<P, Container>
1116where
1117 P: Pixel,
1118 Container: Deref<Target = [P::Subpixel]> + DerefMut,
1119{
1120 fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
1121 &mut self.data
1122 }
1123}
1124
1125impl<P, Container> Index<(u32, u32)> for ImageBuffer<P, Container>
1126where
1127 P: Pixel,
1128 Container: Deref<Target = [P::Subpixel]>,
1129{
1130 type Output = P;
1131
1132 fn index(&self, (x, y): (u32, u32)) -> &P {
1133 self.get_pixel(x, y)
1134 }
1135}
1136
1137impl<P, Container> IndexMut<(u32, u32)> for ImageBuffer<P, Container>
1138where
1139 P: Pixel,
1140 Container: Deref<Target = [P::Subpixel]> + DerefMut,
1141{
1142 fn index_mut(&mut self, (x, y): (u32, u32)) -> &mut P {
1143 self.get_pixel_mut(x, y)
1144 }
1145}
1146
1147impl<P, Container> Clone for ImageBuffer<P, Container>
1148where
1149 P: Pixel,
1150 Container: Deref<Target = [P::Subpixel]> + Clone,
1151{
1152 fn clone(&self) -> ImageBuffer<P, Container> {
1153 ImageBuffer {
1154 data: self.data.clone(),
1155 width: self.width,
1156 height: self.height,
1157 _phantom: PhantomData,
1158 }
1159 }
1160
1161 fn clone_from(&mut self, source: &Self) {
1162 self.data.clone_from(&source.data);
1163 self.width = source.width;
1164 self.height = source.height;
1165 }
1166}
1167
1168impl<P, Container> GenericImageView for ImageBuffer<P, Container>
1169where
1170 P: Pixel,
1171 Container: Deref<Target = [P::Subpixel]> + Deref,
1172{
1173 type Pixel = P;
1174
1175 fn dimensions(&self) -> (u32, u32) {
1176 self.dimensions()
1177 }
1178
1179 fn get_pixel(&self, x: u32, y: u32) -> P {
1180 *self.get_pixel(x, y)
1181 }
1182
1183 #[inline(always)]
1185 unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> P {
1186 let indices = self.pixel_indices_unchecked(x, y);
1187 *<P as Pixel>::from_slice(self.data.get_unchecked(indices))
1188 }
1189}
1190
1191impl<P, Container> GenericImage for ImageBuffer<P, Container>
1192where
1193 P: Pixel,
1194 Container: Deref<Target = [P::Subpixel]> + DerefMut,
1195{
1196 fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
1197 self.get_pixel_mut(x, y)
1198 }
1199
1200 fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
1201 *self.get_pixel_mut(x, y) = pixel;
1202 }
1203
1204 #[inline(always)]
1206 unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: P) {
1207 let indices = self.pixel_indices_unchecked(x, y);
1208 let p = <P as Pixel>::from_slice_mut(self.data.get_unchecked_mut(indices));
1209 *p = pixel;
1210 }
1211
1212 fn blend_pixel(&mut self, x: u32, y: u32, p: P) {
1216 self.get_pixel_mut(x, y).blend(&p);
1217 }
1218
1219 fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool {
1220 let Rect {
1221 x: sx,
1222 y: sy,
1223 width,
1224 height,
1225 } = source;
1226 let dx = x;
1227 let dy = y;
1228 assert!(sx < self.width() && dx < self.width());
1229 assert!(sy < self.height() && dy < self.height());
1230 if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height {
1231 return false;
1232 }
1233
1234 if sy < dy {
1235 for y in (0..height).rev() {
1236 let sy = sy + y;
1237 let dy = dy + y;
1238 let Range { start, .. } = self.pixel_indices_unchecked(sx, sy);
1239 let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy);
1240 let dst = self.pixel_indices_unchecked(dx, dy).start;
1241 self.data.copy_within(start..end, dst);
1242 }
1243 } else {
1244 for y in 0..height {
1245 let sy = sy + y;
1246 let dy = dy + y;
1247 let Range { start, .. } = self.pixel_indices_unchecked(sx, sy);
1248 let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy);
1249 let dst = self.pixel_indices_unchecked(dx, dy).start;
1250 self.data.copy_within(start..end, dst);
1251 }
1252 }
1253 true
1254 }
1255}
1256
1257impl<P: Pixel> ImageBuffer<P, Vec<P::Subpixel>> {
1264 #[must_use]
1272 pub fn new(width: u32, height: u32) -> ImageBuffer<P, Vec<P::Subpixel>> {
1273 let size = Self::image_buffer_len(width, height)
1274 .expect("Buffer length in `ImageBuffer::new` overflows usize");
1275 ImageBuffer {
1276 data: vec![Zero::zero(); size],
1277 width,
1278 height,
1279 _phantom: PhantomData,
1280 }
1281 }
1282
1283 pub fn from_pixel(width: u32, height: u32, pixel: P) -> ImageBuffer<P, Vec<P::Subpixel>> {
1289 let mut buf = ImageBuffer::new(width, height);
1290 for p in buf.pixels_mut() {
1291 *p = pixel;
1292 }
1293 buf
1294 }
1295
1296 pub fn from_fn<F>(width: u32, height: u32, mut f: F) -> ImageBuffer<P, Vec<P::Subpixel>>
1304 where
1305 F: FnMut(u32, u32) -> P,
1306 {
1307 let mut buf = ImageBuffer::new(width, height);
1308 for (x, y, p) in buf.enumerate_pixels_mut() {
1309 *p = f(x, y);
1310 }
1311 buf
1312 }
1313
1314 #[must_use]
1317 pub fn from_vec(
1318 width: u32,
1319 height: u32,
1320 buf: Vec<P::Subpixel>,
1321 ) -> Option<ImageBuffer<P, Vec<P::Subpixel>>> {
1322 ImageBuffer::from_raw(width, height, buf)
1323 }
1324
1325 #[must_use]
1328 pub fn into_vec(self) -> Vec<P::Subpixel> {
1329 self.into_raw()
1330 }
1331}
1332
1333pub trait ConvertBuffer<T> {
1335 fn convert(&self) -> T;
1340}
1341
1342impl GrayImage {
1344 #[must_use]
1348 pub fn expand_palette(
1349 self,
1350 palette: &[(u8, u8, u8)],
1351 transparent_idx: Option<u8>,
1352 ) -> RgbaImage {
1353 let (width, height) = self.dimensions();
1354 let mut data = self.into_raw();
1355 let entries = data.len();
1356 data.resize(entries.checked_mul(4).unwrap(), 0);
1357 let mut buffer = ImageBuffer::from_vec(width, height, data).unwrap();
1358 expand_packed(&mut buffer, 4, 8, |idx, pixel| {
1359 let (r, g, b) = palette[idx as usize];
1360 let a = if let Some(t_idx) = transparent_idx {
1361 if t_idx == idx {
1362 0
1363 } else {
1364 255
1365 }
1366 } else {
1367 255
1368 };
1369 pixel[0] = r;
1370 pixel[1] = g;
1371 pixel[2] = b;
1372 pixel[3] = a;
1373 });
1374 buffer
1375 }
1376}
1377
1378impl<Container, FromType: Pixel, ToType: Pixel>
1382 ConvertBuffer<ImageBuffer<ToType, Vec<ToType::Subpixel>>> for ImageBuffer<FromType, Container>
1383where
1384 Container: Deref<Target = [FromType::Subpixel]>,
1385 ToType: FromColor<FromType>,
1386{
1387 fn convert(&self) -> ImageBuffer<ToType, Vec<ToType::Subpixel>> {
1401 let mut buffer: ImageBuffer<ToType, Vec<ToType::Subpixel>> =
1402 ImageBuffer::new(self.width, self.height);
1403 for (to, from) in buffer.pixels_mut().zip(self.pixels()) {
1404 to.from_color(from);
1405 }
1406 buffer
1407 }
1408}
1409
1410pub type RgbImage = ImageBuffer<Rgb<u8>, Vec<u8>>;
1412pub type RgbaImage = ImageBuffer<Rgba<u8>, Vec<u8>>;
1414pub type GrayImage = ImageBuffer<Luma<u8>, Vec<u8>>;
1416pub type GrayAlphaImage = ImageBuffer<LumaA<u8>, Vec<u8>>;
1418pub(crate) type Rgb16Image = ImageBuffer<Rgb<u16>, Vec<u16>>;
1420pub(crate) type Rgba16Image = ImageBuffer<Rgba<u16>, Vec<u16>>;
1422pub(crate) type Gray16Image = ImageBuffer<Luma<u16>, Vec<u16>>;
1424pub(crate) type GrayAlpha16Image = ImageBuffer<LumaA<u16>, Vec<u16>>;
1426
1427pub type Rgb32FImage = ImageBuffer<Rgb<f32>, Vec<f32>>;
1430
1431pub type Rgba32FImage = ImageBuffer<Rgba<f32>, Vec<f32>>;
1434
1435impl From<DynamicImage> for RgbImage {
1436 fn from(value: DynamicImage) -> Self {
1437 value.into_rgb8()
1438 }
1439}
1440
1441impl From<DynamicImage> for RgbaImage {
1442 fn from(value: DynamicImage) -> Self {
1443 value.into_rgba8()
1444 }
1445}
1446
1447impl From<DynamicImage> for GrayImage {
1448 fn from(value: DynamicImage) -> Self {
1449 value.into_luma8()
1450 }
1451}
1452
1453impl From<DynamicImage> for GrayAlphaImage {
1454 fn from(value: DynamicImage) -> Self {
1455 value.into_luma_alpha8()
1456 }
1457}
1458
1459impl From<DynamicImage> for Rgb16Image {
1460 fn from(value: DynamicImage) -> Self {
1461 value.into_rgb16()
1462 }
1463}
1464
1465impl From<DynamicImage> for Rgba16Image {
1466 fn from(value: DynamicImage) -> Self {
1467 value.into_rgba16()
1468 }
1469}
1470
1471impl From<DynamicImage> for Gray16Image {
1472 fn from(value: DynamicImage) -> Self {
1473 value.into_luma16()
1474 }
1475}
1476
1477impl From<DynamicImage> for GrayAlpha16Image {
1478 fn from(value: DynamicImage) -> Self {
1479 value.into_luma_alpha16()
1480 }
1481}
1482
1483impl From<DynamicImage> for Rgba32FImage {
1484 fn from(value: DynamicImage) -> Self {
1485 value.into_rgba32f()
1486 }
1487}
1488
1489#[cfg(test)]
1490mod test {
1491 use super::{GrayImage, ImageBuffer, RgbImage};
1492 use crate::math::Rect;
1493 use crate::GenericImage as _;
1494 use crate::ImageFormat;
1495 use crate::{Luma, LumaA, Pixel, Rgb, Rgba};
1496 use num_traits::Zero;
1497
1498 #[test]
1499 fn slice_buffer() {
1501 let data = [0; 9];
1502 let buf: ImageBuffer<Luma<u8>, _> = ImageBuffer::from_raw(3, 3, &data[..]).unwrap();
1503 assert_eq!(&*buf, &data[..])
1504 }
1505
1506 macro_rules! new_buffer_zero_test {
1507 ($test_name:ident, $pxt:ty) => {
1508 #[test]
1509 fn $test_name() {
1510 let buffer = ImageBuffer::<$pxt, Vec<<$pxt as Pixel>::Subpixel>>::new(2, 2);
1511 assert!(buffer
1512 .iter()
1513 .all(|p| *p == <$pxt as Pixel>::Subpixel::zero()));
1514 }
1515 };
1516 }
1517
1518 new_buffer_zero_test!(luma_u8_zero_test, Luma<u8>);
1519 new_buffer_zero_test!(luma_u16_zero_test, Luma<u16>);
1520 new_buffer_zero_test!(luma_f32_zero_test, Luma<f32>);
1521 new_buffer_zero_test!(luma_a_u8_zero_test, LumaA<u8>);
1522 new_buffer_zero_test!(luma_a_u16_zero_test, LumaA<u16>);
1523 new_buffer_zero_test!(luma_a_f32_zero_test, LumaA<f32>);
1524 new_buffer_zero_test!(rgb_u8_zero_test, Rgb<u8>);
1525 new_buffer_zero_test!(rgb_u16_zero_test, Rgb<u16>);
1526 new_buffer_zero_test!(rgb_f32_zero_test, Rgb<f32>);
1527 new_buffer_zero_test!(rgb_a_u8_zero_test, Rgba<u8>);
1528 new_buffer_zero_test!(rgb_a_u16_zero_test, Rgba<u16>);
1529 new_buffer_zero_test!(rgb_a_f32_zero_test, Rgba<f32>);
1530
1531 #[test]
1532 fn get_pixel() {
1533 let mut a: RgbImage = ImageBuffer::new(10, 10);
1534 {
1535 let b = a.get_mut(3 * 10).unwrap();
1536 *b = 255;
1537 }
1538 assert_eq!(a.get_pixel(0, 1)[0], 255)
1539 }
1540
1541 #[test]
1542 fn get_pixel_checked() {
1543 let mut a: RgbImage = ImageBuffer::new(10, 10);
1544 a.get_pixel_mut_checked(0, 1).unwrap()[0] = 255;
1545
1546 assert_eq!(a.get_pixel_checked(0, 1), Some(&Rgb([255, 0, 0])));
1547 assert_eq!(a.get_pixel_checked(0, 1).unwrap(), a.get_pixel(0, 1));
1548 assert_eq!(a.get_pixel_checked(10, 0), None);
1549 assert_eq!(a.get_pixel_checked(0, 10), None);
1550 assert_eq!(a.get_pixel_mut_checked(10, 0), None);
1551 assert_eq!(a.get_pixel_mut_checked(0, 10), None);
1552
1553 const WHITE: Rgb<u8> = Rgb([255_u8, 255, 255]);
1555 let mut a = RgbImage::new(2, 1);
1556 a.put_pixel(1, 0, WHITE);
1557
1558 assert_eq!(a.get_pixel_checked(1, 0), Some(&WHITE));
1559 assert_eq!(a.get_pixel_checked(1, 0).unwrap(), a.get_pixel(1, 0));
1560 }
1561
1562 #[test]
1563 fn mut_iter() {
1564 let mut a: RgbImage = ImageBuffer::new(10, 10);
1565 {
1566 let val = a.pixels_mut().next().unwrap();
1567 *val = Rgb([42, 0, 0]);
1568 }
1569 assert_eq!(a.data[0], 42);
1570 }
1571
1572 #[test]
1573 fn zero_width_zero_height() {
1574 let mut image = RgbImage::new(0, 0);
1575
1576 assert_eq!(image.rows_mut().count(), 0);
1577 assert_eq!(image.pixels_mut().count(), 0);
1578 assert_eq!(image.rows().count(), 0);
1579 assert_eq!(image.pixels().count(), 0);
1580 }
1581
1582 #[test]
1583 fn zero_width_nonzero_height() {
1584 let mut image = RgbImage::new(0, 2);
1585
1586 assert_eq!(image.rows_mut().count(), 0);
1587 assert_eq!(image.pixels_mut().count(), 0);
1588 assert_eq!(image.rows().count(), 0);
1589 assert_eq!(image.pixels().count(), 0);
1590 }
1591
1592 #[test]
1593 fn nonzero_width_zero_height() {
1594 let mut image = RgbImage::new(2, 0);
1595
1596 assert_eq!(image.rows_mut().count(), 0);
1597 assert_eq!(image.pixels_mut().count(), 0);
1598 assert_eq!(image.rows().count(), 0);
1599 assert_eq!(image.pixels().count(), 0);
1600 }
1601
1602 #[test]
1603 fn pixels_on_large_buffer() {
1604 let mut image = RgbImage::from_raw(1, 1, vec![0; 6]).unwrap();
1605
1606 assert_eq!(image.pixels().count(), 1);
1607 assert_eq!(image.enumerate_pixels().count(), 1);
1608 assert_eq!(image.pixels_mut().count(), 1);
1609 assert_eq!(image.enumerate_pixels_mut().count(), 1);
1610
1611 assert_eq!(image.rows().count(), 1);
1612 assert_eq!(image.rows_mut().count(), 1);
1613 }
1614
1615 #[test]
1616 fn default() {
1617 let image = ImageBuffer::<Rgb<u8>, Vec<u8>>::default();
1618 assert_eq!(image.dimensions(), (0, 0));
1619 }
1620
1621 #[test]
1622 #[rustfmt::skip]
1623 fn test_image_buffer_copy_within_oob() {
1624 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap();
1625 assert!(!image.copy_within(Rect { x: 0, y: 0, width: 5, height: 4 }, 0, 0));
1626 assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 5 }, 0, 0));
1627 assert!(!image.copy_within(Rect { x: 1, y: 0, width: 4, height: 4 }, 0, 0));
1628 assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 1, 0));
1629 assert!(!image.copy_within(Rect { x: 0, y: 1, width: 4, height: 4 }, 0, 0));
1630 assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 0, 1));
1631 assert!(!image.copy_within(Rect { x: 1, y: 1, width: 4, height: 4 }, 0, 0));
1632 }
1633
1634 #[test]
1635 fn test_image_buffer_copy_within_tl() {
1636 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1637 let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10];
1638 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1639 assert!(image.copy_within(
1640 Rect {
1641 x: 0,
1642 y: 0,
1643 width: 3,
1644 height: 3
1645 },
1646 1,
1647 1
1648 ));
1649 assert_eq!(&image.into_raw(), &expected);
1650 }
1651
1652 #[test]
1653 fn test_image_buffer_copy_within_tr() {
1654 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1655 let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15];
1656 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1657 assert!(image.copy_within(
1658 Rect {
1659 x: 1,
1660 y: 0,
1661 width: 3,
1662 height: 3
1663 },
1664 0,
1665 1
1666 ));
1667 assert_eq!(&image.into_raw(), &expected);
1668 }
1669
1670 #[test]
1671 fn test_image_buffer_copy_within_bl() {
1672 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1673 let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15];
1674 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1675 assert!(image.copy_within(
1676 Rect {
1677 x: 0,
1678 y: 1,
1679 width: 3,
1680 height: 3
1681 },
1682 1,
1683 0
1684 ));
1685 assert_eq!(&image.into_raw(), &expected);
1686 }
1687
1688 #[test]
1689 fn test_image_buffer_copy_within_br() {
1690 let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1691 let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15];
1692 let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1693 assert!(image.copy_within(
1694 Rect {
1695 x: 1,
1696 y: 1,
1697 width: 3,
1698 height: 3
1699 },
1700 0,
1701 0
1702 ));
1703 assert_eq!(&image.into_raw(), &expected);
1704 }
1705
1706 #[test]
1707 #[cfg(feature = "png")]
1708 fn write_to_with_large_buffer() {
1709 let img: GrayImage = ImageBuffer::from_raw(1, 1, vec![0u8; 4]).unwrap();
1712 let mut buffer = std::io::Cursor::new(vec![]);
1713 assert!(img.write_to(&mut buffer, ImageFormat::Png).is_ok());
1714 }
1715
1716 #[test]
1717 fn exact_size_iter_size_hint() {
1718 const N: u32 = 10;
1723
1724 let mut image = RgbImage::from_raw(N, N, vec![0; (N * N * 3) as usize]).unwrap();
1725
1726 let iter = image.pixels();
1727 let exact_len = ExactSizeIterator::len(&iter);
1728 assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
1729
1730 let iter = image.pixels_mut();
1731 let exact_len = ExactSizeIterator::len(&iter);
1732 assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
1733
1734 let iter = image.rows();
1735 let exact_len = ExactSizeIterator::len(&iter);
1736 assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
1737
1738 let iter = image.rows_mut();
1739 let exact_len = ExactSizeIterator::len(&iter);
1740 assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
1741
1742 let iter = image.enumerate_pixels();
1743 let exact_len = ExactSizeIterator::len(&iter);
1744 assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
1745
1746 let iter = image.enumerate_rows();
1747 let exact_len = ExactSizeIterator::len(&iter);
1748 assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
1749
1750 let iter = image.enumerate_pixels_mut();
1751 let exact_len = ExactSizeIterator::len(&iter);
1752 assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
1753
1754 let iter = image.enumerate_rows_mut();
1755 let exact_len = ExactSizeIterator::len(&iter);
1756 assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
1757 }
1758}
1759
1760#[cfg(test)]
1761#[cfg(feature = "benchmarks")]
1762mod benchmarks {
1763 use super::{ConvertBuffer, GrayImage, ImageBuffer, Pixel, RgbImage};
1764
1765 #[bench]
1766 fn conversion(b: &mut test::Bencher) {
1767 let mut a: RgbImage = ImageBuffer::new(1000, 1000);
1768 for p in a.pixels_mut() {
1769 let rgb = p.channels_mut();
1770 rgb[0] = 255;
1771 rgb[1] = 23;
1772 rgb[2] = 42;
1773 }
1774 assert!(a.data[0] != 0);
1775 b.iter(|| {
1776 let b: GrayImage = a.convert();
1777 assert!(0 != b.data[0]);
1778 assert!(a.data[0] != b.data[0]);
1779 test::black_box(b);
1780 });
1781 b.bytes = 1000 * 1000 * 3
1782 }
1783
1784 #[bench]
1785 fn image_access_row_by_row(b: &mut test::Bencher) {
1786 let mut a: RgbImage = ImageBuffer::new(1000, 1000);
1787 for p in a.pixels_mut() {
1788 let rgb = p.channels_mut();
1789 rgb[0] = 255;
1790 rgb[1] = 23;
1791 rgb[2] = 42;
1792 }
1793
1794 b.iter(move || {
1795 let image: &RgbImage = test::black_box(&a);
1796 let mut sum: usize = 0;
1797 for y in 0..1000 {
1798 for x in 0..1000 {
1799 let pixel = image.get_pixel(x, y);
1800 sum = sum.wrapping_add(pixel[0] as usize);
1801 sum = sum.wrapping_add(pixel[1] as usize);
1802 sum = sum.wrapping_add(pixel[2] as usize);
1803 }
1804 }
1805 test::black_box(sum)
1806 });
1807
1808 b.bytes = 1000 * 1000 * 3;
1809 }
1810
1811 #[bench]
1812 fn image_access_col_by_col(b: &mut test::Bencher) {
1813 let mut a: RgbImage = ImageBuffer::new(1000, 1000);
1814 for p in a.pixels_mut() {
1815 let rgb = p.channels_mut();
1816 rgb[0] = 255;
1817 rgb[1] = 23;
1818 rgb[2] = 42;
1819 }
1820
1821 b.iter(move || {
1822 let image: &RgbImage = test::black_box(&a);
1823 let mut sum: usize = 0;
1824 for x in 0..1000 {
1825 for y in 0..1000 {
1826 let pixel = image.get_pixel(x, y);
1827 sum = sum.wrapping_add(pixel[0] as usize);
1828 sum = sum.wrapping_add(pixel[1] as usize);
1829 sum = sum.wrapping_add(pixel[2] as usize);
1830 }
1831 }
1832 test::black_box(sum)
1833 });
1834
1835 b.bytes = 1000 * 1000 * 3;
1836 }
1837}