image_optim 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|