httpthumbnailer-client 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +6 -6
- data/README.md +23 -4
- data/VERSION +1 -1
- data/bin/httpthumbnailer-client +9 -2
- data/httpthumbnailer-client.gemspec +3 -2
- data/lib/httpthumbnailer-client.rb +56 -9
- data/spec/identify_spec.rb +33 -0
- data/spec/thumbnail_spec.rb +9 -0
- data/spec/thumbnails_spec.rb +14 -0
- metadata +4 -3
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../httpthumbnailer
|
3
3
|
specs:
|
4
|
-
httpthumbnailer (1.
|
4
|
+
httpthumbnailer (1.1.0)
|
5
5
|
rmagick (~> 2)
|
6
|
-
unicorn-cuba-base (~> 1.
|
6
|
+
unicorn-cuba-base (~> 1.1)
|
7
7
|
|
8
8
|
PATH
|
9
9
|
remote: ../unicorn-cuba-base
|
10
10
|
specs:
|
11
|
-
unicorn-cuba-base (1.
|
11
|
+
unicorn-cuba-base (1.1.0)
|
12
12
|
cli (~> 1.1.0)
|
13
13
|
cuba (~> 3.0)
|
14
14
|
facter (~> 1.6.11)
|
@@ -42,13 +42,13 @@ GEM
|
|
42
42
|
rake
|
43
43
|
rdoc
|
44
44
|
json (1.6.1)
|
45
|
-
kgio (2.8.
|
45
|
+
kgio (2.8.1)
|
46
46
|
multipart-parser (0.1.1)
|
47
47
|
rack (1.5.2)
|
48
|
-
raindrops (0.
|
48
|
+
raindrops (0.12.0)
|
49
49
|
rake (10.0.4)
|
50
50
|
rdoc (3.9.4)
|
51
|
-
rmagick (2.13.
|
51
|
+
rmagick (2.13.2)
|
52
52
|
rspec (2.13.0)
|
53
53
|
rspec-core (~> 2.13.0)
|
54
54
|
rspec-expectations (~> 2.13.0)
|
data/README.md
CHANGED
@@ -23,8 +23,10 @@ data = File.read('image_file.jpg')
|
|
23
23
|
|
24
24
|
# generate single thumbnail from image data (single thumbnail API)
|
25
25
|
thumbnail = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail(data, 'crop', 60, 30, 'jpeg')
|
26
|
-
thumbnail.mime_type
|
27
|
-
thumbnail.
|
26
|
+
thumbnail.mime_type # => 'image/jpeg'
|
27
|
+
thumbnail.width # => 60
|
28
|
+
thumbnail.height # => 30
|
29
|
+
thumbnail.data # => 60x30 thumbnail JPEG data String
|
28
30
|
|
29
31
|
# generate set of thumbnails from image data (multipart API)
|
30
32
|
thumbnails = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail(data) do
|
@@ -34,15 +36,29 @@ thumbnails = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail(data)
|
|
34
36
|
end
|
35
37
|
|
36
38
|
thumbnails[0].mime_type # => 'image/jpeg'
|
39
|
+
thumbnails[0].width # => 60
|
40
|
+
thumbnails[0].height # => 30
|
37
41
|
thumbnails[0].data # => 60x30 thumbnail JPEG data String
|
38
42
|
|
39
43
|
thumbnails[1].mime_type # => 'image/png'
|
44
|
+
thumbnails[1].width # => 80
|
45
|
+
thumbnails[1].height # => 80
|
40
46
|
thumbnails[1].data # => 80x80 thumbnail PNG data String
|
41
47
|
|
42
48
|
thumbnails[2].mime_type # => 'image/png'
|
49
|
+
thumbnails[2].width # => 40
|
50
|
+
thumbnails[2].height # => 40
|
43
51
|
thumbnails[2].data # => 40x40 thumbnail PNG data String
|
44
52
|
|
45
53
|
thumbnails.input_mime_type # => 'image/jpeg' - detected input image format by API server (content based)
|
54
|
+
thumbnails.input_width # => 800 - detected input image width by API server (content based)
|
55
|
+
thumbnails.input_height # => 600 - detected input image height by API server (content based)
|
56
|
+
|
57
|
+
# just identify the image
|
58
|
+
id = HTTPThumbnailerClient.new('http://localhost:3100').identify(data)
|
59
|
+
id.mime_type # => 'image/jpeg'
|
60
|
+
id.width # => 800
|
61
|
+
id.height # => 600
|
46
62
|
```
|
47
63
|
|
48
64
|
For more details see RSpec for [single thumbnail API](http://github.com/jpastuszek/httpthumbnailer-client/blob/master/spec/thumbnail_spec.rb) and [multipart API](http://github.com/jpastuszek/httpthumbnailer-client/blob/master/spec/thumbnails_spec.rb).
|
@@ -55,11 +71,14 @@ This gem provides `httpthumbnailer-client` command line tool that can be used to
|
|
55
71
|
# start thumbnailing server (to stop: kill `cat httpthumbnailer.pid`)
|
56
72
|
httpthumbnailer
|
57
73
|
|
74
|
+
# identify image
|
75
|
+
cat image.jpg | httpthumbnailer-client
|
76
|
+
|
58
77
|
# thumbnail to standard output
|
59
|
-
cat
|
78
|
+
cat image.jpg | httpthumbnailer-client -t crop,100,200,png > thumbnail.png
|
60
79
|
|
61
80
|
# generate multiple thumbnails
|
62
|
-
cat
|
81
|
+
cat image.jpg | httpthumbnailer-client -t crop,100,200,jpeg,quality:100 -t pad,200,200,png thumbnail1.jpg thumbnail2.png
|
63
82
|
```
|
64
83
|
|
65
84
|
## Contributing to HTTP Thubnailer Client
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.1.0
|
data/bin/httpthumbnailer-client
CHANGED
@@ -34,8 +34,7 @@ settings = CLI.new do
|
|
34
34
|
default: 3100
|
35
35
|
options :thumbnail,
|
36
36
|
short: :t,
|
37
|
-
description: 'thumbnail specification in format <operation type>,<width>,<height>,<format>[,<option key>:<option value>]* - see httpthumbnailer documenation for more information'
|
38
|
-
required: true
|
37
|
+
description: 'thumbnail specification in format <operation type>,<width>,<height>,<format>[,<option key>:<option value>]* - see httpthumbnailer documenation for more information'
|
39
38
|
arguments :output_file_name,
|
40
39
|
short: :f,
|
41
40
|
description: 'file name to store resulting thumbnail; when multiple --thumbail options are used the same number of output file names should be specified; use "-" to write to STDOUT',
|
@@ -49,6 +48,14 @@ end
|
|
49
48
|
|
50
49
|
thumbnailer = HTTPThumbnailerClient.new("http://#{settings.host}:#{settings.port}")
|
51
50
|
|
51
|
+
if settings.thumbnail.empty?
|
52
|
+
id = thumbnailer.identify(settings.stdin.read)
|
53
|
+
id.instance_variables.each do |iv|
|
54
|
+
puts "#{iv.to_s.delete '@'}: #{id.instance_variable_get iv}"
|
55
|
+
end
|
56
|
+
exit
|
57
|
+
end
|
58
|
+
|
52
59
|
thumbnails = if settings.thumbnail.length == 1
|
53
60
|
[thumbnailer.thumbnail(settings.stdin.read, *settings.thumbnail.first)]
|
54
61
|
else
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "httpthumbnailer-client"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jakub Pastuszek"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-09-11"
|
13
13
|
s.description = "Thumbnails images using httpthumbniler server"
|
14
14
|
s.email = "jpastuszek@gmail.com"
|
15
15
|
s.executables = ["httpthumbnailer-client"]
|
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
|
|
32
32
|
"httpthumbnailer-client.gemspec",
|
33
33
|
"lib/httpthumbnailer-client.rb",
|
34
34
|
"spec/httpthumbnailer-client_spec.rb",
|
35
|
+
"spec/identify_spec.rb",
|
35
36
|
"spec/spec_helper.rb",
|
36
37
|
"spec/support/test-large.jpg",
|
37
38
|
"spec/support/test.jpg",
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'httpclient'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'json'
|
2
4
|
require 'multipart_parser/reader'
|
3
5
|
|
4
6
|
class HTTPThumbnailerClient
|
@@ -97,16 +99,40 @@ class HTTPThumbnailerClient
|
|
97
99
|
end
|
98
100
|
|
99
101
|
class Thumbnail
|
100
|
-
def initialize(mime_type, data)
|
102
|
+
def initialize(mime_type, width, height, data)
|
101
103
|
@mime_type = mime_type
|
102
104
|
@data = data
|
105
|
+
|
106
|
+
# added to thumbnailer v1.1.0 so may be nil for older server
|
107
|
+
@width = width.to_i if width
|
108
|
+
@height = height.to_i if height
|
103
109
|
end
|
104
110
|
|
105
|
-
attr_reader :mime_type
|
111
|
+
attr_reader :mime_type
|
112
|
+
attr_reader :width
|
113
|
+
attr_reader :height
|
114
|
+
attr_reader :data
|
106
115
|
end
|
107
116
|
|
108
|
-
module
|
117
|
+
module ThumbnailsInputIdentifyMeta
|
109
118
|
attr_accessor :input_mime_type
|
119
|
+
|
120
|
+
# added to thumbnailer v1.1.0 so may be nil for older server
|
121
|
+
attr_accessor :input_width
|
122
|
+
attr_accessor :input_height
|
123
|
+
end
|
124
|
+
|
125
|
+
class ImageID
|
126
|
+
def initialize(body)
|
127
|
+
id = JSON.load(body)
|
128
|
+
@mime_type = id['mimeType']
|
129
|
+
@width = id['width']
|
130
|
+
@height = id['height']
|
131
|
+
end
|
132
|
+
|
133
|
+
attr_reader :mime_type
|
134
|
+
attr_reader :width
|
135
|
+
attr_reader :height
|
110
136
|
end
|
111
137
|
|
112
138
|
def initialize(server_url, options = {})
|
@@ -140,7 +166,7 @@ class HTTPThumbnailerClient
|
|
140
166
|
when 'text/plain'
|
141
167
|
raise error_for_status(response.status, response.body)
|
142
168
|
when /^image\//
|
143
|
-
Thumbnail.new(content_type, response.body)
|
169
|
+
Thumbnail.new(content_type, response.headers['X-Image-Width'], response.headers['X-Image-Height'], response.body)
|
144
170
|
when /^multipart\/mixed/
|
145
171
|
parts = []
|
146
172
|
parser = MultipartParser::Reader.new(MultipartParser::Reader.extract_boundary_value(content_type))
|
@@ -164,7 +190,7 @@ class HTTPThumbnailerClient
|
|
164
190
|
parts << error
|
165
191
|
end
|
166
192
|
when /^image\//
|
167
|
-
parts << Thumbnail.new(part_content_type, data)
|
193
|
+
parts << Thumbnail.new(part_content_type, part.headers['x-image-width'], part.headers['x-image-height'], data)
|
168
194
|
else
|
169
195
|
raise UnknownResponseType, part_content_type
|
170
196
|
end
|
@@ -178,16 +204,37 @@ class HTTPThumbnailerClient
|
|
178
204
|
raise UnknownResponseType, content_type
|
179
205
|
end
|
180
206
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
207
|
+
thumbnails.extend(ThumbnailsInputIdentifyMeta)
|
208
|
+
thumbnails.input_mime_type = response.header['X-Input-Image-Content-Type'].first unless response.header['X-Input-Image-Content-Type'].empty? # deprecated
|
209
|
+
thumbnails.input_mime_type = response.header['X-Input-Image-Mime-Type'].first unless response.header['X-Input-Image-Mime-Type'].empty?
|
210
|
+
thumbnails.input_width = response.header['X-Input-Image-Width'].first.to_i unless response.header['X-Input-Image-Width'].empty?
|
211
|
+
thumbnails.input_height = response.header['X-Input-Image-Height'].first.to_i unless response.header['X-Input-Image-Height'].empty?
|
185
212
|
|
186
213
|
return thumbnails
|
187
214
|
rescue HTTPClient::KeepAliveDisconnected
|
188
215
|
raise RemoteServerError, 'empty response'
|
189
216
|
end
|
190
217
|
|
218
|
+
def identify(data)
|
219
|
+
response = @client.request('PUT', "#{@server_url}/identify", nil, data, {'Content-Type' => 'image/autodetect'})
|
220
|
+
@client.reset_all unless @keep_alive
|
221
|
+
|
222
|
+
content_type = response.header['Content-Type'].last
|
223
|
+
|
224
|
+
image_id = case content_type
|
225
|
+
when 'text/plain'
|
226
|
+
raise error_for_status(response.status, response.body)
|
227
|
+
when 'application/json'
|
228
|
+
ImageID.new(response.body)
|
229
|
+
else
|
230
|
+
raise UnknownResponseType, content_type
|
231
|
+
end
|
232
|
+
|
233
|
+
return image_id
|
234
|
+
rescue HTTPClient::KeepAliveDisconnected
|
235
|
+
raise RemoteServerError, 'empty response'
|
236
|
+
end
|
237
|
+
|
191
238
|
def inspect
|
192
239
|
"#<#{self.class.name} server_url=#{server_url.inspect} keep_alive=#{keep_alive.inspect}>"
|
193
240
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe HTTPThumbnailerClient, 'identify API' do
|
4
|
+
before :all do
|
5
|
+
log = support_dir + 'server.log'
|
6
|
+
start_server(
|
7
|
+
"httpthumbnailer -f -d -l #{log}",
|
8
|
+
'/tmp/httpthumbnailer.pid',
|
9
|
+
log,
|
10
|
+
'http://localhost:3100/'
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
after :all do
|
15
|
+
stop_server('/tmp/httpthumbnailer.pid')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should return input image identification information' do
|
19
|
+
input_id = HTTPThumbnailerClient.new('http://localhost:3100').identify((support_dir + 'test.jpg').read)
|
20
|
+
input_id.mime_type.should == 'image/jpeg'
|
21
|
+
input_id.width.should == 509
|
22
|
+
input_id.height.should == 719
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'general error handling' do
|
26
|
+
it 'should raise HTTPThumbnailerClient::UnsupportedMediaTypeError error on unsupported media type error' do
|
27
|
+
lambda {
|
28
|
+
HTTPThumbnailerClient.new('http://localhost:3100').identify((support_dir + 'test.txt').read)
|
29
|
+
}.should raise_error HTTPThumbnailerClient::UnsupportedMediaTypeError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
data/spec/thumbnail_spec.rb
CHANGED
@@ -20,6 +20,9 @@ describe HTTPThumbnailerClient, 'single thumbnail API' do
|
|
20
20
|
|
21
21
|
thumbnail.should be_kind_of HTTPThumbnailerClient::Thumbnail
|
22
22
|
thumbnail.mime_type.should == 'image/jpeg'
|
23
|
+
thumbnail.width.should == 6
|
24
|
+
thumbnail.height.should == 3
|
25
|
+
|
23
26
|
i = identify(thumbnail.data)
|
24
27
|
i.format.should == 'JPEG'
|
25
28
|
i.width.should == 6
|
@@ -31,6 +34,12 @@ describe HTTPThumbnailerClient, 'single thumbnail API' do
|
|
31
34
|
thumbnail = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail((support_dir + 'test.jpg').read, 'crop', 6, 3, 'jpeg')
|
32
35
|
thumbnail.input_mime_type.should == 'image/jpeg'
|
33
36
|
end
|
37
|
+
|
38
|
+
it 'should provide input image size' do
|
39
|
+
thumbnail = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail((support_dir + 'test.jpg').read, 'crop', 6, 3, 'jpeg')
|
40
|
+
thumbnail.input_width.should == 509
|
41
|
+
thumbnail.input_height.should == 719
|
42
|
+
end
|
34
43
|
end
|
35
44
|
|
36
45
|
describe 'general error handling' do
|
data/spec/thumbnails_spec.rb
CHANGED
@@ -24,6 +24,8 @@ describe HTTPThumbnailerClient, 'multipart API' do
|
|
24
24
|
|
25
25
|
thumbs[0].should be_kind_of HTTPThumbnailerClient::Thumbnail
|
26
26
|
thumbs[0].mime_type.should == 'image/jpeg'
|
27
|
+
thumbs[0].width.should == 60
|
28
|
+
thumbs[0].height.should == 30
|
27
29
|
i = identify(thumbs[0].data)
|
28
30
|
i.format.should == 'JPEG'
|
29
31
|
i.width.should == 60
|
@@ -31,6 +33,8 @@ describe HTTPThumbnailerClient, 'multipart API' do
|
|
31
33
|
|
32
34
|
thumbs[1].should be_kind_of HTTPThumbnailerClient::Thumbnail
|
33
35
|
thumbs[1].mime_type.should == 'image/png'
|
36
|
+
thumbs[1].width.should == 80
|
37
|
+
thumbs[1].height.should == 80
|
34
38
|
i = identify(thumbs[1].data)
|
35
39
|
i.format.should == 'PNG'
|
36
40
|
i.width.should == 80
|
@@ -38,6 +42,8 @@ describe HTTPThumbnailerClient, 'multipart API' do
|
|
38
42
|
|
39
43
|
thumbs[2].should be_kind_of HTTPThumbnailerClient::Thumbnail
|
40
44
|
thumbs[2].mime_type.should == 'image/png'
|
45
|
+
thumbs[2].width.should == 40
|
46
|
+
thumbs[2].height.should == 40
|
41
47
|
i = identify(thumbs[2].data)
|
42
48
|
i.format.should == 'PNG'
|
43
49
|
i.width.should == 40
|
@@ -51,6 +57,14 @@ describe HTTPThumbnailerClient, 'multipart API' do
|
|
51
57
|
end
|
52
58
|
thumbs.input_mime_type.should == 'image/jpeg'
|
53
59
|
end
|
60
|
+
|
61
|
+
it 'should provide input image size' do
|
62
|
+
thumbs = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail((support_dir + 'test.jpg').read) do
|
63
|
+
thumbnail 'crop', 6, 3, 'jpeg'
|
64
|
+
end
|
65
|
+
thumbs.input_width.should == 509
|
66
|
+
thumbs.input_height.should == 719
|
67
|
+
end
|
54
68
|
end
|
55
69
|
|
56
70
|
describe 'returns HTTPThumbnailerClient::HTTPThumbnailerClientError object within set of returned thumbnails' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httpthumbnailer-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httpclient
|
@@ -226,6 +226,7 @@ files:
|
|
226
226
|
- httpthumbnailer-client.gemspec
|
227
227
|
- lib/httpthumbnailer-client.rb
|
228
228
|
- spec/httpthumbnailer-client_spec.rb
|
229
|
+
- spec/identify_spec.rb
|
229
230
|
- spec/spec_helper.rb
|
230
231
|
- spec/support/test-large.jpg
|
231
232
|
- spec/support/test.jpg
|
@@ -248,7 +249,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
248
249
|
version: '0'
|
249
250
|
segments:
|
250
251
|
- 0
|
251
|
-
hash:
|
252
|
+
hash: -4370277079170178883
|
252
253
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
253
254
|
none: false
|
254
255
|
requirements:
|