emilk / egui

egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native
https://www.egui.rs/
Apache License 2.0
21.66k stars 1.56k forks source link

Allow choice of endianness when reading RGBA data into a `ColorImage` #2325

Open BridgeTheMasterBuilder opened 1 year ago

BridgeTheMasterBuilder commented 1 year ago

Is your feature request related to a problem? Please describe. ColorImage::from_rgba_unmultiplied assumes a byte-order layout of the rgba parameter, as if the data were a &[u32] of pixels using the pixel format 0xAABBGGRR. In other words, the red color component is located at the lowest address.

Describe the solution you'd like First and foremost, document what pixel format is used as it is currently not obvious what the order of bytes is. For reference, what egui calls RGBA, SDL calls ABGR.

The user should be allowed to choose what pixel format to use. For now, documenting what format is used for ColorImage::from_rgba_unmultiplied and adding a new associated function ColorImage::from_abgr_unmultiplied which uses the opposite endianness to interpret the pixel data should be good enough.

Describe alternatives you've considered N/A

Additional context I am willing to make a PR that implements the above-mentioned changes.

n00kii commented 1 year ago

couldnt you just manually chunk the pixel data? i.e. for a &[u8] array of abgr,

let size = [100usize; 2]; // replace with whatever the actual size is
let pixels = raw_abgr.chunks_exact(4).map(|abgr_pixel| Color32::from_rgba_unmultiplied(abgr_pixel[3], abgr_pixel[2], abgr_pixel[1], abgr_pixel[0])).collect::<Vec<Color32>>();
let color_image = ColorImage { size, pixels };
BridgeTheMasterBuilder commented 1 year ago

couldnt you just manually chunk the pixel data? i.e. for a &[u8] array of abgr,

let size = [100usize; 2]; // replace with whatever the actual size is
let pixels = raw_abgr.chunks_exact(4).map(|abgr_pixel| Color32::from_rgba_unmultiplied(abgr_pixel[3], abgr_pixel[2], abgr_pixel[1], abgr_pixel[0])).collect::<Vec<Color32>>();
let color_image = ColorImage { size, pixels };

Naturally, you can do that. For realtime graphics however that adds an unnecessary and avoidable overhead. It forces the user to use a specific pixel format if they want to avoid said overhead, which may not be under their control because the pixel data may be coming from somewhere else.

In any case, at the very least the documentation must state what format is used. The layout of bytes in RGBA8888 is not obvious, in some graphics libraries it is always [R, G, B, A] regardless of system endianness and in others it does depend on endianness (so on little-endian machines it might be [A, B, G, R]). So I don't see how there is any way to know what choice egui has made.