pub struct Image<Layout = Bytes> { /* private fields */ }
Expand description

A container of allocated bytes, parameterized over the layout.

This type permits user defined layouts of any kind and does not unsafely depend on the validity of the layouts. Correctness is achieved in the common case by discouraging methods that would lead to a diverging size of the memory buffer and the layout. Hence, access to the image pixels should not lead to panic unless an incorrectly implemented layout is used.

It possible to convert the layout to a less strictly typed one without reallocating the buffer. For example, all standard layouts such as Matrix can be weakened to DynLayout. The reverse can not be done unchecked but is possible with fallible conversions.

Indeed, the image can arbitrarily change its own layout—different ImageRef and ImageMut may even chose _conflicting layouts—and thus overwrite the content with completely different types and layouts. This is intended to maximize the flexibility for users. In complicated cases it could be hard for the type system to reflect the compatibility of a custom pixel layout and a standard one. It is solely the user’s responsibility to use the interface sensibly. The soundness of standard channel types (e.g. u8 or u32) is not impacted by this as any byte content is valid for them.

Examples

Initialize a matrix as computed [u8; 4] rga pixels:

use image_texel::{Image, Matrix};

let mut image = Image::from(Matrix::<[u8; 4]>::with_width_and_height(400, 400));

image.shade(|x, y, rgba| {
    rgba[0] = x as u8;
    rgba[1] = y as u8;
    rgba[3] = 0xff;
});

Design

Since a Image can not unsafely rely on the layout behaving correctly, direct accessors may have suboptimal behaviour and perform a few (seemingly) redundant checks. More optimal, but much more specialized, wrappers can be provided in other types that first reduce to a first-party layout and byte buffer and then preserve this invariant by never calling second/third-party code from traits. Some of these may be offered in this crate in the future.

Note also that Image provides fallible operations, some of them are meant to modify the type. This can obviously not be performed in-place, in the manner with which it would be common if the type did not change. Instead we approximate at least the result type by transferring the buffer on success while leaving it unchanged in case of failure. An example signature for this is:

fn mend<M>(&mut self, with: L::Item) -> Option<Image<M>>

Implementations

Image methods for all layouts.

Create a new image for a specific layout.

Create a new image with initial byte content.

Create a new image with initial texel contents.

The memory is reused as much as possible. If the layout is too large for the buffer then the remainder is filled up with zeroed bytes.

Get a reference to those bytes used by the layout.

Get a mutable reference to those bytes used by the layout.

If necessary, reallocate the buffer to fit the layout.

Call this method after having mutated a layout with Image::layout_mut_unguarded whenever you are not sure that the layout did not grow. This will ensure the contract that the internal buffer is large enough for the layout.

Panics

This method panics when the allocation of the new buffer fails.

Change the layer of the image.

Reallocates the buffer when growing a layout. Call Image::fits to check this property.

Decay into a image with less specific layout.

See the Decay trait for an explanation of this operation.

Example

The common layouts define ways to decay into a dynamically typed variant.

let matrix = Matrix::<u8>::with_width_and_height(400, 400);
let image: Image<layout::Matrix<u8>> = Image::from(matrix);

// to turn hide the `u8` type but keep width, height, texel layout
let image: Image<layout::MatrixBytes> = image.decay();
assert_eq!(image.layout().width(), 400);
assert_eq!(image.layout().height(), 400);

See also Image::mend and Image::try_mend for operations that reverse the effects.

Can also be used to forget specifics of the layout, turning the image into a more general container type. For example, to use a uniform type as an allocated buffer waiting on reuse.

let matrix = Matrix::<u8>::with_width_and_height(400, 400);

// Can always decay to a byte buffer.
let bytes: Image = Image::from(matrix).decay();
let _: &layout::Bytes = bytes.layout();

Move the buffer into a new image.

Strengthen the layout of the image.

See the Mend trait for an explanation of this operation.

Strengthen the layout of the image.

See the Mend trait for an explanation of this operation.

This is a fallible operation. In case of success returns Ok and the byte buffer of the image is moved into the result. When mending fails this method returns Err and the buffer is kept by this image.

Image methods that do not require a layout.

Check if the buffer could accommodate another layout without reallocating.

Get a reference to the unstructured bytes of the image.

Note that this may return more bytes than required for the specific layout for various reasons. See also as_bytes.

Get a mutable reference to the unstructured bytes of the image.

Note that this may return more bytes than required for the specific layout for various reasons. See also as_bytes_mut.

View this buffer as a slice of pixels.

This reinterprets the bytes of the buffer. It can be used to view the buffer as any kind of pixel, regardless of its association with the layout. Use it with care.

An alternative way to get a slice of texels when a layout has an inherent texel type is Self::as_slice.

View this buffer as a slice of pixels.

This reinterprets the bytes of the buffer. It can be used to view the buffer as any kind of pixel, regardless of its association with the layout. Use it with care.

An alternative way to get a slice of texels when a layout has an inherent texel type is Self::as_mut_slice.

Get a reference to the layout.

Get a mutable reference to the layout.

Be mindful not to modify the layout to exceed the allocated size. This does not cause any unsoundness but might lead to panics when calling other methods.

Get a view of this image.

Get a view of this image, if the alternate layout fits.

Get a mutable view of this image.

Get a mutable view under an alternate layout.

Get a mutable view of this image, if the alternate layout fits.

Get a single texel from a raster image.

Put a single texel to a raster image.

Call a function on each texel of this raster image.

The order of evaluation is not defined although certain layouts may offer more specific guarantees. In general, one can expect that layouts call the function in a cache-efficient manner if they are aware of a better iteration strategy.

Image methods for layouts based on pod samples.

Interpret an existing buffer as a pixel image.

The data already contained within the buffer is not modified so that prior initialization can be performed or one array of samples reinterpreted for an image of other sample type. This method will never reallocate data.

Panics

This function will panic if the buffer is shorter than the layout.

Get a slice of the individual samples in the layout.

An alternative way to get a slice of texels when a layout does not have an inherent texel type is Self::as_texels.

Get a mutable slice of the individual samples in the layout.

An alternative way to get a slice of texels when a layout does not have an inherent texel type is Self::as_mut_texels.

Convert into an vector-like of sample types.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Returns the “default value” for a type. Read more

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.