image-optimizer 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -8
- data/Gemfile.lock +10 -33
- data/LICENSE.txt +1 -1
- data/README.md +23 -19
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/image-optimizer +45 -20
- data/image-optimizer.gemspec +17 -29
- data/lib/image-optimizer.rb +60 -53
- data/lib/image-optimizer/jpeg.rb +34 -0
- data/lib/image-optimizer/png.rb +72 -0
- data/lib/image-optimizer/png.script +13 -0
- metadata +35 -59
data/Gemfile
CHANGED
@@ -1,14 +1,9 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
# Add dependencies required to use your gem here.
|
3
3
|
# Example:
|
4
|
-
gem "yaop"
|
5
|
-
gem "
|
6
|
-
gem "
|
7
|
-
gem "jpegoptim", ">= 0.2.0"
|
8
|
-
gem "unix-whereis"
|
9
|
-
gem "options-hash"
|
10
|
-
gem "command-builder", ">= 0.3.0"
|
11
|
-
gem "mini_magick"
|
4
|
+
gem "yaop", ">= 0.2.0"
|
5
|
+
gem "which"
|
6
|
+
gem "hash-utils", ">= 2.0.0"
|
12
7
|
|
13
8
|
# Add dependencies to develop your gem here.
|
14
9
|
# Include everything needed to run rake, tests, features, etc.
|
data/Gemfile.lock
CHANGED
@@ -2,42 +2,24 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
abstract (1.0.0)
|
5
|
-
|
6
|
-
hash-utils (>= 0.18.0)
|
7
|
-
pipe-run (>= 0.2.1)
|
5
|
+
facade (1.0.5)
|
8
6
|
git (1.2.5)
|
9
7
|
hash-utils (2.0.0)
|
10
8
|
ruby-version
|
11
|
-
hashie (1.2.0)
|
12
9
|
jeweler2 (2.0.9)
|
13
10
|
git (>= 1.2.5)
|
14
|
-
jpegoptim (0.2.1)
|
15
|
-
command-builder (>= 0.2.0)
|
16
|
-
unix-whereis (>= 0.1.0)
|
17
|
-
jpegtran (0.1.3)
|
18
|
-
command-builder (>= 0.2.0)
|
19
|
-
hash-utils (>= 0.18.0)
|
20
|
-
unix-whereis (>= 0.1.0)
|
21
|
-
mini_magick (3.4)
|
22
|
-
subexec (~> 0.2.1)
|
23
11
|
multitype-introspection (0.2.0)
|
24
12
|
hash-utils (>= 0.16.0)
|
25
|
-
|
26
|
-
|
27
|
-
optipng (0.2.1)
|
28
|
-
command-builder (>= 0.2.0)
|
29
|
-
unix-whereis (>= 0.1.0)
|
30
|
-
pipe-run (0.3.0)
|
13
|
+
pathname2 (1.6.5)
|
14
|
+
facade
|
31
15
|
ruby-version (0.3.1)
|
32
|
-
subexec (0.2.1)
|
33
16
|
types (0.1.3)
|
34
17
|
abstract (>= 1.0.0)
|
35
18
|
multitype-introspection (>= 0.1.0)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
hash-utils (>= 0.1.0)
|
19
|
+
which (0.0.2)
|
20
|
+
pathname2 (>= 1.4.4)
|
21
|
+
yaop (0.2.0)
|
22
|
+
hash-utils (>= 2.0.0)
|
41
23
|
types (>= 0.1.0)
|
42
24
|
|
43
25
|
PLATFORMS
|
@@ -45,12 +27,7 @@ PLATFORMS
|
|
45
27
|
|
46
28
|
DEPENDENCIES
|
47
29
|
bundler (>= 1.0.14)
|
48
|
-
|
30
|
+
hash-utils (>= 2.0.0)
|
49
31
|
jeweler2 (>= 2.0.0)
|
50
|
-
|
51
|
-
|
52
|
-
mini_magick
|
53
|
-
options-hash
|
54
|
-
optipng (>= 0.2.0)
|
55
|
-
unix-whereis
|
56
|
-
yaop
|
32
|
+
which
|
33
|
+
yaop (>= 0.2.0)
|
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2011
|
1
|
+
Copyright (c) 2011-2012 Martin Kozák (martinkozak@martinkozak.net)
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
data/README.md
CHANGED
@@ -2,10 +2,20 @@ Image Optimizer
|
|
2
2
|
===============
|
3
3
|
|
4
4
|
**Image Optimizer** optimizes given JPEG and PNG images or images in
|
5
|
-
given folder.
|
5
|
+
given folder. Uses several encoders for achieving the best possible
|
6
|
+
*lossless* compression ratio and tries to employ the most advanced
|
7
|
+
methods such as JPEG *algorithmic encoding* if available or PNG
|
8
|
+
*transparent pixels stripping* and automatic color reduction. Performs
|
9
|
+
the following for PNG:
|
6
10
|
|
7
|
-
1.
|
8
|
-
2.
|
11
|
+
1. converts the PNG file using `gimp` to the XCF format,
|
12
|
+
2. converts XCF back to the PNG without transparent pixels using `xcf2png`,
|
13
|
+
3. optimizes it using `pngcrush` or `optipng`.
|
14
|
+
|
15
|
+
Or:
|
16
|
+
|
17
|
+
1. rewrites the PNG file using `convert`,
|
18
|
+
3. optimizes it using `pngcrush` or `optipng`.
|
9
19
|
|
10
20
|
And for JPEG:
|
11
21
|
|
@@ -14,29 +24,22 @@ And for JPEG:
|
|
14
24
|
|
15
25
|
## Usage
|
16
26
|
|
17
|
-
Simply both for files or whole directories:
|
18
|
-
|
19
|
-
ImageOptimizer::optimize("./some-dir", :strip => false, :level => 7) do |file|
|
20
|
-
p file # prints out target filename
|
21
|
-
end
|
22
|
-
|
23
|
-
Where `:strip` option indicates it should strip all metadata from
|
24
|
-
JPEG files. Default is `true`. `:level` indicates level of
|
25
|
-
PNG optimization. Default is `7`.
|
26
|
-
|
27
27
|
For *command line* usage see help for the `image-optimizer` command.
|
28
|
+
For usage as *library* see source of the `image-optimizer` command.
|
28
29
|
|
29
30
|
## Requirements
|
30
31
|
|
31
32
|
Following software for full functionality is necessary:
|
32
33
|
|
33
|
-
* [UNIX][2]-like system (*required*),
|
34
34
|
* [Ruby][1] (*required*),
|
35
|
-
* [
|
35
|
+
* [Bash][11] (*required*),
|
36
|
+
* [GIMP][3],
|
36
37
|
* [ImageMagick][8],
|
37
38
|
* [Jpegtran][5],
|
38
39
|
* [Jpegoptim][6],
|
39
|
-
* [OptiPNG][7]
|
40
|
+
* [OptiPNG][7],
|
41
|
+
* [Pngcrush][2],
|
42
|
+
* [Xcftools][4].
|
40
43
|
|
41
44
|
Steps which requires non-strictly required components will be silently
|
42
45
|
ignored if these components will not be available.
|
@@ -58,12 +61,13 @@ Copyright © 2011 [Martin Kozák][10]. See `LICENSE.txt` for
|
|
58
61
|
further details.
|
59
62
|
|
60
63
|
[1]: http://www.ruby-lang.org/
|
61
|
-
[2]: http://
|
62
|
-
[3]: http://
|
63
|
-
[4]: http://
|
64
|
+
[2]: http://pmt.sourceforge.net/pngcrush/
|
65
|
+
[3]: http://www.gimp.org/
|
66
|
+
[4]: http://henning.makholm.net/software#xcftools,
|
64
67
|
[5]: http://linux.die.net/man/1/jpegtran
|
65
68
|
[6]: http://freshmeat.net/projects/jpegoptim/
|
66
69
|
[7]: http://optipng.sourceforge.net/
|
67
70
|
[8]: http://www.imagemagick.org/
|
68
71
|
[9]: http://github.com/martinkozak/image-optimizer/issues
|
69
72
|
[10]: http://www.martinkozak.net/
|
73
|
+
[11]: http://www.gnu.org/software/bash/
|
data/Rakefile
CHANGED
@@ -20,7 +20,7 @@ Jeweler::Tasks.new do |gem|
|
|
20
20
|
gem.name = "image-optimizer"
|
21
21
|
gem.homepage = "http://github.com/martinkozak/image-optimizer"
|
22
22
|
gem.license = "MIT"
|
23
|
-
gem.summary = "Optimizes given JPEG and PNG images or images in given folder."
|
23
|
+
gem.summary = "Optimizes given JPEG and PNG images or images in given folder. Uses several encoders for achieving the best possible lossless compression ratio and tries to employ the most advanced methods such as JPEG algorithmic encoding if available or PNG transparent pixels stripping and automatic color reduction."
|
24
24
|
gem.email = "martinkozak@martinkozak.net"
|
25
25
|
gem.authors = ["Martin Kozák"]
|
26
26
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/image-optimizer
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
|
-
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
# (c) 2011-2012 Martin Kozák (martinkozak@martinkozak.net)
|
4
4
|
|
5
5
|
require "image-optimizer"
|
6
6
|
require "yaop"
|
@@ -8,16 +8,8 @@ require "yaop"
|
|
8
8
|
# Parses command line
|
9
9
|
opts = YAOP::get do
|
10
10
|
option "--help"
|
11
|
-
type Boolean, false
|
12
|
-
|
13
11
|
option "--version"
|
14
|
-
|
15
|
-
|
16
|
-
option "--strip"
|
17
|
-
type Boolean, true
|
18
|
-
|
19
|
-
option "--level"
|
20
|
-
type Integer, 7
|
12
|
+
option "--verbose"
|
21
13
|
end
|
22
14
|
|
23
15
|
# Shows help or version
|
@@ -25,22 +17,55 @@ if opts.arguments["--help"]
|
|
25
17
|
puts "Usage: image-optimizer <arguments> [files or folders]*"
|
26
18
|
puts "\t--help display this help and exit"
|
27
19
|
puts "\t--version output version information and exit"
|
28
|
-
puts "\t--
|
29
|
-
puts "\t--strip indicates it should strip all JPEG files metadata"
|
20
|
+
puts "\t--verbose be verbose"
|
30
21
|
exit
|
31
22
|
elsif opts.arguments["--version"]
|
32
|
-
puts "image-optimizer 0.
|
33
|
-
puts "Copyright (C) 2011
|
23
|
+
puts "image-optimizer 0.2.0"
|
24
|
+
puts "Copyright (C) 2011-2012 Martin Kozák (martinkozak@martinkozak.net)"
|
25
|
+
puts
|
34
26
|
puts "Optimizes given JPEG and PNG images or all images in given folders."
|
27
|
+
puts "Uses several encoders for achieving the best possible lossless"
|
28
|
+
puts "compression ratio and tries to employ the most advanced methods"
|
29
|
+
puts "such as JPEG algorithmic encoding if available or PNG transparent"
|
30
|
+
puts "pixels stripping and automatic color reduction."
|
35
31
|
exit
|
36
32
|
end
|
37
33
|
|
38
34
|
# Optimizes
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
size = nil
|
36
|
+
total = 0
|
37
|
+
total_new = 0
|
38
|
+
verbose = opts.arguments["--verbose"]
|
43
39
|
|
44
|
-
|
45
|
-
puts
|
40
|
+
if verbose
|
41
|
+
puts "# image-optimizer 0.2.0"
|
42
|
+
puts "# Copyright (C) 2011-2012 Martin Kozák (martinkozak@martinkozak.net)"
|
43
|
+
puts
|
46
44
|
end
|
45
|
+
|
46
|
+
ImageOptimizer::optimize(opts.parameters) do |data, type|
|
47
|
+
if verbose
|
48
|
+
case type
|
49
|
+
when ImageOptimizer::BEFORE
|
50
|
+
size = File.size(data)
|
51
|
+
total += size
|
52
|
+
puts data
|
53
|
+
STDOUT.write "methods: "
|
54
|
+
|
55
|
+
when ImageOptimizer::METHOD
|
56
|
+
STDOUT.write data.to_s + " "
|
57
|
+
|
58
|
+
when ImageOptimizer::AFTER
|
59
|
+
new_size = File.size(data)
|
60
|
+
total_new += new_size
|
61
|
+
ratio = ((size - new_size) / size.to_f) * 100
|
62
|
+
puts "\n" + size.to_s + " B -> " + new_size.to_s + " B (" + ratio.round.to_s + " %)\n\n"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if verbose
|
68
|
+
delta = total - total_new
|
69
|
+
ratio = (delta / total.to_f) * 100
|
70
|
+
puts "In total: " + delta.to_s + " B (" + ratio.round.to_s + " %)"
|
71
|
+
end
|
data/image-optimizer.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "image-optimizer"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Martin Koz\u{e1}k"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-08-05"
|
13
13
|
s.email = "martinkozak@martinkozak.net"
|
14
14
|
s.executables = ["image-optimizer"]
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,49 +26,37 @@ Gem::Specification.new do |s|
|
|
26
26
|
"VERSION",
|
27
27
|
"bin/image-optimizer",
|
28
28
|
"image-optimizer.gemspec",
|
29
|
-
"lib/image-optimizer.rb"
|
29
|
+
"lib/image-optimizer.rb",
|
30
|
+
"lib/image-optimizer/jpeg.rb",
|
31
|
+
"lib/image-optimizer/png.rb",
|
32
|
+
"lib/image-optimizer/png.script"
|
30
33
|
]
|
31
34
|
s.homepage = "http://github.com/martinkozak/image-optimizer"
|
32
35
|
s.licenses = ["MIT"]
|
33
36
|
s.require_paths = ["lib"]
|
34
|
-
s.rubygems_version = "1.8.
|
35
|
-
s.summary = "Optimizes given JPEG and PNG images or images in given folder."
|
37
|
+
s.rubygems_version = "1.8.24"
|
38
|
+
s.summary = "Optimizes given JPEG and PNG images or images in given folder. Uses several encoders for achieving the best possible lossless compression ratio and tries to employ the most advanced methods such as JPEG algorithmic encoding if available or PNG transparent pixels stripping and automatic color reduction."
|
36
39
|
|
37
40
|
if s.respond_to? :specification_version then
|
38
41
|
s.specification_version = 3
|
39
42
|
|
40
43
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
41
|
-
s.add_runtime_dependency(%q<yaop>, [">= 0"])
|
42
|
-
s.add_runtime_dependency(%q<
|
43
|
-
s.add_runtime_dependency(%q<
|
44
|
-
s.add_runtime_dependency(%q<jpegoptim>, [">= 0.2.0"])
|
45
|
-
s.add_runtime_dependency(%q<unix-whereis>, [">= 0"])
|
46
|
-
s.add_runtime_dependency(%q<options-hash>, [">= 0"])
|
47
|
-
s.add_runtime_dependency(%q<command-builder>, [">= 0.3.0"])
|
48
|
-
s.add_runtime_dependency(%q<mini_magick>, [">= 0"])
|
44
|
+
s.add_runtime_dependency(%q<yaop>, [">= 0.2.0"])
|
45
|
+
s.add_runtime_dependency(%q<which>, [">= 0"])
|
46
|
+
s.add_runtime_dependency(%q<hash-utils>, [">= 2.0.0"])
|
49
47
|
s.add_development_dependency(%q<bundler>, [">= 1.0.14"])
|
50
48
|
s.add_development_dependency(%q<jeweler2>, [">= 2.0.0"])
|
51
49
|
else
|
52
|
-
s.add_dependency(%q<yaop>, [">= 0"])
|
53
|
-
s.add_dependency(%q<
|
54
|
-
s.add_dependency(%q<
|
55
|
-
s.add_dependency(%q<jpegoptim>, [">= 0.2.0"])
|
56
|
-
s.add_dependency(%q<unix-whereis>, [">= 0"])
|
57
|
-
s.add_dependency(%q<options-hash>, [">= 0"])
|
58
|
-
s.add_dependency(%q<command-builder>, [">= 0.3.0"])
|
59
|
-
s.add_dependency(%q<mini_magick>, [">= 0"])
|
50
|
+
s.add_dependency(%q<yaop>, [">= 0.2.0"])
|
51
|
+
s.add_dependency(%q<which>, [">= 0"])
|
52
|
+
s.add_dependency(%q<hash-utils>, [">= 2.0.0"])
|
60
53
|
s.add_dependency(%q<bundler>, [">= 1.0.14"])
|
61
54
|
s.add_dependency(%q<jeweler2>, [">= 2.0.0"])
|
62
55
|
end
|
63
56
|
else
|
64
|
-
s.add_dependency(%q<yaop>, [">= 0"])
|
65
|
-
s.add_dependency(%q<
|
66
|
-
s.add_dependency(%q<
|
67
|
-
s.add_dependency(%q<jpegoptim>, [">= 0.2.0"])
|
68
|
-
s.add_dependency(%q<unix-whereis>, [">= 0"])
|
69
|
-
s.add_dependency(%q<options-hash>, [">= 0"])
|
70
|
-
s.add_dependency(%q<command-builder>, [">= 0.3.0"])
|
71
|
-
s.add_dependency(%q<mini_magick>, [">= 0"])
|
57
|
+
s.add_dependency(%q<yaop>, [">= 0.2.0"])
|
58
|
+
s.add_dependency(%q<which>, [">= 0"])
|
59
|
+
s.add_dependency(%q<hash-utils>, [">= 2.0.0"])
|
72
60
|
s.add_dependency(%q<bundler>, [">= 1.0.14"])
|
73
61
|
s.add_dependency(%q<jeweler2>, [">= 2.0.0"])
|
74
62
|
end
|
data/lib/image-optimizer.rb
CHANGED
@@ -1,15 +1,39 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
2
|
+
# (c) 2011-2012 Martin Kozák (martinkozak@martinkozak.net)
|
3
3
|
|
4
|
-
require "
|
5
|
-
require "
|
6
|
-
require "
|
7
|
-
|
8
|
-
require "mini_magick"
|
9
|
-
require "unix/whereis"
|
10
|
-
require "options-hash"
|
4
|
+
require "which"
|
5
|
+
require "image-optimizer/jpeg"
|
6
|
+
require "image-optimizer/png"
|
11
7
|
|
12
8
|
module ImageOptimizer
|
9
|
+
|
10
|
+
##
|
11
|
+
# Indicates, callback is called before the optimization.
|
12
|
+
# @var [Symbol]
|
13
|
+
#
|
14
|
+
|
15
|
+
BEFORE = :before
|
16
|
+
|
17
|
+
##
|
18
|
+
# Indicates, callback is called before the optimization.
|
19
|
+
# @var [Symbol]
|
20
|
+
#
|
21
|
+
|
22
|
+
AFTER = :after
|
23
|
+
|
24
|
+
##
|
25
|
+
# Indicates, callback returns the method.
|
26
|
+
# @var [Symbol]
|
27
|
+
#
|
28
|
+
|
29
|
+
METHOD = :method
|
30
|
+
|
31
|
+
##
|
32
|
+
# Optimizers availiability cache.
|
33
|
+
# @var [Hash]
|
34
|
+
#
|
35
|
+
|
36
|
+
@optimizers
|
13
37
|
|
14
38
|
##
|
15
39
|
# Optimizes given file or folder.
|
@@ -18,22 +42,19 @@ module ImageOptimizer
|
|
18
42
|
# optimized files.
|
19
43
|
#
|
20
44
|
# @param [String, Array] item path or paths to files or directories
|
21
|
-
# @param [Hash] options options for optimizing
|
22
45
|
# @param [Proc] block block for giving back the results
|
23
|
-
# @option options [Boolean] :strip indicates it should strip metadata from JPEG files
|
24
|
-
# @option options [Integer] :level indicates level of PNG optimizations
|
25
46
|
#
|
26
47
|
|
27
|
-
def self.optimize(item,
|
48
|
+
def self.optimize(item, &block)
|
28
49
|
if item.kind_of? Array
|
29
50
|
item.each do |i|
|
30
|
-
self::optimize(i,
|
51
|
+
self::optimize(i, &block)
|
31
52
|
end
|
32
53
|
else
|
33
54
|
if File.file? item
|
34
|
-
self::optimize_file(item,
|
55
|
+
self::optimize_file(item, &block)
|
35
56
|
elsif File.directory? item
|
36
|
-
self::optimize_directory(item,
|
57
|
+
self::optimize_directory(item, &block)
|
37
58
|
end
|
38
59
|
end
|
39
60
|
end
|
@@ -43,17 +64,14 @@ module ImageOptimizer
|
|
43
64
|
# Yields paths to optimized files.
|
44
65
|
#
|
45
66
|
# @param [String] item path to directory
|
46
|
-
# @param [Hash] options options for optimizing
|
47
67
|
# @param [Proc] block block for giving back the results
|
48
|
-
# @option options [Boolean] :strip indicates it should strip metadata from JPEG files
|
49
|
-
# @option options [Integer] :level indicates level of PNG optimizations
|
50
68
|
#
|
51
69
|
|
52
|
-
def self.optimize_directory(item,
|
70
|
+
def self.optimize_directory(item, &block)
|
53
71
|
Dir.open(item) do |dir|
|
54
72
|
dir.each do |i|
|
55
73
|
if i[0].chr != ?.
|
56
|
-
self::optimize(item + "/" + i,
|
74
|
+
self::optimize(item + "/" + i, &block)
|
57
75
|
end
|
58
76
|
end
|
59
77
|
end
|
@@ -64,48 +82,37 @@ module ImageOptimizer
|
|
64
82
|
# Yields paths to optimized files.
|
65
83
|
#
|
66
84
|
# @param [String] item path to file
|
67
|
-
# @param [Hash] options options for optimizing
|
68
85
|
# @param [Proc] block block for giving back the results
|
69
|
-
# @option options [Boolean] :strip indicates it should strip metadata from JPEG files
|
70
|
-
# @option options [Integer] :level indicates level of PNG optimizations
|
71
86
|
#
|
72
87
|
|
73
|
-
def self.optimize_file(path,
|
88
|
+
def self.optimize_file(path, &block)
|
74
89
|
ext = File.extname(path)
|
75
90
|
|
76
|
-
# Loads options
|
77
|
-
opts = OptionsHash::get(options) [
|
78
|
-
:strip => true,
|
79
|
-
:level => 7
|
80
|
-
]
|
81
|
-
|
82
91
|
case ext
|
83
92
|
when ".png"
|
84
|
-
|
85
|
-
|
86
|
-
if Whereis.available? :convert
|
87
|
-
cmd = CommandBuilder::new(:convert, ["-", " ", "-", " "])
|
88
|
-
cmd << path
|
89
|
-
cmd.arg(:quality, 100)
|
90
|
-
cmd << path
|
91
|
-
|
92
|
-
cmd.execute!
|
93
|
-
end
|
94
|
-
|
95
|
-
if Optipng.available?
|
96
|
-
Optipng.optimize(path, { :level => opts[:level] })
|
97
|
-
end
|
98
|
-
|
93
|
+
ImageOptimizer::Png::optimize(path, &block)
|
94
|
+
|
99
95
|
when ".jpg"
|
100
|
-
|
96
|
+
ImageOptimizer::Jpeg::optimize(path, &block)
|
101
97
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Indicates, optimizer is available.
|
103
|
+
#
|
104
|
+
# @param [Symbol, String] command command name
|
105
|
+
# @return [Boolean]
|
106
|
+
#
|
107
|
+
|
108
|
+
def self.available?(command)
|
109
|
+
@optimizers = { } if @optimizers.nil?
|
110
|
+
|
111
|
+
if command.in? @optimizers
|
112
|
+
return @optimizers[command]
|
113
|
+
else
|
114
|
+
available = (not Which.which(command.to_s).empty?)
|
115
|
+
return @optimizers[command] = available
|
109
116
|
end
|
110
117
|
end
|
111
118
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2012 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
module ImageOptimizer
|
5
|
+
|
6
|
+
##
|
7
|
+
# JPEG optimizing module.
|
8
|
+
# @since 1.0
|
9
|
+
#
|
10
|
+
|
11
|
+
module Jpeg
|
12
|
+
|
13
|
+
def self.optimize(path, &block)
|
14
|
+
|
15
|
+
# calls back
|
16
|
+
block.call(path.dup, ImageOptimizer::BEFORE)
|
17
|
+
|
18
|
+
if ImageOptimizer.available? :jpegoptim
|
19
|
+
block.call(:jpegoptim, ImageOptimizer::METHOD)
|
20
|
+
`jpegoptim --strip-all #{path} 2> /dev/null`
|
21
|
+
end
|
22
|
+
|
23
|
+
if ImageOptimizer.available? :jpegtran
|
24
|
+
block.call(:jpegtran, ImageOptimizer::METHOD)
|
25
|
+
`jpegtran -arithmetic -optimize -progressive -copy none #{path} 2> /dev/null`
|
26
|
+
end
|
27
|
+
|
28
|
+
# calls back
|
29
|
+
block.call(path.dup, ImageOptimizer::AFTER)
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2012 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "hash-utils"
|
5
|
+
require "fileutils"
|
6
|
+
require "tmpdir"
|
7
|
+
|
8
|
+
module ImageOptimizer
|
9
|
+
|
10
|
+
##
|
11
|
+
# PNG optimizing module.
|
12
|
+
# @since 1.0
|
13
|
+
#
|
14
|
+
|
15
|
+
module Png
|
16
|
+
|
17
|
+
def self.optimize(path, &block)
|
18
|
+
|
19
|
+
# calls back
|
20
|
+
block.call(path.dup, ImageOptimizer::BEFORE)
|
21
|
+
|
22
|
+
# New method (GIMP & XcfTools)
|
23
|
+
if ImageOptimizer.available? :gimp and ImageOptimizer.available? :xcf2png
|
24
|
+
dirname = File.dirname(path)
|
25
|
+
basename = File.basename(path, '.png')
|
26
|
+
basepath = dirname + '/' + basename
|
27
|
+
png_path = basepath + '.png'
|
28
|
+
xcf_path = basepath + '.xcf'
|
29
|
+
protect = File.exists? xcf_path
|
30
|
+
|
31
|
+
if protect
|
32
|
+
protect = Dir.tmpdir + '/' + File.basename(xcf_path)
|
33
|
+
FileUtils.mv(xcf_path, protect)
|
34
|
+
end
|
35
|
+
|
36
|
+
# GIMP
|
37
|
+
block.call(:gimp, ImageOptimizer::METHOD)
|
38
|
+
gimp = File.read(File.dirname(__FILE__) + '/png.script')
|
39
|
+
gimp.gsub!(':path', png_path)
|
40
|
+
`#{gimp}`
|
41
|
+
|
42
|
+
# xcf2png
|
43
|
+
block.call(:xcf2png, ImageOptimizer::METHOD)
|
44
|
+
`xcf2png #{xcf_path} > #{png_path} 2> /dev/null`
|
45
|
+
FileUtils.rm(xcf_path)
|
46
|
+
|
47
|
+
if protect
|
48
|
+
FileUtils.mv(protect, xcf_path)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Old method (ImageMagick)
|
52
|
+
elsif ImageOptimizer.available? :convert
|
53
|
+
block.call(:convert, ImageOptimizer::METHOD)
|
54
|
+
`convert #{path} -quality 100 #{path} 2> /dev/null`
|
55
|
+
end
|
56
|
+
|
57
|
+
# General optimizers
|
58
|
+
if ImageOptimizer.available? :pngcrush
|
59
|
+
block.call(:pngcrush, ImageOptimizer::METHOD)
|
60
|
+
`pngcrush -reduce -brute -ow #{path} 2> /dev/null`
|
61
|
+
elsif ImageOptimizer.available? :optipng
|
62
|
+
block.call(:optipng, ImageOptimizer::METHOD)
|
63
|
+
`optipng -o 7 #{path} 2> /dev/null`
|
64
|
+
end
|
65
|
+
|
66
|
+
# calls back
|
67
|
+
block.call(path.dup, ImageOptimizer::AFTER)
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
gimp -n -i -b - 2> /dev/null <<EOF
|
2
|
+
(let* ( (file's (cadr (file-glob ":path" 1))) (filename "") (image 0) (layer 0) )
|
3
|
+
(while (pair? file's)
|
4
|
+
(set! image (car (gimp-file-load RUN-NONINTERACTIVE (car file's) (car file's))))
|
5
|
+
(set! layer (car (gimp-image-merge-visible-layers image CLIP-TO-IMAGE)))
|
6
|
+
(set! filename (string-append (substring (car file's) 0 (- (string-length (car file's)) 4)) ".xcf"))
|
7
|
+
(gimp-file-save RUN-NONINTERACTIVE image layer filename filename)
|
8
|
+
(gimp-image-delete image)
|
9
|
+
(set! file's (cdr file's))
|
10
|
+
)
|
11
|
+
(gimp-quit 0)
|
12
|
+
)
|
13
|
+
EOF
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image-optimizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,33 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: yaop
|
16
|
-
requirement:
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0'
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: *24265520
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: jpegtran
|
27
|
-
requirement: &24264900 !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
|
-
requirements:
|
30
|
-
- - ! '>='
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '0'
|
33
|
-
type: :runtime
|
34
|
-
prerelease: false
|
35
|
-
version_requirements: *24264900
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: optipng
|
38
|
-
requirement: &24264360 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
39
17
|
none: false
|
40
18
|
requirements:
|
41
19
|
- - ! '>='
|
@@ -43,21 +21,15 @@ dependencies:
|
|
43
21
|
version: 0.2.0
|
44
22
|
type: :runtime
|
45
23
|
prerelease: false
|
46
|
-
version_requirements:
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: jpegoptim
|
49
|
-
requirement: &24263740 !ruby/object:Gem::Requirement
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
25
|
none: false
|
51
26
|
requirements:
|
52
27
|
- - ! '>='
|
53
28
|
- !ruby/object:Gem::Version
|
54
29
|
version: 0.2.0
|
55
|
-
type: :runtime
|
56
|
-
prerelease: false
|
57
|
-
version_requirements: *24263740
|
58
30
|
- !ruby/object:Gem::Dependency
|
59
|
-
name:
|
60
|
-
requirement:
|
31
|
+
name: which
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
61
33
|
none: false
|
62
34
|
requirements:
|
63
35
|
- - ! '>='
|
@@ -65,43 +37,31 @@ dependencies:
|
|
65
37
|
version: '0'
|
66
38
|
type: :runtime
|
67
39
|
prerelease: false
|
68
|
-
version_requirements:
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: options-hash
|
71
|
-
requirement: &24262580 !ruby/object:Gem::Requirement
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
41
|
none: false
|
73
42
|
requirements:
|
74
43
|
- - ! '>='
|
75
44
|
- !ruby/object:Gem::Version
|
76
45
|
version: '0'
|
77
|
-
type: :runtime
|
78
|
-
prerelease: false
|
79
|
-
version_requirements: *24262580
|
80
46
|
- !ruby/object:Gem::Dependency
|
81
|
-
name:
|
82
|
-
requirement:
|
47
|
+
name: hash-utils
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
83
49
|
none: false
|
84
50
|
requirements:
|
85
51
|
- - ! '>='
|
86
52
|
- !ruby/object:Gem::Version
|
87
|
-
version: 0.
|
53
|
+
version: 2.0.0
|
88
54
|
type: :runtime
|
89
55
|
prerelease: false
|
90
|
-
version_requirements:
|
91
|
-
- !ruby/object:Gem::Dependency
|
92
|
-
name: mini_magick
|
93
|
-
requirement: &24277820 !ruby/object:Gem::Requirement
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
57
|
none: false
|
95
58
|
requirements:
|
96
59
|
- - ! '>='
|
97
60
|
- !ruby/object:Gem::Version
|
98
|
-
version:
|
99
|
-
type: :runtime
|
100
|
-
prerelease: false
|
101
|
-
version_requirements: *24277820
|
61
|
+
version: 2.0.0
|
102
62
|
- !ruby/object:Gem::Dependency
|
103
63
|
name: bundler
|
104
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
105
65
|
none: false
|
106
66
|
requirements:
|
107
67
|
- - ! '>='
|
@@ -109,10 +69,15 @@ dependencies:
|
|
109
69
|
version: 1.0.14
|
110
70
|
type: :development
|
111
71
|
prerelease: false
|
112
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.0.14
|
113
78
|
- !ruby/object:Gem::Dependency
|
114
79
|
name: jeweler2
|
115
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
116
81
|
none: false
|
117
82
|
requirements:
|
118
83
|
- - ! '>='
|
@@ -120,7 +85,12 @@ dependencies:
|
|
120
85
|
version: 2.0.0
|
121
86
|
type: :development
|
122
87
|
prerelease: false
|
123
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.0.0
|
124
94
|
description:
|
125
95
|
email: martinkozak@martinkozak.net
|
126
96
|
executables:
|
@@ -140,6 +110,9 @@ files:
|
|
140
110
|
- bin/image-optimizer
|
141
111
|
- image-optimizer.gemspec
|
142
112
|
- lib/image-optimizer.rb
|
113
|
+
- lib/image-optimizer/jpeg.rb
|
114
|
+
- lib/image-optimizer/png.rb
|
115
|
+
- lib/image-optimizer/png.script
|
143
116
|
homepage: http://github.com/martinkozak/image-optimizer
|
144
117
|
licenses:
|
145
118
|
- MIT
|
@@ -155,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
128
|
version: '0'
|
156
129
|
segments:
|
157
130
|
- 0
|
158
|
-
hash: -
|
131
|
+
hash: -3356677403226077411
|
159
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
133
|
none: false
|
161
134
|
requirements:
|
@@ -164,8 +137,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
137
|
version: '0'
|
165
138
|
requirements: []
|
166
139
|
rubyforge_project:
|
167
|
-
rubygems_version: 1.8.
|
140
|
+
rubygems_version: 1.8.24
|
168
141
|
signing_key:
|
169
142
|
specification_version: 3
|
170
|
-
summary: Optimizes given JPEG and PNG images or images in given folder.
|
143
|
+
summary: Optimizes given JPEG and PNG images or images in given folder. Uses several
|
144
|
+
encoders for achieving the best possible lossless compression ratio and tries to
|
145
|
+
employ the most advanced methods such as JPEG algorithmic encoding if available
|
146
|
+
or PNG transparent pixels stripping and automatic color reduction.
|
171
147
|
test_files: []
|