Class ColorTools
java.lang.Object
com.github.tommyettinger.colorful.pure.ipt.ColorTools
Contains code for manipulating colors as
int
and packed float
values in the IPT color space.
IPT has more perceptually-uniform handling of hue than some other color spaces, like YCwCm, and even
though the version here gives up the complex exponential adjustments to various components that the original IPT
paper used, it still is pretty good at preserving perceptual lightness. In most regards, this is a more
thoroughly-constructed color space than YCwCm, but YCwCm may still be useful because of how it maps to aesthetic
components of color. See ipt(float, float, float, float)
for docs on the I, P, and T channels.-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionstatic float
alpha
(float encoded) Gets the alpha channel value of the given encoded color, as a float from 0.0f to 1.0f, inclusive.static int
alphaInt
(float encoded) Gets the alpha channel value of the given encoded color, as an even int ranging from 0 to 254, inclusive.static float
blot
(float start, float change) Interpolates from the packed float color start towards that color made opaque by change.static float
blue
(float encoded) Gets the blue channel value of the given encoded color, as a float from 0.0f to 1.0f, inclusive.static int
blueInt
(float encoded) Gets the blue channel value of the given encoded color, as an int ranging from 0 to 255, inclusive.static float
darken
(float start, float change) Interpolates from the packed float color start towards black by change.static float
differentiateLightness
(float mainColor, float contrastingColor) Given a packed float IPT colormainColor
and another IPT color that it should be made to contrast with, gets a packed float IPT color with I that should be quite different fromcontrastingColor
's I, but the same chromatic channels and opacity (A and B are likely to be clamped if the result gets close to white or black).static float
dullen
(float start, float change) Brings the chromatic components ofstart
closer to grayscale bychange
(desaturating them).static float
editIPT
(float encoded, float addI, float addP, float addT, float addAlpha) Given a packed float IPT color, this edits its intensity, protan, tritan, and alpha channels by adding the corresponding "add" parameter and then clamping.static float
editIPT
(float encoded, float addI, float addP, float addT, float addAlpha, float mulI, float mulP, float mulT, float mulAlpha) Given a packed float IPT color, this edits its intensity, protan, tritan, and alpha channels by first multiplying each channel by the corresponding "mul" parameter and then adding the corresponding "add" parameter, before clamping.static float
enrich
(float start, float change) Pushes the chromatic components ofstart
away from grayscale by change (saturating them).static float
fade
(float start, float change) Interpolates from the packed float color start towards transparent by change.static float
floatGetHSL
(float hue, float saturation, float lightness, float opacity) Gets a color as an IPT packed float given floats representing hue, saturation, lightness, and opacity.static float
fromHSI
(float packed) Converts from a packed float in HSI format to a packed float in IPT format.static float
fromHSI
(float hue, float saturation, float intensity, float alpha) Converts from hue, saturation, intensity, and alpha components (each ranging from 0 to 1 inclusive) to a packed float color in IPT format.static float
fromRGBA
(float packed) Takes a color encoded as an RGBA8888 packed float and converts to a packed float in the IPT format this uses.static float
fromRGBA
(float r, float g, float b, float a) Takes RGBA components from 0.0 to 1.0 each and converts to a packed float in the IPT format this uses.static float
fromRGBA8888
(int rgba) Takes a color encoded as an RGBA8888 int and converts to a packed float in the IPT format this uses.static float
green
(float encoded) Gets the green channel value of the given encoded color, as a float from 0.0f to 1.0f, inclusive.static int
greenInt
(float encoded) Gets the green channel value of the given encoded color, as an int ranging from 0 to 255, inclusive.static float
hue
(float encoded) Gets the hue of the given encoded color, as a float from 0f (inclusive, red and approaching orange if increased) to 1f (exclusive, red and approaching purple if decreased).static boolean
inGamut
(float packed) Returns true if the given packed float color, as IPT, is valid to convert losslessly back to RGBA.static boolean
inGamut
(float i, float p, float t) Returns true if the given IPT values are valid to convert losslessly back to RGBA.static float
intensity
(float encoded) The "intensity" of the given packed float in IPT format, which is like its lightness; ranges from 0.0f to 1.0f .static float
inverseLightness
(float mainColor, float contrastingColor) Given a packed float IPT colormainColor
and another IPT color that it should be made to contrast with, gets a packed float IPT color with roughly inverted intnsity but the same chromatic channels and opacity (P and T are likely to be clamped if the result gets close to white or black).static float
ipt
(float intens, float protan, float tritan, float alpha) Gets a packed float representation of a color given as 4 float components, here, I (intensity or lightness), P (protan, a chromatic component ranging from greenish to reddish), T (tritan, a chromatic component ranging from bluish to yellowish), and A (alpha or opacity).static float
lessenChange
(float color, float fraction) Makes the additive IPT color stored incolor
cause less of a change when used as a tint, as if it were mixed with neutral gray.static float
lighten
(float start, float change) Interpolates from the packed float color start towards white by change.static float
lightness
(float encoded) static float
limitToGamut
(float packed) Iteratively checks whether the given IPT color is in-gamut, and either brings the color closer to 50% gray if it isn't in-gamut, or returns it as soon as it is in-gamut.static float
limitToGamut
(float i, float p, float t) Iteratively checks whether the given IPT color is in-gamut, and either brings the color closer to 50% gray if it isn't in-gamut, or returns it as soon as it is in-gamut.static float
limitToGamut
(float i, float p, float t, float a) Iteratively checks whether the given IPT color is in-gamut, and either brings the color closer to 50% gray if it isn't in-gamut, or returns it as soon as it is in-gamut.static float
offsetLightness
(float mainColor) Pretty simple; adds 0.5 to the given color's I and wraps it around if it would go above 1.0, then averages that with the original I.static float
protan
(float encoded) The "protan" of the given packed float in IPT format, which when combined with tritan describes the hue and saturation of a color; ranges from 0f to 1f .static float
protanDown
(float start, float change) Interpolates from the packed float color start towards a cooler color (green to blue) by change.static float
protanUp
(float start, float change) Interpolates from the packed float color start towards a warmer color (orange to magenta) by change.static float
randomColor
(Random random) Produces a random packed float color that is always in-gamut (and opaque) and should be uniformly distributed.static float
randomEdit
(float color, long seed, float variance) Makes a quasi-randomly-edited variant on the givencolor
, allowing typically a small amount ofvariance
(such as 0.05 to 0.25) between the given color and what this can return.static float
randomizedColor
(com.github.tommyettinger.random.EnhancedRandom random) Produces a random packed float color that is always opaque and should be uniformly distributed.static float
red
(float encoded) Gets the red channel value of the given encoded color, as a float from 0.0f to 1.0f, inclusive.static int
redInt
(float encoded) Gets the red channel value of the given encoded color, as an int ranging from 0 to 255, inclusive.static float
saturation
(float encoded) Gets the saturation of the given encoded color, as a float ranging from 0.0f to 1.0f, inclusive.static float
subrandomColor
(float r, float g, float b) Limited-use; likerandomColor(Random)
but for cases where you already have three floats (r, g, and b) distributed how you want.static float
toEditedFloat
(float basis, float hue, float saturation, float light, float opacity) Gets a variation on the packed float color basis as another packed float that has its hue, saturation, lightness, and opacity adjusted by the specified amounts.static float
toRGBA
(float packed) Converts a packed float color in the format produced byipt(float, float, float, float)
to a packed float in RGBA format.static int
toRGBA8888
(float packed) Converts a packed float color in the format produced byipt(float, float, float, float)
to an RGBA8888 int.static float
tritan
(float encoded) The "tritan" of the given packed float in IPT format, which when combined with protan describes the hue and saturation of a color; ranges from 0f to 1f .static float
tritanDown
(float start, float change) Interpolates from the packed float color start towards an "artificial" color (between blue and purple) by change.static float
tritanUp
(float start, float change) Interpolates from the packed float color start towards a "natural" color (between green and orange) by change.
-
Constructor Details
-
ColorTools
public ColorTools()
-
-
Method Details
-
ipt
Gets a packed float representation of a color given as 4 float components, here, I (intensity or lightness), P (protan, a chromatic component ranging from greenish to reddish), T (tritan, a chromatic component ranging from bluish to yellowish), and A (alpha or opacity). Intensity should be between 0 and 1, inclusive, with 0 used for very dark colors (almost only black), and 1 used for very light colors (almost only white). Protan and tritan range from 0.0 to 1.0, with grayscale results when both are about 0.5. There's some aesthetic value in changing just one chroma value. When protan is high and tritan is low, the color is more purple/magenta, when both are low it is more bluish, when tritan is high and protan is low, the color tends to be greenish, and when both are high it tends to be orange. When protan and tritan are both near 0.5f, the color is closer to gray. Alpha is the multiplicative opacity of the color, and acts like RGBA's alpha.
This method bit-masks the resulting color's byte values, so any values can technically be given to this as intensity, protan, and tritan, but they will only be reversible from the returned float color to the original I, P, and T values if the original values were in the range thatintensity(float)
,protan(float)
, andtritan(float)
return.- Parameters:
intens
- 0f to 1f, intensity or I component of IPT, with 0.5f meaning "no change" and 1f brighteningprotan
- 0f to 1f, protan or P component of IPT, with 1f more orange, red, or magentatritan
- 0f to 1f, tritan or T component of IPT, with 1f more green, yellow, or redalpha
- 0f to 1f, 0f makes the color transparent and 1f makes it opaque- Returns:
- a float encoding a color with the given properties
-
toRGBA8888
Converts a packed float color in the format produced byipt(float, float, float, float)
to an RGBA8888 int. This format of int can be used with Pixmap and in some other places in libGDX.- Parameters:
packed
- a packed float color, as produced byipt(float, float, float, float)
- Returns:
- an RGBA8888 int color
-
toRGBA
Converts a packed float color in the format produced byipt(float, float, float, float)
to a packed float in RGBA format. This format of float can be used with the standard SpriteBatch and in some other places in libGDX.- Parameters:
packed
- a packed float color, as produced byipt(float, float, float, float)
- Returns:
- a packed float color as RGBA
-
fromRGBA8888
Takes a color encoded as an RGBA8888 int and converts to a packed float in the IPT format this uses.- Parameters:
rgba
- an int with the channels (in order) red, green, blue, alpha; should have 8 bits per channel- Returns:
- a packed float as IPT, which this class can use
-
fromRGBA
Takes a color encoded as an RGBA8888 packed float and converts to a packed float in the IPT format this uses.- Parameters:
packed
- a packed float in RGBA8888 format, with A in the MSB and R in the LSB- Returns:
- a packed float as IPT, which this class can use
-
fromRGBA
Takes RGBA components from 0.0 to 1.0 each and converts to a packed float in the IPT format this uses.- Parameters:
r
- red, from 0.0 to 1.0 (both inclusive)g
- green, from 0.0 to 1.0 (both inclusive)b
- blue, from 0.0 to 1.0 (both inclusive)a
- alpha, from 0.0 to 1.0 (both inclusive)- Returns:
- a packed float as IPT, which this class can use
-
redInt
Gets the red channel value of the given encoded color, as an int ranging from 0 to 255, inclusive.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- an int from 0 to 255, inclusive, representing the red channel value of the given encoded color
-
greenInt
Gets the green channel value of the given encoded color, as an int ranging from 0 to 255, inclusive.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- an int from 0 to 255, inclusive, representing the green channel value of the given encoded color
-
blueInt
Gets the blue channel value of the given encoded color, as an int ranging from 0 to 255, inclusive.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- an int from 0 to 255, inclusive, representing the blue channel value of the given encoded color
-
alphaInt
Gets the alpha channel value of the given encoded color, as an even int ranging from 0 to 254, inclusive. Because of how alpha is stored in libGDX, no odd-number values are possible for alpha.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- an even int from 0 to 254, inclusive, representing the alpha channel value of the given encoded color
-
red
Gets the red channel value of the given encoded color, as a float from 0.0f to 1.0f, inclusive.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- a float from 0.0f to 1.0f, inclusive, representing the red channel value of the given encoded color
-
green
Gets the green channel value of the given encoded color, as a float from 0.0f to 1.0f, inclusive.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- a float from 0.0f to 1.0f, inclusive, representing the green channel value of the given encoded color
-
blue
Gets the blue channel value of the given encoded color, as a float from 0.0f to 1.0f, inclusive.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- a float from 0.0f to 1.0f, inclusive, representing the blue channel value of the given encoded color
-
alpha
Gets the alpha channel value of the given encoded color, as a float from 0.0f to 1.0f, inclusive.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- a float from 0.0f to 1.0f, inclusive, representing the alpha channel value of the given encoded color
-
floatGetHSL
Gets a color as an IPT packed float given floats representing hue, saturation, lightness, and opacity. All parameters should normally be between 0 and 1 inclusive, though any hue is tolerated (precision loss may affect the color if the hue is too large). A hue of 0 is red, progressively higher hue values go to orange, yellow, green, blue, and purple before wrapping around to red as it approaches 1. A saturation of 0 is grayscale, a saturation of 1 is brightly colored, and values close to 1 will usually appear more distinct than values close to 0, especially if the hue is different. A lightness of 0.001f or less is always black (also using a shortcut if this is the case, respecting opacity), while a lightness of 1f is white. Very bright colors are mostly in a band of high-saturation where lightness is 0.5f.- Parameters:
hue
- 0f to 1f, color wheel positionsaturation
- 0f to 1f, 0f is grayscale and 1f is brightly coloredlightness
- 0f to 1f, 0f is black and 1f is whiteopacity
- 0f to 1f, 0f is fully transparent and 1f is opaque- Returns:
- a float encoding a color with the given properties
-
saturation
Gets the saturation of the given encoded color, as a float ranging from 0.0f to 1.0f, inclusive.- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- the saturation of the color from 0.0 (a grayscale color; inclusive) to 1.0 (a bright color, inclusive)
-
lightness
-
hue
Gets the hue of the given encoded color, as a float from 0f (inclusive, red and approaching orange if increased) to 1f (exclusive, red and approaching purple if decreased).- Parameters:
encoded
- a color as a packed float that can be obtained byipt(float, float, float, float)
- Returns:
- The hue of the color from 0.0 (red, inclusive) towards orange, then yellow, and eventually to purple before looping back to almost the same red (1.0, exclusive)
-
intensity
The "intensity" of the given packed float in IPT format, which is like its lightness; ranges from 0.0f to 1.0f . You can edit the intensity of a color withlighten(float, float)
anddarken(float, float)
.- Parameters:
encoded
- a color encoded as a packed float, as byipt(float, float, float, float)
- Returns:
- the intensity value as a float from 0.0f to 1.0f
-
protan
The "protan" of the given packed float in IPT format, which when combined with tritan describes the hue and saturation of a color; ranges from 0f to 1f . If protan is 0f, the color will be cooler, more green or blue; if protan is 1f, the color will be warmer, from magenta to orange. You can edit the protan of a color withprotanUp(float, float)
andprotanDown(float, float)
.- Parameters:
encoded
- a color encoded as a packed float, as byipt(float, float, float, float)
- Returns:
- the protan value as a float from 0.0f to 1.0f
-
tritan
The "tritan" of the given packed float in IPT format, which when combined with protan describes the hue and saturation of a color; ranges from 0f to 1f . If tritan is 0f, the color will be more "artificial", more blue or purple; if tritan is 1f, the color will be more "natural", from green to yellow to orange. You can edit the tritan of a color withtritanUp(float, float)
andtritanDown(float, float)
.- Parameters:
encoded
- a color encoded as a packed float, as byipt(float, float, float, float)
- Returns:
- the tritan value as a float from 0.0f to 1.0f
-
toEditedFloat
public static float toEditedFloat(float basis, float hue, float saturation, float light, float opacity) Gets a variation on the packed float color basis as another packed float that has its hue, saturation, lightness, and opacity adjusted by the specified amounts. Note that this edits the color in HSL space, not IPT! Takes floats representing the amounts of change to apply to hue, saturation, lightness, and opacity; these can be between -1f and 1f. Returns a float that can be used as a packed or encoded color. The float is likely to be different than the result ofipt(float, float, float, float)
unless hue, saturation, lightness, and opacity are all 0. This won't allocate any objects.
The parameters this takes all specify additive changes for a color component, clamping the final values so they can't go above 1 or below 0, with an exception for hue, which can rotate around if lower or higher hues would be used. As an example, if you give this 0.4f for saturation, and the current color has saturation 0.7f, then the resulting color will have 1f for saturation. If you gave this -0.1f for saturation and the current color again has saturation 0.7f, then resulting color will have 0.6f for saturation.- Parameters:
basis
- a packed float color that will be used as the starting point to make the next colorhue
- -1f to 1f, the hue change that can be applied to the new float color (not clamped, wraps)saturation
- -1f to 1f, the saturation change that can be applied to the new float colorlight
- -1f to 1f, the light/brightness change that can be applied to the new float coloropacity
- -1f to 1f, the opacity/alpha change that can be applied to the new float color- Returns:
- a float encoding a variation of basis with the given changes
-
lighten
Interpolates from the packed float color start towards white by change. While change should be between 0f (return start as-is) and 1f (return white), start should be a packed color, as fromipt(float, float, float, float)
. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usingFloatColors.lerpFloatColors(float, float, float)
to lerp towards white. UnlikeFloatColors.lerpFloatColors(float, float, float)
, this keeps the alpha and both chroma of start as-is.- Parameters:
start
- the starting color as a packed floatchange
- how much to go from start toward white, as a float between 0 and 1; higher means closer to white- Returns:
- a packed float that represents a color between start and white
- See Also:
-
darken
Interpolates from the packed float color start towards black by change. While change should be between 0f (return start as-is) and 1f (return black), start should be a packed color, as fromipt(float, float, float, float)
. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usingFloatColors.lerpFloatColors(float, float, float)
to lerp towards black. UnlikeFloatColors.lerpFloatColors(float, float, float)
, this keeps the alpha and both chroma of start as-is.- Parameters:
start
- the starting color as a packed floatchange
- how much to go from start toward black, as a float between 0 and 1; higher means closer to black- Returns:
- a packed float that represents a color between start and black
- See Also:
-
protanUp
Interpolates from the packed float color start towards a warmer color (orange to magenta) by change. While change should be between 0f (return start as-is) and 1f (return fully warmed), start should be a packed color, as fromipt(float, float, float, float)
. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usingFloatColors.lerpFloatColors(float, float, float)
to lerp towards a warmer color. UnlikeFloatColors.lerpFloatColors(float, float, float)
, this keeps the alpha and intensity of start as-is.- Parameters:
start
- the starting color as a packed floatchange
- how much to warm start, as a float between 0 and 1; higher means a warmer result- Returns:
- a packed float that represents a color between start and a warmer color
- See Also:
-
protanDown
Interpolates from the packed float color start towards a cooler color (green to blue) by change. While change should be between 0f (return start as-is) and 1f (return fully cooled), start should be a packed color, as fromipt(float, float, float, float)
. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usingFloatColors.lerpFloatColors(float, float, float)
to lerp towards a cooler color. UnlikeFloatColors.lerpFloatColors(float, float, float)
, this keeps the alpha and intensity of start as-is.- Parameters:
start
- the starting color as a packed floatchange
- how much to cool start, as a float between 0 and 1; higher means a cooler result- Returns:
- a packed float that represents a color between start and a cooler color
- See Also:
-
tritanUp
Interpolates from the packed float color start towards a "natural" color (between green and orange) by change. While change should be between 0f (return start as-is) and 1f (return fully natural), start should be a packed color, as fromipt(float, float, float, float)
. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usingFloatColors.lerpFloatColors(float, float, float)
to lerp towards a more natural color. UnlikeFloatColors.lerpFloatColors(float, float, float)
, this keeps the alpha and intensity of start as-is.- Parameters:
start
- the starting color as a packed floatchange
- how much to change start to a natural color, as a float between 0 and 1; higher means a more natural result- Returns:
- a packed float that represents a color between start and a more natural color
- See Also:
-
tritanDown
Interpolates from the packed float color start towards an "artificial" color (between blue and purple) by change. While change should be between 0f (return start as-is) and 1f (return fully artificial), start should be a packed color, as fromipt(float, float, float, float)
. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usingFloatColors.lerpFloatColors(float, float, float)
to lerp towards a more artificial color. UnlikeFloatColors.lerpFloatColors(float, float, float)
, this keeps the alpha and intensity of start as-is.- Parameters:
start
- the starting color as a packed floatchange
- how much to change start to a bolder color, as a float between 0 and 1; higher means a more artificial result- Returns:
- a packed float that represents a color between start and a more artificial color
- See Also:
-
blot
Interpolates from the packed float color start towards that color made opaque by change. While change should be between 0f (return start as-is) and 1f (return start with full alpha), start should be a packed color, as fromipt(float, float, float, float)
. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usingFloatColors.lerpFloatColors(float, float, float)
to lerp towards transparent. This won't change the intensity, protan, or tritan of the color.- Parameters:
start
- the starting color as a packed floatchange
- how much to go from start toward opaque, as a float between 0 and 1; higher means closer to opaque- Returns:
- a packed float that represents a color between start and its opaque version
- See Also:
-
fade
Interpolates from the packed float color start towards transparent by change. While change should be between 0 (return start as-is) and 1f (return the color with 0 alpha), start should be a packed color, as fromipt(float, float, float, float)
. This is a good way to reduce allocations of temporary Colors, and is a little more efficient and clear than usingFloatColors.lerpFloatColors(float, float, float)
to lerp towards transparent. This won't change the intensity, protan, or tritan of the color.- Parameters:
start
- the starting color as a packed floatchange
- how much to go from start toward transparent, as a float between 0 and 1; higher means closer to transparent- Returns:
- a packed float that represents a color between start and transparent
- See Also:
-
dullen
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 a packed color, as fromipt(float, float, float, float)
. This only changes protan and tritan; it leaves intensity and alpha alone, unlikelessenChange(float, float)
, which usually changes intensity.- Parameters:
start
- the starting color as a packed floatchange
- how much to change start to a desaturated color, as a float between 0 and 1; higher means a less saturated result- Returns:
- a packed float that represents a color between start and a desaturated color
- See Also:
-
enrich
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 a packed color, as fromipt(float, float, float, float)
. This usually changes only protan and tritan, but higher values forchange
can force the color out of the gamut, which this corrects usinglimitToGamut(float, float, float, float)
(and that can change intensity somewhat). If the color stays in-gamut, then intensity won't change; alpha never changes.- Parameters:
start
- the starting color as a packed floatchange
- how much to change start to a saturated color, as a float between 0 and 1; higher means a more saturated result- Returns:
- a packed float that represents a color between start and a saturated color
- See Also:
-
inverseLightness
Given a packed float IPT colormainColor
and another IPT color that it should be made to contrast with, gets a packed float IPT color with roughly inverted intnsity but the same chromatic channels and opacity (P and T are likely to be clamped if the result gets close to white or black). This won't ever produce black or other very dark colors, and also has a gap in the range it produces for intensity values between 0.5 and 0.55. That allows most of the colors this method produces to contrast well as a foreground when displayed on a background ofcontrastingColor
, or vice versa. This will leave the intensity unchanged if the chromatic channels of the contrastingColor and those of the mainColor are already very different. This has nothing to do with the contrast channel of the tweak in ColorfulBatch; where that part of the tweak can make too-similar lightness values further apart by just a little, this makes a modification onmainColor
to maximize its lightness difference fromcontrastingColor
without losing its other qualities.- Parameters:
mainColor
- a packed float color, as produced byipt(float, float, float, float)
; this is the color that will be adjustedcontrastingColor
- a packed float color, as produced byipt(float, float, float, float)
; the adjusted mainColor will contrast with this- Returns:
- a different IPT packed float color, based on mainColor but with potentially very different lightness
-
differentiateLightness
Given a packed float IPT colormainColor
and another IPT color that it should be made to contrast with, gets a packed float IPT color with I that should be quite different fromcontrastingColor
's I, but the same chromatic channels and opacity (A and B are likely to be clamped if the result gets close to white or black). This allows most of the colors this method produces to contrast well as a foreground when displayed on a background ofcontrastingColor
, or vice versa.
This is similar toinverseLightness(float, float)
, but is considerably simpler, and this method will change the lightness of mainColor when the two given colors have close lightness but distant chroma. Because it averages the original I of mainColor with the modified one, this tends to not produce harsh color changes.- Parameters:
mainColor
- a packed IPT float color; this is the color that will be adjustedcontrastingColor
- a packed IPT float color; the adjusted mainColor will contrast with the I of this- Returns:
- a different packed IPT float color, based on mainColor but typically with different lightness
-
offsetLightness
Pretty simple; adds 0.5 to the given color's I and wraps it around if it would go above 1.0, then averages that with the original I. This means light colors become darker, and dark colors become lighter, with almost all results in the middle-range of possible lightness.- Parameters:
mainColor
- a packed IPT float color- Returns:
- a different packed IPT float color, with its I channel changed and limited to the correct gamut
-
lessenChange
Makes the additive IPT color stored incolor
cause less of a change when used as a tint, as if it were mixed with neutral gray. Whenfraction
is 1.0, this returns color unchanged; when fraction is 0.0, it returnsPalette.GRAY
, and when it is in-between 0.0 and 1.0 it returns something between the two. This is meant for things like area of effect abilities that make smaller color changes toward their periphery.- Parameters:
color
- a color that should have its tinting effect potentially weakenedfraction
- how much ofcolor
should be kept, from 0.0 to 1.0- Returns:
- an IPT float color between gray and
color
-
randomEdit
Makes a quasi-randomly-edited variant on the givencolor
, allowing typically a small amount ofvariance
(such as 0.05 to 0.25) between the given color and what this can return. Theseed
should be different each time this is called, and can be obtained from a random number generator to make the colors more random, or can be incremented on each call. If the seed is only incremented or decremented, then this shouldn't produce two similar colors in a row unless variance is very small. The variance affects the I, P, and T of the generated color, and each of those channels can go up or down by the given variance as long as the total distance isn't greater than the variance (this considers P and T extra-wide, going from -1 to 1, while I goes from 0 to 1, but only internally for measuring distance).- Parameters:
color
- a packed float color, as produced byipt(float, float, float, float)
seed
- a long seed that should be different on each call; should not be 0variance
- max amount of difference between the given color and the generated color; always less than 1- Returns:
- a generated packed float color that should be at least somewhat different from
color
-
inGamut
Returns true if the given packed float color, as IPT, is valid to convert losslessly back to RGBA.- Parameters:
packed
- a packed float color as IPT- Returns:
- true if the given packed float color can be converted back and forth to RGBA
-
inGamut
Returns true if the given IPT values are valid to convert losslessly back to RGBA.- Parameters:
i
- intensity channel, as a float from 0 to 1p
- protan channel, as a float from 0 to 1t
- tritan channel, as a float from 0 to 1- Returns:
- true if the given packed float color can be converted back and forth to RGBA
-
limitToGamut
Iteratively checks whether the given IPT color is in-gamut, and either brings the color closer to 50% gray if it isn't in-gamut, or returns it as soon as it is in-gamut.- Parameters:
packed
- a packed float color in IPT format; often this color is not in-gamut- Returns:
- the first color this finds that is between the given IPT color and 50% gray, and is in-gamut
- See Also:
-
limitToGamut
Iteratively checks whether the given IPT color is in-gamut, and either brings the color closer to 50% gray if it isn't in-gamut, or returns it as soon as it is in-gamut. This always produces an opaque color.- Parameters:
i
- intensity component; will be clamped between 0 and 1 if it isn't alreadyp
- protan component; will be clamped between 0 and 1 if it isn't alreadyt
- tritan component; will be clamped between 0 and 1 if it isn't already- Returns:
- the first color this finds that is between the given IPT color and 50% gray, and is in-gamut
- See Also:
-
limitToGamut
Iteratively checks whether the given IPT color is in-gamut, and either brings the color closer to 50% gray if it isn't in-gamut, or returns it as soon as it is in-gamut.- Parameters:
i
- intensity component; will be clamped between 0 and 1 if it isn't alreadyp
- protan component; will be clamped between 0 and 1 if it isn't alreadyt
- tritan component; will be clamped between 0 and 1 if it isn't alreadya
- alpha component; will be clamped between 0 and 1 if it isn't already- Returns:
- the first color this finds that is between the given IPT color and 50% gray, and is in-gamut
- See Also:
-
editIPT
Given a packed float IPT color, this edits its intensity, protan, tritan, and alpha channels by adding the corresponding "add" parameter and then clamping. This returns a different float value (of course, the given float can't be edited in-place). You can give a value of 0 for any "add" parameter you want to stay unchanged. This clamps the resulting color to remain in-gamut, so it should be safe to convert it back to RGBA.- Parameters:
encoded
- a packed float IPT coloraddI
- how much to add to the intensity channel; typically in the -1 to 1 rangeaddP
- how much to add to the protan channel; typically in the -2 to 2 rangeaddT
- how much to add to the tritan channel; typically in the -2 to 2 rangeaddAlpha
- how much to add to the alpha channel; typically in the -1 to 1 range- Returns:
- a packed float IPT color with the requested edits applied to
encoded
-
editIPT
public static float editIPT(float encoded, float addI, float addP, float addT, float addAlpha, float mulI, float mulP, float mulT, float mulAlpha) Given a packed float IPT color, this edits its intensity, protan, tritan, and alpha channels by first multiplying each channel by the corresponding "mul" parameter and then adding the corresponding "add" parameter, before clamping. This means the intensity value is multiplied bymulI
, then hasaddI
added, and then is clamped to the normal range for intensity (0 to 1). This returns a different float value (of course, the given float can't be edited in-place). You can give a value of 0 for any "add" parameter you want to stay unchanged, or a value of 1 for any "mul" parameter that shouldn't change. Note that this manipulates protan and tritan in the -1 to 1 range, so if you multiply by a small number like0.25f
, then this will produce a less-saturated color, and if you multiply by a larger number like4f
, then you will get a much more-saturated color. This clamps the resulting color to remain in-gamut, so it should be safe to convert it back to RGBA.- Parameters:
encoded
- a packed float IPT coloraddI
- how much to add to the intensity channel; typically in the -1 to 1 rangeaddP
- how much to add to the protan channel; typically in the -2 to 2 rangeaddT
- how much to add to the tritan channel; typically in the -2 to 2 rangeaddAlpha
- how much to add to the alpha channel; typically in the -1 to 1 rangemulI
- how much to multiply the intensity channel by; should be non-negativemulP
- how much to multiply the protan channel by; usually non-negative (not always)mulT
- how much to multiply the tritan channel by; usually non-negative (not always)mulAlpha
- how much to multiply the alpha channel by; should be non-negative- Returns:
- a packed float IPT color with the requested edits applied to
encoded
-
fromHSI
Converts from a packed float in HSI format to a packed float in IPT format.- Parameters:
packed
- a packed float in HSI format- Returns:
- a packed float in IPT format
-
fromHSI
Converts from hue, saturation, intensity, and alpha components (each ranging from 0 to 1 inclusive) to a packed float color in IPT format.- Parameters:
hue
- hue, from 0 to 1 inclusive; 0 is red, 0.25 is yellow, 0.75 is bluesaturation
- saturation from 0 (grayscale) to a limit between 0 and 1 depending on intensity (it can be 1 only when intensity is 0.5)intensity
- intensity, or lightness, from 0 (black) to 1 (white)alpha
- alpha transparency/opacity, from 0 (fully transparent) to 1 (fully opaque)- Returns:
- a packed float in IPT format
-
randomColor
Produces a random packed float color that is always in-gamut (and opaque) and should be uniformly distributed.- Parameters:
random
- a Random object (or preferably a subclass of Random, likeLaserRandom
)- Returns:
- a packed float color that is always in-gamut
-
randomizedColor
Produces a random packed float color that is always opaque and should be uniformly distributed. This is named differently fromrandomColor(Random)
to avoid confusion when a class both extends Random and EnhancedRandom.- Parameters:
random
- any subclass of juniper's EnhancedRandom, such as aDistinctRandom
orFourWheelRandom
- Returns:
- a packed float color that is always in-gamut
-
subrandomColor
Limited-use; likerandomColor(Random)
but for cases where you already have three floats (r, g, and b) distributed how you want. This can be somewhat useful if you are using a "subrandom" or "quasi-random" sequence, like the Halton, Sobol, or R3 sequences, to get 3D points and map them to colors. It can also be useful if you want to randomly generate the RGB channels yourself and track the values produced, as you would if you wanted to avoid generating too many colors with high blue, for instance. This approximately maps the r, g, and b parameters to distances on the RGB axes of a rectangular prism, which is stretched and rotated to form the IPT gamut.- Parameters:
r
- red value to use; will be clamped between 0 and 1g
- green value to use; will be clamped between 0 and 1b
- blue value to use; will be clamped between 0 and 1- Returns:
- a packed float color that is always opaque
-