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}