grosser-smusher 0.1 → 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.
- data/README.markdown +16 -16
- data/Rakefile +2 -2
- data/bin/smusher +9 -5
- data/lib/smusher.rb +41 -67
- data/smusher.gemspec +3 -3
- data/spec/reduced/add.png +0 -0
- data/spec/smusher_spec.rb +15 -51
- metadata +4 -2
data/README.markdown
CHANGED
@@ -11,38 +11,38 @@ Solution
|
|
11
11
|
|
12
12
|
Install
|
13
13
|
=======
|
14
|
-
install ruby + rubygems
|
14
|
+
install ruby + rubygems + curl
|
15
15
|
sudo gem install grosser-smusher --source http://gems.github.com/
|
16
16
|
|
17
17
|
Usage
|
18
18
|
=====
|
19
|
-
|
20
|
-
smusher /apps/x/public/images
|
21
|
-
smusher
|
19
|
+
smusher /apps/x/public/images # optimize all jpg/png images, NOT gifs
|
20
|
+
smusher /apps/x/public/images/x.png # optimize a single image
|
21
|
+
smusher /apps/x/public/images/x.gif # !!optimize to smaller png, rename it yourself!!
|
22
22
|
|
23
23
|
Protection
|
24
24
|
==========
|
25
|
-
Smusher makes .backup copies of any image before optimizing.
|
26
|
-
Any image that returns a failure code, is larger than before,
|
25
|
+
Smusher makes .backup copies of any image before optimizing.
|
26
|
+
Any image that returns a failure code, is larger than before,
|
27
27
|
or is empty will be reverted.
|
28
28
|
|
29
29
|
Example
|
30
30
|
======
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
smusher /apps/ts/public/images
|
32
|
+
sushing /apps/rs/public/images/social/facebook_icon.png
|
33
|
+
2887 -> 132 = 4%
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
sushing /apps/rs/public/images/social/myspace_icon.png
|
36
|
+
3136 -> 282 = 8%
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
sushing /apps/rs/public/images/dvd/dvd_1.png
|
39
|
+
5045 -> 4 = 0%
|
40
|
+
reverted!
|
41
|
+
...
|
42
42
|
|
43
43
|
TODO
|
44
44
|
====
|
45
|
-
-
|
45
|
+
- use rest-client rather than curl
|
46
46
|
- windows support?
|
47
47
|
|
48
48
|
Author
|
data/Rakefile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
desc "Run all specs in spec directory"
|
2
|
-
task :
|
2
|
+
task :test do |t|
|
3
3
|
require 'spec'
|
4
4
|
options = "--colour --format progress --loadby --reverse"
|
5
5
|
files = FileList['spec/**/*_spec.rb']
|
@@ -9,7 +9,7 @@ end
|
|
9
9
|
#Gemspec
|
10
10
|
require 'echoe'
|
11
11
|
porject_name = 'smusher'
|
12
|
-
Echoe.new(porject_name , '0.
|
12
|
+
Echoe.new(porject_name , '0.3') do |p|
|
13
13
|
p.description = "Automatic Lossless Reduction Of All Your Images"
|
14
14
|
p.url = "http://github.com/grosser/#{porject_name}"
|
15
15
|
p.author = "Michael Grosser"
|
data/bin/smusher
CHANGED
@@ -2,11 +2,15 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'smusher'
|
4
4
|
|
5
|
-
|
6
|
-
if ARGV.length
|
7
|
-
puts "smusher
|
8
|
-
puts "smusher /apps/x/public/images
|
5
|
+
path = ARGV[0]
|
6
|
+
if ARGV.length != 1 or not File.exist?(path)
|
7
|
+
puts "smusher DIRECTORY_OR_FILE_TO_OPTIMIZE"
|
8
|
+
puts "smusher /apps/x/public/images"
|
9
9
|
exit
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
if File.directory?(path)
|
13
|
+
Smusher.optimize_images_in_folder(path)
|
14
|
+
else
|
15
|
+
Smusher.optimize_image(path)
|
16
|
+
end
|
data/lib/smusher.rb
CHANGED
@@ -1,47 +1,37 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
module Smusher
|
5
6
|
extend self
|
6
|
-
#http://smushit.com/ws.php?img=http%3A%2F%2Fwww.famfamfam.com%2Flab%2Ficons%2Fsilk%2Ficons%2Fdrink_empty.png&task=89266837334214400&id=paste2
|
7
|
-
SMUSHIT_FAILURE_SIZE = 9667
|
8
7
|
EMPTY_FILE_SIZE = 4
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
|
9
|
+
# optimize the given image !!coverts gif to png!!
|
10
|
+
def optimize_image(file)
|
11
|
+
if empty?(file)
|
12
|
+
puts "THIS FILE IS EMPTY!!! #{file}"
|
13
|
+
return
|
14
|
+
end
|
12
15
|
with_protection(file) do
|
13
|
-
with_logging(
|
14
|
-
|
16
|
+
with_logging(file) do
|
17
|
+
write_optimized_data(file)
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
folder = sanitize_folder(folder)
|
22
|
-
|
22
|
+
# fetch all jpg/png images from given folder and optimize them
|
23
|
+
def optimize_images_in_folder(folder)
|
23
24
|
images_in_folder(folder).each do |file|
|
24
|
-
|
25
|
-
url = "#{base_url}/#{relative_path_to_folder}"
|
26
|
-
store_smushed_image(url,file)
|
25
|
+
optimize_image(file)
|
27
26
|
puts ''
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
30
|
private
|
32
31
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
raise data if data =~ /<html>/i
|
37
|
-
f.puts data
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def sanitize_url(url)
|
42
|
-
url = url.sub(%r[/$],'')#remove tailing slash
|
43
|
-
url = url.sub(url,"http://#{url}") unless url.include?('://')#add http if protocol is missing
|
44
|
-
url
|
32
|
+
def write_optimized_data(file)
|
33
|
+
data = optimized_image_data_for(file)
|
34
|
+
File.open(file,'w') {|f| f.puts data}
|
45
35
|
end
|
46
36
|
|
47
37
|
def sanitize_folder(folder)
|
@@ -49,31 +39,23 @@ private
|
|
49
39
|
end
|
50
40
|
|
51
41
|
def images_in_folder(folder)
|
42
|
+
folder = sanitize_folder(folder)
|
52
43
|
images = %w[png jpg jpeg JPG].map {|ext| "#{folder}/**/*.#{ext}"}
|
53
44
|
FileList[*images]
|
54
45
|
end
|
55
46
|
|
56
47
|
def with_protection(file)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
else
|
69
|
-
FileUtils.rm(backup)
|
70
|
-
end
|
71
|
-
else#is created
|
72
|
-
yield
|
73
|
-
after = size(file)
|
74
|
-
if after == SMUSHIT_FAILURE_SIZE or after == EMPTY_FILE_SIZE
|
75
|
-
FileUtils.rm file
|
76
|
-
end
|
48
|
+
backup = "#{file}.backup"
|
49
|
+
FileUtils.cp(file,backup)
|
50
|
+
|
51
|
+
before = size(file)
|
52
|
+
yield
|
53
|
+
|
54
|
+
if empty?(file) or size(file) >= before
|
55
|
+
FileUtils.mv(backup,file,:force=>true)#revert
|
56
|
+
puts "reverted!"
|
57
|
+
else
|
58
|
+
FileUtils.rm(backup)
|
77
59
|
end
|
78
60
|
end
|
79
61
|
|
@@ -81,34 +63,26 @@ private
|
|
81
63
|
File.exist?(file) ? File.size(file) : 0
|
82
64
|
end
|
83
65
|
|
84
|
-
def
|
85
|
-
|
66
|
+
def empty?(file)
|
67
|
+
size(file) <= EMPTY_FILE_SIZE
|
68
|
+
end
|
69
|
+
|
70
|
+
def with_logging(file)
|
71
|
+
puts "sushing #{file}"
|
86
72
|
|
87
73
|
before = size(file)
|
88
74
|
yield
|
89
75
|
after = size(file)
|
90
76
|
|
91
|
-
result =
|
77
|
+
result = "#{(100*after)/before}%"
|
92
78
|
puts "#{before} -> #{after}".ljust(40) + " = #{result}"
|
93
79
|
end
|
94
80
|
|
95
|
-
def
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
require 'rubygems'
|
102
|
-
require 'json'
|
103
|
-
|
104
|
-
http = Net::HTTP.new('smushit.com')
|
105
|
-
path = "/ws.php?img=#{url}&task=89266837334214400&id=paste2"
|
106
|
-
|
107
|
-
resp, data = http.get(path, nil)
|
108
|
-
raise "oops #{resp}" unless resp.is_a? Net::HTTPOK
|
109
|
-
|
110
|
-
path = "/#{JSON.parse(data)['dest']}"
|
111
|
-
resp, data = http.get(path, nil)
|
112
|
-
data
|
81
|
+
def optimized_image_data_for(file)
|
82
|
+
#TODO use rest-client --> independent of curl
|
83
|
+
response = `curl -F files[]=@#{file} http://smush.it/ws.php -s`
|
84
|
+
return nil if response['error']
|
85
|
+
path = JSON.parse(response)['dest']
|
86
|
+
`curl http://smush.it/#{path} -s`
|
113
87
|
end
|
114
88
|
end
|
data/smusher.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{smusher}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Michael Grosser"]
|
9
|
-
s.date = %q{2009-01-
|
9
|
+
s.date = %q{2009-01-25}
|
10
10
|
s.default_executable = %q{smusher}
|
11
11
|
s.description = %q{Automatic Lossless Reduction Of All Your Images}
|
12
12
|
s.email = %q{grosser.michael@gmail.com}
|
13
13
|
s.executables = ["smusher"]
|
14
14
|
s.extra_rdoc_files = ["lib/smusher.rb", "bin/smusher", "README.markdown"]
|
15
|
-
s.files = ["Manifest", "nbproject/private/rake-d.txt", "nbproject/project.xml", "nbproject/project.properties", "lib/smusher.rb", "spec/out/people.jpg", "spec/spec_helper.rb", "spec/smusher_spec.rb", "spec/images/logo.gif", "spec/images/woman.jpeg", "spec/images/add.png", "spec/images/drink_empty.png", "spec/images/people.jpg", "spec/images/water.JPG", "spec/reduced/fam.png", "bin/smusher", "Rakefile", "README.markdown", "smusher.gemspec"]
|
15
|
+
s.files = ["Manifest", "nbproject/private/private.xml", "nbproject/private/rake-d.txt", "nbproject/project.xml", "nbproject/project.properties", "lib/smusher.rb", "spec/out/people.jpg", "spec/spec_helper.rb", "spec/smusher_spec.rb", "spec/images/logo.gif", "spec/images/woman.jpeg", "spec/images/add.png", "spec/images/drink_empty.png", "spec/images/people.jpg", "spec/images/water.JPG", "spec/reduced/fam.png", "spec/reduced/add.png", "bin/smusher", "Rakefile", "README.markdown", "smusher.gemspec"]
|
16
16
|
s.has_rdoc = true
|
17
17
|
s.homepage = %q{http://github.com/grosser/smusher}
|
18
18
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Smusher", "--main", "README.markdown"]
|
Binary file
|
data/spec/smusher_spec.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
ROOT = File.expand_path(File.dirname(__FILE__))
|
2
2
|
require File.join(ROOT,"spec_helper")
|
3
3
|
|
4
|
-
URL = "http://famfamfam.com/lab/icons/silk/icons/drink_empty.png"
|
5
|
-
ESCAPED_URL = "http%3A%2F%2Fwww.famfamfam.com%2Flab%2Ficons%2Fsilk%2Ficons%2Fdrink_empty.png"
|
6
|
-
|
7
4
|
describe :smusher do
|
8
5
|
def size
|
9
6
|
File.size(@file)
|
@@ -19,20 +16,15 @@ describe :smusher do
|
|
19
16
|
@file = File.join(@out,'people.jpg')
|
20
17
|
end
|
21
18
|
|
22
|
-
describe :
|
19
|
+
describe :optimize_image do
|
23
20
|
it "stores the image in an reduced size" do
|
24
21
|
original_size = size
|
25
|
-
Smusher.
|
22
|
+
Smusher.optimize_image(@file)
|
26
23
|
size.should < original_size
|
27
24
|
end
|
28
|
-
|
29
|
-
it "uses cleaned url" do
|
30
|
-
Smusher.expects(:write_smushed_data).with("http://xx",@file)
|
31
|
-
Smusher.store_smushed_image('xx',@file)
|
32
|
-
end
|
33
25
|
end
|
34
26
|
|
35
|
-
describe :
|
27
|
+
describe :optimize_images_in_folder do
|
36
28
|
before do
|
37
29
|
FileUtils.rm @file
|
38
30
|
@files = []
|
@@ -45,23 +37,13 @@ describe :smusher do
|
|
45
37
|
end
|
46
38
|
|
47
39
|
it "smushes all images" do
|
48
|
-
Smusher.
|
40
|
+
Smusher.optimize_images_in_folder(@out)
|
49
41
|
new_sizes = @files.map {|f|File.size(f)}
|
50
42
|
puts new_sizes * ' x '
|
51
43
|
new_sizes.size.times {|i| new_sizes[i].should < @before[i]}
|
52
44
|
end
|
53
45
|
end
|
54
46
|
|
55
|
-
describe :sanitize_url do
|
56
|
-
it "cleans a url" do
|
57
|
-
Smusher.send(:sanitize_url,'xx').should == "http://xx"
|
58
|
-
end
|
59
|
-
|
60
|
-
it "does not cleans a url if it contains a protocol" do
|
61
|
-
Smusher.send(:sanitize_url,'ftp://xx').should == "ftp://xx"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
47
|
describe :sanitize_folder do
|
66
48
|
it "cleans a folders trailing slash" do
|
67
49
|
Smusher.send(:sanitize_folder,"xx/").should == 'xx'
|
@@ -111,15 +93,6 @@ describe :smusher do
|
|
111
93
|
@before.should == size
|
112
94
|
end
|
113
95
|
|
114
|
-
it "does not revert a file that got created" do
|
115
|
-
FileUtils.rm @file
|
116
|
-
File.exist?(@file).should be_false
|
117
|
-
Smusher.send(:with_protection,@file) do
|
118
|
-
copy
|
119
|
-
end
|
120
|
-
File.exist?(@file).should be_true
|
121
|
-
end
|
122
|
-
|
123
96
|
it "reverts a file that got empty" do
|
124
97
|
Smusher.send(:with_protection,@file) do
|
125
98
|
write nil
|
@@ -129,30 +102,20 @@ describe :smusher do
|
|
129
102
|
end
|
130
103
|
|
131
104
|
it "reverts a file that has error-suggesting size" do
|
132
|
-
|
133
|
-
write(failure_data+failure_data)
|
105
|
+
write("valid-file-contents")
|
134
106
|
@before = size
|
135
|
-
@before.should > Smusher::
|
107
|
+
@before.should > Smusher::EMPTY_FILE_SIZE
|
136
108
|
|
137
109
|
#gets overwritten by failure data size
|
138
110
|
Smusher.send(:with_protection,@file) do
|
139
|
-
write
|
140
|
-
size.should == Smusher::
|
111
|
+
write nil
|
112
|
+
size.should == Smusher::EMPTY_FILE_SIZE
|
141
113
|
end
|
142
114
|
|
143
115
|
#and should be reverted
|
144
|
-
size.should_not == Smusher::
|
116
|
+
size.should_not == Smusher::EMPTY_FILE_SIZE
|
145
117
|
size.should == @before
|
146
118
|
end
|
147
|
-
|
148
|
-
it "reverts a file that got created and has error suggesting size" do
|
149
|
-
FileUtils.rm @file
|
150
|
-
Smusher.send(:with_protection,@file) do
|
151
|
-
write failure_data
|
152
|
-
File.exist?(@file).should be_true
|
153
|
-
end
|
154
|
-
File.exist?(@file).should be_false
|
155
|
-
end
|
156
119
|
end
|
157
120
|
|
158
121
|
describe :size do
|
@@ -168,16 +131,17 @@ describe :smusher do
|
|
168
131
|
describe :logging do
|
169
132
|
it "yields" do
|
170
133
|
val = 0
|
171
|
-
Smusher.send(:with_logging
|
134
|
+
Smusher.send(:with_logging,@file) {val = 1}
|
172
135
|
val.should == 1
|
173
136
|
end
|
174
137
|
end
|
175
138
|
|
176
|
-
describe :
|
139
|
+
describe :optimized_image_data_for do
|
177
140
|
it "loads the reduced image" do
|
178
|
-
|
179
|
-
|
180
|
-
received
|
141
|
+
original = File.join(ROOT,'images','add.png')
|
142
|
+
reduced = File.open(File.join(ROOT,'reduced','add.png')).read
|
143
|
+
received = (Smusher.send(:optimized_image_data_for,original))
|
144
|
+
received.should == reduced
|
181
145
|
end
|
182
146
|
end
|
183
147
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grosser-smusher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.3"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-25 00:00:00 -08:00
|
13
13
|
default_executable: smusher
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -51,6 +51,7 @@ extra_rdoc_files:
|
|
51
51
|
- README.markdown
|
52
52
|
files:
|
53
53
|
- Manifest
|
54
|
+
- nbproject/private/private.xml
|
54
55
|
- nbproject/private/rake-d.txt
|
55
56
|
- nbproject/project.xml
|
56
57
|
- nbproject/project.properties
|
@@ -65,6 +66,7 @@ files:
|
|
65
66
|
- spec/images/people.jpg
|
66
67
|
- spec/images/water.JPG
|
67
68
|
- spec/reduced/fam.png
|
69
|
+
- spec/reduced/add.png
|
68
70
|
- bin/smusher
|
69
71
|
- Rakefile
|
70
72
|
- README.markdown
|