From 53fc1596890519b4c21d6c08e3890b222ebf6b17 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jan 2025 22:09:10 -0500 Subject: [PATCH] final draft --- .../mapping-strings-to-rgb-colors/index.md | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/content/posts/mapping-strings-to-rgb-colors/index.md b/content/posts/mapping-strings-to-rgb-colors/index.md index 6c9c69a..80d8dba 100644 --- a/content/posts/mapping-strings-to-rgb-colors/index.md +++ b/content/posts/mapping-strings-to-rgb-colors/index.md @@ -43,42 +43,48 @@ func ToRGB(s string) color.RGBA { r := binary.LittleEndian.Uint64(sum[:8]) g := binary.LittleEndian.Uint64(sum[8:16]) b := binary.LittleEndian.Uint64(sum[12:]) - rgb.R = uint8(InterpolateUint64(r, 0, uint64(math.Pow(2, 56)), 0, 64384)) - rgb.G = uint8(InterpolateUint64(g, 0, uint64(math.Pow(2, 56)), 0, 64384)) - rgb.B = uint8(InterpolateUint64(b, 0, uint64(math.Pow(2, 56)), 0, 64384)) + rgb.R = uint8(ScaleUint64(r, 0, uint64(math.Pow(2, 56)), 0, 64384)) + rgb.G = uint8(ScaleUint64(g, 0, uint64(math.Pow(2, 56)), 0, 64384)) + rgb.B = uint8(ScaleUint64(b, 0, uint64(math.Pow(2, 56)), 0, 64384)) rgb.A = uint8(255) return rgb } ``` -`ToRGBA` functions almost identically, with a few small changes. Instead of 7 byte chunks, we use 5 byte chunks and adjust the `Interpolate` call accordingly for the 40 bit chunks. +`ToRGBA` functions almost identically, with a few small changes. Instead of 7 byte chunks, we use 5 byte chunks and adjust the `Scale` call accordingly for the 40 bit chunks. ```go func ToRGBA(s string) color.RGBA { // ... - a := binary.LittleEndian.Uint64(sum[15:]) + // We use Uint32 here because the chunks are smaller and the Uint64 function panics if the input []byte is too short. + a := binary.LittleEndian.Uint32(sum[15:]) // ... - rgba.A = uint8(InterpolateUint64(a, 0, uint64(math.Pow(2, 40)), 0, 64384)) + rgba.A = uint8(ScaleUint64(a, 0, uint64(math.Pow(2, 40)), 0, 64384)) // ... return rgb } ``` -### Interpolation -- Not sure if interpolation is the right technical term -- Using generics +### Scaling +The final bit of magic we need is a way to scale these 64 bit integers down to between 0 and 255 to represent the RGB ( and sometimes A ) values that make up the `image.Color`. Enter the `Scale` function: + ```go -func Interpolate[T constraints.Unsigned](f, inputMin, inputMax, outputMin, outputMax T) T { +func Scale[T constraints.Unsigned | constraints.Float | constraints.Signed](f, inputMin, inputMax, outputMin, outputMax T) T { return (f-(inputMin))*(outputMax-outputMin)/(inputMax-inputMin) + outputMin } + +var ScaleUint64 = Scale[uint64] ``` +This does a bit of relatively straightforward math to smoothly scale the input into the desired range. Not a lot to say about it, it's just math and I don't know much about where it came from. I've had this floating around in various repos for years and I don't have any notes on where I found it. + ## The Results Below is a sample of "lorem ipsum" with each word colored using this algorithm.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

## Possible Improvements -- Provide HSV or HSL color values -- Light/dark mode awareness -- Accessibility. The colors chosen are effectively random with no regard for color schemes, background, display device capability +There's a few places where this code could be meaningfully improved. +- It'd be nice to have HSL/HSV colors as an option. I've personally never been in a situation where RGB wasn't enough to do what I needed, but they exist for a reason. [HSLuv](https://www.hsluv.org/) claims to better capture colors as perceived by the human eye and that sounds pretty neat. +- Accessibility and consistency. Sometimes the color for a word will be almost identical to its background making portions of the text hard or impossible to read. It'd be cool to be able to limit color generation to values within certain ranges of a color palette. This is probably doable with another application of `Scale`. +