image_size 3.0.1 → 3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9caeef6f83a5e285b9925268a389b46b2d15b6def554e0480c3b4105868022e8
4
- data.tar.gz: b1933e6c5d7fdc6686d8fe15082a64d39b76433aa659fc203c6d09c0ed937b86
3
+ metadata.gz: b0873a78a9fb9f84f07d0389071379dda288330bd38ee7516b442ffde85a3af8
4
+ data.tar.gz: 0b9fffd2311efa1c24379686821289951a4cd2ec895c27325148a886a24ff57b
5
5
  SHA512:
6
- metadata.gz: be6a77d33b518ca07842b3b1d4bc8793949b0fb09ede5bc46c6753f7bd51255ee078f34714c851010b0b43df9ce32e2d52a236f990155ad5dd056fd5cc297214
7
- data.tar.gz: d63e52caaa020d1b26e573a06d74b309f154542a82f7539fcb5c44d8ea7df7d44b5fbb54e51b502fe05e8e42e4191c8b0e8281f3d169a01717355016fa1fd9e5
6
+ metadata.gz: f6dede99002af9b9fc32f9776e42019079abcd846370c06b2aeee812a73c9ec46dcb6c703d1ae454f807d532c1d6b740aabb999892a6ef610cd17311f6a9a7f0
7
+ data.tar.gz: 819d8a3b7797b1f12b59eb608ffdeda9338314a923ca54711143832685853ed36b9ae8d165fcfa242ce4e1d72aecd5a03bd11714aa7aee3b464722ea8bb4688f
@@ -19,8 +19,10 @@ jobs:
19
19
  - '2.6'
20
20
  - '2.7'
21
21
  - '3.0'
22
+ - '3.1'
22
23
  - jruby-9.1
23
24
  - jruby-9.2
25
+ - jruby-9.3
24
26
  fail-fast: false
25
27
  steps:
26
28
  - uses: actions/checkout@v2
@@ -50,6 +52,7 @@ jobs:
50
52
  - '2.6'
51
53
  - '2.7'
52
54
  - '3.0'
55
+ - '3.1'
53
56
  fail-fast: false
54
57
  steps:
55
58
  - uses: actions/checkout@v2
@@ -58,12 +61,3 @@ jobs:
58
61
  ruby-version: "${{ matrix.ruby }}"
59
62
  bundler-cache: true
60
63
  - run: bundle exec rspec --format documentation
61
- rubocop:
62
- runs-on: ubuntu-latest
63
- steps:
64
- - uses: actions/checkout@v2
65
- - uses: ruby/setup-ruby@v1
66
- with:
67
- ruby-version: '3.0'
68
- bundler-cache: true
69
- - run: bundle exec rubocop
@@ -0,0 +1,16 @@
1
+ name: rubocop
2
+ on:
3
+ push:
4
+ pull_request:
5
+ schedule:
6
+ - cron: 45 4 * * 3
7
+ jobs:
8
+ rubocop:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v2
12
+ - uses: ruby/setup-ruby@v1
13
+ with:
14
+ ruby-version: '3.1'
15
+ bundler-cache: true
16
+ - run: bundle exec rubocop
data/.rubocop.yml CHANGED
@@ -53,6 +53,9 @@ Style/EmptyCaseCondition:
53
53
  Style/Encoding:
54
54
  Enabled: false
55
55
 
56
+ Style/FileRead:
57
+ Enabled: false
58
+
56
59
  Style/HashEachMethods:
57
60
  Enabled: true
58
61
 
@@ -77,6 +80,9 @@ Style/ParallelAssignment:
77
80
  Style/SafeNavigation:
78
81
  Enabled: false
79
82
 
83
+ Style/SlicingWithRange:
84
+ Enabled: false
85
+
80
86
  Style/TrailingCommaInArrayLiteral:
81
87
  EnforcedStyleForMultiline: comma
82
88
 
data/.rubocop_todo.yml CHANGED
@@ -9,17 +9,17 @@
9
9
  # Offense count: 8
10
10
  # Configuration parameters: IgnoredMethods.
11
11
  Metrics/AbcSize:
12
- Max: 43
12
+ Enabled: false
13
13
 
14
14
  # Offense count: 5
15
15
  # Configuration parameters: IgnoredMethods.
16
16
  Metrics/CyclomaticComplexity:
17
- Max: 21
17
+ Enabled: false
18
18
 
19
19
  # Offense count: 2
20
20
  # Configuration parameters: IgnoredMethods.
21
21
  Metrics/PerceivedComplexity:
22
- Max: 21
22
+ Enabled: false
23
23
 
24
24
  # Offense count: 8
25
25
  # Cop supports --auto-correct.
data/CHANGELOG.markdown CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## unreleased
4
4
 
5
+ ## v3.1.0 (2022-09-17)
6
+
7
+ * Document experimental fetching from http server [#18](https://github.com/toy/image_size/issues/18) [@toy](https://github.com/toy)
8
+ * Improve experimental fetching of image meta from http server by reading only required amount of data when server does not support range header [@toy](https://github.com/toy)
9
+
10
+ ## v3.0.2 (2022-05-19)
11
+
12
+ * Fix handling empty files [#20](https://github.com/toy/image_size/issues/20) [@toy](https://github.com/toy)
13
+
5
14
  ## v3.0.1 (2021-10-21)
6
15
 
7
16
  * Fix reading file chunks starting after EOF and reading chunks non-consecutively [toy/image_optim_rails#12](https://github.com/toy/image_optim_rails/issues/12) [@toy](https://github.com/toy)
@@ -11,6 +20,7 @@
11
20
  * Read only required chunks of data for files and seekable IOs [@toy](https://github.com/toy)
12
21
  * Raise `FormatError` whenever reading data returns less data than expected [#12](https://github.com/toy/image_size/issues/12) [@toy](https://github.com/toy)
13
22
  * Add `w`/`width` and `h`/`height` accessors to `Size` [@toy](https://github.com/toy)
23
+ * Experimental efficient fetching of image meta from http server supporting range [@toy](https://github.com/toy)
14
24
 
15
25
  ## v2.1.2 (2021-08-21)
16
26
 
data/README.markdown CHANGED
@@ -1,5 +1,6 @@
1
1
  [![Gem Version](https://img.shields.io/gem/v/image_size?logo=rubygems)](https://rubygems.org/gems/image_size)
2
2
  [![Build Status](https://img.shields.io/github/workflow/status/toy/image_size/check/master?logo=github)](https://github.com/toy/image_size/actions/workflows/check.yml)
3
+ [![Rubocop](https://img.shields.io/github/workflow/status/toy/image_size/rubocop/master?label=rubocop&logo=rubocop)](https://github.com/toy/image_size/actions/workflows/rubocop.yml)
3
4
 
4
5
  # image_size
5
6
 
@@ -17,7 +18,7 @@ gem install image_size
17
18
  Add to your `Gemfile`:
18
19
 
19
20
  ```ruby
20
- gem 'image_size', '~> 2.0'
21
+ gem 'image_size', '~> 3.0'
21
22
  ```
22
23
 
23
24
  ## Usage
@@ -53,7 +54,7 @@ require 'image_size'
53
54
  image_size = ImageSize.new(ARGF)
54
55
  ```
55
56
 
56
- Works with `open-uri` if needed:
57
+ Works with `open-uri`, see [experimental HTTP server interface below](#experimental-fetch-image-meta-from-http-server):
57
58
 
58
59
  ```ruby
59
60
  require 'image_size'
@@ -89,9 +90,58 @@ File.open('spec/images/jpeg/436x429.jpeg', 'rb') do |fh|
89
90
  end
90
91
  ```
91
92
 
93
+ ### Experimental: fetch image meta from HTTP server
94
+
95
+ If server recognises Range header, only needed chunks will be fetched even for TIFF images, otherwise required amount
96
+ of data will be fetched, in most cases first few kilobytes (TIFF images is an exception).
97
+
98
+ ```ruby
99
+ require 'image_size'
100
+ require 'image_size/uri_reader'
101
+
102
+ url = 'http://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_1350692_33_images.jpg'
103
+ p ImageSize.url(url).size
104
+ ```
105
+
106
+ This interface is as fast as dedicated gem fastimage for images with meta information in the header:
107
+
108
+ ```ruby
109
+ url = 'http://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_1350692_33_images.jpg'
110
+ puts Benchmark.measure{ p FastImage.size(url) }
111
+ ```
112
+ ```
113
+ [9545, 6623]
114
+ 0.004176 0.001974 0.006150 ( 0.282889)
115
+ ```
116
+ ```ruby
117
+ puts Benchmark.measure{ p ImageSize.url(url).size }
118
+ ```
119
+ ```
120
+ [9545, 6623]
121
+ 0.005604 0.001406 0.007010 ( 0.238629)
122
+ ```
123
+
124
+ And considerably faster for images with meta information at the end of file:
125
+
126
+ ```ruby
127
+ url = "https://upload.wikimedia.org/wikipedia/commons/c/c7/Curiosity%27s_Vehicle_System_Test_Bed_%28VSTB%29_Rover_%28PIA15876%29.tif"
128
+ puts Benchmark.measure{ p FastImage.size(url) }
129
+ ```
130
+ ```
131
+ [7360, 4912]
132
+ 0.331284 0.247295 0.578579 ( 6.027051)
133
+ ```
134
+ ```ruby
135
+ puts Benchmark.measure{ p ImageSize.url(url).size }
136
+ ```
137
+ ```
138
+ [7360, 4912]
139
+ 0.006247 0.001045 0.007292 ( 0.197631)
140
+ ```
141
+
92
142
  ## Licence
93
143
 
94
144
  This code is free to use under the terms of the [Ruby's licence](LICENSE.txt).
95
145
 
96
146
  Original author: Keisuke Minami <keisuke@rccn.com>.\
97
- Further development 2010-2021 Ivan Kuchin https://github.com/toy/image_size
147
+ Further development 2010-2022 Ivan Kuchin https://github.com/toy/image_size
data/image_size.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'image_size'
5
- s.version = '3.0.1'
5
+ s.version = '3.1.0'
6
6
  s.summary = %q{Measure image size using pure Ruby}
7
7
  s.description = %q{Measure following file dimensions: apng, bmp, cur, gif, ico, j2c, jp2, jpeg, jpx, mng, pam, pbm, pcx, pgm, png, ppm, psd, svg, swf, tiff, webp, xbm, xpm}
8
8
  s.homepage = "https://github.com/toy/#{s.name}"
@@ -22,8 +22,8 @@ Gem::Specification.new do |s|
22
22
  s.require_paths = %w[lib]
23
23
 
24
24
  s.add_development_dependency 'rspec', '~> 3.0'
25
- if RUBY_VERSION >= '2.4'
26
- s.add_development_dependency 'rubocop', '~> 1.0'
25
+ if RUBY_VERSION >= '2.5'
26
+ s.add_development_dependency 'rubocop', '~> 1.22'
27
27
  s.add_development_dependency 'rubocop-rspec', '~> 2.0'
28
28
  end
29
29
  end
@@ -6,65 +6,103 @@ require 'image_size/chunky_reader'
6
6
  require 'net/https'
7
7
  require 'uri'
8
8
 
9
- # This is a hacky experiment and not part of public API
9
+ # Experimental, not yet part of stable API
10
10
  #
11
- # It adds ability to fetch size of image from http server while downloading only
12
- # needed chunks if the server recognises Range header
11
+ # It adds ability to fetch image meta from HTTP server while downloading only
12
+ # needed chunks if the server recognises Range header, otherwise fetches only
13
+ # required amount of data
13
14
  class ImageSize
14
- class URIReader # :nodoc:
15
- include ChunkyReader
16
-
17
- def initialize(uri, redirects = 5)
18
- if !@http || @http.address != uri.host || @http.port != uri.port
19
- @http.finish if @http
20
- @http = Net::HTTP.new(uri.host, uri.port)
21
- @http.use_ssl = true if uri.scheme == 'https'
22
- @http.start
23
- end
15
+ module URIReader # :nodoc:
16
+ module HTTPChunkyReader # :nodoc:
17
+ include ChunkyReader
24
18
 
25
- @request_uri = uri.request_uri
26
- response = request_chunk(0)
19
+ def chunk_range_header(i)
20
+ { 'Range' => "bytes=#{chunk_size * i}-#{(chunk_size * (i + 1)) - 1}" }
21
+ end
22
+ end
27
23
 
28
- case response
29
- when Net::HTTPRedirection
30
- raise "Too many redirects: #{response['location']}" unless redirects > 0
24
+ class BodyReader # :nodoc:
25
+ include ChunkyReader
31
26
 
32
- initialize(uri + response['location'], redirects - 1)
33
- when Net::HTTPOK
34
- @body = response.body
35
- when Net::HTTPPartialContent
36
- @chunks = { 0 => response.body }
37
- else
38
- raise "Unexpected response: #{response}"
27
+ def initialize(response)
28
+ @body = String.new
29
+ @body_reader = response.to_enum(:read_body)
39
30
  end
40
- end
41
31
 
42
- def [](offset, length)
43
- if @body
32
+ def [](offset, length)
33
+ if @body_reader
34
+ begin
35
+ @body << @body_reader.next while @body.length < offset + length
36
+ rescue StopIteration, IOError
37
+ @body_reader = nil
38
+ end
39
+ end
40
+
44
41
  @body[offset, length]
45
- else
46
- super
47
42
  end
48
43
  end
49
44
 
50
- def chunk(i)
51
- unless @chunks.key?(i)
52
- response = request_chunk(i)
53
- case response
54
- when Net::HTTPPartialContent
55
- @chunks[i] = response.body
56
- else
57
- raise "Unexpected response: #{response}"
58
- end
45
+ class RangeReader # :nodoc:
46
+ include HTTPChunkyReader
47
+
48
+ def initialize(http, request_uri, chunk0)
49
+ @http = http
50
+ @request_uri = request_uri
51
+ @chunks = { 0 => chunk0 }
59
52
  end
60
53
 
61
- @chunks[i]
54
+ def chunk(i)
55
+ unless @chunks.key?(i)
56
+ response = @http.get(@request_uri, chunk_range_header(i))
57
+ case response
58
+ when Net::HTTPPartialContent
59
+ @chunks[i] = response.body
60
+ else
61
+ raise "Unexpected response: #{response}"
62
+ end
63
+ end
64
+
65
+ @chunks[i]
66
+ end
62
67
  end
63
68
 
64
- private
69
+ class << self
70
+ include HTTPChunkyReader
71
+
72
+ def open(uri, max_redirects = 5)
73
+ http = nil
74
+ (max_redirects + 1).times do
75
+ unless http && http.address == uri.host && http.port == uri.port
76
+ http.finish if http
77
+
78
+ http = Net::HTTP.new(uri.host, uri.port)
79
+ http.use_ssl = true if uri.scheme == 'https'
80
+ http.start
81
+ end
65
82
 
66
- def request_chunk(i)
67
- @http.get(@request_uri, 'Range' => "bytes=#{chunk_size * i}-#{(chunk_size * (i + 1)) - 1}")
83
+ response = http.request_get(uri.request_uri, chunk_range_header(0)) do |response_with_unread_body|
84
+ case response_with_unread_body
85
+ when Net::HTTPOK
86
+ return yield BodyReader.new(response_with_unread_body)
87
+ end
88
+ end
89
+
90
+ case response
91
+ when Net::HTTPRedirection
92
+ uri += response['location']
93
+ when Net::HTTPPartialContent
94
+ return yield RangeReader.new(http, uri.request_uri, response.body)
95
+ when Net::HTTPRequestedRangeNotSatisfiable
96
+ return yield StringReader.new('')
97
+ else
98
+ raise "Unexpected response: #{response}"
99
+ end
100
+ end
101
+
102
+ raise "Too many redirects: #{uri}"
103
+ ensure
104
+ http.finish if http.started?
105
+ end
68
106
  end
69
107
  end
70
108
 
@@ -72,7 +110,7 @@ class ImageSize
72
110
  class << self
73
111
  def open_with_uri(input, &block)
74
112
  if input.is_a?(URI)
75
- yield URIReader.new(input)
113
+ URIReader.open(input, &block)
76
114
  else
77
115
  open_without_uri(input, &block)
78
116
  end
data/lib/image_size.rb CHANGED
@@ -76,6 +76,7 @@ private
76
76
  def detect_format(ir)
77
77
  head = ir[0, 1024]
78
78
  case
79
+ when head.nil? || head.empty? then nil
79
80
  when head[0, 6] =~ /GIF8[79]a/ then :gif
80
81
  when head[0, 8] == "\211PNG\r\n\032\n" then detect_png_type(ir)
81
82
  when head[0, 8] == "\212MNG\r\n\032\n" then :mng
@@ -56,9 +56,11 @@ describe ImageSize::ChunkyReader do
56
56
  offsets.each do |offset_b|
57
57
  length = offset_b - offset
58
58
  expect(reader[offset, length]).to eq(data[offset, length]),
59
- "for offset #{offset} and length #{length}\n"\
60
- "expected: #{data[offset, length].inspect}\n"\
61
- " got: #{reader[offset, length].inspect}"
59
+ [
60
+ "for offset #{offset} and length #{length}",
61
+ "expected: #{data[offset, length].inspect}",
62
+ " got: #{reader[offset, length].inspect}",
63
+ ].join("\n")
62
64
  end
63
65
  end
64
66
  end
@@ -7,31 +7,20 @@ require 'image_size/uri_reader'
7
7
 
8
8
  require 'tempfile'
9
9
  require 'shellwords'
10
- require 'webrick'
10
+
11
+ require 'test_server'
11
12
 
12
13
  describe ImageSize do
13
14
  before :all do
14
- @server = WEBrick::HTTPServer.new({
15
- :Logger => WEBrick::Log.new(StringIO.new),
16
- :AccessLog => [],
17
- :BindAddress => '127.0.0.1',
18
- :Port => 0, # get the next available port
19
- :DocumentRoot => '.',
20
- })
21
- @server_thread = Thread.new{ @server.start }
22
- @server_base_url = URI("http://127.0.0.1:#{@server.config[:Port]}/")
15
+ @server = TestServer.new
23
16
  end
24
17
 
25
18
  after :all do
26
- @server.shutdown
27
- @server_thread.join
19
+ @server.finish
28
20
  end
29
21
 
30
- max_filesize = 16_384
31
-
32
- (Dir['spec/images/*/*.*'] + [__FILE__[%r{spec/.+?\z}]]).each do |path|
33
- filesize = File.size(path)
34
- warn "#{path} is too big #{filesize} (max #{max_filesize})" if filesize > max_filesize
22
+ Dir['spec/**/*'].each do |path|
23
+ next unless File.file?(path)
35
24
 
36
25
  describe "for #{path}" do
37
26
  let(:name){ File.basename(path) }
@@ -49,6 +38,15 @@ describe ImageSize do
49
38
  }
50
39
  end
51
40
  let(:file_data){ File.open(path, 'rb', &:read) }
41
+ let(:file_size){ file_data.length }
42
+
43
+ before do
44
+ max_file_size = 16_384
45
+
46
+ if file_size > max_file_size
47
+ raise "reduce resulting gem size, #{path} is too big (#{file_size} > #{max_file_size})"
48
+ end
49
+ end
52
50
 
53
51
  context 'given as data' do
54
52
  it 'gets format and dimensions' do
@@ -65,7 +63,11 @@ describe ImageSize do
65
63
  image_size = ImageSize.new(io)
66
64
  expect(image_size).to have_attributes(attributes)
67
65
  expect(io).not_to be_closed
68
- expect(io.pos).to_not be_zero
66
+ if file_size.zero?
67
+ expect(io.pos).to be_zero
68
+ else
69
+ expect(io.pos).to_not be_zero
70
+ end
69
71
  io.rewind
70
72
  expect(io.read).to eq(file_data)
71
73
  end
@@ -102,7 +104,11 @@ describe ImageSize do
102
104
  image_size = ImageSize.new(io)
103
105
  expect(image_size).to have_attributes(attributes)
104
106
  expect(io).not_to be_closed
105
- expect(io.pos).to_not be_zero
107
+ if file_size.zero?
108
+ expect(io.pos).to be_zero
109
+ else
110
+ expect(io.pos).to_not be_zero
111
+ end
106
112
  io.rewind
107
113
  expect(io.read).to eq(file_data)
108
114
  end
@@ -117,9 +123,54 @@ describe ImageSize do
117
123
  end
118
124
 
119
125
  context 'fetching from webserver' do
120
- it 'gets format and dimensions' do
121
- image_size = ImageSize.url(@server_base_url + path)
122
- expect(image_size).to have_attributes(attributes)
126
+ let(:file_url){ @server.base_url + path }
127
+
128
+ context 'supporting range' do
129
+ context 'without redirects' do
130
+ it 'gets format and dimensions' do
131
+ image_size = ImageSize.url(file_url)
132
+ expect(image_size).to have_attributes(attributes)
133
+ end
134
+ end
135
+
136
+ context 'with redirects' do
137
+ it 'gets format and dimensions' do
138
+ image_size = ImageSize.url("#{file_url}?redirect=5")
139
+ expect(image_size).to have_attributes(attributes)
140
+ end
141
+ end
142
+
143
+ context 'with too many redirects' do
144
+ it 'gets format and dimensions' do
145
+ expect do
146
+ ImageSize.url("#{file_url}?redirect=6")
147
+ end.to raise_error(/Too many redirects/)
148
+ end
149
+ end
150
+ end
151
+
152
+ context 'not supporting range' do
153
+ context 'without redirects' do
154
+ it 'gets format and dimensions' do
155
+ image_size = ImageSize.url("#{file_url}?ignore_range")
156
+ expect(image_size).to have_attributes(attributes)
157
+ end
158
+ end
159
+
160
+ context 'with redirects' do
161
+ it 'gets format and dimensions' do
162
+ image_size = ImageSize.url("#{file_url}?ignore_range&redirect=5")
163
+ expect(image_size).to have_attributes(attributes)
164
+ end
165
+ end
166
+
167
+ context 'with too many redirects' do
168
+ it 'gets format and dimensions' do
169
+ expect do
170
+ ImageSize.url("#{file_url}?ignore_range&redirect=6")
171
+ end.to raise_error(/Too many redirects/)
172
+ end
173
+ end
123
174
  end
124
175
  end
125
176
  end
data/spec/images/empty ADDED
File without changes
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'webrick'
4
+
5
+ class TestServer
6
+ attr_reader :base_url
7
+
8
+ def initialize(host = '127.0.0.1')
9
+ server_options = {
10
+ :Logger => WEBrick::Log.new(StringIO.new),
11
+ :AccessLog => [],
12
+ :BindAddress => host,
13
+ :Port => 0, # get the next available port
14
+ :DocumentRoot => '.',
15
+ :RequestCallback => proc do |req, res|
16
+ redirect = req.query['redirect'].to_i
17
+ if redirect > 0
18
+ res.set_redirect(
19
+ WEBrick::HTTPStatus::TemporaryRedirect,
20
+ [
21
+ req.request_uri.port == @base_url.port ? @second_url : @base_url,
22
+ req.request_uri.request_uri,
23
+ "?#{encode_www_form(req.query.merge('redirect' => redirect - 1))}",
24
+ ].inject(:+)
25
+ )
26
+ end
27
+
28
+ req.header.delete('range') if req.query['ignore_range']
29
+ end,
30
+ }
31
+
32
+ @server = WEBrick::HTTPServer.new(server_options)
33
+ @server.listen(host, 0) # listen on second port
34
+
35
+ @base_url = URI("http://#{host}:#{@server.listeners[0].addr[1]}/")
36
+ @second_url = URI("http://#{host}:#{@server.listeners[1].addr[1]}/")
37
+
38
+ @thread = Thread.new{ @server.start }
39
+ end
40
+
41
+ def finish
42
+ @server.shutdown
43
+ @thread.join
44
+ end
45
+
46
+ private
47
+
48
+ if URI.respond_to?(:encode_www_form)
49
+ def encode_www_form(h)
50
+ URI.encode_www_form(h)
51
+ end
52
+ else
53
+ require 'cgi'
54
+
55
+ def encode_www_form(h)
56
+ h.map do |k, v|
57
+ "#{CGI.escape(k)}=#{CGI.escape(v.to_s)}"
58
+ end.join('&')
59
+ end
60
+ end
61
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: image_size
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keisuke Minami
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-10-21 00:00:00.000000000 Z
12
+ date: 2022-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '1.0'
34
+ version: '1.22'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '1.0'
41
+ version: '1.22'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rubocop-rspec
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -61,6 +61,7 @@ extensions: []
61
61
  extra_rdoc_files: []
62
62
  files:
63
63
  - ".github/workflows/check.yml"
64
+ - ".github/workflows/rubocop.yml"
64
65
  - ".gitignore"
65
66
  - ".rubocop.yml"
66
67
  - ".rubocop_todo.yml"
@@ -85,6 +86,7 @@ files:
85
86
  - spec/images/bmp/v3-bottom2top.42x50.bmp
86
87
  - spec/images/bmp/v3-top2bottom.42x50.bmp
87
88
  - spec/images/cur/32x256.cur
89
+ - spec/images/empty
88
90
  - spec/images/gif/668x481.gif
89
91
  - spec/images/ico/32x256.ico
90
92
  - spec/images/jp2/163x402.jp2
@@ -118,13 +120,14 @@ files:
118
120
  - spec/images/xbm/crlf.16x32.xbm
119
121
  - spec/images/xpm/24x32.xpm
120
122
  - spec/images/xpm/crlf.24x32.xpm
123
+ - spec/test_server.rb
121
124
  homepage: https://github.com/toy/image_size
122
125
  licenses:
123
126
  - Ruby
124
127
  metadata:
125
128
  bug_tracker_uri: https://github.com/toy/image_size/issues
126
129
  changelog_uri: https://github.com/toy/image_size/blob/master/CHANGELOG.markdown
127
- documentation_uri: https://www.rubydoc.info/gems/image_size/3.0.1
130
+ documentation_uri: https://www.rubydoc.info/gems/image_size/3.1.0
128
131
  source_code_uri: https://github.com/toy/image_size
129
132
  post_install_message:
130
133
  rdoc_options: []
@@ -141,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
144
  - !ruby/object:Gem::Version
142
145
  version: '0'
143
146
  requirements: []
144
- rubygems_version: 3.2.29
147
+ rubygems_version: 3.3.11
145
148
  signing_key:
146
149
  specification_version: 4
147
150
  summary: Measure image size using pure Ruby
@@ -154,6 +157,7 @@ test_files:
154
157
  - spec/images/bmp/v3-bottom2top.42x50.bmp
155
158
  - spec/images/bmp/v3-top2bottom.42x50.bmp
156
159
  - spec/images/cur/32x256.cur
160
+ - spec/images/empty
157
161
  - spec/images/gif/668x481.gif
158
162
  - spec/images/ico/32x256.ico
159
163
  - spec/images/jp2/163x402.jp2
@@ -187,3 +191,4 @@ test_files:
187
191
  - spec/images/xbm/crlf.16x32.xbm
188
192
  - spec/images/xpm/24x32.xpm
189
193
  - spec/images/xpm/crlf.24x32.xpm
194
+ - spec/test_server.rb