image_optim 0.31.3 → 0.32.0

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.
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'image_optim/worker/svgo'
5
+
6
+ describe ImageOptim::Worker::Svgo do
7
+ %i[
8
+ disable_plugins
9
+ enable_plugins
10
+ ].each do |option|
11
+ describe "#{option} option" do
12
+ let(:subject){ described_class.new(ImageOptim.new, value).send(option) }
13
+
14
+ context 'default' do
15
+ let(:value){ {} }
16
+
17
+ it{ is_expected.to eq([]) }
18
+ end
19
+
20
+ context 'when passed single valid value' do
21
+ let(:value){ {option => :pluginName} }
22
+
23
+ it 'converts it to a string array' do
24
+ is_expected.to eq(%w[pluginName])
25
+ end
26
+ end
27
+
28
+ context 'when passed multiple valid values' do
29
+ let(:value){ {option => %i[pluginName anotherName]} }
30
+
31
+ it 'converts them to a string array' do
32
+ is_expected.to eq(%w[pluginName anotherName])
33
+ end
34
+ end
35
+
36
+ context 'when given invalid values' do
37
+ let(:value){ {option => %w[1abc pluginName alert() anotherName]} }
38
+
39
+ it 'warns and skips them' do
40
+ expect_any_instance_of(described_class).
41
+ to receive(:warn).with('Doesn\'t look like svgo plugin name: 1abc')
42
+ expect_any_instance_of(described_class).
43
+ to receive(:warn).with('Doesn\'t look like svgo plugin name: alert()')
44
+ is_expected.to eq(%w[pluginName anotherName])
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ describe 'precision option' do
51
+ describe 'default' do
52
+ subject{ described_class::PRECISION_OPTION.default }
53
+
54
+ it{ is_expected.to eq(3) }
55
+ end
56
+
57
+ describe 'value' do
58
+ let(:subject){ described_class.new(ImageOptim.new, options).precision }
59
+
60
+ context 'when lossy not allowed' do
61
+ context 'by default' do
62
+ let(:options){ {} }
63
+
64
+ it{ is_expected.to eq(3) }
65
+ end
66
+
67
+ context 'when value is passed through options' do
68
+ let(:options){ {precision: 5} }
69
+
70
+ it 'warns and keeps default' do
71
+ expect_any_instance_of(described_class).
72
+ to receive(:warn).with(%r{ignored in default/lossless mode})
73
+ is_expected.to eq(3)
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'when lossy allowed' do
79
+ context 'by default' do
80
+ let(:options){ {allow_lossy: true} }
81
+
82
+ it{ is_expected.to eq(3) }
83
+ end
84
+
85
+ context 'when value is passed through options' do
86
+ let(:options){ {allow_lossy: true, precision: 5} }
87
+
88
+ it 'sets the value without warning' do
89
+ expect_any_instance_of(described_class).not_to receive(:warn)
90
+ is_expected.to eq(5)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -61,9 +61,10 @@ describe ImageOptim do
61
61
 
62
62
  base_options = {skip_missing_workers: false}
63
63
  [
64
- ['lossless', base_options, 0],
65
- ['lossy', base_options.merge(allow_lossy: true), 0.001],
66
- ].each do |type, options, max_difference|
64
+ # 120 comes from https://github.com/ImageMagick/ImageMagick/commit/8a7495a6d9
65
+ ['lossless', base_options, 120],
66
+ ['lossy', base_options.merge(allow_lossy: true), 30],
67
+ ].each do |type, options, psnr_min|
67
68
  it "does it #{type}" do
68
69
  image_optim = ImageOptim.new(options)
69
70
  copies = test_images.map{ |image| temp_copy(image) }
@@ -78,7 +79,7 @@ describe ImageOptim do
78
79
  expect(optimized).not_to have_same_data_as(original)
79
80
 
80
81
  compare_to = rotate_images.include?(original) ? rotated : original
81
- expect(optimized).to be_similar_to(compare_to, max_difference)
82
+ expect(optimized).to be_similar_to(compare_to, psnr_min)
82
83
  end
83
84
  end
84
85
  end
@@ -268,6 +269,20 @@ describe ImageOptim do
268
269
  end
269
270
  end
270
271
 
272
+ describe 'benchmark_images' do
273
+ it 'does it' do
274
+ image_optim = ImageOptim.new
275
+ pairs = image_optim.benchmark_images(test_images)
276
+ test_images.zip(pairs).each do |original, (src, bm)|
277
+ expect(original).to equal(src)
278
+ expect(bm[0]).to be_a(ImageOptim::BenchmarkResult)
279
+ expect(bm[0].bytes).to be_a(Numeric)
280
+ expect(bm[0].elapsed).to be_a(Numeric)
281
+ expect(bm[0].worker).to be_a(String)
282
+ end
283
+ end
284
+ end
285
+
271
286
  %w[
272
287
  optimize_image
273
288
  optimize_image!
@@ -7,6 +7,8 @@ require 'shellwords'
7
7
 
8
8
  side = 64
9
9
 
10
+ colors = Array.new(256){ [rand(256), rand(256), rand(256)] }
11
+
10
12
  IO.popen(%W[
11
13
  convert
12
14
  -depth 8
@@ -18,7 +20,7 @@ IO.popen(%W[
18
20
  side.times do |a|
19
21
  side.times do |b|
20
22
  alpha = [0, 1, 0x7f, 0xff][((a / 8) + (b / 8)) % 4]
21
- f << [rand(256), rand(256), rand(256), alpha].pack('C*')
23
+ f << [*colors.sample, alpha].pack('C*')
22
24
  end
23
25
  end
24
26
  end
Binary file
data/spec/spec_helper.rb CHANGED
@@ -42,12 +42,12 @@ def flatten_animation(image)
42
42
  end
43
43
  end
44
44
 
45
- def mepp(image_a, image_b)
45
+ def psnr(image_a, image_b)
46
46
  coalesce_a = flatten_animation(image_a)
47
47
  coalesce_b = flatten_animation(image_b)
48
48
  output = ImageOptim::Cmd.capture((IMAGEMAGICK_PREFIX + %W[
49
49
  compare
50
- -metric MEPP
50
+ -metric PSNR
51
51
  -alpha Background
52
52
  #{coalesce_a.to_s.shellescape}
53
53
  #{coalesce_b.to_s.shellescape}
@@ -59,21 +59,21 @@ def mepp(image_a, image_b)
59
59
  end
60
60
 
61
61
  num_r = '\d+(?:\.\d+(?:[eE][-+]?\d+)?)?'
62
- output[/\((#{num_r}), #{num_r}\)/, 1].to_f
62
+ num = output[/\A(#{num_r})/, 1].to_f
63
+ num == 0 ? Float::INFINITY : num
63
64
  end
64
65
 
65
66
  RSpec::Matchers.define :be_smaller_than do |expected|
66
67
  match{ |actual| actual.size < expected.size }
67
68
  end
68
69
 
69
- RSpec::Matchers.define :be_similar_to do |expected, max_difference|
70
+ RSpec::Matchers.define :be_similar_to do |expected, psnr_min|
70
71
  match do |actual|
71
- @diff = mepp(actual, expected)
72
- @diff <= max_difference
72
+ @diff = psnr(actual, expected)
73
+ @diff >= psnr_min
73
74
  end
74
75
  failure_message do |actual|
75
- "expected #{actual} to have at most #{max_difference} difference from " \
76
- "#{expected}, got mean error per pixel of #{@diff}"
76
+ "expected peaks signal to noise ratio between #{actual} and #{expected} to be #{psnr_min}, got #{@diff}"
77
77
  end
78
78
  end
79
79
 
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: image_optim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.31.3
4
+ version: 0.32.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Kuchin
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-02-17 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: fspath
@@ -166,27 +165,28 @@ dependencies:
166
165
  - - "~>"
167
166
  - !ruby/object:Gem::Version
168
167
  version: '2.0'
169
- description:
170
- email:
171
168
  executables:
172
169
  - image_optim
173
170
  extensions: []
174
171
  extra_rdoc_files: []
175
172
  files:
173
+ - ".github/dependabot.yml"
174
+ - ".github/workflows/build-test-containers.yml"
176
175
  - ".github/workflows/check.yml"
177
- - ".github/workflows/codeql.yml"
178
176
  - ".github/workflows/rubocop.yml"
179
177
  - ".gitignore"
180
178
  - ".pre-commit-hooks.yaml"
181
179
  - ".rubocop.yml"
182
180
  - CHANGELOG.markdown
183
181
  - CONTRIBUTING.markdown
182
+ - Dockerfile.test
184
183
  - Gemfile
185
184
  - LICENSE.txt
186
185
  - README.markdown
187
186
  - bin/image_optim
188
187
  - image_optim.gemspec
189
188
  - lib/image_optim.rb
189
+ - lib/image_optim/benchmark_result.rb
190
190
  - lib/image_optim/bin_resolver.rb
191
191
  - lib/image_optim/bin_resolver/bin.rb
192
192
  - lib/image_optim/bin_resolver/comparable_condition.rb
@@ -211,6 +211,7 @@ files:
211
211
  - lib/image_optim/runner/glob_helpers.rb
212
212
  - lib/image_optim/runner/option_parser.rb
213
213
  - lib/image_optim/space.rb
214
+ - lib/image_optim/table.rb
214
215
  - lib/image_optim/timer.rb
215
216
  - lib/image_optim/true_false_nil.rb
216
217
  - lib/image_optim/worker.rb
@@ -230,6 +231,7 @@ files:
230
231
  - script/template/jquery-2.1.3.min.js
231
232
  - script/template/sortable-0.6.0.min.js
232
233
  - script/template/worker_analysis.erb
234
+ - script/update-rubygems-n-bundler
233
235
  - script/update_worker_options_in_readme
234
236
  - script/worker_analysis
235
237
  - spec/files/config_with_range.yaml
@@ -252,10 +254,12 @@ files:
252
254
  - spec/image_optim/runner/option_parser_spec.rb
253
255
  - spec/image_optim/space_spec.rb
254
256
  - spec/image_optim/timer_spec.rb
257
+ - spec/image_optim/true_false_nil_spec.rb
255
258
  - spec/image_optim/worker/jpegrecompress_spec.rb
256
259
  - spec/image_optim/worker/optipng_spec.rb
257
260
  - spec/image_optim/worker/oxipng_spec.rb
258
261
  - spec/image_optim/worker/pngquant_spec.rb
262
+ - spec/image_optim/worker/svgo_spec.rb
259
263
  - spec/image_optim/worker_spec.rb
260
264
  - spec/image_optim_spec.rb
261
265
  - spec/images/broken_jpeg
@@ -293,7 +297,7 @@ licenses:
293
297
  metadata:
294
298
  bug_tracker_uri: https://github.com/toy/image_optim/issues
295
299
  changelog_uri: https://github.com/toy/image_optim/blob/master/CHANGELOG.markdown
296
- documentation_uri: https://www.rubydoc.info/gems/image_optim/0.31.3
300
+ documentation_uri: https://www.rubydoc.info/gems/image_optim/0.32.0
297
301
  source_code_uri: https://github.com/toy/image_optim
298
302
  post_install_message: |
299
303
  Rails image assets optimization is extracted into image_optim_rails gem
@@ -312,8 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
312
316
  - !ruby/object:Gem::Version
313
317
  version: '0'
314
318
  requirements: []
315
- rubygems_version: 3.3.26
316
- signing_key:
319
+ rubygems_version: 4.0.3
317
320
  specification_version: 4
318
321
  summary: Command line tool and ruby interface to optimize (lossless compress, optionally
319
322
  lossy) jpeg, png, gif and svg images using external utilities (advpng, gifsicle,
@@ -340,10 +343,12 @@ test_files:
340
343
  - spec/image_optim/runner/option_parser_spec.rb
341
344
  - spec/image_optim/space_spec.rb
342
345
  - spec/image_optim/timer_spec.rb
346
+ - spec/image_optim/true_false_nil_spec.rb
343
347
  - spec/image_optim/worker/jpegrecompress_spec.rb
344
348
  - spec/image_optim/worker/optipng_spec.rb
345
349
  - spec/image_optim/worker/oxipng_spec.rb
346
350
  - spec/image_optim/worker/pngquant_spec.rb
351
+ - spec/image_optim/worker/svgo_spec.rb
347
352
  - spec/image_optim/worker_spec.rb
348
353
  - spec/image_optim_spec.rb
349
354
  - spec/images/broken_jpeg
@@ -1,30 +0,0 @@
1
- name: codeql
2
- on:
3
- push:
4
- pull_request:
5
- schedule:
6
- - cron: '43 20 * * 0'
7
-
8
- jobs:
9
- analyze:
10
- runs-on: ubuntu-latest
11
- permissions:
12
- actions: read
13
- contents: read
14
- security-events: write
15
-
16
- strategy:
17
- fail-fast: false
18
- matrix:
19
- language: [ 'ruby' ]
20
-
21
- steps:
22
- - uses: actions/checkout@v3
23
-
24
- - uses: github/codeql-action/init@v1
25
- with:
26
- languages: ${{ matrix.language }}
27
-
28
- - uses: github/codeql-action/autobuild@v1
29
-
30
- - uses: github/codeql-action/analyze@v1