Class ColorUtils

java.lang.Object
com.github.tommyettinger.textra.utils.ColorUtils

public class ColorUtils extends Object
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

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    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 .
    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
    describe(String description)
    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 of start closer to grayscale by change (desaturating them).
    static int
    enrich(int start, float change)
    Pushes the chromatic components of start 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
    This simply looks up key in Colors, 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 original color 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 if power is higher (closer to 1.0f).
    static int
    offsetLightness(int color, float power)
    Gets an "offset color" for the original color, 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.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • 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. The h 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 used
      s - saturation, from 0.0 to 1.0
      l - lightness, from 0.0 to 1.0
      a - 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.0
      g - green, from 0.0 to 1.0
      b - blue, from 0.0 to 1.0
      a - 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. The h 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.0
      s - saturation, from 0.0 to 1.0
      b - brightness, from 0.0 to 1.0
      a - 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.0
      g - green, from 0.0 to 1.0
      b - blue, from 0.0 to 1.0
      a - 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 in HSLA 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 format
      channel - 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 in HSLA 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 format
      channel - 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 int
      e - the end/target color as a packed int
      change - 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. If colors is null or has no items, this returns 256 (a transparent placeholder used by ColorLookup for "no color found"). This is mostly useful in conjunction with IntArray, using its items for colors, typically 0 for offset, and its size for size.
      Parameters:
      colors - an array of RGBA8888 int colors; all should use the same color space
      offset - the index of the first item in colors to use
      size - how many items from colors 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 with color, weight, color, weight.... If colors 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 alternating color, 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 with color, weight, color, weight..., starting at offset in the array and continuing for size indices in the array. The size 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. If colors is null or has no items, or if size <= 0, this returns 0 (fully-transparent black).
      Parameters:
      colors - starting at offset, this should contain alternating color, weight, color, weight... ints
      offset - where to start reading from in colors
      size - how many indices to read from colors; 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 using lerpColors(int, int, float) to lerp towards white. Unlike lerpColors(int, int, float), this keeps the alpha of start as-is.
      Parameters:
      start - the starting color as an RGBA8888 int
      change - 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 using lerpColors(int, int, float) to lerp towards black. Unlike lerpColors(int, int, float), this keeps the alpha of start as-is.
      Parameters:
      start - the starting color as an RGBA8888 int
      change - 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 of start closer to grayscale by change (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 int
      change - 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 of start 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 int
      change - 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 original color 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 if power is higher (closer to 1.0f). It is usually fine for power to be 0.5f . This can look... pretty strange for some input colors, and you may want offsetLightness(int, float) instead.
      Parameters:
      color - the original color as an RGBA8888 int
      power - 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 higher power using more of the offset
    • offsetLightness

      public static int offsetLightness(int color, float power)
      Gets an "offset color" for the original color, 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 call lighten(color, power) or darken(color, power). It is usually fine for power to be 0.5f . This leaves hue alone, and doesn't change saturation much. The lightness measurement is effectively red * 3/8 + green * 1/2 + blue * 1/8.
      Parameters:
      color - the original color as an RGBA8888 int
      power - 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 color
      multiplier - 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 color
      multiplier - 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 uses multiplyAlpha(int, float) internally, so its documentation applies.
      Parameters:
      colors - a 2D int array of RGBA or HSLA colors, none of which can include null arrays
      multiplier - a multiplier to apply to each color's alpha
      Returns:
      colors, after having each item's alpha multiplied
    • describe

      public static int describe(String description)
      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 in Palette will be looked up in Palette.NAMED and tracked; if there is more than one of these color names, the colors will be mixed using unevenMix(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 libGDX Colors use ALL_CAPS, and the colors additionally defined by Palette 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 include Palette.orange and Palette.ORANGE, or Palette.salmon and Palette.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 value 256 (used as a placeholder by ColorLookup).
      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

      public static int lookupInColors(String key)
      This simply looks up key in Colors, 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 are ALL_CAPS in libGDX's Colors collection by default.
      Parameters:
      key - a color name, typically in ALL_CAPS
      Returns:
      the RGBA8888 int color matching the name, or 256 if the name was not found