httpthumbnailer-client 1.0.0 → 1.1.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/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:
|