image_texel/
image.rs

1//! Defines the `Image` container, with flexibly type-safe layout.
2//!
3//! Besides the main type, [`Image`], which is an owned buffer of particular layout there are some
4//! supporting types that represent other ways in which layouts interact with buffers. Note that
5//! the layout is flexible in the sense that it is up to the user to ultimately ensure correct
6//! typing. The type definition will _help_ you by not providing the tools for strong types but
7//! it's always _allowed_/_valid_ to refer to the same bytes by a different layout. This makes it
8//! possible to use your own texel/pixel wrapper types regardless of the underlying byte
9//! representation. Indeed, the byte buffer need not even represent a pixel matrix (but it's
10//! advised, probably very common, and the only 'supported' use-case).
11mod atomic;
12mod cell;
13mod raw;
14
15pub mod data;
16
17use core::{fmt, ops};
18
19pub(crate) use self::raw::RawImage;
20use crate::buf::{buf, Buffer};
21use crate::layout::{
22    Bytes, Decay, Layout, Mend, PlaneOf, Raster, RasterMut, Relocate, SliceLayout, Take, TryMend,
23};
24use crate::texel::MAX_ALIGN;
25use crate::{BufferReuseError, Texel, TexelBuffer};
26
27pub use crate::stride::{StridedBufferMut, StridedBufferRef};
28pub use atomic::{AtomicImage, AtomicImageRef};
29pub use cell::{CellImage, CellImageRef};
30pub use data::{AsCopySource, AsCopyTarget, DataCells, DataMut, DataRef};
31
32/// A container of allocated bytes, parameterized over the layout.
33///
34/// This type permits user defined layouts of any kind and does not unsafely depend on the validity
35/// of the layouts. Correctness is achieved in the common case by discouraging methods that would
36/// lead to a diverging size of the memory buffer and the layout. Hence, access to the image pixels
37/// should not lead to panic unless an incorrectly implemented layout is used.
38///
39/// It possible to convert the layout to a less strictly typed one without reallocating the buffer,
40/// by re-interpreting the bytes. For example, all standard layouts such as
41/// [`Matrix`](`crate::layout::Matrix`) can be weakened to [`Bytes`]. The reverse can not be done
42/// unchecked but is possible with fallible conversions.
43///
44/// Indeed, the image can _arbitrarily_ change its own layout—different [`ImageRef`] and
45/// [`ImageMut`] may even chose _conflicting layouts—and thus overwrite the content with completely
46/// different types and layouts. This is intended to maximize the flexibility for users. In
47/// complicated cases it could be hard for the type system to reflect the compatibility of a custom
48/// pixel layout and a standard one. It is solely the user's responsibility to use the interface
49/// sensibly. The _soundness_ of standard channel types (e.g. [`u8`] or [`u32`]) is not impacted by
50/// this as any byte content is valid for them.
51///
52/// ## Examples
53///
54/// Initialize a matrix as computed `[u8; 4]` rga pixels:
55///
56#[cfg_attr(not(miri), doc = "```")]
57#[cfg_attr(miri, doc = "```no_run")] // too expensive and pointless
58/// # fn test() -> Option<()> {
59/// use image_texel::{Image, Matrix};
60///
61/// let mut image = Image::from(Matrix::<[u8; 4]>::with_width_and_height(400, 400));
62///
63/// image.shade(|x, y, rgba| {
64///     rgba[0] = x as u8;
65///     rgba[1] = y as u8;
66///     rgba[3] = 0xff;
67/// });
68///
69/// # Some(()) }
70/// # let _ = test();
71/// ```
72///
73/// # Design
74///
75/// Since a `Image` can not unsafely rely on the layout behaving correctly, direct accessors may
76/// have suboptimal behaviour and perform a few (seemingly) redundant checks. More optimal, but
77/// much more specialized, wrappers can be provided in other types that first reduce to a
78/// first-party layout and byte buffer and then preserve this invariant by never calling
79/// second/third-party code from traits. Some of these may be offered in this crate in the future.
80///
81/// Note also that `Image` provides fallible operations, some of them are meant to modify the
82/// type. This can obviously not be performed in-place, in the manner with which it would be common
83/// if the type did not change. Instead we approximate at least the result type by transferring the
84/// buffer on success while leaving it unchanged in case of failure. An example signature for this is:
85///
86/// > [`fn mend<M>(&mut self, with: L::Item) -> Option<Image<M>>`][`mend`]
87///
88/// [`mend`]: #method.mend
89#[derive(Clone, PartialEq, Eq)]
90pub struct Image<Layout = Bytes> {
91    inner: RawImage<Buffer, Layout>,
92}
93
94/// A read-only view of an image.
95///
96/// Note that this requires its underlying buffer to be highly aligned! For that reason it is not
97/// possible to take a reference at an arbitrary byte slice for its initialization.
98#[derive(Clone, PartialEq, Eq)]
99pub struct ImageRef<'buf, Layout = &'buf Bytes> {
100    inner: RawImage<&'buf buf, Layout>,
101}
102
103/// A writeable reference to an image buffer.
104///
105/// Note that this requires its underlying buffer to be highly aligned! For that reason it is not
106/// possible to take a reference at an arbitrary byte slice for its initialization.
107#[derive(PartialEq, Eq)]
108pub struct ImageMut<'buf, Layout = &'buf mut Bytes> {
109    inner: RawImage<&'buf mut buf, Layout>,
110}
111
112/// Returned when failing to split an image into planes.
113#[allow(dead_code)]
114pub struct IntoPlanesError {
115    index_errors: core::num::NonZeroUsize,
116}
117
118/// Describes an image coordinate.
119#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
120pub struct Coord(pub u32, pub u32);
121
122impl Coord {
123    /// The coordinate across the width of the image (horizontal direction).
124    pub fn x(self) -> u32 {
125        self.0
126    }
127
128    /// The coordinate across the height of the image (horizontal direction).
129    pub fn y(self) -> u32 {
130        self.1
131    }
132
133    /// Access both coordinates as a tuple.
134    pub fn yx(self) -> (u32, u32) {
135        (self.1, self.0)
136    }
137
138    /// Access both coordinates as a tuple.
139    pub fn xy(self) -> (u32, u32) {
140        (self.0, self.1)
141    }
142}
143
144/// Image methods for all layouts.
145impl<L: Layout> Image<L> {
146    /// Create a new image for a specific layout.
147    pub fn new(layout: L) -> Self {
148        RawImage::<Buffer, L>::new(layout).into()
149    }
150
151    /// Create a new image with initial byte content.
152    pub fn with_bytes(layout: L, bytes: &[u8]) -> Self {
153        RawImage::with_contents(bytes, layout).into()
154    }
155
156    /// Create a new image with initial texel contents.
157    ///
158    /// The memory is reused as much as possible. If the layout is too large for the buffer then
159    /// the remainder is filled up with zeroed bytes.
160    pub fn with_buffer<T>(layout: L, bytes: TexelBuffer<T>) -> Self {
161        RawImage::from_buffer(Bytes(0), bytes.into_inner())
162            .with_layout(layout)
163            .into()
164    }
165
166    /// Get a reference to those bytes used by the layout.
167    pub fn as_bytes(&self) -> &[u8] {
168        self.inner.as_bytes()
169    }
170
171    /// Get a mutable reference to those bytes used by the layout.
172    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
173        self.inner.as_bytes_mut()
174    }
175
176    /// Get a reference to the aligned unstructured bytes of the image.
177    pub fn as_buf(&self) -> &buf {
178        self.inner.as_buf()
179    }
180
181    /// Get a reference to the mutable aligned unstructured bytes of the image.
182    pub fn as_mut_buf(&mut self) -> &mut buf {
183        self.inner.as_mut_buf()
184    }
185
186    /// If necessary, reallocate the buffer to fit the layout.
187    ///
188    /// Call this method after having mutated a layout with [`Image::layout_mut_unguarded`]
189    /// whenever you are not sure that the layout did not grow. This will ensure the contract that
190    /// the internal buffer is large enough for the layout.
191    ///
192    /// # Panics
193    ///
194    /// This method panics when the allocation of the new buffer fails.
195    pub fn ensure_layout(&mut self) {
196        self.inner.mutate_layout(|_| ());
197    }
198
199    /// Change the layer of the image.
200    ///
201    /// Reallocates the buffer when growing a layout. Call [`Image::fits`] to check this property.
202    pub fn with_layout<M>(self, layout: M) -> Image<M>
203    where
204        M: Layout,
205    {
206        self.inner.with_layout(layout).into()
207    }
208
209    /// Decay into a image with less specific layout.
210    ///
211    /// See the [`Decay`] trait for an explanation of this operation.
212    ///
213    /// # Example
214    ///
215    /// The common layouts define ways to decay into a dynamically typed variant.
216    ///
217    /// ```
218    /// # use image_texel::{Image, Matrix, layout};
219    /// let matrix = Matrix::<u8>::with_width_and_height(400, 400);
220    /// let image: Image<layout::Matrix<u8>> = Image::from(matrix);
221    ///
222    /// // to turn hide the `u8` type but keep width, height, texel layout
223    /// let image: Image<layout::MatrixBytes> = image.decay();
224    /// assert_eq!(image.layout().width(), 400);
225    /// assert_eq!(image.layout().height(), 400);
226    /// ```
227    ///
228    /// See also [`Image::mend`] and [`Image::try_mend`] for operations that reverse the effects.
229    ///
230    /// Can also be used to forget specifics of the layout, turning the image into a more general
231    /// container type. For example, to use a uniform type as an allocated buffer waiting on reuse.
232    ///
233    /// ```
234    /// # use image_texel::{Image, Matrix, layout};
235    /// let matrix = Matrix::<u8>::with_width_and_height(400, 400);
236    ///
237    /// // Can always decay to a byte buffer.
238    /// let bytes: Image = Image::from(matrix).decay();
239    /// let _: &layout::Bytes = bytes.layout();
240    /// ```
241    ///
242    /// [`Decay`]: ../layout/trait.Decay.html
243    pub fn decay<M>(self) -> Image<M>
244    where
245        M: Decay<L>,
246        M: Layout,
247    {
248        self.inner.decay().into()
249    }
250
251    /// Like [`Self::decay`]` but returns `None` rather than panicking. While this is strictly
252    /// speaking a violation of the trait contract, you may want to handle this yourself.
253    pub fn checked_decay<M>(self) -> Option<Image<M>>
254    where
255        M: Decay<L>,
256        M: Layout,
257    {
258        Some(self.inner.checked_decay()?.into())
259    }
260
261    /// Move the buffer into a new image.
262    pub fn take(&mut self) -> Image<L>
263    where
264        L: Take,
265    {
266        self.inner.take().into()
267    }
268
269    /// Strengthen the layout of the image.
270    ///
271    /// See the [`Mend`] trait for an explanation of this operation.
272    ///
273    /// [`Mend`]: ../layout/trait.Mend.html
274    pub fn mend<Item>(self, mend: Item) -> Image<Item::Into>
275    where
276        Item: Mend<L>,
277        L: Take,
278    {
279        let new_layout = mend.mend(self.inner.layout());
280        self.inner.mogrify_layout(|_| new_layout).into()
281    }
282
283    /// Strengthen the layout of the image.
284    ///
285    /// See the [`Mend`] trait for an explanation of this operation.
286    ///
287    /// This is a fallible operation. In case of success returns `Ok` and the byte buffer of the
288    /// image is moved into the result. When mending fails this method returns `Err` and the buffer
289    /// is kept by this image.
290    ///
291    /// [`Mend`]: ../layout/trait.Mend.html
292    pub fn try_mend<Item>(&mut self, mend: Item) -> Result<Image<Item::Into>, Item::Err>
293    where
294        Item: TryMend<L>,
295        L: Take,
296    {
297        let new_layout = mend.try_mend(self.inner.layout())?;
298        Ok(self.inner.take().mogrify_layout(|_| new_layout).into())
299    }
300}
301
302/// Image methods that do not require a layout.
303impl<L> Image<L> {
304    /// Check if the buffer could accommodate another layout without reallocating.
305    pub fn fits(&self, other: &impl Layout) -> bool {
306        self.inner.fits(other)
307    }
308
309    /// Get a reference to the unstructured bytes of the image.
310    ///
311    /// Note that this may return more bytes than required for the specific layout for various
312    /// reasons. See also [`as_bytes`].
313    ///
314    /// [`as_bytes`]: #method.as_bytes
315    pub fn as_capacity_bytes(&self) -> &[u8] {
316        self.inner.as_capacity_bytes()
317    }
318
319    /// Get a mutable reference to the unstructured bytes of the image.
320    ///
321    /// Note that this may return more bytes than required for the specific layout for various
322    /// reasons. See also [`as_bytes_mut`].
323    ///
324    /// [`as_bytes_mut`]: #method.as_bytes_mut
325    pub fn as_capacity_bytes_mut(&mut self) -> &mut [u8] {
326        self.inner.as_capacity_bytes_mut()
327    }
328
329    /// Get a reference to the aligned unstructured bytes of the image.
330    ///
331    /// Note that this may return more bytes than required for the specific layout for various
332    /// reasons. See also [`Self::as_capacity_bytes`].
333    pub fn as_capacity_buf(&self) -> &buf {
334        self.inner.as_capacity_buf()
335    }
336
337    /// Get a mutable reference to the unstructured bytes of the image.
338    ///
339    /// Note that this may return more bytes than required for the specific layout for various
340    /// reasons. See also [`Self::as_capacity_bytes_mut`].
341    pub fn as_capacity_buf_mut(&mut self) -> &mut buf {
342        self.inner.as_capacity_buf_mut()
343    }
344
345    /// View this buffer as a slice of pixels.
346    ///
347    /// This reinterprets the bytes of the buffer. It can be used to view the buffer as any kind of
348    /// pixel, regardless of its association with the layout. Use it with care.
349    ///
350    /// An alternative way to get a slice of texels when a layout has an inherent texel type is
351    /// [`Self::as_slice`].
352    pub fn as_texels<P>(&self, pixel: Texel<P>) -> &[P]
353    where
354        L: Layout,
355    {
356        pixel.cast_buf(self.inner.as_buf())
357    }
358
359    /// View this buffer as a slice of pixels.
360    ///
361    /// This reinterprets the bytes of the buffer. It can be used to view the buffer as any kind of
362    /// pixel, regardless of its association with the layout. Use it with care.
363    ///
364    /// An alternative way to get a slice of texels when a layout has an inherent texel type is
365    /// [`Self::as_mut_slice`].
366    pub fn as_mut_texels<P>(&mut self, pixel: Texel<P>) -> &mut [P]
367    where
368        L: Layout,
369    {
370        pixel.cast_mut_buf(self.inner.as_mut_buf())
371    }
372
373    /// Get a reference to the layout.
374    pub fn layout(&self) -> &L {
375        self.inner.layout()
376    }
377
378    /// Change the layout, growing the buffer in the process.
379    ///
380    /// Note that there is no equivalent method on any of the other buffer types since this is the
381    /// only one that can reallocate the buffer when necessary.
382    pub fn set_layout(&mut self, layout: L)
383    where
384        L: Layout,
385    {
386        *self.layout_mut_unguarded() = layout;
387        self.ensure_layout();
388    }
389
390    /// Get a mutable reference to the layout.
391    ///
392    /// Be mindful not to modify the layout to exceed the allocated size. This does not cause any
393    /// unsoundness but might lead to panics when calling other methods.
394    pub fn layout_mut_unguarded(&mut self) -> &mut L {
395        self.inner.layout_mut_unguarded()
396    }
397
398    /// Get a view of this image.
399    pub fn as_ref(&self) -> ImageRef<'_, &'_ L> {
400        self.inner.as_deref().into()
401    }
402
403    /// Get a view of this image, if the alternate layout fits.
404    pub fn try_to_ref<M: Layout>(&self, layout: M) -> Option<ImageRef<'_, M>> {
405        self.as_ref().with_layout(layout)
406    }
407
408    /// Get a mutable view of this image.
409    pub fn as_mut(&mut self) -> ImageMut<'_, &'_ mut L> {
410        self.inner.as_deref_mut().into()
411    }
412
413    /// Get a mutable view under an alternate layout.
414    ///
415    /// Reallocates the buffer when necessary, adding new bytes to the end. The layout of this
416    /// image itself is not modified.
417    pub fn to_mut<M: Layout>(&mut self, layout: M) -> ImageMut<'_, M> {
418        self.inner.as_reinterpreted(layout).into()
419    }
420
421    /// Get a mutable view of this image, if the alternate layout fits.
422    pub fn try_to_mut<M: Layout>(&mut self, layout: M) -> Option<ImageMut<'_, M>> {
423        self.as_mut().with_layout(layout)
424    }
425
426    /// Get a single texel from a raster image.
427    pub fn get_texel<P>(&self, coord: Coord) -> Option<P>
428    where
429        L: Raster<P>,
430    {
431        L::get(self.as_ref(), coord)
432    }
433
434    /// Put a single texel to a raster image.
435    pub fn put_texel<P>(&mut self, coord: Coord, texel: P)
436    where
437        L: RasterMut<P>,
438    {
439        L::put(self.as_mut(), coord, texel)
440    }
441
442    /// Call a function on each texel of this raster image.
443    ///
444    /// The order of evaluation is _not_ defined although certain layouts may offer more specific
445    /// guarantees. In general, one can expect that layouts call the function in a cache-efficient
446    /// manner if they are aware of a better iteration strategy.
447    pub fn shade<P>(&mut self, f: impl FnMut(u32, u32, &mut P))
448    where
449        L: RasterMut<P>,
450    {
451        L::shade(self.as_mut(), f)
452    }
453}
454
455/// Image methods for layouts based on pod samples.
456impl<L: SliceLayout> Image<L> {
457    /// Interpret an existing buffer as a pixel image.
458    ///
459    /// The data already contained within the buffer is not modified so that prior initialization
460    /// can be performed or one array of samples reinterpreted for an image of other sample type.
461    /// This method will never reallocate data.
462    ///
463    /// # Panics
464    ///
465    /// This function will panic if the buffer is shorter than the layout.
466    pub fn from_buffer(buffer: TexelBuffer<L::Sample>, layout: L) -> Self {
467        assert!(buffer.byte_len() >= layout.byte_len());
468        RawImage::from_texel_buffer(buffer, layout).into()
469    }
470
471    /// Get a slice of the individual samples in the layout.
472    ///
473    /// An alternative way to get a slice of texels when a layout does _not_ have an inherent texel
474    /// _type_ is [`Self::as_texels`].
475    pub fn as_slice(&self) -> &[L::Sample] {
476        self.inner.as_slice()
477    }
478
479    /// Get a mutable slice of the individual samples in the layout.
480    ///
481    /// An alternative way to get a slice of texels when a layout does _not_ have an inherent texel
482    /// _type_ is [`Self::as_mut_texels`].
483    pub fn as_mut_slice(&mut self) -> &mut [L::Sample] {
484        self.inner.as_mut_slice()
485    }
486
487    /// Convert into an vector-like of sample types.
488    pub fn into_buffer(self) -> TexelBuffer<L::Sample> {
489        self.inner.into_buffer()
490    }
491}
492
493impl<'data, L> ImageRef<'data, L> {
494    /// Get a reference to those bytes used by the layout.
495    pub fn as_bytes(&self) -> &[u8]
496    where
497        L: Layout,
498    {
499        self.inner.as_bytes()
500    }
501
502    /// Get a reference to the underlying buffer.
503    pub fn as_buf(&self) -> &buf
504    where
505        L: Layout,
506    {
507        self.inner.as_buf()
508    }
509
510    /// Get a reference to the complete underlying buffer, ignoring the layout.
511    pub fn as_capacity_buf(&self) -> &buf {
512        self.inner.get()
513    }
514
515    pub fn layout(&self) -> &L {
516        self.inner.layout()
517    }
518
519    /// Get a view of this image.
520    pub fn as_ref(&self) -> ImageRef<'_, &'_ L> {
521        self.inner.as_deref().into()
522    }
523
524    /// Check if a call to [`ImageRef::with_layout`] would succeed.
525    pub fn fits(&self, other: &impl Layout) -> bool {
526        self.inner.fits(other)
527    }
528
529    /// Change this view to a different layout.
530    ///
531    /// This returns `Some` if the layout fits the underlying data, and `None` otherwise. Use
532    /// [`ImageRef::fits`] to check this property in a separate call. Note that the new layout
533    /// need not be related to the old layout in any other way.
534    ///
535    /// # Usage
536    ///
537    /// ```rust
538    /// # fn not_main() -> Option<()> {
539    /// use image_texel::{Image, Matrix, layout::Bytes};
540    /// let image = Image::from(Matrix::<[u8; 4]>::with_width_and_height(10, 10));
541    ///
542    /// let reference = image.as_ref();
543    ///
544    /// let as_bytes = reference.with_layout(Bytes(400))?;
545    /// assert!(matches!(as_bytes.layout(), Bytes(400)));
546    ///
547    /// // But not if we request too much.
548    /// assert!(as_bytes.with_layout(Bytes(500)).is_none());
549    ///
550    /// # Some(()) }
551    /// # fn main() { not_main(); }
552    /// ```
553    pub fn with_layout<M>(self, layout: M) -> Option<ImageRef<'data, M>>
554    where
555        M: Layout,
556    {
557        let image = self.inner.try_reinterpret(layout).ok()?;
558        Some(image.into())
559    }
560
561    /// Decay into a image with less specific layout.
562    ///
563    /// See [`Image::decay`].
564    pub fn decay<M>(self) -> ImageRef<'data, M>
565    where
566        M: Decay<L>,
567        M: Layout,
568    {
569        self.inner
570            .checked_decay()
571            .unwrap_or_else(decay_failed)
572            .into()
573    }
574
575    /// Like [`Self::decay`]` but returns `None` rather than panicking. While this is strictly
576    /// speaking a violation of the trait contract, you may want to handle this yourself.
577    pub fn checked_decay<M>(self) -> Option<ImageRef<'data, M>>
578    where
579        M: Decay<L>,
580        M: Layout,
581    {
582        Some(self.inner.checked_decay()?.into())
583    }
584
585    /// Copy all bytes to a newly allocated image.
586    ///
587    /// Note this will allocate a buffer according to the capacity length of this reference, not
588    /// merely the layout. When this is not the intention, consider calling [`Self::split_layout`]
589    /// or [`Self::truncate_layout`] respectively.
590    ///
591    /// # Examples
592    ///
593    /// Here we make an independent copy of the second plane of a composite image.
594    ///
595    /// ```
596    /// use image_texel::image::{Image, ImageRef};
597    /// use image_texel::layout::{PlaneMatrices, Matrix};
598    /// use image_texel::texels::U8;
599    ///
600    /// let mat = Matrix::from_width_height(U8, 8, 8).unwrap();
601    /// let buffer = Image::new(PlaneMatrices::<_, 2>::from_repeated(mat));
602    ///
603    /// // … some code to initialize those planes.
604    /// # let mut buffer = buffer;
605    /// # buffer.as_mut().into_planes([1]).unwrap()[0]
606    /// #     .as_capacity_buf_mut()[..8].copy_from_slice(b"not zero");
607    /// # let buffer = buffer;
608    ///
609    /// let [p1] = buffer.as_ref().into_planes([1]).unwrap();
610    /// let clone_of: Image<_> = p1.into_owned();
611    ///
612    /// let [p1] = buffer.as_ref().into_planes([1]).unwrap();
613    /// assert_eq!(clone_of.as_bytes(), p1.as_bytes());
614    /// ```
615    pub fn into_owned(self) -> Image<L> {
616        self.inner.into_owned().into()
617    }
618
619    /// Get a slice of the individual samples in the layout.
620    pub fn as_slice(&self) -> &[L::Sample]
621    where
622        L: SliceLayout,
623    {
624        self.inner.as_slice()
625    }
626
627    /// View this buffer as a slice of pixels.
628    ///
629    /// This reinterprets the bytes of the buffer. It can be used to view the buffer as any kind of
630    /// pixel, regardless of its association with the layout. Use it with care.
631    ///
632    /// An alternative way to get a slice of texels when a layout has an inherent texel type is
633    /// [`Self::as_slice`].
634    pub fn as_texels<P>(&self, pixel: Texel<P>) -> &[P]
635    where
636        L: Layout,
637    {
638        pixel.cast_buf(self.inner.as_buf())
639    }
640
641    /// Turn into a slice of the individual samples in the layout.
642    ///
643    /// This preserves the lifetime with which the layout is borrowed from the underlying image,
644    /// and the `ImageMut` need not stay alive.
645    pub fn into_bytes(self) -> &'data [u8]
646    where
647        L: Layout,
648    {
649        let (visible, layout) = self.inner.into_parts();
650        visible.truncate(layout.byte_len())
651    }
652
653    /// Turn into a slice of the individual samples in the layout.
654    ///
655    /// This preserves the lifetime with which the layout is borrowed from the underlying image,
656    /// and the `ImageMut` need not stay alive.
657    pub fn into_slice(self) -> &'data [L::Sample]
658    where
659        L: SliceLayout,
660    {
661        let (visible, layout) = self.inner.into_parts();
662        layout.sample().cast_buf(visible)
663    }
664
665    /// Retrieve a single texel from a raster image.
666    pub fn get_texel<P>(&self, coord: Coord) -> Option<P>
667    where
668        L: Raster<P>,
669    {
670        L::get(self.as_ref(), coord)
671    }
672
673    /// Split off all unused bytes at the tail of the layout.
674    pub fn split_layout(&mut self) -> ImageRef<'data, Bytes>
675    where
676        L: Layout,
677    {
678        // Need to roundup to correct alignment.
679        let size = self.inner.layout().byte_len();
680        let round_up = (size.wrapping_neg() & !(MAX_ALIGN - 1)).wrapping_neg();
681        let buffer = self.inner.get_mut();
682
683        if round_up > buffer.len() {
684            return RawImage::from_buffer(Bytes(0), buf::new(&[])).into();
685        }
686
687        let (initial, next) = buffer.split_at(round_up);
688        *buffer = initial;
689
690        RawImage::from_buffer(Bytes(next.len()), next).into()
691    }
692
693    /// Remove all past-the-layout bytes.
694    ///
695    /// This is a utility to combine with pipelining. It is equivalent to calling
696    /// [`Self::split_layout`] and discarding that result.
697    pub fn truncate_layout(mut self) -> Self
698    where
699        L: Layout,
700    {
701        let _ = self.split_layout();
702        self
703    }
704
705    /// Split this reference into independent planes.
706    ///
707    /// If any plane fails their indexing operation or would not be aligned to the required
708    /// alignment or any plane layouts would overlap, an error is returned. The planes are returned
709    /// in the order of the descriptors.
710    ///
711    /// FIXME: the layout type is not what we want. For instance, with `PlaneMatrices` we get a
712    /// plane type of `Relocated<Matrix<_>>` but when we relocate that to `0` then we would really
713    /// prefer having a simple `Matrix<_>` as the layout type.
714    ///
715    /// # Examples
716    ///
717    /// A layout describing a matrix array can be split:
718    ///
719    /// ```
720    /// use image_texel::image::{Image, ImageRef};
721    /// use image_texel::layout::{PlaneMatrices, Matrix};
722    /// use image_texel::texels::U8;
723    ///
724    /// let mat = Matrix::from_width_height(U8, 8, 8).unwrap();
725    /// let buffer = Image::new(PlaneMatrices::<_, 2>::from_repeated(mat));
726    /// let image: ImageRef<'_, _> = buffer.as_ref();
727    ///
728    /// let [p0, p1] = buffer.as_ref().into_planes([0, 1]).unwrap();
729    /// ```
730    ///
731    /// You may select the same plane twice:
732    ///
733    pub fn into_planes<const N: usize, D>(
734        self,
735        descriptors: [D; N],
736    ) -> Result<[ImageRef<'data, D::Plane>; N], IntoPlanesError>
737    where
738        D: PlaneOf<L>,
739        D::Plane: Relocate,
740    {
741        let layout = self.layout();
742        let mut planes = descriptors.map(|d| {
743            let plane = <D as PlaneOf<L>>::get_plane(d, layout);
744            let empty_buf = buf::new(&[]);
745            (plane, empty_buf)
746        });
747
748        let (mut buffer, _) = self.inner.into_parts();
749
750        for plane in &mut planes {
751            let Some(layout) = &mut plane.0 else {
752                continue;
753            };
754
755            let skip_by = layout.byte_offset();
756
757            // FIXME: do we want failure reasons?
758            if skip_by % MAX_ALIGN != 0 {
759                plane.0 = None;
760                continue;
761            }
762
763            if buffer.len() < skip_by {
764                plane.0 = None;
765                continue;
766            }
767
768            layout.relocate(Default::default());
769            let len = layout.byte_len().div_ceil(MAX_ALIGN) * MAX_ALIGN;
770
771            // Check this before we consume the buffer. This way the tail can still be used by
772            // following layouts, we ignore this.
773            if buffer.len() - skip_by < len {
774                plane.0 = None;
775                continue;
776            }
777
778            let (_pre, tail) = buffer.split_at(skip_by);
779            let (img_buf, _post) = tail.split_at(len);
780
781            plane.1 = img_buf;
782            buffer = tail;
783        }
784
785        let planes = IntoPlanesError::from_array(planes)?;
786        Ok(planes.map(|(layout, buffer)| RawImage::from_buffer(layout, buffer).into()))
787    }
788}
789
790impl<'data, L> ImageMut<'data, L> {
791    /// Get a reference to those bytes used by the layout.
792    pub fn as_bytes(&self) -> &[u8]
793    where
794        L: Layout,
795    {
796        self.inner.as_bytes()
797    }
798
799    /// Get a mutable reference to those bytes used by the layout.
800    pub fn as_bytes_mut(&mut self) -> &mut [u8]
801    where
802        L: Layout,
803    {
804        self.inner.as_bytes_mut()
805    }
806
807    /// Get a reference to the underlying buffer.
808    pub fn as_buf(&self) -> &buf
809    where
810        L: Layout,
811    {
812        self.inner.as_buf()
813    }
814
815    /// Get a mutable reference to the underlying buffer.
816    pub fn as_mut_buf(&mut self) -> &mut buf
817    where
818        L: Layout,
819    {
820        self.inner.as_mut_buf()
821    }
822
823    /// Get a reference to the complete underlying buffer, ignoring the layout.
824    pub fn as_capacity_buf(&self) -> &buf {
825        self.inner.get()
826    }
827
828    /// Get a mutable reference to the underlying buffer, ignoring the layout.
829    pub fn as_capacity_buf_mut(&mut self) -> &mut buf {
830        self.inner.get_mut()
831    }
832
833    pub fn layout(&self) -> &L {
834        self.inner.layout()
835    }
836
837    /// Get a view of this image.
838    pub fn as_ref(&self) -> ImageRef<'_, &'_ L> {
839        self.inner.as_deref().into()
840    }
841
842    /// Get a mutable view of this image.
843    pub fn as_mut(&mut self) -> ImageMut<'_, &'_ mut L> {
844        self.inner.as_deref_mut().into()
845    }
846
847    /// Convert to a view of this image.
848    pub fn into_ref(self) -> ImageRef<'data, L> {
849        let (buffer, layout) = self.inner.into_parts();
850        RawImage::with_buffer_unchecked(layout, &*buffer).into()
851    }
852
853    /// Check if a call to [`ImageMut::with_layout`] would succeed, without consuming this reference.
854    pub fn fits(&self, other: &impl Layout) -> bool {
855        self.inner.fits(other)
856    }
857
858    /// Change this view to a different layout.
859    ///
860    /// This returns `Some` if the layout fits the underlying data, and `None` otherwise. Use
861    /// [`ImageMut::fits`] to check this property in a separate call. Note that the new layout
862    /// need not be related to the old layout in any other way.
863    ///
864    /// # Usage
865    ///
866    /// ```rust
867    /// # fn not_main() -> Option<()> {
868    /// use image_texel::{Image, Matrix, layout::Bytes};
869    /// let mut image = Image::from(Matrix::<[u8; 4]>::with_width_and_height(10, 10));
870    ///
871    /// let reference = image.as_mut();
872    ///
873    /// let as_bytes = reference.with_layout(Bytes(400))?;
874    /// assert!(matches!(as_bytes.layout(), Bytes(400)));
875    ///
876    /// // But not if we request too much.
877    /// assert!(as_bytes.with_layout(Bytes(500)).is_none());
878    ///
879    /// # Some(()) }
880    /// # fn main() { not_main(); }
881    /// ```
882    pub fn with_layout<M>(self, layout: M) -> Option<ImageMut<'data, M>>
883    where
884        M: Layout,
885    {
886        let image = self.inner.try_reinterpret(layout).ok()?;
887        Some(image.into())
888    }
889
890    /// Attempt to modify the layout to a new value, without modifying its type.
891    ///
892    /// Returns an `Err` if the layout does not fit the underlying buffer. Otherwise returns `Ok`
893    /// and overwrites the layout accordingly.
894    ///
895    /// TODO: public name and provide a `set_capacity` for `L = Bytes`?
896    pub(crate) fn try_set_layout(&mut self, layout: L) -> Result<(), BufferReuseError>
897    where
898        L: Layout,
899    {
900        self.inner.try_reuse(layout)
901    }
902
903    /// Decay into a image with less specific layout.
904    ///
905    /// See [`Image::decay`].
906    pub fn decay<M>(self) -> ImageMut<'data, M>
907    where
908        M: Decay<L>,
909        M: Layout,
910    {
911        self.inner
912            .checked_decay()
913            .unwrap_or_else(decay_failed)
914            .into()
915    }
916
917    /// Like [`Self::decay`]` but returns `None` rather than panicking. While this is strictly
918    /// speaking a violation of the trait contract, you may want to handle this yourself.
919    pub fn checked_decay<M>(self) -> Option<ImageMut<'data, M>>
920    where
921        M: Decay<L>,
922        M: Layout,
923    {
924        Some(self.inner.checked_decay()?.into())
925    }
926
927    /// Get a slice of the individual samples in the layout.
928    pub fn as_slice(&self) -> &[L::Sample]
929    where
930        L: SliceLayout,
931    {
932        self.inner.as_slice()
933    }
934
935    /// Get a mutable slice of the individual samples in the layout.
936    pub fn as_mut_slice(&mut self) -> &mut [L::Sample]
937    where
938        L: SliceLayout,
939    {
940        self.inner.as_mut_slice()
941    }
942
943    /// View this buffer as a slice of pixels.
944    ///
945    /// This reinterprets the bytes of the buffer. It can be used to view the buffer as any kind of
946    /// pixel, regardless of its association with the layout. Use it with care.
947    ///
948    /// An alternative way to get a slice of texels when a layout has an inherent texel type is
949    /// [`Self::as_slice`].
950    pub fn as_texels<P>(&self, pixel: Texel<P>) -> &[P]
951    where
952        L: Layout,
953    {
954        pixel.cast_buf(self.inner.as_buf())
955    }
956
957    /// View this buffer as a slice of pixels.
958    ///
959    /// This reinterprets the bytes of the buffer. It can be used to view the buffer as any kind of
960    /// pixel, regardless of its association with the layout. Use it with care.
961    ///
962    /// An alternative way to get a slice of texels when a layout has an inherent texel type is
963    /// [`Self::as_mut_slice`].
964    pub fn as_mut_texels<P>(&mut self, pixel: Texel<P>) -> &mut [P]
965    where
966        L: Layout,
967    {
968        pixel.cast_mut_buf(self.inner.as_mut_buf())
969    }
970
971    /// Copy all bytes to a newly allocated image.
972    ///
973    /// Note this will allocate a buffer according to the capacity length of this reference, not
974    /// merely the layout. When this is not the intention, consider calling [`Self::split_layout`]
975    /// or [`Self::truncate_layout`] respectively.
976    ///
977    /// # Examples
978    ///
979    /// Here we make an independent copy of the second plane of a composite image.
980    ///
981    /// ```
982    /// use image_texel::image::{Image, ImageRef};
983    /// use image_texel::layout::{PlaneMatrices, Matrix};
984    /// use image_texel::texels::U8;
985    ///
986    /// let mat = Matrix::from_width_height(U8, 8, 8).unwrap();
987    /// let mut buffer = Image::new(PlaneMatrices::<_, 2>::from_repeated(mat));
988    ///
989    /// // … some code to initialize those planes.
990    /// # buffer.as_mut().into_planes([1]).unwrap()[0]
991    /// #     .as_capacity_buf_mut()[..8].copy_from_slice(b"not zero");
992    ///
993    /// let [p1] = buffer.as_mut().into_planes([1]).unwrap();
994    /// let clone_of: Image<_> = p1.into_owned();
995    ///
996    /// let [p1] = buffer.as_ref().into_planes([1]).unwrap();
997    /// assert_eq!(clone_of.as_bytes(), p1.as_bytes());
998    /// ```
999    pub fn into_owned(self) -> Image<L> {
1000        self.inner.into_owned().into()
1001    }
1002
1003    /// Turn into a slice of the individual samples in the layout.
1004    ///
1005    /// This preserves the lifetime with which the layout is borrowed from the underlying image,
1006    /// and the `ImageMut` need not stay alive.
1007    pub fn into_slice(self) -> &'data [L::Sample]
1008    where
1009        L: SliceLayout,
1010    {
1011        let (visible, layout) = self.inner.into_parts();
1012        layout.sample().cast_mut_buf(visible)
1013    }
1014
1015    /// Turn into a mutable slice of the individual samples in the layout.
1016    ///
1017    /// This preserves the lifetime with which the layout is borrowed from the underlying image,
1018    /// and the `ImageMut` need not stay alive.
1019    pub fn into_mut_slice(self) -> &'data mut [L::Sample]
1020    where
1021        L: SliceLayout,
1022    {
1023        let (visible, layout) = self.inner.into_parts();
1024        layout.sample().cast_mut_buf(visible)
1025    }
1026
1027    /// Retrieve a single texel from a raster image.
1028    pub fn get_texel<P>(&self, coord: Coord) -> Option<P>
1029    where
1030        L: Raster<P>,
1031    {
1032        L::get(self.as_ref(), coord)
1033    }
1034
1035    /// Put a single texel to a raster image.
1036    pub fn put_texel<P>(&mut self, coord: Coord, texel: P)
1037    where
1038        L: RasterMut<P>,
1039    {
1040        L::put(self.as_mut(), coord, texel)
1041    }
1042
1043    /// Call a function on each texel of this raster image.
1044    ///
1045    /// The order of evaluation is _not_ defined although certain layouts may offer more specific
1046    /// guarantees. In general, one can expect that layouts call the function in a cache-efficient
1047    /// manner if they are aware of a better iteration strategy.
1048    pub fn shade<P>(&mut self, f: impl FnMut(u32, u32, &mut P))
1049    where
1050        L: RasterMut<P>,
1051    {
1052        L::shade(self.as_mut(), f)
1053    }
1054
1055    /// Split off unused bytes at the tail of the layout.
1056    pub fn split_layout(&mut self) -> ImageMut<'data, Bytes>
1057    where
1058        L: Layout,
1059    {
1060        // Need to roundup to correct alignment.
1061        let size = self.inner.layout().byte_len();
1062        let round_up = (size.wrapping_neg() & !(MAX_ALIGN - 1)).wrapping_neg();
1063        let buffer = self.inner.get_mut();
1064
1065        let empty = buf::new_mut(&mut []);
1066        if round_up > buffer.len() {
1067            return RawImage::from_buffer(Bytes(0), empty).into();
1068        }
1069
1070        // replace is needed for the type system as we operate on a mutable reference and must not
1071        // shorten its lifetime in any way by re-borrowing.
1072        let (initial, next) = core::mem::replace(buffer, empty).split_at_mut(round_up);
1073        *buffer = initial;
1074
1075        RawImage::from_buffer(Bytes(next.len()), next).into()
1076    }
1077
1078    /// Remove all past-the-layout bytes.
1079    ///
1080    /// This is a utility to combine with pipelining. It is equivalent to calling
1081    /// [`Self::split_layout`] and discarding that result.
1082    pub fn truncate_layout(mut self) -> Self
1083    where
1084        L: Layout,
1085    {
1086        let _ = self.split_layout();
1087        self
1088    }
1089
1090    /// Split this mutable reference into independent planes.
1091    ///
1092    /// If any plane fails their indexing operation or would not be aligned to the required
1093    /// alignment or the same index is used twice or any plane layouts would overlap for other
1094    /// reasons, an error is returned. The planes are returned in the order of the descriptors.
1095    ///
1096    /// # Examples
1097    ///
1098    /// A layout describing a matrix array can be split:
1099    ///
1100    /// ```
1101    /// use image_texel::image::{Image, ImageMut};
1102    /// use image_texel::layout::{PlaneMatrices, Matrix};
1103    /// use image_texel::texels::U8;
1104    ///
1105    /// let mat = Matrix::from_width_height(U8, 8, 8).unwrap();
1106    /// let mut buffer = Image::new(PlaneMatrices::<_, 2>::from_repeated(mat));
1107    /// let image: ImageMut<'_, _> = buffer.as_mut();
1108    ///
1109    /// let [p0, p1] = image.into_planes([0, 1]).unwrap();
1110    /// ```
1111    ///
1112    /// Contrary to a shared buffer, it is not possible to select the same plane twice or for
1113    /// planes to overlap:
1114    ///
1115    /// ```
1116    /// use image_texel::image::{Image, ImageMut};
1117    /// use image_texel::layout::{PlaneMatrices, Matrix};
1118    /// use image_texel::texels::U8;
1119    ///
1120    /// let mat = Matrix::from_width_height(U8, 8, 8).unwrap();
1121    /// let mut buffer = Image::new(PlaneMatrices::<_, 2>::from_repeated(mat));
1122    /// let image: ImageMut<'_, _> = buffer.as_mut();
1123    ///
1124    /// assert!(image.into_planes([0, 0]).is_err(), "cannot have the same mutable references");
1125    /// ```
1126    pub fn into_planes<const N: usize, D>(
1127        self,
1128        descriptors: [D; N],
1129    ) -> Result<[ImageMut<'data, D::Plane>; N], IntoPlanesError>
1130    where
1131        D: PlaneOf<L>,
1132        D::Plane: Relocate,
1133    {
1134        let layout = self.layout();
1135        let mut planes = descriptors.map(|d| {
1136            let plane = <D as PlaneOf<L>>::get_plane(d, layout);
1137            let empty_buf = buf::new_mut(&mut []);
1138            (plane, empty_buf)
1139        });
1140
1141        // Now re-adjust the planes in order. For this, first collect their associated order.
1142        let mut remap = planes.each_mut().map(|plane| {
1143            // Maps all undefined planes to the zero-offset, so that they get skipped.
1144            let offset = plane.0.as_ref().map_or(0, |p| p.byte_offset());
1145            (offset, plane)
1146        });
1147
1148        // Stable sort, we want to keep the first of each plane that overlaps.
1149        remap.sort_by_key(|&(offset, _)| offset);
1150
1151        let mut consumed = 0;
1152        let (mut buffer, _) = self.inner.into_parts();
1153
1154        for (offset, plane) in remap {
1155            let Some(layout) = &mut plane.0 else {
1156                continue;
1157            };
1158
1159            let Some(skip_by) = offset.checked_sub(consumed) else {
1160                plane.0 = None;
1161                continue;
1162            };
1163
1164            if skip_by % MAX_ALIGN != 0 {
1165                plane.0 = None;
1166                continue;
1167            }
1168
1169            if buffer.len() < skip_by {
1170                plane.0 = None;
1171                continue;
1172            }
1173
1174            layout.relocate(Default::default());
1175            let len = layout.byte_len().div_ceil(MAX_ALIGN) * MAX_ALIGN;
1176
1177            // Check this before we consume the buffer. This way the tail can still be used by
1178            // following layouts, we ignore this.
1179            if buffer.len() - skip_by < len {
1180                plane.0 = None;
1181                continue;
1182            }
1183
1184            buffer = buf::take_at_mut(&mut buffer, skip_by);
1185            consumed += skip_by;
1186
1187            let tail = buf::take_at_mut(&mut buffer, len);
1188            consumed += len;
1189
1190            plane.1 = buffer;
1191            buffer = tail;
1192        }
1193
1194        let planes = IntoPlanesError::from_array(planes)?;
1195        Ok(planes.map(|(layout, buffer)| RawImage::from_buffer(layout, buffer).into()))
1196    }
1197}
1198
1199fn decay_failed<T>() -> T {
1200    #[cold]
1201    fn decay_failed_inner() -> ! {
1202        panic!("decayed layout is incompatible with the original layout");
1203    }
1204
1205    decay_failed_inner()
1206}
1207
1208impl IntoPlanesError {
1209    pub(crate) fn from_array<L, Buffer, const N: usize>(
1210        items: [(Option<L>, Buffer); N],
1211    ) -> Result<[(L, Buffer); N], Self> {
1212        if let Some(index_errors) = {
1213            let count = items.iter().filter(|(l, _)| l.is_none()).count();
1214            core::num::NonZeroUsize::new(count)
1215        } {
1216            return Err(IntoPlanesError { index_errors });
1217        }
1218
1219        Ok(items.map(|(l, b)| (l.unwrap(), b)))
1220    }
1221}
1222
1223impl core::fmt::Debug for IntoPlanesError {
1224    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1225        f.debug_struct("IntoPlanesError").finish()
1226    }
1227}
1228
1229// TODO: how to expose?
1230// This is used internally in `RasterMut::shade` however only for the special case of
1231// * `&mut &mut L` -> `&mut L`
1232// * `&&mut L` -> `&L`
1233// which we know are semantically equivalent. In the general case these would go through checks
1234// that ensure the new layout is consistent with the data.
1235impl<'data, 'l, L: Layout> ImageRef<'data, &'l L> {
1236    pub(crate) fn as_deref(self) -> ImageRef<'data, &'l L::Target>
1237    where
1238        L: ops::Deref,
1239        L::Target: Layout,
1240    {
1241        self.inner.mogrify_layout(|l| &**l).into()
1242    }
1243}
1244
1245impl<'data, 'l, L: Layout> ImageMut<'data, &'l mut L> {
1246    pub(crate) fn as_deref_mut(self) -> ImageMut<'data, &'l mut L::Target>
1247    where
1248        L: ops::DerefMut,
1249        L::Target: Layout,
1250    {
1251        self.inner.mogrify_layout(|l| &mut **l).into()
1252    }
1253}
1254
1255impl<'lt, L: Layout + Clone> From<Image<&'lt L>> for Image<L> {
1256    fn from(image: Image<&'lt L>) -> Self {
1257        let (buffer, layout) = image.inner.into_parts();
1258        let layout: L = layout.clone();
1259        RawImage::from_buffer(layout, buffer).into()
1260    }
1261}
1262
1263impl<'lt, L: Layout + Clone> From<Image<&'lt mut L>> for Image<L> {
1264    fn from(image: Image<&'lt mut L>) -> Self {
1265        let (buffer, layout) = image.inner.into_parts();
1266        let layout: L = layout.clone();
1267        RawImage::from_buffer(layout, buffer).into()
1268    }
1269}
1270
1271impl<'lt, L> From<&'lt Image<L>> for ImageRef<'lt, &'lt L> {
1272    fn from(image: &'lt Image<L>) -> Self {
1273        image.as_ref()
1274    }
1275}
1276
1277impl<'lt, L> From<&'lt mut Image<L>> for ImageMut<'lt, &'lt mut L> {
1278    fn from(image: &'lt mut Image<L>) -> Self {
1279        image.as_mut()
1280    }
1281}
1282
1283impl<'lt, L: Layout + Clone> From<&'lt Image<L>> for ImageRef<'lt, L> {
1284    fn from(image: &'lt Image<L>) -> Self {
1285        image.as_ref().into()
1286    }
1287}
1288
1289impl<'lt, L: Layout + Clone> From<&'lt mut Image<L>> for ImageMut<'lt, L> {
1290    fn from(image: &'lt mut Image<L>) -> Self {
1291        image.as_mut().into()
1292    }
1293}
1294
1295/* FIXME: decide if this should be an explicit method. */
1296impl<'lt, L: Layout + Clone> From<ImageRef<'lt, &'_ L>> for ImageRef<'lt, L> {
1297    fn from(image: ImageRef<'lt, &'_ L>) -> Self {
1298        let (buffer, layout) = image.inner.into_parts();
1299        let layout: L = layout.clone();
1300        RawImage::from_buffer(layout, buffer).into()
1301    }
1302}
1303
1304impl<'lt, L: Layout + Clone> From<ImageRef<'lt, &'_ mut L>> for ImageRef<'lt, L> {
1305    fn from(image: ImageRef<'lt, &'_ mut L>) -> Self {
1306        let (buffer, layout) = image.inner.into_parts();
1307        let layout: L = layout.clone();
1308        RawImage::from_buffer(layout, buffer).into()
1309    }
1310}
1311
1312impl<'lt, L: Layout + Clone> From<ImageMut<'lt, &'_ L>> for ImageMut<'lt, L> {
1313    fn from(image: ImageMut<'lt, &'_ L>) -> Self {
1314        let (buffer, layout) = image.inner.into_parts();
1315        let layout: L = layout.clone();
1316        RawImage::from_buffer(layout, buffer).into()
1317    }
1318}
1319
1320impl<'lt, L: Layout + Clone> From<ImageMut<'lt, &'_ mut L>> for ImageMut<'lt, L> {
1321    fn from(image: ImageMut<'lt, &'_ mut L>) -> Self {
1322        let (buffer, layout) = image.inner.into_parts();
1323        let layout: L = layout.clone();
1324        RawImage::from_buffer(layout, buffer).into()
1325    }
1326}
1327/* FIXME: until here */
1328
1329impl<L> From<RawImage<Buffer, L>> for Image<L> {
1330    fn from(image: RawImage<Buffer, L>) -> Self {
1331        Image { inner: image }
1332    }
1333}
1334
1335impl<'lt, L> From<RawImage<&'lt buf, L>> for ImageRef<'lt, L> {
1336    fn from(image: RawImage<&'lt buf, L>) -> Self {
1337        ImageRef { inner: image }
1338    }
1339}
1340
1341impl<'lt, L> From<RawImage<&'lt mut buf, L>> for ImageMut<'lt, L> {
1342    fn from(image: RawImage<&'lt mut buf, L>) -> Self {
1343        ImageMut { inner: image }
1344    }
1345}
1346
1347impl<L: Layout + Default> Default for Image<L> {
1348    fn default() -> Self {
1349        Image {
1350            inner: RawImage::from_buffer(L::default(), Buffer::default()),
1351        }
1352    }
1353}
1354
1355impl<L> fmt::Debug for Image<L>
1356where
1357    L: SliceLayout + fmt::Debug,
1358    L::Sample: fmt::Debug,
1359{
1360    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1361        f.debug_struct("Image")
1362            .field("layout", self.inner.layout())
1363            .field("content", &self.inner.as_slice())
1364            .finish()
1365    }
1366}