image_optim_tolerance 0.0.3
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 +7 -0
- data/CHANGELOG.md +0 -0
- data/LICENSE +16 -0
- data/README.md +33 -0
- data/VERSION +1 -0
- data/bin/image_optim_tolerance +3 -0
- data/lib/image_optim_tolerance/executor.rb +62 -0
- data/lib/image_optim_tolerance/image_optim_tolerance.rb +90 -0
- data/lib/image_optim_tolerance/version.rb +3 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cc3fcc0b514deaa80ade949a9ac3d9ba7425eefa
|
4
|
+
data.tar.gz: 20aa1f1e9cb06a616f489f56dcc465146a8056be
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7c7b0ae401482f733fd5cecc3abc023c37222106353e17702cfbd1e5423ffdfd0324138821fb6447ddfc819ef7a45c4d93ad43f724c4c18e8e13d2666c32c3d5
|
7
|
+
data.tar.gz: 468ec21bfd083103f71596e494ec44695c184a415213a67a8ad02c995fc63451632833c18093ad814059112c8328722034e47bc610f3a6e350c13c9511aadc44
|
data/CHANGELOG.md
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
ImageOptimTolerance
|
2
|
+
Copyright (c) 2014 LinkedIn Corp. All rights reserved.
|
3
|
+
Apache Software License 2.0
|
4
|
+
|
5
|
+
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
you may not use this file except in compliance with the License.
|
8
|
+
You may obtain a copy of the License at
|
9
|
+
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
See the License for the specific language governing permissions and
|
16
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# image\_optim\_tolerance
|
2
|
+
|
3
|
+
Tests that an image is compressed within a specified tolerance. [image_optim](https://github.com/toy/image_optim) does all the heavy lifting.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
### Install the gem
|
8
|
+
|
9
|
+
```sh
|
10
|
+
[sudo] gem install image\_optim\_tolerance
|
11
|
+
```
|
12
|
+
|
13
|
+
Instead of installing the gem directly via the command line, we recommend using [Bundler](http://gembundler.com/) to manage your gem dependencies.
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
```
|
18
|
+
Usage: image\_optim\_tolerance path [, path2 [, pathN]]
|
19
|
+
|
20
|
+
Examples:
|
21
|
+
image\_optim\_tolerance /path/to/image.png /path/to/other/image.jpg
|
22
|
+
image\_optim\_tolerance -t 5 /path/to/image.png /path/to/other/image.jpg
|
23
|
+
|
24
|
+
@options:
|
25
|
+
-t, --tolerance NUMBER the maximum allowed compression tolerance (in percentage)
|
26
|
+
-a, --[no-]aggressive if aggressive, also return the non-failing (acceptable) offenders if there are other offenders
|
27
|
+
-v, --[no-]verbose run verbosely
|
28
|
+
-h, --help shows this help message
|
29
|
+
```
|
30
|
+
|
31
|
+
## Configuration
|
32
|
+
|
33
|
+
See [image_optim](https://github.com/toy/image_optim) for configuration options. e.g. use a `.image_optim.yml` file.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.3
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
require "#{File.join(File.dirname(__FILE__), 'image_optim_tolerance')}"
|
4
|
+
|
5
|
+
# allow ImageOptim.app path to be discoverable if it exists
|
6
|
+
image_optim_app_path = '/Applications/ImageOptim.app/Contents/MacOS'
|
7
|
+
ENV['PATH'] = "#{image_optim_app_path}:#{ENV['PATH']}" if File.exist?(image_optim_app_path)
|
8
|
+
|
9
|
+
# defaults
|
10
|
+
options = {}
|
11
|
+
|
12
|
+
opts = OptionParser.new do |opts|
|
13
|
+
opts.banner = "Tests that an image is compressed within a specified tolerance\n\n"
|
14
|
+
opts.define_head "Usage: image_optim_tolerance path [, path2 [, pathN]]"
|
15
|
+
opts.separator ""
|
16
|
+
opts.separator "Examples:"
|
17
|
+
opts.separator " image_optim_tolerance /path/to/image.png /path/to/other/image.jpg"
|
18
|
+
opts.separator " image_optim_tolerance -t 5 /path/to/image.png /path/to/other/image.jpg"
|
19
|
+
opts.separator ""
|
20
|
+
opts.separator "@options:"
|
21
|
+
|
22
|
+
opts.on('-t', '--tolerance NUMBER', Float, 'the maximum allowed compression tolerance (in percentage)') do |v|
|
23
|
+
options[:tolerance] = v
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on("-a", "--[no-]aggressive", "if aggressive, also return the non-failing (acceptable) offenders if there are other offenders") do |v|
|
27
|
+
options[:aggressive] = v
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-v", "--[no-]verbose", "run verbosely") do |v|
|
31
|
+
options[:verbose] = v
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on('-h', '--help', 'shows this help message') do
|
35
|
+
puts opts
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
end
|
39
|
+
opts.parse!
|
40
|
+
|
41
|
+
if not ARGV.empty?
|
42
|
+
image_optim_tolerance = ImageOptimTolerance.new(options)
|
43
|
+
offenders = image_optim_tolerance.offenders(ARGV)
|
44
|
+
if offenders && offenders.count > 0
|
45
|
+
$stderr << <<-TEXT.gsub(/^\s*\|/, '')
|
46
|
+
|the following images are not optimized:
|
47
|
+
|
|
48
|
+
| #{offenders.join("\n ")}
|
49
|
+
|
|
50
|
+
|FAILED
|
51
|
+
TEXT
|
52
|
+
exit 1
|
53
|
+
else
|
54
|
+
puts "PASSED"
|
55
|
+
exit 0
|
56
|
+
end
|
57
|
+
else
|
58
|
+
puts opts
|
59
|
+
exit 1
|
60
|
+
end
|
61
|
+
|
62
|
+
exit
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'image_optim'
|
3
|
+
|
4
|
+
class ImageOptimTolerance
|
5
|
+
|
6
|
+
attr_accessor :options
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
self.options = DEFAULTS.merge(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def is_valid_image(path)
|
13
|
+
return false if path.nil? or path.empty?
|
14
|
+
valid_pattern = /.*\.(gif|png|jpeg|jpg|svg)$/
|
15
|
+
return ((valid_pattern =~ path.to_s.strip) && File.exist?(path))
|
16
|
+
end
|
17
|
+
|
18
|
+
def log(msg, type = nil)
|
19
|
+
if self.options[:verbose]
|
20
|
+
puts (type && MARKS[type]) ? " #{MARKS[type]} #{msg}" : msg
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def offenders(paths)
|
25
|
+
offenders = {
|
26
|
+
:terrible => [],
|
27
|
+
:acceptable => []
|
28
|
+
}
|
29
|
+
paths = [paths] if paths.is_a?(String)
|
30
|
+
paths.each do |path|
|
31
|
+
if self.is_valid_image(path)
|
32
|
+
self.log "checking optimization of #{path}..."
|
33
|
+
optimized = image_optim.optimize_image(path)
|
34
|
+
if optimized
|
35
|
+
size = {}
|
36
|
+
size[:original] = File.size(path)
|
37
|
+
size[:optimized] = File.size?(optimized) || size[:original]
|
38
|
+
size[:saved] = size[:original] - size[:optimized]
|
39
|
+
size[:percentage] = size[:saved].to_f / size[:original].to_f * 100
|
40
|
+
|
41
|
+
if size[:saved] > 0
|
42
|
+
self.log "could have saved #{size[:saved]} bytes (#{size[:percentage].ceil}%)!", :sad
|
43
|
+
if size[:percentage] > self.options[:tolerance]
|
44
|
+
self.log "exceeds tolerance threshold by #{(size[:percentage] - self.options[:tolerance]).ceil}%", :bad
|
45
|
+
offenders[:terrible] << path
|
46
|
+
else
|
47
|
+
offenders[:acceptable] << path
|
48
|
+
self.log "within acceptable tolerance", :good
|
49
|
+
end
|
50
|
+
next
|
51
|
+
end
|
52
|
+
else
|
53
|
+
self.log "nothing to see here", :happy
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# if there are terrible offenders that are above the threshold
|
59
|
+
if offenders[:terrible].count > 0
|
60
|
+
# return both the terrible and acceptable, if we're being aggressive
|
61
|
+
return offenders[:terrible] + offenders[:acceptable] if self.options[:aggressive]
|
62
|
+
return offenders[:terrible]
|
63
|
+
end
|
64
|
+
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def verify(paths)
|
69
|
+
return self.offenders(paths).nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
MARKS = {
|
74
|
+
# Ruby < 1.9 has bad unicode support, so we're doing it this way
|
75
|
+
:good => ['2714'.to_i(16)].pack('U*'),
|
76
|
+
:bad => ['2717'.to_i(16)].pack('U*'),
|
77
|
+
:happy => ['263A'.to_i(16)].pack('U*'),
|
78
|
+
:sad => ['2639'.to_i(16)].pack('U*')
|
79
|
+
}
|
80
|
+
|
81
|
+
DEFAULTS = {
|
82
|
+
:tolerance => 0,
|
83
|
+
:aggressive => true,
|
84
|
+
:verbose => false
|
85
|
+
}
|
86
|
+
|
87
|
+
def image_optim
|
88
|
+
@image_optim ||= ImageOptim.new()
|
89
|
+
end
|
90
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: image_optim_tolerance
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eugene ONeill
|
8
|
+
- LinkedIn
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-04-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: image_optim
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.12'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.12'
|
28
|
+
description: verifies that images are within an acceptable compression tolerance
|
29
|
+
email: oneill.eugene@gmail.com
|
30
|
+
executables:
|
31
|
+
- image_optim_tolerance
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- CHANGELOG.md
|
36
|
+
- LICENSE
|
37
|
+
- README.md
|
38
|
+
- VERSION
|
39
|
+
- bin/image_optim_tolerance
|
40
|
+
- lib/image_optim_tolerance/executor.rb
|
41
|
+
- lib/image_optim_tolerance/image_optim_tolerance.rb
|
42
|
+
- lib/image_optim_tolerance/version.rb
|
43
|
+
homepage:
|
44
|
+
licenses:
|
45
|
+
- Apache License (2.0)
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.2.2
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: verifies that images are within an acceptable compression tolerance
|
67
|
+
test_files: []
|