Convert hexadecimal color to decimal RGB values in UNIX shell script
Asked Answered
D

6

12

I'm sure someone has already solved this problem: what is an easy and portable way to convert a hex color value (anything from 000000 to FFFFFF) to 3 decimal values from 0 to 255. (If you're not familiar with how colors are traditionally represented in HTML, the first two hex digits are the first decimal number, and so forth.)

Dehypnotize answered 31/8, 2011 at 6:16 Comment(0)
S
1

If you need a POSIX compatible version of this script that handles more valid CSS hex color formats (ie: 4-part with alpha channel #AABBCCDD, 3 char shortcuts #FFF), this should do the trick:

#!/bin/sh
##? ~/bin/hex2rgb - convert color hex to rgb
# '#C0FFEE' => 192 255 238
# 'DEADBEEF' => 222 173 190 239
# 'fab' => 255 170 187
__hex2rgb() {
  # reset $1 to scrubbed hex: '#01efa9' becomes '01EFA9'
  set -- "$(echo "$1" | tr -d '#' | tr '[:lower:]' '[:upper:]')"
  START=0
  STR=
  while (( START < ${#1} )); do
    # double each char under len 6 : FAB => FFAABB
    if (( ${#1} < 6 )); then
      STR="$(printf "${1:${START}:1}%.0s" 1 2)"
      (( START += 1 ))
    else
      STR="${1:${START}:2}"
      (( START += 2 ))
    fi
    echo "ibase=16; ${STR}" | bc
  done
  unset START STR
}
__hex2rgb "$@"
Substitute answered 5/3, 2023 at 15:56 Comment(1)
Very impressive!Dehypnotize
R
22
$ cat hexrgb.sh
#!/bin/bash
hex="11001A"
printf "%d %d %d\n" 0x${hex:0:2} 0x${hex:2:2} 0x${hex:4:2}

$ ./hexrgb.sh
17 0 26

If you are not willing to use bash for substring expansion, I'd still use printf for the conversion.

Resnatron answered 31/8, 2011 at 7:49 Comment(1)
More elegant, this.Arvell
G
8

You can use a script like:

#!/bin/sh
# hextorgb.sh
hexinput=`echo $1 | tr '[:lower:]' '[:upper:]'`  # uppercase-ing
a=`echo $hexinput | cut -c-2`
b=`echo $hexinput | cut -c3-4`
c=`echo $hexinput | cut -c5-6`

r=`echo "ibase=16; $a" | bc`
g=`echo "ibase=16; $b" | bc`
b=`echo "ibase=16; $c" | bc`

echo $r $g $b
exit 0

and use it like:

./hextorgb.sh "11001A"

resulting in output like:

17 0 26

It can be improved by testing for arguments and so on, but it does what you want.

Grenier answered 31/8, 2011 at 7:21 Comment(3)
Small note on bc; the hex input data must be uppercase. Else it'll bite you in the ass down the line when you give it ff which is interpreted as the variable ff, which isn't set so it gives you 0.Resnatron
thanks, i'll correct that. I only wanted to demonstrate the transformation, script can by improved.Grenier
To get this to work on my machine I had to change $0 to $1Urology
V
1
#!/usr/bin/env bash

hex2rgb() {
    hex=$(echo "${1^^}" | sed 's/#//g')

    a=$(echo $hex | cut -c-2)
    b=$(echo $hex | cut -c3-4)
    c=$(echo $hex | cut -c5-6)

    r=$(echo "ibase=16; $a" | bc)
    g=$(echo "ibase=16; $b" | bc)
    b=$(echo "ibase=16; $c" | bc)

    echo ${1^^}
    echo $r $g $b
}

hex2rgb "#FF0000"
hex2rgb "#00FF00"
hex2rgb "#0000FF"
Viridissa answered 26/4, 2019 at 19:32 Comment(1)
Welcome on StackOverflow, while this may be the correct answer, you should be leaving a little insight/ explanation of what you have done here to make it a quality answer which will help others understand the root cause of problem.Kolosick
S
1

If you need a POSIX compatible version of this script that handles more valid CSS hex color formats (ie: 4-part with alpha channel #AABBCCDD, 3 char shortcuts #FFF), this should do the trick:

#!/bin/sh
##? ~/bin/hex2rgb - convert color hex to rgb
# '#C0FFEE' => 192 255 238
# 'DEADBEEF' => 222 173 190 239
# 'fab' => 255 170 187
__hex2rgb() {
  # reset $1 to scrubbed hex: '#01efa9' becomes '01EFA9'
  set -- "$(echo "$1" | tr -d '#' | tr '[:lower:]' '[:upper:]')"
  START=0
  STR=
  while (( START < ${#1} )); do
    # double each char under len 6 : FAB => FFAABB
    if (( ${#1} < 6 )); then
      STR="$(printf "${1:${START}:1}%.0s" 1 2)"
      (( START += 1 ))
    else
      STR="${1:${START}:2}"
      (( START += 2 ))
    fi
    echo "ibase=16; ${STR}" | bc
  done
  unset START STR
}
__hex2rgb "$@"
Substitute answered 5/3, 2023 at 15:56 Comment(1)
Very impressive!Dehypnotize
S
0

I know this question is quite old but to add an anecdote;

alternatively, if you wanted to convert rgb to hex you could do a little something like:

#!/bin/sh
# rgbtohex.sh
f="$1,"
focus=0
start=0
until [ "$limit" == "3" ]
  do
    focus=$((focus+1))
    if [ "${f:$focus:1}" == "," ]
    then
        limit=$((limit+1))
        length=$(($focus-$start))
        let c$limit="${f:start:length}"
        start=$((focus+1))
    fi
done
r=`echo "obase=16; $c1" | bc`
r2=`echo "obase=16; $c2" | bc`
r3=`echo "obase=16; $c3" | bc`
if [ "${r:1:2}" == "" ]
  then r=0$r
fi
if [ "${r2:1:2}" == "" ]
  then r2=0$r2
fi
if [ "${r3:1:2}" == "" ]
  then r3=0$r3
fi
echo $r$r2$r3
Skald answered 15/9, 2020 at 3:58 Comment(0)
R
0
The simplest, but not compact, way to convert a color value is to 
use the constant = ("1.00, 255 FF" "..., .. .." "0.0, 0 00").
The  example in the last line of the script converts the string 
to a hexadecimal color value from the file /usr/share/X11/rgb.txt. 
Using the search command grep -A in the case of rgb 0.00.

#!/usr/bin/env bash
# rgb; X11; hex; --> HEX.
# ${BASH} ./rgb-hex.sh or "{ 0.0, 0.0, 0.0 }"; or "magenta"; or #ffffff
# Otherwise, a value of the type "#000" will be returned, as well as "empty" or "error".
# В іншому випадку буде повернуто значення типу "#000", а також "порожнє" або "помилка".

NO_ARGS=0
E_OPTERROR=65

if [ $# -eq "$NO_ARGS" ]  # Script called without arguments?
then
  echo "Directions for use: `basename $0` options \"{ 0.0, 0.0, 0.0 }\""
  exit $E_OPTERROR      # If there are no arguments, exit with a message
fi

rgbinhex (){

IN="${1:-{ 0.0, 0.0, 0.0 }}"

printf -v IN "${IN//[\{\ \}]/}0"
   IN="${IN//[,]/0,}"
   IN="$( grep -Eo '[1]*\.[0-9]{,2}' \
   <<<"${IN}" | tr -d \. | sed 's/^0//g;'       )"

printf -v R "$( head -n1 <<<"${IN}" | tail -n1  )"

printf -v G "$( head -n2 <<<"${IN}" | tail -n1  )"

printf -v B "$( head -n3 <<<"${IN}" | tail -n1  )"


printf '\x23%02X%02X%02X\n' "$(( R * 255 / 100 ))" \
     "$(( G * 255 / 100 ))" "$(( B * 255 / 100 ))"

}


[[ ${1} = \{*\,* ]] && rgbinhex "${1}" \
  && \
      exit 0

[[ ${1} = \#[[:xdigit:]]* ]] && printf '%s\n' "${1}" \
    | tr '[:lower:]' '[:upper:]' \
  && \
      exit 0

[[ ${1} = "" ]] && printf '%s\n' "#000" \
  && \
      exit 0

[[ ${1} = [[:alnum:]\ ]* ]] && printf '#%02X%02X%02X\n' \
   $(grep -Eiwm1 "\s\s*${1}$" "/usr/share/X11/rgb.txt"  \
    | awk '{print $1,$2,$3}') \
  && \
      exit 0


exit 0

For checking and control you can use the wonderful GUI script nf yad:
~$ yad --window-icon=color-selection --title=Color-Selection --color --gtk-palette --expand-palette --palette=/usr/share/X11/rgb.txt --scroll
Remove answered 8/8 at 17:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.