mmthumb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|