Skip to content

Instantly share code, notes, and snippets.

@vain
Created October 5, 2010 18:59
Show Gist options
  • Save vain/612099 to your computer and use it in GitHub Desktop.
Save vain/612099 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Based on the "Shell image viewer" by Andreas Schönfelder:
# https://bbs.archlinux.org/viewtopic.php?id=106089
# Defaults.
doublexres="yes"
colors="$(tput colors)"
size="$(($(tput cols) - 2))x$(($(tput lines) - 2))"
# Process arguments.
while getopts nc:s:b: name
do
case $name in
n)
# Don't double the resolution in X direction?
doublexres="no"
;;
c)
# Number of colors?
colors="$OPTARG";
;;
s)
# Desired size?
size="$OPTARG"
;;
b)
# Background for transparent images?
transparentbg=(-background "$OPTARG")
;;
esac
done
shift $((OPTIND - 1))
if [[ "$colors" != 8 ]] && [[ "$colors" != 256 ]]
then
echo "'$colors' colors not supported." >&2
exit 1
fi
if [[ "$doublexres" == "yes" ]]
then
# First, we assume that there's twice as much space in Y direction.
wid="${size%x*}"
hei="${size#*x}"
hei=$((hei * 2))
size="${wid}x${hei}"
# Afterwards, squash the image. This results in twice the pixels in
# X direction.
squash=(-scale "100%x50%")
else
squash=()
fi
# Remaining arguments are filenames.
while (( $# > 0 ))
do
# Convert the image into a PPM image which can easily be read by
# awk.
convert \
"${transparentbg[@]}" \
-compress none \
-depth 8 \
-resize "$size" \
"${squash[@]}" \
"$1" "ppm:-" |
gawk '
BEGIN {
# Define colors and width of one pixel.
blank = " "
reset = "'"$(tput sgr0)"'"
black = "'"$(tput setab 0)"'"
blue = "'"$(tput setab 4)"'"
green = "'"$(tput setab 2)"'"
cyan = "'"$(tput setab 6)"'"
red = "'"$(tput setab 1)"'"
magenta = "'"$(tput setab 5)"'"
yellow = "'"$(tput setab 3)"'"
white = "'"$(tput setab 7)"'"
if ('"$colors"' == 8)
divideby = 128
else
divideby = 51
# Read first three non-comment and non-empty lines and get the
# image width.
while (i < 3)
{
if (getline <= 0)
break
if (!($0 ~ /^#/ || $0 == ""))
i++
if (i == 2)
wid = $1
}
}
# Read the rest of the image.
{
for (i = 1; i <= NF; i += 3)
{
r = int($i / divideby)
g = int($(i + 1) / divideby)
b = int($(i + 2) / divideby)
if ('"$colors"' == 8)
{
if (r == 0 && g == 0 && b == 0)
printf "%s%s%s", black, blank, reset
if (r == 0 && g == 0 && b == 1)
printf "%s%s%s", blue, blank, reset
if (r == 0 && g == 1 && b == 0)
printf "%s%s%s", green, blank, reset
if (r == 0 && g == 1 && b == 1)
printf "%s%s%s", cyan, blank, reset
if (r == 1 && g == 0 && b == 0)
printf "%s%s%s", red, blank, reset
if (r == 1 && g == 0 && b == 1)
printf "%s%s%s", magenta, blank, reset
if (r == 1 && g == 1 && b == 0)
printf "%s%s%s", yellow, blank, reset
if (r == 1 && g == 1 && b == 1)
printf "%s%s%s", white, blank, reset
}
else
{
if (r == g && g == b)
{
# Try to use the full grayscale ramp. Using "r", "g"
# and "b" automatically uses some fuzziness because
# theyve already been divided by 51. But now, we
# reset "g" to the real grayscale value. Full white
# and full black are not part of the ramp.
g = $i
if (g == 255)
printf "\033[48;5;231m%s%s", blank, reset
else if (g == 0)
printf "\033[48;5;16m%s%s", blank, reset
else
{
printf "\033[48;5;%dm%s%s",
(int(($i / 255) * 24) + 232), blank, reset
}
}
else
{
# Find the nearest neighbor in XTerms 6x6x6 color
# cube.
printf "\033[48;5;%dm%s%s",
(16 + r * 36 + g * 6 + b), blank, reset
}
}
pixel++
if (pixel == wid)
{
printf "\n"
pixel = 0
}
}
}'
# One empty line between two images.
shift
if (( $# > 0 ))
then
echo
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment