Description
MMThumb is a sane and simple but flexible approach to automating the common tasks of processing images for use in webpages. If your image workflow includes applying:
- Pre-Processing ...sharpen 2x2, normalize levels
- Generating a couple of different outputs ...thumbnail, preview, full-view
- Post-Processing ...watermark, vignette
Then this gem will serve you right.
This gem has been written with the intent that you should write minimal code to do what you want, but it should not limit you - configuration options are chained, so you can have sane defaults and still easily handle corner cases.
It has also been written with the intent to be usable both as an offline batch processor or as an engine for a long-running service process - therefore the approach to exception handling may be slightly different than usual.
Current version uses the mini_magick gem and therefore you will need either ImageMagick or GraphicsMagick. This, in my humble opinion, gives you by default the best trade-off between performance and functionality.
Performance note:
Due to how mini_magick
works the preprocess
and postprocess
blocks will be
called for each output
block, contrary to the intuition that they should run
once each (before and after outputs, respectively). In other words right now they
are mostly a visual convenience to separate things.
Install
Dependencies:
Install:
$ gem install mmthumb
Examples
First my personal most-common-ever use-case, as a simple CLI batch converter:
#!/usr/bin/env ruby
# encoding: utf-8
#
require 'mmthumb'
conv = MMThumb::Converter.new
conv.preprocess do |img, opts|
if opts[:photo]
img.normalize
img.sharpen '2x2'
end
end
conv.add_output(:thumb) {|img| img.resize('320x240>') }
conv.add_output(:full) {|img| img.resize('1024x768>') }
ARGV.each do |path|
puts path
ext = File.extname(path).slice(1, 4).downcase
ext = 'jpg' if ext == 'jpeg'
opts = {
:format => ext,
:photo => ext == 'jpg',
}
begin
res = conv.convert(path, opts)
rescue MMThumb::Error => e
STDERR.puts "ERROR: #{e}"
else
res.each do |key, info|
if info[:done]
puts info[:path]
else
STDERR.puts "ERROR: (#{key}) #{info[:error]}"
end
end
File.delete(path) if res.values.all? {|e| e[:done] }
end
end
You can use everything mini_magick
has to offer:
# Configure
conv = MMThumb::Converter.new
conv.preprocess do |img|
img.normalize
img.sharpen '2x2'
end
conv.add_output(:thumb) do |img|
img.resize '160x160>'
img.vignette '2x3+2+2'
end
conv.add_output(:preview) do |img|
img.resize '320x256>'
end
conv.add_output(:full) do |img|
img.resize '1920x1080>'
img.draw 'text 10, 10 "(C) Website"'
end
Options are both chained and available for you inside the blocks:
@conv = MMThumb::Converter.new(:path => '/static/assets')
@conv.preprocess do |img, opts|
img.sharpen '2x2' if opts[:photo]
end
@conv.add_output(:full) do |img, opts|
img.resize '1920x1080>'
img.draw "text 10,10 '(C) #{opts[:user]}'"
end
batch.each do |path, user|
ext = File.extname(path).slice(1, 4).downcase
ext = 'jpg' if ext == 'jpeg'
opts = {
:format => ext,
:photo => ext == 'jpg',
:user => user.fullname,
:prefix => user.id,
}
res = @conv.convert(path, opts)
if res.values.all? {|e| e[:done] }
File.delete(path)
else
log :error, "Processing #{path} for #{user}"
res.values.select {|e| e[:done] }.each {|e| File.delete(e[:path]) }
end
end
Testing
I've included a rather large (2.3 MB) JPEG file for tests.
When you run rake spec
a number of test images will be generated and left
in the spec
folder, so that you can visually inspect that everything works
as advertised. These images are deleted before tests are run, but if you want
to clean them afterwards there is the rake clean
task.
I believe the test don't cover everything, but they are helpful nonetheless.
Trivia: The box of floppy disks is about 140 MB (or 172 MB if you use an Amiga). It weights a couple kg.
Possible TODO
- Add support for other converters (speed vs. functionality)
- Make
pre
andpost
blocks run only once per image
Copyright
Copyright (c) 2014 Piotr S. Staszewski
See {file:LICENSE.txt} for details.