1#![no_std]
53
54extern crate alloc;
55#[cfg(test)]
56extern crate std;
57
58use alloc::borrow::{Cow, ToOwned};
59use alloc::vec::Vec;
60use core::slice;
61
62mod traits;
63
64mod iter;
65mod ops;
66pub use iter::*;
67
68pub type ImgVec<Pixel> = Img<Vec<Pixel>>;
74
75pub type ImgRef<'slice, Pixel> = Img<&'slice [Pixel]>;
80
81pub type ImgRefMut<'slice, Pixel> = Img<&'slice mut [Pixel]>;
85
86pub trait ImgExt<Pixel> {
94 #[cfg(feature = "deprecated")]
100 fn width_padded(&self) -> usize;
101
102 #[cfg(feature = "deprecated")]
109 fn height_padded(&self) -> usize;
110
111 #[cfg(feature = "deprecated")]
115 fn rows_padded(&self) -> slice::Chunks<'_, Pixel>;
116
117 fn as_ref(&self) -> ImgRef<'_, Pixel>;
119}
120
121pub trait ImgExtMut<Pixel> {
129 #[cfg(feature = "deprecated")]
133 fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel>;
134
135 fn as_mut(&mut self) -> ImgRefMut<'_, Pixel>;
137}
138
139#[derive(Debug, Copy, Clone)]
143pub struct Img<Container> {
144 #[deprecated(note = "Don't access struct fields directly. Use buf(), buf_mut() or into_buf()")]
148 #[cfg(feature = "deprecated")]
149 pub buf: Container,
150
151 #[cfg(not(feature = "deprecated"))]
152 buf: Container,
153
154 #[deprecated(note = "Don't access struct fields directly. Use stride()")]
158 #[cfg(feature = "deprecated")]
159 pub stride: usize,
160
161 #[cfg(not(feature = "deprecated"))]
162 stride: usize,
163
164 #[deprecated(note = "Don't access struct fields directly. Use width()")]
168 #[cfg(feature = "deprecated")]
169 pub width: u32,
170
171 #[cfg(not(feature = "deprecated"))]
172 width: u32,
173
174 #[deprecated(note = "Don't access struct fields directly. Use height()")]
176 #[cfg(feature = "deprecated")]
177 pub height: u32,
178
179 #[cfg(not(feature = "deprecated"))]
180 height: u32,
181}
182
183impl<Container> Img<Container> {
184 #[inline(always)]
188 #[allow(deprecated)]
189 pub const fn width(&self) -> usize { self.width as usize }
190
191 #[inline(always)]
193 #[allow(deprecated)]
194 pub const fn height(&self) -> usize { self.height as usize }
195
196 #[inline(always)]
201 #[allow(deprecated)]
202 pub const fn stride(&self) -> usize { self.stride }
203
204 #[inline(always)]
208 #[allow(deprecated)]
209 pub const fn buf(&self) -> &Container { &self.buf }
210
211 #[inline(always)]
215 #[allow(deprecated)]
216 pub fn buf_mut(&mut self) -> &mut Container { &mut self.buf }
217
218 #[inline(always)]
220 #[allow(deprecated)]
221 pub fn into_buf(self) -> Container { self.buf }
222
223 #[deprecated(note = "this was meant to be private, use new_buf() and/or rows()")]
224 #[cfg(feature = "deprecated")]
225 #[doc(hidden)]
226 pub fn rows_buf<'buf, T: 'buf>(&self, buf: &'buf [T]) -> RowsIter<'buf, T> {
227 self.rows_buf_internal(buf)
228 }
229
230 #[inline]
231 #[track_caller]
232 fn rows_buf_internal<'buf, T: 'buf>(&self, buf: &'buf [T]) -> RowsIter<'buf, T> {
233 let stride = self.stride();
234 debug_assert!(self.width() <= self.stride());
235 debug_assert!(buf.len() >= self.width() * self.height());
236 assert!(stride > 0);
237 let non_padded = &buf[0..stride * self.height() + self.width() - stride];
238 RowsIter {
239 width: self.width(),
240 inner: non_padded.chunks(stride),
241 }
242 }
243}
244
245impl<Pixel,Container> ImgExt<Pixel> for Img<Container> where Container: AsRef<[Pixel]> {
246 #[inline(always)]
247 #[cfg(feature = "deprecated")]
248 fn width_padded(&self) -> usize {
249 self.stride()
250 }
251
252 #[inline(always)]
253 #[cfg(feature = "deprecated")]
254 fn height_padded(&self) -> usize {
255 let len = self.buf().as_ref().len();
256 assert_eq!(0, len % self.stride());
257 len / self.stride()
258 }
259
260 #[inline(always)]
264 #[cfg(feature = "deprecated")]
265 fn rows_padded(&self) -> slice::Chunks<'_, Pixel> {
266 self.buf().as_ref().chunks(self.stride())
267 }
268
269 #[inline(always)]
270 #[allow(deprecated)]
271 fn as_ref(&self) -> ImgRef<'_, Pixel> {
272 Img {
273 buf: self.buf.as_ref(),
274 width: self.width,
275 height: self.height,
276 stride: self.stride,
277 }
278 }
279}
280
281impl<Pixel,Container> ImgExtMut<Pixel> for Img<Container> where Container: AsMut<[Pixel]> {
282 #[cfg(feature = "deprecated")]
290 fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel> {
291 let stride = self.stride();
292 self.buf_mut().as_mut().chunks_mut(stride)
293 }
294
295 #[inline(always)]
296 #[allow(deprecated)]
297 fn as_mut(&mut self) -> ImgRefMut<'_, Pixel> {
298 Img {
299 buf: self.buf.as_mut(),
300 width: self.width,
301 height: self.height,
302 stride: self.stride,
303 }
304 }
305}
306
307#[inline]
308fn sub_image(left: usize, top: usize, width: usize, height: usize, stride: usize, buf_len: usize) -> (usize, usize, usize) {
309 let start = stride * top + left;
310 let full_strides_end = start + stride * height;
311 let end = if buf_len >= full_strides_end {
313 full_strides_end
314 } else {
315 debug_assert!(height > 0);
316 let min_strides_len = full_strides_end + width - stride;
317 debug_assert!(buf_len >= min_strides_len, "the buffer is too small to fit the subimage");
318 min_strides_len
320 };
321 (start, end, stride)
322}
323
324impl<'slice, T> ImgRef<'slice, T> {
325 #[inline]
332 #[must_use]
333 #[track_caller]
334 pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> Self {
335 assert!(top + height <= self.height());
336 assert!(left + width <= self.width());
337 let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf().len());
338 let buf = &self.buf()[start..end];
339 Self::new_stride(buf, width, height, stride)
340 }
341
342 #[inline]
343 pub fn rows(&self) -> RowsIter<'slice, T> {
351 self.rows_buf_internal(self.buf())
352 }
353
354 #[deprecated(note = "Size of this buffer is unpredictable. Use .rows() instead")]
358 #[cfg(feature = "deprecated")]
359 #[doc(hidden)]
360 pub fn iter(&self) -> slice::Iter<'slice, T> {
361 self.buf().iter()
362 }
363}
364
365impl<'a, T: Clone> ImgRef<'a, T> {
366 #[allow(deprecated)]
372 #[must_use]
373 pub fn to_contiguous_buf(&self) -> (Cow<'a, [T]>, usize, usize) {
374 let width = self.width();
375 let height = self.height();
376 let stride = self.stride();
377 if width == stride {
378 return (Cow::Borrowed(self.buf), width, height);
379 }
380 let mut buf = Vec::with_capacity(width * height);
381 for row in self.rows() {
382 buf.extend_from_slice(row);
383 }
384 (Cow::Owned(buf), width, height)
385 }
386}
387
388impl<'slice, T> ImgRefMut<'slice, T> {
389 #[inline]
391 #[allow(deprecated)]
392 #[must_use]
393 pub fn sub_image(&'slice self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'slice, T> {
394 self.as_ref().sub_image(left, top, width, height)
395 }
396
397 #[inline]
406 #[allow(deprecated)]
407 #[must_use]
408 #[track_caller]
409 pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
410 assert!(top + height <= self.height());
411 assert!(left + width <= self.width());
412 let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf.len());
413 let buf = &mut self.buf[start..end];
414 ImgRefMut::new_stride(buf, width, height, stride)
415 }
416
417 #[allow(deprecated)]
426 #[must_use]
427 #[track_caller]
428 pub fn into_sub_image_mut(self, left: usize, top: usize, width: usize, height: usize) -> Self {
429 assert!(top + height <= self.height());
430 assert!(left + width <= self.width());
431 let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf.len());
432 let buf = &mut self.buf[start..end];
433 ImgRefMut::new_stride(buf, width, height, stride)
434 }
435
436 #[inline]
438 #[must_use]
439 pub fn as_ref(&self) -> ImgRef<'_, T> {
440 self.new_buf(self.buf().as_ref())
441 }
442}
443
444impl<'slice, T: Copy> ImgRef<'slice, T> {
445 #[inline]
453 #[track_caller]
454 pub fn pixels(&self) -> PixelsIter<'slice, T> {
455 PixelsIter::new(*self)
456 }
457}
458
459impl<'slice, T> ImgRef<'slice, T> {
460 #[inline]
468 pub fn pixels_ref(&self) -> PixelsRefIter<'slice, T> {
469 PixelsRefIter::new(*self)
470 }
471}
472
473impl<T: Copy> ImgRefMut<'_, T> {
474 #[inline]
480 pub fn pixels(&self) -> PixelsIter<'_, T> {
481 PixelsIter::new(self.as_ref())
482 }
483}
484
485impl<T> ImgRefMut<'_, T> {
486 #[inline]
491 pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> {
492 PixelsIterMut::new(self)
493 }
494}
495
496impl<T: Copy> ImgVec<T> {
497 #[inline]
502 pub fn pixels(&self) -> PixelsIter<'_, T> {
503 PixelsIter::new(self.as_ref())
504 }
505}
506
507impl<T> ImgVec<T> {
508 #[inline]
513 pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> {
514 PixelsIterMut::new(&mut self.as_mut())
515 }
516}
517
518impl<T> ImgRefMut<'_, T> {
519 #[inline]
525 pub fn rows(&self) -> RowsIter<'_, T> {
526 self.rows_buf_internal(&self.buf()[..])
527 }
528
529 #[inline]
535 #[allow(deprecated)]
536 pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> {
537 let stride = self.stride();
538 let width = self.width();
539 let height = self.height();
540 let non_padded = &mut self.buf[0..stride * height + width - stride];
541 RowsIterMut {
542 width,
543 inner: non_padded.chunks_mut(stride),
544 }
545 }
546}
547
548#[cfg(feature = "deprecated")]
550impl<Container> IntoIterator for Img<Container> where Container: IntoIterator {
551 type Item = Container::Item;
552 type IntoIter = Container::IntoIter;
553 fn into_iter(self) -> Container::IntoIter {
555 self.into_buf().into_iter()
556 }
557}
558
559impl<T> ImgVec<T> {
560 #[allow(deprecated)]
566 #[must_use]
567 #[track_caller]
568 pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
569 assert!(top + height <= self.height());
570 assert!(left + width <= self.width());
571 let start = self.stride * top + left;
572 let min_buf_size = if self.height > 0 { self.stride * height + width - self.stride } else {0};
573 let buf = &mut self.buf[start .. start + min_buf_size];
574 Img::new_stride(buf, width, height, self.stride)
575 }
576
577 #[inline]
578 #[must_use]
579 pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'_, T> {
581 self.as_ref().sub_image(left, top, width, height)
582 }
583
584 #[inline]
590 #[must_use]
591 pub fn as_ref(&self) -> ImgRef<'_, T> {
592 self.new_buf(self.buf().as_ref())
593 }
594
595 #[inline]
601 pub fn as_mut(&mut self) -> ImgRefMut<'_, T> {
602 let width = self.width();
603 let height = self.height();
604 let stride = self.stride();
605 Img::new_stride(self.buf_mut().as_mut(), width, height, stride)
606 }
607
608 #[deprecated(note = "Size of this buffer may be unpredictable. Use .rows() instead")]
609 #[cfg(feature = "deprecated")]
610 #[doc(hidden)]
611 pub fn iter(&self) -> slice::Iter<'_, T> {
612 self.buf().iter()
613 }
614
615 #[inline]
621 pub fn rows(&self) -> RowsIter<'_, T> {
622 self.rows_buf_internal(self.buf())
623 }
624
625 #[inline]
631 #[allow(deprecated)]
632 pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> {
633 let stride = self.stride();
634 let width = self.width();
635 let height = self.height();
636 let non_padded = &mut self.buf[0..stride * height + width - stride];
637 RowsIterMut {
638 width,
639 inner: non_padded.chunks_mut(stride),
640 }
641 }
642}
643
644impl<Container> Img<Container> {
645 #[inline]
655 #[allow(deprecated)]
656 #[track_caller]
657 pub fn new_stride(buf: Container, width: usize, height: usize, stride: usize) -> Self {
658 assert!(stride > 0);
659 assert!(stride >= width);
660 debug_assert!(height < u32::MAX as usize);
661 debug_assert!(width < u32::MAX as usize);
662 Self {
663 buf,
664 width: width as u32,
665 height: height as u32,
666 stride,
667 }
668 }
669
670 #[inline]
676 pub fn new(buf: Container, width: usize, height: usize) -> Self {
677 Self::new_stride(buf, width, height, width)
678 }
679}
680
681impl<T: Copy> Img<Vec<T>> {
682 #[allow(deprecated)]
687 #[must_use]
688 pub fn into_contiguous_buf(mut self) -> (Vec<T>, usize, usize) {
689 let (_, w, h) = self.as_contiguous_buf();
690 (self.buf, w, h)
691 }
692
693 #[allow(deprecated)]
698 #[must_use]
699 pub fn as_contiguous_buf(&mut self) -> (&[T], usize, usize) {
700 let width = self.width();
701 let height = self.height();
702 let stride = self.stride();
703 if width != stride {
704 for row in 1..height {
705 self.buf.copy_within(row * stride .. row * stride + width, row * width);
706 }
707 }
708 self.buf.truncate(width * height);
709 (&mut self.buf, width, height)
710 }
711}
712
713impl<OldContainer> Img<OldContainer> {
714 #[inline]
716 #[track_caller]
717 pub fn map_buf<NewContainer, OldPixel, NewPixel, F>(self, callback: F) -> Img<NewContainer>
718 where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]>, F: FnOnce(OldContainer) -> NewContainer {
719 let width = self.width();
720 let height = self.height();
721 let stride = self.stride();
722 let old_buf_len = self.buf().as_ref().len();
723 #[allow(deprecated)]
724 let new_buf = callback(self.buf);
725 assert_eq!(old_buf_len, new_buf.as_ref().len());
726 Img::new_stride(new_buf, width, height, stride)
727 }
728
729 #[inline]
731 #[track_caller]
732 pub fn new_buf<NewContainer, OldPixel, NewPixel>(&self, new_buf: NewContainer) -> Img<NewContainer>
733 where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]> {
734 assert_eq!(self.buf().as_ref().len(), new_buf.as_ref().len());
735 Img::new_stride(new_buf, self.width(), self.height(), self.stride())
736 }
737}
738
739impl<T: Clone> From<Img<Cow<'_, [T]>>> for Img<Vec<T>> {
740 #[allow(deprecated)]
741 fn from(img: Img<Cow<'_, [T]>>) -> Self {
742 Self {
743 width: img.width,
744 height: img.height,
745 stride: img.stride,
746 buf: img.buf.into_owned(),
747 }
748 }
749}
750
751impl<T: Clone> From<ImgVec<T>> for Img<Cow<'static, [T]>> {
752 #[allow(deprecated)]
753 fn from(img: ImgVec<T>) -> Self {
754 Img {
755 width: img.width,
756 height: img.height,
757 stride: img.stride,
758 buf: img.buf.into(),
759 }
760 }
761}
762
763impl<'a, T: Clone> From<ImgRef<'a, T>> for Img<Cow<'a, [T]>> {
764 #[allow(deprecated)]
765 fn from(img: ImgRef<'a, T>) -> Self {
766 Img {
767 buf: img.buf.into(),
768 width: img.width,
769 height: img.height,
770 stride: img.stride,
771 }
772 }
773}
774
775impl<T: Clone> Img<Cow<'_, [T]>> {
776 #[allow(deprecated)]
780 #[must_use]
781 pub fn into_owned(self) -> ImgVec<T> {
782 match self.buf {
783 Cow::Borrowed(_) => {
784 let tmp = self.as_ref();
785 let (buf, w, h) = tmp.to_contiguous_buf();
786 ImgVec::new(buf.into_owned(), w, h)
787 },
788 Cow::Owned(buf) => Img {
789 buf,
790 width: self.width,
791 height: self.height,
792 stride: self.stride,
793 },
794 }
795 }
796}
797
798impl<T> Img<T> where T: ToOwned {
799 #[allow(deprecated)]
803 pub fn to_owned(&self) -> Img<T::Owned> {
804 Img {
805 buf: self.buf.to_owned(),
806 width: self.width,
807 height: self.height,
808 stride: self.stride,
809 }
810 }
811}
812
813#[cfg(test)]
814mod tests {
815 use super::*;
816 use alloc::vec;
817
818 mod with_opinionated_container {
819 use super::*;
820
821 struct IDontDeriveAnything;
822
823 #[test]
824 fn compiles() {
825 let _ = Img::new(IDontDeriveAnything, 1, 1);
826 }
827 }
828
829 #[test]
830 fn with_vec() {
831 let bytes = vec![0u8;20];
832 let old = Img::new_stride(bytes, 10,2,10);
833 let _ = old.new_buf(vec![6u16;20]);
834 }
835
836 #[test]
837 fn zero() {
838 let bytes = vec![0u8];
839 let mut img = Img::new_stride(bytes,0,0,1);
840 let _ = img.sub_image(0,0,0,0);
841 let _ = img.sub_image_mut(0,0,0,0);
842 let _ = img.as_ref();
843 }
844
845 #[test]
846 fn zero_width() {
847 let bytes = vec![0u8];
848 let mut img = Img::new_stride(bytes,0,1,1);
849 let _ = img.sub_image(0,1,0,0);
850 let _ = img.sub_image_mut(0,0,0,1);
851 }
852
853 #[test]
854 fn zero_height() {
855 let bytes = vec![0u8];
856 let mut img = Img::new_stride(bytes,1,0,1);
857 assert_eq!(0, img.rows().count());
858 let _ = img.sub_image(1,0,0,0);
859 let _ = img.sub_image_mut(0,0,1,0);
860 }
861
862 #[test]
863 #[allow(deprecated)]
864 fn with_slice() {
865 let bytes = vec![0u8;20];
866 let _ = Img::new_stride(bytes.as_slice(), 10,2,10);
867 let vec = ImgVec::new_stride(bytes, 10,2,10);
868
869 #[cfg(feature = "deprecated")]
870 for _ in vec.iter() {}
871
872 assert_eq!(2, vec.rows().count());
873 for _ in *vec.as_ref().buf() {}
874
875 #[cfg(feature = "deprecated")]
876 for _ in vec {}
877 }
878
879 #[test]
880 fn sub() {
881 let img = Img::new_stride(vec![1,2,3,4,
882 5,6,7,8,
883 9], 3, 2, 4);
884 assert_eq!(img.buf()[img.stride()], 5);
885 assert_eq!(img.buf()[img.stride() + img.width()-1], 7);
886
887 assert_eq!(img.pixels().count(), img.width() * img.height());
888 assert_eq!(img.pixels().sum::<i32>(), 24);
889
890 {
891 let refimg = img.as_ref();
892 let refimg2 = refimg; let s1 = refimg.sub_image(1, 0, refimg.width()-1, refimg.height());
896 let _ = s1.sub_image(1, 0, s1.width()-1, s1.height());
897
898 let subimg = refimg.sub_image(1, 1, 2, 1);
899 assert_eq!(subimg.pixels().count(), subimg.width() * subimg.height());
900
901 assert_eq!(subimg.buf()[0], 6);
902 assert_eq!(subimg.stride(), refimg2.stride());
903 assert!(subimg.stride() * subimg.height() + subimg.width() - subimg.stride() <= subimg.buf().len());
904 assert_eq!(refimg.buf()[0], 1);
905 assert_eq!(1, subimg.rows().count());
906 }
907
908 let mut img_for_mut_1 = img.clone();
910 let mut img_for_mut_2 = img.clone();
911 let mut img_for_mut_3 = img;
912 for mut subimg in [
913 img_for_mut_1.sub_image_mut(1, 1, 2, 1),
914 img_for_mut_2.as_mut().sub_image_mut(1, 1, 2, 1),
915 img_for_mut_3.as_mut().into_sub_image_mut(1, 1, 2, 1),
916 ] {
917 assert_eq!(1, subimg.rows().count());
918 assert_eq!(1, subimg.rows_mut().count());
919 assert_eq!(1, subimg.rows_mut().rev().count());
920 assert_eq!(1, subimg.rows_mut().fuse().rev().count());
921 assert_eq!(subimg.buf()[0], 6);
922 }
923 }
924
925 #[test]
926 fn rows() {
927 let img = ImgVec::new_stride(vec![0u8; 10000], 10, 15, 100);
928 assert_eq!(img.height(), img.rows().count());
929 assert_eq!(img.height(), img.rows().rev().count());
930 assert_eq!(img.height(), img.rows().fuse().rev().count());
931 }
932
933 #[test]
934 fn mut_pixels() {
935 for y in 1..15 {
936 for x in 1..10 {
937 let mut img = ImgVec::new_stride(vec![0u8; 10000], x, y, 100);
938 assert_eq!(x*y, img.pixels_mut().count());
939 assert_eq!(x*y, img.as_mut().pixels().count());
940 assert_eq!(x*y, img.as_mut().pixels_mut().count());
941 assert_eq!(x*y, img.as_mut().as_ref().pixels().count());
942 }
943 }
944 }
945
946 #[test]
947 fn into_contiguous_buf() {
948 for in_h in [1, 2, 3, 38, 39, 40, 41].iter().copied() {
949 for in_w in [1, 2, 3, 120, 121].iter().copied() {
950 for stride in [in_w, 121, 122, 166, 242, 243].iter().copied() {
951 let img = ImgVec::new_stride((0..10000).map(|x| x as u8).collect(), in_w, in_h, stride)
952 .map_buf(|x| x);
953 let pixels: Vec<_> = img.pixels().collect();
954 let (buf, w, h) = img.into_contiguous_buf();
955 assert_eq!(pixels, buf);
956 assert_eq!(in_w*in_h, buf.len());
957 assert_eq!(10000, buf.capacity());
958 assert_eq!(in_w, w);
959 assert_eq!(in_h, h);
960 }
961 }
962 }
963
964 let img = ImgVec::new((0..55*33).map(|x| x as u8).collect(), 55, 33);
965 let pixels: Vec<_> = img.pixels().collect();
966 let tmp = img.as_ref();
967 let (buf, ..) = tmp.to_contiguous_buf();
968 assert_eq!(&pixels[..], &buf[..]);
969 let (buf, ..) = img.into_contiguous_buf();
970 assert_eq!(pixels, buf);
971 }
972}