image
image copied to clipboard
Image Format Feature Request: QOI - Quite Ok Image format support
Add encode and decode support for QOI format.
The specification for the format can be found here.
More information can be found on this blog post.
There are three implementations of the reference encoder/decoder in rust already -
- https://github.com/ChevyRay/qoi_rs
- https://github.com/steven-joruk/qoi
- https://github.com/zakarumych/rapid-qoi
Adding: https://github.com/taotao54321/img-qoi
Looks complete although using somewhat dubious unsafe
, ArrayVec
dependency for pure stack buffers for some reason, and other implementation issues.
QOI is an exciting format that we should definitely keep an eye on. However, I'm very hesitant to already commit to supporting the format for years to come, when it has only been around for a matter of weeks.
Given that it has an agreed upon specification that works, isn't the only thing that can change is them making breaking changes to a new version of the specification, which we wouldn't need to support.
Alternatively, how about hiding it behind a non-default feature flag that doesn't promise support for future specifications?
The concern isn't so much about supporting further upstream changes, but rather that we don't yet know whether the format will takeoff and actually get widespread use. I'm afraid we could end up in a situation where we have a mostly abandoned codec as part of our public API with no way to know whether anyone is actually depending on it, and no pathway to getting rid of it.
My stance on 'fringe' codecs is mainly by weighing the potential maintenance burden. Generally, I'm positive towards them. (See: accepting 'farbfeld' in #1171 for its simplicity). As far as I can understand, the format itself is 1.0
and simplistic. On face value, I see no reason to believe it will undergo massive changes or require too many errata to the spec itself. (Plus it's promised to be final, pinky promise even, and the author has successfully demonstrated a stance on rejecting fluff extensions). There's too little space left in the spec to evolve anyways.
I don't think there is a particular burden in supporting stable code for a specific and unchanging codecs—almost no matter how recent. Mainly in compile time which can be easily solved a feature that defaults to off, again referring to farbfeld for how it was handled. The number (and state) of dependencies can also be considered when choosing one of the implementations linked above.
Given this, my main concern with support is in reducing the risk of building poorly maintained bindings—by which is mean silently buggy. I would expect decently good coverage in tests and, in the best case, utilizing a downstream crate that is also 1.0
. If there ever is going to be a 2.0 of the format release then I suppose it should be evaluated entirely different from the first version. I would also like to wait out at least some of the open requests for clarification of the specification (this or this) to reduce the risk of long-standing bug reports even more.
Hi all, let me throw in my 2 cents if there's any interest: https://github.com/aldanor/qoi-rust.
I've been working on my own Rust implementation too (since the start), and finally got it to a state where it can be published: qoi
crate.
Some notes on this implementation and also re: some concerns raised above:
- It is a
forbid(unsafe_code)
crate (I initially had some unsafe stuff in there, but at the cost of a few percent performance drop managed to convert it to zero-unsafe). - It beats both the original C implementation and other Rust impls performance-wise so far (~1GB/s encode speed, ~1.5GB/s decode speed on the reference image suite provided upstream). See the readme in the repository for more details.
- Support for both streaming reads/writes and memory-to-memory (the API for the former can be tweaked if needed though, as it can be done differently).
- Reasonably good test coverage (including roundtrips vs the reference C implementation, fuzz testing, tests on generated image data etc; still working on more tests though).
- Dependencies: there's a single
bytemuck
dependency which is already a dependency ofimage
. - Build time: there's ~1k loc total, so it's fairly tiny.
- "1.0 state" - it is likely that streaming Read/Write API (and maybe some other public APIs) may need to be backwards-incompatibly tweaked in order to integrate them into
image
if it ever comes to that, so I'd rather wait on calling it 1.0. - QOI format itself: first off, it's been solidified and won't change in its current incarnation (unless the community eventually agrees on what qoi2 should look like; but then, technically, it would be a completely different, unrelated format). Second, some major frameworks like raylib and SAIL already support QOI in their main branches, so why not? 🤷
- This issue has been resolved (qoi-rust decoder always validates the padding at the end).
- This issue has also been resolved (qoi-rust decoder will throw an error if there's insufficient data to fill the full image).
This is now complete