Last active
September 16, 2024 16:13
-
-
Save kRHYME7/0ddd01a92a6b7c3ae773deb0fed65ab2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
#|---/ /+---------------------------------------------+---/ /|# | |
#|--/ /-| Script to generate color palette from image |--/ /-|# | |
#|-/ /--| Prasanth Rangan |-/ /--|# | |
#|/ /---+---------------------------------------------+/ /---|# | |
#// accent color profile | |
colorProfile="default" | |
wallbashCurve="32 50\n42 46\n49 40\n56 39\n64 38\n76 37\n90 33\n94 29\n100 20" | |
sortMode="auto" | |
while [ $# -gt 0 ] ; do | |
case "$1" in | |
-v|--vibrant) colorProfile="vibrant" | |
wallbashCurve="18 99\n32 97\n48 95\n55 90\n70 80\n80 70\n88 60\n94 40\n99 24" | |
;; | |
-p|--pastel) colorProfile="pastel" | |
wallbashCurve="10 99\n17 66\n24 49\n39 41\n51 37\n58 34\n72 30\n84 26\n99 22" | |
;; | |
-m|--mono) colorProfile="mono" | |
wallbashCurve="10 0\n17 0\n24 0\n39 0\n51 0\n58 0\n72 0\n84 0\n99 0" | |
;; | |
-c|--custom) | |
shift | |
if [ -n "${1}" ] && [[ "${1}" =~ ^([0-9]+[[:space:]][0-9]+\\n){8}[0-9]+[[:space:]][0-9]+$ ]] ; then | |
colorProfile="custom" | |
wallbashCurve="${1}" | |
else | |
echo "Error: Custom color curve format is incorrect ${1}" | |
exit 1 | |
fi | |
;; | |
-d|--dark) sortMode="dark" | |
colSort="" | |
;; | |
-l|--light) sortMode="light" | |
colSort="-r" | |
;; | |
*) break | |
;; | |
esac | |
shift | |
done | |
#// set variables | |
wallbashImg="${1}" | |
wallbashColors=4 | |
wallbashFuzz=70 | |
wallbashRaw="${2:-"${wallbashImg}"}.mpc" | |
wallbashOut="${2:-"${wallbashImg}"}.dcol" | |
wallbashCache="${2:-"${wallbashImg}"}.cache" | |
#// color modulations | |
pryDarkBri=116 | |
pryDarkSat=110 | |
pryDarkHue=88 | |
pryLightBri=100 | |
pryLightSat=100 | |
pryLightHue=114 | |
txtDarkBri=188 | |
txtLightBri=16 | |
#// input image validation | |
if [ -z "${wallbashImg}" ] || [ ! -f "${wallbashImg}" ] ; then | |
echo "Error: Input file not found!" | |
exit 1 | |
fi | |
magick -ping "${wallbashImg}" -format "%t" info: &> /dev/null | |
if [ $? -ne 0 ] ; then | |
echo "Error: Unsuppoted image format ${wallbashImg}" | |
exit 1 | |
fi | |
echo -e "wallbash ${colorProfile} profile :: ${sortMode} :: Colors ${wallbashColors} :: Fuzzy ${wallbashFuzz} :: \"${wallbashOut}\"" | |
mkdir -p "${cacheDir}/${cacheThm}" | |
> "${wallbashOut}" | |
#// define functions | |
rgb_negative() { | |
local inCol=$1 | |
local r=${inCol:0:2} | |
local g=${inCol:2:2} | |
local b=${inCol:4:2} | |
local r16=$((16#$r)) | |
local g16=$((16#$g)) | |
local b16=$((16#$b)) | |
r=$(printf "%02X" $((255 - $r16))) | |
g=$(printf "%02X" $((255 - $g16))) | |
b=$(printf "%02X" $((255 - $b16))) | |
echo "${r}${g}${b}" | |
} | |
rgba_convert() { | |
local inCol=$1 | |
local r=${inCol:0:2} | |
local g=${inCol:2:2} | |
local b=${inCol:4:2} | |
local r16=$((16#$r)) | |
local g16=$((16#$g)) | |
local b16=$((16#$b)) | |
printf "rgba(%d,%d,%d,\1341)\n" "$r16" "$g16" "$b16" | |
} | |
fx_brightness() { | |
local inCol="${1}" | |
local fxb=$(magick "${inCol}" -colorspace gray -format "%[fx:mean]" info:) | |
if awk -v fxb="${fxb}" 'BEGIN {exit !(fxb < 0.5)}' ; then | |
return 0 #// echo ":: ${fxb} :: dark :: ${inCol}" | |
else | |
return 1 #// echo ":: ${fxb} :: light :: ${inCol}" | |
fi | |
} | |
#// quantize raw primary colors | |
magick -quiet -regard-warnings "${wallbashImg}"[0] -alpha off +repage "${wallbashRaw}" | |
# #? Original command (commented out for reference) | |
# #! readarray -t dcolRaw <<< $(magick "${wallbashRaw}" -depth 8 -fuzz ${wallbashFuzz}% +dither -kmeans ${wallbashColors} -depth 8 -format "%c" histogram:info: | sed -n 's/^[ ]*\(.*\):.*[#]\([0-9a-fA-F]*\) .*$/\1,\2/p' | sort -r -n -k 1 -t ",") | |
# #? Read test values into array | |
# readarray -t dcolRaw <<< "$(echo "${MOCK_VALUE}" | sed -n 's/^[ ]*\(.*\):.*[#]\([0-9a-fA-F]*\) .*$/\1,\2/p' | sort -r -n -k 1 -t ",")" | |
# # readarray -t dcolRaw <<< $(magick "${wallbashRaw}" -depth 8 -fuzz ${wallbashFuzz}% +dither -kmeans ${wallbashColors} -depth 8 -format "%c" histogram:info: | sed -n 's/^[ ]*\(.*\):.*[#]\([0-9a-fA-F]*\) .*$/\1,\2/p' | sort -r -n -k 1 -t ",") | |
# if [ ${#dcolRaw[*]} -lt ${wallbashColors} ] ; then | |
# echo -e "RETRYING :: distinct colors ${#dcolRaw[*]} is less than ${wallbashColors} palette color..." | |
# readarray -t dcolRaw <<< $(magick "${wallbashRaw}" -depth 8 -fuzz ${wallbashFuzz}% +dither -kmeans $((wallbashColors + 2)) -depth 8 -format "%c" histogram:info: | sed -n 's/^[ ]*\(.*\):.*[#]\([0-9a-fA-F]*\) .*$/\1,\2/p' | sort -r -n -k 1 -t ",") | |
# # readarray -t dcolRaw <<< "$(echo "${MOCK_VALUE}" | sed -n 's/^[ ]*\(.*\):.*[#]\([0-9a-fA-F]*\) .*$/\1,\2/p' | sort -r -n -k 1 -t ",")" | |
# fi | |
# Generate a Mock value for dcolRaw | |
dcolRaw=( | |
"25707417,2A2C39" | |
"8568639,3C3F52" | |
"1736445,8387A2" | |
"543210,FEDCBA" | |
) | |
#// sort colors based on image brightness | |
if [ "${sortMode}" == "auto" ] ; then | |
if fx_brightness "${wallbashRaw}" ; then | |
sortMode="dark" | |
colSort="" | |
else | |
sortMode="light" | |
colSort="-r" | |
fi | |
fi | |
echo "dcol_mode=\"${sortMode}\"" >> "${wallbashOut}" | |
dcolHex=($(echo -e "${dcolRaw[@]:0:$wallbashColors}" | tr ' ' '\n' | awk -F ',' '{print $2}' | sort ${colSort})) | |
greyCheck=$(magick "${wallbashRaw}" -colorspace HSL -channel g -separate +channel -format "%[fx:mean]" info:) | |
if (( $(awk 'BEGIN {print ('"$greyCheck"' < 0.12)}') )); then | |
wallbashCurve="10 0\n17 0\n24 0\n39 0\n51 0\n58 0\n72 0\n84 0\n99 0" | |
fi | |
#// loop for derived colors | |
for (( i=0; i<${wallbashColors}; i++ )) ; do | |
#// generate missing primary colors | |
if [ -z "${dcolHex[i]}" ] ; then | |
if fx_brightness "xc:#${dcolHex[i - 1]}" ; then | |
modBri=$pryDarkBri | |
modSat=$pryDarkSat | |
modHue=$pryDarkHue | |
else | |
modBri=$pryLightBri | |
modSat=$pryLightSat | |
modHue=$pryLightHue | |
fi | |
echo -e "dcol_pry$((i + 1)) :: regen missing color" | |
dcol[i]=$(magick xc:"#${dcolHex[i - 1]}" -depth 8 -normalize -modulate ${modBri},${modSat},${modHue} -depth 8 -format "%c" histogram:info: | sed -n 's/^[ ]*\(.*\):.*[#]\([0-9a-fA-F]*\) .*$/\2/p') | |
fi | |
echo "dcol_pry$((i + 1))=\"${dcolHex[i]}\"" >> "${wallbashOut}" | |
echo "dcol_pry$((i + 1))_rgba=\"$( rgba_convert "${dcolHex[i]}" )\"" >> "${wallbashOut}" | |
#// generate primary text colors | |
nTxt=$(rgb_negative ${dcolHex[i]}) | |
if fx_brightness "xc:#${dcolHex[i]}" ; then | |
modBri=$txtDarkBri | |
else | |
modBri=$txtLightBri | |
fi | |
tcol=$(magick xc:"#${nTxt}" -depth 8 -normalize -modulate ${modBri},10,100 -depth 8 -format "%c" histogram:info: | sed -n 's/^[ ]*\(.*\):.*[#]\([0-9a-fA-F]*\) .*$/\2/p') | |
echo "dcol_txt$((i + 1))=\"${tcol}\"" >> "${wallbashOut}" | |
echo "dcol_txt$((i + 1))_rgba=\"$( rgba_convert "${tcol}" )\"" >> "${wallbashOut}" | |
#// generate accent colors | |
xHue=$(magick xc:"#${dcolHex[i]}" -colorspace HSB -format "%c" histogram:info: | awk -F '[hsb(,]' '{print $2}') | |
acnt=1 | |
echo -e "${wallbashCurve}" | sort -n ${colSort} | while read -r xBri xSat | |
do | |
acol=$(magick xc:"hsb(${xHue},${xSat}%,${xBri}%)" -depth 8 -format "%c" histogram:info: | sed -n 's/^[ ]*\(.*\):.*[#]\([0-9a-fA-F]*\) .*$/\2/p') | |
echo "dcol_$((i + 1))xa${acnt}=\"${acol}\"" >> "${wallbashOut}" | |
echo "dcol_$((i + 1))xa${acnt}_rgba=\"$( rgba_convert "${acol}" )\"" >> "${wallbashOut}" | |
((acnt++)) | |
done | |
done | |
#// cleanup temp cache | |
rm -f "${wallbashRaw}" "${wallbashCache}" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment