Skip to content

Instantly share code, notes, and snippets.

@ttscoff
Last active December 26, 2020 16:47
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ttscoff/d11fd063d0047bb0d4d235d2279e2085 to your computer and use it in GitHub Desktop.
Save ttscoff/d11fd063d0047bb0d4d235d2279e2085 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
#!/usr/bin/ruby
# Brett Terpstra <http://brettterpstra.com>
=begin
Example:
> file1@2x%%ohc.png
=> Converts png to jpeg, creates 1x and 2x versions, optimizes both with jpegoptim
Available directives:
%%[och]rXXX[xXXX]
o => optimize image
c => convert png to jpg
h => create a half size image (remove @2x or add _sm)
rXXX[xXXX] => resize to max-width or WxH
Requires jpegoptim, pngcrush, and convert (ImageMagick)
=end
require 'fileutils'
ARGV.each do |arg|
input = File.expand_path(arg)
Process.exit 1 unless File.exists?(input)
extension = File.extname(input)
filename = File.basename(input,extension)
folder = File.dirname(input)
if filename =~ /%%/
targets = []
m = filename.match(/%%([hcor\dx]+)$/)
unless m.nil?
directives = m[1]
filename.sub!(/%%[hcor\dx]+$/,'')
if directives =~ /c/ && extension =~ /\.png/i
target = File.join(folder,filename+".jpg")
print "Converting #{input} -> #{target}... "
res = system %Q{/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
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")
FileUtils.mv input, target, :force => true
input = target
targets.push(target)
end
if directives =~ /r(\d+(x(\d+))?)/
width = $1
dim = $2.nil? ? "#{width}x#{width}" : "#{width}x#{$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 %Q{/usr/local/bin/convert "#{input}" -adaptive-resize #{dim} "#{resized}" &> /dev/null}
if res
puts "OK"
FileUtils.mv input, File.expand_path("~/.Trash"), :force => true
targets.delete(input)
targets.push(resized)
input = resized
else
puts "ERROR"
Process.exit 1
end
end
if directives =~ /h/
if filename =~ /@2x$/
halfsize = File.join(folder, filename.sub(/@2x$/,'') + extension)
else
halfsize = File.join(folder, filename + "_sm" + extension)
end
print "Halving #{input} -> #{halfsize}... "
puts %Q{/usr/local/bin/convert "#{input}" -adaptive-resize 50% "#{halfsize}" &> /dev/null}
res = system %Q{/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
if directives =~ /o/
targets.each do |target|
print "Optimizing #{target}... "
if target =~ /\.jpe?g$/i && File.exists?('/usr/local/bin/jpegoptim')
res = system %Q{/usr/local/bin/jpegoptim -fopt --strip-all -m80 -T10 "#{target}" &> /dev/null}
elsif target =~ /.png$/i && File.exists?('/usr/local/bin/pngcrush')
res = system %Q{/usr/local/bin/pngcrush -q -ow "#{target}" &> /dev/null}
end
puts res ? "OK" : "ERROR"
end
end
end
end
end
@jgclark
Copy link

jgclark commented Apr 2, 2018

Thanks for this, Brett. I have extended it slightly to allow originals to kept, which I find helpful when working with photos. I'm not very familiar with github gists, but have forked it to https://gist.github.com/jgclark/2f82e4a27a6157d5608cfc122b26891f with this extension.

@ttscoff
Copy link
Author

ttscoff commented Apr 9, 2018

@jgclark 👍

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