image/
flat.rs

1//! Image representations for ffi.
2//!
3//! # Usage
4//!
5//! Imagine you want to offer a very simple ffi interface: The caller provides an image buffer and
6//! your program creates a thumbnail from it and dumps that image as `png`. This module is designed
7//! to help you transition from raw memory data to Rust representation.
8//!
9//! ```no_run
10//! use std::ptr;
11//! use std::slice;
12//! use image::Rgb;
13//! use image::flat::{FlatSamples, SampleLayout};
14//! use image::imageops::thumbnail;
15//!
16//! #[no_mangle]
17//! pub extern "C" fn store_rgb8_compressed(
18//!     data: *const u8, len: usize,
19//!     layout: *const SampleLayout
20//! )
21//!     -> bool
22//! {
23//!     let samples = unsafe { slice::from_raw_parts(data, len) };
24//!     let layout = unsafe { ptr::read(layout) };
25//!
26//!     let buffer = FlatSamples {
27//!         samples,
28//!         layout,
29//!         color_hint: None,
30//!     };
31//!
32//!     let view = match buffer.as_view::<Rgb<u8>>() {
33//!         Err(_) => return false, // Invalid layout.
34//!         Ok(view) => view,
35//!     };
36//!
37//!     thumbnail(&view, 64, 64)
38//!         .save("output.png")
39//!         .map(|_| true)
40//!         .unwrap_or_else(|_| false)
41//! }
42//! ```
43//!
44use std::marker::PhantomData;
45use std::ops::{Deref, Index, IndexMut};
46use std::{cmp, error, fmt};
47
48use num_traits::Zero;
49
50use crate::color::ColorType;
51use crate::error::{
52    DecodingError, ImageError, ImageFormatHint, ParameterError, ParameterErrorKind,
53    UnsupportedError, UnsupportedErrorKind,
54};
55use crate::image::{GenericImage, GenericImageView};
56use crate::traits::Pixel;
57use crate::ImageBuffer;
58
59/// A flat buffer over a (multi channel) image.
60///
61/// In contrast to `ImageBuffer`, this representation of a sample collection is much more lenient
62/// in the layout thereof. It also allows grouping by color planes instead of by pixel as long as
63/// the strides of each extent are constant. This struct itself has no invariants on the strides
64/// but not every possible configuration can be interpreted as a [`GenericImageView`] or
65/// [`GenericImage`]. The methods [`as_view`] and [`as_view_mut`] construct the actual implementors
66/// of these traits and perform necessary checks. To manually perform this and other layout checks
67/// use [`is_normal`] or [`has_aliased_samples`].
68///
69/// Instances can be constructed not only by hand. The buffer instances returned by library
70/// functions such as [`ImageBuffer::as_flat_samples`] guarantee that the conversion to a generic
71/// image or generic view succeeds. A very different constructor is [`with_monocolor`]. It uses a
72/// single pixel as the backing storage for an arbitrarily sized read-only raster by mapping each
73/// pixel to the same samples by setting some strides to `0`.
74///
75/// [`GenericImage`]: ../trait.GenericImage.html
76/// [`GenericImageView`]: ../trait.GenericImageView.html
77/// [`ImageBuffer::as_flat_samples`]: ../struct.ImageBuffer.html#method.as_flat_samples
78/// [`is_normal`]: #method.is_normal
79/// [`has_aliased_samples`]: #method.has_aliased_samples
80/// [`as_view`]: #method.as_view
81/// [`as_view_mut`]: #method.as_view_mut
82/// [`with_monocolor`]: #method.with_monocolor
83#[derive(Clone, Debug)]
84pub struct FlatSamples<Buffer> {
85    /// Underlying linear container holding sample values.
86    pub samples: Buffer,
87
88    /// A `repr(C)` description of the layout of buffer samples.
89    pub layout: SampleLayout,
90
91    /// Supplementary color information.
92    ///
93    /// You may keep this as `None` in most cases. This is NOT checked in `View` or other
94    /// converters. It is intended mainly as a way for types that convert to this buffer type to
95    /// attach their otherwise static color information. A dynamic image representation could
96    /// however use this to resolve representational ambiguities such as the order of RGB channels.
97    pub color_hint: Option<ColorType>,
98}
99
100/// A ffi compatible description of a sample buffer.
101#[repr(C)]
102#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
103pub struct SampleLayout {
104    /// The number of channels in the color representation of the image.
105    pub channels: u8,
106
107    /// Add this to an index to get to the sample in the next channel.
108    pub channel_stride: usize,
109
110    /// The width of the represented image.
111    pub width: u32,
112
113    /// Add this to an index to get to the next sample in x-direction.
114    pub width_stride: usize,
115
116    /// The height of the represented image.
117    pub height: u32,
118
119    /// Add this to an index to get to the next sample in y-direction.
120    pub height_stride: usize,
121}
122
123/// Helper struct for an unnamed (stride, length) pair.
124#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
125struct Dim(usize, usize);
126
127impl SampleLayout {
128    /// Describe a row-major image packed in all directions.
129    ///
130    /// The resulting will surely be `NormalForm::RowMajorPacked`. It can therefore be converted to
131    /// safely to an `ImageBuffer` with a large enough underlying buffer.
132    ///
133    /// ```
134    /// # use image::flat::{NormalForm, SampleLayout};
135    /// let layout = SampleLayout::row_major_packed(3, 640, 480);
136    /// assert!(layout.is_normal(NormalForm::RowMajorPacked));
137    /// ```
138    ///
139    /// # Panics
140    ///
141    /// On platforms where `usize` has the same size as `u32` this panics when the resulting stride
142    /// in the `height` direction would be larger than `usize::max_value()`. On other platforms
143    /// where it can surely accommodate `u8::max_value() * u32::max_value(), this can never happen.
144    pub fn row_major_packed(channels: u8, width: u32, height: u32) -> Self {
145        let height_stride = (channels as usize).checked_mul(width as usize).expect(
146            "Row major packed image can not be described because it does not fit into memory",
147        );
148        SampleLayout {
149            channels,
150            channel_stride: 1,
151            width,
152            width_stride: channels as usize,
153            height,
154            height_stride,
155        }
156    }
157
158    /// Describe a column-major image packed in all directions.
159    ///
160    /// The resulting will surely be `NormalForm::ColumnMajorPacked`. This is not particularly
161    /// useful for conversion but can be used to describe such a buffer without pitfalls.
162    ///
163    /// ```
164    /// # use image::flat::{NormalForm, SampleLayout};
165    /// let layout = SampleLayout::column_major_packed(3, 640, 480);
166    /// assert!(layout.is_normal(NormalForm::ColumnMajorPacked));
167    /// ```
168    ///
169    /// # Panics
170    ///
171    /// On platforms where `usize` has the same size as `u32` this panics when the resulting stride
172    /// in the `width` direction would be larger than `usize::max_value()`. On other platforms
173    /// where it can surely accommodate `u8::max_value() * u32::max_value(), this can never happen.
174    pub fn column_major_packed(channels: u8, width: u32, height: u32) -> Self {
175        let width_stride = (channels as usize).checked_mul(height as usize).expect(
176            "Column major packed image can not be described because it does not fit into memory",
177        );
178        SampleLayout {
179            channels,
180            channel_stride: 1,
181            height,
182            height_stride: channels as usize,
183            width,
184            width_stride,
185        }
186    }
187
188    /// Get the strides for indexing matrix-like `[(c, w, h)]`.
189    ///
190    /// For a row-major layout with grouped samples, this tuple is strictly
191    /// increasing.
192    pub fn strides_cwh(&self) -> (usize, usize, usize) {
193        (self.channel_stride, self.width_stride, self.height_stride)
194    }
195
196    /// Get the dimensions `(channels, width, height)`.
197    ///
198    /// The interface is optimized for use with `strides_cwh` instead. The channel extent will be
199    /// before width and height.
200    pub fn extents(&self) -> (usize, usize, usize) {
201        (
202            self.channels as usize,
203            self.width as usize,
204            self.height as usize,
205        )
206    }
207
208    /// Tuple of bounds in the order of coordinate inputs.
209    ///
210    /// This function should be used whenever working with image coordinates opposed to buffer
211    /// coordinates. The only difference compared to `extents` is the output type.
212    pub fn bounds(&self) -> (u8, u32, u32) {
213        (self.channels, self.width, self.height)
214    }
215
216    /// Get the minimum length of a buffer such that all in-bounds samples have valid indices.
217    ///
218    /// This method will allow zero strides, allowing compact representations of monochrome images.
219    /// To check that no aliasing occurs, try `check_alias_invariants`. For compact images (no
220    /// aliasing and no unindexed samples) this is `width*height*channels`. But for both of the
221    /// other cases, the reasoning is slightly more involved.
222    ///
223    /// # Explanation
224    ///
225    /// Note that there is a difference between `min_length` and the index of the sample
226    /// 'one-past-the-end`. This is due to strides that may be larger than the dimension below.
227    ///
228    /// ## Example with holes
229    ///
230    /// Let's look at an example of a grayscale image with
231    /// * `width_stride = 1`
232    /// * `width = 2`
233    /// * `height_stride = 3`
234    /// * `height = 2`
235    ///
236    /// ```text
237    /// | x x   | x x m | $
238    ///  min_length m ^
239    ///                   ^ one-past-the-end $
240    /// ```
241    ///
242    /// The difference is also extreme for empty images with large strides. The one-past-the-end
243    /// sample index is still as large as the largest of these strides while `min_length = 0`.
244    ///
245    /// ## Example with aliasing
246    ///
247    /// The concept gets even more important when you allow samples to alias each other. Here we
248    /// have the buffer of a small grayscale image where this is the case, this time we will first
249    /// show the buffer and then the individual rows below.
250    ///
251    /// * `width_stride = 1`
252    /// * `width = 3`
253    /// * `height_stride = 2`
254    /// * `height = 2`
255    ///
256    /// ```text
257    ///  1 2 3 4 5 m
258    /// |1 2 3| row one
259    ///     |3 4 5| row two
260    ///            ^ m min_length
261    ///          ^ ??? one-past-the-end
262    /// ```
263    ///
264    /// This time 'one-past-the-end' is not even simply the largest stride times the extent of its
265    /// dimension. That still points inside the image because `height*height_stride = 4` but also
266    /// `index_of(1, 2) = 4`.
267    pub fn min_length(&self) -> Option<usize> {
268        if self.width == 0 || self.height == 0 || self.channels == 0 {
269            return Some(0);
270        }
271
272        self.index(self.channels - 1, self.width - 1, self.height - 1)
273            .and_then(|idx| idx.checked_add(1))
274    }
275
276    /// Check if a buffer of length `len` is large enough.
277    pub fn fits(&self, len: usize) -> bool {
278        self.min_length().map(|min| len >= min).unwrap_or(false)
279    }
280
281    /// The extents of this array, in order of increasing strides.
282    fn increasing_stride_dims(&self) -> [Dim; 3] {
283        // Order extents by strides, then check that each is less equal than the next stride.
284        let mut grouped: [Dim; 3] = [
285            Dim(self.channel_stride, self.channels as usize),
286            Dim(self.width_stride, self.width as usize),
287            Dim(self.height_stride, self.height as usize),
288        ];
289
290        grouped.sort();
291
292        let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]);
293        assert!(min_dim.stride() <= mid_dim.stride() && mid_dim.stride() <= max_dim.stride());
294
295        grouped
296    }
297
298    /// If there are any samples aliasing each other.
299    ///
300    /// If this is not the case, it would always be safe to allow mutable access to two different
301    /// samples at the same time. Otherwise, this operation would need additional checks. When one
302    /// dimension overflows `usize` with its stride we also consider this aliasing.
303    pub fn has_aliased_samples(&self) -> bool {
304        let grouped = self.increasing_stride_dims();
305        let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]);
306
307        let min_size = match min_dim.checked_len() {
308            None => return true,
309            Some(size) => size,
310        };
311
312        let mid_size = match mid_dim.checked_len() {
313            None => return true,
314            Some(size) => size,
315        };
316
317        match max_dim.checked_len() {
318            None => return true,
319            Some(_) => (), // Only want to know this didn't overflow.
320        };
321
322        // Each higher dimension must walk over all of one lower dimension.
323        min_size > mid_dim.stride() || mid_size > max_dim.stride()
324    }
325
326    /// Check if a buffer fulfills the requirements of a normal form.
327    ///
328    /// Certain conversions have preconditions on the structure of the sample buffer that are not
329    /// captured (by design) by the type system. These are then checked before the conversion. Such
330    /// checks can all be done in constant time and will not inspect the buffer content. You can
331    /// perform these checks yourself when the conversion is not required at this moment but maybe
332    /// still performed later.
333    pub fn is_normal(&self, form: NormalForm) -> bool {
334        if self.has_aliased_samples() {
335            return false;
336        }
337
338        if form >= NormalForm::PixelPacked && self.channel_stride != 1 {
339            return false;
340        }
341
342        if form >= NormalForm::ImagePacked {
343            // has aliased already checked for overflows.
344            let grouped = self.increasing_stride_dims();
345            let (min_dim, mid_dim, max_dim) = (grouped[0], grouped[1], grouped[2]);
346
347            if 1 != min_dim.stride() {
348                return false;
349            }
350
351            if min_dim.len() != mid_dim.stride() {
352                return false;
353            }
354
355            if mid_dim.len() != max_dim.stride() {
356                return false;
357            }
358        }
359
360        if form >= NormalForm::RowMajorPacked {
361            if self.width_stride != self.channels as usize {
362                return false;
363            }
364
365            if self.width as usize * self.width_stride != self.height_stride {
366                return false;
367            }
368        }
369
370        if form >= NormalForm::ColumnMajorPacked {
371            if self.height_stride != self.channels as usize {
372                return false;
373            }
374
375            if self.height as usize * self.height_stride != self.width_stride {
376                return false;
377            }
378        }
379
380        true
381    }
382
383    /// Check that the pixel and the channel index are in bounds.
384    ///
385    /// An in-bound coordinate does not yet guarantee that the corresponding calculation of a
386    /// buffer index does not overflow. However, if such a buffer large enough to hold all samples
387    /// actually exists in memory, this property of course follows.
388    pub fn in_bounds(&self, channel: u8, x: u32, y: u32) -> bool {
389        channel < self.channels && x < self.width && y < self.height
390    }
391
392    /// Resolve the index of a particular sample.
393    ///
394    /// `None` if the index is outside the bounds or does not fit into a `usize`.
395    pub fn index(&self, channel: u8, x: u32, y: u32) -> Option<usize> {
396        if !self.in_bounds(channel, x, y) {
397            return None;
398        }
399
400        self.index_ignoring_bounds(channel as usize, x as usize, y as usize)
401    }
402
403    /// Get the theoretical position of sample (channel, x, y).
404    ///
405    /// The 'check' is for overflow during index calculation, not that it is contained in the
406    /// image. Two samples may return the same index, even when one of them is out of bounds. This
407    /// happens when all strides are `0`, i.e. the image is an arbitrarily large monochrome image.
408    pub fn index_ignoring_bounds(&self, channel: usize, x: usize, y: usize) -> Option<usize> {
409        let idx_c = channel.checked_mul(self.channel_stride);
410        let idx_x = x.checked_mul(self.width_stride);
411        let idx_y = y.checked_mul(self.height_stride);
412
413        let (idx_c, idx_x, idx_y) = match (idx_c, idx_x, idx_y) {
414            (Some(idx_c), Some(idx_x), Some(idx_y)) => (idx_c, idx_x, idx_y),
415            _ => return None,
416        };
417
418        Some(0usize)
419            .and_then(|b| b.checked_add(idx_c))
420            .and_then(|b| b.checked_add(idx_x))
421            .and_then(|b| b.checked_add(idx_y))
422    }
423
424    /// Get an index provided it is inbouds.
425    ///
426    /// Assumes that the image is backed by some sufficiently large buffer. Then computation can
427    /// not overflow as we could represent the maximum coordinate. Since overflow is defined either
428    /// way, this method can not be unsafe.
429    ///
430    /// Behavior is *unspecified* if the index is out of bounds or this sample layout would require
431    /// a buffer larger than `isize::MAX` bytes.
432    pub fn in_bounds_index(&self, c: u8, x: u32, y: u32) -> usize {
433        let (c_stride, x_stride, y_stride) = self.strides_cwh();
434        (y as usize * y_stride) + (x as usize * x_stride) + (c as usize * c_stride)
435    }
436
437    /// Shrink the image to the minimum of current and given extents.
438    ///
439    /// This does not modify the strides, so that the resulting sample buffer may have holes
440    /// created by the shrinking operation. Shrinking could also lead to an non-aliasing image when
441    /// samples had aliased each other before.
442    pub fn shrink_to(&mut self, channels: u8, width: u32, height: u32) {
443        self.channels = self.channels.min(channels);
444        self.width = self.width.min(width);
445        self.height = self.height.min(height);
446    }
447}
448
449impl Dim {
450    fn stride(self) -> usize {
451        self.0
452    }
453
454    /// Length of this dimension in memory.
455    fn checked_len(self) -> Option<usize> {
456        self.0.checked_mul(self.1)
457    }
458
459    fn len(self) -> usize {
460        self.0 * self.1
461    }
462}
463
464impl<Buffer> FlatSamples<Buffer> {
465    /// Get the strides for indexing matrix-like `[(c, w, h)]`.
466    ///
467    /// For a row-major layout with grouped samples, this tuple is strictly
468    /// increasing.
469    pub fn strides_cwh(&self) -> (usize, usize, usize) {
470        self.layout.strides_cwh()
471    }
472
473    /// Get the dimensions `(channels, width, height)`.
474    ///
475    /// The interface is optimized for use with `strides_cwh` instead. The channel extent will be
476    /// before width and height.
477    pub fn extents(&self) -> (usize, usize, usize) {
478        self.layout.extents()
479    }
480
481    /// Tuple of bounds in the order of coordinate inputs.
482    ///
483    /// This function should be used whenever working with image coordinates opposed to buffer
484    /// coordinates. The only difference compared to `extents` is the output type.
485    pub fn bounds(&self) -> (u8, u32, u32) {
486        self.layout.bounds()
487    }
488
489    /// Get a reference based version.
490    pub fn as_ref<T>(&self) -> FlatSamples<&[T]>
491    where
492        Buffer: AsRef<[T]>,
493    {
494        FlatSamples {
495            samples: self.samples.as_ref(),
496            layout: self.layout,
497            color_hint: self.color_hint,
498        }
499    }
500
501    /// Get a mutable reference based version.
502    pub fn as_mut<T>(&mut self) -> FlatSamples<&mut [T]>
503    where
504        Buffer: AsMut<[T]>,
505    {
506        FlatSamples {
507            samples: self.samples.as_mut(),
508            layout: self.layout,
509            color_hint: self.color_hint,
510        }
511    }
512
513    /// Copy the data into an owned vector.
514    pub fn to_vec<T>(&self) -> FlatSamples<Vec<T>>
515    where
516        T: Clone,
517        Buffer: AsRef<[T]>,
518    {
519        FlatSamples {
520            samples: self.samples.as_ref().to_vec(),
521            layout: self.layout,
522            color_hint: self.color_hint,
523        }
524    }
525
526    /// Get a reference to a single sample.
527    ///
528    /// This more restrictive than the method based on `std::ops::Index` but guarantees to properly
529    /// check all bounds and not panic as long as `Buffer::as_ref` does not do so.
530    ///
531    /// ```
532    /// # use image::{RgbImage};
533    /// let flat = RgbImage::new(480, 640).into_flat_samples();
534    ///
535    /// // Get the blue channel at (10, 10).
536    /// assert!(flat.get_sample(1, 10, 10).is_some());
537    ///
538    /// // There is no alpha channel.
539    /// assert!(flat.get_sample(3, 10, 10).is_none());
540    /// ```
541    ///
542    /// For cases where a special buffer does not provide `AsRef<[T]>`, consider encapsulating
543    /// bounds checks with `min_length` in a type similar to `View`. Then you may use
544    /// `in_bounds_index` as a small speedup over the index calculation of this method which relies
545    /// on `index_ignoring_bounds` since it can not have a-priori knowledge that the sample
546    /// coordinate is in fact backed by any memory buffer.
547    pub fn get_sample<T>(&self, channel: u8, x: u32, y: u32) -> Option<&T>
548    where
549        Buffer: AsRef<[T]>,
550    {
551        self.index(channel, x, y)
552            .and_then(|idx| self.samples.as_ref().get(idx))
553    }
554
555    /// Get a mutable reference to a single sample.
556    ///
557    /// This more restrictive than the method based on `std::ops::IndexMut` but guarantees to
558    /// properly check all bounds and not panic as long as `Buffer::as_ref` does not do so.
559    /// Contrary to conversion to `ViewMut`, this does not require that samples are packed since it
560    /// does not need to convert samples to a color representation.
561    ///
562    /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned
563    /// here can in fact modify more than the coordinate in the argument.
564    ///
565    /// ```
566    /// # use image::{RgbImage};
567    /// let mut flat = RgbImage::new(480, 640).into_flat_samples();
568    ///
569    /// // Assign some new color to the blue channel at (10, 10).
570    /// *flat.get_mut_sample(1, 10, 10).unwrap() = 255;
571    ///
572    /// // There is no alpha channel.
573    /// assert!(flat.get_mut_sample(3, 10, 10).is_none());
574    /// ```
575    ///
576    /// For cases where a special buffer does not provide `AsRef<[T]>`, consider encapsulating
577    /// bounds checks with `min_length` in a type similar to `View`. Then you may use
578    /// `in_bounds_index` as a small speedup over the index calculation of this method which relies
579    /// on `index_ignoring_bounds` since it can not have a-priori knowledge that the sample
580    /// coordinate is in fact backed by any memory buffer.
581    pub fn get_mut_sample<T>(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut T>
582    where
583        Buffer: AsMut<[T]>,
584    {
585        match self.index(channel, x, y) {
586            None => None,
587            Some(idx) => self.samples.as_mut().get_mut(idx),
588        }
589    }
590
591    /// View this buffer as an image over some type of pixel.
592    ///
593    /// This first ensures that all in-bounds coordinates refer to valid indices in the sample
594    /// buffer. It also checks that the specified pixel format expects the same number of channels
595    /// that are present in this buffer. Neither are larger nor a smaller number will be accepted.
596    /// There is no automatic conversion.
597    pub fn as_view<P>(&self) -> Result<View<&[P::Subpixel], P>, Error>
598    where
599        P: Pixel,
600        Buffer: AsRef<[P::Subpixel]>,
601    {
602        if self.layout.channels != P::CHANNEL_COUNT {
603            return Err(Error::ChannelCountMismatch(
604                self.layout.channels,
605                P::CHANNEL_COUNT,
606            ));
607        }
608
609        let as_ref = self.samples.as_ref();
610        if !self.layout.fits(as_ref.len()) {
611            return Err(Error::TooLarge);
612        }
613
614        Ok(View {
615            inner: FlatSamples {
616                samples: as_ref,
617                layout: self.layout,
618                color_hint: self.color_hint,
619            },
620            phantom: PhantomData,
621        })
622    }
623
624    /// View this buffer but keep mutability at a sample level.
625    ///
626    /// This is similar to `as_view` but subtly different from `as_view_mut`. The resulting type
627    /// can be used as a `GenericImage` with the same prior invariants needed as for `as_view`.
628    /// It can not be used as a mutable `GenericImage` but does not need channels to be packed in
629    /// their pixel representation.
630    ///
631    /// This first ensures that all in-bounds coordinates refer to valid indices in the sample
632    /// buffer. It also checks that the specified pixel format expects the same number of channels
633    /// that are present in this buffer. Neither are larger nor a smaller number will be accepted.
634    /// There is no automatic conversion.
635    ///
636    /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned
637    /// for one sample can in fact modify other samples as well. Sometimes exactly this is
638    /// intended.
639    pub fn as_view_with_mut_samples<P>(&mut self) -> Result<View<&mut [P::Subpixel], P>, Error>
640    where
641        P: Pixel,
642        Buffer: AsMut<[P::Subpixel]>,
643    {
644        if self.layout.channels != P::CHANNEL_COUNT {
645            return Err(Error::ChannelCountMismatch(
646                self.layout.channels,
647                P::CHANNEL_COUNT,
648            ));
649        }
650
651        let as_mut = self.samples.as_mut();
652        if !self.layout.fits(as_mut.len()) {
653            return Err(Error::TooLarge);
654        }
655
656        Ok(View {
657            inner: FlatSamples {
658                samples: as_mut,
659                layout: self.layout,
660                color_hint: self.color_hint,
661            },
662            phantom: PhantomData,
663        })
664    }
665
666    /// Interpret this buffer as a mutable image.
667    ///
668    /// To succeed, the pixels in this buffer may not alias each other and the samples of each
669    /// pixel must be packed (i.e. `channel_stride` is `1`). The number of channels must be
670    /// consistent with the channel count expected by the pixel format.
671    ///
672    /// This is similar to an `ImageBuffer` except it is a temporary view that is not normalized as
673    /// strongly. To get an owning version, consider copying the data into an `ImageBuffer`. This
674    /// provides many more operations, is possibly faster (if not you may want to open an issue) is
675    /// generally polished. You can also try to convert this buffer inline, see
676    /// `ImageBuffer::from_raw`.
677    pub fn as_view_mut<P>(&mut self) -> Result<ViewMut<&mut [P::Subpixel], P>, Error>
678    where
679        P: Pixel,
680        Buffer: AsMut<[P::Subpixel]>,
681    {
682        if !self.layout.is_normal(NormalForm::PixelPacked) {
683            return Err(Error::NormalFormRequired(NormalForm::PixelPacked));
684        }
685
686        if self.layout.channels != P::CHANNEL_COUNT {
687            return Err(Error::ChannelCountMismatch(
688                self.layout.channels,
689                P::CHANNEL_COUNT,
690            ));
691        }
692
693        let as_mut = self.samples.as_mut();
694        if !self.layout.fits(as_mut.len()) {
695            return Err(Error::TooLarge);
696        }
697
698        Ok(ViewMut {
699            inner: FlatSamples {
700                samples: as_mut,
701                layout: self.layout,
702                color_hint: self.color_hint,
703            },
704            phantom: PhantomData,
705        })
706    }
707
708    /// View the samples as a slice.
709    ///
710    /// The slice is not limited to the region of the image and not all sample indices are valid
711    /// indices into this buffer. See `image_mut_slice` as an alternative.
712    pub fn as_slice<T>(&self) -> &[T]
713    where
714        Buffer: AsRef<[T]>,
715    {
716        self.samples.as_ref()
717    }
718
719    /// View the samples as a slice.
720    ///
721    /// The slice is not limited to the region of the image and not all sample indices are valid
722    /// indices into this buffer. See `image_mut_slice` as an alternative.
723    pub fn as_mut_slice<T>(&mut self) -> &mut [T]
724    where
725        Buffer: AsMut<[T]>,
726    {
727        self.samples.as_mut()
728    }
729
730    /// Return the portion of the buffer that holds sample values.
731    ///
732    /// This may fail when the coordinates in this image are either out-of-bounds of the underlying
733    /// buffer or can not be represented. Note that the slice may have holes that do not correspond
734    /// to any sample in the image represented by it.
735    pub fn image_slice<T>(&self) -> Option<&[T]>
736    where
737        Buffer: AsRef<[T]>,
738    {
739        let min_length = match self.min_length() {
740            None => return None,
741            Some(index) => index,
742        };
743
744        let slice = self.samples.as_ref();
745        if slice.len() < min_length {
746            return None;
747        }
748
749        Some(&slice[..min_length])
750    }
751
752    /// Mutable portion of the buffer that holds sample values.
753    pub fn image_mut_slice<T>(&mut self) -> Option<&mut [T]>
754    where
755        Buffer: AsMut<[T]>,
756    {
757        let min_length = match self.min_length() {
758            None => return None,
759            Some(index) => index,
760        };
761
762        let slice = self.samples.as_mut();
763        if slice.len() < min_length {
764            return None;
765        }
766
767        Some(&mut slice[..min_length])
768    }
769
770    /// Move the data into an image buffer.
771    ///
772    /// This does **not** convert the sample layout. The buffer needs to be in packed row-major form
773    /// before calling this function. In case of an error, returns the buffer again so that it does
774    /// not release any allocation.
775    pub fn try_into_buffer<P>(self) -> Result<ImageBuffer<P, Buffer>, (Error, Self)>
776    where
777        P: Pixel + 'static,
778        P::Subpixel: 'static,
779        Buffer: Deref<Target = [P::Subpixel]>,
780    {
781        if !self.is_normal(NormalForm::RowMajorPacked) {
782            return Err((Error::NormalFormRequired(NormalForm::RowMajorPacked), self));
783        }
784
785        if self.layout.channels != P::CHANNEL_COUNT {
786            return Err((
787                Error::ChannelCountMismatch(self.layout.channels, P::CHANNEL_COUNT),
788                self,
789            ));
790        }
791
792        if !self.fits(self.samples.deref().len()) {
793            return Err((Error::TooLarge, self));
794        }
795
796        Ok(
797            ImageBuffer::from_raw(self.layout.width, self.layout.height, self.samples)
798                .unwrap_or_else(|| {
799                    panic!("Preconditions should have been ensured before conversion")
800                }),
801        )
802    }
803
804    /// Get the minimum length of a buffer such that all in-bounds samples have valid indices.
805    ///
806    /// This method will allow zero strides, allowing compact representations of monochrome images.
807    /// To check that no aliasing occurs, try `check_alias_invariants`. For compact images (no
808    /// aliasing and no unindexed samples) this is `width*height*channels`. But for both of the
809    /// other cases, the reasoning is slightly more involved.
810    ///
811    /// # Explanation
812    ///
813    /// Note that there is a difference between `min_length` and the index of the sample
814    /// 'one-past-the-end`. This is due to strides that may be larger than the dimension below.
815    ///
816    /// ## Example with holes
817    ///
818    /// Let's look at an example of a grayscale image with
819    /// * `width_stride = 1`
820    /// * `width = 2`
821    /// * `height_stride = 3`
822    /// * `height = 2`
823    ///
824    /// ```text
825    /// | x x   | x x m | $
826    ///  min_length m ^
827    ///                   ^ one-past-the-end $
828    /// ```
829    ///
830    /// The difference is also extreme for empty images with large strides. The one-past-the-end
831    /// sample index is still as large as the largest of these strides while `min_length = 0`.
832    ///
833    /// ## Example with aliasing
834    ///
835    /// The concept gets even more important when you allow samples to alias each other. Here we
836    /// have the buffer of a small grayscale image where this is the case, this time we will first
837    /// show the buffer and then the individual rows below.
838    ///
839    /// * `width_stride = 1`
840    /// * `width = 3`
841    /// * `height_stride = 2`
842    /// * `height = 2`
843    ///
844    /// ```text
845    ///  1 2 3 4 5 m
846    /// |1 2 3| row one
847    ///     |3 4 5| row two
848    ///            ^ m min_length
849    ///          ^ ??? one-past-the-end
850    /// ```
851    ///
852    /// This time 'one-past-the-end' is not even simply the largest stride times the extent of its
853    /// dimension. That still points inside the image because `height*height_stride = 4` but also
854    /// `index_of(1, 2) = 4`.
855    pub fn min_length(&self) -> Option<usize> {
856        self.layout.min_length()
857    }
858
859    /// Check if a buffer of length `len` is large enough.
860    pub fn fits(&self, len: usize) -> bool {
861        self.layout.fits(len)
862    }
863
864    /// If there are any samples aliasing each other.
865    ///
866    /// If this is not the case, it would always be safe to allow mutable access to two different
867    /// samples at the same time. Otherwise, this operation would need additional checks. When one
868    /// dimension overflows `usize` with its stride we also consider this aliasing.
869    pub fn has_aliased_samples(&self) -> bool {
870        self.layout.has_aliased_samples()
871    }
872
873    /// Check if a buffer fulfills the requirements of a normal form.
874    ///
875    /// Certain conversions have preconditions on the structure of the sample buffer that are not
876    /// captured (by design) by the type system. These are then checked before the conversion. Such
877    /// checks can all be done in constant time and will not inspect the buffer content. You can
878    /// perform these checks yourself when the conversion is not required at this moment but maybe
879    /// still performed later.
880    pub fn is_normal(&self, form: NormalForm) -> bool {
881        self.layout.is_normal(form)
882    }
883
884    /// Check that the pixel and the channel index are in bounds.
885    ///
886    /// An in-bound coordinate does not yet guarantee that the corresponding calculation of a
887    /// buffer index does not overflow. However, if such a buffer large enough to hold all samples
888    /// actually exists in memory, this property of course follows.
889    pub fn in_bounds(&self, channel: u8, x: u32, y: u32) -> bool {
890        self.layout.in_bounds(channel, x, y)
891    }
892
893    /// Resolve the index of a particular sample.
894    ///
895    /// `None` if the index is outside the bounds or does not fit into a `usize`.
896    pub fn index(&self, channel: u8, x: u32, y: u32) -> Option<usize> {
897        self.layout.index(channel, x, y)
898    }
899
900    /// Get the theoretical position of sample (x, y, channel).
901    ///
902    /// The 'check' is for overflow during index calculation, not that it is contained in the
903    /// image. Two samples may return the same index, even when one of them is out of bounds. This
904    /// happens when all strides are `0`, i.e. the image is an arbitrarily large monochrome image.
905    pub fn index_ignoring_bounds(&self, channel: usize, x: usize, y: usize) -> Option<usize> {
906        self.layout.index_ignoring_bounds(channel, x, y)
907    }
908
909    /// Get an index provided it is inbouds.
910    ///
911    /// Assumes that the image is backed by some sufficiently large buffer. Then computation can
912    /// not overflow as we could represent the maximum coordinate. Since overflow is defined either
913    /// way, this method can not be unsafe.
914    pub fn in_bounds_index(&self, channel: u8, x: u32, y: u32) -> usize {
915        self.layout.in_bounds_index(channel, x, y)
916    }
917
918    /// Shrink the image to the minimum of current and given extents.
919    ///
920    /// This does not modify the strides, so that the resulting sample buffer may have holes
921    /// created by the shrinking operation. Shrinking could also lead to an non-aliasing image when
922    /// samples had aliased each other before.
923    pub fn shrink_to(&mut self, channels: u8, width: u32, height: u32) {
924        self.layout.shrink_to(channels, width, height)
925    }
926}
927
928impl<'buf, Subpixel> FlatSamples<&'buf [Subpixel]> {
929    /// Create a monocolor image from a single pixel.
930    ///
931    /// This can be used as a very cheap source of a `GenericImageView` with an arbitrary number of
932    /// pixels of a single color, without any dynamic allocation.
933    ///
934    /// ## Examples
935    ///
936    /// ```
937    /// # fn paint_something<T>(_: T) {}
938    /// use image::{flat::FlatSamples, GenericImage, RgbImage, Rgb};
939    ///
940    /// let background = Rgb([20, 20, 20]);
941    /// let bg = FlatSamples::with_monocolor(&background, 200, 200);;
942    ///
943    /// let mut image = RgbImage::new(200, 200);
944    /// paint_something(&mut image);
945    ///
946    /// // Reset the canvas
947    /// image.copy_from(&bg.as_view().unwrap(), 0, 0);
948    /// ```
949    pub fn with_monocolor<P>(pixel: &'buf P, width: u32, height: u32) -> Self
950    where
951        P: Pixel<Subpixel = Subpixel>,
952        Subpixel: crate::Primitive,
953    {
954        FlatSamples {
955            samples: pixel.channels(),
956            layout: SampleLayout {
957                channels: P::CHANNEL_COUNT,
958                channel_stride: 1,
959                width,
960                width_stride: 0,
961                height,
962                height_stride: 0,
963            },
964
965            // TODO this value is never set. It should be set in all places where the Pixel type implements PixelWithColorType
966            color_hint: None,
967        }
968    }
969}
970
971/// A flat buffer that can be used as an image view.
972///
973/// This is a nearly trivial wrapper around a buffer but at least sanitizes by checking the buffer
974/// length first and constraining the pixel type.
975///
976/// Note that this does not eliminate panics as the `AsRef<[T]>` implementation of `Buffer` may be
977/// unreliable, i.e. return different buffers at different times. This of course is a non-issue for
978/// all common collections where the bounds check once must be enough.
979///
980/// # Inner invariants
981///
982/// * For all indices inside bounds, the corresponding index is valid in the buffer
983/// * `P::channel_count()` agrees with `self.inner.layout.channels`
984///
985#[derive(Clone, Debug)]
986pub struct View<Buffer, P: Pixel>
987where
988    Buffer: AsRef<[P::Subpixel]>,
989{
990    inner: FlatSamples<Buffer>,
991    phantom: PhantomData<P>,
992}
993
994/// A mutable owning version of a flat buffer.
995///
996/// While this wraps a buffer similar to `ImageBuffer`, this is mostly intended as a utility. The
997/// library endorsed normalized representation is still `ImageBuffer`. Also, the implementation of
998/// `AsMut<[P::Subpixel]>` must always yield the same buffer. Therefore there is no public way to
999/// construct this with an owning buffer.
1000///
1001/// # Inner invariants
1002///
1003/// * For all indices inside bounds, the corresponding index is valid in the buffer
1004/// * There is no aliasing of samples
1005/// * The samples are packed, i.e. `self.inner.layout.sample_stride == 1`
1006/// * `P::channel_count()` agrees with `self.inner.layout.channels`
1007///
1008#[derive(Clone, Debug)]
1009pub struct ViewMut<Buffer, P: Pixel>
1010where
1011    Buffer: AsMut<[P::Subpixel]>,
1012{
1013    inner: FlatSamples<Buffer>,
1014    phantom: PhantomData<P>,
1015}
1016
1017/// Denotes invalid flat sample buffers when trying to convert to stricter types.
1018///
1019/// The biggest use case being `ImageBuffer` which expects closely packed
1020/// samples in a row major matrix representation. But this error type may be
1021/// resused for other import functions. A more versatile user may also try to
1022/// correct the underlying representation depending on the error variant.
1023#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1024pub enum Error {
1025    /// The represented image was too large.
1026    ///
1027    /// The optional value denotes a possibly accepted maximal bound.
1028    TooLarge,
1029
1030    /// The represented image can not use this representation.
1031    ///
1032    /// Has an additional value of the normalized form that would be accepted.
1033    NormalFormRequired(NormalForm),
1034
1035    /// The color format did not match the channel count.
1036    ///
1037    /// In some cases you might be able to fix this by lowering the reported pixel count of the
1038    /// buffer without touching the strides.
1039    ///
1040    /// In very special circumstances you *may* do the opposite. This is **VERY** dangerous but not
1041    /// directly memory unsafe although that will likely alias pixels. One scenario is when you
1042    /// want to construct an `Rgba` image but have only 3 bytes per pixel and for some reason don't
1043    /// care about the value of the alpha channel even though you need `Rgba`.
1044    ChannelCountMismatch(u8, u8),
1045
1046    /// Deprecated - ChannelCountMismatch is used instead
1047    WrongColor(ColorType),
1048}
1049
1050/// Different normal forms of buffers.
1051///
1052/// A normal form is an unaliased buffer with some additional constraints.  The `ÌmageBuffer` uses
1053/// row major form with packed samples.
1054#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1055pub enum NormalForm {
1056    /// No pixel aliases another.
1057    ///
1058    /// Unaliased also guarantees that all index calculations in the image bounds using
1059    /// `dim_index*dim_stride` (such as `x*width_stride + y*height_stride`) do not overflow.
1060    Unaliased,
1061
1062    /// At least pixels are packed.
1063    ///
1064    /// Images of these types can wrap `[T]`-slices into the standard color types. This is a
1065    /// precondition for `GenericImage` which requires by-reference access to pixels.
1066    PixelPacked,
1067
1068    /// All samples are packed.
1069    ///
1070    /// This is orthogonal to `PixelPacked`. It requires that there are no holes in the image but
1071    /// it is not necessary that the pixel samples themselves are adjacent. An example of this
1072    /// behaviour is a planar image layout.
1073    ImagePacked,
1074
1075    /// The samples are in row-major form and all samples are packed.
1076    ///
1077    /// In addition to `PixelPacked` and `ImagePacked` this also asserts that the pixel matrix is
1078    /// in row-major form.
1079    RowMajorPacked,
1080
1081    /// The samples are in column-major form and all samples are packed.
1082    ///
1083    /// In addition to `PixelPacked` and `ImagePacked` this also asserts that the pixel matrix is
1084    /// in column-major form.
1085    ColumnMajorPacked,
1086}
1087
1088impl<Buffer, P: Pixel> View<Buffer, P>
1089where
1090    Buffer: AsRef<[P::Subpixel]>,
1091{
1092    /// Take out the sample buffer.
1093    ///
1094    /// Gives up the normalization invariants on the buffer format.
1095    pub fn into_inner(self) -> FlatSamples<Buffer> {
1096        self.inner
1097    }
1098
1099    /// Get a reference on the inner sample descriptor.
1100    ///
1101    /// There is no mutable counterpart as modifying the buffer format, including strides and
1102    /// lengths, could invalidate the accessibility invariants of the `View`. It is not specified
1103    /// if the inner buffer is the same as the buffer of the image from which this view was
1104    /// created. It might have been truncated as an optimization.
1105    pub fn flat(&self) -> &FlatSamples<Buffer> {
1106        &self.inner
1107    }
1108
1109    /// Get a reference on the inner buffer.
1110    ///
1111    /// There is no mutable counter part since it is not intended to allow you to reassign the
1112    /// buffer or otherwise change its size or properties.
1113    pub fn samples(&self) -> &Buffer {
1114        &self.inner.samples
1115    }
1116
1117    /// Get a reference to a selected subpixel if it is in-bounds.
1118    ///
1119    /// This method will return `None` when the sample is out-of-bounds. All errors that could
1120    /// occur due to overflow have been eliminated while construction the `View`.
1121    pub fn get_sample(&self, channel: u8, x: u32, y: u32) -> Option<&P::Subpixel> {
1122        if !self.inner.in_bounds(channel, x, y) {
1123            return None;
1124        }
1125
1126        let index = self.inner.in_bounds_index(channel, x, y);
1127        // Should always be `Some(_)` but checking is more costly.
1128        self.samples().as_ref().get(index)
1129    }
1130
1131    /// Get a mutable reference to a selected subpixel if it is in-bounds.
1132    ///
1133    /// This is relevant only when constructed with `FlatSamples::as_view_with_mut_samples`.  This
1134    /// method will return `None` when the sample is out-of-bounds. All errors that could occur due
1135    /// to overflow have been eliminated while construction the `View`.
1136    ///
1137    /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned
1138    /// here can in fact modify more than the coordinate in the argument.
1139    pub fn get_mut_sample(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut P::Subpixel>
1140    where
1141        Buffer: AsMut<[P::Subpixel]>,
1142    {
1143        if !self.inner.in_bounds(channel, x, y) {
1144            return None;
1145        }
1146
1147        let index = self.inner.in_bounds_index(channel, x, y);
1148        // Should always be `Some(_)` but checking is more costly.
1149        self.inner.samples.as_mut().get_mut(index)
1150    }
1151
1152    /// Get the minimum length of a buffer such that all in-bounds samples have valid indices.
1153    ///
1154    /// See `FlatSamples::min_length`. This method will always succeed.
1155    pub fn min_length(&self) -> usize {
1156        self.inner.min_length().unwrap()
1157    }
1158
1159    /// Return the portion of the buffer that holds sample values.
1160    ///
1161    /// While this can not fail–the validity of all coordinates has been validated during the
1162    /// conversion from `FlatSamples`–the resulting slice may still contain holes.
1163    pub fn image_slice(&self) -> &[P::Subpixel] {
1164        &self.samples().as_ref()[..self.min_length()]
1165    }
1166
1167    /// Return the mutable portion of the buffer that holds sample values.
1168    ///
1169    /// This is relevant only when constructed with `FlatSamples::as_view_with_mut_samples`. While
1170    /// this can not fail–the validity of all coordinates has been validated during the conversion
1171    /// from `FlatSamples`–the resulting slice may still contain holes.
1172    pub fn image_mut_slice(&mut self) -> &mut [P::Subpixel]
1173    where
1174        Buffer: AsMut<[P::Subpixel]>,
1175    {
1176        let min_length = self.min_length();
1177        &mut self.inner.samples.as_mut()[..min_length]
1178    }
1179
1180    /// Shrink the inner image.
1181    ///
1182    /// The new dimensions will be the minimum of the previous dimensions. Since the set of
1183    /// in-bounds pixels afterwards is a subset of the current ones, this is allowed on a `View`.
1184    /// Note that you can not change the number of channels as an intrinsic property of `P`.
1185    pub fn shrink_to(&mut self, width: u32, height: u32) {
1186        let channels = self.inner.layout.channels;
1187        self.inner.shrink_to(channels, width, height)
1188    }
1189
1190    /// Try to convert this into an image with mutable pixels.
1191    ///
1192    /// The resulting image implements `GenericImage` in addition to `GenericImageView`. While this
1193    /// has mutable samples, it does not enforce that pixel can not alias and that samples are
1194    /// packed enough for a mutable pixel reference. This is slightly cheaper than the chain
1195    /// `self.into_inner().as_view_mut()` and keeps the `View` alive on failure.
1196    ///
1197    /// ```
1198    /// # use image::RgbImage;
1199    /// # use image::Rgb;
1200    /// let mut buffer = RgbImage::new(480, 640).into_flat_samples();
1201    /// let view = buffer.as_view_with_mut_samples::<Rgb<u8>>().unwrap();
1202    ///
1203    /// // Inspect some pixels, …
1204    ///
1205    /// // Doesn't fail because it was originally an `RgbImage`.
1206    /// let view_mut = view.try_upgrade().unwrap();
1207    /// ```
1208    pub fn try_upgrade(self) -> Result<ViewMut<Buffer, P>, (Error, Self)>
1209    where
1210        Buffer: AsMut<[P::Subpixel]>,
1211    {
1212        if !self.inner.is_normal(NormalForm::PixelPacked) {
1213            return Err((Error::NormalFormRequired(NormalForm::PixelPacked), self));
1214        }
1215
1216        // No length check or channel count check required, all the same.
1217        Ok(ViewMut {
1218            inner: self.inner,
1219            phantom: PhantomData,
1220        })
1221    }
1222}
1223
1224impl<Buffer, P: Pixel> ViewMut<Buffer, P>
1225where
1226    Buffer: AsMut<[P::Subpixel]>,
1227{
1228    /// Take out the sample buffer.
1229    ///
1230    /// Gives up the normalization invariants on the buffer format.
1231    pub fn into_inner(self) -> FlatSamples<Buffer> {
1232        self.inner
1233    }
1234
1235    /// Get a reference on the sample buffer descriptor.
1236    ///
1237    /// There is no mutable counterpart as modifying the buffer format, including strides and
1238    /// lengths, could invalidate the accessibility invariants of the `View`. It is not specified
1239    /// if the inner buffer is the same as the buffer of the image from which this view was
1240    /// created. It might have been truncated as an optimization.
1241    pub fn flat(&self) -> &FlatSamples<Buffer> {
1242        &self.inner
1243    }
1244
1245    /// Get a reference on the inner buffer.
1246    ///
1247    /// There is no mutable counter part since it is not intended to allow you to reassign the
1248    /// buffer or otherwise change its size or properties. However, its contents can be accessed
1249    /// mutable through a slice with `image_mut_slice`.
1250    pub fn samples(&self) -> &Buffer {
1251        &self.inner.samples
1252    }
1253
1254    /// Get the minimum length of a buffer such that all in-bounds samples have valid indices.
1255    ///
1256    /// See `FlatSamples::min_length`. This method will always succeed.
1257    pub fn min_length(&self) -> usize {
1258        self.inner.min_length().unwrap()
1259    }
1260
1261    /// Get a reference to a selected subpixel.
1262    ///
1263    /// This method will return `None` when the sample is out-of-bounds. All errors that could
1264    /// occur due to overflow have been eliminated while construction the `View`.
1265    pub fn get_sample(&self, channel: u8, x: u32, y: u32) -> Option<&P::Subpixel>
1266    where
1267        Buffer: AsRef<[P::Subpixel]>,
1268    {
1269        if !self.inner.in_bounds(channel, x, y) {
1270            return None;
1271        }
1272
1273        let index = self.inner.in_bounds_index(channel, x, y);
1274        // Should always be `Some(_)` but checking is more costly.
1275        self.samples().as_ref().get(index)
1276    }
1277
1278    /// Get a mutable reference to a selected sample.
1279    ///
1280    /// This method will return `None` when the sample is out-of-bounds. All errors that could
1281    /// occur due to overflow have been eliminated while construction the `View`.
1282    pub fn get_mut_sample(&mut self, channel: u8, x: u32, y: u32) -> Option<&mut P::Subpixel> {
1283        if !self.inner.in_bounds(channel, x, y) {
1284            return None;
1285        }
1286
1287        let index = self.inner.in_bounds_index(channel, x, y);
1288        // Should always be `Some(_)` but checking is more costly.
1289        self.inner.samples.as_mut().get_mut(index)
1290    }
1291
1292    /// Return the portion of the buffer that holds sample values.
1293    ///
1294    /// While this can not fail–the validity of all coordinates has been validated during the
1295    /// conversion from `FlatSamples`–the resulting slice may still contain holes.
1296    pub fn image_slice(&self) -> &[P::Subpixel]
1297    where
1298        Buffer: AsRef<[P::Subpixel]>,
1299    {
1300        &self.inner.samples.as_ref()[..self.min_length()]
1301    }
1302
1303    /// Return the mutable buffer that holds sample values.
1304    pub fn image_mut_slice(&mut self) -> &mut [P::Subpixel] {
1305        let length = self.min_length();
1306        &mut self.inner.samples.as_mut()[..length]
1307    }
1308
1309    /// Shrink the inner image.
1310    ///
1311    /// The new dimensions will be the minimum of the previous dimensions. Since the set of
1312    /// in-bounds pixels afterwards is a subset of the current ones, this is allowed on a `View`.
1313    /// Note that you can not change the number of channels as an intrinsic property of `P`.
1314    pub fn shrink_to(&mut self, width: u32, height: u32) {
1315        let channels = self.inner.layout.channels;
1316        self.inner.shrink_to(channels, width, height)
1317    }
1318}
1319
1320// The out-of-bounds panic for single sample access similar to `slice::index`.
1321#[inline(never)]
1322#[cold]
1323fn panic_cwh_out_of_bounds(
1324    (c, x, y): (u8, u32, u32),
1325    bounds: (u8, u32, u32),
1326    strides: (usize, usize, usize),
1327) -> ! {
1328    panic!(
1329        "Sample coordinates {:?} out of sample matrix bounds {:?} with strides {:?}",
1330        (c, x, y),
1331        bounds,
1332        strides
1333    )
1334}
1335
1336// The out-of-bounds panic for pixel access similar to `slice::index`.
1337#[inline(never)]
1338#[cold]
1339fn panic_pixel_out_of_bounds((x, y): (u32, u32), bounds: (u32, u32)) -> ! {
1340    panic!("Image index {:?} out of bounds {:?}", (x, y), bounds)
1341}
1342
1343impl<Buffer> Index<(u8, u32, u32)> for FlatSamples<Buffer>
1344where
1345    Buffer: Index<usize>,
1346{
1347    type Output = Buffer::Output;
1348
1349    /// Return a reference to a single sample at specified coordinates.
1350    ///
1351    /// # Panics
1352    ///
1353    /// When the coordinates are out of bounds or the index calculation fails.
1354    fn index(&self, (c, x, y): (u8, u32, u32)) -> &Self::Output {
1355        let bounds = self.bounds();
1356        let strides = self.strides_cwh();
1357        let index = self
1358            .index(c, x, y)
1359            .unwrap_or_else(|| panic_cwh_out_of_bounds((c, x, y), bounds, strides));
1360        &self.samples[index]
1361    }
1362}
1363
1364impl<Buffer> IndexMut<(u8, u32, u32)> for FlatSamples<Buffer>
1365where
1366    Buffer: IndexMut<usize>,
1367{
1368    /// Return a mutable reference to a single sample at specified coordinates.
1369    ///
1370    /// # Panics
1371    ///
1372    /// When the coordinates are out of bounds or the index calculation fails.
1373    fn index_mut(&mut self, (c, x, y): (u8, u32, u32)) -> &mut Self::Output {
1374        let bounds = self.bounds();
1375        let strides = self.strides_cwh();
1376        let index = self
1377            .index(c, x, y)
1378            .unwrap_or_else(|| panic_cwh_out_of_bounds((c, x, y), bounds, strides));
1379        &mut self.samples[index]
1380    }
1381}
1382
1383impl<Buffer, P: Pixel> GenericImageView for View<Buffer, P>
1384where
1385    Buffer: AsRef<[P::Subpixel]>,
1386{
1387    type Pixel = P;
1388
1389    fn dimensions(&self) -> (u32, u32) {
1390        (self.inner.layout.width, self.inner.layout.height)
1391    }
1392
1393    fn bounds(&self) -> (u32, u32, u32, u32) {
1394        let (w, h) = self.dimensions();
1395        (0, w, 0, h)
1396    }
1397
1398    fn in_bounds(&self, x: u32, y: u32) -> bool {
1399        let (w, h) = self.dimensions();
1400        x < w && y < h
1401    }
1402
1403    fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
1404        if !self.inner.in_bounds(0, x, y) {
1405            panic_pixel_out_of_bounds((x, y), self.dimensions())
1406        }
1407
1408        let image = self.inner.samples.as_ref();
1409        let base_index = self.inner.in_bounds_index(0, x, y);
1410        let channels = P::CHANNEL_COUNT as usize;
1411
1412        let mut buffer = [Zero::zero(); 256];
1413        buffer
1414            .iter_mut()
1415            .enumerate()
1416            .take(channels)
1417            .for_each(|(c, to)| {
1418                let index = base_index + c * self.inner.layout.channel_stride;
1419                *to = image[index];
1420            });
1421
1422        *P::from_slice(&buffer[..channels])
1423    }
1424}
1425
1426impl<Buffer, P: Pixel> GenericImageView for ViewMut<Buffer, P>
1427where
1428    Buffer: AsMut<[P::Subpixel]> + AsRef<[P::Subpixel]>,
1429{
1430    type Pixel = P;
1431
1432    fn dimensions(&self) -> (u32, u32) {
1433        (self.inner.layout.width, self.inner.layout.height)
1434    }
1435
1436    fn bounds(&self) -> (u32, u32, u32, u32) {
1437        let (w, h) = self.dimensions();
1438        (0, w, 0, h)
1439    }
1440
1441    fn in_bounds(&self, x: u32, y: u32) -> bool {
1442        let (w, h) = self.dimensions();
1443        x < w && y < h
1444    }
1445
1446    fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
1447        if !self.inner.in_bounds(0, x, y) {
1448            panic_pixel_out_of_bounds((x, y), self.dimensions())
1449        }
1450
1451        let image = self.inner.samples.as_ref();
1452        let base_index = self.inner.in_bounds_index(0, x, y);
1453        let channels = P::CHANNEL_COUNT as usize;
1454
1455        let mut buffer = [Zero::zero(); 256];
1456        buffer
1457            .iter_mut()
1458            .enumerate()
1459            .take(channels)
1460            .for_each(|(c, to)| {
1461                let index = base_index + c * self.inner.layout.channel_stride;
1462                *to = image[index];
1463            });
1464
1465        *P::from_slice(&buffer[..channels])
1466    }
1467}
1468
1469impl<Buffer, P: Pixel> GenericImage for ViewMut<Buffer, P>
1470where
1471    Buffer: AsMut<[P::Subpixel]> + AsRef<[P::Subpixel]>,
1472{
1473    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel {
1474        if !self.inner.in_bounds(0, x, y) {
1475            panic_pixel_out_of_bounds((x, y), self.dimensions())
1476        }
1477
1478        let base_index = self.inner.in_bounds_index(0, x, y);
1479        let channel_count = <P as Pixel>::CHANNEL_COUNT as usize;
1480        let pixel_range = base_index..base_index + channel_count;
1481        P::from_slice_mut(&mut self.inner.samples.as_mut()[pixel_range])
1482    }
1483
1484    #[allow(deprecated)]
1485    fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
1486        *self.get_pixel_mut(x, y) = pixel;
1487    }
1488
1489    #[allow(deprecated)]
1490    fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
1491        self.get_pixel_mut(x, y).blend(&pixel);
1492    }
1493}
1494
1495impl From<Error> for ImageError {
1496    fn from(error: Error) -> ImageError {
1497        #[derive(Debug)]
1498        struct NormalFormRequiredError(NormalForm);
1499        impl fmt::Display for NormalFormRequiredError {
1500            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1501                write!(f, "Required sample buffer in normal form {:?}", self.0)
1502            }
1503        }
1504        impl error::Error for NormalFormRequiredError {}
1505
1506        match error {
1507            Error::TooLarge => ImageError::Parameter(ParameterError::from_kind(
1508                ParameterErrorKind::DimensionMismatch,
1509            )),
1510            Error::NormalFormRequired(form) => ImageError::Decoding(DecodingError::new(
1511                ImageFormatHint::Unknown,
1512                NormalFormRequiredError(form),
1513            )),
1514            Error::ChannelCountMismatch(_lc, _pc) => ImageError::Parameter(
1515                ParameterError::from_kind(ParameterErrorKind::DimensionMismatch),
1516            ),
1517            Error::WrongColor(color) => {
1518                ImageError::Unsupported(UnsupportedError::from_format_and_kind(
1519                    ImageFormatHint::Unknown,
1520                    UnsupportedErrorKind::Color(color.into()),
1521                ))
1522            }
1523        }
1524    }
1525}
1526
1527impl fmt::Display for Error {
1528    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1529        match self {
1530            Error::TooLarge => write!(f, "The layout is too large"),
1531            Error::NormalFormRequired(form) => write!(
1532                f,
1533                "The layout needs to {}",
1534                match form {
1535                    NormalForm::ColumnMajorPacked => "be packed and in column major form",
1536                    NormalForm::ImagePacked => "be fully packed",
1537                    NormalForm::PixelPacked => "have packed pixels",
1538                    NormalForm::RowMajorPacked => "be packed and in row major form",
1539                    NormalForm::Unaliased => "not have any aliasing channels",
1540                }
1541            ),
1542            Error::ChannelCountMismatch(layout_channels, pixel_channels) => write!(
1543                f,
1544                "The channel count of the chosen pixel (={}) does agree with the layout (={})",
1545                pixel_channels, layout_channels
1546            ),
1547            Error::WrongColor(color) => write!(
1548                f,
1549                "The chosen color type does not match the hint {:?}",
1550                color
1551            ),
1552        }
1553    }
1554}
1555
1556impl error::Error for Error {}
1557
1558impl PartialOrd for NormalForm {
1559    /// Compares the logical preconditions.
1560    ///
1561    /// `a < b` if the normal form `a` has less preconditions than `b`.
1562    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1563        match (*self, *other) {
1564            (NormalForm::Unaliased, NormalForm::Unaliased) => Some(cmp::Ordering::Equal),
1565            (NormalForm::PixelPacked, NormalForm::PixelPacked) => Some(cmp::Ordering::Equal),
1566            (NormalForm::ImagePacked, NormalForm::ImagePacked) => Some(cmp::Ordering::Equal),
1567            (NormalForm::RowMajorPacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Equal),
1568            (NormalForm::ColumnMajorPacked, NormalForm::ColumnMajorPacked) => {
1569                Some(cmp::Ordering::Equal)
1570            }
1571
1572            (NormalForm::Unaliased, _) => Some(cmp::Ordering::Less),
1573            (_, NormalForm::Unaliased) => Some(cmp::Ordering::Greater),
1574
1575            (NormalForm::PixelPacked, NormalForm::ColumnMajorPacked) => Some(cmp::Ordering::Less),
1576            (NormalForm::PixelPacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Less),
1577            (NormalForm::RowMajorPacked, NormalForm::PixelPacked) => Some(cmp::Ordering::Greater),
1578            (NormalForm::ColumnMajorPacked, NormalForm::PixelPacked) => {
1579                Some(cmp::Ordering::Greater)
1580            }
1581
1582            (NormalForm::ImagePacked, NormalForm::ColumnMajorPacked) => Some(cmp::Ordering::Less),
1583            (NormalForm::ImagePacked, NormalForm::RowMajorPacked) => Some(cmp::Ordering::Less),
1584            (NormalForm::RowMajorPacked, NormalForm::ImagePacked) => Some(cmp::Ordering::Greater),
1585            (NormalForm::ColumnMajorPacked, NormalForm::ImagePacked) => {
1586                Some(cmp::Ordering::Greater)
1587            }
1588
1589            (NormalForm::ImagePacked, NormalForm::PixelPacked) => None,
1590            (NormalForm::PixelPacked, NormalForm::ImagePacked) => None,
1591            (NormalForm::RowMajorPacked, NormalForm::ColumnMajorPacked) => None,
1592            (NormalForm::ColumnMajorPacked, NormalForm::RowMajorPacked) => None,
1593        }
1594    }
1595}
1596
1597#[cfg(test)]
1598mod tests {
1599    use super::*;
1600    use crate::buffer_::GrayAlphaImage;
1601    use crate::color::{LumaA, Rgb};
1602
1603    #[test]
1604    fn aliasing_view() {
1605        let buffer = FlatSamples {
1606            samples: &[42],
1607            layout: SampleLayout {
1608                channels: 3,
1609                channel_stride: 0,
1610                width: 100,
1611                width_stride: 0,
1612                height: 100,
1613                height_stride: 0,
1614            },
1615            color_hint: None,
1616        };
1617
1618        let view = buffer.as_view::<Rgb<u8>>().expect("This is a valid view");
1619        let pixel_count = view
1620            .pixels()
1621            .inspect(|pixel| assert!(pixel.2 == Rgb([42, 42, 42])))
1622            .count();
1623        assert_eq!(pixel_count, 100 * 100);
1624    }
1625
1626    #[test]
1627    fn mutable_view() {
1628        let mut buffer = FlatSamples {
1629            samples: [0; 18],
1630            layout: SampleLayout {
1631                channels: 2,
1632                channel_stride: 1,
1633                width: 3,
1634                width_stride: 2,
1635                height: 3,
1636                height_stride: 6,
1637            },
1638            color_hint: None,
1639        };
1640
1641        {
1642            let mut view = buffer
1643                .as_view_mut::<LumaA<u16>>()
1644                .expect("This should be a valid mutable buffer");
1645            assert_eq!(view.dimensions(), (3, 3));
1646            #[allow(deprecated)]
1647            for i in 0..9 {
1648                *view.get_pixel_mut(i % 3, i / 3) = LumaA([2 * i as u16, 2 * i as u16 + 1]);
1649            }
1650        }
1651
1652        buffer
1653            .samples
1654            .iter()
1655            .enumerate()
1656            .for_each(|(idx, sample)| assert_eq!(idx, *sample as usize));
1657    }
1658
1659    #[test]
1660    fn normal_forms() {
1661        assert!(FlatSamples {
1662            samples: [0u8; 0],
1663            layout: SampleLayout {
1664                channels: 2,
1665                channel_stride: 1,
1666                width: 3,
1667                width_stride: 9,
1668                height: 3,
1669                height_stride: 28,
1670            },
1671            color_hint: None,
1672        }
1673        .is_normal(NormalForm::PixelPacked));
1674
1675        assert!(FlatSamples {
1676            samples: [0u8; 0],
1677            layout: SampleLayout {
1678                channels: 2,
1679                channel_stride: 8,
1680                width: 4,
1681                width_stride: 1,
1682                height: 2,
1683                height_stride: 4,
1684            },
1685            color_hint: None,
1686        }
1687        .is_normal(NormalForm::ImagePacked));
1688
1689        assert!(FlatSamples {
1690            samples: [0u8; 0],
1691            layout: SampleLayout {
1692                channels: 2,
1693                channel_stride: 1,
1694                width: 4,
1695                width_stride: 2,
1696                height: 2,
1697                height_stride: 8,
1698            },
1699            color_hint: None,
1700        }
1701        .is_normal(NormalForm::RowMajorPacked));
1702
1703        assert!(FlatSamples {
1704            samples: [0u8; 0],
1705            layout: SampleLayout {
1706                channels: 2,
1707                channel_stride: 1,
1708                width: 4,
1709                width_stride: 4,
1710                height: 2,
1711                height_stride: 2,
1712            },
1713            color_hint: None,
1714        }
1715        .is_normal(NormalForm::ColumnMajorPacked));
1716    }
1717
1718    #[test]
1719    fn image_buffer_conversion() {
1720        let expected_layout = SampleLayout {
1721            channels: 2,
1722            channel_stride: 1,
1723            width: 4,
1724            width_stride: 2,
1725            height: 2,
1726            height_stride: 8,
1727        };
1728
1729        let initial = GrayAlphaImage::new(expected_layout.width, expected_layout.height);
1730        let buffer = initial.into_flat_samples();
1731
1732        assert_eq!(buffer.layout, expected_layout);
1733
1734        let _: GrayAlphaImage = buffer.try_into_buffer().unwrap_or_else(|(error, _)| {
1735            panic!("Expected buffer to be convertible but {:?}", error)
1736        });
1737    }
1738}