image_optim 0.12.0 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.markdown +33 -24
- data/image_optim.gemspec +1 -1
- data/lib/image_optim.rb +8 -4
- data/lib/image_optim/bin_resolver.rb +6 -2
- data/lib/image_optim/config.rb +1 -3
- data/lib/image_optim/railtie.rb +10 -6
- data/lib/image_optim/worker/advpng.rb +1 -1
- data/lib/image_optim/worker/jpegoptim.rb +2 -2
- data/lib/image_optim/worker/optipng.rb +2 -2
- data/lib/image_optim/worker/pngcrush.rb +2 -2
- data/lib/image_optim/worker/pngout.rb +1 -1
- data/script/update_worker_options_in_readme +6 -4
- data/spec/image_optim/bin_resolver_spec.rb +3 -6
- data/spec/image_optim/config_spec.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MzhlYjg1NzA0MjUxYmM3MDhjNWVkZDcyYTAyZTM4MTAyMzUyZWU1ZQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MjE2MjNkNzk1NDIyY2NjM2VjZjc4OTkwNmQ5MGY4NWU5YmI4NmViZA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Yzg2ZDUyY2E3MTNhMTQzODgxOWU5M2ZkMWYxZDE1ZThkN2Q3ZTQyYTM3MThj
|
10
|
+
OTE0OWQwMDUyYjJlZTFlZjU3YWI1ZmI4NTJlZGU4OTdkZTYyM2YzOTY2NTU0
|
11
|
+
MjM1ZDQyMmQ1NGZhYTJiNGFlY2MyNThhNTdkYTAxMzExODkxYTM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZmM1ZDRjNzBkNjNjYmI3MmEwZDRjYWVhYThjMjQ1NjIxMTJjZTgzZDJiMmNl
|
14
|
+
OTQ4NjM2MjU3YTA4M2NlMGZjNDk3YTIyODYzM2RhZWM5YmVjOThjMGM2NjU3
|
15
|
+
YzFhMjJkMWEyNDFhOTllYjNjOWZhNTViMzQ1YWJhNmQ3M2NjYzg=
|
data/README.markdown
CHANGED
@@ -188,6 +188,9 @@ image_optim.optimize_images_data(datas)
|
|
188
188
|
|
189
189
|
`ImageOptim::Railtie` will automatically register sprockets preprocessor unless you set `config.assets.image_optim = false` or `config.assets.compress = false` (later for partial rails 3 compatibility).
|
190
190
|
|
191
|
+
You can provide options for image_optim used for preprocessor through config `config.assets.image_optim = {nice: 20, svgo: false}` (ruby1.8 style: `{:nice => 20, :svgo => false}`).
|
192
|
+
Check available options in [options section](#options).
|
193
|
+
|
191
194
|
Image optimization can be time consuming, so depending on your deployment process you may prefer to optimize original asset files.
|
192
195
|
|
193
196
|
## Configuration
|
@@ -208,41 +211,47 @@ optipng:
|
|
208
211
|
|
209
212
|
## Options
|
210
213
|
|
211
|
-
* `:nice` — Nice level *(defaults to 10)*
|
214
|
+
* `:nice` — Nice level *(defaults to `10`)*
|
212
215
|
* `:threads` — Number of threads or disable *(defaults to number of processors)*
|
213
|
-
* `:verbose` — Verbose output *(defaults to false)*
|
216
|
+
* `:verbose` — Verbose output *(defaults to `false`)*
|
214
217
|
|
215
|
-
Worker can be disabled by passing false instead of options hash.
|
218
|
+
Worker can be disabled by passing `false` instead of options hash.
|
216
219
|
|
217
220
|
<!---<worker-options>-->
|
218
221
|
|
219
|
-
### pngcrush
|
220
|
-
* `:chunks` — List of chunks to remove or
|
221
|
-
* `:fix` — Fix otherwise fatal conditions such as bad CRCs *(defaults to false)*
|
222
|
-
* `:brute` — Brute force try all methods, very time-consuming and generally not worthwhile *(defaults to false)*
|
222
|
+
### :pngcrush =>
|
223
|
+
* `:chunks` — List of chunks to remove or `:alla` - all except tRNS/transparency or `:allb` - all except tRNS and gAMA/gamma *(defaults to `:alla`)*
|
224
|
+
* `:fix` — Fix otherwise fatal conditions such as bad CRCs *(defaults to `false`)*
|
225
|
+
* `:brute` — Brute force try all methods, very time-consuming and generally not worthwhile *(defaults to `false`)*
|
226
|
+
|
227
|
+
### :pngout =>
|
228
|
+
* `:copy_chunks` — Copy optional chunks *(defaults to `false`)*
|
229
|
+
* `:strategy` — Strategy: `0` - xtreme, `1` - intense, `2` - longest Match, `3` - huffman Only, `4` - uncompressed *(defaults to `0`)*
|
230
|
+
|
231
|
+
### :optipng =>
|
232
|
+
* `:level` — Optimization level preset: `0` is least, `7` is best *(defaults to `6`)*
|
233
|
+
* `:interlace` — Interlace, `true` - interlace on, `false` - interlace off, `nil` - as is in original image *(defaults to `false`)*
|
223
234
|
|
224
|
-
###
|
225
|
-
* `:
|
226
|
-
* `:strategy` — Strategy: 0 - xtreme, 1 - intense, 2 - longest Match, 3 - huffman Only, 4 - uncompressed *(defaults to 0)*
|
235
|
+
### :advpng =>
|
236
|
+
* `:level` — Compression level: `0` - don't compress, `1` - fast, `2` - normal, `3` - extra, `4` - extreme *(defaults to `4`)*
|
227
237
|
|
228
|
-
###
|
229
|
-
|
230
|
-
* `:interlace` — Interlace, true - interlace on, false - interlace off, nil - as is in original image *(defaults to false)*
|
238
|
+
### :jhead =>
|
239
|
+
Worker has no options
|
231
240
|
|
232
|
-
###
|
233
|
-
* `:
|
241
|
+
### :jpegoptim =>
|
242
|
+
* `:strip` — List of extra markers to strip: `:comments`, `:exif`, `:iptc`, `:icc` or `:all` *(defaults to `:all`)*
|
243
|
+
* `:max_quality` — Maximum image quality factor `0`..`100` *(defaults to `100`)*
|
234
244
|
|
235
|
-
###
|
236
|
-
* `:
|
237
|
-
* `:
|
245
|
+
### :jpegtran =>
|
246
|
+
* `:copy_chunks` — Copy all chunks *(defaults to `false`)*
|
247
|
+
* `:progressive` — Create progressive JPEG file *(defaults to `true`)*
|
248
|
+
* `:jpegrescan` — Use jpegtran through jpegrescan, ignore progressive option *(defaults to `false`)*
|
238
249
|
|
239
|
-
###
|
240
|
-
* `:
|
241
|
-
* `:progressive` — Create progressive JPEG file *(defaults to true)*
|
242
|
-
* `:jpegrescan` — Use jpegtran through jpegrescan, ignore progressive option *(defaults to false)*
|
250
|
+
### :gifsicle =>
|
251
|
+
* `:interlace` — Turn interlacing on *(defaults to `false`)*
|
243
252
|
|
244
|
-
###
|
245
|
-
|
253
|
+
### :svgo =>
|
254
|
+
Worker has no options
|
246
255
|
|
247
256
|
<!---</worker-options>-->
|
248
257
|
|
data/image_optim.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'image_optim'
|
5
|
-
s.version = '0.12.
|
5
|
+
s.version = '0.12.1'
|
6
6
|
s.summary = %q{Optimize (lossless compress) images (jpeg, png, gif, svg) using external utilities (advpng, gifsicle, jpegoptim, jpegtran, optipng, pngcrush, pngout, svgo)}
|
7
7
|
s.homepage = "http://github.com/toy/#{s.name}"
|
8
8
|
s.authors = ['Ivan Kuchin']
|
data/lib/image_optim.rb
CHANGED
@@ -36,13 +36,19 @@ class ImageOptim
|
|
36
36
|
#
|
37
37
|
# ImageOptim.new(:nice => 20)
|
38
38
|
def initialize(options = {})
|
39
|
-
@bin_resolver = BinResolver.new
|
40
|
-
|
41
39
|
config = Config.new(options)
|
42
40
|
@nice = config.nice
|
43
41
|
@threads = config.threads
|
44
42
|
@verbose = config.verbose
|
45
43
|
|
44
|
+
if verbose?
|
45
|
+
$stderr << config
|
46
|
+
$stderr << "Nice level: #{nice}\n"
|
47
|
+
$stderr << "Using threads: #{threads}\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
@bin_resolver = BinResolver.new(self)
|
51
|
+
|
46
52
|
@workers_by_format = {}
|
47
53
|
Worker.klasses.each do |klass|
|
48
54
|
if worker_options = config.for_worker(klass)
|
@@ -56,8 +62,6 @@ class ImageOptim
|
|
56
62
|
@workers_by_format.values.each(&:sort!)
|
57
63
|
|
58
64
|
config.assert_no_unused_options!
|
59
|
-
|
60
|
-
puts config if verbose?
|
61
65
|
end
|
62
66
|
|
63
67
|
# Get workers for image
|
@@ -18,7 +18,8 @@ class ImageOptim
|
|
18
18
|
end
|
19
19
|
|
20
20
|
attr_reader :dir
|
21
|
-
def initialize
|
21
|
+
def initialize(image_optim)
|
22
|
+
@image_optim = image_optim
|
22
23
|
@bins = {}
|
23
24
|
@lock = Mutex.new
|
24
25
|
end
|
@@ -27,7 +28,10 @@ class ImageOptim
|
|
27
28
|
name = name.to_sym
|
28
29
|
|
29
30
|
resolving(name) do
|
30
|
-
|
31
|
+
if bin = resolve?(name) && Bin.new(name, version(name))
|
32
|
+
$stderr << "Resolved #{bin}\n" if @image_optim.verbose?
|
33
|
+
end
|
34
|
+
@bins[name] = bin
|
31
35
|
end
|
32
36
|
|
33
37
|
if @bins[name]
|
data/lib/image_optim/config.rb
CHANGED
@@ -75,7 +75,7 @@ class ImageOptim
|
|
75
75
|
def threads
|
76
76
|
threads = get!(:threads)
|
77
77
|
|
78
|
-
|
78
|
+
case threads
|
79
79
|
when true, nil
|
80
80
|
processor_count
|
81
81
|
when false
|
@@ -83,8 +83,6 @@ class ImageOptim
|
|
83
83
|
else
|
84
84
|
threads.to_i
|
85
85
|
end
|
86
|
-
|
87
|
-
OptionHelpers.limit_with_range(threads, 1..16)
|
88
86
|
end
|
89
87
|
|
90
88
|
def verbose
|
data/lib/image_optim/railtie.rb
CHANGED
@@ -3,12 +3,15 @@ require 'image_optim'
|
|
3
3
|
class ImageOptim
|
4
4
|
class Railtie < Rails::Railtie
|
5
5
|
initializer 'image_optim.initializer' do |app|
|
6
|
-
if app.config.assets.compress != false && app.config.assets.image_optim != false
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
if app.config.assets.compress != false && app.config.assets.image_optim != false && app.assets
|
7
|
+
|
8
|
+
options = if app.config.assets.image_optim == true
|
9
|
+
{}
|
10
|
+
else
|
11
|
+
app.config.assets.image_optim || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
image_optim = ImageOptim.new(options)
|
12
15
|
|
13
16
|
processor = proc do |context, data|
|
14
17
|
image_optim.optimize_image_data(data) || data
|
@@ -18,6 +21,7 @@ class ImageOptim
|
|
18
21
|
app.assets.register_preprocessor 'image/jpeg', :image_optim, &processor
|
19
22
|
app.assets.register_preprocessor 'image/png', :image_optim, &processor
|
20
23
|
app.assets.register_preprocessor 'image/svg+xml', :image_optim, &processor
|
24
|
+
|
21
25
|
end
|
22
26
|
end
|
23
27
|
end
|
@@ -4,7 +4,7 @@ require 'image_optim/option_helpers'
|
|
4
4
|
class ImageOptim
|
5
5
|
class Worker
|
6
6
|
class Advpng < Worker
|
7
|
-
option(:level, 4, 'Compression level: 0 - don\'t compress, 1 - fast, 2 - normal, 3 - extra, 4 - extreme') do |v|
|
7
|
+
option(:level, 4, 'Compression level: `0` - don\'t compress, `1` - fast, `2` - normal, `3` - extra, `4` - extreme') do |v|
|
8
8
|
OptionHelpers.limit_with_range(v.to_i, 0..4)
|
9
9
|
end
|
10
10
|
|
@@ -4,7 +4,7 @@ require 'image_optim/option_helpers'
|
|
4
4
|
class ImageOptim
|
5
5
|
class Worker
|
6
6
|
class Jpegoptim < Worker
|
7
|
-
option(:strip, :all, Array, 'List of extra markers to strip: comments
|
7
|
+
option(:strip, :all, Array, 'List of extra markers to strip: `:comments`, `:exif`, `:iptc`, `:icc` or `:all`') do |v|
|
8
8
|
values = Array(v).map(&:to_s)
|
9
9
|
known_values = %w[all comments exif iptc icc]
|
10
10
|
unknown_values = values - known_values
|
@@ -12,7 +12,7 @@ class ImageOptim
|
|
12
12
|
values & known_values
|
13
13
|
end
|
14
14
|
|
15
|
-
option(:max_quality, 100, 'Maximum image quality factor 0
|
15
|
+
option(:max_quality, 100, 'Maximum image quality factor `0`..`100`'){ |v| OptionHelpers.limit_with_range(v.to_i, 0..100) }
|
16
16
|
|
17
17
|
# Run first if max_quality < 100
|
18
18
|
def run_order
|
@@ -5,9 +5,9 @@ require 'image_optim/true_false_nil'
|
|
5
5
|
class ImageOptim
|
6
6
|
class Worker
|
7
7
|
class Optipng < Worker
|
8
|
-
option(:level, 6, 'Optimization level preset 0 is least, 7 is best'){ |v| OptionHelpers.limit_with_range(v.to_i, 0..7) }
|
8
|
+
option(:level, 6, 'Optimization level preset: `0` is least, `7` is best'){ |v| OptionHelpers.limit_with_range(v.to_i, 0..7) }
|
9
9
|
|
10
|
-
option(:interlace, false, TrueFalseNil, 'Interlace, true - interlace on, false - interlace off, nil - as is in original image') do |v|
|
10
|
+
option(:interlace, false, TrueFalseNil, 'Interlace, `true` - interlace on, `false` - interlace off, `nil` - as is in original image') do |v|
|
11
11
|
v && true
|
12
12
|
end
|
13
13
|
|
@@ -3,8 +3,8 @@ require 'image_optim/worker'
|
|
3
3
|
class ImageOptim
|
4
4
|
class Worker
|
5
5
|
class Pngcrush < Worker
|
6
|
-
option(:chunks, :alla, Array, 'List of chunks to remove or
|
7
|
-
'
|
6
|
+
option(:chunks, :alla, Array, 'List of chunks to remove or `:alla` - all except tRNS/transparency or '\
|
7
|
+
'`:allb` - all except tRNS and gAMA/gamma'){ |v| Array(v).map(&:to_s) }
|
8
8
|
|
9
9
|
option(:fix, false, 'Fix otherwise fatal conditions such as bad CRCs'){ |v| !!v }
|
10
10
|
|
@@ -6,7 +6,7 @@ class ImageOptim
|
|
6
6
|
class Pngout < Worker
|
7
7
|
option(:copy_chunks, false, 'Copy optional chunks'){ |v| !!v }
|
8
8
|
|
9
|
-
option(:strategy, 0, 'Strategy: 0 - xtreme, 1 - intense, 2 - longest Match, 3 - huffman Only, 4 - uncompressed') do |v|
|
9
|
+
option(:strategy, 0, 'Strategy: `0` - xtreme, `1` - intense, `2` - longest Match, `3` - huffman Only, `4` - uncompressed') do |v|
|
10
10
|
OptionHelpers.limit_with_range(v.to_i, 0..4)
|
11
11
|
end
|
12
12
|
|
@@ -13,13 +13,15 @@ def worker_options
|
|
13
13
|
io = StringIO.new
|
14
14
|
|
15
15
|
ImageOptim::Worker.klasses.each_with_index do |klass, i|
|
16
|
-
|
17
|
-
|
16
|
+
io.puts "### :#{klass.bin_sym} =>"
|
17
|
+
if klass.option_definitions.empty?
|
18
|
+
io.puts 'Worker has no options'
|
19
|
+
else
|
18
20
|
klass.option_definitions.each do |option_definition|
|
19
|
-
io.puts "* `:#{option_definition.name}` — #{option_definition.description} *(defaults to
|
21
|
+
io.puts "* `:#{option_definition.name}` — #{option_definition.description} *(defaults to `#{option_definition.default.inspect}`)*"
|
20
22
|
end
|
21
|
-
io.puts
|
22
23
|
end
|
24
|
+
io.puts
|
23
25
|
end
|
24
26
|
|
25
27
|
io.string
|
@@ -10,9 +10,11 @@ ensure
|
|
10
10
|
end
|
11
11
|
|
12
12
|
describe ImageOptim::BinResolver do
|
13
|
+
let(:image_optim){ double(:image_optim, :verbose? => false) }
|
14
|
+
let(:resolver){ ImageOptim::BinResolver.new(image_optim) }
|
15
|
+
|
13
16
|
it "should resolve bin in path" do
|
14
17
|
with_env 'LS_BIN', nil do
|
15
|
-
resolver = ImageOptim::BinResolver.new
|
16
18
|
resolver.should_receive(:accessible?).with(:ls).once.and_return(true)
|
17
19
|
FSPath.should_not_receive(:temp_dir)
|
18
20
|
|
@@ -29,7 +31,6 @@ describe ImageOptim::BinResolver do
|
|
29
31
|
tmpdir = double(:tmpdir)
|
30
32
|
symlink = double(:symlink)
|
31
33
|
|
32
|
-
resolver = ImageOptim::BinResolver.new
|
33
34
|
resolver.should_receive(:accessible?).with(:image_optim).once.and_return(true)
|
34
35
|
FSPath.should_receive(:temp_dir).once.and_return(tmpdir)
|
35
36
|
tmpdir.should_receive(:/).with(:image_optim).once.and_return(symlink)
|
@@ -52,7 +53,6 @@ describe ImageOptim::BinResolver do
|
|
52
53
|
|
53
54
|
it "should raise on failure to resolve bin" do
|
54
55
|
with_env 'SHOULD_NOT_EXIST_BIN', nil do
|
55
|
-
resolver = ImageOptim::BinResolver.new
|
56
56
|
resolver.should_receive(:accessible?).with(:should_not_exist).once.and_return(false)
|
57
57
|
FSPath.should_not_receive(:temp_dir)
|
58
58
|
|
@@ -71,7 +71,6 @@ describe ImageOptim::BinResolver do
|
|
71
71
|
tmpdir = double(:tmpdir)
|
72
72
|
symlink = double(:symlink)
|
73
73
|
|
74
|
-
resolver = ImageOptim::BinResolver.new
|
75
74
|
resolver.should_receive(:accessible?).with(:should_not_exist).once.and_return(false)
|
76
75
|
FSPath.should_receive(:temp_dir).once.and_return(tmpdir)
|
77
76
|
tmpdir.should_receive(:/).with(:should_not_exist).once.and_return(symlink)
|
@@ -96,7 +95,6 @@ describe ImageOptim::BinResolver do
|
|
96
95
|
|
97
96
|
it "should resolve bin only once" do
|
98
97
|
with_env 'LS_BIN', nil do
|
99
|
-
resolver = ImageOptim::BinResolver.new
|
100
98
|
resolver.should_receive(:resolve?).once.with(:ls){ sleep 0.1; true }
|
101
99
|
|
102
100
|
10.times.map do
|
@@ -109,7 +107,6 @@ describe ImageOptim::BinResolver do
|
|
109
107
|
|
110
108
|
it "should raise on detection of problematic version" do
|
111
109
|
with_env 'PNGCRUSH_BIN', nil do
|
112
|
-
resolver = ImageOptim::BinResolver.new
|
113
110
|
resolver.should_receive(:accessible?).with(:pngcrush).once.and_return(true)
|
114
111
|
resolver.should_receive(:version).with(:pngcrush).once.and_return('1.7.60')
|
115
112
|
FSPath.should_not_receive(:temp_dir)
|
@@ -51,9 +51,9 @@ class ImageOptim
|
|
51
51
|
config.threads.should == 1
|
52
52
|
end
|
53
53
|
|
54
|
-
it "should convert value to number
|
54
|
+
it "should convert value to number" do
|
55
55
|
config = Config.new({:threads => '616'})
|
56
|
-
config.threads.should ==
|
56
|
+
config.threads.should == 616
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_optim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.12.
|
4
|
+
version: 0.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Kuchin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fspath
|