-
-
Save jgclark/2f82e4a27a6157d5608cfc122b26891f to your computer and use it in GitHub Desktop.
Script intended for use with Hazel to resize/optimize web images based on directives in image filenames. Extended from ttscoff's original.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
# From Brett Terpstra <https://gist.github.com/ttscoff/d11fd063d0047bb0d4d235d2279e2085> | |
# extended by Jonathan Clark 2.4.2018 to allow original to be kept | |
# extended further, 11.9.2020 to allow borders to be added (currently white and/or black) | |
# and published at https://gist.github.com/jgclark/2f82e4a27a6157d5608cfc122b26891f | |
# | |
# Example: | |
# > file1@2x%%ohc.png | |
# => Converts png to jpeg, creates 1x and 2x versions, optimizes both with jpegoptim | |
# | |
# Available directives: | |
# | |
# %%[ochdkbw]rXXX[xXXX] | |
# o => optimize image | |
# c => convert png to jpg | |
# h => create a half size image (remove @2x or add _sm) | |
# k => keep original | |
# rXXX[xXXX] => resize to max-width or WxH | |
# b => add black border (default 2 px) | |
# w => add white border (default 8 px). | |
# If both borders are present, they are added in order they appear. | |
# Borders are added after resize and conversion operations. | |
# | |
# Requires jpegoptim, pngcrush, and convert (ImageMagick) | |
require 'fileutils' | |
ARGV.each do |arg| | |
input = File.expand_path(arg) | |
Process.exit 1 unless File.exist?(input) | |
extension = File.extname(input) | |
filename = File.basename(input, extension) | |
folder = File.dirname(input) | |
keep = false | |
next unless filename =~ /%%/ | |
targets = [] | |
m = filename.match(/%%([hcor\dxkbw]+)$/) | |
next if m.nil? | |
directives = m[1] | |
filename.sub!(/%%[hcor\dxkbw]+$/, '') | |
# Convert png -> jpg | |
if directives =~ /c/ && extension =~ /\.png/i | |
target = File.join(folder, filename + '.jpg') | |
print "Converting #{input} -> #{target}... " | |
res = system %(/usr/local/bin/convert "#{input}" -background white -flatten -alpha off "#{target}" &> /dev/null) | |
if res | |
puts 'OK' | |
FileUtils.mv input, File.expand_path('~/.Trash'), force: true unless keep | |
extension = '.jpg' | |
input = target | |
targets.push(target) | |
else | |
puts 'ERROR' | |
Process.exit 1 | |
end | |
else | |
target = File.join(folder, filename + extension) | |
FileUtils.cp input, File.expand_path('~/.Trash') unless keep | |
FileUtils.mv input, target, force: true | |
input = target | |
targets.push(target) | |
end | |
if directives =~ /k/ | |
keep = true | |
puts 'Will keep original' | |
end | |
# resize to max-width or WxH | |
if directives =~ /r(\d+(x(\d+))?)/ | |
width = Regexp.last_match(1) | |
dim = Regexp.last_match(2).nil? ? "#{width}x#{width}" : "#{width}x#{Regexp.last_match(3)}" | |
if filename =~ /@2x$/ && directives =~ /h/ | |
size = (width.to_i / 2).to_s | |
puts "#{width} / 2 = #{size}" | |
else | |
size = width.to_s | |
puts "Fullsize = #{size}" | |
end | |
filename.sub!(/(@2x)?$/, "-#{size}\\1") | |
resized = File.join(folder, filename + extension) | |
print "Resizing #{input} to #{dim} -> #{resized}... " | |
res = system %(/usr/local/bin/convert "#{input}" -adaptive-resize #{dim} "#{resized}" &> /dev/null) | |
if res | |
puts 'OK' | |
unless keep | |
FileUtils.mv input, File.expand_path('~/.Trash'), force: true | |
targets.delete(input) | |
end | |
targets.push(resized) | |
input = resized | |
else | |
puts 'ERROR' | |
Process.exit 1 | |
end | |
end | |
# create a half size image (remove @2x or add _sm) | |
if directives =~ /h/ | |
halfsize = if filename =~ /@2x$/ | |
File.join(folder, filename.sub(/@2x$/, '') + extension) | |
else | |
File.join(folder, filename + '_sm' + extension) | |
end | |
print "Halving #{input} -> #{halfsize}... " | |
puts %(/usr/local/bin/convert "#{input}" -adaptive-resize 50% "#{halfsize}" &> /dev/null) | |
res = system %(/usr/local/bin/convert "#{input}" -adaptive-resize 50% "#{halfsize}" &> /dev/null) | |
if res | |
puts 'OK' | |
targets.push(halfsize) | |
else | |
puts 'ERROR' | |
Process.exit 1 | |
end | |
end | |
# Add border(s) | |
if directives =~ /[wb]/ | |
temp = File.join(folder, filename + '_temp' + extension) | |
if directives =~ /wb/ | |
puts 'Adding white then black borders ...' | |
bordered = File.join(folder, filename + '_borderwb' + extension) | |
# it seems these can't both be done as one operation | |
res = system %(/usr/local/bin/convert "#{input}" -bordercolor white -border 8 "#{temp}" &> /dev/null) | |
unless res | |
puts 'ERROR' | |
Process.exit 1 | |
end | |
res = system %(/usr/local/bin/convert "#{temp}" -bordercolor black -border 2 "#{bordered}" &> /dev/null) | |
elsif directives =~ /bw/ | |
puts 'Adding black then white borders ...' | |
bordered = File.join(folder, filename + '_borderbw' + extension) | |
# it seems these can't both be done as one operation | |
res = system %(/usr/local/bin/convert "#{input}" -bordercolor black -border 2 "#{temp}" &> /dev/null) | |
unless res | |
puts 'ERROR' | |
Process.exit 1 | |
end | |
res = system %(/usr/local/bin/convert "#{temp}" -bordercolor white -border 8 "#{bordered}" &> /dev/null) | |
elsif directives =~ /w/ && directives !~ /b/ | |
puts 'Adding white border ...' | |
bordered = File.join(folder, filename + '_borderw' + extension) | |
res = system %(/usr/local/bin/convert "#{input}" -bordercolor white -border 8 "#{bordered}" &> /dev/null) | |
elsif directives =~ /b/ && directives !~ /w/ | |
puts 'Adding black border ...' | |
bordered = File.join(folder, filename + '_borderb' + extension) | |
res = system %(/usr/local/bin/convert "#{input}" -bordercolor black -border 2 "#{bordered}" &> /dev/null) | |
end | |
if !res | |
puts 'ERROR' | |
Process.exit 1 | |
else | |
puts 'OK' | |
targets.push(bordered) | |
# delete temporary file | |
FileUtils.mv temp, File.expand_path('~/.Trash'), force: true | |
unless keep | |
FileUtils.mv input, File.expand_path('~/.Trash'), force: true | |
targets.delete(input) | |
end | |
end | |
end | |
# Optimise target | |
next unless directives =~ /o/ | |
targets.each do |target| | |
print "Optimizing #{target}... " | |
if target =~ /\.jpe?g$/i && File.exist?('/usr/local/bin/jpegoptim') | |
res = system %(/usr/local/bin/jpegoptim -fopt --strip-all -m80 -T10 "#{target}" &> /dev/null) | |
elsif target =~ /.png$/i && File.exist?('/usr/local/bin/pngcrush') | |
res = system %(/usr/local/bin/pngcrush -q -ow "#{target}" &> /dev/null) | |
end | |
puts res ? 'OK' : 'ERROR' | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment