# RuneColor

Easily convert RS2 HSL to/from(approximate) RGB

### The problem

We often need to approximate a 16-bit RS2 HSL color given an RGB.

Typically, people simply used a direct translation from RGB to HSL, with a function like:

```fun rgbToRS2HSL(r: Int, g: Int, b: Int): Short {
val hsb = Color.RGBtoHSB(r, g, b, null)
val hue = hsb[0]
val saturation = hsb[1]
val brightness = hsb[2]
val encodedHue = (hue * 63F).toInt() // to 6-bits
val encodedSaturation = (saturation * 7F).toInt() // to 3-bits
val encodedBrightness = (brightness * 127F).toInt() // to 7-bits
return ((encodedHue shl 10) + (encodedSaturation shl 7) + encodedBrightness).toShort()
}```

This will then produce a result, for example:

```val redHSL = rgbToRS2HSL(255, 0, 0)
println(redHSL) // HSL 1023, which is RGB color #ff0000```

The problem is, within the RuneScape world, such a color does not actually exist, making for strange visuals:

### The solution

`RuneColor` allows you to easily build and search an RS2 color palette for the closest match to an RGB color.

```val palette = RS2CacheHSLColorPalette.load("cache")

val redHSL = palette.closest(255, 0, 0).first() // HSLColor(hsl=960)
println("\${redHSL.hsl}(#\${redHSL.rgb.toString(16)})") // 960(#ff0202)```

Using the HSL color we calculated with `RuneColor` (`960`), you can see it looks great when applied in-game:

### Under the hood

Under the hood, by default `RuneColor` by default loads all game model’s face colors to use as the search palette.

This color palette is mapped into RGB, and then sorted
by CIEDE2000 to find the closest matching RS2 HSL colors for
the given RGB color.

It’s possible and often that you might want to use a limited color palette, which you can easily pass a `ShortArray` to
create:

`val palette = RS2HSLColorPalette(shortArray)`

Or you can pass a `vararg Int`:

`val palette = RS2HSLColorPalette(1, 2, 3, 4, 5, ...)`

View Github