image_optim 0.12.0 → 0.12.1
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 +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
|