Skip to content

Instantly share code, notes, and snippets.

@agates4
Last active August 3, 2021 20:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save agates4/54be4a8584ee5e80d02f6b601e7d3e6a to your computer and use it in GitHub Desktop.
Save agates4/54be4a8584ee5e80d02f6b601e7d3e6a to your computer and use it in GitHub Desktop.
Script to turn a given image into a beautiful screenshot with rounded corners, drop shadow, and whitespace
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>Activate</key>
<string>Normal</string>
<key>CreationDate</key>
<real>622511872.68444896</real>
<key>Macros</key>
<array>
<dict>
<key>Actions</key>
<array>
<dict>
<key>Conditions</key>
<dict>
<key>ConditionList</key>
<array>
<dict>
<key>Button</key>
<integer>0</integer>
<key>ConditionType</key>
<string>MouseButton</string>
</dict>
</array>
<key>ConditionListMatch</key>
<string>All</string>
</dict>
<key>MacroActionType</key>
<string>PauseUntil</string>
<key>TimeOutAbortsMacro</key>
<true/>
</dict>
<dict>
<key>Conditions</key>
<dict>
<key>ConditionList</key>
<array>
<dict>
<key>Button</key>
<integer>0</integer>
<key>ConditionType</key>
<string>MouseButton</string>
<key>Pressed</key>
<false/>
</dict>
</array>
<key>ConditionListMatch</key>
<string>All</string>
</dict>
<key>MacroActionType</key>
<string>PauseUntil</string>
<key>TimeOutAbortsMacro</key>
<true/>
</dict>
<dict>
<key>MacroActionType</key>
<string>Pause</string>
<key>Time</key>
<string>0.2</string>
<key>TimeOutAbortsMacro</key>
<true/>
</dict>
<dict>
<key>Conditions</key>
<dict>
<key>ConditionList</key>
<array>
<dict>
<key>ClipboardConditionType</key>
<string>HasImage</string>
<key>ClipboardText</key>
<string></string>
<key>ConditionType</key>
<string>Clipboard</string>
</dict>
</array>
<key>ConditionListMatch</key>
<string>All</string>
</dict>
<key>ElseActions</key>
<array/>
<key>MacroActionType</key>
<string>IfThenElse</string>
<key>ThenActions</key>
<array>
<dict>
<key>Append</key>
<false/>
<key>Destination</key>
<string>/Users/personal/Workspace/drop-shadow/temp.png</string>
<key>Encoding</key>
<string>UTF8</string>
<key>Format</key>
<string>PNG</string>
<key>Format2</key>
<string>PNG</string>
<key>MacroActionType</key>
<string>WriteFile</string>
<key>Source</key>
<string>Clipboard</string>
</dict>
<dict>
<key>DisplayKind</key>
<string>Window</string>
<key>HonourFailureSettings</key>
<true/>
<key>IncludeStdErr</key>
<true/>
<key>MacroActionType</key>
<string>ExecuteShellScript</string>
<key>Path</key>
<string>~/Workspace/drop-shadow/drop-shadow.sh</string>
<key>Source</key>
<string>Nothing</string>
<key>Text</key>
<string>./Users/personal/Workspace/drop-shadow/drop-shadow.sh /Users/personal/Workspace/drop-shadow/temp.png</string>
<key>TimeOutAbortsMacro</key>
<true/>
<key>TrimResults</key>
<true/>
<key>TrimResultsNew</key>
<true/>
<key>UseText</key>
<true/>
</dict>
</array>
<key>TimeOutAbortsMacro</key>
<true/>
</dict>
</array>
<key>CreationDate</key>
<real>622511932.61007595</real>
<key>ModificationDate</key>
<real>623533929.95638096</real>
<key>Name</key>
<string>Apply shadow to screenshot</string>
<key>Triggers</key>
<array>
<dict>
<key>FireType</key>
<string>Pressed</string>
<key>KeyCode</key>
<integer>21</integer>
<key>MacroTriggerType</key>
<string>HotKey</string>
<key>Modifiers</key>
<integer>768</integer>
</dict>
</array>
<key>UID</key>
<string>5EFD8E79-1CE2-4B4E-95D6-A0156AF1379F</string>
</dict>
</array>
<key>Name</key>
<string>Global Macro Group</string>
<key>ToggleMacroUID</key>
<string>837A4569-414A-45B0-B086-D85B3AAE90D0</string>
<key>UID</key>
<string>55D3F2B4-0024-4857-9E8D-02CF4B05D3D2</string>
</dict>
</array>
</plist>
#!/usr/bin/env bash
# ---------------------------------
# set this script as an executable:
# chmod u+x drop-shadow.sh
# example usage:
# ./Users/personal/Workspace/drop-shadow/drop-shadow.sh /Users/personal/Workspace/drop-shadow/temp.png
# ---------------------------------
# we need a filename as an argument
if [ $# -eq 0 ]; then
echo "Needs the filename as the first argument"
exit -1
fi
# Required package
type /usr/local/bin/convert >/dev/null 2>&1 || { echo >&2 "The convert command must be available (from imagemagick)."; exit 1; }
# use our argument path as our input filename
input_filename="${1}"
# set our output directory for temp images
output_dir="/Users/personal/Workspace/drop-shadow/"
# https://stackoverflow.com/questions/965053/extract-filename-and-extension-in-bash#965072
filename=$(basename -- "${input_filename}")
extension="${filename##*.}"
filename="${filename%.*}"
# get the mean colorspace as a decimal
colorspace=$(/usr/local/bin/convert "${input_filename}" -colorspace gray -format "%[fx:100*mean]%%" info:)
colorspace=$(echo $colorspace|perl -pe 's{\d+\.\d+%}{$&/100}eg')
# chose shadow color based on colorspace of the image
chosen_shadow="#000"
[ "`echo "${colorspace} < 1.0" | bc`" -eq 1 ] && chosen_shadow="#B0B0B0"
[ "`echo "${colorspace} < 0.91" | bc`" -eq 1 ] && chosen_shadow="#AAA"
[ "`echo "${colorspace} < 0.6" | bc`" -eq 1 ] && chosen_shadow="#333"
[ "`echo "${colorspace} < 0.2" | bc`" -eq 1 ] && chosen_shadow="#222"
[ "`echo "${colorspace} < 0.1" | bc`" -eq 1 ] && chosen_shadow="#000"
# generate rounded corners for image
/usr/local/bin/convert "${input_filename}" \( +clone -alpha extract -draw 'fill black polygon 0,0 0,15 15,0 fill white circle 15,15 15,0' \( +clone -flip \) -compose Multiply -composite \( +clone -flop \) -compose Multiply -composite \) -alpha off -compose CopyOpacity -composite "${output_dir}${filename}_shadow.${extension}"
# generate shadow for image
/usr/local/bin/convert "${output_dir}${filename}_shadow.${extension}" \( +clone -background "${chosen_shadow}" -shadow 100x10+0+10 \) +swap -background none -layers merge +repage "${output_dir}${filename}_shadow.${extension}"
# generate whitespace for image
/usr/local/bin/convert "${output_dir}${filename}_shadow.${extension}" -bordercolor none -border 1 -gravity south -background none -splice 0x25 "${output_dir}${filename}_shadow.${extension}"
# copy generated image to clipboard
osascript -e "set the clipboard to (read (POSIX file \"${output_dir}${filename}_shadow.${extension}\") as JPEG picture)"
@Namaskar-1F64F
Copy link

That's cool.

@gatesyp
Copy link

gatesyp commented Sep 23, 2020

That looks really nice , how do I install?

@agates4
Copy link
Author

agates4 commented Aug 3, 2021

updated with dynamically generated whitespace based on image dimensions
and don't need to install copyq - using normal copy tool prepackaged with OS X

#!/usr/bin/env bash

# ---------------------------------
# set this script as an executable:
# chmod u+x drop-shadow.sh

# example usage:
# ./Users/personal/Workspace/drop-shadow/drop-shadow.sh /Users/personal/Workspace/drop-shadow/temp.png
# ---------------------------------

# we need a filename as an argument
if [ $# -eq 0 ]; then
  echo "Needs the filename as the first argument"
  exit -1
fi

# Required package
type /usr/local/bin/convert >/dev/null 2>&1 || { echo >&2 "The convert command must be available (from imagemagick)."; exit 1; }

# use our argument path as our input filename
input_filename="${1}"

# set our output directory for temp images
output_dir="/Users/personal/Workspace/drop-shadow/"

# https://stackoverflow.com/questions/965053/extract-filename-and-extension-in-bash#965072
filename=$(basename -- "${input_filename}")
extension="${filename##*.}"
filename="${filename%.*}"

# get the mean colorspace as a decimal
colorspace=$(/usr/local/bin/convert "${input_filename}" -colorspace gray -format "%[fx:100*mean]%%" info:)
colorspace=$(echo $colorspace|perl -pe 's{\d+\.\d+%}{$&/100}eg')

# chose shadow color based on colorspace of the image
chosen_shadow="#000"
[ "`echo "${colorspace} < 1.0" | bc`" -eq 1 ] && chosen_shadow="#B0B0B0"
[ "`echo "${colorspace} < 0.91" | bc`" -eq 1 ] && chosen_shadow="#AAA"
[ "`echo "${colorspace} < 0.6" | bc`" -eq 1 ] && chosen_shadow="#333"
[ "`echo "${colorspace} < 0.2" | bc`" -eq 1 ] && chosen_shadow="#222"
[ "`echo "${colorspace} < 0.1" | bc`" -eq 1 ] && chosen_shadow="#000"

# generate rounded corners for image
/usr/local/bin/convert "${input_filename}" \( +clone  -alpha extract -draw 'fill black polygon 0,0 0,15 15,0 fill white circle 15,15 15,0' \( +clone -flip \) -compose Multiply -composite \( +clone -flop \) -compose Multiply -composite \) -alpha off -compose CopyOpacity -composite "${output_dir}${filename}_shadow.${extension}"

# calculating whitespace by dimension and our magic numbers
width=`/usr/local/bin/identify ${input_filename} | cut -f 3 -d " " | sed s/x.*//` # width
height=`/usr/local/bin/identify ${input_filename} | cut -f 3 -d " " | sed s/.*x//` # height
whitespace_bottom="$(echo "$width*0.042" | bc)"
whitespace_top="$(echo "$height*0.026" | bc)"
whitespace_sides="$(echo "$height*0.035" | bc)"

# generate shadow for image
/usr/local/bin/convert "${output_dir}${filename}_shadow.${extension}" \( +clone -background "${chosen_shadow}" -shadow 100x10+0+10 \) +swap -background none -layers merge +repage "${output_dir}${filename}_shadow.${extension}"

# generate whitespace for image
/usr/local/bin/convert "${output_dir}${filename}_shadow.${extension}" -bordercolor none -border 1 -gravity south -background none -splice "0x${whitespace_bottom}" "${output_dir}${filename}_shadow.${extension}"
/usr/local/bin/convert "${output_dir}${filename}_shadow.${extension}" -bordercolor none -border 1 -gravity north -background none -splice "0x${whitespace_top}" "${output_dir}${filename}_shadow.${extension}"
/usr/local/bin/convert "${output_dir}${filename}_shadow.${extension}" -bordercolor none -border 1 -gravity east -background none -splice "${whitespace_sides}x0" "${output_dir}${filename}_shadow.${extension}"
/usr/local/bin/convert "${output_dir}${filename}_shadow.${extension}" -bordercolor none -border 1 -gravity west -background none -splice "${whitespace_sides}x0" "${output_dir}${filename}_shadow.${extension}"

# copy generated image to clipboard
osascript -e "set the clipboard to (read (POSIX file \"${output_dir}${filename}_shadow.${extension}\") as JPEG picture)"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment