#!/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