orbtk
orbtk copied to clipboard
ImageWidget Stretch/Fill/Fit
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.
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 resizing is not yet implemented. Thank you for the issue.
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
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
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.
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
Currently, I'm reading the image from disk again before resizing.
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
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.
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:
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.
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.