expose webp_write API that returns WebpBox directly
Closed this issue · 4 comments
...instead of requiring the user to pass in a &mut W: Write
.
While being able to directly have it write to a file or network stream is nice, if you want to just collect the image's bytes into a Vec, it's not an ideal solution:
let mut vec = Vec::new();
webp_write(&img, &mut vec)?;
I would imagine an interface similar to what the webp_read_from_memory functions already provide; functions named webp_write_to_memory
or similar which just return the inner WebpBox<[u8]>
instead of writing its contents.
That API could then be used like this:
webp_write_to_memory(&img)?.to_vec();
which feels more rusty to me. Alternatively, since DynamicImage already lives in RAM and you're allocating a WebpBox anyways, this could be the only API that's exposed, as it more clearly shows the cost of the developer's actions; in this case there would be no new functions, but the existing ones would change. Users can then of course just call .write_all(&webp_box)
on where they want to write the image.
Which changes would you prefer? I'm open to discussion and ready to implement them myself.
Only the simplest APIs of libwebp (C) use WebpBox
(i.e. WebPFree
). We can get rid of it using lower-level APIs. Though libwebp-rs might lack the corresponding bindings for now.
For decoding, we can read the header first, allocate the Vec
, and then call a DecodeInto
-family function.
What I meant was, instead of taking a &mut W: Write
, like fn webp_write(img: &DynamicImage, w: &mut W)
, change function signatures (or add new functions) to return WebpBox<[u8]>
instead. That's slightly more efficient and less indirection for the in-memory usecase.
Example:
pub fn webp_write_rgba<W: Write, C>(img: &ImageBuffer<Rgba<u8>, C>, w: &mut W) -> ImageResult<WebpBox<[u8]>>
where
C: Deref<Target = [u8]>,
{
libwebp::WebPEncodeRGBA(&img, img.width(), img.height(), img.width() * 4, 0.75)
.map_err(|_| EncodingError::new(ImageFormatHint::Unknown, "Webp Format Error".to_string()))
.map_err(ImageError::Encoding)
}
However, now that I know you prefer following the image API over exposing more efficient interfaces, I'm pretty sure you will not want that, so you are free to close this issue.
I think the right direction is to use streaming encoding APIs exposed by libwebp (C), keeping the current interface. It is only an implementation detail that fn webp_write
internally allocates WebpBox<[u8]>
.