jpegoptim 0.1.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,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "depq", ">= 0.4"
5
+ # gem "hash-utils", ">= 0.9.0"
6
+ gem "pipe-run", ">= 0.1.0"
7
+ gem "command-builder", ">= 0.1.0"
8
+ gem "unix-whereis", ">= 0.1.0"
9
+
10
+ # Add dependencies to develop your gem here.
11
+ # Include everything needed to run rake, tests, features, etc.
12
+ group :development do
13
+ gem "bundler", "~> 1.0.0"
14
+ gem "jeweler", "~> 1.5.2"
15
+ end
@@ -0,0 +1,27 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ command-builder (0.1.0)
5
+ hash-utils (>= 0.7.0)
6
+ git (1.2.5)
7
+ hash-utils (0.9.0)
8
+ jeweler (1.5.2)
9
+ bundler (~> 1.0.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ pipe-run (0.1.0)
13
+ rake (0.8.7)
14
+ unix-whereis (0.1.0)
15
+ command-builder (>= 0.1.0)
16
+ hash-utils (>= 0.9.0)
17
+ pipe-run (>= 0.1.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ bundler (~> 1.0.0)
24
+ command-builder (>= 0.1.0)
25
+ jeweler (~> 1.5.2)
26
+ pipe-run (>= 0.1.0)
27
+ unix-whereis (>= 0.1.0)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ Jpegoptim
2
+ =========
3
+
4
+ **Jpegoptim** provides Ruby interface to the `jpegoptim` tool.
5
+ Some examples follow: (for details, see module documentation)
6
+
7
+ require "jpegoptim"
8
+
9
+ Jpegoptim.available? # will return true (or false)
10
+
11
+ Jpegoptim.optimize(["foo.jpg", "empty.jpg", "nonexist.jpg"], { :preserve => true, :strip => :all })
12
+
13
+ # will run 'jpegoptim --strip-all --preserve foo.jpg bar.jpgug empty.jpg'
14
+ # and then will return for example:
15
+ # '#<struct Jpegoptim::Result succeed={"foo.jpg => -22.1}}, errors=[["empty.jpg", "ERROR"]]>
16
+
17
+ ### Call Result
18
+
19
+ Result contains members `:success` and `:errors`. Sucess member contains
20
+ hash of successfully optimized files with ratio as value. Zero or
21
+ positive percent ratio means the same as file has been `skipped`. It's
22
+ negative number against the number reported by `jpegoptim` so it means
23
+ new size against the old size.
24
+
25
+ Errors contains array with pairs where first member of the pair is
26
+ filename and second the message. First one can be null if message isn't
27
+ strictly associated with file. As unassociated messages are considered
28
+ all errors beginning by the `jpegoptim:` string although these are
29
+ usually written to the error output so generaly unhandled and written
30
+ out to error output of the application instead.
31
+
32
+ Be warn, unassociated message is `can't open` error too, so double
33
+ check, file exists if desired result is critical.
34
+
35
+ ### Unsupported Options
36
+
37
+ Destination directory option isn't supported, so you are purely
38
+ responsible for optimizing files on the right place. Use Ruby methods
39
+ for it.
40
+
41
+
42
+
43
+
44
+ Contributing
45
+ ------------
46
+
47
+ 1. Fork it.
48
+ 2. Create a branch (`git checkout -b 20101220-my-change`).
49
+ 3. Commit your changes (`git commit -am "Added something"`).
50
+ 4. Push to the branch (`git push origin 20101220-my-change`).
51
+ 5. Create an [Issue][2] with a link to your branch.
52
+ 6. Enjoy a refreshing Diet Coke and wait.
53
+
54
+ Copyright
55
+ ---------
56
+
57
+ Copyright &copy; 2011 [Martin Kozák][3]. See `LICENSE.txt` for
58
+ further details.
59
+
60
+ [2]: http://github.com/martinkozak/qrpc/issues
61
+ [3]: http://www.martinkozak.net/
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+ require 'rake'
12
+
13
+ require 'jeweler'
14
+ Jeweler::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
16
+ gem.name = "jpegoptim"
17
+ gem.homepage = "https://github.com/martinkozak/jpegoptim"
18
+ gem.license = "MIT"
19
+ gem.summary = "Ruby interface to 'jpegoptim' tool."
20
+ gem.email = "martinkozak@martinkozak.net"
21
+ gem.authors = ["Martin Kozák"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/rdoctask'
30
+ Rake::RDocTask.new do |rdoc|
31
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
32
+
33
+ rdoc.rdoc_dir = 'rdoc'
34
+ rdoc.title = "qrpc #{version}"
35
+ rdoc.rdoc_files.include('README*')
36
+ rdoc.rdoc_files.include('lib/**/*.rb')
37
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,60 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{jpegoptim}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Martin Kozák"]
12
+ s.date = %q{2011-02-21}
13
+ s.email = %q{martinkozak@martinkozak.net}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE.txt",
16
+ "README.md"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE.txt",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "jpegoptim.gemspec",
27
+ "lib/jpegoptim.rb",
28
+ "test"
29
+ ]
30
+ s.homepage = %q{https://github.com/martinkozak/jpegoptim}
31
+ s.licenses = ["MIT"]
32
+ s.require_paths = ["lib"]
33
+ s.rubygems_version = %q{1.5.2}
34
+ s.summary = %q{Ruby interface to 'jpegoptim' tool.}
35
+
36
+ if s.respond_to? :specification_version then
37
+ s.specification_version = 3
38
+
39
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
40
+ s.add_runtime_dependency(%q<pipe-run>, [">= 0.1.0"])
41
+ s.add_runtime_dependency(%q<command-builder>, [">= 0.1.0"])
42
+ s.add_runtime_dependency(%q<unix-whereis>, [">= 0.1.0"])
43
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
44
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
45
+ else
46
+ s.add_dependency(%q<pipe-run>, [">= 0.1.0"])
47
+ s.add_dependency(%q<command-builder>, [">= 0.1.0"])
48
+ s.add_dependency(%q<unix-whereis>, [">= 0.1.0"])
49
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
50
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
51
+ end
52
+ else
53
+ s.add_dependency(%q<pipe-run>, [">= 0.1.0"])
54
+ s.add_dependency(%q<command-builder>, [">= 0.1.0"])
55
+ s.add_dependency(%q<unix-whereis>, [">= 0.1.0"])
56
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
57
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
58
+ end
59
+ end
60
+
@@ -0,0 +1,146 @@
1
+ # encoding: utf-8
2
+ # (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
3
+
4
+ require "command-builder"
5
+ require "pipe-run"
6
+ require "unix/whereis"
7
+
8
+ ##
9
+ # The +jpegoptim+ tool command frontend.
10
+ # @see
11
+ #
12
+
13
+ module Jpegoptim
14
+
15
+ ##
16
+ # Holds +jpegoptim+ command.
17
+ #
18
+
19
+ COMMAND = :jpegoptim
20
+
21
+ ##
22
+ # Result structure.
23
+ #
24
+ # Contains members +:success+ and +:errors+. Sucess member contains
25
+ # hash of successfully optimized files with ratio as value. Zero
26
+ # or positive percent ratio means the same as file has been
27
+ # +skipped+. It's negative number against the number reported by
28
+ # +jpegoptim+ so it means new size against the old size.
29
+ #
30
+ # Errors contains array with pairs where first member of the pair is
31
+ # filename and second the message. First one can be null if message
32
+ # isn't strictly associated with file. As unassociated messages are
33
+ # considered all errors beginning by the +jpegoptim:+ string althoug
34
+ # these are usually written to the error output so generaly
35
+ # unhandled and written out to error output of the application
36
+ # instead.
37
+ #
38
+ # Be warn, unassociated message is +can't open+ error too, so double
39
+ # check, file exists if desired result is critical.
40
+ #
41
+
42
+ Result = Struct::new(:succeed, :errors)
43
+
44
+ ##
45
+ # Holds output matchers.
46
+ #
47
+
48
+ MATCHERS = [
49
+ /(.*)\[(ERROR)\]/,
50
+ /jpegoptim:\s*(.*)/,
51
+ /(.*)\s+\d+x\d+.*\((\-?\d+\.\d+)%\)/
52
+ ]
53
+
54
+ ##
55
+ # Checks if +jpegoptim+ is available.
56
+ # @return [Boolean] +true+ if it is, +false+ in otherwise
57
+ #
58
+
59
+ def self.available?
60
+ return Whereis.available? self::COMMAND
61
+ end
62
+
63
+ ##
64
+ # Performs optimizations above file or set of files.
65
+ #
66
+ # Destination directory option isn't supported, so you are purely
67
+ # responsible for optimizing files on the right place. Use Ruby
68
+ # methods for it.
69
+ #
70
+ # @param [String, Array] paths file path or array of paths for optimizing
71
+ # @param [Hash] options options
72
+ # @option options [Boolean, Symbol] :strip says what informations strip, see +jpegoptim+ documentation, default is +:all+
73
+ # @option options [Boolean] :preserve turns on preserving the timestamps
74
+ # @option options [Integer] :max set maximum image quality factor
75
+ # @option options [Boolean] :debug turn on debugging mode, so command will be put out to the +STDERR+
76
+ # @return [Struct] see {Result}
77
+ #
78
+
79
+ def self.optimize(paths, options = { })
80
+
81
+ # Command
82
+ cmd = CommandBuilder::new(self::COMMAND)
83
+
84
+ # Strip definition
85
+ strip = options[:strip]
86
+ if strip.nil? or (strip == true)
87
+ strip == :all
88
+ end
89
+ if strip
90
+ cmd << ("strip-" << strip.to_s).to_sym
91
+ end
92
+
93
+ # Preserve
94
+ if options[:preserve]
95
+ cmd << :preserve
96
+ end
97
+
98
+ # Max
99
+ if options[:max].kind_of? Integer
100
+ cmd.arg(:max, options[:max].to_i)
101
+ end
102
+
103
+ # Files
104
+ if paths.kind_of? String
105
+ paths = [paths]
106
+ end
107
+
108
+ # Runs the command
109
+ cmd << paths
110
+
111
+ if options[:debug] == true
112
+ STDERR.write cmd.to_s + "\n"
113
+ end
114
+
115
+ output = Pipe.run(cmd.to_s)
116
+
117
+ # Parses output
118
+ succeed, errors = __parse_output(output)
119
+ return self::Result::new(succeed, errors)
120
+
121
+ end
122
+
123
+
124
+ private
125
+
126
+ ##
127
+ # Parses output.
128
+ #
129
+
130
+ def self.__parse_output(output)
131
+ errors = [ ]
132
+ succeed = { }
133
+
134
+ output.each_line do |line|
135
+ if m = line.match(self::MATCHERS[0])
136
+ errors << [m[1].strip, m[2]]
137
+ elsif m = line.match(self::MATCHERS[1])
138
+ errors << [nil, m[1]]
139
+ elsif m = line.match(self::MATCHERS[2])
140
+ succeed[m[1]] = m[2].to_f * -1
141
+ end
142
+ end
143
+
144
+ return [succeed, errors]
145
+ end
146
+ end
data/test ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ $:.push("./lib")
5
+ require "jpegoptim"
6
+
7
+ puts Jpegoptim.available?.inspect
8
+ puts Jpegoptim.optimize(["foo.jpg", "bar.jpg", "empty.jpg"], { :preserve => true, :strip => :all, :debug => true })
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jpegoptim
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - "Martin Koz\xC3\xA1k"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-02-21 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: pipe-run
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.0
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: command-builder
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.1.0
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: unix-whereis
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.0
46
+ type: :runtime
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: bundler
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 1.0.0
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: jeweler
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 1.5.2
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: *id005
71
+ description:
72
+ email: martinkozak@martinkozak.net
73
+ executables: []
74
+
75
+ extensions: []
76
+
77
+ extra_rdoc_files:
78
+ - LICENSE.txt
79
+ - README.md
80
+ files:
81
+ - .document
82
+ - Gemfile
83
+ - Gemfile.lock
84
+ - LICENSE.txt
85
+ - README.md
86
+ - Rakefile
87
+ - VERSION
88
+ - jpegoptim.gemspec
89
+ - lib/jpegoptim.rb
90
+ - test
91
+ has_rdoc: true
92
+ homepage: https://github.com/martinkozak/jpegoptim
93
+ licenses:
94
+ - MIT
95
+ post_install_message:
96
+ rdoc_options: []
97
+
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ hash: -392424592510368295
106
+ segments:
107
+ - 0
108
+ version: "0"
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: "0"
115
+ requirements: []
116
+
117
+ rubyforge_project:
118
+ rubygems_version: 1.5.2
119
+ signing_key:
120
+ specification_version: 3
121
+ summary: Ruby interface to 'jpegoptim' tool.
122
+ test_files: []
123
+