Hey! I was hoping for some help with image formats.
I'm trying to use ksni to add an icon to the system tray. The method that determines the icon shown is called icon_pixmap and it returns Vec<Icon>. Icon represents an ARGB32 image in network byte order and it takes a height, width, and data as Vec<u8>.
I have the icons as PNGs which I am embedding via include_bytes!, but I'm having a hard time figuring out how to convert it to ARGB32. The closest lead I've found is cairo's variant for Argb32. I would appreciate any guidance in the right direction?
You could do this in a build script, output the ARGBs, and include_bytes those instead. Or just convert them with something else if it's a static-ish set; I'm sure there's some ImageMagick incantation to do it for example.
Thank you so much for all your help, @quinedot! Could you please review my implementation below when you get a chance? Interestingly, only one of the PNGs is showing correctly and the other seems to have its channels in a different order.
use image::{load_from_memory, Rgba};
fn rgba_image_bytes_to_argb32_network_order(image_bytes: &[u8]) -> Vec<u8> {
if let Ok(image) = load_from_memory(image_bytes) {
let mut image_buffer = image.to_rgba8();
for pixel in image_buffer.pixels_mut() {
*pixel = Rgba(u32::from_le_bytes(pixel.0).rotate_right(8).to_be_bytes());
}
image_buffer.into_raw()
} else {
println!("Error converting RGBA image bytes to ARGB 32 network order.");
Vec::<u8>::new()
}
}
Also, extra special thanks for taking the time to rewrite the code in idiomatic Rust. I'm still trying to improve in that regard, so your refactoring was very helpful.