slint icon indicating copy to clipboard operation
slint copied to clipboard

Image: data url support

Open task-jp opened this issue 1 year ago • 7 comments

Data url format is useful when one tries slintpad with images.

Image { source: @image-url("data:image/png;base64,iV....="); }

task-jp avatar Dec 23 '24 06:12 task-jp

Does dataurl I added depend on some old version of crates that didn't support no_std yet? In such case how do we solve it in general?

task-jp avatar Dec 23 '24 07:12 task-jp

Thanks for your feedback.

Does "in the compiler" mean decoding the image in from_at_image_url_node?

In the current version, I wanted to use image::load_from_memory_with_format() as same place as image::open(). Another reason is that in the case of wasm, we can skip the decoding as below.

#[cfg(target_arch = "wasm32")]
return self.lookup_image_in_cache_or_create(cache_key, |_| {
    return Some(ImageInner::HTMLImage(vtable::VRc::new(
        super::htmlimage::HTMLImage::new(&str),
    )));
});

task-jp avatar Dec 24 '24 05:12 task-jp

It may be better not to introduce the DataUrl for ImageReference. Adding "data:/" block below the "builtin:/" block could be good enough.

task-jp avatar Dec 24 '24 05:12 task-jp

Thanks for the PR. This is an usefull feature to have. I'm thinking the decoding could be done in the compiler instead. (and stored in EmbeddedData)

I agree. This feature can most likely be handled entirely in the compiler, without introducing any additional functions and dependencies in the runtime.

Is there a particular benefit to letting the browser do the data url decoding at runtime for wasm builds?

tronical avatar Dec 24 '24 08:12 tronical

Is there a particular benefit to letting the browser do the data url decoding at runtime for wasm builds?

I don't have any strong reason for that, it just looked cleaner for me. I'll move the logic in the compiler.

task-jp avatar Dec 24 '24 10:12 task-jp

I need more advise to make it right.

As far as I checked, there is only one place that EmbeddedData is created. https://github.com/slint-ui/slint/blob/266c6039702e82f60c6eb9c4ea7e368372a264b3/internal/compiler/passes/embed_images.rs#L181

The code here is called during compilation but if I use slint-viewer, it won't be called because embed_images returns immediately in the first if statement.

pub async fn embed_images(
    ...
) {
    if embed_files == EmbedResourcesKind::Nothing && resource_url_mapper.is_none() {
        return;
    }

Is that correct?

task-jp avatar Dec 25 '24 16:12 task-jp

Indeed, it may need to be handled separately depending on the language.

  • In rust, we generate an include_bytes! in the embedded_file_tokens function. Instead, we need to generate a slice. (Like we do already for builtins). https://github.com/slint-ui/slint/blob/266c6039702e82f60c6eb9c4ea7e368372a264b3/internal/compiler/generator/rust.rs#L3155

  • In C++, we do include the data in the binary so we should do the dame for data, but without opening the file: https://github.com/slint-ui/slint/blob/266c6039702e82f60c6eb9c4ea7e368372a264b3/internal/compiler/generator/cpp.rs#L885

  • in the interpreter we'd open the file there, and we would need to handle the data url similarly to the builtin https://github.com/slint-ui/slint/blob/266c6039702e82f60c6eb9c4ea7e368372a264b3/internal/interpreter/eval.rs#L274

I guess there could be an helper function in i_slint_compiler to share some of the decoding. Maybe ImageReference can get a new enum value like ImageReference::Data { data: String, extension: String }` (which contain the actual data (base-64 decoded))

ogoffart avatar Dec 26 '24 17:12 ogoffart