final draft

main^2
unknown 4 weeks ago
parent 87d9a2cbd9
commit 53fc159689

@ -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.
<p><span style="color:#FD9FAB;">Lorem</span> <span style="color:#D35EC5;">ipsum</span> <span style="color:#45EEDD;">dolor</span> <span style="color:#3A2FE8;">sit</span> <span style="color:#04B55A;">amet</span>, <span style="color:#883581;">consectetur</span> <span style="color:#31CA93;">adipiscing</span> <span style="color:#99461B;">elit</span>, <span style="color:#000AF1;">sed</span> <span style="color:#899099;">do</span> <span style="color:#7B05AB;">eiusmod</span> <span style="color:#F0B186;">tempor</span> <span style="color:#3D1519;">incididunt</span> <span style="color:#93B1CD;">ut</span> <span style="color:#8333C5;">labore</span> <span style="color:#846002;">et</span> <span style="color:#81BB0B;">dolore</span> <span style="color:#E3DDD1;">magna</span> <span style="color:#877C09;">aliqua</span>. <span style="color:#CB6967;">Ut</span> <span style="color:#B38347;">enim</span> <span style="color:#4B8A53;">ad</span> <span style="color:#078AC6;">minim</span> <span style="color:#D2F7E3;">veniam</span>, <span style="color:#6BD5A2;">quis</span> <span style="color:#2B37D2;">nostrud</span> <span style="color:#C592D6;">exercitation</span> <span style="color:#0EB9D1;">ullamco</span> <span style="color:#9BC026;">laboris</span> <span style="color:#872CC2;">nisi</span> <span style="color:#93B1CD;">ut</span> <span style="color:#7DB82B;">aliquip</span> <span style="color:#1CED95;">ex</span> <span style="color:#C0504C;">ea</span> <span style="color:#5DA8B5;">commodo</span> <span style="color:#B762A6;">consequat</span>. <span style="color:#2FCB06;">Duis</span> <span style="color:#EADF81;">aute</span> <span style="color:#0602B8;">irure</span> <span style="color:#45EEDD;">dolor</span> <span style="color:#5E0D47;">in</span> <span style="color:#8B2DEF;">reprehenderit</span> <span style="color:#5E0D47;">in</span> <span style="color:#790B62;">voluptate</span> <span style="color:#7486E8;">velit</span> <span style="color:#33E7F2;">esse</span> <span style="color:#DE099F;">cillum</span> <span style="color:#81BB0B;">dolore</span> <span style="color:#C514CD;">eu</span> <span style="color:#B4B15A;">fugiat</span> <span style="color:#93AA9C;">nulla</span> <span style="color:#83967C;">pariatur</span>. <span style="color:#EDD318;">Excepteur</span> <span style="color:#580A2A;">sint</span> <span style="color:#7DC184;">occaecat</span> <span style="color:#BCEEAB;">cupidatat</span> <span style="color:#EA0503;">non</span> <span style="color:#0AC6DC;">proident</span>, <span style="color:#90C0A3;">sunt</span> <span style="color:#5E0D47;">in</span> <span style="color:#0C0B4B;">culpa</span> <span style="color:#B0E1D5;">qui</span> <span style="color:#F8F0B6;">officia</span> <span style="color:#FFF0B6;">deserunt</span> <span style="color:#115AE8;">mollit</span> <span style="color:#6EC31F;">anim</span> <span style="color:#10B00E;">id</span> <span style="color:#8ADFA4;">est</span> <span style="color:#7EBB61;">laborum</span>. </p>
## 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`.

Loading…
Cancel
Save