#!/bin/bash # SHITPOST # Takes an image and adds some shitty text to it # someone on /r/linuxmasterrace asked what image programs were good for shitposts # it got me thinking that there should be a cli command just for that # days later (I'm still pretty noob)... # Originally by Mykal Anderson # Patched by Declan Hoare 2016-12-02: use PNG instead of GIF for temp files to preserve quality # Modified by coolreader18 2021-03-01: fix some bugs and use a directory under /tmp for temporary files, add -o option # Modified by Magnus Anderson 2021-09-21: clean up the code, make -f implied # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE # Version 2, December 2004 # Copyright (C) 2004 Sam Hocevar # Everyone is permitted to copy and distribute verbatim or modified # copies of this license document, and changing it is allowed as long # as the name is changed. # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION # 0. You just DO WHAT THE FUCK YOU WANT TO. usage() { printf "Usage: shitpost [-f] /path/to/file [-t top -b bottom -o outfile]\n\t-f\tPath to image file (-f is implied)\n\t-t\tTop Text\n\t-b\tBottom Text\n\t-o\tOutput file name\n" } # Check if imagemagick (just convert checked, but others used) is installed and exit if missing command -v convert >/dev/null 2>&1 || { echo >&2 "I require ImageMagick but it's not installed. Aborting."; exit 1; } top_text=" " bottom_text=" " image_file="" output_file="" # Get CLI args while true; do OPTIND=1 while getopts "h?t:b:f:o:" opt; do case "$opt" in t) top_text="$OPTARG" ;; b) bottom_text="$OPTARG" ;; f) image_file="$OPTARG" ;; o) output_file="$OPTARG" ;; h|\?) usage exit 0 ;; esac done shift $((OPTIND-1)) # If `-f` not provided, use the first non-flag argument as the image file, and continue parsing options [[ -z "$image_file" ]] && image_file="$1" && shift 1 && continue break done # Ensure that an image file is provided and exists. Does not check that it actually contains image data [[ -z "$image_file" ]] && echo "You must specify an image file!" && usage && exit 1 # Let the user know any options that were invalid that were not already handled by getopts. [[ ! -z "$@" ]] && echo "Invalid argument(s): '$@'" && echo "Ignored, continuing..." # Set the output file to shitpost-INPUT_FILE if none was given base=${image_file##*/} [[ -z "$output_file" ]] && output_file="shitpost-$base" # Create a temporary directory to hold the temporary files tmpdir=$(mktemp -d /tmp/shitpost.XXXXXX) trap 'rm -rf "$tmpdir"' 0 1 2 3 6 # Upscale the image if it's too shitty. This is required to make the text readable as it's generated to fit the pixels of the original convert -resize 1024x1024\< "$image_file" "$tmpdir"/shitpost-temp-resize.png # Get the height and width of the image to use later to size the overlays. Clipped height keeps things locked in the top and bottom fifth of the image. image_width=$(identify -format "%[width]" "$tmpdir"/shitpost-temp-resize.png) image_height=$(identify -format "%[height]" "$tmpdir"/shitpost-temp-resize.png) clipped_height=$(($image_height/5)) stroke_width=$(($clipped_height/40)) convert -background none -fill white -stroke black -strokewidth "$stroke_width" -size "$image_width"x"$clipped_height" -gravity Center -font 'Impact' caption:"$top_text" "$tmpdir"/shitpost-temp-top-text.png convert -background none -fill white -stroke black -strokewidth "$stroke_width" -size "$image_width"x"$clipped_height" -gravity Center -font 'Impact' caption:"$bottom_text" "$tmpdir"/shitpost-temp-bottom-text.png composite -gravity north "$tmpdir"/shitpost-temp-top-text.png "$tmpdir"/shitpost-temp-resize.png "$tmpdir"/shitpost-temp-composite.png composite -gravity south "$tmpdir"/shitpost-temp-bottom-text.png "$tmpdir"/shitpost-temp-composite.png "$output_file" #Announce the results echo "Created file '$output_file'"