{"id":13529161,"url":"https://github.com/tommyettinger/colorful-gdx","last_synced_at":"2025-04-07T05:12:59.507Z","repository":{"id":51253076,"uuid":"225547952","full_name":"tommyettinger/colorful-gdx","owner":"tommyettinger","description":"A libGDX mechanism to manipulate colors in powerful ways","archived":false,"fork":false,"pushed_at":"2025-02-16T11:11:08.000Z","size":151457,"stargazers_count":80,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-31T04:05:52.390Z","etag":null,"topics":["aesthetic","color","libgdx","ycc","yuv"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tommyettinger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-03T06:32:00.000Z","updated_at":"2025-03-06T07:57:00.000Z","dependencies_parsed_at":"2023-11-07T04:35:23.503Z","dependency_job_id":"37d60cc0-6c13-423d-a085-a0dc67b069cf","html_url":"https://github.com/tommyettinger/colorful-gdx","commit_stats":{"total_commits":814,"total_committers":1,"mean_commits":814.0,"dds":0.0,"last_synced_commit":"02fede2e29ed26f0f4b5acf5c5b4d49e66e4d212"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyettinger%2Fcolorful-gdx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyettinger%2Fcolorful-gdx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyettinger%2Fcolorful-gdx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyettinger%2Fcolorful-gdx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tommyettinger","download_url":"https://codeload.github.com/tommyettinger/colorful-gdx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247595335,"owners_count":20963943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aesthetic","color","libgdx","ycc","yuv"],"created_at":"2024-08-01T07:00:33.893Z","updated_at":"2025-04-07T05:12:59.476Z","avatar_url":"https://github.com/tommyettinger.png","language":"Java","funding_links":[],"categories":["Resources","颜色库"],"sub_categories":["Visual Effects","文件同步"],"readme":"![colorful-gdx logo](images/colorful-gdx-logo-name-500x160.png)\n\n# colorful-gdx\nA libGDX mechanism to manipulate colors in powerful ways\n\nColorful is a small library that mostly offers some predefined shaders and code for handling colors differently from the\nnormal way. Why would you want this? There are several shortcomings of the default SpriteBatch shader's color handling,\nspecifically how it handles color tinting with `setColor(float, float, float, float)`:\n\n  - You can use the default setColor() to make an image darker, but never lighter.\n  - The default setColor() can't increase any channel's value; that is, if the red channel is 0, then nothing you do can\n    make red higher.\n  - The ways you can adjust tints don't match any kind of aesthetic way of representing color; you're limited to\n    reducing red, green, and blue by some percentage each.\n\nWe address this in colorful by representing tint colors differently. The library focuses on six color spaces: RGB, IPT,\nYCwCm, CIELAB, Oklab, and HSLuv. The emphasis mostly lies on RGB, Oklab, and HSLuv as the most likely color spaces you\nwould want to use. Most of this library's users will only employ one of these color spaces at a time, and the APIs for\nall the color spaces are extremely similar. You most likely want to use RGB (because it is the most compatible with\nexisting colors), Oklab (because it is the most expressive and makes quite a lot of common color operations more\nintuitive) and/or HSLuv (because it is similar to how users often expect colors to be described). \n\n### RGB\n\nRGB is familiar to almost everyone who works with color on computers; it has a red, a green, and a blue channel, plus\nalpha here. The difference between the way an RGB color tint works with a standard libGDX SpriteBatch, and the way one\nworks here, is that a SpriteBatch is neutral at the value `(1.0, 1.0, 1.0, 1.0)` and can only reduce channels as they go\nlower, while here, a ColorfulBatch is neutral at the value `(0.5, 0.5, 0.5, 1.0)` and can lower channels in the same way\nor raise channels if they go above 0.5. Typically, RGB is used with the `com.github.tommyettinger.colorful.rgb` package,\nwith the `ColorfulBatch` class replacing `SpriteBatch`. The `ColorTools` class in the same package provides various\nRGB-specific color manipulation, while `FloatColors` in the parent package provides non-specific manipulation of colors\nas packed floats (which are the default here). `Palette` has 256 predefined colors from the DawnBringer Aurora palette,\nwhich is well-distributed for almost any pixel art or digital painting, as packed floats that have substantial\ndocumentation. These colors can be accessed with their names via an ObjectFloatMap, `NAMED`, and those names in usefully\nsorted orders as `NAMES_BY_LIGHTNESS` and `NAMES_BY_HUE`. There's also `SimplePalette`, which has fewer named colors\npredefined, but allows specifying edited and/or combined colors using simple `String`s; more on that later.\n\nHere's an aside about those colors as packed floats. Packed float colors may seem somewhat odd at first, but libGDX\nuses them to represent a color in a way that OpenGL can easily handle. They store almost the same info as an RGBA8888\nint color, except that they never use or set one bit in alpha (so they really only have 7 bits of alpha, the most\nsignificant ones), and the RGBA bytes are in reversed order. The conversion from int color to packed float color is very\nefficient thanks to how the JVM (and GWT, with a caveat) handle this operation. GWT, used for the HTML backend in\nlibGDX, actually defaults to a very slow conversion between int bits and float, but provides a way for libGDX (or other\nlibraries) to convert quite efficiently; libGDX does this with its `NumberUtils` class. The `ColorTools` class in each\ncolor space's package provides many ways to manipulate and query packed floats.\n\n`ColorfulBatch` doesn't just provide the option for tints to brighten and darken. It effectively has two batch colors;\none is multiplicative and is called the \"tweak,\" while the regular color is now additive. The changes from the tweak can\nlower a channel's value if the tweak has a value less than 0.5 for that channel, or can raise its value if the tweak\nhas a value greater than 0.5. After the tweak multiplies red, green, and blue, the regular color gets added in (minus\n0.5, so low values in the regular color will subtract from the resulting color). There's standard multiplicative alpha\nin the regular color, and the tweak's alpha channel adjusts lightness contrast (tweak alpha above 0.5 sharpens contrast,\nwhile tweak alpha below 0.5 makes the image puffy or cloudy). Some games may want to use contrast as a way to highlight\nspecific areas, with reduced contrast in \"background\" regions and heightened contrast in important ones. You can combine\nmultiplicative and additive colors creatively to achieve certain effects; while this is easier with the other color\nspaces discussed next, it can be done with RGB as well. Multiplicative colors affect the contribution of the original\ntexture color to the resulting color, so if you had some randomly-generated colorful static and wanted to make it look\nlike leaves, you could use a tweak of `(0.2f, 0.6f, 0.0f, 0.3f)` and a regular color of `(0.3f, 0.8f, 0.0f, 1.0f)` to at\nleast get a bit closer to a leafy background. Because libGDX's `Sprite` class depends on internal details of\n`SpriteBatch` that aren't as useful with `ColorfulBatch`, we have a `ColorfulSprite` class here that allows setting its\ncolor and its tweak, but otherwise can be treated like a Sprite. You can still use a `Sprite` with a `ColorfulBatch`,\nyou just can't set its tweak, so it uses the default (multiplying by 1 for all channels).\n\nStarting in colorful-gdx 0.9.0, there's an optional subclass of `ColorfulBatch` called `TextureArrayColorfulBatch`; it\nis present for the rgb and oklab packages. `TextureArrayColorfulBatch` uses some proposed optimizations for SpriteBatch\nthat so far haven't made their way into libGDX; these optimizations allow rendering from many different `Texture`\ninstances at almost the speed of rendering from one `Texture` with `SpriteBatch`. This can be very useful for larger\ngames that need more than one 4096x4096 atlas texture for any reason. Usage of a `TextureArrayColorfulBatch` is exactly\nthe same as a `ColorfulBatch`, though there are a few extra options when constructing one. You can give a String vertex\nand fragment shader to `createDefaultShader()`, and some options for other shaders are present in each Batch class.\nIn particular, the rgb Batch has `createShaderWithOklabTweak()`, which creates a `ShaderProgram` you can give to the\nconstructor. This special shader allows using \"normal\" RGBA colors, which are easier to display and reason about most of\nthe time, but the tweak and features associated with it from the oklab Batch, using a tweak with L, A, B, and contrast.\nThere's a similar option in the oklab Batch, where you can use the vertex shader String `vertexShaderOklabWithRGBATint`\nwith whatever Oklab fragment shader you need to be able to do the same thing as `createShaderWithOklabTweak()`, but in\nthe oklab package. If you're using the rgb or oklab ColorfulBatch, it should be easy to drop in a\n`TextureArrayColorfulBatch` and see if it works for you.\n\nIf you don't want to use `ColorfulBatch`, then `Shaders` provides `ShaderProgram` generators and GLSL code for shaders\nthat handle various color spaces. There are convenient functions that produce ShaderPrograms, like `makeRGBAShader()`\nand `makeGammaRGBAShader()`, from the GLSL sources `fragmentShaderRGBA` and `fragmentShaderGammaRGBA`, respectively.\nWith these, you still use 50% gray as the neutral value, tinting with white brightens, and tinting with black eliminates\nall color. However, you don't have the \"tweak\" that `ColorfulBatch` has, so there's no contrast adjustment with this.\nYou can use these `ShaderProgram`s with a standard `SpriteBatch` via `setShader()` or a `SpriteBatch` constructor.\n\n### YCwCm\n\nInstead of red, green, blue, and alpha channels, YCwCm uses luma (also called lightness), chromatic warmth, chromatic\nmildness, and alpha. It's the first color space that was implemented here, and it's still not exactly perfect; there's\nno `SimplePalette` here, and sometimes two colors with equivalent luma (as YCwCm calculates it) do not look like they\nhave the same actual lightness. You may want to skip this section and move ahead to Oklab if you intend to use a better\ncolor space from the start, but this also describes some commonly-used classes shared by the color spaces.\n\nThe chromatic channels are only meaningful together, and can be used to get the hue and colorfulness (AKA chroma,\nrelated to saturation) of any individual color. All channels go from `0.0f` to `1.0f` as `float`s,\nand can also be viewed as `int`s from `0` to `255` (`254` for alpha, because it is never an odd number). For luma,\n`0.0f` is black regardless of chromatic channels, and `1.0f` is white, again regardless. Tinting an image with black\nwon't actually make the image all black, unlike the default setColor(), but it will make it much darker. Similarly,\ntinting an image with white will make the image much lighter (unlike the default, where white makes no change). When you\nwant to tint with a neutral color, use `batch.setColor(0.5f, 0.5f, 0.5f, 1.0f)` or `batch.setPackedColor(Palette.GRAY)`;\nthis will make almost no changes to the colors in the textures you draw. For chromatic warmth, `0.0f` is used for colors\nfrom green to blue, while `1.0f` is used for colors from yellow to red. For chromatic mildness, `0.0f` is used for\ncolors from blue to red, while `1.0f` is used for colors from green to yellow. When both warmth and mildness are `0.5f`,\nthat represents a grayscale color, which means it makes no change to the hue or saturation of the image drawn. For\nalpha, it acts exactly like alpha does normally in SpriteBatch.\n\nYCwCm uses a similar naming convention to\n[YcbCr](https://en.wikipedia.org/wiki/YCbCr) or [YCoCg](https://en.wikipedia.org/wiki/YCoCg), both close relatives. The\nreason this library uses YCwCm instead of YCoCg is that it is comparable in computational cost to transform to and from\nRGB, but the luma is somewhat more accurate with YCwCm, and the warmth axis is very useful for aesthetic reasons. As an\nexample of the aesthetic usage, you could move an image into warm or hot hues when a fire is nearby, or into cooler hues\nwhen the weather is freezing. When warmth is very high, it is also nice to be able to move mildness up and down, which\nmakes the color mimic that of fire (going from red embers to yellow sparks, spending more time near orange flame).\n\nThe YCwCm `ColorfulBatch` has a tweak color, like the RGB `ColorfulBatch`, that can be applied to colors\nsomewhat-independently of the regular color that can be set with `setColor()`. Where `setColor()` changes the additive\n(or subtractive) luma, chromatic warmth, and chromatic mildness, plus multiplicative alpha, `setTweak()` changes:\n  - the multiplicative luma (a value from 0.0 to 1.0 that maps to a multiplier from 0.0 to 2.0),\n  - multiplicative chromatic warmth and chromatic mildness (two separate values from 0.0 to 1.0 that map to multipliers\n    from 0.0 to 2.0, but apply to the current warmth or mildness of a pixel as if they are centered on 0.0, not 0.5),\n  - and a contrast adjustment (a value from 0.0 to 1.0 that can make mid-range colors more similar when it is low, or\n    separate bright colors into brighter colors and dark colors into darker colors when it is high).\n\nSome useful things to use the tweak for include:\n  - Setting the chromatic tweaks to 0.0 will make the rendered color grayscale.\n    - If the regular color of a ColorfulBatch isn't gray, then the rendered color will be \"green-scale\" or some other\n      variation of brightness for an existing color.\n  - Setting the chromatic tweaks both to values higher than 0.5 will increase saturation/vividness.\n  - You can set the chromatic tweaks separately, with 0.0 warmth but 0.5 mildness making all colors somewhere between\n    lime and magenta, and 0.0 mildness but 0.5 warmth making all colors between red-orange and cyan.\n    - Adjusting one value randomly in small movements over a small range can liven up an effect that seems too slow.\n  - Reducing the contrast and increasing the color's lightness will make a misty or foggy effect.\n    - You can also change the color to more blue or cyan to make a blue mist, or to pink or purple for \"magic fog.\"\n  - Sharply increasing the contrast and increasing luma tweak, optionally changing the color to something thematic, can\n    help with an electric shock animation when brief frames, randomly spaced, have the adjustments and other frames have\n    darkening or other adjustments.\n\nIn the library, there's the basic shader code in `Shaders.java` (and convenience methods that construct SpriteBatch\nobjects using those shaders), predefined packed-float colors in `ycwcm/Palette.java`, and quite a lot of methods for\nmanipulating those colors as floats in `FloatColors.java` and `ycwcm/ColorTools.java`. The newer method involving a\ntweak requires using a ColorfulBatch instead of a SpriteBatch, but the API is almost the same, and is in\n`ycwcm/ColorfulBatch.java`. If you use a ColorfulBatch, you should also use ColorfulSprite instead of Sprite if you want\nto set a tweak per-sprite, but even a standard Sprite will render correctly.\n\nThe new `GradientTools` class provides some simple methods that write to libGDX `FloatArray` objects, producing a\nsequence of packed float colors (allocating no objects) that go from one color to one or more later colors. Gradients\nproduced by YCwCm should be a little smoother than ones made by the RGB `GradientTools`, and gradients made by IPT_HQ or\nOklab should be even smoother. CIELAB... don't count on it.\n\nThe palette used is a slight adjustment on DawnBringer's Aurora palette, a 256-color palette that gets less attention\nthan his smaller pixel art palettes, but that has excellent coverage of most colors. The names used for colors in it are\nvery similar to the ones chosen for the palette as used in [SquidLib](https://github.com/SquidPony/SquidLib), though\nnot identical; some colors have simpler names, like `Green` instead of `Shamrock Green` or `Yellow` instead of `Lemon`.\nNaming 256 colors, some of them very similar, was not easy, and some choices are probably odd.\n\n### IPT\n\nThe IPT color space is quite similar to YCwCm in some ways, but should have smoother transitions between hues -- after\nall, [that's what it was created for](https://www.researchgate.net/publication/221677980_Development_and_Testing_of_a_Color_Space_IPT_with_Improved_Hue_Uniformity)\nby Ebner and Fairchild in 1998. It has I (intensity, effectively lightness), P (protan, named after protanopia, or\nred-green colorblindness, and corresponding to a cyan-to-red axis), and T (tritan, named after tritanopia, another type\nof colorblindness, and corresponding to a blue-to-yellow axis) channels, plus alpha here. In standard IPT, intensity is\nvery similar for most mid-brightness colors, but falls off suddenly from about 0.3 to 0 in a range of just 1/14 gray to\nblack. Here, we avoid any `Math.pow()` calculations, which evens out the intensity so 1/10 gray has 0.1 intensity. The\nhue and chroma components should be fairly similar, but aren't quite identical. You might want to prefer IPT over YCwCm\nif you want color transitions to look as smooth as possible, and don't mind a tiny bit of extra calculation this needs\nto do internally. Even with the different calculation for intensity/lightness, most colors that are perceptually similar\nin lightness should have somewhat similar intensity here.\n\nThe `com.github.tommyettinger.colorful.ipt` package has parallels to all the classes in the `ycmcw` package, and the\n`ColorfulBatch`, `ColorfulSprite`, and `Palette` classes work almost identically. For ColorfulBatch, this means there's\nan additive color, and a multiplicative \"tweak,\" plus multiplicative alpha in the color and contrast in the tweak.\n\n### IPT_HQ\n\nThis library provides two variants on IPT; the above version in the `com.github.tommyettinger.colorful.ipt` package is\nsimpler to compute, while a newer version in the `com.github.tommyettinger.colorful.ipt_hq` package is more faithful to\nEbner's and Fairchild's paper, and gauges the lightness of colors much more accurately. To get a sense of whether you\nshould use IPT or IPT_HQ, you can compare these palette lists, which are sorted by lightness:\n[the above simpler IPT list](https://tommyettinger.github.io/colorful-gdx/ColorTableValueIPT.html), and\n[the more-involved IPT_HQ list](https://tommyettinger.github.io/colorful-gdx/ColorTableValueIPT_HQ.html).\nIPT has some odd jumps in lightness for red and blue, while IPT_HQ has all perceptually-dark colors in the start of its\nlist. Using IPT_HQ involves some extra operations that aren't always especially fast, especially when on the GPU, and\nthey need to be calculated on many fragments. The IPT_HQ shader is still branch-less and isn't much longer than the IPT\nshader, so the performance dip is likely to be small.\n\n### Oklab\n\nSo, IPT is great when comparing the hues of colors, but isn't optimal when comparing their lightness, or their chroma\n(how close or far from being gray they are). YCwCm isn't great at either. RGB doesn't compare lightness easily at all.\nHow about something new, then? The similar, much newer color space Oklab, by Björn Ottosson, was\nintroduced in [this recent blog post](https://bottosson.github.io/posts/oklab/), and seeks to remedy the mismatch\nbetween hue and the other aspects of color comparison. It has the components L (lightness), A (one chromatic channel,\nroughly describing how cool or warm a color is, with high values closer to red and low values closer to cyan), and\nB (the other chromatic channel, also in a sense describing something like cool to warm, but with high values closer to\nyellow and low values closer to blue). It's like a slightly-rotated version of IPT or YCwCm. The main benefits of Oklab\nare for comparing colors, where you can use a standard Euclidean distance, and for making smooth gradients. It may also\nbe a slight bit faster than IPT_HQ, even though its calculations are extremely similar, because Oklab uses a fast\napproximation of cube root when it's processed by Java, where IPT_HQ uses a slightly slower call to `Math.pow()` with\n0.43 as the exponent. Going in reverse, Oklab can just do `n * n * n` where IPT_HQ needs to use `Math.pow()` again but\nalso preserve the sign of its argument. This difference probably won't be noticeable in practice, since most color\nprocessing will be done on the GPU for the most intensive applications.\n\nAlso, the more I use Oklab, the more I want to keep using Oklab, so future work is probably going to continue on\nimproving features in Oklab or making variants on Oklab for mysterious purposes.\n\nThe exact variety of Oklab isn't 100% faithful to the linked blog post by Ottosson; as he detailed in\n[a later blog post](https://bottosson.github.io/posts/colorpicker/#intermission---a-new-lightness-estimate-for-oklab),\nOklab as it was originally detailed has far too many colors that are nearly-black, and too few that are close to white.\nOttosson devised a high-quality conversion from the dark-color-heavy scale to a more-uniform scale, but computing it\ninvolves quite a bit of code per-pixel, so I used a modified [\"Barron spline\"](https://arxiv.org/abs/2010.09714) that\nalso gets 50% gray to 0.5 L. This is where it should be; L would be at 0.63 before applying the spline. Various other\nchanges have applied across versions to Oklab to get its gamut, or the range of valid colors that can be converted to\nand from RGBA, correct, and it should be now.\n\nThe `com.github.tommyettinger.colorful.oklab` package has parallels to all the classes in the `ipt_hq` package, which\nincludes those in `ycwcm` and `ipt` as well. Its `SimplePalette` is particularly adept at smoothly changing colors.\nIt has a `TextureArrayColorfulBatch` like the rgb package, as mentioned earlier.\n\n### CIELAB\n\nCIELAB, or more accurately, the `1976 CIE L*A*B* Color Space`, is mostly here for completeness; in practice, many common\noperations are done better by the implementation of Oklab here. Both Oklab and CIELAB use L for lightness, A for red vs.\ncyan, and B for yellow vs. blue, but they calculate lots of little things differently, and CIELAB is sometimes smoother.\nHowever, we only store the full gamut information for Oklab (it's stored in a giant String that gets read as bytes),\nwhile CIELAB needs to calculate the approximate gamut for each color as requested. The full gamut is large, and I didn't\nwant to store it multiple times for two similar color spaces, so CIELAB is just generally slower at gamut-related code,\nand less precise. CIELAB is slower at most operations by at least a little bit, relative to Oklab. It does handle some\ngradients more accurately, but most less accurately, so every use case may encounter trade-offs. A notable flaw of the\nimplementation here is that grayscale colors \"tilt\" out of the central line along A=0.5, B=0.5, and around black or very\ndark colors, there isn't any color in-gamut with A=0.5 and B=0.5.\n\nThe `com.github.tommyettinger.colorful.cielab` package has parallels to all the classes in the `ipt_hq` package, which\nincludes those in `ycwcm`, `ipt`, and `oklab` as well. Its `SimplePalette` is just-okay, though it tends to change the\nhue of colors when it lightens or darkens them. As you can see from the description demo (see next), CIELAB has all\nkinds of trouble with blue and similar colors.\n\n### HSLuv\n\nHSLuv is a form of Hue, Saturation, Lightness color space, similar to the standard HSL, but with drastically more-even\nperceptual lightness when L is the same but H and/or S change. As you can see from\n[the HSLuv website](https://www.hsluv.org/), it is very useful for cases such as user-selected colors. It has the nice\nquality that nearly all combinations of H, S, and L are valid colors; only min or max L with high S are technically not\nsupposed to appear, and this can tolerate those colors being entered anyway. Adding to hue rotates from red to orange to\nyellow, and so on; adding to saturation brings the colorfulness closer to the maximum (at 1.0), and adding to lightness,\nwell, lightens. With a `ColorfulBatch`, you can also multiply hue (which is basically useless, and may be changed in a\nfuture release), multiply saturation (which is much more useful, and makes the image more bright/bold or\ndull/desaturated), multiply lightness (which occurs before lightness is added), and adjust contrast (like in the other\ncolor spaces).\n\nLike Oklab, HSLuv uses a modified lightness value so it should match the expectations of RGB very closely. It also uses\na Barron spline, though a different one from Oklab. Unlike Oklab, HSLuv does not need a large precalculated Gamut file,\nbecause its gamut can be calculated with several relatively-simple formulas. I have to give thanks to the community\naround HSLuv, such as [Nathan Sweet's HSLuv code](https://github.com/EsotericSoftware/hsl/blob/main/src/com/esotericsoftware/hsluv/Hsl.java)\nand [Alex Boronine's earlier code](https://github.com/hsluv/hsluv-java); I wouldn't have taken a second look at HSLuv if\nnot for Nathan Sweet's more-efficient conversion code.\n\nThe `com.github.tommyettinger.colorful.hsluv` package has parallels to all the classes in the `ipt_hq` package, which\nincludes those in `ycwcm`, `ipt`, and `oklab` as well. Its `SimplePalette` is not at all shabby.\n\n### Describing Colors\n\nThe `rgb`, `ipt_hq`, `oklab`, `hsluv`, and `cielab` packages have the same classes present for other color spaces, like\nthose in `ipt`, plus an extra palette, `SimplePalette`, with a key extra feature. You can use the\n`SimplePalette.parseDescription(String)`\nmethod to describe a color with a combination of one or more (clearly-named) color names and optionally with adjectives\nlike \"light\", \"dull\", \"darker\", or \"richest\". The predefined colors in SimplePalette for IPT_HQ can be previewed in\n[this list alphabetically](https://tommyettinger.github.io/colorful-gdx/ColorTableSimpleIPT_HQ.html),\n[this list by hue](https://tommyettinger.github.io/colorful-gdx/ColorTableHueSimpleIPT_HQ.html), or\n[this list by lightness](https://tommyettinger.github.io/colorful-gdx/ColorTableValueSimpleIPT_HQ.html). The predefined\ncolors in SimplePalette for Oklab can be previewed in\n[this list alphabetically](https://tommyettinger.github.io/colorful-gdx/ColorTableSimpleOklab.html),\n[this list by hue](https://tommyettinger.github.io/colorful-gdx/ColorTableHueSimpleOklab.html), or\n[this list by lightness](https://tommyettinger.github.io/colorful-gdx/ColorTableValueSimpleOklab.html).\n\nColor names can have a number after them, typically separated by a space or `^` character, that says what weight that\ncolor has when mixing more than one. For example, in versions 0.8.4 and earlier, you could use `red red red blue blue`\nto describe a mix that has 3/2 as much emphasis applied to red as applied to blue. Starting in version 0.8.5, there's\nthe quicker syntax `red 3 blue 2` or even `red 1.5 blue`, which all mean the same thing as `red red red blue blue`.\n\nYou can use [this small libGDX web app](https://tommyettinger.github.io/colorful-gdx/description/) to experiment with\ndifferent descriptions and what they produce. Use the `[` and `]` keys to change modes; there are RGB, Oklab, IPT_HQ,\nCIELAB, comparison, and gradient modes. The comparison mode may be the most useful; it has 4 bars that change color\nusing different color spaces and their SimplePalette transformations. The gradient mode is new, and lets you preview\nOklab gradients between two described colors.\n\n### HSLC\n\nIf for some reason you don't want to use HSLuv, there's a version that has contrast instead of alpha in tints.\n\nHSLC doesn't allow changing alpha, so it may be unsuitable for some tasks, but it does allow smooth hue rotations across\nthe HSL hue range, can saturate or desaturate colors like the two Chroma values can in YCwCm, and has similar luma\nadjustment to YCwCm as well. Like with YCwCm, when you tint with all values equal to 0.5f, then the result color\nshouldn't change. Raising or lowering hue (stored in the red channel) will rotate the hue away from the input color.\nRaising saturation (stored in the green channel) will make the colors more vivid, while decreasing it wll make them\ncloser to grayscale. Raising lightness (stored in the blue channel) will make colors lighter (it can make them brighter\nthan the original color if lightness is greater than 0.5), while lowering it will make colors darker. Contrast affects\nhow rapidly the lightness in input colors changes, so when contrast is high, even slightly different mid-range colors\nwill have stark lightness differences, while when contrast is low, most lightness will be in the mid-range.\n\n### colorful vs. colorful-pure\n\nStarting with version 0.4.0, there are two similar, but not identical, sub-projects in this repo: colorful, which will\nprobably be used more frequently, and colorful-pure, which is more specialized. You want colorful if you already depend\non libGDX (currently on version 1.9.13 or higher); it has the useful `ColorfulBatch` and `ColorfulSprite` classes, and\ncan convert to and from libGDX `Color` objects. If you have a server project, or some other kind of project that doesn't\nhave a dependency on libGDX, then you might want colorful-pure instead. Instead of libGDX, colorful-pure depends on\n[jdkgdxds](https://github.com/tommyettinger/jdkgdxds) for its primitive-backed data structures, and needs Java 8 or\nhigher (colorful needs Java 7 or higher). Both colorful and colorful-pure produce compatible packed float colors when\nthey use the same color space, and even though their `Palette` classes use different data structures, the colors in\nthose palettes are the same. The descriptive color system in `SimplePalette` for the `rgb`, `ipt_hq`, `oklab`, and\n`cielab` packages may be especially useful in colorful-pure.\n\n## Samples\n\nThese all show Oklab changes.\n\nTinting with gray as the color causes no change to the original image.\n![Tinting with gray](https://i.imgur.com/5a4LUDr.png)\n\nTinting with black as the color makes it much darker, but keeps the most colorful areas where they are.\n![Tinting with black](https://i.imgur.com/O5oeoWA.png)\n\nTinting with white as the color makes it much lighter, which isn't possible with the default SpriteBatch shader and color representation.\n![Tinting with white](https://i.imgur.com/Rg4CSrY.png)\n\nIt's a common request to be able to make a Sprite or other texture flash red when a character is hurt; you can tint with the predefined color `Palette.RED` to tint any image to vivid red (including images that have `0.0f` in their red channel).\n![Tinting with red](https://i.imgur.com/BKQ0NwN.png)\n\nTinting with gray, but using a tweak with 0.0 for the chromatic channels A and B makes the image grayscale.\n![Tint with gray, tweak with 0.0 chroma](https://i.imgur.com/RbyjQ3f.png)\n\nTinting with the palette color `WOODLANDS`, but using a tweak with 0.0 for the chromatic channels A and B makes the image \"green-scale.\"\n![Tint with \"Woodlands\", tweak with 0.0 A and B](https://i.imgur.com/iQNumNc.png)\n\nTinting with gray, but using a tweak with 1.0 for the chromatic channels A and B makes the image more saturated.\n![Tint with gray, tweak with 1.0 chroma](https://i.imgur.com/RhyLtFT.png)\n\nTinting with gray, but using a tweak with 0.5 for the chromatic channel A and 0.0 for the chromatic channel B distorts the colors used.\n![Tint with gray, tweak with 0.0 chroma](https://i.imgur.com/Gar7qBU.png)\n\nTinting with the Palette color `THISTLE`, but using a tweak with about 0.6 L and about 0.25 contrast achieves the aforementioned \"magic fog\" effect.\n![Magic Fog](https://i.imgur.com/71c4MNG.png)\n\nTinting with the Palette color `OCHRE` and using a tweak with L=0.43, A=0.14, B=0.258, contrast=0.8125 changes the cartoon-y graphics to a more gritty palette.\n![Gritty Tint](https://i.imgur.com/ZQqRJTA.png)\n\n## Compatibility Notes\n\n### ProGuard\n\nProGuard (on desktop and iOS) doesn't do well with some code here, at least\nout-of-the-box. If you are using colorful or colorful-pure, you need to add\nthis line to your `proguard-rules.pro` file to use ProGuard:\n\n```\n-optimizations !code/simplification/string\n```\n\nThis allows some large data stored in a very long String to be loaded correctly.\n\nNote that this line will be added automatically to the Android R8 configuration,\nwhich is subtly different from ProGuard configuration on any other platform.\nIf you only use ProGuard on Android (where it's really using R8), you don't need\nto change any `.pro` files manually to use colorful or colorful-pure.\n\n### GPU/Shader Incompatibility\n\nOlder versions of colorful-gdx had issues on some particular GPUs, and would show nothing but black textures. This\nhas been fixed since 0.6.0 , and shouldn't affect code using the current version. If it does, please post an issue.\n\n## How to Obtain\n\nUsing the Maven Central dependency is recommended, and Gradle and Maven can both depend on this library using that repository.\n\nTo depend on colorful, which is the main way to use the library and uses libGDX, use:\n\nGradle dependency (`implementation` should be changed to `api` if any other dependencies use `api`):\n```groovy\nimplementation 'com.github.tommyettinger:colorful:0.9.0'\n```\n\nGradle dependency in the HTML project, if present:\n```groovy\nimplementation 'com.github.tommyettinger:colorful:0.9.0:sources'\n```\n\nAnd also for GWT, in your application's `.gwt.xml` file (usually `GdxDefinition.gwt.xml`)\n```xml\n\u003cinherits name=\"com.github.tommyettinger.colorful.colorful\" /\u003e\n```\n\nIf you don't use Gradle, here's the Maven dependency:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.tommyettinger\u003c/groupId\u003e\n  \u003cartifactId\u003ecolorful\u003c/artifactId\u003e\n  \u003cversion\u003e0.9.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nUsing colorful-pure is similar; note that **Most Client-Side Applications Do Not Need These Following Steps**.\n\nGradle dependency (`implementation` should be changed to `api` if any other dependencies use `api`):\n```groovy\nimplementation 'com.github.tommyettinger:colorful-pure:0.9.0'\n```\n\nGradle dependency in the HTML project, if present:\n```groovy\nimplementation 'com.github.tommyettinger:funderby:0.1.2:sources'\nimplementation 'com.github.tommyettinger:digital:0.5.4:sources'\nimplementation 'com.github.tommyettinger:jdkgdxds:1.7.0:sources'\nimplementation 'com.github.tommyettinger:colorful-pure:0.9.0:sources'\n```\n\nAnd also for GWT, in your application's `.gwt.xml` file (usually `GdxDefinition.gwt.xml`)\n```\n\u003cinherits name=\"funderby\" /\u003e\n\u003cinherits name=\"digital\" /\u003e\n\u003cinherits name=\"jdkgdxds\" /\u003e\n\u003cinherits name=\"com.github.tommyettinger.colorful.pure.colorful_pure\" /\u003e\n```\n\nIf you don't use Gradle, here's the Maven dependency (GWT dependencies should be similar to Gradle):\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.tommyettinger\u003c/groupId\u003e\n  \u003cartifactId\u003ecolorful-pure\u003c/artifactId\u003e\n  \u003cversion\u003e0.9.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nThere was a dependency (and GWT inherit) on Juniper in versions prior to 0.9.0; check the history of the README.md for\nhistorical dependencies.\n\nIf you don't use Gradle or Maven, [there are jars here](https://github.com/tommyettinger/colorful-gdx/releases/).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftommyettinger%2Fcolorful-gdx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftommyettinger%2Fcolorful-gdx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftommyettinger%2Fcolorful-gdx/lists"}