image_optim 0.3.2 → 0.4.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.
- data/README.markdown +34 -0
- data/TODO +0 -2
- data/bin/image_optim +4 -0
- data/image_optim.gemspec +1 -1
- data/lib/image_optim.rb +29 -12
- data/lib/image_optim/util.rb +0 -9
- data/lib/image_optim/worker.rb +21 -8
- data/spec/image_optim_spec.rb +6 -6
- metadata +5 -5
data/README.markdown
CHANGED
@@ -4,6 +4,40 @@ Optimize images (jpeg, png, gif) using external utilities (advpng, gifsicle, jpe
|
|
4
4
|
|
5
5
|
Based on [ImageOptim.app](http://imageoptim.pornel.net/).
|
6
6
|
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
In terminal:
|
10
|
+
|
11
|
+
image_optim *.{jpg,png,gif}
|
12
|
+
|
13
|
+
image_optim -h
|
14
|
+
|
15
|
+
Initilize optimizer (options are described in comments for ImageOptim, Worker and all workers):
|
16
|
+
|
17
|
+
io = ImageOptim.new
|
18
|
+
|
19
|
+
io = ImageOptim.new(:pngout => false)
|
20
|
+
|
21
|
+
io = ImageOptim.new(:nice => 20)
|
22
|
+
|
23
|
+
Optimize image getting temp path:
|
24
|
+
|
25
|
+
io.optimize_image('a.png')
|
26
|
+
|
27
|
+
Optimize image in place:
|
28
|
+
|
29
|
+
io.optimize_image('b.jpg')
|
30
|
+
|
31
|
+
Multiple images:
|
32
|
+
|
33
|
+
io.optimize_images(Dir['*.png']) do |unoptimized, optimized|
|
34
|
+
if optimized
|
35
|
+
puts "#{unoptimized} => #{optimized}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
io.optimize_images!(Dir['*.*'])
|
40
|
+
|
7
41
|
## Copyright
|
8
42
|
|
9
43
|
Copyright (c) 2012 Ivan Kuchin. See LICENSE.txt for details.
|
data/TODO
CHANGED
data/bin/image_optim
CHANGED
@@ -20,6 +20,10 @@ Usege:
|
|
20
20
|
options[:threads] = threads
|
21
21
|
end
|
22
22
|
|
23
|
+
op.on('--[no-]nice NUMBER', Integer, 'Nice levle (defaults to 10)') do |nice|
|
24
|
+
options[:nice] = nice
|
25
|
+
end
|
26
|
+
|
23
27
|
ImageOptim::Worker.klasses.each do |klass|
|
24
28
|
bin = klass.underscored_name.to_sym
|
25
29
|
op.on("--[no-]#{bin} PATH", "#{bin} path or disable") do |path|
|
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.4.0'
|
6
6
|
s.summary = %q{Optimize images (jpeg, png, gif) using external utilities (advpng, gifsicle, jpegoptim, jpegtran, optipng, pngcrush, pngout)}
|
7
7
|
s.homepage = "http://github.com/toy/#{s.name}"
|
8
8
|
s.authors = ['Ivan Kuchin']
|
data/lib/image_optim.rb
CHANGED
@@ -27,7 +27,35 @@ class ImageOptim
|
|
27
27
|
# or hash with options to worker and :bin specifying binary
|
28
28
|
#
|
29
29
|
# ImageOptim.new(:advpng => {:level => 3}, :optipng => {:level => 2}, :jpegoptim => {:bin => 'jpegoptim345'})
|
30
|
+
#
|
31
|
+
# use :threads to set number of parallel optimizers to run (passing true or nil determines number of processors, false disables parallel processing)
|
32
|
+
#
|
33
|
+
# ImageOptim.new(:threads => 8)
|
34
|
+
#
|
35
|
+
# use :nice to specify optimizers nice level (true or nil makes it 10, false makes it 0)
|
36
|
+
#
|
37
|
+
# ImageOptim.new(:threads => 8)
|
30
38
|
def initialize(options = {})
|
39
|
+
nice = case nice = options.delete(:nice)
|
40
|
+
when true, nil
|
41
|
+
10
|
42
|
+
when false
|
43
|
+
0
|
44
|
+
else
|
45
|
+
nice.to_i
|
46
|
+
end
|
47
|
+
|
48
|
+
threads = options.delete(:threads)
|
49
|
+
threads = case threads
|
50
|
+
when true, nil
|
51
|
+
Util.processor_count
|
52
|
+
when false
|
53
|
+
1
|
54
|
+
else
|
55
|
+
threads.to_i
|
56
|
+
end
|
57
|
+
@threads = limit_with_range(threads, 1..16)
|
58
|
+
|
31
59
|
@workers_by_format = {}
|
32
60
|
Worker.klasses.each do |klass|
|
33
61
|
case worker_options = options.delete(klass.underscored_name.to_sym)
|
@@ -41,7 +69,7 @@ class ImageOptim
|
|
41
69
|
else
|
42
70
|
raise "Got #{worker_options.inspect} for #{klass.name} options"
|
43
71
|
end
|
44
|
-
worker = klass.new(worker_options)
|
72
|
+
worker = klass.new({:nice => nice}.merge(worker_options))
|
45
73
|
klass.image_formats.each do |format|
|
46
74
|
@workers_by_format[format] ||= []
|
47
75
|
@workers_by_format[format] << worker
|
@@ -51,17 +79,6 @@ class ImageOptim
|
|
51
79
|
workers.replace workers.sort_by(&:run_priority)
|
52
80
|
end
|
53
81
|
|
54
|
-
threads = options.delete(:threads)
|
55
|
-
threads = case threads
|
56
|
-
when true, nil
|
57
|
-
Util.processor_count
|
58
|
-
when false
|
59
|
-
1
|
60
|
-
else
|
61
|
-
threads.to_i
|
62
|
-
end
|
63
|
-
@threads = limit_with_range(threads, 1..16)
|
64
|
-
|
65
82
|
assert_options_empty!(options)
|
66
83
|
end
|
67
84
|
|
data/lib/image_optim/util.rb
CHANGED
@@ -2,15 +2,6 @@ require 'shellwords'
|
|
2
2
|
|
3
3
|
class ImageOptim
|
4
4
|
module Util
|
5
|
-
# Run command redirecting both stdout and stderr to /dev/null, raising signal if command was signaled and return successfulness
|
6
|
-
def self.run(*args)
|
7
|
-
res = system "#{args.map(&:to_s).shelljoin} &> /dev/null"
|
8
|
-
if $?.signaled?
|
9
|
-
raise SignalException.new($?.termsig)
|
10
|
-
end
|
11
|
-
res
|
12
|
-
end
|
13
|
-
|
14
5
|
# http://stackoverflow.com/questions/891537/ruby-detect-number-of-cpus-installed
|
15
6
|
def self.processor_count
|
16
7
|
@processor_count ||= case host_os = RbConfig::CONFIG['host_os']
|
data/lib/image_optim/worker.rb
CHANGED
@@ -31,9 +31,13 @@ class ImageOptim
|
|
31
31
|
# Binary name or path
|
32
32
|
attr_reader :bin
|
33
33
|
|
34
|
+
# Binary name or path
|
35
|
+
attr_reader :nice
|
36
|
+
|
34
37
|
# Configure (raises on extra options), find binary (raises if not found)
|
35
38
|
def initialize(options = {})
|
36
39
|
get_option!(options, :bin, default_bin)
|
40
|
+
get_option!(options, :nice, 10){ |v| v.to_i }
|
37
41
|
parse_options(options)
|
38
42
|
raise "`#{bin}` not found" if `which #{bin.to_s.shellescape}`.empty?
|
39
43
|
assert_options_empty!(options)
|
@@ -43,20 +47,29 @@ class ImageOptim
|
|
43
47
|
def run_first?
|
44
48
|
end
|
45
49
|
|
46
|
-
#
|
50
|
+
# Priority in list of workers
|
51
|
+
def run_priority
|
52
|
+
run_first? ? 0 : 1
|
53
|
+
end
|
54
|
+
|
55
|
+
# Optimize file from src to dst, return boolean representing success status
|
47
56
|
def optimize(src, dst)
|
48
|
-
|
57
|
+
pid = fork do
|
58
|
+
$stdout.reopen('/dev/null', 'w')
|
59
|
+
$stderr.reopen('/dev/null', 'w')
|
60
|
+
Process.setpriority(Process::PRIO_PROCESS, 0, nice)
|
61
|
+
exec bin, *command_args(src, dst)
|
62
|
+
end
|
63
|
+
Process.wait pid
|
64
|
+
if $?.signaled?
|
65
|
+
raise SignalException.new($?.termsig)
|
66
|
+
end
|
67
|
+
$?.success? && dst.size? && dst.size < src.size
|
49
68
|
end
|
50
69
|
|
51
70
|
# Name of binary determined from class name
|
52
71
|
def default_bin
|
53
72
|
self.class.underscored_name
|
54
73
|
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def run_priority
|
59
|
-
run_first? ? 0 : 1
|
60
|
-
end
|
61
74
|
end
|
62
75
|
end
|
data/spec/image_optim_spec.rb
CHANGED
@@ -13,7 +13,7 @@ def temp_copy_path(original)
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
Tempfile
|
16
|
+
class Tempfile
|
17
17
|
alias_method :initialize_orig, :initialize
|
18
18
|
|
19
19
|
def initialize(*args, &block)
|
@@ -141,14 +141,14 @@ describe ImageOptim do
|
|
141
141
|
describe "given block" do
|
142
142
|
it "should optimize images, yield path and result for each and return array of yield results" do
|
143
143
|
io = ImageOptim.new
|
144
|
+
results = []
|
144
145
|
srcs.each do |src|
|
145
|
-
|
146
|
+
dst = "#{src}_"
|
147
|
+
io.should_receive(single_method).with(src).and_return(dst)
|
148
|
+
results << "#{src} #{dst}"
|
146
149
|
end
|
147
|
-
results = []
|
148
150
|
io.send(list_method, srcs) do |src, dst|
|
149
|
-
|
150
|
-
results << "#{src} #{dst}"
|
151
|
-
result
|
151
|
+
"#{src} #{dst}"
|
152
152
|
end.should == results
|
153
153
|
end
|
154
154
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_optim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ivan Kuchin
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-01-
|
18
|
+
date: 2012-01-13 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: fspath
|