mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 22:00:03 -04:00
Fix semi-transparent colors appearing too bright (#5824)
The bug was in `Color32::from_rgba_unmultiplied` and by extension affects: * `Color32::from_rgba_unmultiplied` * `hex_color!` * `HexColor` * `ColorImage::from_rgba_unmultiplied` * All images with transparency (png, webp, …) * `Color32::from_white_alpha` The bug caused translucent colors to appear too bright. ## More Color is hard. When I started out egui I thought "linear space is objectively better, for everything!" and then I've been slowly walking that back for various reasons: * sRGB textures not available everywhere * gamma-space is more _perceptually_ even, so it makes sense to use for anti-aliasing * other applications do everything in gamma space, so that's what people expect (this PR) Similarly, pre-multiplied alpha _makes sense_ for blending colors. It also enables additive colors, which is nice. But it does complicate things. Especially when mixed with sRGB/gamma (As @karhu [points out](https://github.com/emilk/egui/pull/5824#issuecomment-2738099254)). ## Related * Closes https://github.com/emilk/egui/issues/5751 * Closes https://github.com/emilk/egui/issues/5771 ? (probably; hard to tell without a repro) * But not https://github.com/emilk/egui/issues/5810 ## TODO * [x] I broke the RGBA u8 color picker. Fix it --------- Co-authored-by: Andreas Reich <andreas@rerun.io>
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
gamma_u8_from_linear_f32, linear_f32_from_gamma_u8, linear_f32_from_linear_u8,
|
||||
linear_u8_from_linear_f32, Color32, Rgba,
|
||||
gamma_u8_from_linear_f32, linear_f32_from_gamma_u8, linear_u8_from_linear_f32, Color32, Rgba,
|
||||
};
|
||||
|
||||
/// Hue, saturation, value, alpha. All in the range [0, 1].
|
||||
@@ -29,30 +28,20 @@ impl Hsva {
|
||||
/// From `sRGBA` with premultiplied alpha
|
||||
#[inline]
|
||||
pub fn from_srgba_premultiplied([r, g, b, a]: [u8; 4]) -> Self {
|
||||
Self::from_rgba_premultiplied(
|
||||
linear_f32_from_gamma_u8(r),
|
||||
linear_f32_from_gamma_u8(g),
|
||||
linear_f32_from_gamma_u8(b),
|
||||
linear_f32_from_linear_u8(a),
|
||||
)
|
||||
Self::from(Color32::from_rgba_premultiplied(r, g, b, a))
|
||||
}
|
||||
|
||||
/// From `sRGBA` without premultiplied alpha
|
||||
#[inline]
|
||||
pub fn from_srgba_unmultiplied([r, g, b, a]: [u8; 4]) -> Self {
|
||||
Self::from_rgba_unmultiplied(
|
||||
linear_f32_from_gamma_u8(r),
|
||||
linear_f32_from_gamma_u8(g),
|
||||
linear_f32_from_gamma_u8(b),
|
||||
linear_f32_from_linear_u8(a),
|
||||
)
|
||||
Self::from(Color32::from_rgba_unmultiplied(r, g, b, a))
|
||||
}
|
||||
|
||||
/// From linear RGBA with premultiplied alpha
|
||||
#[inline]
|
||||
pub fn from_rgba_premultiplied(r: f32, g: f32, b: f32, a: f32) -> Self {
|
||||
#![allow(clippy::many_single_char_names)]
|
||||
if a == 0.0 {
|
||||
if a <= 0.0 {
|
||||
if r == 0.0 && b == 0.0 && a == 0.0 {
|
||||
Self::default()
|
||||
} else {
|
||||
@@ -152,13 +141,7 @@ impl Hsva {
|
||||
|
||||
#[inline]
|
||||
pub fn to_srgba_premultiplied(&self) -> [u8; 4] {
|
||||
let [r, g, b, a] = self.to_rgba_premultiplied();
|
||||
[
|
||||
gamma_u8_from_linear_f32(r),
|
||||
gamma_u8_from_linear_f32(g),
|
||||
gamma_u8_from_linear_f32(b),
|
||||
linear_u8_from_linear_f32(a),
|
||||
]
|
||||
Color32::from(*self).to_array()
|
||||
}
|
||||
|
||||
/// To gamma-space 0-255.
|
||||
|
||||
Reference in New Issue
Block a user