Class ColorUtils
java.lang.Object
com.github.tommyettinger.textra.utils.ColorUtils
A few static methods for commonly-used color handling tasks.
This has methods to convert from HSLA colors to RGBA and back again, for hue-changing effects mainly.
It also has
lerpColors(int, int, float)
to blend RGBA colors, and multiplyAlpha(int, float)
to
alter only the alpha channel on an RGBA or HSLA int color.-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionstatic float
channel
(int color, int channel) Given a packed int color and a channel value from 0 to 3, gets the value of that channel as a float from 0.0f to 1.0f .static int
channelInt
(int color, int channel) Given a packed int color and a channel value from 0 to 3, gets the value of that channel as an int from 0 to 255 .static int
darken
(int start, float change) Interpolates from the int color start towards black by change.static int
Parses a color description and returns the approximate color it describes, as an RGBA8888 int color.static int
dullen
(int start, float change) Brings the chromatic components ofstart
closer to grayscale bychange
(desaturating them).static int
enrich
(int start, float change) Pushes the chromatic components ofstart
away from grayscale by change (saturating them).static int
hsb2rgb
(float h, float s, float b, float a) Converts the four HSBA/HSVA components, each in the 0.0 to 1.0 range, to an int in RGBA8888 format.static int
hsl2rgb
(float h, float s, float l, float a) Converts the four HSLA components, each in the 0.0 to 1.0 range, to an int in RGBA8888 format.static int
lerpColors
(int s, int e, float change) Interpolates from the RGBA8888 int color start towards end by change.static int
lighten
(int start, float change) Interpolates from the int color start towards white by change.static int
lookupInColors
(String key) This simply looks upkey
inColors
, returning 256 (fully transparent, extremely dark blue) if no Color exists by that exact name (case-sensitive), or returning the RGBA8888 value of the color otherwise.static int
mix
(int[] colors, int offset, int size) Given several colors, this gets an even mix of all colors in equal measure.static int[][]
multiplyAllAlpha
(int[][] colors, float multiplier) Given any purely-non-null 2D int array representing RGBA or HSLA colors, this multiplies the alpha channel of each color by multiplier, modifying the given array, and returns the changed array for chaining.static float
multiplyAlpha
(float color, float multiplier) Given a packed ABGR float color, this multiplies the alpha of that color by multiplier and returns another float color of the same format passed in.static int
multiplyAlpha
(int color, float multiplier) Given an RGBA8888 or HSLA color as an int, this multiplies the alpha of that color by multiplier and returns another int color of the same format passed in.static int
offset
(int color, float power) Gets an "offset color" for the originalcolor
where high red, green, or blue channels become low values in that same channel, and vice versa, then blends the original with that offset, using more of the offset ifpower
is higher (closer to 1.0f).static int
offsetLightness
(int color, float power) Gets an "offset color" for the originalcolor
, lightening it if it is perceptually dark (under 40% luma by a simplistic measurement) or darkening it if it is perceptually light.static int
rgb2hsb
(float r, float g, float b, float a) Converts the four RGBA components, each in the 0.0 to 1.0 range, to an int in HSBA/HSVA format (hue, saturation, brightness/value, alpha).static int
rgb2hsl
(float r, float g, float b, float a) Converts the four RGBA components, each in the 0.0 to 1.0 range, to an int in HSLA format (hue, saturation, lightness, alpha).static int
unevenMix
(int... colors) Mixes any number of colors with arbitrary weights per-color.static int
unevenMix
(int[] colors, int offset, int size) Mixes any number of colors with arbitrary weights per-color.
-
Constructor Details
-
ColorUtils
public ColorUtils()
-
-
Method Details
-
hsl2rgb
public static int hsl2rgb(float h, float s, float l, float a) Converts the four HSLA components, each in the 0.0 to 1.0 range, to an int in RGBA8888 format. I brought this over from colorful-gdx's FloatColors class. I can't recall where I got the original HSL(A) code from, but there's a strong chance it was written by cypherdare/cyphercove for their color space comparison. Theh
parameter for hue can be lower than 0.0 or higher than 1.0 because the hue "wraps around;" only the fractional part of h is used. The other parameters must be between 0.0 and 1.0 (inclusive) to make sense.- Parameters:
h
- hue, usually from 0.0 to 1.0, but only the fractional part is useds
- saturation, from 0.0 to 1.0l
- lightness, from 0.0 to 1.0a
- alpha, from 0.0 to 1.0- Returns:
- an RGBA8888-format int
-
rgb2hsl
public static int rgb2hsl(float r, float g, float b, float a) Converts the four RGBA components, each in the 0.0 to 1.0 range, to an int in HSLA format (hue, saturation, lightness, alpha). This format is exactly like RGBA8888 but treats what would normally be red as hue, green as saturation, and blue as lightness; alpha is the same.- Parameters:
r
- red, from 0.0 to 1.0g
- green, from 0.0 to 1.0b
- blue, from 0.0 to 1.0a
- alpha, from 0.0 to 1.0- Returns:
- an "HSLA-format" int
-
hsb2rgb
public static int hsb2rgb(float h, float s, float b, float a) Converts the four HSBA/HSVA components, each in the 0.0 to 1.0 range, to an int in RGBA8888 format. I brought this over from colorful-gdx's FloatColors class. I can't recall where I got the original HSL(A) code from, but there's a strong chance it was written by cypherdare/cyphercove for their color space comparison. HSV and HSB are synonyms; it makes a little more sense to call the third channel brightness. Theh
parameter for hue can be lower than 0.0 or higher than 1.0 because the hue "wraps around;" only the fractional part of h is used. The other parameters must be between 0.0 and 1.0 (inclusive) to make sense.- Parameters:
h
- hue, from 0.0 to 1.0s
- saturation, from 0.0 to 1.0b
- brightness, from 0.0 to 1.0a
- alpha, from 0.0 to 1.0- Returns:
- an RGBA8888-format int
-
rgb2hsb
public static int rgb2hsb(float r, float g, float b, float a) Converts the four RGBA components, each in the 0.0 to 1.0 range, to an int in HSBA/HSVA format (hue, saturation, brightness/value, alpha). This format is exactly like RGBA8888 but treats what would normally be red as hue, green as saturation, and blue as brightness/value; alpha is the same. HSV and HSB are synonyms; it makes a little more sense to call the third channel brightness.- Parameters:
r
- red, from 0.0 to 1.0g
- green, from 0.0 to 1.0b
- blue, from 0.0 to 1.0a
- alpha, from 0.0 to 1.0- Returns:
- an "HSBA/HSVA-format" int
-
channel
public static float channel(int color, int channel) Given a packed int color and a channel value from 0 to 3, gets the value of that channel as a float from 0.0f to 1.0f . Channel 0 refers to R in RGBA8888 and H inHSLA
ints, channel 1 refers to G or S, 2 refers to B or L, and 3 always refers to A.- Parameters:
color
- a packed int color in any 32-bit, 4-channel formatchannel
- which channel to access, as an index from 0 to 3 inclusive- Returns:
- the non-packed float value of the requested channel, from 0.0f to 1.0f inclusive
-
channelInt
public static int channelInt(int color, int channel) Given a packed int color and a channel value from 0 to 3, gets the value of that channel as an int from 0 to 255 . Channel 0 refers to R in RGBA8888 and H inHSLA
ints, channel 1 refers to G or S, 2 refers to B or L, and 3 always refers to A.- Parameters:
color
- a packed int color in any 32-bit, 4-channel formatchannel
- which channel to access, as an index from 0 to 3 inclusive- Returns:
- the int value of the requested channel, from 0 to 255 inclusive
-
lerpColors
public static int lerpColors(int s, int e, float change) Interpolates from the RGBA8888 int color start towards end by change. Both start and end should be RGBA8888 ints, and change can be between 0f (keep start) and 1f (only use end). This is a good way to reduce allocations of temporary Colors.- Parameters:
s
- the starting color as a packed inte
- the end/target color as a packed intchange
- how much to go from start toward end, as a float between 0 and 1; higher means closer to end- Returns:
- an RGBA8888 int that represents a color between start and end
-
mix
public static int mix(int[] colors, int offset, int size) Given several colors, this gets an even mix of all colors in equal measure. Ifcolors
is null or has no items, this returns 256 (a transparent placeholder used byColorLookup
for "no color found"). This is mostly useful in conjunction withIntArray
, using itsitems
for colors, typically 0 for offset, and itssize
for size.- Parameters:
colors
- an array of RGBA8888 int colors; all should use the same color spaceoffset
- the index of the first item incolors
to usesize
- how many items fromcolors
to use- Returns:
- an even mix of all colors given, as an RGBA8888 int color
-
unevenMix
public static int unevenMix(int... colors) Mixes any number of colors with arbitrary weights per-color. Takes an array of varargs of alternating ints representing colors and weights, as withcolor, weight, color, weight...
. Ifcolors
is null or has no items, this returns 0 (fully-transparent black). Each color should be an RGBA8888 int, and each weight should be greater than 0.- Parameters:
colors
- an array or varargs that should contain alternatingcolor, weight, color, weight...
ints- Returns:
- the mixed color, as an RGBA8888 int
-
unevenMix
public static int unevenMix(int[] colors, int offset, int size) Mixes any number of colors with arbitrary weights per-color. Takes an array of alternating ints representing colors and weights, as withcolor, weight, color, weight...
, starting atoffset
in the array and continuing forsize
indices in the array. Thesize
should be an even number 2 or greater, otherwise it will be reduced by 1. The weights can be any non-negative int values; this method handles normalizing them internally. Each color should an RGBA8888 int, and each weight should be greater than 0. Ifcolors
is null or has no items, or if size <= 0, this returns 0 (fully-transparent black).- Parameters:
colors
- starting atoffset
, this should contain alternatingcolor, weight, color, weight...
intsoffset
- where to start reading from incolors
size
- how many indices to read fromcolors
; must be an even number- Returns:
- the mixed color, as an RGBA8888 int
-
lighten
public static int lighten(int start, float change) Interpolates from the int color start towards white by change. While change should be between 0f (return start as-is) and 1f (return white), start should be an RGBA8888 color. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usinglerpColors(int, int, float)
to lerp towards white. UnlikelerpColors(int, int, float)
, this keeps the alpha of start as-is.- Parameters:
start
- the starting color as an RGBA8888 intchange
- how much to go from start toward white, as a float between 0 and 1; higher means closer to white- Returns:
- an RGBA8888 int that represents a color between start and white
- See Also:
-
darken
public static int darken(int start, float change) Interpolates from the int color start towards black by change. While change should be between 0f (return start as-is) and 1f (return black), start should be an RGBA8888 color. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usinglerpColors(int, int, float)
to lerp towards black. UnlikelerpColors(int, int, float)
, this keeps the alpha of start as-is.- Parameters:
start
- the starting color as an RGBA8888 intchange
- how much to go from start toward black, as a float between 0 and 1; higher means closer to black- Returns:
- an RGBA8888 int that represents a color between start and black
- See Also:
-
dullen
public static int dullen(int start, float change) Brings the chromatic components ofstart
closer to grayscale bychange
(desaturating them). While change should be between 0f (return start as-is) and 1f (return fully gray), start should be an RGBA8888 int color. This leaves alpha alone.
The algorithm used is from here.- Parameters:
start
- the starting color as an RGBA8888 intchange
- how much to change start to a desaturated color, as a float between 0 and 1; higher means a less saturated result- Returns:
- an RGBA8888 int that represents a color between start and a desaturated color
- See Also:
-
enrich
public static int enrich(int start, float change) Pushes the chromatic components ofstart
away from grayscale by change (saturating them). While change should be between 0f (return start as-is) and 1f (return maximally saturated), start should be an RGBA8888 int color.
The algorithm used is from here.- Parameters:
start
- the starting color as an RGBA8888 intchange
- how much to change start to a saturated color, as a float between 0 and 1; higher means a more saturated result- Returns:
- an RGBA8888 int that represents a color between start and a saturated color
- See Also:
-
offset
public static int offset(int color, float power) Gets an "offset color" for the originalcolor
where high red, green, or blue channels become low values in that same channel, and vice versa, then blends the original with that offset, using more of the offset ifpower
is higher (closer to 1.0f). It is usually fine forpower
to be 0.5f . This can look... pretty strange for some input colors, and you may wantoffsetLightness(int, float)
instead.- Parameters:
color
- the original color as an RGBA8888 intpower
- between 0.0f and 1.0f, this is how heavily the offset color should factor in to the result- Returns:
- a mix between
color
and its offset, with higherpower
using more of the offset
-
offsetLightness
public static int offsetLightness(int color, float power) Gets an "offset color" for the originalcolor
, lightening it if it is perceptually dark (under 40% luma by a simplistic measurement) or darkening it if it is perceptually light. This essentially uses the lightness to determine whether to calllighten(color, power)
ordarken(color, power)
. It is usually fine forpower
to be 0.5f . This leaves hue alone, and doesn't change saturation much. The lightness measurement is effectivelyred * 3/8 + green * 1/2 + blue * 1/8
.- Parameters:
color
- the original color as an RGBA8888 intpower
- between 0.0f and 1.0f, this is how much this should either lighten or darken the result- Returns:
- a variant on
color
, either lighter or darker depending on its original lightness
-
multiplyAlpha
public static int multiplyAlpha(int color, float multiplier) Given an RGBA8888 or HSLA color as an int, this multiplies the alpha of that color by multiplier and returns another int color of the same format passed in. This clamps the alpha if it would go below 0 or above 255, and leaves the RGB or HSL channels alone.- Parameters:
color
- an RGBA8888 or HSLA colormultiplier
- a multiplier to apply to color's alpha- Returns:
- another color of the same format as the one given, with alpha multiplied
-
multiplyAlpha
public static float multiplyAlpha(float color, float multiplier) Given a packed ABGR float color, this multiplies the alpha of that color by multiplier and returns another float color of the same format passed in. This clamps the alpha if it would go below 0 or above 255, and leaves the RGB channels alone.- Parameters:
color
- an RGBA8888 or HSLA colormultiplier
- a multiplier to apply to color's alpha- Returns:
- another color of the same format as the one given, with alpha multiplied
-
multiplyAllAlpha
public static int[][] multiplyAllAlpha(int[][] colors, float multiplier) Given any purely-non-null 2D int array representing RGBA or HSLA colors, this multiplies the alpha channel of each color by multiplier, modifying the given array, and returns the changed array for chaining. This usesmultiplyAlpha(int, float)
internally, so its documentation applies.- Parameters:
colors
- a 2D int array of RGBA or HSLA colors, none of which can include null arraysmultiplier
- a multiplier to apply to each color's alpha- Returns:
- colors, after having each item's alpha multiplied
-
describe
Parses a color description and returns the approximate color it describes, as an RGBA8888 int color. Color descriptions consist of one or more alphabetical words, separated by non-alphanumeric characters (typically spaces and/or hyphens, though the underscore is treated as a letter). Any word that is the name of a color inPalette
will be looked up inPalette.NAMED
and tracked; if there is more than one of these color names, the colors will be mixed usingunevenMix(int[], int, int)
, or if there is just one color name, then the corresponding color will be used. A number can be present after a color name (separated by any non-alphanumeric character(s) other than the underscore); if so, it acts as a positive weight for that color when mixed with other named colors. The recommended separator between a color name and its weight is the space' '
, but other punctuation like':'
, or whitespace, is usually valid. Note that in some contexts, color descriptions shouldn't contain square brackets, curly braces, or the chars@%?^=.
, because they can have unintended effects on the behavior of markup. You can also repeat a color name to increase its weight, as in "red red blue".
The special adjectives "light" and "dark" change the lightness of the described color; likewise, "rich" and "dull" change the saturation (how different the color is from grayscale). All of these adjectives can have "-er" or "-est" appended to make their effect twice or three times as strong. Technically, the chars appended to an adjective don't matter, only their count, so "lightaa" is the same as "lighter" and "richcat" is the same as "richest". There's an unofficial fourth level as well, used when any 4 characters are appended to an adjective (as in "darkmost"); it has four times the effect of the original adjective. There are also the adjectives "bright" (equivalent to "light rich"), "pale" ("light dull"), "deep" ("dark rich"), and "weak" ("dark dull"). These can be amplified like the other four, except that "pale" goes to "paler", "palest", and then to "palemax" or (its equivalent) "palemost", where only the word length is checked.
Note that while adjectives are case-insensitive, color names are not. Because the colors defined in libGDXColors
use ALL_CAPS, and the colors additionally defined byPalette
use lower case and are always one word, there are a few places where two different colors are defined by names that only differ in case. Examples includePalette.orange
andPalette.ORANGE
, orPalette.salmon
andPalette.SALMON
.
If part of a color name or adjective is invalid, it is not considered; if the description is empty or fully invalid, this returns the RGBA8888 int value256
(used as a placeholder byColorLookup
).
Examples of valid descriptions include "blue", "dark green", "DULLER RED", "peach pink", "indigo purple mauve", "lightest, richer apricot-olive", "BRIGHT GOLD", "palest cyan blue", "Deep fern black", "weakmost celery", "LIGHTMOST rich MAROON 2 indigo 3", "red:3 orange", and "dark deep (blue 7) (cyan 3)".- Parameters:
description
- a color description, as a String matching the above format- Returns:
- an RGBA8888 int color as described
-
lookupInColors
This simply looks upkey
inColors
, returning 256 (fully transparent, extremely dark blue) if no Color exists by that exact name (case-sensitive), or returning the RGBA8888 value of the color otherwise. All color names areALL_CAPS
in libGDX's Colors collection by default.- Parameters:
key
- a color name, typically inALL_CAPS
- Returns:
- the RGBA8888 int color matching the name, or
256
if the name was not found
-