discourse_image_optim 0.24.5 → 0.26.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +0 -1
- data/.rubocop.yml +38 -34
- data/.travis.yml +11 -9
- data/CHANGELOG.markdown +21 -3
- data/Gemfile +0 -1
- data/README.markdown +61 -50
- data/bin/image_optim +1 -1
- data/image_optim.gemspec +3 -3
- data/lib/image_optim/bin_resolver/bin.rb +1 -0
- data/lib/image_optim/runner/option_parser.rb +3 -1
- data/lib/image_optim/worker/jhead.rb +1 -1
- data/lib/image_optim/worker/jpegtran.rb +1 -1
- data/lib/image_optim/worker/pngquant.rb +6 -0
- data/lib/image_optim/worker.rb +2 -1
- data/script/worker_analysis +76 -58
- data/vendor/jpegrescan +49 -19
- data/vendor/jpegrescan.bat +6 -0
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d4cc5e84e0c8dff3c8fd0af654608b8ee958b3283463f7f945076964ae9d3eae
|
4
|
+
data.tar.gz: ca77fd28eac0fb79493ed19600eaae18fdb7ea244f9025fdc909e7791a32133e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcbd37ef3c8899889ebcf1912f0200f7bab98399779e32658b39d55af99da87f452dfec263e91d15a177e1700d566705891f455191758ebc23f9c68d47b96cfa
|
7
|
+
data.tar.gz: 0b1379b801324ee93c546c4672abec97385cd7e5c50624e8657c9049d4f4e06135d167783d46901385209aab8b0ae364dfaf40887a67f8931c8a3b6f36255352
|
data/.gitignore
CHANGED
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
|
@@ -13,6 +40,9 @@ Lint/AmbiguousBlockAssociation:
|
|
13
40
|
Lint/EndAlignment:
|
14
41
|
EnforcedStyleAlignWith: variable
|
15
42
|
|
43
|
+
Lint/NestedPercentLiteral:
|
44
|
+
Enabled: false
|
45
|
+
|
16
46
|
Lint/UnneededSplatExpansion:
|
17
47
|
Enabled: false
|
18
48
|
|
@@ -41,18 +71,9 @@ Security/MarshalLoad:
|
|
41
71
|
Exclude:
|
42
72
|
- 'script/worker_analysis'
|
43
73
|
|
44
|
-
Style/AccessModifierIndentation:
|
45
|
-
EnforcedStyle: outdent
|
46
|
-
|
47
74
|
Style/Alias:
|
48
75
|
EnforcedStyle: prefer_alias_method
|
49
76
|
|
50
|
-
Style/CaseIndentation:
|
51
|
-
EnforcedStyle: end
|
52
|
-
|
53
|
-
Style/DotPosition:
|
54
|
-
EnforcedStyle: trailing
|
55
|
-
|
56
77
|
Style/DoubleNegation:
|
57
78
|
Enabled: false
|
58
79
|
|
@@ -60,33 +81,22 @@ Style/EmptyCaseCondition:
|
|
60
81
|
Enabled: false
|
61
82
|
|
62
83
|
Style/Encoding:
|
63
|
-
|
84
|
+
Enabled: false
|
85
|
+
|
86
|
+
Style/FormatStringToken:
|
87
|
+
Enabled: false
|
64
88
|
|
65
89
|
Style/HashSyntax:
|
66
90
|
EnforcedStyle: hash_rockets
|
67
91
|
|
68
92
|
Style/IfUnlessModifier:
|
69
|
-
MaxLineLength: 40
|
70
|
-
|
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
93
|
Enabled: false
|
82
94
|
|
83
95
|
Style/ParallelAssignment:
|
84
96
|
Enabled: false
|
85
97
|
|
86
|
-
Style/
|
87
|
-
|
88
|
-
'%w': '[]'
|
89
|
-
'%W': '[]'
|
98
|
+
Style/RescueStandardError:
|
99
|
+
EnforcedStyle: implicit
|
90
100
|
|
91
101
|
Style/Semicolon:
|
92
102
|
AllowAsExpressionSeparator: true
|
@@ -94,17 +104,11 @@ Style/Semicolon:
|
|
94
104
|
Style/SignalException:
|
95
105
|
EnforcedStyle: semantic
|
96
106
|
|
97
|
-
Style/
|
98
|
-
|
99
|
-
|
100
|
-
Style/SpaceInsideHashLiteralBraces:
|
101
|
-
EnforcedStyle: no_space
|
107
|
+
Style/SymbolArray:
|
108
|
+
Enabled: false
|
102
109
|
|
103
110
|
Style/TrailingCommaInArguments:
|
104
111
|
EnforcedStyleForMultiline: no_comma
|
105
112
|
|
106
113
|
Style/TrailingCommaInLiteral:
|
107
114
|
EnforcedStyleForMultiline: comma
|
108
|
-
|
109
|
-
Style/SymbolArray:
|
110
|
-
Enabled: false
|
data/.travis.yml
CHANGED
@@ -10,30 +10,32 @@ rvm:
|
|
10
10
|
- '1.9.3-p551'
|
11
11
|
- '2.0.0-p648'
|
12
12
|
- '2.1.10'
|
13
|
-
- '2.2.
|
14
|
-
- '2.3.
|
15
|
-
- '2.4.
|
16
|
-
- 'jruby-1.7.26'
|
13
|
+
- '2.2.8'
|
14
|
+
- '2.3.5'
|
15
|
+
- '2.4.2'
|
17
16
|
- 'jruby-9.0.5.0'
|
18
|
-
- 'jruby-9.1.
|
17
|
+
- 'jruby-9.1.9.0'
|
19
18
|
script:
|
20
19
|
- bundle exec image_optim --info
|
21
20
|
- bundle exec rspec
|
22
21
|
before_install:
|
22
|
+
- gem update --system
|
23
|
+
- gem update bundler
|
24
|
+
- nvm install stable
|
23
25
|
- mkdir -p ~/bin
|
24
|
-
- command -v svgo || npm install svgo
|
26
|
+
- command -v svgo || npm install -g svgo
|
25
27
|
- 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'
|
26
28
|
matrix:
|
27
29
|
include:
|
28
30
|
- env: CODECLIMATE=✓
|
29
|
-
rvm: '2.4.
|
31
|
+
rvm: '2.4.2'
|
30
32
|
after_success: bundle exec codeclimate-test-reporter
|
31
33
|
- env: RUBOCOP=✓
|
32
|
-
rvm: '2.4.
|
34
|
+
rvm: '2.4.2'
|
33
35
|
script: bundle exec rubocop
|
34
36
|
before_install:
|
35
37
|
- env: CHECK_RUBIES=✓
|
36
|
-
rvm: '2.4.
|
38
|
+
rvm: '2.4.2'
|
37
39
|
script: bundle exec travis_check_rubies
|
38
40
|
before_install:
|
39
41
|
addons:
|
data/CHANGELOG.markdown
CHANGED
@@ -2,8 +2,26 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v0.26.1 (2017-12-14)
|
6
|
+
|
7
|
+
* Require `'date'` which is used in parsing pngout version [toy/image_optim_pack#14](https://github.com/toy/image_optim_pack/issues/14) [@toy](https://github.com/toy)
|
8
|
+
|
5
9
|
* Add `timeout` option to workers [#21](https://github.com/toy/image_optim/issues/21)
|
6
|
-
[@tgxworld](http://github.com/tgxworld)
|
10
|
+
[@tgxworld](http://github.com/tgxworld)
|
11
|
+
|
12
|
+
## v0.26.0 (2017-11-13)
|
13
|
+
|
14
|
+
* Enable `jpegrescan` by default after removing its dependency on `File::Slurp` and fixing for windows [#153](https://github.com/toy/image_optim/issues/153) [@toy](https://github.com/toy)
|
15
|
+
* Extend description of `--verbose` flag [#152](https://github.com/toy/image_optim/issues/152) [@toy](https://github.com/toy)
|
16
|
+
|
17
|
+
## v0.25.0 (2017-07-06)
|
18
|
+
|
19
|
+
* 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)
|
20
|
+
* 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)
|
21
|
+
|
22
|
+
## v0.24.3 (2017-05-04)
|
23
|
+
|
24
|
+
* Set mode of cache files to `0666 & ~umask`, related to [#147](https://github.com/toy/image_optim/issues/147) [@toy](https://github.com/toy)
|
7
25
|
|
8
26
|
## v0.24.2 (2017-02-18)
|
9
27
|
|
@@ -18,7 +36,7 @@
|
|
18
36
|
|
19
37
|
## v0.24.0 (2016-08-14)
|
20
38
|
|
21
|
-
* Rails image assets optimization is extracted into [
|
39
|
+
* Rails image assets optimization is extracted into [image_optim_rails gem](https://github.com/toy/image_optim_rails) [#127](https://github.com/toy/image_optim/issues/127) [@toy](https://github.com/toy)
|
22
40
|
* Add proper handling of `ImageOptim.respond_to?` [@toy](https://github.com/toy)
|
23
41
|
* Fix an issue not working OptiPNG `interlace` option [#136](https://github.com/toy/image_optim/pull/136) [@mrk21](https://github.com/mrk21)
|
24
42
|
* Minimize number of file system calls in default implementation of `optimized?` [#137](https://github.com/toy/image_optim/issues/137) [@toy](https://github.com/toy)
|
@@ -265,7 +283,7 @@
|
|
265
283
|
|
266
284
|
* Warn if directly added files are not images or are not optimizable [@toy](https://github.com/toy)
|
267
285
|
* Recursively scan directories for images [#4](https://github.com/toy/image_optim/issues/4) [@toy](https://github.com/toy)
|
268
|
-
* Typo in bin/image_optim
|
286
|
+
* Typo in bin/image_optim [#3](https://github.com/toy/image_optim/issues/3) [@fabiomcosta](https://github.com/fabiomcosta)
|
269
287
|
|
270
288
|
## v0.5.1 (2012-08-07)
|
271
289
|
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
Optimize (lossless compress, optionally lossy) images (jpeg, png, gif, svg) using external utilities:
|
12
12
|
|
13
13
|
* [advpng](http://advancemame.sourceforge.net/doc-advpng.html) from [AdvanceCOMP](http://advancemame.sourceforge.net/comp-readme.html)
|
14
|
-
(will use [zopfli](https://code.google.com/p/zopfli/) on default/maximum level 4)
|
14
|
+
(will use [zopfli](https://code.google.com/p/zopfli/) on default/maximum level 4)
|
15
15
|
* [gifsicle](http://www.lcdf.org/gifsicle/)
|
16
16
|
* [jhead](http://www.sentex.net/~mwandel/jhead/)
|
17
17
|
* [jpegoptim](http://www.kokkonen.net/tjko/projects.html)
|
@@ -57,9 +57,11 @@ gem 'image_optim_pack'
|
|
57
57
|
With version:
|
58
58
|
|
59
59
|
<!---<update-version>-->
|
60
|
+
|
60
61
|
```ruby
|
61
|
-
gem 'image_optim', '~> 0.
|
62
|
+
gem 'image_optim', '~> 0.26'
|
62
63
|
```
|
64
|
+
|
63
65
|
<!---</update-version>-->
|
64
66
|
|
65
67
|
If you want to check latest changes:
|
@@ -241,7 +243,7 @@ image_optim.optimize_images_data(datas)
|
|
241
243
|
|
242
244
|
### From rails
|
243
245
|
|
244
|
-
Rails image assets optimization is extracted into [
|
246
|
+
Rails image assets optimization is extracted into [image_optim_rails gem](https://github.com/toy/image_optim_rails).
|
245
247
|
|
246
248
|
## Configuration
|
247
249
|
|
@@ -263,79 +265,92 @@ optipng:
|
|
263
265
|
|
264
266
|
## Options
|
265
267
|
|
266
|
-
* `:nice` — Nice level, priority of all used tools with higher value meaning lower priority, in range `-20..19`, negative values can be set only if run by root user
|
267
|
-
* `:threads` — Number of threads or disable
|
268
|
-
* `:verbose` — Verbose output
|
269
|
-
* `:pack` — Require
|
270
|
-
* `:skip_missing_workers` — Skip workers with missing or problematic binaries
|
271
|
-
* `:allow_lossy` — Allow lossy workers and optimizations
|
268
|
+
* `:nice` — Nice level, priority of all used tools with higher value meaning lower priority, in range `-20..19`, negative values can be set only if run by root user _(defaults to `10`)_
|
269
|
+
* `:threads` — Number of threads or disable _(defaults to number of processors)_
|
270
|
+
* `:verbose` — Verbose output _(defaults to `false`)_
|
271
|
+
* `:pack` — Require image_optim_pack or disable it, by default image_optim_pack will be used if available, will turn on `:skip-missing-workers` unless explicitly disabled _(defaults to `nil`)_
|
272
|
+
* `:skip_missing_workers` — Skip workers with missing or problematic binaries _(defaults to `false`)_
|
273
|
+
* `:allow_lossy` — Allow lossy workers and optimizations _(defaults to `false`)_
|
272
274
|
* `:cache_dir` — Configure cache directory
|
273
275
|
* `:cache_worker_digests` - Also cache worker digests along with original file digest and worker options: updating workers invalidates cache
|
274
|
-
* `:timeout` — Number of seconds before workers are timed out. Must be greater than 0 to enable timeout.
|
276
|
+
* `:timeout` — Number of seconds before workers are timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
275
277
|
|
276
278
|
Worker can be disabled by passing `false` instead of options hash or by setting option `:disable` to `true`.
|
277
279
|
|
278
280
|
<!---<worker-options>-->
|
281
|
+
|
279
282
|
<!-- markdown for worker options is generated by `script/update_worker_options_in_readme` -->
|
280
283
|
|
281
284
|
### advpng:
|
282
|
-
|
283
|
-
* `:
|
285
|
+
|
286
|
+
* `:level` — Compression level: `0` - don't compress, `1` - fast, `2` - normal, `3` - extra, `4` - extreme _(defaults to `4`)_
|
287
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
284
288
|
|
285
289
|
### gifsicle:
|
290
|
+
|
286
291
|
* `:interlace` — Interlace: `true` - interlace on, `false` - interlace off, `nil` - as is in original image (defaults to running two instances, one with interlace off and one with on)
|
287
|
-
* `:level` — Compression level: `1` - light and fast, `2` - normal, `3` - heavy (slower)
|
288
|
-
* `:careful` — Avoid bugs with some software
|
289
|
-
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout.
|
292
|
+
* `:level` — Compression level: `1` - light and fast, `2` - normal, `3` - heavy (slower) _(defaults to `3`)_
|
293
|
+
* `:careful` — Avoid bugs with some software _(defaults to `false`)_
|
294
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
290
295
|
|
291
296
|
### jhead:
|
292
|
-
|
297
|
+
|
298
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
293
299
|
|
294
300
|
### jpegoptim:
|
295
|
-
|
296
|
-
* `:
|
297
|
-
* `:
|
298
|
-
* `:
|
301
|
+
|
302
|
+
* `:allow_lossy` — Allow limiting maximum quality _(defaults to `false`)_
|
303
|
+
* `:strip` — List of extra markers to strip: `:comments`, `:exif`, `:iptc`, `:icc` or `:all` _(defaults to `:all`)_
|
304
|
+
* `:max_quality` — Maximum image quality factor `0`..`100`, ignored in default/lossless mode _(defaults to `100`)_
|
305
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
299
306
|
|
300
307
|
### jpegrecompress:
|
301
|
-
|
302
|
-
* `:
|
303
|
-
* `:
|
308
|
+
|
309
|
+
* `:allow_lossy` — Allow worker, it is always lossy _(defaults to `false`)_
|
310
|
+
* `:quality` — JPEG quality preset: `0` - low, `1` - medium, `2` - high, `3` - veryhigh _(defaults to `3`)_
|
311
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
304
312
|
|
305
313
|
### jpegtran:
|
306
|
-
|
307
|
-
* `:
|
308
|
-
* `:
|
309
|
-
* `:
|
314
|
+
|
315
|
+
* `:copy_chunks` — Copy all chunks _(defaults to `false`)_
|
316
|
+
* `:progressive` — Create progressive JPEG file _(defaults to `true`)_
|
317
|
+
* `:jpegrescan` — Use jpegtran through jpegrescan, ignore progressive option _(defaults to `false`)_
|
318
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
310
319
|
|
311
320
|
### optipng:
|
312
|
-
|
313
|
-
* `:
|
314
|
-
* `:
|
315
|
-
* `:
|
321
|
+
|
322
|
+
* `:level` — Optimization level preset: `0` is least, `7` is best _(defaults to `6`)_
|
323
|
+
* `:interlace` — Interlace: `true` - interlace on, `false` - interlace off, `nil` - as is in original image _(defaults to `false`)_
|
324
|
+
* `:strip` — Remove all auxiliary chunks _(defaults to `true`)_
|
325
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
316
326
|
|
317
327
|
### pngcrush:
|
318
|
-
|
319
|
-
* `:
|
320
|
-
* `:
|
321
|
-
* `:
|
322
|
-
* `:
|
328
|
+
|
329
|
+
* `:chunks` — List of chunks to remove or `:alla` - all except tRNS/transparency or `:allb` - all except tRNS and gAMA/gamma _(defaults to `:alla`)_
|
330
|
+
* `:fix` — Fix otherwise fatal conditions such as bad CRCs _(defaults to `false`)_
|
331
|
+
* `:brute` — Brute force try all methods, very time-consuming and generally not worthwhile _(defaults to `false`)_
|
332
|
+
* `:blacken` — Blacken fully transparent pixels _(defaults to `true`)_
|
333
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
323
334
|
|
324
335
|
### pngout:
|
325
|
-
|
326
|
-
* `:
|
327
|
-
* `:
|
336
|
+
|
337
|
+
* `:copy_chunks` — Copy optional chunks _(defaults to `false`)_
|
338
|
+
* `:strategy` — Strategy: `0` - xtreme, `1` - intense, `2` - longest Match, `3` - huffman Only, `4` - uncompressed _(defaults to `0`)_
|
339
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
328
340
|
|
329
341
|
### pngquant:
|
330
|
-
|
331
|
-
* `:
|
332
|
-
* `:
|
333
|
-
* `:
|
342
|
+
|
343
|
+
* `:allow_lossy` — Allow quality option _(defaults to `false`)_
|
344
|
+
* `:max_colors` — Maximum number of colors to use _(defaults to `256`)_
|
345
|
+
* `: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)_
|
346
|
+
* `:speed` — speed/quality trade-off: `1` - slow, `3` - default, `11` - fast & rough _(defaults to `3`)_
|
347
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
334
348
|
|
335
349
|
### svgo:
|
336
|
-
|
337
|
-
* `:
|
338
|
-
* `:
|
350
|
+
|
351
|
+
* `:disable_plugins` — List of plugins to disable _(defaults to `[]`)_
|
352
|
+
* `:enable_plugins` — List of plugins to enable _(defaults to `[]`)_
|
353
|
+
* `:timeout` — Number of seconds before worker is timed out. Must be greater than 0 to enable timeout. _(defaults to `0`)_
|
339
354
|
|
340
355
|
<!---</worker-options>-->
|
341
356
|
|
@@ -345,10 +360,6 @@ Worker can be disabled by passing `false` instead of options hash or by setting
|
|
345
360
|
|
346
361
|
If you would like to contribute - that is great and you are very welcome. Please check few notes in file [CONTRIBUTING.markdown](CONTRIBUTING.markdown).
|
347
362
|
|
348
|
-
Financial contributions can be made via [gratipay](https://gratipay.com/toy/).
|
349
|
-
|
350
|
-
[![Support via Gratipay](https://cdn.rawgit.com/gratipay/gratipay-badge/2.1.2/dist/gratipay.png)](https://gratipay.com/toy/)
|
351
|
-
|
352
363
|
## ChangeLog
|
353
364
|
|
354
365
|
In separate file [CHANGELOG.markdown](CHANGELOG.markdown).
|
data/bin/image_optim
CHANGED
data/image_optim.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'discourse_image_optim'
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.26.1'
|
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']
|
@@ -28,7 +28,7 @@ EOF
|
|
28
28
|
|
29
29
|
s.add_development_dependency 'image_optim_pack', '~> 0.2', '>= 0.2.2'
|
30
30
|
s.add_development_dependency 'rspec', '~> 3.0'
|
31
|
-
if RUBY_VERSION >= '2.
|
32
|
-
s.add_development_dependency 'rubocop', '~> 0.
|
31
|
+
if RUBY_VERSION >= '2.1'
|
32
|
+
s.add_development_dependency 'rubocop', '~> 0.52'
|
33
33
|
end
|
34
34
|
end
|
@@ -225,7 +225,9 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
225
225
|
op.separator nil
|
226
226
|
op.separator ' Common options:'
|
227
227
|
|
228
|
-
op.on_tail('-v', '--verbose', 'Verbose output'
|
228
|
+
op.on_tail('-v', '--verbose', 'Verbose output (show global and worker '\
|
229
|
+
'config, binary resolution log, information about each tool invocation, '\
|
230
|
+
'backtrace of exception)') do
|
229
231
|
options[:verbose] = true
|
230
232
|
end
|
231
233
|
|
@@ -14,7 +14,7 @@ class ImageOptim
|
|
14
14
|
option(:progressive, true, 'Create progressive JPEG file'){ |v| !!v }
|
15
15
|
|
16
16
|
JPEGRESCAN_OPTION =
|
17
|
-
option(:jpegrescan,
|
17
|
+
option(:jpegrescan, true, 'Use jpegtran through jpegrescan, '\
|
18
18
|
'ignore progressive option'){ |v| !!v }
|
19
19
|
|
20
20
|
TIMEOUT_OPTION = timeout_option
|
@@ -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 '\
|
@@ -51,6 +56,7 @@ class ImageOptim
|
|
51
56
|
--speed=#{speed}
|
52
57
|
--output=#{dst}
|
53
58
|
--force
|
59
|
+
#{max_colors}
|
54
60
|
--
|
55
61
|
#{src}
|
56
62
|
]
|
data/lib/image_optim/worker.rb
CHANGED
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)
|
data/vendor/jpegrescan
CHANGED
@@ -1,11 +1,19 @@
|
|
1
|
-
#!/usr/bin/perl
|
1
|
+
#!/usr/bin/env perl
|
2
2
|
# jpegrescan by Loren Merritt
|
3
3
|
# Last updated: 2008-11-29 / 2013-03-19
|
4
4
|
# This code is public domain.
|
5
5
|
|
6
|
-
use
|
6
|
+
use warnings;
|
7
7
|
use File::Temp qw/ tempfile /;
|
8
8
|
|
9
|
+
%switches = ();
|
10
|
+
while (@ARGV && $ARGV[0] =~ /^-.+/) {
|
11
|
+
for (shift @ARGV) {
|
12
|
+
m/^--$/ && last;
|
13
|
+
m/^-([svq])$/ && do { $switches{$1} = 1; next; };
|
14
|
+
die "Unknown switch: $_";
|
15
|
+
}
|
16
|
+
}
|
9
17
|
@ARGV==2 or die "usage: jpegrescan in.jpg out.jpg
|
10
18
|
tries various progressive scan orders
|
11
19
|
switches:
|
@@ -15,26 +23,49 @@ switches:
|
|
15
23
|
";
|
16
24
|
$fin = $ARGV[0];
|
17
25
|
$fout = $ARGV[1];
|
18
|
-
(undef, $
|
19
|
-
$
|
20
|
-
$
|
21
|
-
$
|
22
|
-
|
23
|
-
|
26
|
+
(undef, $meta_tmp) = tempfile(SUFFIX => ".scan");
|
27
|
+
(undef, $baseline_tmp) = tempfile(SUFFIX => ".jpg");
|
28
|
+
$output_tmp = $fout;
|
29
|
+
$verbose = $switches{'v'};
|
30
|
+
$quiet = $switches{'q'};
|
31
|
+
@strip = $switches{'s'} ? ("-copy","none") : ("-copy","all");
|
24
32
|
undef $/;
|
25
33
|
$|=1;
|
26
34
|
|
35
|
+
sub read_file {
|
36
|
+
my ($path) = @_;
|
37
|
+
my $data;
|
38
|
+
|
39
|
+
open my $fh, '<', $path
|
40
|
+
or die "Could not open file $path: $!\n";
|
41
|
+
binmode $fh;
|
42
|
+
$data = <$fh>;
|
43
|
+
close $fh
|
44
|
+
or die "Could not close $path: $!\n";
|
45
|
+
|
46
|
+
return $data;
|
47
|
+
}
|
48
|
+
|
49
|
+
sub write_file {
|
50
|
+
my ($path, $data) = @_;
|
51
|
+
|
52
|
+
open my $fh, '>', $path
|
53
|
+
or die "Could not open file $path: $!\n";
|
54
|
+
binmode $fh;
|
55
|
+
print $fh $data;
|
56
|
+
close $fh
|
57
|
+
or die "Could not close $path: $!\n";
|
58
|
+
}
|
59
|
+
|
27
60
|
# convert the input to baseline, just to make all the other conversions faster
|
28
61
|
# FIXME there's still a bunch of redundant computation in separate calls to jpegtran
|
29
62
|
open $OLDERR, ">&", STDERR;
|
30
|
-
open STDERR, ">", $
|
31
|
-
|
32
|
-
write_file($jtmp, <TRAN>);
|
33
|
-
close TRAN;
|
63
|
+
open STDERR, ">", $meta_tmp;
|
64
|
+
system("jpegtran", "-v", @strip, "-optimize", "-outfile", $baseline_tmp, $fin) == 0 or die;
|
34
65
|
open STDERR, ">&", $OLDERR;
|
35
66
|
|
36
|
-
$type = read_file($
|
37
|
-
$type =~ /components=(\d+)/ or die;
|
67
|
+
$type = read_file($meta_tmp);
|
68
|
+
$type =~ /components=(\d+)/ or die "Could not find components=\d+ in $type";
|
38
69
|
$rgb = $1==3 ? 1 : $1==1 ? 0 : die "not RGB nor gray\n";
|
39
70
|
|
40
71
|
# FIXME optimize order for either progressive transfer or decoding speed
|
@@ -55,10 +86,9 @@ sub canonize {
|
|
55
86
|
sub try {
|
56
87
|
my $txt = canonize(shift);
|
57
88
|
return $memo{$txt} if $memo{$txt};
|
58
|
-
write_file($
|
59
|
-
|
60
|
-
$data =
|
61
|
-
close TRAN;
|
89
|
+
write_file($meta_tmp, $txt);
|
90
|
+
system("jpegtran", @strip, "-scans", $meta_tmp, "-outfile", $output_tmp, $baseline_tmp) == 0 or die;
|
91
|
+
$data = read_file($output_tmp);
|
62
92
|
my $s = length $data;
|
63
93
|
$s or die;
|
64
94
|
$memo{$txt} = $s;
|
@@ -140,4 +170,4 @@ $old_size = -s $fin;
|
|
140
170
|
if($size < $old_size) {
|
141
171
|
write_file($fout, $data);
|
142
172
|
}
|
143
|
-
unlink $
|
173
|
+
unlink $meta_tmp, $baseline_tmp;
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: discourse_image_optim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.26.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:
|
11
|
+
date: 2018-07-03 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.52'
|
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.52'
|
143
143
|
description:
|
144
144
|
email:
|
145
145
|
executables:
|
@@ -250,6 +250,7 @@ files:
|
|
250
250
|
- spec/images/vergroessert.jpg
|
251
251
|
- spec/spec_helper.rb
|
252
252
|
- vendor/jpegrescan
|
253
|
+
- vendor/jpegrescan.bat
|
253
254
|
homepage: http://github.com/toy/discourse_image_optim
|
254
255
|
licenses:
|
255
256
|
- MIT
|
@@ -272,7 +273,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
272
273
|
version: '0'
|
273
274
|
requirements: []
|
274
275
|
rubyforge_project: discourse_image_optim
|
275
|
-
rubygems_version: 2.6
|
276
|
+
rubygems_version: 2.7.6
|
276
277
|
signing_key:
|
277
278
|
specification_version: 4
|
278
279
|
summary: Optimize (lossless compress, optionally lossy) images (jpeg, png, gif, svg)
|