Image data is loaded synchronously

Source code: https://github.com/iced-rs/iced/blob/c9bd48704dd9679c033dd0b8588e2744a3df44a0/graphics/src/image.rs#L14
Shouldn’t images be loaded asynchronously since iced is running on top of an async runtime?

What I would propose is to remove the Path variant of image::Data and a new command to load an image from a path. Since loading image from memory isn’t blocking, it could work like this.
For example:

enum Message {
    ImageLoaded(image::Handle)
}

impl Application for App {
    fn new(_) -> iced::Command<Self::Message> {
           image::load_file(PathBuf::new(...), Message::ImageLoaded)
    }

    fn view(&self) -> iced::Element {
          image(self.handle).into()
    }

    fn update(&mut self, msg) {
          match msg {
              Message::ImageLoaded(handle) => self.handle = handle;
          }
    }
}

It would also be cool if the image data would be decoded when creating the handle (ofc, except Web).

fn Handle::from_encoded(bytes: Vec<u8>) -> Result<Handle, image::Result>
fn Handle::from_raw(bytes: Vec<u8>, width: u32, height: u32) -> Handle

(Also, we can use the bytes crate to get efficient byte handling, though this isn’t in the context of this discussion.)

I’d like to try to implement this, if accepted.

I’ll write a polished RFC (soonly.)

I think the image::load_file command is a great idea. It can create a Data::Bytes variant internally.

The challenge here will obtaining a Future that performs I/O while keeping iced decoupled from any particular futures runtime. But it seems that futures has a futures::io module.

I think these are operations that inherently need to happen at the renderer level. Renderers may need to decode and process the image data differently depending on their supported color spaces or their texture atlas format. For instance, we need to swap the R and G channels intiny-skia, as well as premultiply the colors.

We also generally want to avoid depending on heavy dependencies (like image) in iced_core.