ImageBuffer as ops::Deref
though, which will also get you the raw slice of samples.
pub fn box_filter_mut(filter: MeanKernel, image: &mut RgbaImage) {
let (width, height) = image.dimensions();
// want the truncated value of this division, hence not using float
let radius: i32 = filter.size() as i32 / 2;
let mut new_image: RgbaImage =
ImageBuffer::from_pixel(width, height, Rgba::from_channels(255, 255, 255, 255));
// at this point both images have the same dimensions and I can do a
// horizontal pass over image and write the output onto new_image
// blur pixels row wise
horizontal_blur(radius, &image, &mut new_image);
// Now I don't want to allocate a new buffer to transpose new_image
// so I want to reuse image's buffer to reinterpret as (height, width)
// instead of (width, height)
let mut image: RgbaImage = ImageBuffer::from_raw(height, width, *image.as_raw()).unwrap();
transpose_rgba(&new_image, &mut image);
}
I'm actually having an issue where the borrow checker doesn't allow me to use image's buffer because it's behind a mutable reference. So at this point, if you have advice on how I can do this when taking image as a mutable reference. I worked around this issue already by taking ownership of image. I just wanted to know if I could provide two interfaces like, box_filter_mut
and box_filter
.
image
with a zero-sized allocation temporarily which allows you to take the buffer and reuse it directly.let temp = core::mem::replace(image, ImageBuffer::new(0, 0));
let temp: RgbaImage = ImageBuffer::from_raw(height, width, tmp.into_raw()).unwrap();
*image = temp;
(1, 1)
doesn't stay there which would be arguably unexpected for changing dimensions. So I'd rather add it only with stronger motivation.
ImageBuffer
.
/// swaps width and height for when transposing image
pub fn swap_dimensions(&mut self) {
let (width, height) = self.dimensions();
self.width = height;
self.height = width;
}
I implement this function for ImageBuffer
, in the buffer file, which will swap the dimensions, then in my function:
pub fn box_filter_mut(filter: MeanKernel, mut image: &mut RgbaImage) {
use crate::matrix_ops::transpose_rgba;
use image::Pixel;
let (width, height) = image.dimensions();
// want the truncated value of this division, hence not using float
let radius: i32 = filter.size() as i32 / 2;
let mut new_image: RgbaImage =
ImageBuffer::from_pixel(width, height, Rgba::from_channels(255, 255, 255, 255));
// blur pixels row wise
horizontal_blur(radius, &image, &mut new_image);
// swap image dimensions to allow transposing new_image into image
image.swap_dimensions();
transpose_rgba(&new_image, &mut image);
// swap new_image dimensions to allow blurring image and writing
// to new_image
new_image.swap_dimensions();
// blur pixels column wise
horizontal_blur(radius, &image, &mut new_image);
// swap dimensions again to transpose new image into image for final
// output
image.swap_dimensions();
transpose_rgba(&new_image, &mut image);
}
I'm not necessarily asking for this to be implemented, but I want to clarify what I'm trying to do. The reason why i'm trying to reuse buffers is because I'm compiling this to Webassembly and I'm trying to cut down on allocations. I'm using WeeAlloc as the allocator.
/// sets dimensions of image
pub fn set_dimensions(&mut self, width: u32, height: u32) -> Result<(), String> {
if (width * height * <P as Pixel>::CHANNEL_COUNT as u32) as usize > self.data.len() {
return Err("width and height too large for container".to_string());
}
self.width = width;
self.height = height;
Ok(())
}
something like this would be nice too. I don't know how useful this would be to the overall project though.
ConvertInplace
interface proposed in this issue could even be used to take an image and convert into a transposed image, if that makes sense.
It seems like an separate isse. ConvertInplace was, to my understanding of the draft, meant to preserve pixel relation and also work pixel-by-pixel. This enables some parallelism where a true transpose of the image matrix requires a different kind of parallelization strategy. Your implemtation of swap_dimensions
of course only perserves semantics together with transpose_rgba
. I would recommend going to flat::Flat
for this purpose, it gives you full control over all aspects.
The reason why i'm trying to reuse buffers is because I'm compiling this to Webassembly and I'm trying to cut down on allocations. I'm using WeeAlloc as the allocator.
Please look closely at the code here, and you will find that it does not allocate any memory. Yet, it gives you an intermediate owned Vec of the pixel data. You seem to be under the impression that &mut RgbaImage
makes this impossible. That is not the case. The Rust type system only requires you to give a temporary replacement, which can be constructed without an allocation by substituting a zero-sized image.
let temp = core::mem::replace(image, ImageBuffer::new(0, 0)); let temp: RgbaImage = ImageBuffer::from_raw(height, width, tmp.into_raw()).unwrap(); *image = temp;
@ruffson: Great, if you open an issue, I'll also add my reproduction to it :)
Cool, I'll ping you when I did it.
Limits
struct in the TIFF decoder mod.rs
has a private field _non_exhaustive
which means I cannot simply create a new struct with Limits{...}
, what is the idiomatic way of creating a new Limits
struct outside of this module if you want to change e.g. all three default values? Creating a struct with Limits::default()
and then changing each field one by one?
Interesting. So the examples are all too long?
That's weird but maybe not too bad.. What would happen if we were to truncate?
This may have previously worked incidentally.
while bytes_read < compressed_length && uncompressed.len() < max_uncompressed_length {
let (len, bytes) = decoder.decode_bytes(&compressed[bytes_read..])?;
uncompressed.extend_from_slice(bytes);
Since the lzw
library decodes symbols word-for-word it's not unlikely that we hit exactly the right length.
The new library decodes fixed size chunks
buffer.byte_len
?
According to the docs: https://developer.gnome.org/gdk-pixbuf/unstable/gdk-pixbuf-The-GdkPixbuf-Structure.html#image-data
Image data in a pixbuf is stored in memory in uncompressed, packed format. Rows in the image are stored top to bottom, and in each row pixels are stored from left to right. There may be padding at the end of a row. The "rowstride" value of a pixbuf, as returned by gdk_pixbuf_get_rowstride(), indicates the number of bytes between rows.