Opening a png of type gio::File in cairo

Hello,

I am trying to create a libadwaita application in Rust. I want to open two images and overlay them on top of eachother. I am however struggling to understand the documentation. I used an AI assistant which recommended me to use cairo and use create_from_png(). To open the files.

I have already built the logic to allow the user to select a file and have a gio::File which I want to insert. When I do ImageSurface::create_from_png(&mut file); and run the program, I get the error:

error[E0277]: the trait bound `libadwaita::gio::File: std::io::Read` is not satisfied
   --> src/window.rs:138:51
    |
138 |         let image = ImageSurface::create_from_png(&mut file);
    |                     ----------------------------- ^^^^^^^^^ the trait `std::io::Read` is not implemented for `libadwaita::gio::File`
    |                     |
    |                     required by a bound introduced by this call

So I assume the type I need to use must implement std::io::Read. I can do file.read(None) which gives me a FileInputStream. But I think this is a different implementation of read.
What do I need to do differently to make this work, Can I even make this work with a gio::File or do I need to use something else?

Any tips are much appreciated!

Hi,

For opening images from gio::File, just use Picture.for_file().

For overlaying 2 images, an Overlay should do the trick.

Could work, but that way sounds incredibly complicated…
By the way, cairo is the old gtk3 method for custom drawing. In gtk4, prefer snapshots.

thank you for the reply, that could indeed be an easy sollution. However I want to be able to save to overlayed images. I am trying to create an application to easilly add an icon to a folder like this:
image

Ah, OK, thanks for the details!

Looks like create_from_png() takes a file path (i.e. a string) as parameter.
If you have a gio::File you can get its path with the get_path() method.

Alternatively, you could use a GDK Texture and load it to a cairo surface (but I’ve never tried…).

gio::File is just like a path or URL, it does not involve an actually opened file. You first need to get an input stream from it via e.g. read() or read_async() / read_future(). Once you have that you can convert that input stream into something that implements the std::io::Read trait via into_read(), for example.

2 Likes

Hi, thank you very much for that tip. Doing file.read(cancellable).unwrap().into_read() gave me the result I needed. Many thanks

1 Like