add color blending and tinting functions
this is definitely one of those things where i wonder if there are probably better names (more standardized names) that could be used here instead
This commit is contained in:
parent
a087c35024
commit
050c2ac6e9
|
@ -17,6 +17,38 @@ pub const COLOR_BRIGHT_MAGENTA: u32 = 0xffff55ff;
|
|||
pub const COLOR_BRIGHT_YELLOW: u32 = 0xffffff55;
|
||||
pub const COLOR_BRIGHT_WHITE: u32 = 0xffffffff;
|
||||
|
||||
// TODO: probably should name these better, after i do much more reading on the subject :-)
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum BlendFunction {
|
||||
Blend,
|
||||
BlendSourceWithAlpha(u8),
|
||||
TintedBlend(u32),
|
||||
}
|
||||
|
||||
impl BlendFunction {
|
||||
#[inline]
|
||||
/// Blends the source and destination color together using the function associated with
|
||||
/// this enum value. Both colors should be 32-bit packed colors in the format 0xAARRGGBB.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `src`: the source color to blend
|
||||
/// * `dest`: the destination color to blend the source color over
|
||||
///
|
||||
/// returns: the blended color
|
||||
pub fn blend(&self, src: u32, dest: u32) -> u32 {
|
||||
use BlendFunction::*;
|
||||
match self {
|
||||
Blend => blend_argb32(src, dest),
|
||||
BlendSourceWithAlpha(opacity) => blend_source_by_value(src, dest, *opacity),
|
||||
TintedBlend(tint) => {
|
||||
let tinted = tint_argb32(src, *tint);
|
||||
blend_argb32(tinted, dest)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a set of individual ARGB components to a combined 32-bit color value, packed into
|
||||
/// the format 0xAARRGGBB
|
||||
///
|
||||
|
@ -82,6 +114,96 @@ pub fn from_rgb32(rgb: u32) -> (u8, u8, u8) {
|
|||
(r, g, b)
|
||||
}
|
||||
|
||||
/// Blends two color components together using a "strength" factor to control how much of the source
|
||||
/// color versus destination color is represented in the result. This is using the formula:
|
||||
/// `(source * strength) + (dest * (1 - strength))`
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `strength`: controls how much of the source versus destination is represented in the final output,
|
||||
/// where 0 means the source component is 100% present in the output while 255 means the
|
||||
/// destination component is 100% present in the output and 128 means 50% of each.
|
||||
/// * `src`: the source component to be blended
|
||||
/// * `dest`: the destination component to be blended
|
||||
///
|
||||
/// returns: the blended component result
|
||||
#[inline]
|
||||
pub fn blend_components(strength: u8, src: u8, dest: u8) -> u8 {
|
||||
(((src as u16 * strength as u16) + (dest as u16 * (255 - strength as u16))) / 255) as u8
|
||||
}
|
||||
|
||||
/// Alpha blends the components of a source and destination color. Both colors should be 32-bit
|
||||
/// packed colors in the format 0xAARRGGBB.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `src`: the source color that is to be blended onto the destination
|
||||
/// * `dest`: the destination color that the source is being blended into
|
||||
///
|
||||
/// returns: the blended result
|
||||
#[inline]
|
||||
pub fn blend_argb32(src: u32, dest: u32) -> u32 {
|
||||
let (src_a, src_r, src_g, src_b) = from_argb32(src);
|
||||
let (dest_a, dest_r, dest_g, dest_b) = from_argb32(dest);
|
||||
to_argb32(
|
||||
blend_components(src_a, src_a, dest_a),
|
||||
blend_components(src_a, src_r, dest_r),
|
||||
blend_components(src_a, src_g, dest_g),
|
||||
blend_components(src_a, src_b, dest_b),
|
||||
)
|
||||
}
|
||||
|
||||
/// Blends the source and destination colors together, where the alpha value used to blend the two
|
||||
/// colors is derived from the given alpha value multiplied with the source color's alpha component.
|
||||
/// This allows for more flexibility in directly controling how transparent the source
|
||||
/// color is overtop of the destination. Both colors should be 32-bit packed colors in the format
|
||||
/// 0xAARRGGBB.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `src`: the source color that is to be blended onto the destination. the alpha component of this
|
||||
/// color is used during the blend.
|
||||
/// * `dest`: the destination color that the source is being blended into. the alpha component of this
|
||||
/// color is ignored.
|
||||
/// * `alpha`: the transparency or opacity of the source color over the destination color. this is
|
||||
/// multipled together with the source color's alpha component to arrive at the final
|
||||
/// alpha value used for blending the source and destination color's RGB components.
|
||||
///
|
||||
/// returns: the blended result
|
||||
pub fn blend_source_by_value(src: u32, dest: u32, alpha: u8) -> u32 {
|
||||
let (src_a, src_r, src_g, src_b) = from_argb32(src);
|
||||
let (dest_r, dest_g, dest_b) = from_rgb32(dest);
|
||||
let alpha = ((alpha as u16 * src_a as u16) / 255) as u8;
|
||||
to_argb32(
|
||||
alpha,
|
||||
blend_components(alpha, src_r, dest_r),
|
||||
blend_components(alpha, src_g, dest_g),
|
||||
blend_components(alpha, src_b, dest_b),
|
||||
)
|
||||
}
|
||||
|
||||
/// Applies a tint to a color, using the tint color's alpha component as the strength of the tint,
|
||||
/// where 0 means no tint and 255 means full tint. The original color's alpha component is preserved in
|
||||
/// the result. Both the source color and tint color should be 32-bit packed colors in the format
|
||||
/// 0xAARRGGBB.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `color`: the color to be tinted
|
||||
/// * `tint`: the tint to be applied to the color, where the alpha component represents the tint strength
|
||||
///
|
||||
/// returns: the resulting tinted color
|
||||
pub fn tint_argb32(color: u32, tint: u32) -> u32 {
|
||||
let (color_a, color_r, color_g, color_b) = from_argb32(color);
|
||||
let (tint_a, tint_r, tint_g, tint_b) = from_argb32(tint);
|
||||
to_argb32(
|
||||
color_a,
|
||||
blend_components(tint_a, tint_r, color_r),
|
||||
blend_components(tint_a, tint_g, color_g),
|
||||
blend_components(tint_a, tint_b, color_b),
|
||||
)
|
||||
}
|
||||
|
||||
/// Linearly interpolates between two 32-bit packed colors in the format 0xAARRGGBB.
|
||||
///
|
||||
/// # Arguments
|
||||
|
|
Loading…
Reference in a new issue