mmthumb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +2 -0
- data/.gitignore +5 -0
- data/.yardopts +5 -0
- data/LICENSE.txt +23 -0
- data/README.md +174 -0
- data/Rakefile +46 -0
- data/examples/for_web.rb +42 -0
- data/lib/mmthumb.rb +204 -0
- data/lib/mmthumb/version.rb +7 -0
- data/mmthumb.gemspec +29 -0
- data/spec/mmthumb_spec.rb +124 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/test.jpg +0 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f4c8c60416b5f9ee92cd320decb7313f9e8c5449
|
4
|
+
data.tar.gz: a693342d6b6820e93f1aca706d66d0ca2b570873
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 90ba91a6e46defe6eb947d7d1c7b0f38fbdeb0e617ef36afa00d66482e5d07447c18b3b186fc6bdc498fa56e17785e6e83df97f6784e1ab115a609d5bc57ea56
|
7
|
+
data.tar.gz: d93e4d7869307cb75d1574edd02a7d7ec60b895fffc4682328a3df424d11a7cce140b8244ec3234e8ac99cd2012c5307d0663a663eb038b2a45f60a6e76929ef
|
data/.document
ADDED
data/.yardopts
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2014, Piotr S. Staszewski
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
15
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
16
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
18
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
20
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
21
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
22
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
23
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
# MMThumb
|
2
|
+
|
3
|
+
* [Homepage](https://github.com/drbig/)
|
4
|
+
* [Documentation](http://rubydoc.info/gems/mmthumb/frames)
|
5
|
+
|
6
|
+
## Description
|
7
|
+
|
8
|
+
MMThumb is a sane and simple but flexible approach to automating the common
|
9
|
+
tasks of
|
10
|
+
processing images for use in webpages. If your image workflow includes applying:
|
11
|
+
|
12
|
+
* Pre-Processing
|
13
|
+
...sharpen 2x2, normalize levels
|
14
|
+
* Generating a couple of different outputs
|
15
|
+
...thumbnail, preview, full-view
|
16
|
+
* Post-Processing
|
17
|
+
...watermark, vignette
|
18
|
+
|
19
|
+
Then this gem will serve you right.
|
20
|
+
|
21
|
+
This gem has been written with the intent that you should write minimal code
|
22
|
+
to do what you want, but it should not limit you - configuration options are
|
23
|
+
chained, so you can have sane defaults and still easily handle corner cases.
|
24
|
+
|
25
|
+
It has also been written with the intent to be usable both as an offline batch
|
26
|
+
processor or as an engine for a long-running service process - therefore the
|
27
|
+
approach to exception handling may be slightly different than usual.
|
28
|
+
|
29
|
+
Current version uses the [mini_magick](http://rubygems.org/gems/mini_magick)
|
30
|
+
gem and therefore you will need either [ImageMagick](http://www.imagemagick.org/)
|
31
|
+
or [GraphicsMagick](www.graphicsmagick.org). This, in my humble opinion, gives you
|
32
|
+
by default the best trade-off between performance and functionality.
|
33
|
+
|
34
|
+
**Performance note:**
|
35
|
+
|
36
|
+
Due to how `mini_magick` works the `preprocess` and `postprocess` blocks will be
|
37
|
+
called *for each* `output` block, contrary to the intuition that they should run
|
38
|
+
once each (before and after outputs, respectively). In other words right now they
|
39
|
+
are mostly a visual convenience to separate things.
|
40
|
+
|
41
|
+
## Install
|
42
|
+
|
43
|
+
Dependencies:
|
44
|
+
|
45
|
+
* [ImageMagick](http://www.imagemagick.org/) or [GraphicsMagick](www.graphicsmagick.org)
|
46
|
+
* [mini_magick](http://rubygems.org/gems/mini_magick)
|
47
|
+
|
48
|
+
Install:
|
49
|
+
|
50
|
+
$ gem install mmthumb
|
51
|
+
|
52
|
+
## Examples
|
53
|
+
|
54
|
+
First my personal most-common-ever use-case, as a simple CLI batch converter:
|
55
|
+
|
56
|
+
#!/usr/bin/env ruby
|
57
|
+
# encoding: utf-8
|
58
|
+
#
|
59
|
+
|
60
|
+
require 'mmthumb'
|
61
|
+
|
62
|
+
conv = MMThumb::Converter.new
|
63
|
+
conv.preprocess do |img, opts|
|
64
|
+
if opts[:photo]
|
65
|
+
img.normalize
|
66
|
+
img.sharpen '2x2'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
conv.add_output(:thumb) {|img| img.resize('320x240>') }
|
70
|
+
conv.add_output(:full) {|img| img.resize('1024x768>') }
|
71
|
+
|
72
|
+
ARGV.each do |path|
|
73
|
+
puts path
|
74
|
+
|
75
|
+
ext = File.extname(path).slice(1, 4).downcase
|
76
|
+
ext = 'jpg' if ext == 'jpeg'
|
77
|
+
opts = {
|
78
|
+
:format => ext,
|
79
|
+
:photo => ext == 'jpg',
|
80
|
+
}
|
81
|
+
|
82
|
+
begin
|
83
|
+
res = conv.convert(path, opts)
|
84
|
+
rescue MMThumb::Error => e
|
85
|
+
STDERR.puts "ERROR: #{e}"
|
86
|
+
else
|
87
|
+
res.each do |key, info|
|
88
|
+
if info[:done]
|
89
|
+
puts info[:path]
|
90
|
+
else
|
91
|
+
STDERR.puts "ERROR: (#{key}) #{info[:error]}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
File.delete(path) if res.values.all? {|e| e[:done] }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
You can use everything `mini_magick` has to offer:
|
100
|
+
|
101
|
+
# Configure
|
102
|
+
conv = MMThumb::Converter.new
|
103
|
+
conv.preprocess do |img|
|
104
|
+
img.normalize
|
105
|
+
img.sharpen '2x2'
|
106
|
+
end
|
107
|
+
conv.add_output(:thumb) do |img|
|
108
|
+
img.resize '160x160>'
|
109
|
+
img.vignette '2x3+2+2'
|
110
|
+
end
|
111
|
+
conv.add_output(:preview) do |img|
|
112
|
+
img.resize '320x256>'
|
113
|
+
end
|
114
|
+
conv.add_output(:full) do |img|
|
115
|
+
img.resize '1920x1080>'
|
116
|
+
img.draw 'text 10, 10 "(C) Website"'
|
117
|
+
end
|
118
|
+
|
119
|
+
Options are both chained and available for you inside the blocks:
|
120
|
+
|
121
|
+
@conv = MMThumb::Converter.new(:path => '/static/assets')
|
122
|
+
@conv.preprocess do |img, opts|
|
123
|
+
img.sharpen '2x2' if opts[:photo]
|
124
|
+
end
|
125
|
+
@conv.add_output(:full) do |img, opts|
|
126
|
+
img.resize '1920x1080>'
|
127
|
+
img.draw "text 10,10 '(C) #{opts[:user]}'"
|
128
|
+
end
|
129
|
+
|
130
|
+
batch.each do |path, user|
|
131
|
+
ext = File.extname(path).slice(1, 4).downcase
|
132
|
+
ext = 'jpg' if ext == 'jpeg'
|
133
|
+
|
134
|
+
opts = {
|
135
|
+
:format => ext,
|
136
|
+
:photo => ext == 'jpg',
|
137
|
+
:user => user.fullname,
|
138
|
+
:prefix => user.id,
|
139
|
+
}
|
140
|
+
|
141
|
+
res = @conv.convert(path, opts)
|
142
|
+
if res.values.all? {|e| e[:done] }
|
143
|
+
File.delete(path)
|
144
|
+
else
|
145
|
+
log :error, "Processing #{path} for #{user}"
|
146
|
+
res.values.select {|e| e[:done] }.each {|e| File.delete(e[:path]) }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
## Testing
|
151
|
+
|
152
|
+
I've included a rather large (2.3 MB) JPEG file for tests.
|
153
|
+
|
154
|
+
When you run `rake spec` a number of test images will be generated and left
|
155
|
+
in the `spec` folder, so that you can visually inspect that everything works
|
156
|
+
as advertised. These images are deleted before tests are run, but if you want
|
157
|
+
to clean them afterwards there is the `rake clean` task.
|
158
|
+
|
159
|
+
I believe the test don't cover everything, but they are helpful nonetheless.
|
160
|
+
|
161
|
+
*Trivia:* The box of [floppy disks](http://en.wikipedia.org/wiki/Floppy_disk) is about
|
162
|
+
140 MB (or 172 MB if you use an [Amiga](http://en.wikipedia.org/wiki/Amiga_1200)).
|
163
|
+
It weights a couple kg.
|
164
|
+
|
165
|
+
## Possible TODO
|
166
|
+
|
167
|
+
* Add support for other converters (speed vs. functionality)
|
168
|
+
* Make `pre` and `post` blocks run only once per image
|
169
|
+
|
170
|
+
## Copyright
|
171
|
+
|
172
|
+
Copyright (c) 2014 Piotr S. Staszewski
|
173
|
+
|
174
|
+
See {file:LICENSE.txt} for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
begin
|
7
|
+
gem 'rubygems-tasks', '~> 0.2'
|
8
|
+
require 'rubygems/tasks'
|
9
|
+
|
10
|
+
Gem::Tasks.new
|
11
|
+
rescue LoadError => e
|
12
|
+
warn e.message
|
13
|
+
warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
gem 'rspec', '~> 2.4'
|
18
|
+
require 'rspec/core/rake_task'
|
19
|
+
|
20
|
+
RSpec::Core::RakeTask.new
|
21
|
+
rescue LoadError => e
|
22
|
+
task :spec do
|
23
|
+
abort "Please run `gem install rspec` to install RSpec."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
task :test => :spec
|
28
|
+
task :default => :spec
|
29
|
+
|
30
|
+
begin
|
31
|
+
gem 'yard', '~> 0.8'
|
32
|
+
require 'yard'
|
33
|
+
|
34
|
+
YARD::Rake::YardocTask.new
|
35
|
+
rescue LoadError => e
|
36
|
+
task :yard do
|
37
|
+
abort "Please run `gem install yard` to install YARD."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
task :doc => :yard
|
42
|
+
|
43
|
+
task :clean do
|
44
|
+
target = File.join(File.dirname(__FILE__), 'spec', 'test_*')
|
45
|
+
Dir.glob(target).each {|path| File.delete(path) }
|
46
|
+
end
|
data/examples/for_web.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'mmthumb'
|
6
|
+
|
7
|
+
conv = MMThumb::Converter.new
|
8
|
+
conv.preprocess do |img, opts|
|
9
|
+
if opts[:photo]
|
10
|
+
img.normalize
|
11
|
+
img.sharpen '2x2'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
conv.add_output(:thumb) {|img| img.resize('320x240>') }
|
15
|
+
conv.add_output(:full) {|img| img.resize('1024x768>') }
|
16
|
+
|
17
|
+
ARGV.each do |path|
|
18
|
+
puts path
|
19
|
+
|
20
|
+
ext = File.extname(path).slice(1, 4).downcase
|
21
|
+
ext = 'jpg' if ext == 'jpeg'
|
22
|
+
opts = {
|
23
|
+
:format => ext,
|
24
|
+
:photo => ext == 'jpg',
|
25
|
+
}
|
26
|
+
|
27
|
+
begin
|
28
|
+
res = conv.convert(path, opts)
|
29
|
+
rescue MMThumb::Error => e
|
30
|
+
STDERR.puts "ERROR: #{e}"
|
31
|
+
else
|
32
|
+
res.each do |key, info|
|
33
|
+
if info[:done]
|
34
|
+
puts info[:path]
|
35
|
+
else
|
36
|
+
STDERR.puts "ERROR: (#{key}) #{info[:error]}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
File.delete(path) if res.values.all? {|e| e[:done] }
|
41
|
+
end
|
42
|
+
end
|
data/lib/mmthumb.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
|
4
|
+
require 'mini_magick'
|
5
|
+
require 'mmthumb/version'
|
6
|
+
|
7
|
+
# See {file:README.md} for practical examples.
|
8
|
+
module MMThumb
|
9
|
+
# Default output format
|
10
|
+
FORMAT = 'jpg'
|
11
|
+
# Default output JPEG quality
|
12
|
+
QUALITY = '80'
|
13
|
+
|
14
|
+
# MMThumb generated errors
|
15
|
+
class Error < StandardError; end
|
16
|
+
|
17
|
+
# See {file:README.md} for practical examples.
|
18
|
+
# @attr config [Hash] Instance configuration
|
19
|
+
class Converter
|
20
|
+
attr_accessor :config
|
21
|
+
|
22
|
+
# New converter
|
23
|
+
#
|
24
|
+
# For options see `setup`. The options you pass here will be
|
25
|
+
# preserved as defaults.
|
26
|
+
#
|
27
|
+
# @see #setup
|
28
|
+
# @param config [Hash] Configuration options
|
29
|
+
def initialize(config = {})
|
30
|
+
@default = config
|
31
|
+
setup
|
32
|
+
end
|
33
|
+
|
34
|
+
# Reset instance config to defaults
|
35
|
+
#
|
36
|
+
# @see #setup
|
37
|
+
# @see #initialize
|
38
|
+
# @return [Hash] Configuration options
|
39
|
+
def reset!; setup; end
|
40
|
+
|
41
|
+
# Add preprocess block
|
42
|
+
#
|
43
|
+
# The block will be executed before outputs.
|
44
|
+
#
|
45
|
+
# @return [Block] Given block
|
46
|
+
def preprocess(&blk); @before = blk; end
|
47
|
+
|
48
|
+
# Remove preprocess block
|
49
|
+
#
|
50
|
+
# @return [nil]
|
51
|
+
def del_preprocess!; @before = nil; end
|
52
|
+
|
53
|
+
# Check if preprocess block is present
|
54
|
+
#
|
55
|
+
# @return [Boolean]
|
56
|
+
def preprocess?; @before ? true : false; end
|
57
|
+
|
58
|
+
# Add postprocess block
|
59
|
+
#
|
60
|
+
# The block will be executed after outputs.
|
61
|
+
#
|
62
|
+
# @return [Block] Given block
|
63
|
+
def postprocess(&blk); @after = blk; end
|
64
|
+
|
65
|
+
# Remove postprocess block
|
66
|
+
#
|
67
|
+
# @return [nil]
|
68
|
+
def del_postprocess!; @after = nil; end
|
69
|
+
|
70
|
+
# Check if postprocess block is present
|
71
|
+
#
|
72
|
+
# @return [Boolean]
|
73
|
+
def postprocess?; @after ? true : false; end
|
74
|
+
|
75
|
+
# Add output
|
76
|
+
#
|
77
|
+
# @see #setup
|
78
|
+
# @param key [Symbol, String] Unique key for the output
|
79
|
+
# @param opts [Hash] Configuration options
|
80
|
+
# @param block [Block] Code for the output
|
81
|
+
def add_output(key, opts = {}, &block)
|
82
|
+
@outputs[key] = [opts, block]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Remove output
|
86
|
+
#
|
87
|
+
# @return [Array, nil]
|
88
|
+
def del_output(key); @outputs.delete(key); end
|
89
|
+
|
90
|
+
# Get outputs
|
91
|
+
#
|
92
|
+
# @return [Hash<Symbol, Array>]
|
93
|
+
def outputs; @outputs; end
|
94
|
+
|
95
|
+
# Convert image to given outputs
|
96
|
+
#
|
97
|
+
# Configuration options are chained and calculated on each convert with
|
98
|
+
# the following hierarchy: instance options - output options - convert
|
99
|
+
# call options (this list is lowest-to-highest priority order). Thus you
|
100
|
+
# can easily override any option.
|
101
|
+
#
|
102
|
+
# Will raise `Error` if given file is unreadable, it *won't* raise
|
103
|
+
# exceptions on *any other errors*. Instead error information will
|
104
|
+
# be returned with the result.
|
105
|
+
#
|
106
|
+
# The returned hash keys correspond to the output keys, and each
|
107
|
+
# value will be another hash; which will contain either `:done => true`
|
108
|
+
# and `:path => String` when successful, or `:done => false` and
|
109
|
+
# `:error => Exception` if not.
|
110
|
+
#
|
111
|
+
# @see #setup
|
112
|
+
# @param path [String] Path to file to convert
|
113
|
+
# @param opts [Hash] Configuration options
|
114
|
+
# @return [Hash<Symbol, Hash>] Results
|
115
|
+
def convert(path, opts = {})
|
116
|
+
return nil if @outputs.empty?
|
117
|
+
|
118
|
+
input = File.absolute_path(path)
|
119
|
+
raise Error, 'File is unreadable' unless File.readable? input
|
120
|
+
|
121
|
+
res = Hash.new
|
122
|
+
@outputs.each_pair do |key, (cfg, blk)|
|
123
|
+
config = @config.merge(cfg).merge(opts)
|
124
|
+
config[:path] ||= File.dirname(input)
|
125
|
+
config[:basename] ||= File.basename(path, File.extname(path))
|
126
|
+
config[:suffix] ||= '_' + key.to_s
|
127
|
+
output = output_path(config)
|
128
|
+
|
129
|
+
begin
|
130
|
+
img = MiniMagick::Image.open(input)
|
131
|
+
@before.call(img, config) if @before
|
132
|
+
|
133
|
+
img.format(config[:format])
|
134
|
+
blk.call(img, config) if blk
|
135
|
+
|
136
|
+
@after.call(img, config) if @after
|
137
|
+
|
138
|
+
img.quality(config[:quality])
|
139
|
+
img.write(output)
|
140
|
+
rescue StandardError => e
|
141
|
+
res[key] = {
|
142
|
+
:done => false,
|
143
|
+
:error => e,
|
144
|
+
}
|
145
|
+
else
|
146
|
+
res[key] = {
|
147
|
+
:done => true,
|
148
|
+
:path => output,
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
res
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
# Setup instance
|
159
|
+
#
|
160
|
+
# You can keep any options you want inside the `@config` hash, but these
|
161
|
+
# keys are used internally for:
|
162
|
+
#
|
163
|
+
# * `:format` - output format as an extension without a dot (e.g. `'jpg'`)
|
164
|
+
# * `:quality` - string indicating JPEG quality (e.g. `'80'`)
|
165
|
+
# * `:path` - string indicating target directory
|
166
|
+
# * `:basename` - basename of the output file
|
167
|
+
# * `:prefix` - prefix to add to the output filename
|
168
|
+
# * `:suffix` - suffix to add to the output filename
|
169
|
+
#
|
170
|
+
# If `:path => nil` then outputs will be saved in the directory where the
|
171
|
+
# source file is located.
|
172
|
+
#
|
173
|
+
# If `:basename => nil` then the source file basename will be used.
|
174
|
+
#
|
175
|
+
# If `:suffix => nil` then the `:key` of the output will be added (after an
|
176
|
+
# `_`) to the output filename.
|
177
|
+
#
|
178
|
+
# @return [Hash] Configuration options
|
179
|
+
def setup
|
180
|
+
@before = nil
|
181
|
+
@outputs = Hash.new
|
182
|
+
@after = nil
|
183
|
+
|
184
|
+
@config = {
|
185
|
+
:format => FORMAT,
|
186
|
+
:quality => QUALITY,
|
187
|
+
:path => nil,
|
188
|
+
:prefix => '',
|
189
|
+
}.merge!(@default)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Calculate output path
|
193
|
+
#
|
194
|
+
# @see #setup
|
195
|
+
# @param opts [Hash] Configuration options
|
196
|
+
# @return [String] Full output file path
|
197
|
+
def output_path(opts)
|
198
|
+
File.join(opts[:path], opts[:prefix] +\
|
199
|
+
opts[:basename] +\
|
200
|
+
opts[:suffix] + '.' +\
|
201
|
+
opts[:format])
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
data/mmthumb.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
|
4
|
+
require File.expand_path('../lib/mmthumb/version', __FILE__)
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'mmthumb'
|
8
|
+
s.version = MMThumb::VERSION
|
9
|
+
s.date = Time.now
|
10
|
+
|
11
|
+
s.summary = %q{Convenient image converter for common workflows}
|
12
|
+
s.description = %q{Define pre-, post- and a number of output operations and let MMThumb do the work. Will fit well with offline batch-processing just as well as as a component of a continuous online service. Single dependency.}
|
13
|
+
s.license = 'BSD'
|
14
|
+
s.authors = ['Piotr S. Staszewski']
|
15
|
+
s.email = 'p.staszewski@gmail.com'
|
16
|
+
s.homepage = 'https://github.com/drbig/mmthumb'
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = s.files.grep(%r{^spec/})
|
20
|
+
s.require_paths = ['lib']
|
21
|
+
|
22
|
+
s.required_ruby_version = '>= 1.8.7'
|
23
|
+
|
24
|
+
s.add_dependency 'mini_magick', '~> 3.7'
|
25
|
+
|
26
|
+
s.add_development_dependency 'rspec', '~> 2.4'
|
27
|
+
s.add_development_dependency 'rubygems-tasks', '~> 0.2'
|
28
|
+
s.add_development_dependency 'yard', '~> 0.8'
|
29
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
require 'mmthumb'
|
6
|
+
|
7
|
+
describe 'MMThumb' do
|
8
|
+
it 'should have a VERSION constant' do
|
9
|
+
expect(MMThumb::VERSION).to_not be_empty
|
10
|
+
expect(MMThumb::VERSION).to be_a(String)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have a FORMAT constant' do
|
14
|
+
expect(MMThumb::FORMAT).to_not be_empty
|
15
|
+
expect(MMThumb::FORMAT).to be_a(String)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should have a QUALITY constant' do
|
19
|
+
expect(MMThumb::QUALITY).to_not be_empty
|
20
|
+
expect(MMThumb::QUALITY).to be_a(String)
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'Error' do
|
24
|
+
it 'should be a subclass of StandardError' do
|
25
|
+
expect(MMThumb::Error.new).to be_a(StandardError)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'Converter' do
|
30
|
+
before(:all) do
|
31
|
+
@mmt = MMThumb::Converter.new
|
32
|
+
@target = File.dirname(__FILE__)
|
33
|
+
@test_image = File.join(@target, 'test.jpg')
|
34
|
+
Dir.glob(File.join(@target, 'test_*')).each {|path| File.delete(path) }
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should accept preprocessing' do
|
38
|
+
expect(@mmt.preprocess?).to be_false
|
39
|
+
@mmt.preprocess {|img| img.sharpen '2x2' }
|
40
|
+
expect(@mmt.preprocess?).to be_true
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should accept postprocessing' do
|
44
|
+
expect(@mmt.postprocess?).to be_false
|
45
|
+
@mmt.postprocess do |img|
|
46
|
+
img.vignette '2x3+2+2'
|
47
|
+
img.draw 'text 10,10 "TEST TEST TEST"'
|
48
|
+
end
|
49
|
+
expect(@mmt.postprocess?).to be_true
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should accept outputs' do
|
53
|
+
@mmt.add_output(:thumb) do |img|
|
54
|
+
img.resize('320x256>')
|
55
|
+
end
|
56
|
+
@mmt.add_output(:full) do |img|
|
57
|
+
img.resize('1024x768>')
|
58
|
+
end
|
59
|
+
expect(@mmt.outputs.length).to eq 2
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should convert properly' do
|
63
|
+
res = @mmt.convert(@test_image)
|
64
|
+
res.each_value do |info|
|
65
|
+
expect(info[:done]).to be_true
|
66
|
+
expect(File.exists?(info[:path])).to be_true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should reset to defaults' do
|
71
|
+
default = @mmt.reset!
|
72
|
+
expect(default[:format]).to eq MMThumb::FORMAT
|
73
|
+
expect(default[:quality]).to eq MMThumb::QUALITY
|
74
|
+
expect(default[:prefix]).to eq ''
|
75
|
+
expect(@mmt.preprocess?).to be_false
|
76
|
+
expect(@mmt.postprocess?).to be_false
|
77
|
+
expect(@mmt.outputs).to be_empty
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should correctly use options' do
|
81
|
+
target = File.join(@target, 'test_changed_suffix.gif')
|
82
|
+
|
83
|
+
@mmt.config[:format] = 'gif'
|
84
|
+
@mmt.config[:prefix] = 'test_'
|
85
|
+
@mmt.config[:basename] = 'changed'
|
86
|
+
@mmt.config[:suffix] = '_suffix'
|
87
|
+
|
88
|
+
@mmt.add_output(:test) {|img| img.resize('160x160>') }
|
89
|
+
|
90
|
+
res = @mmt.convert(@test_image)
|
91
|
+
expect(res[:test][:done]).to be_true
|
92
|
+
expect(res[:test][:path]).to eq target
|
93
|
+
expect(File.exists?(target)).to be_true
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should pass options to blocks' do
|
97
|
+
@mmt.reset!
|
98
|
+
@mmt.add_output(:named) do |img, opts|
|
99
|
+
expect(opts[:text]).to eq 'This is a test'
|
100
|
+
img.draw "text 10,10 '#{opts[:text]}'"
|
101
|
+
end
|
102
|
+
|
103
|
+
res = @mmt.convert(@test_image, :text => 'This is a test')
|
104
|
+
expect(res[:named][:done]).to be_true
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should raise exception on unreadable file' do
|
108
|
+
expect{ @mmt.convert('non_existent') }.to raise_error(MMThumb::Error)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should not raise exceptions during processing' do
|
112
|
+
@mmt.reset!
|
113
|
+
@mmt.add_output(:broken) do |img|
|
114
|
+
this_should_fail
|
115
|
+
end
|
116
|
+
|
117
|
+
res = @mmt.convert(@test_image)
|
118
|
+
expect(res.values.length).to eq 1
|
119
|
+
expect(res.values.any? {|e| e[:done] }).to be_false
|
120
|
+
expect(res[:broken][:error]).to be_a(StandardError)
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/test.jpg
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mmthumb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Piotr S. Staszewski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mini_magick
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.4'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubygems-tasks
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.8'
|
69
|
+
description: Define pre-, post- and a number of output operations and let MMThumb
|
70
|
+
do the work. Will fit well with offline batch-processing just as well as as a component
|
71
|
+
of a continuous online service. Single dependency.
|
72
|
+
email: p.staszewski@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".document"
|
78
|
+
- ".gitignore"
|
79
|
+
- ".yardopts"
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- examples/for_web.rb
|
84
|
+
- lib/mmthumb.rb
|
85
|
+
- lib/mmthumb/version.rb
|
86
|
+
- mmthumb.gemspec
|
87
|
+
- spec/mmthumb_spec.rb
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
- spec/test.jpg
|
90
|
+
homepage: https://github.com/drbig/mmthumb
|
91
|
+
licenses:
|
92
|
+
- BSD
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.8.7
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.2.2
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Convenient image converter for common workflows
|
114
|
+
test_files:
|
115
|
+
- spec/mmthumb_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- spec/test.jpg
|