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 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,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "#{File.join(File.dirname(__FILE__), '..', 'lib/image_optim_tolerance/executor')}"
@@ -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
@@ -0,0 +1,3 @@
1
+ module ImageOptimTolerance
2
+ VERSION = File.read(File.join(File.dirname(__FILE__), "..", "..", "VERSION")).strip
3
+ 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: []