Add a way to construct a sub-image without lifetime shortening
Suppose that you want to write a function like
struct Foo {
pixels: Vec<[u8; 4]>, // not an ImgVec for whatever reason
...
}
impl Foo {
fn get_image(&self, rectangle: Rectangle) -> imgref::ImgRefMut<'_, [u8; 4]> {
todo!();
}
}
With the current API of ImgRefMut, there is no way to construct such an ImgRefMut using sub_image_mut() or any other rectangle-oriented operation; you can only use new_stride(). This is because the signature of ImgRefMut::sub_image_mut() is:
pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
which is always a borrow of the initial ImgRefMut, so if you write ImgRefMut::new(&mut self.pixels).sub_image(...), you'll be getting “cannot return value referencing temporary value”. Ideally, there would be something like:
impl<'slice, T> ImgRefMut<'slice, T> {
pub fn into_sub_image_mut(self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'slice, T> {
which takes ownership of the existing mutable reference and thus does not shorten its lifetime. This is of course not a critical expressiveness issue since new_stride() does exist, but it feels like it would be a good API addition, aligned with imgref's goals, to not require the caller to compute stride manually.
This issue does not apply to the non-mutable version ImgRef::sub_image() since its signature copies the original 'slice lifetime already (and relies on the fact that you can get a &'a T from a &'b &'a T, which you cannot do analogously with mutable references).
Actually, this is straightforwardly solvable by adding the proposed method; guess I should write a PR for it. When I started writing this issue (and accidentally submitted it too soon) I was thinking this was only fixable as a breaking change (i.e. version 2.0).
Yeah, an into_ version makes sense.
The regular method has to preserve aliasing guarantees. I'm also thinking about adding split_at_mut or tiling methods.