orbtk icon indicating copy to clipboard operation
orbtk copied to clipboard

ImageWidget Stretch/Fill/Fit

Open e1019 opened this issue 5 years ago • 10 comments

I'm not sure if this is already a feature or not, but I could not figure out how to do this after looking around. Let's say I have a 2400x2400 background image and a 640x480 window. As far as I can tell, the only option for displaying such an image currently is to just show a 640x480 area of the image, like this. image

This is obviously not ideal for making background images. I'd like for there to be some way to make an ImageWidget resize to fill its parent while maintaining aspect ratio or achieve something similar to the picture below. image

e1019 avatar Dec 16 '19 17:12 e1019

Image resizing is not yet implemented. Thank you for the issue.

FloVanGH avatar Dec 16 '19 21:12 FloVanGH

Hi, i have searched for a library that can be integrated to provide this feature and the most used (and the only one) is https://github.com/image-rs/image . Effectively there are some other libraries, but they are all based on this. The only problem is that require some dependencies, but is also provide an entire image manipulation library for a lot of formats, that include flip, crop, resize , rotate, replace, overlay.... (the complete list is here https://docs.rs/image/0.23.7/image/imageops/index.html). So maybe worth it? I don't know, what do you think?

Have a good day

uniformbuffer avatar Jul 26 '20 11:07 uniformbuffer

Hi, thanks again for your research 😉. Good new the OrbTk's render crate depends on the image crate for image handling. This functionality is only not yet implemented in OrbTk. Maybe the best place to do it would be a ImageWidgetState of the ImageWidget. It could adjust the image property (e.g. scale). This should work without changing the ImageRenderObject and the layout object of the image. What do you think.

Thanks

FloVanGH avatar Jul 26 '20 14:07 FloVanGH

For web we will need an other method. The web image does not use the image crate. Maybe we should implement it on the Image object itself. There is a native and a web variant of the image. But as I described the imagewidget state could trigger the scaling.

FloVanGH avatar Jul 26 '20 14:07 FloVanGH

I started working on this. I see in the Image struct the image representation is already in the memory after opening as a render_target.data.

Unfortunately it is a Vec, but image::load_from_memory() expects a Vec. I need to call this function to create a DynamicImage which I can call resize() on. Any sane way to convert Vec back to Vec<8>?

Currently, I'm reading the image from disk again before resizing.

kivimango avatar Oct 18 '20 10:10 kivimango

I made this little function for a previous project, maybe help:

fn move_rect(from: &image::RgbaImage, to: &mut image::RgbaImage, fx: u32, fy: u32, fw: u32, fh: u32, tx: u32, ty: u32, tw: u32, th: u32) {
    if fx >= from.width() || fy >= from.height() || tx >= to.width() || ty >= to.height() {
        return;
    }
    for x in 0..fw.min(from.width()-fx).min((to.width()-tx) * fw / tw) {
        for y in 0..fh.min(from.height()-fy).min((to.height()-ty) * fh / th) {
            let pixel = *from.get_pixel(x+fx, y+fy);
            let scale_left = x * tw / fw;
            let scale_top = y * th / fh;
            let scale_right = (x+1) * tw / fw;
            let scale_bottom = (y+1) * th / fh;
            for px in tx+scale_left..tx+scale_right {
                for py in ty+scale_top..ty+scale_bottom {
                    to.put_pixel(px, py, pixel);
                }
            }
        }
    }
}

It is capable of move and resize a image, you can custom it to work with that Vec

sandmor avatar Oct 18 '20 14:10 sandmor

This is how resizing is handled by orbimage crate https://gitlab.redox-os.org/redox-os/orbimage/-/blob/master/src/lib.rs. Maybe this will help you.

FloVanGH avatar Oct 19 '20 04:10 FloVanGH

Woah, I had no idea that crate exists, event has some nice filters to soften the image... well the original intention of my above function was to scale up certain sprites so it becomes pixel art, it does it pretty well :laughing:

sandmor avatar Oct 19 '20 04:10 sandmor

This is how resizing is handled by orbimage crate https://gitlab.redox-os.org/redox-os/orbimage/-/blob/master/src/lib.rs. Maybe this will help you.

The two Image struct is almost identical. In orbimage, there is another crate used to resize images, which is resize.I don't want to add another dependency since we already using the image-rs crate. Unfortunately, there is no way to bridge the RederTartget.data() to image::resize() method, since the latter expects a Vec of u8. and the Image struct stores the image representation in a Vec of u32. Converting back failures with The image format could not be determined error. Another thing is the Image struct does not carry its source after its created.

kivimango avatar Oct 24 '20 17:10 kivimango

Feel free to do changes on the Image struct as long as it does not break the example. It would be also ok to use your own vec inside of the Image instead of RenderTarget. Important is we get this functionality to work. And if the resize crate can help and it is not outdated or is ok for me to use it. Thanks for your effort.

FloVanGH avatar Oct 24 '20 18:10 FloVanGH