image_optim 0.24.3 → 0.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +29 -34
- data/.travis.yml +4 -1
- data/CHANGELOG.markdown +5 -0
- data/README.markdown +2 -1
- data/image_optim.gemspec +2 -2
- data/lib/image_optim/worker/jhead.rb +1 -1
- data/lib/image_optim/worker/pngquant.rb +6 -0
- data/script/worker_analysis +76 -58
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0274d7bf579938c5c208f39fb85d60781d727566
|
4
|
+
data.tar.gz: e27be28692c75bc6456071311a3bed6fa3a8a216
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8b6ec09460fa0f07b11ab3930e4b55d52c6ab313caf1a04b55ad5244b20430686f1833a0e66e3501f3cbeb64893b7e35cc9fa75edcb3810b93fb8942d853a20
|
7
|
+
data.tar.gz: 7550e19b5a4ec5821e3b4603bab89d48f09fe6c24e65beb79130c5eda8fa2aa5f7e3e7fe08630bef0021ddcf3affc50964662db1e339d8e5b4c96c10ca08fea7
|
data/.rubocop.yml
CHANGED
@@ -6,6 +6,33 @@ AllCops:
|
|
6
6
|
Bundler/OrderedGems:
|
7
7
|
Enabled: false
|
8
8
|
|
9
|
+
Layout/AccessModifierIndentation:
|
10
|
+
EnforcedStyle: outdent
|
11
|
+
|
12
|
+
Layout/CaseIndentation:
|
13
|
+
EnforcedStyle: end
|
14
|
+
|
15
|
+
Layout/DotPosition:
|
16
|
+
EnforcedStyle: trailing
|
17
|
+
|
18
|
+
Layout/IndentArray:
|
19
|
+
EnforcedStyle: consistent
|
20
|
+
|
21
|
+
Layout/IndentAssignment:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Layout/IndentHash:
|
25
|
+
EnforcedStyle: consistent
|
26
|
+
|
27
|
+
Layout/IndentHeredoc:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
Layout/SpaceBeforeBlockBraces:
|
31
|
+
EnforcedStyle: no_space
|
32
|
+
|
33
|
+
Layout/SpaceInsideHashLiteralBraces:
|
34
|
+
EnforcedStyle: no_space
|
35
|
+
|
9
36
|
Lint/AmbiguousBlockAssociation:
|
10
37
|
Exclude:
|
11
38
|
- spec/**/*_spec.rb
|
@@ -41,18 +68,9 @@ Security/MarshalLoad:
|
|
41
68
|
Exclude:
|
42
69
|
- 'script/worker_analysis'
|
43
70
|
|
44
|
-
Style/AccessModifierIndentation:
|
45
|
-
EnforcedStyle: outdent
|
46
|
-
|
47
71
|
Style/Alias:
|
48
72
|
EnforcedStyle: prefer_alias_method
|
49
73
|
|
50
|
-
Style/CaseIndentation:
|
51
|
-
EnforcedStyle: end
|
52
|
-
|
53
|
-
Style/DotPosition:
|
54
|
-
EnforcedStyle: trailing
|
55
|
-
|
56
74
|
Style/DoubleNegation:
|
57
75
|
Enabled: false
|
58
76
|
|
@@ -68,43 +86,20 @@ Style/HashSyntax:
|
|
68
86
|
Style/IfUnlessModifier:
|
69
87
|
MaxLineLength: 40
|
70
88
|
|
71
|
-
Style/IndentArray:
|
72
|
-
EnforcedStyle: consistent
|
73
|
-
|
74
|
-
Style/IndentAssignment:
|
75
|
-
Enabled: false
|
76
|
-
|
77
|
-
Style/IndentHash:
|
78
|
-
EnforcedStyle: consistent
|
79
|
-
|
80
|
-
Style/IndentHeredoc:
|
81
|
-
Enabled: false
|
82
|
-
|
83
89
|
Style/ParallelAssignment:
|
84
90
|
Enabled: false
|
85
91
|
|
86
|
-
Style/PercentLiteralDelimiters:
|
87
|
-
PreferredDelimiters:
|
88
|
-
'%w': '[]'
|
89
|
-
'%W': '[]'
|
90
|
-
|
91
92
|
Style/Semicolon:
|
92
93
|
AllowAsExpressionSeparator: true
|
93
94
|
|
94
95
|
Style/SignalException:
|
95
96
|
EnforcedStyle: semantic
|
96
97
|
|
97
|
-
Style/
|
98
|
-
|
99
|
-
|
100
|
-
Style/SpaceInsideHashLiteralBraces:
|
101
|
-
EnforcedStyle: no_space
|
98
|
+
Style/SymbolArray:
|
99
|
+
Enabled: false
|
102
100
|
|
103
101
|
Style/TrailingCommaInArguments:
|
104
102
|
EnforcedStyleForMultiline: no_comma
|
105
103
|
|
106
104
|
Style/TrailingCommaInLiteral:
|
107
105
|
EnforcedStyleForMultiline: comma
|
108
|
-
|
109
|
-
Style/SymbolArray:
|
110
|
-
Enabled: false
|
data/.travis.yml
CHANGED
@@ -15,11 +15,14 @@ rvm:
|
|
15
15
|
- '2.4.1'
|
16
16
|
- 'jruby-1.7.26'
|
17
17
|
- 'jruby-9.0.5.0'
|
18
|
-
- 'jruby-9.1.
|
18
|
+
- 'jruby-9.1.9.0'
|
19
19
|
script:
|
20
20
|
- bundle exec image_optim --info
|
21
21
|
- bundle exec rspec
|
22
22
|
before_install:
|
23
|
+
- gem update --system
|
24
|
+
- gem update bundler
|
25
|
+
- nvm install stable
|
23
26
|
- mkdir -p ~/bin
|
24
27
|
- command -v svgo || npm install svgo
|
25
28
|
- command -v pngout || curl -L "http://static.jonof.id.au/dl/kenutils/pngout-20130221-linux.tar.gz" | tar -xz -C ~/bin --strip-components 2 --wildcards '*/x86_64/pngout'
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v0.25.0 (2017-07-06)
|
6
|
+
|
7
|
+
* Fix error `uninitialized constant EXIFR::JPEG` (breaking change in [exifr v1.3.0](https://github.com/remvee/exifr/commit/e073a22d06c39f2c1c0e77f5b5fe71545b25e967)) [#150](https://github.com/toy/image_optim/pull/150) [@abemedia](https://github.com/abemedia)
|
8
|
+
* Add option to `pngquant` worker to limit maximum number of colors to use [#144](https://github.com/toy/image_optim/issues/144) [@toy](https://github.com/toy)
|
9
|
+
|
5
10
|
## v0.24.3 (2017-05-04)
|
6
11
|
|
7
12
|
* Set mode of cache files to `0666 & ~umask`, related to [#147](https://github.com/toy/image_optim/issues/147) [@toy](https://github.com/toy)
|
data/README.markdown
CHANGED
@@ -58,7 +58,7 @@ With version:
|
|
58
58
|
|
59
59
|
<!---<update-version>-->
|
60
60
|
```ruby
|
61
|
-
gem 'image_optim', '~> 0.
|
61
|
+
gem 'image_optim', '~> 0.25'
|
62
62
|
```
|
63
63
|
<!---</update-version>-->
|
64
64
|
|
@@ -319,6 +319,7 @@ Worker has no options
|
|
319
319
|
|
320
320
|
### pngquant:
|
321
321
|
* `:allow_lossy` — Allow quality option *(defaults to `false`)*
|
322
|
+
* `:max_colors` — Maximum number of colors to use *(defaults to `256`)*
|
322
323
|
* `:quality` — min..max - don't save below min, use less colors below max (both in range `0..100`; in yaml - `!ruby/range 0..100`), ignored in default/lossless mode *(defaults to `100..100`, `0..100` in lossy mode)*
|
323
324
|
* `:speed` — speed/quality trade-off: `1` - slow, `3` - default, `11` - fast & rough *(defaults to `3`)*
|
324
325
|
|
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.
|
5
|
+
s.version = '0.25.0'
|
6
6
|
s.summary = %q{Optimize (lossless compress, optionally lossy) images (jpeg, png, gif, svg) using external utilities (advpng, gifsicle, jhead, jpeg-recompress, jpegoptim, jpegrescan, jpegtran, optipng, pngcrush, pngout, pngquant, svgo)}
|
7
7
|
s.homepage = "http://github.com/toy/#{s.name}"
|
8
8
|
s.authors = ['Ivan Kuchin']
|
@@ -29,6 +29,6 @@ EOF
|
|
29
29
|
s.add_development_dependency 'image_optim_pack', '~> 0.2', '>= 0.2.2'
|
30
30
|
s.add_development_dependency 'rspec', '~> 3.0'
|
31
31
|
if RUBY_VERSION >= '2.0'
|
32
|
-
s.add_development_dependency 'rubocop', '~> 0.
|
32
|
+
s.add_development_dependency 'rubocop', '~> 0.49'
|
33
33
|
end
|
34
34
|
end
|
@@ -9,6 +9,11 @@ class ImageOptim
|
|
9
9
|
ALLOW_LOSSY_OPTION =
|
10
10
|
option(:allow_lossy, false, 'Allow quality option'){ |v| !!v }
|
11
11
|
|
12
|
+
MAX_COLORS_OPTION =
|
13
|
+
option(:max_colors, 256, 'Maximum number of colors to use') do |v|
|
14
|
+
OptionHelpers.limit_with_range(v.to_i, 2..256)
|
15
|
+
end
|
16
|
+
|
12
17
|
QUALITY_OPTION =
|
13
18
|
option(:quality, '`100..100`, `0..100` in lossy mode',
|
14
19
|
NonNegativeIntegerRange, 'min..max - don\'t '\
|
@@ -49,6 +54,7 @@ class ImageOptim
|
|
49
54
|
--speed=#{speed}
|
50
55
|
--output=#{dst}
|
51
56
|
--force
|
57
|
+
#{max_colors}
|
52
58
|
--
|
53
59
|
#{src}
|
54
60
|
]
|
data/script/worker_analysis
CHANGED
@@ -133,8 +133,10 @@ class Analyser
|
|
133
133
|
|
134
134
|
# Delegate to worker with short id
|
135
135
|
class WorkerVariant < DelegateClass(ImageOptim::Worker)
|
136
|
-
attr_reader :name, :id, :cons_id
|
136
|
+
attr_reader :name, :id, :cons_id, :required
|
137
137
|
def initialize(klass, image_optim, options)
|
138
|
+
@required = options.delete(:required)
|
139
|
+
@run_order = options.delete(:run_order)
|
138
140
|
allow_consecutive_on = Array(options.delete(:allow_consecutive_on))
|
139
141
|
@image_optim = image_optim
|
140
142
|
@name = klass.bin_sym.to_s + options_string(options)
|
@@ -143,6 +145,10 @@ class Analyser
|
|
143
145
|
@cons_id = [klass, allow_consecutive_on.map{ |key| [key, send(key)] }]
|
144
146
|
end
|
145
147
|
|
148
|
+
def run_order
|
149
|
+
@run_order || super
|
150
|
+
end
|
151
|
+
|
146
152
|
def etag
|
147
153
|
[
|
148
154
|
id,
|
@@ -155,7 +161,8 @@ class Analyser
|
|
155
161
|
|
156
162
|
def bin_versions
|
157
163
|
@bin_versions ||= used_bins.map do |name|
|
158
|
-
@image_optim.resolve_bin!(name)
|
164
|
+
bin = @image_optim.resolve_bin!(name)
|
165
|
+
"#{bin.name} #{bin.version}"
|
159
166
|
end
|
160
167
|
end
|
161
168
|
|
@@ -189,7 +196,7 @@ class Analyser
|
|
189
196
|
|
190
197
|
dst_size = success ? dst.size : nil
|
191
198
|
digest = (success ? dst : src).digest
|
192
|
-
cache = digest.sub(/../, '\0/')
|
199
|
+
cache = digest.sub(/../, '\0/')
|
193
200
|
result = new(worker.id, success, time, src.size, dst_size, cache)
|
194
201
|
if success
|
195
202
|
path = result.path
|
@@ -274,7 +281,9 @@ class Analyser
|
|
274
281
|
end
|
275
282
|
|
276
283
|
def run_workers(src, workers, last_result = nil, &block)
|
284
|
+
required_workers = workers.select(&:required)
|
277
285
|
with_progress(workers, last_result) do |worker|
|
286
|
+
next if required_workers.any?{ |w| w.run_order < worker.run_order }
|
278
287
|
worker_result, result_image = run_worker(src, worker)
|
279
288
|
|
280
289
|
steps = (last_result ? last_result.steps : []) + [worker_result]
|
@@ -306,19 +315,12 @@ class Analyser
|
|
306
315
|
def difference_with(other)
|
307
316
|
run_cache[:difference][other.digest] ||=
|
308
317
|
Cache.get(:difference, [@path.digest, other.digest].sort, nil) do
|
309
|
-
images =
|
310
|
-
|
311
|
-
alpha_presence = images.map do |image|
|
312
|
-
Cmd.capture("identify -format '%A' #{image.to_s.shellescape}")
|
313
|
-
end
|
314
|
-
if alpha_presence.uniq.length == 2
|
315
|
-
images.map!{ |image| underlay_noise(image) }
|
316
|
-
end
|
318
|
+
images = for_compare(@path, other)
|
317
319
|
|
318
320
|
nrmse = Cmd.capture(%W[
|
319
321
|
convert
|
320
|
-
#{images[0]} -auto-orient
|
321
|
-
#{images[1]} -auto-orient
|
322
|
+
#{images[0].image_format}:#{images[0]} -auto-orient
|
323
|
+
#{images[1].image_format}:#{images[1]} -auto-orient
|
322
324
|
-metric RMSE
|
323
325
|
-compare
|
324
326
|
-format %[distortion]
|
@@ -331,16 +333,33 @@ class Analyser
|
|
331
333
|
end
|
332
334
|
end
|
333
335
|
|
336
|
+
def for_compare(*images)
|
337
|
+
images.map!{ |image| flatten_animation(image) }
|
338
|
+
|
339
|
+
alpha_presence = images.map do |image|
|
340
|
+
!!Cmd.capture(%W[
|
341
|
+
identify
|
342
|
+
-format %A
|
343
|
+
#{image.image_format}:#{image.to_s.shellescape}
|
344
|
+
].shelljoin)[/true/i]
|
345
|
+
end
|
346
|
+
if alpha_presence.uniq.length != 1
|
347
|
+
images.map!{ |image| underlay_noise(image) }
|
348
|
+
end
|
349
|
+
|
350
|
+
images
|
351
|
+
end
|
352
|
+
|
334
353
|
def flatten_animation(image)
|
335
354
|
run_cache[:flatten][image.digest] ||= begin
|
336
355
|
if image.image_format == :gif
|
337
356
|
flattened = image.temp_path
|
338
357
|
Cmd.run(*%W[
|
339
358
|
convert
|
340
|
-
#{image}
|
359
|
+
#{image.image_format}:#{image}
|
341
360
|
-coalesce
|
342
361
|
-append
|
343
|
-
#{flattened}
|
362
|
+
#{image.image_format}:#{flattened}
|
344
363
|
]) || fail("failed flattening of #{image}")
|
345
364
|
flattened
|
346
365
|
else
|
@@ -354,12 +373,12 @@ class Analyser
|
|
354
373
|
with_noise = image.temp_path
|
355
374
|
Cmd.run(*%W[
|
356
375
|
convert
|
357
|
-
#{image}
|
376
|
+
#{image.image_format}:#{image}
|
358
377
|
+noise Random
|
359
|
-
#{image}
|
378
|
+
#{image.image_format}:#{image}
|
360
379
|
-flatten
|
361
380
|
-alpha off
|
362
|
-
#{with_noise}
|
381
|
+
#{image.image_format}:#{with_noise}
|
363
382
|
]) || fail("failed underlaying noise to #{image}")
|
364
383
|
with_noise
|
365
384
|
end
|
@@ -455,25 +474,24 @@ class Analyser
|
|
455
474
|
end
|
456
475
|
end
|
457
476
|
|
458
|
-
def initialize(
|
459
|
-
|
477
|
+
def initialize(config)
|
478
|
+
config = HashHelpers.deep_symbolise_keys(config)
|
460
479
|
image_optim = ImageOptim.new
|
461
480
|
|
462
481
|
@workers_by_format = Hash.new{ |h, k| h[k] = [] }
|
463
482
|
ImageOptim::Worker.klasses.each do |klass|
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
483
|
+
worker_config = config.delete(klass.bin_sym)
|
484
|
+
next if worker_config == false
|
485
|
+
worker_config ||= {}
|
486
|
+
|
487
|
+
option_variants = worker_config.delete(:variants) || [{}]
|
488
|
+
option_variants = case option_variants
|
489
|
+
when Array then option_variants
|
490
|
+
when Hash then option_variants.variants
|
491
|
+
else fail "Array or Hash expected, got #{option_variants}"
|
473
492
|
end
|
474
|
-
|
475
|
-
options = HashHelpers.deep_symbolise_keys(options)
|
476
|
-
options[:allow_consecutive_on] = allow_consecutive_on
|
493
|
+
option_variants.each do |options|
|
494
|
+
options = HashHelpers.deep_symbolise_keys(options).merge(worker_config)
|
477
495
|
worker = WorkerVariant.new(klass, image_optim, options)
|
478
496
|
worker.image_formats.each do |format|
|
479
497
|
@workers_by_format[format] << worker
|
@@ -483,7 +501,7 @@ class Analyser
|
|
483
501
|
|
484
502
|
log_workers_by_format
|
485
503
|
|
486
|
-
fail "unknown variants: #{
|
504
|
+
fail "unknown variants: #{config}" unless config.empty?
|
487
505
|
end
|
488
506
|
|
489
507
|
def analyse(paths)
|
@@ -553,7 +571,30 @@ private
|
|
553
571
|
end
|
554
572
|
end
|
555
573
|
|
556
|
-
|
574
|
+
abort <<-HELP if ARGV.empty?
|
575
|
+
Specify paths for analysis.
|
576
|
+
|
577
|
+
Example of `.analysis_variants.yml`:
|
578
|
+
jhead:
|
579
|
+
required: true # don't skip this worker
|
580
|
+
jpegtran: # 3 worker variants
|
581
|
+
variants:
|
582
|
+
- jpegrescan: true
|
583
|
+
- progressive: true
|
584
|
+
- progressive: false
|
585
|
+
optipng: # 6 worker variants by combining options
|
586
|
+
variants:
|
587
|
+
level: [6, 7]
|
588
|
+
interlace: [true, false, nil]
|
589
|
+
gifsicle: # allow variants with different interlace to run consecutively
|
590
|
+
variants:
|
591
|
+
allow_consecutive_on: interlace
|
592
|
+
interlace: [true, false]
|
593
|
+
careful: [true, false]
|
594
|
+
# other workers will be used with default options
|
595
|
+
HELP
|
596
|
+
|
597
|
+
Analyser.new(begin
|
557
598
|
path = '.analysis_variants.yml'
|
558
599
|
case h = YAML.load_file(path)
|
559
600
|
when Hash then h
|
@@ -563,27 +604,4 @@ def option_variants
|
|
563
604
|
rescue Errno::ENOENT => e
|
564
605
|
warn e
|
565
606
|
{}
|
566
|
-
end
|
567
|
-
|
568
|
-
analyser = Analyser.new(option_variants)
|
569
|
-
|
570
|
-
if ARGV.empty?
|
571
|
-
abort <<-HELP
|
572
|
-
Specify paths for analysis.
|
573
|
-
|
574
|
-
Example of `.analysis_variants.yml`:
|
575
|
-
jpegtran: # 3 worker variants
|
576
|
-
- jpegrescan: true
|
577
|
-
- progressive: true
|
578
|
-
- progressive: false
|
579
|
-
optipng: # 6 worker variants by combining options
|
580
|
-
level: [6, 7]
|
581
|
-
interlace: [true, false, nil]
|
582
|
-
gifsicle: # allow variants with different interlace to run consecutively
|
583
|
-
allow_consecutive_on: interlace
|
584
|
-
interlace: [true, false]
|
585
|
-
careful: [true, false]
|
586
|
-
# other workers will be used with default options
|
587
|
-
HELP
|
588
|
-
end
|
589
|
-
analyser.analyse(ARGV)
|
607
|
+
end).analyse(ARGV)
|
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.
|
4
|
+
version: 0.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Kuchin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fspath
|
@@ -132,14 +132,14 @@ dependencies:
|
|
132
132
|
requirements:
|
133
133
|
- - "~>"
|
134
134
|
- !ruby/object:Gem::Version
|
135
|
-
version: '0.
|
135
|
+
version: '0.49'
|
136
136
|
type: :development
|
137
137
|
prerelease: false
|
138
138
|
version_requirements: !ruby/object:Gem::Requirement
|
139
139
|
requirements:
|
140
140
|
- - "~>"
|
141
141
|
- !ruby/object:Gem::Version
|
142
|
-
version: '0.
|
142
|
+
version: '0.49'
|
143
143
|
description:
|
144
144
|
email:
|
145
145
|
executables:
|