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}