How to work with BGR/BGRA images in version 0.24?
In my code, I need to decompress an image from JPEG and then create a Cairo surface from this image. Cairo uses BGRA format for images, so I was using image::ImageBuffer<image::Bgra<u8>, Vec<u8>> as a convenient container for the image data. To decompress JPEGs, I used the turbojpeg crate [1] (which I created for this purpose), which provides seamless support for both RGB(A) and BGR(A) images [2].
[1] https://docs.rs/turbojpeg/0.2.1/turbojpeg/index.html [2] https://docs.rs/turbojpeg/0.2.1/turbojpeg/trait.JpegPixel.html
However, in image version 0.24, the Bgra struct and all support for BGR/BGRA image buffers was removed. Therefore, I had to remove the implementation for ImageBuffer<Bgra> from turbojpeg as well, so now I either have to give up the convenient ImageBuffer wrapper and work directly with Vec<u8> or sacrifice performance and add the redundant RGBA -> BGRA conversion.
I understand the concerns regarding complexity that led to the removal of BGR in #1482, so perhaps it might make sense to move BGR support into another crate (e.g. image-bgr)? This would keep the core library smaller but still allow people to use BGR when needed.
You can still implement a custom BGR type and use it within the ImageBuffer, as long as you implement the Pixel Trait on it.
Yes, I considered implementing the BGR types myself, but for my application it was not worth the trouble, so I simply stopped using image-rs. However, I'm probably not the only one who needs to work with BGR images, so I wonder if it makes sense to create a new crate (image-bgr?) implementing the BGR type? I might create and maintain that crate myself, if there is enough interest.
The Pixel type in this library is a hassle to implement. I hope it will get simpler in the future.
The Pixel type in this library is a hassle to implement. I hope it will get simpler in the future.
Ironically, removing the need for everyone to implement Pixel::to_bgr and Pixel::to_bgra was part of what started this whole thing... :upside_down_face:
The image create "only" supports RGB and Luma Pixels, because BGR does not contain any other information than RGB already does. ~~Unfortunately, implementing the Pixel type requires defining an associated value of a predefined enum, ColorType which does not contain any BGR variant, and cannot be extended. Therefore, the Pixel Trait could never be implemented correctly for BGR by any other crate.~~
On the other hand, I would advise you to use the image crate for decoding purposes, and not for storing the decoded data. Is there any problem with using the RGB type, and converting it to BGR just before passing it to Cairo?
The relation between Pixel and ColorType actually changed in the 0.24 release. There's now a separate PixelWithColorType trait, and the main Pixel trait isn't required to be one of the known color types.
Wait I forgot about that (wtf I was the one who wrote that piece of code)
Sorry for being confused and for confusing haha
In that case, it should not be too complicated to implement a custom BGR pixel type. Most of the functions are not used anyways, depending on what you're actually doing with the BGR image. If you are not exposing the image, it should be possible to leave some panics instead of adding a real function body.
On the other hand, I would advise you to use the image crate for decoding purposes, and not for storing the decoded data. Is there any problem with using the RGB type, and converting it to BGR just before passing it to Cairo?
In my case, I wanted to decode the image with TurboJPEG (the turbojpeg crate), using the image crate just as a convenient container. I could of course decode into an RGB ImageBuffer and then convert it to BGR, but TurboJPEG can decode directly into BGR, so I wanted to avoid the unnecessary conversion, because performance of image decoding is very important in my application.
Sounds like you made a good choice. Did you have to do any extra work when switching to turbo jpeg?
I made a small improvement to the turbojpeg crate that allows me to conveniently use its Image type both as an owned container Image<Vec<u8>> and as a borrowed reference Image<&[u8]>. These modifications will be a part of turbojpeg version 0.4.
Awesome :)