image_optim 0.22.1 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.appveyor.yml +95 -0
- data/.rubocop.yml +3 -0
- data/.travis.yml +27 -22
- data/CHANGELOG.markdown +10 -0
- data/CONTRIBUTING.markdown +2 -1
- data/Gemfile +1 -1
- data/README.markdown +10 -2
- data/image_optim.gemspec +4 -4
- data/lib/image_optim.rb +32 -16
- data/lib/image_optim/bin_resolver/bin.rb +11 -4
- data/lib/image_optim/cache.rb +71 -0
- data/lib/image_optim/cache_path.rb +16 -0
- data/lib/image_optim/config.rb +12 -2
- data/lib/image_optim/handler.rb +1 -1
- data/lib/image_optim/image_meta.rb +5 -10
- data/lib/image_optim/optimized_path.rb +25 -0
- data/lib/image_optim/path.rb +70 -0
- data/lib/image_optim/runner/option_parser.rb +13 -0
- data/lib/image_optim/worker.rb +5 -8
- data/lib/image_optim/worker/class_methods.rb +3 -1
- data/lib/image_optim/worker/jpegoptim.rb +3 -0
- data/lib/image_optim/worker/jpegrecompress.rb +3 -0
- data/lib/image_optim/worker/pngquant.rb +3 -0
- data/script/worker_analysis +10 -9
- data/spec/image_optim/bin_resolver/comparable_condition_spec.rb +1 -1
- data/spec/image_optim/bin_resolver/simple_version_spec.rb +48 -40
- data/spec/image_optim/bin_resolver_spec.rb +190 -172
- data/spec/image_optim/cache_path_spec.rb +59 -0
- data/spec/image_optim/cache_spec.rb +159 -0
- data/spec/image_optim/cmd_spec.rb +11 -7
- data/spec/image_optim/config_spec.rb +92 -71
- data/spec/image_optim/handler_spec.rb +3 -6
- data/spec/image_optim/image_meta_spec.rb +61 -0
- data/spec/image_optim/optimized_path_spec.rb +58 -0
- data/spec/image_optim/option_helpers_spec.rb +25 -0
- data/spec/image_optim/path_spec.rb +105 -0
- data/spec/image_optim/railtie_spec.rb +6 -6
- data/spec/image_optim/runner/glob_helpers_spec.rb +2 -6
- data/spec/image_optim/runner/option_parser_spec.rb +3 -3
- data/spec/image_optim/space_spec.rb +16 -18
- data/spec/image_optim/worker/optipng_spec.rb +3 -3
- data/spec/image_optim/worker/pngquant_spec.rb +47 -7
- data/spec/image_optim/worker_spec.rb +114 -17
- data/spec/image_optim_spec.rb +58 -69
- data/spec/images/broken_jpeg +1 -0
- data/spec/spec_helper.rb +40 -10
- metadata +30 -8
- data/lib/image_optim/image_path.rb +0 -68
- data/spec/image_optim/image_path_spec.rb +0 -54
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MzcwOTc4MmMxMjI0YWM4YmQ2NzcyZTE0NTRkNjM4YjNlMmMwZGExMA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZmFmOWZhY2U5MTMyNjIwM2U3N2M0Y2U1NjVkNTJkNmNjYTk4NzQ0Yg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NDMyNWI3ODA2ZTg5NTFjN2Y3YTJjMzU5MjAzZGM4ZDg3NzU4Y2IzYjU3NGZl
|
10
|
+
NmJkN2JiMTg3YmMyNmJjZjFkMDRlOGVlYWIzYjg2MmVhYzMxYTY5YjE0NDc5
|
11
|
+
N2ZlMmU2ZTQxNTU4NGMyYzcxMjU3MDM2MTllZGMxZjhiYjc0Y2E=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OWU2NjI5YjMyOWJmNmEzMGJjNGNmMjA0NmNlYWYyNzMxMDA0MTgyNDhjNmQz
|
14
|
+
NGU2NGY1Yzg4YzI3NTVkMjI4NTFiOGY1MzY0ZDlkYmI2MWFjNThmOTI3NGM0
|
15
|
+
M2ZmMjQ3OGIyZDc3YzY1NDI1MjU2N2U5ZDUyMDg3MDcwMzBkYTE=
|
data/.appveyor.yml
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
version: '{build}-{branch}'
|
2
|
+
install:
|
3
|
+
- mkdir tmp\bin || exit 0
|
4
|
+
- set PATH=%cd%\tmp\bin;%PATH%
|
5
|
+
- ruby --version
|
6
|
+
- bundle package --all
|
7
|
+
- echo curl.exe -fsSL --max-time 15 --retry 5 -o %%%%1 %%%%2 > tmp\bin\download.bat
|
8
|
+
|
9
|
+
- ps: | # advpng
|
10
|
+
if (-not (test-path tmp/bin/advpng.exe)) {
|
11
|
+
download.bat tmp/advancecomp.zip https://github.com/amadvance/advancecomp/releases/download/v1.20/advancecomp-1.20-windows-x86.zip
|
12
|
+
7z e tmp/advancecomp.zip -otmp/bin advpng.exe
|
13
|
+
}
|
14
|
+
|
15
|
+
- ps: | # gifsicle
|
16
|
+
if (-not (test-path tmp/bin/gifsicle.exe)) {
|
17
|
+
download.bat tmp/gifsicle.zip https://eternallybored.org/misc/gifsicle/releases/gifsicle-1.88-win64.zip
|
18
|
+
7z e tmp/gifsicle.zip -otmp/bin */gifsicle.exe
|
19
|
+
}
|
20
|
+
|
21
|
+
- ps: | # jhead
|
22
|
+
if (-not (test-path tmp/bin/jhead.exe)) {
|
23
|
+
download.bat tmp/bin/jhead.exe http://www.sentex.net/~mwandel/jhead/jhead.exe
|
24
|
+
}
|
25
|
+
|
26
|
+
- ps: | # jpeg-recompress
|
27
|
+
if (-not (test-path tmp/bin/jpeg-recompress.exe)) {
|
28
|
+
download.bat tmp/jpeg-archive.zip https://ci.appveyor.com/api/buildjobs/8t8vga27t8vn1js2/artifacts/jpeg-archive.zip
|
29
|
+
7z e tmp/jpeg-archive.zip -otmp/bin jpeg-recompress.exe
|
30
|
+
}
|
31
|
+
|
32
|
+
- ps: | # jpegoptim
|
33
|
+
if (-not (test-path tmp/bin/jpegoptim.exe)) {
|
34
|
+
download.bat tmp/jpegoptim.zip https://bitbucket.org/rorgoroth/jpegoptim-for-windows/downloads/jpegoptim-1.4.3-Win32.zip
|
35
|
+
7z e tmp/jpegoptim.zip -otmp/bin */jpegoptim.exe
|
36
|
+
}
|
37
|
+
|
38
|
+
- ps: | # jpegtran
|
39
|
+
if (-not (test-path tmp/bin/jpegtran.exe)) {
|
40
|
+
download.bat tmp/bin/jpegtran.exe http://jpegclub.org/jpegtran.exe
|
41
|
+
}
|
42
|
+
|
43
|
+
- ps: | # optipng
|
44
|
+
if (-not (test-path tmp/bin/optipng.exe)) {
|
45
|
+
download.bat tmp/optipng.zip https://sourceforge.net/projects/optipng/files/OptiPNG/optipng-0.7.6/optipng-0.7.6-win32.zip/download
|
46
|
+
7z e tmp/optipng.zip -otmp/bin */optipng.exe
|
47
|
+
}
|
48
|
+
|
49
|
+
- ps: | # pngcrush
|
50
|
+
if (-not (test-path tmp/bin/pngcrush.exe)) {
|
51
|
+
download.bat tmp/bin/pngcrush.exe https://sourceforge.net/projects/pmt/files/pngcrush-executables/1.8.1/pngcrush_1_8.1_w32.exe/download
|
52
|
+
}
|
53
|
+
|
54
|
+
- ps: | # pngout
|
55
|
+
if (-not (test-path tmp/bin/pngout.exe)) {
|
56
|
+
download.bat tmp/bin/pngout.exe http://advsys.net/ken/util/pngout.exe
|
57
|
+
}
|
58
|
+
|
59
|
+
- ps: | # pngquant
|
60
|
+
if (-not (test-path tmp/bin/pngquant.exe)) {
|
61
|
+
download.bat tmp/pngquant.zip https://pngquant.org/pngquant-windows.zip
|
62
|
+
7z e tmp/pngquant.zip -otmp/bin */pngquant.exe
|
63
|
+
}
|
64
|
+
|
65
|
+
- ps: | # svgo
|
66
|
+
npm install -g svgo
|
67
|
+
|
68
|
+
- ps: | # ImageMagick
|
69
|
+
if ((-not (test-path tmp/bin/convert.exe)) -or (-not (test-path tmp/bin/compare.exe)) -or (-not (test-path tmp/bin/magic.xml))) {
|
70
|
+
choco install -y imagemagick.tool
|
71
|
+
cp C:\ProgramData\chocolatey\lib\imagemagick.tool\tools\convert.exe tmp\bin
|
72
|
+
cp C:\ProgramData\chocolatey\lib\imagemagick.tool\tools\compare.exe tmp\bin
|
73
|
+
cp C:\ProgramData\chocolatey\lib\imagemagick.tool\tools\magic.xml tmp\bin
|
74
|
+
}
|
75
|
+
|
76
|
+
- bundle exec image_optim --info --allow-lossy --no-pack
|
77
|
+
cache:
|
78
|
+
- tmp/bin
|
79
|
+
build: off
|
80
|
+
test_script:
|
81
|
+
- ps: |
|
82
|
+
$path = $env:Path
|
83
|
+
$rubypaths = ls -Path C:\Ruby*\bin
|
84
|
+
foreach ($rubypath in $rubypaths[0, -2, -1]) {
|
85
|
+
echo "################################################################################"
|
86
|
+
$env:Path = "$rubypath;" + $path
|
87
|
+
ruby --version
|
88
|
+
bundle install --local -j4
|
89
|
+
bundle exec rspec
|
90
|
+
if ($LASTEXITCODE -gt 0) {
|
91
|
+
exit 1
|
92
|
+
}
|
93
|
+
}
|
94
|
+
$env:Path = $path
|
95
|
+
- bundle exec image_optim --allow-lossy -r spec/images
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -13,25 +13,30 @@ rvm:
|
|
13
13
|
- '2.2'
|
14
14
|
- jruby-19mode
|
15
15
|
- ree
|
16
|
-
script:
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
&&
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
16
|
+
script: |
|
17
|
+
(
|
18
|
+
set -ex
|
19
|
+
if [ -n "$RUBOCOP" ]; then
|
20
|
+
bundle exec rubocop
|
21
|
+
elif [ -n "$RAILS_VERSION" ] && [ -z "$CODECLIMATE" ]; then
|
22
|
+
bundle exec image_optim --info
|
23
|
+
bundle exec rspec spec/image_optim/railtie_spec.rb
|
24
|
+
else
|
25
|
+
bundle exec image_optim --info
|
26
|
+
bundle exec rspec
|
27
|
+
fi
|
28
|
+
)
|
29
|
+
before_install: |
|
30
|
+
(
|
31
|
+
set -ex
|
32
|
+
if [ -z "$RUBOCOP" ]; then
|
33
|
+
command -v svgo || npm install svgo
|
34
|
+
command -v pngout || {
|
35
|
+
mkdir -p ~/bin
|
36
|
+
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'
|
37
|
+
}
|
38
|
+
fi
|
39
|
+
)
|
35
40
|
matrix:
|
36
41
|
fast_finish: true
|
37
42
|
include:
|
@@ -40,9 +45,9 @@ matrix:
|
|
40
45
|
- env: RAILS_VERSION='~> 3.2'
|
41
46
|
rvm: default
|
42
47
|
- env: RAILS_VERSION='~> 4.0' SPROCKETS_RAILS_VERSION='~> 2.0'
|
43
|
-
rvm:
|
44
|
-
- env: RAILS_VERSION='~> 4.0'
|
45
|
-
rvm:
|
48
|
+
rvm: '2'
|
49
|
+
- env: RAILS_VERSION='~> 4.0' CODECLIMATE=1
|
50
|
+
rvm: '2'
|
46
51
|
- env: RUBOCOP=true
|
47
52
|
rvm: default
|
48
53
|
allow_failures:
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v0.23.0 (2016-07-17)
|
6
|
+
|
7
|
+
* Added `cache_dir` and `cache_worker_digests` options to cache results [#83](https://github.com/toy/image_optim/issues/83) [@gpakosz](https://github.com/gpakosz)
|
8
|
+
* Should work on windows [#24](https://github.com/toy/image_optim/issues/24) [@toy](https://github.com/toy)
|
9
|
+
* Rename `ImageOptim::ImagePath` to `ImageOptim::Path` and its method `#format` to `#image_format` [@toy](https://github.com/toy)
|
10
|
+
* Ignore empty config files [#133](https://github.com/toy/image_optim/issues/133) [@toy](https://github.com/toy)
|
11
|
+
* Use `FileUtils.move` in `ImagePath#replace` to rename file instead of copying on same device, don't preserve mtime and atime [#134](https://github.com/toy/image_optim/issues/134) [@toy](https://github.com/toy)
|
12
|
+
* Make `:allow_lossy` an individual option for workers that can use it, so it will be in the list of worker options [#130](https://github.com/toy/image_optim/issues/130) [@toy](https://github.com/toy)
|
13
|
+
* Use first 8 characters of sha1 hex for jpegrescan version [#131](https://github.com/toy/image_optim/issues/131) [@toy](https://github.com/toy)
|
14
|
+
|
5
15
|
## v0.22.1 (2016-02-21)
|
6
16
|
|
7
17
|
* Fix missing old (1.x) `pngquant` version as it was output to stderr [#123](https://github.com/toy/image_optim/issues/123) [@toy](https://github.com/toy)
|
data/CONTRIBUTING.markdown
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
* Create topic/feature branch: `git checkout -b awesome-changes`
|
4
4
|
* Commit…
|
5
|
-
* Add entry
|
5
|
+
* Add entry at the top of [ChangeLog](CHANGELOG.markdown)
|
6
6
|
* Run tests: `bundle exec rspec`
|
7
7
|
* Check code style: `bundle exec rubocop`
|
8
|
+
* Rebase on master and squash commits to logical units
|
8
9
|
* Push your branch: `git push origin awesome-changes`
|
9
10
|
* Create pull request
|
10
11
|
* Check if [travis is happy](https://travis-ci.org/toy/image_optim/pull_requests)
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
[![Gem Version](https://img.shields.io/gem/v/image_optim.svg?style=flat)](https://rubygems.org/gems/image_optim)
|
2
2
|
[![Build Status](https://img.shields.io/travis/toy/image_optim/master.svg?style=flat)](https://travis-ci.org/toy/image_optim)
|
3
|
+
[![AppVeyor Status](https://img.shields.io/appveyor/ci/toy/image-optim/master.svg?style=flat&label=windows)](https://ci.appveyor.com/project/toy/image-optim)
|
3
4
|
[![Code Climate](https://img.shields.io/codeclimate/github/toy/image_optim.svg?style=flat)](https://codeclimate.com/github/toy/image_optim)
|
4
5
|
[![Code Climate Coverage](https://img.shields.io/codeclimate/coverage/github/toy/image_optim.svg?style=flat)](https://codeclimate.com/github/toy/image_optim)
|
5
6
|
[![Dependency Status](https://img.shields.io/gemnasium/toy/image_optim.svg?style=flat)](https://gemnasium.com/toy/image_optim)
|
6
|
-
[![Inch CI](
|
7
|
+
[![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master&style=flat)](https://inch-ci.org/github/toy/image_optim)
|
7
8
|
|
8
9
|
# image_optim
|
9
10
|
|
@@ -55,9 +56,11 @@ gem 'image_optim_pack'
|
|
55
56
|
|
56
57
|
With version:
|
57
58
|
|
59
|
+
<!---<update-version>-->
|
58
60
|
```ruby
|
59
|
-
gem 'image_optim', '~> 0.
|
61
|
+
gem 'image_optim', '~> 0.23'
|
60
62
|
```
|
63
|
+
<!---</update-version>-->
|
61
64
|
|
62
65
|
If you want to check latest changes:
|
63
66
|
|
@@ -271,6 +274,8 @@ optipng:
|
|
271
274
|
* `: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
275
|
* `:skip_missing_workers` — Skip workers with missing or problematic binaries *(defaults to `false`)*
|
273
276
|
* `:allow_lossy` — Allow lossy workers and optimizations *(defaults to `false`)*
|
277
|
+
* `:cache_dir` — Configure cache directory
|
278
|
+
* `:cache_worker_digests` - Also cache worker digests along with original file digest and worker options: updating workers invalidates cache
|
274
279
|
|
275
280
|
Worker can be disabled by passing `false` instead of options hash or by setting option `:disable` to `true`.
|
276
281
|
|
@@ -289,10 +294,12 @@ Worker can be disabled by passing `false` instead of options hash or by setting
|
|
289
294
|
Worker has no options
|
290
295
|
|
291
296
|
### jpegoptim:
|
297
|
+
* `:allow_lossy` — Allow limiting maximum quality *(defaults to `false`)*
|
292
298
|
* `:strip` — List of extra markers to strip: `:comments`, `:exif`, `:iptc`, `:icc` or `:all` *(defaults to `:all`)*
|
293
299
|
* `:max_quality` — Maximum image quality factor `0`..`100`, ignored in default/lossless mode *(defaults to `100`)*
|
294
300
|
|
295
301
|
### jpegrecompress:
|
302
|
+
* `:allow_lossy` — Allow worker, it is always lossy *(defaults to `false`)*
|
296
303
|
* `:quality` — JPEG quality preset: `0` - low, `1` - medium, `2` - high, `3` - veryhigh *(defaults to `3`)*
|
297
304
|
|
298
305
|
### jpegtran:
|
@@ -316,6 +323,7 @@ Worker has no options
|
|
316
323
|
* `:strategy` — Strategy: `0` - xtreme, `1` - intense, `2` - longest Match, `3` - huffman Only, `4` - uncompressed *(defaults to `0`)*
|
317
324
|
|
318
325
|
### pngquant:
|
326
|
+
* `:allow_lossy` — Allow quality option *(defaults to `false`)*
|
319
327
|
* `: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)*
|
320
328
|
* `:speed` — speed/quality trade-off: `1` - slow, `3` - default, `11` - fast & rough *(defaults to `3`)*
|
321
329
|
|
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.23.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']
|
@@ -15,15 +15,15 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
16
|
s.require_paths = %w[lib]
|
17
17
|
|
18
|
-
s.add_dependency 'fspath', '~>
|
18
|
+
s.add_dependency 'fspath', '~> 3.0'
|
19
19
|
s.add_dependency 'image_size', '~> 1.3'
|
20
20
|
s.add_dependency 'exifr', '~> 1.2', '>= 1.2.2'
|
21
21
|
s.add_dependency 'progress', '~> 3.0', '>= 3.0.1'
|
22
22
|
s.add_dependency 'in_threads', '~> 1.3'
|
23
23
|
|
24
|
-
s.add_development_dependency 'image_optim_pack', '~> 0.2'
|
24
|
+
s.add_development_dependency 'image_optim_pack', '~> 0.2', '>= 0.2.2'
|
25
25
|
s.add_development_dependency 'rspec', '~> 3.0'
|
26
|
-
if
|
26
|
+
if RUBY_VERSION >= '1.9.3'
|
27
27
|
s.add_development_dependency 'rubocop', '~> 0.37'
|
28
28
|
end
|
29
29
|
end
|
data/lib/image_optim.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'image_optim/bin_resolver'
|
2
|
+
require 'image_optim/cache'
|
2
3
|
require 'image_optim/config'
|
3
4
|
require 'image_optim/handler'
|
4
5
|
require 'image_optim/image_meta'
|
5
|
-
require 'image_optim/
|
6
|
+
require 'image_optim/optimized_path'
|
7
|
+
require 'image_optim/path'
|
6
8
|
require 'image_optim/railtie' if defined?(Rails)
|
7
9
|
require 'image_optim/worker'
|
8
10
|
require 'in_threads'
|
@@ -37,6 +39,12 @@ class ImageOptim
|
|
37
39
|
# Allow lossy workers and optimizations
|
38
40
|
attr_reader :allow_lossy
|
39
41
|
|
42
|
+
# Cache directory
|
43
|
+
attr_reader :cache_dir
|
44
|
+
|
45
|
+
# Cache worker digests
|
46
|
+
attr_reader :cache_worker_digests
|
47
|
+
|
40
48
|
# Initialize workers, specify options using worker underscored name:
|
41
49
|
#
|
42
50
|
# pass false to disable worker
|
@@ -67,6 +75,8 @@ class ImageOptim
|
|
67
75
|
pack
|
68
76
|
skip_missing_workers
|
69
77
|
allow_lossy
|
78
|
+
cache_dir
|
79
|
+
cache_worker_digests
|
70
80
|
].each do |name|
|
71
81
|
instance_variable_set(:"@#{name}", config.send(name))
|
72
82
|
$stderr << "#{name}: #{send(name)}\n" if verbose
|
@@ -78,6 +88,8 @@ class ImageOptim
|
|
78
88
|
config.for_worker(klass)
|
79
89
|
end
|
80
90
|
|
91
|
+
@cache = Cache.new(self, @workers_by_format)
|
92
|
+
|
81
93
|
log_workers_by_format if verbose
|
82
94
|
|
83
95
|
config.assert_no_unused_options!
|
@@ -85,39 +97,43 @@ class ImageOptim
|
|
85
97
|
|
86
98
|
# Get workers for image
|
87
99
|
def workers_for_image(path)
|
88
|
-
@workers_by_format[
|
100
|
+
@workers_by_format[Path.convert(path).image_format]
|
89
101
|
end
|
90
102
|
|
91
|
-
# Optimize one file, return new path as
|
103
|
+
# Optimize one file, return new path as OptimizedPath or nil if
|
92
104
|
# optimization failed
|
93
105
|
def optimize_image(original)
|
94
|
-
original =
|
106
|
+
original = Path.convert(original)
|
95
107
|
return unless (workers = workers_for_image(original))
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
108
|
+
|
109
|
+
optimized = @cache.fetch(original) do
|
110
|
+
Handler.for(original) do |handler|
|
111
|
+
workers.each do |worker|
|
112
|
+
handler.process do |src, dst|
|
113
|
+
worker.optimize(src, dst)
|
114
|
+
end
|
100
115
|
end
|
101
116
|
end
|
102
117
|
end
|
103
|
-
|
104
|
-
|
118
|
+
|
119
|
+
return unless optimized
|
120
|
+
OptimizedPath.new(optimized, original)
|
105
121
|
end
|
106
122
|
|
107
|
-
# Optimize one file in place, return original as
|
123
|
+
# Optimize one file in place, return original as OptimizedPath or nil if
|
108
124
|
# optimization failed
|
109
125
|
def optimize_image!(original)
|
110
|
-
original =
|
126
|
+
original = Path.convert(original)
|
111
127
|
return unless (result = optimize_image(original))
|
112
128
|
result.replace(original)
|
113
|
-
|
129
|
+
OptimizedPath.new(original, result.original_size)
|
114
130
|
end
|
115
131
|
|
116
132
|
# Optimize image data, return new data or nil if optimization failed
|
117
133
|
def optimize_image_data(original_data)
|
118
|
-
|
119
|
-
return unless
|
120
|
-
|
134
|
+
format = ImageMeta.format_for_data(original_data)
|
135
|
+
return unless format
|
136
|
+
Path.temp_file %W[image_optim .#{format}] do |temp|
|
121
137
|
temp.binmode
|
122
138
|
temp.write(original_data)
|
123
139
|
temp.close
|
@@ -2,7 +2,9 @@ require 'image_optim/bin_resolver/error'
|
|
2
2
|
require 'image_optim/bin_resolver/simple_version'
|
3
3
|
require 'image_optim/bin_resolver/comparable_condition'
|
4
4
|
require 'image_optim/cmd'
|
5
|
+
require 'image_optim/path'
|
5
6
|
require 'shellwords'
|
7
|
+
require 'digest/sha1'
|
6
8
|
|
7
9
|
class ImageOptim
|
8
10
|
class BinResolver
|
@@ -18,6 +20,11 @@ class ImageOptim
|
|
18
20
|
@version = detect_version
|
19
21
|
end
|
20
22
|
|
23
|
+
def digest
|
24
|
+
return @digest if defined?(@digest)
|
25
|
+
@digest = File.exist?(@path) && Digest::SHA1.file(@path).hexdigest
|
26
|
+
end
|
27
|
+
|
21
28
|
def to_s
|
22
29
|
"#{name} #{version || '?'} at #{path}"
|
23
30
|
end
|
@@ -73,11 +80,11 @@ class ImageOptim
|
|
73
80
|
def version_string
|
74
81
|
case name
|
75
82
|
when :advpng, :gifsicle, :jpegoptim, :optipng
|
76
|
-
capture("#{escaped_path} --version 2>
|
83
|
+
capture("#{escaped_path} --version 2> #{Path::NULL}")[/\d+(\.\d+)+/]
|
77
84
|
when :svgo, :pngquant
|
78
85
|
capture("#{escaped_path} --version 2>&1")[/\d+(\.\d+)+/]
|
79
86
|
when :jhead, :'jpeg-recompress'
|
80
|
-
capture("#{escaped_path} -V 2>
|
87
|
+
capture("#{escaped_path} -V 2> #{Path::NULL}")[/\d+(\.\d+)+/]
|
81
88
|
when :jpegtran
|
82
89
|
capture("#{escaped_path} -v - 2>&1")[/version (\d+\S*)/, 1]
|
83
90
|
when :pngcrush
|
@@ -87,8 +94,8 @@ class ImageOptim
|
|
87
94
|
date_str = capture("#{escaped_path} 2>&1")[date_regexp]
|
88
95
|
Date.parse(date_str).strftime('%Y%m%d') if date_str
|
89
96
|
when :jpegrescan
|
90
|
-
# jpegrescan has no version so
|
91
|
-
path
|
97
|
+
# jpegrescan has no version so use first 8 characters of sha1 hex
|
98
|
+
Digest::SHA1.file(path).hexdigest[0, 8] if path
|
92
99
|
else
|
93
100
|
fail "getting `#{name}` version is not defined"
|
94
101
|
end
|