Skip to content

Instantly share code, notes, and snippets.

@asaaki
Forked from twooster/README.md
Last active April 23, 2020 13:44
Show Gist options
  • Save asaaki/de45882ce784510b7f8ac48baf2e5c2b to your computer and use it in GitHub Desktop.
Save asaaki/de45882ce784510b7f8ac48baf2e5c2b to your computer and use it in GitHub Desktop.
Create scrolling text gifs for Slack

(Forked fork, that works on macos, too)

Makes little scrolly text jiffs in Flywheel colors.

Prerequisites

  • macos: brew install fontconfig imagemagick gifsicle
  • Linux: sudo apt install fontconfig imagemagick gifsicle

Usage

Usage: ./yolo.sh [options] <message>

Options:

  -h                Show this help message

  -o <output.gif>   Path to output gif. Default: output.<random>.gif

  -c <color>        Choose color set, valid options are:
                    red, orange, yellow, green, blue, purple,
                    pink, black, white.  Default: black

  -d <delay>        Delay between frames. Default: 6

  -s <step>         How many pixels to step each frame. Default: 10

  -H <height>       Image height (and also the width). Default: 128

  -f <font name>    The font name. Default: helvetica

  -w                Force white text color

  -t                Force transparent background

  -r                CREATE RAINBOW ANIMATION! (only stacking multiple
                    single color GIFs into one; incl. black + white)

Examples

$ yolo.sh -c purple -o awesome.gif "That's awesome!"

Changes

  • RAINBOWS! YAY!
  • add option to use transparent background — yay!
  • default output file will include a short random hash, so you can quickly generate multiple scrollers without overwriting the previously generated one, because you forgot to set a different output file name.
  • print the output file name after generation
  • tries to open the file (on macos with Safari, on Linux with xdg-open)
#!/usr/bin/env bash
contains() {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
usage() {
if [ "$1" != "" ]; then
echo -e "Error: $1\n" >&2
fi
echo "Usage: $0 [options] <message>"
echo
echo "Options:"
echo
echo " -h Show this help message"
echo
echo " -o <output.gif> Path to output gif. Default: output.<random>.gif"
echo
echo " -c <color> Choose color set, valid options are:"
echo " red, orange, yellow, green, blue, purple,"
echo " pink, black, white. Default: black"
echo
echo " -d <delay> Delay between frames. Default: 6"
echo
echo " -s <step> How many pixels to step each frame. Default: 10"
echo
echo " -H <height> Image height (and also the width). Default: 128"
echo
echo " -f <font name> The font name. Default: helvetica"
echo
echo " -w Force white text color"
echo
echo " -t Force transparent background"
echo
echo " -r CREATE RAINBOW ANIMATION! (only stacking multiple"
echo " single color GIFs into one; incl. black + white)"
exit 1
}
# Make a "unique" prefix for this run
PREFIX="$(head -c 32 /dev/urandom | shasum | cut -b 1-10)"
VALID_COLORS=("red" "orange" "yellow" "green" "blue" "purple" "pink" "black" "white")
COLOR="black"
OUTPUT="output.$PREFIX.gif"
FONT_NAME="helvetica"
FORCE_WHITE_TEXT=0
FORCE_TRANSPARENT_BACKGROUND=0
SPEED=16
DELAY=6
HEIGHT=128
SKIP_OUTPUT_OPEN=0
RAINBOW_MODE=0
while getopts ":c:o:f:s:d:H:hwtrn" opt; do
case $opt in
h)
usage
;;
n)
SKIP_OUTPUT_OPEN=1
;;
r)
RAINBOW_MODE=1
;;
w)
FORCE_WHITE_TEXT=1
;;
t)
FORCE_TRANSPARENT_BACKGROUND=1
;;
c)
if contains "$OPTARG" "${VALID_COLORS[@]}"; then
COLOR="$OPTARG"
else
usage "Invalid color: $OPTARG"
fi
;;
o)
OUTPUT="$OPTARG"
;;
H)
HEIGHT="$OPTARG"
;;
f)
FONT_NAME="$OPTARG"
;;
d)
DELAY="$OPTARG"
;;
s)
SPEED="$OPTARG"
;;
\?)
usage "Invalid option: -$OPTARG"
;;
:)
usage "Option -$OPTARG requires an argument."
exit 1
;;
esac
done
shift $((OPTIND - 1))
# Find our font before we do anything.
FONT_PATH="$( fc-match "${FONT_NAME}" -f'%{file}' )"
if [ "$FONT_PATH" == "" ]; then
usage "Could not find '${FONT_NAME}' font. Is it installed?"
else
echo "Using ${FONT_PATH} for ${FONT_NAME} font."
fi
MESSAGE="$*"
if [ "$MESSAGE" == "" ]; then
usage "A message is required."
fi
if [ "$RAINBOW_MODE" == 1 ]; then
colors=("red" "orange" "yellow" "green" "blue" "purple" "black" "white")
declare -a files
for color in ${colors[@]}; do
echo "Generate color $color ..."
file="rainbow.step.$color.gif"
files+=($file)
$0 -d "$DELAY" -s "$SPEED" -H "$HEIGHT" -f "$FONT_NAME" -c "$color" -t -n -o $file "$MESSAGE"
done
COMBINED="rainbow.$PREFIX.gif"
convert ${files[@]} $COMBINED
gifsicle -b -O3 -Okeep-empty -k16 $COMBINED
echo "Final rainbow file: $COMBINED"
exit 0
fi
case $COLOR in
red)
FILL="#e40303"
BACKGROUND="#4c0000"
;;
orange)
FILL="#ff8c00"
BACKGROUND="#562b00"
;;
yellow)
FILL="#ffed00"
BACKGROUND="#565100"
;;
green)
FILL="#008026"
BACKGROUND="#002705"
;;
blue)
FILL="#004dff"
BACKGROUND="#001456"
;;
purple)
FILL="#750787"
BACKGROUND="#23012a"
;;
pink)
FILL="#851252"
BACKGROUND="#e0368c"
;;
black)
FILL="#111111"
BACKGROUND="#ffffff"
;;
white)
FILL="#ffffff"
BACKGROUND="#111111"
;;
esac
if [ "$FORCE_WHITE_TEXT" == 1 ]; then
FILL="#ffffff"
fi
if [ "$FORCE_TRANSPARENT_BACKGROUND" == 1 ]; then
echo "Using transparent background"
BACKGROUND="transparent"
fi
# Generate image from text input
convert \
-background "$BACKGROUND" \
-fill "$FILL" \
-font "$FONT_PATH" \
-density 200 \
-pointsize 100 \
"label:${MESSAGE}" \
"/tmp/${PREFIX}_label.png"
# Resize to 128px high
convert \
-resize x${HEIGHT} \
"/tmp/${PREFIX}_label.png" \
"/tmp/${PREFIX}_sized.png"
# Add padding
WIDTH="$(identify -format "%[fx:w]" "/tmp/${PREFIX}_sized.png")"
CANVAS_SIZE=$((WIDTH + HEIGHT + HEIGHT + (HEIGHT / 4))) # HEIGHT in front, HEIGHT / 4 in back
# convert "/tmp/${PREFIX}_sized.png" -bordercolor $BACKGROUND -border ${HEIGHT}x0 "/tmp/${PREFIX}_padded.png"
convert \
"/tmp/${PREFIX}_sized.png" \
-gravity center \
-background $BACKGROUND \
-extent $CANVAS_SIZE \
"/tmp/${PREFIX}_padded.png"
# Generate individual frames
STEP=$((HEIGHT / (64 / SPEED)))
OFFSET=0
I=0
LIMIT=$((CANVAS_SIZE - HEIGHT))
while [[ "$OFFSET" -lt "$LIMIT" ]]; do
convert \
"/tmp/${PREFIX}_padded.png" \
-crop "${HEIGHT}x${HEIGHT}+${OFFSET}+0!" \
"$(printf "/tmp/${PREFIX}_frame_%05d.png" $I)"
I=$((I + 1))
OFFSET=$((OFFSET + STEP))
done
# Compile to gif
convert \
-delay "$DELAY" \
-loop 0 \
-dispose previous \
"/tmp/${PREFIX}_frame_*.png" \
"$OUTPUT"
# Clean up!
rm /tmp/${PREFIX}_*.png
if [ "$SKIP_OUTPUT_OPEN" == 0 ]; then
# Optimize it
gifsicle -b -O3 -Okeep-empty -k16 "$OUTPUT"
echo "Your GIF is ready: $OUTPUT"
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*)
xdg-open $OUTPUT
;;
Darwin*)
open -a "Safari" "$OUTPUT"
;;
CYGWIN*)
;;
MINGW*)
;;
*)
;;
esac
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment