Convert hex to RGB

Hello,

Maybe someone can help me with this specific task.

I’m wondering how can I convert a hex color to a slice of integers.

input: #ffffff
output: 255,255,255

I need to do it in a template file (html), not in a SCSS file.

I need it to compare colors and decide if a color is suitable or not.

Any help would be appreciated.

I am not aware of a way to perform such a conversion directly in Hugo.

1 Like

Hi! I guess JavaScript is a good option here.

1 Like

That would be an option, but would be my last resort.

Anyway, now I have this partial:

{{ $c := . }}
{{ $conv := slice "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" }}
{{ $val := 0 }}
{{ $out := slice }}
{{ range $i, $c := ( slice (substr $c 1 1) (substr $c 2 1) (substr $c 3 1) (substr $c 4 1) (substr $c 5 1) (substr $c 6 1) ) }}
  {{ $mod := mod $i 2 }}
  {{ $dec := 0 }}
  {{ range $j, $v := $conv }}
    {{ if eq $v $c }}{{$dec = $j}}{{ end }}
  {{ end }}
  {{ $dec }}
  {{ $val = add $val ( mul $dec ( cond (eq $mod 0) 16 1 ) ) }}
  {{ if $mod }}{{ $out = $out | append $val}}{{ $val = 0}}{{end}}
{{ end }}
{{ return $out }}

And this is how I use it:

{{ partial "color/hex-to-rgb" "#bbbbbb" }}

But I don’t like this solution. I’m hoping someone can help me find a better one. Or at least make mine better.

1 Like

Why ? It works, no ?

And I’ll borrow this, nice partial for my use case. Thanks.

It’s slow - if you run it 2000 times it will increase your build by near a second.
But you can use partialCached if your use case benefits from it.

But yes, it works.

I’m glad you liked it!

you could directly split the string, and use after to exclude the # character.

--{{ $c := . }}
{{ $conv := slice "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" }}
{{ $val := 0 }}
{{ $out := slice }}
++{{ range $i, $c := after 1 (split . "")  }}
--{{ range $i, $c := ( slice (substr $c 1 1) (substr $c 2 1) (substr $c 3 1) (substr $c 4 1) (substr $c 5 1) (substr $c 6 1) ) }}
  {{ $mod := mod $i 2 }}
  {{ $dec := 0 }}
  {{ range $j, $v := $conv }}
    {{ if eq $v $c }}{{$dec = $j}}{{ end }}
  {{ end }}
  {{ $dec }}
  {{ $val = add $val ( mul $dec ( cond (eq $mod 1) 16 1 ) ) }}
  {{ if $mod }}{{ $out = $out | append $val}}{{ $val = 0}}{{end}}
{{ end }}
{{ return $out }}

i dont know it’s going to improve the speed or not.

1 Like

What you’re doing is probably the best approach today. I would definitely use partialCached for this.

Would it be helpful if we added a hexDecode function? {{ $r := hexDecode "c0" }}

As shown by the OP there is a need for such a function. So +1.

The speed is almost the same, but it’s cleaner and works for colors with alpha like #ffffffff
But using a map in the conversion improved the performance.
Here is the updated version and thanks for the suggestion!

{{ $convMap := dict "0" 0 "1" 1 "2" 2 "3" 3 "4" 4 "5" 5 "6" 6 "7" 7 "8" 8 "9" 9 "a" 10 "b" 11 "c" 12 "d" 13 "e" 14 "f" 15 }}
{{ $val := 0 }}
{{ $out := slice }}
{{ range $i, $c := split (substr . 1) "" }}
  {{ $mod := mod $i 2 }}
  {{ $dec := index $convMap $c }}
  {{ $val = add $val ( mul $dec ( cond (eq $mod 0) 16 1 ) ) }}
  {{ if $mod }}{{ $out = $out | append $val}}{{ $val = 0}}{{end}}
{{ end }}
{{ return $out }}
3 Likes

Thanks for your help.

Yes, the function hexDecode would help! So +1 for that.

But I’m wondering if a more specialized function, related to colors - would also be interesting.

My use case is very specific, I’m not sure if this would create unnecessary noise.

Let me explain my use case:

I’m using Bootstrap in my theme. An editor can change the Bootstrap primary color variable in a Data file (theme.yaml).

Some sections of my website use the primary or secondary color as background. I want to know if it’s safe to use a btn-primary, btn-secondary or btn-danger in a specific section. If not, I want to decide which class would be better to use as a fallback, btn-light or btn-dark.

The logic is the same of this Bootstrap SCSS function:

@function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) {
  $r: red($color);
  $g: green($color);
  $b: blue($color);

  $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;

  @if ($yiq >= $yiq-contrasted-threshold) {
    @return $dark;
  } @else {
    @return $light;
  }
}

Adding color-specific template functions is a bit of a stretch. Let’s stick with hex encoding enhancements for now.

I have a working implementation in a dev branch, and I’m seeing about a 10x improvement in speed versus your partial above. I’ll try to get a PR submitted in the few days.

PS - Your partial has a bug. Use (eq $mod 0) instead of (eq $mod 1).

1 Like

In my efforts to learn Go I worked on a colour palette generator app a couple of years ago - the code is horrible but it’s here - Palegen

It relies on the go-colorful library which may be worth a look if you want to manipulate colours in Go.

(Wish I’d had the time and energy to push on and polish it, but it’s getting eclipsed by improvements in CSS and now it seems Hugo as well :))