I'm trying to build a very simple application using Relm4 (which uses Gtk4 as its underlying toolkit) that should display an image. It succeeds in displaying a jpeg image, but fails at loading avif images, producing the error: Error { domain: gdk-pixbuf-error-quark, code: 3, message: "Unrecognized image file format" }. The code is
fn main() {
let path_to_image = ...;
gtk4::gdk::Texture::from_filename(path_to_image).unwrap();
}
After a quick search, it appears that Gtk doesn't support avif images. This surprised me quite a bit. Isn't there a way to display avif images in a Gtk application?
You might be able to use the image crate, which has support for 8-bit only avif images (via the avif-native feature flag).
You can convert the loaded image into bytes (using as_bytes or into_bytes method), then load it using gtk4::gdk::Texture::from_bytes().
Edit: you might try to_rgb8() from the image crate or one of the variants
I have tried doing so, but it still didn't work. I think that's because loading an image with the image crate doesn't change its byte representation when you call as_bytes().
I also tried using that crate to convert to a format that is accepted by Gtk, as such
But this takes so long. About 10 seconds per image, even if the image was originally already in the jpeg format! I think a couple of seconds of delay before showing an image makes a pretty bad but still usable image viewer, but having to wait for 10 seconds per image (the goal of the application being that multiple images should be seen) is waaaay too much. Especially when other image viewers open these images almost instantly.
Ah, well, of course, building with release significantly improved the rendering speed. It's still a bit slow for my taste, but at least now it's "usable".
you should then be able to create a texture using gtk4::Texture::for_pixbuf
This should avoid re-encoding to jpg just for it to be immediately decoded again (along with a loss in precision).
Alternatively have you tried installing the libavif-gdk-pixbuf (Debian/Ubuntu) or avif-pixbuf-loader (Fedora) packages? It seems they should provide system-wide support for loading AVIF images in all GTK applications.
This would probably approximately halve the load time per file, which would be great. I tried that, but I'm stuck at the "this can then be converted to a flat byte buffer". I can't find an API to extract a buffer of bytes out of an RgbImage. I'm also not sure what the bits_per_sample and rowstride parameters are (I'm not an very knowledgeable about image encoding and stuff).
This would be the ideal solution. No package with a similar name seems to exist for my distribution, I'll look into that.
Ah sorry, that should be RgbImage::into_vec. Also, the into_ variants of the DynamicImage may help avoid another data copy (as opposed to the to_ variants which will always copy it).
It seems bits_per_sample should be 8 while rowstride should be 3 * width.