Tuesday, October 8, 2019

Terminal Color Analyzer - Prints True RGB Values for Terminal Colors

#!/bin/bash 

  ######################################################################
 ######################################################################
## Author: Adam Michael Danischewski 
## GitHub: https://github.com/AdamDanischewski/scriptsandoneliners
## Created Date: 2019-10-08
## Name: pscolors.bsh
## Version: v0.01
## Last Modified: 2019-10-08
## Issues: If you find any issues emai1 me at <my first name> (dot) 
##         <my last name> (at) gmail (dot) com. 
##
## Requirements:xdotool/xdotool, xwininfo/x11-utils, tput/ncurses-bin, 
##              scrot/scrot, convert/imagemagick 
## On Ubuntu: 
## sudo apt-get install xdotool x11-utils scrot ncurses-bin imagemagick
##
## Prints the full xterm-256 ansi color mapping to RGB (decimal) and HEX 
## in ANSI color (\x1b[38;5;<ansi>m) and Truecolor (\x1b[38;2;<R>;<G>;
## <B>m) and prints the rgb values of the colors that the terminal 
## prints to the screen. 
##
## How? First it prints all 256 ANSI colors for your terminal into a 
## grid then it uses scrot to take a screenshot. It then steps over the 
## image using imageMagick to pull the pixel color value for each cell. 
## 
## Why? Because there are alot of potential manipulators of color prior 
## to colors landing on the actual screen. E.g. compton, shading, etc.  
##
## With this tool you can get the end result rgb colors after all 
## graphics processing is done when you are looking at your terminal. 
## 
## Without this tool, you would only know what you configured and what 
## is advertised. This tool gives you the color actuals -- of course you 
## can't really SEE the actual colors though I attempt to display them 
## in TRUECOLOR. You can grab the RGB values and display them elsewhere 
## (e.g. color tool in a web browser) to really see the nuances between 
## what is advertised and what is experienced in your terminal.  
## 
## Note: If you have translucent windows, the background may affect the 
## results - you should probably kill conky and run this on a blank 
## workspace in a maximized terminal for best results. 
##
## Look-up values gleened from: 
## https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
##
## Released under Creative Commons License: CC BY-SA 4.0
## https://creativecommons.org/licenses/by-sa/4.0/
 ######################################################################
  ######################################################################

 ## Global variables 
declare    SCREENSHOT_LOC=/tmp/__pscolorscrnshot_$RANDOM__.png
declare -i COLOR_SWATCH_IMG_COLS=60 ## Use a 60 term col wide image. 
declare    SHOW_COLOR_DELAY=.25
declare    XWININFO="" ## Get the current window info via xwininfo.  
declare    X_COORD=""  ## Absolute upper-left X
declare    Y_COORD=""  ## Absolute upper-left Y
declare    REL_X=""    ## Relative upper-left X
declare    REL_Y=""    ## Relative upper-left Y

function show_colors() { 
 local -i ANSI=0
 tput clear 
  ## Print the mysterious ANSI colors. 
 for ANSI in {0..256} ; do 
  echo -en "\\033[38;5;${ANSI}m█\\033[0m" 
  (($((${ANSI}+1))%${COLOR_SWATCH_IMG_COLS}==0)) && echo 
 done 
 echo
} 

## Parse RGB hex tuples. 
## <Arg 1> - Hex: Input hex value [[:xdigit]]{6}
## <Arg 2> - String: Tuple [r|g|b]
function get_rgbtuple() { 
 local hexrgb="${1}" 
 local tuple_flag="${2}" 
 local tuple_fmt="${3:-x}" 
 local tuple="" 
 case "${tuple_flag}" in 
  r|R) 
   tuple=${hexrgb:0:2}
   ;; 
  g|G) 
   tuple=${hexrgb:2:2}
   ;; 
  b|B) 
   tuple=${hexrgb:4:2}
   ;; 
 esac
 echo $((0x${tuple}))
}

function get_rgb() { 
 local -i ansi=${1:-1}
 local -a rgb=("000000" "800000" "008000" "808000" "000080"     \
 "800080" "008080" "c0c0c0" "808080" "ff0000" "00ff00" "ffff00" \
 "0000ff" "ff00ff" "00ffff" "ffffff" "000000" "00005f" "000087" \
 "0000af" "0000d7" "0000ff" "005f00" "005f5f" "005f87" "005faf" \
 "005fd7" "005fff" "008700" "00875f" "008787" "0087af" "0087d7" \
 "0087ff" "00af00" "00af5f" "00af87" "00afaf" "00afd7" "00afff" \
 "00d700" "00d75f" "00d787" "00d7af" "00d7d7" "00d7ff" "00ff00" \
 "00ff5f" "00ff87" "00ffaf" "00ffd7" "00ffff" "5f0000" "5f005f" \
 "5f0087" "5f00af" "5f00d7" "5f00ff" "5f5f00" "5f5f5f" "5f5f87" \
 "5f5faf" "5f5fd7" "5f5fff" "5f8700" "5f875f" "5f8787" "5f87af" \
 "5f87d7" "5f87ff" "5faf00" "5faf5f" "5faf87" "5fafaf" "5fafd7" \
 "5fafff" "5fd700" "5fd75f" "5fd787" "5fd7af" "5fd7d7" "5fd7ff" \
 "5fff00" "5fff5f" "5fff87" "5fffaf" "5fffd7" "5fffff" "870000" \
 "87005f" "870087" "8700af" "8700d7" "8700ff" "875f00" "875f5f" \
 "875f87" "875faf" "875fd7" "875fff" "878700" "87875f" "878787" \
 "8787af" "8787d7" "8787ff" "87af00" "87af5f" "87af87" "87afaf" \
 "87afd7" "87afff" "87d700" "87d75f" "87d787" "87d7af" "87d7d7" \
 "87d7ff" "87ff00" "87ff5f" "87ff87" "87ffaf" "87ffd7" "87ffff" \
 "af0000" "af005f" "af0087" "af00af" "af00d7" "af00ff" "af5f00" \
 "af5f5f" "af5f87" "af5faf" "af5fd7" "af5fff" "af8700" "af875f" \
 "af8787" "af87af" "af87d7" "af87ff" "afaf00" "afaf5f" "afaf87" \
 "afafaf" "afafd7" "afafff" "afd700" "afd75f" "afd787" "afd7af" \
 "afd7d7" "afd7ff" "afff00" "afff5f" "afff87" "afffaf" "afffd7" \
 "afffff" "d70000" "d7005f" "d70087" "d700af" "d700d7" "d700ff" \
 "d75f00" "d75f5f" "d75f87" "d75faf" "d75fd7" "d75fff" "d78700" \
 "d7875f" "d78787" "d787af" "d787d7" "d787ff" "dfaf00" "dfaf5f" \
 "dfaf87" "dfafaf" "dfafdf" "dfafff" "dfdf00" "dfdf5f" "dfdf87" \
 "dfdfaf" "dfdfdf" "dfdfff" "dfff00" "dfff5f" "dfff87" "dfffaf" \
 "dfffdf" "dfffff" "ff0000" "ff005f" "ff0087" "ff00af" "ff00df" \
 "ff00ff" "ff5f00" "ff5f5f" "ff5f87" "ff5faf" "ff5fdf" "ff5fff" \
 "ff8700" "ff875f" "ff8787" "ff87af" "ff87df" "ff87ff" "ffaf00" \
 "ffaf5f" "ffaf87" "ffafaf" "ffafdf" "ffafff" "ffdf00" "ffdf5f" \
 "ffdf87" "ffdfaf" "ffdfdf" "ffdfff" "ffff00" "ffff5f" "ffff87" \
 "ffffaf" "ffffdf" "ffffff" "080808" "121212" "1c1c1c" "262626" \
 "303030" "3a3a3a" "444444" "4e4e4e" "585858" "626262" "6c6c6c" \
 "767676" "808080" "8a8a8a" "949494" "9e9e9e" "a8a8a8" "b2b2b2" \
 "bcbcbc" "c6c6c6" "d0d0d0" "dadada" "e4e4e4" "eeeeee")
 if ((ansi<=256)); then 
  printf "%s\n" "${rgb[${ansi}]}" 
  return 0 
 else 
  return 1
 fi
}

function print_coords(){ 
 local -i i=0 
 for((i=0;i<256;i++)){ 
  echo "IMG_TRU_XCOORD: ${IMG_TRU_XCOORD}, IMG_TRU_YCOORD: ${IMG_TRU_YCOORD}, IMG_XCOORD: ${IMG_XCOORD}, IMG_YCOORD: ${IMG_YCOORD}"
  get_next_x_coord
 }
}

function get_next_x_coord(){ 
 IMG_TRU_XCOORD=$(echo "scale=10;${IMG_TRU_XCOORD}+${CHAR_WIDTH}"|bc)
 if awk "BEGIN{exit !(${IMG_TRU_XCOORD}>(${COLOR_SWATCH_IMG_COLS}*${CHAR_WIDTH}))}"; then 
  IMG_TRU_XCOORD=$(echo "scale=10;${CHAR_WIDTH}*.5"|bc)
  get_next_y_coord
 fi
 IMG_XCOORD=$(awk -vtx=${IMG_TRU_XCOORD} 'BEGIN{printf("%1.f\n",tx)}')
}

function get_next_y_coord(){ 
 IMG_TRU_YCOORD=$(echo "scale=10;${IMG_TRU_YCOORD}+${CHAR_HEIGHT}"|bc)
 IMG_YCOORD=$(awk -vty=${IMG_TRU_YCOORD} 'BEGIN{printf("%1.f\n",ty)}')
}

function print_rgb(){ 
 local -i ANSI=0 
 local -i r=0 
 local -i g=0 
 local -i b=0 
 local    p_r="" 
 local    p_g="" 
 local    p_b="" 
 local    p_ANSI="" 
 local    ACTUAL_RGB=""
 local    xrgb_R=""
 local    xrgb_G=""
 local    xrgb_B=""
 local    xprgb_R=""
 local    xprgb_G=""
 local    xprgb_B=""
 local    xhex=""
 tput reset 
 for((ANSI=0;ANSI<256;ANSI++)){ 
  xhex=$(get_rgb "${ANSI}")
  xrgb_R=$(get_rgbtuple "${xhex}" "r")
  xrgb_G=$(get_rgbtuple "${xhex}" "g")
  xrgb_B=$(get_rgbtuple "${xhex}" "b")
  xprgb_R=$(printf "%3s" "${xrgb_R}")
  xprgb_G=$(printf "%3s" "${xrgb_G}")
  xprgb_B=$(printf "%3s" "${xrgb_B}")
  read -r -d=' ' r g b < <(convert "${SCREENSHOT_LOC}" -format  "%[fx:int(255*p{${IMG_XCOORD},${IMG_YCOORD}}.r)] %[fx:int(255*p{${IMG_XCOORD},${IMG_YCOORD}}.g)] %[fx:int(255*p{${IMG_XCOORD},${IMG_YCOORD}}.b)]" info:-)
  p_r=$(printf "%3s" "${r}")
  p_g=$(printf "%3s" "${g}")
  p_b=$(printf "%3s" "${b}")
  p_ANSI=$(printf "%3s" "${ANSI}")
  printf "\\033[38;5;${ANSI}m████ ANSI ${p_ANSI}\\033[0m|\\033[38;5;${ANSI}m%s%s\\033[0m|\x1b[38;2;${xrgb_R};${xrgb_G};${xrgb_B}mxterm-256color - RGB/TRUECOLOR - RGB:%s,%s,%s\\033[0m%s \\033[38;2;${r};${g};${b}mActual terminal RGB: %s ████\\033[0m\n" "HEX:0x" "${xhex}" "${xprgb_R}" "${xprgb_G}" "${xprgb_B}" " |" "srgb(${p_r},${p_g},${p_b})"
  get_next_x_coord
 }
}

function init() {
 ## Get xwindow info  
 XWININFO=$(xwininfo -id $(xdotool getactivewindow))
 ## Parse xwininfo data: 
 X_COORD=$(sed -nE 's/(^.*Absolute upper-left X:)( *)([0-9]+)/\3/p' <<< "${XWININFO}")
 Y_COORD=$(sed -nE 's/(^.*Absolute upper-left Y:)( *)([0-9]+)/\3/p' <<< "${XWININFO}") 
 REL_X=$(sed   -nE 's/(^.*Relative upper-left X:)( *)([0-9]+)/\3/p' <<< "${XWININFO}")
 REL_Y=$(sed   -nE 's/(^.*Relative upper-left Y:)( *)([0-9]+)/\3/p' <<< "${XWININFO}")  
 SCRN_WIDTH=$(sed -nE 's/(^.*Width:)( *)([0-9]+)/\3/p'   <<< "${XWININFO}")
 SCRN_HEIGHT=$(sed -nE 's/(^.*Height:)( *)([0-9]+)/\3/p'   <<< "${XWININFO}")
 ## Get terminal sizing
 SCRN_ROWS=$(tput lines)
 SCRN_COLS=$(tput cols)
 CHAR_WIDTH=$(echo "scale=10;${SCRN_WIDTH}/${SCRN_COLS}"|bc)
 CHAR_HEIGHT=$(echo "scale=10;${SCRN_HEIGHT}/${SCRN_ROWS}"|bc)
 ## IMG_TRU_XCOORD starts at half the terminal char width. Thereafter 
 ## we will move by a full character width rounded to the nearest 
 ## pixel. IMG_TRU_XCOORD will keep the accurate unrounded values and 
 ## the IMG_XCOORD is the rounded value needed for imageMagick.  
 IMG_TRU_XCOORD=$(echo "scale=10; ${CHAR_WIDTH}*.5"|bc)
 IMG_XCOORD=$(awk -vtx=${IMG_TRU_XCOORD} 'BEGIN{printf("%1.f\n",tx)}') 
 ## IMG_TRU_YCOORD starts at half the terminal char height. Thereafter 
 ## we will move down by a full char height after COLOR_SWATCH_IMG_COLS 
 ## columns have been calculated.  
 IMG_TRU_YCOORD=$(echo "scale=10; ${CHAR_HEIGHT}*.5"|bc)
 IMG_YCOORD=$(awk -vty=${IMG_TRU_YCOORD} 'BEGIN{printf("%1.f\n",ty)}')
 ## Screenshot coords 
 ## Add the relative offset to absolute coord to get the true coords. 
 let X_COORD+=${REL_X} ## Screenshot X Coord 
 let Y_COORD+=${REL_Y} ## Screenshot Y Coord
 ## Screenshot size  
 IMG_WIDTH=$(awk -viw=$(echo "scale=10;${COLOR_SWATCH_IMG_COLS}*${CHAR_WIDTH}"|bc) 'BEGIN{printf("%1.f\n",iw)}')
 IMG_HEIGHT=$(awk -vih=$(echo "scale=10;5*${CHAR_HEIGHT}"|bc) 'BEGIN{printf("%1.f\n",ih)}')
}

function main(){ 
 init 
 tput smcup ## Save screen. 
 rm -f "${SCREENSHOT_LOC}" 
 show_colors
 sleep ${SHOW_COLOR_DELAY}
 ## Take screenshot w/location and image dimensions. 
 scrot "${SCREENSHOT_LOC}" -a${X_COORD},${Y_COORD},${IMG_WIDTH},${IMG_HEIGHT}
 tput rmcup ## Restore screen.  
 print_rgb
 rm -f "${SCREENSHOT_LOC}" 
}

main 
exit 0
Get the latest on GitHub.

No comments:

Post a Comment