image_size 3.3.0 → 3.4.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 +4 -4
- data/.github/workflows/check.yml +2 -2
- data/.rubocop.yml +2 -32
- data/CHANGELOG.markdown +7 -0
- data/README.markdown +5 -4
- data/image_size.gemspec +3 -1
- data/lib/image_size/isobmff.rb +5 -5
- data/lib/image_size/media_types.rb +32 -0
- data/lib/image_size/uri.rb +3 -0
- data/lib/image_size/uri_reader.rb +1 -0
- data/lib/image_size.rb +25 -19
- data/spec/image_size/chunky_reader_spec.rb +1 -1
- data/spec/image_size/isobmff_spec.rb +44 -44
- data/spec/image_size_spec.rb +53 -17
- data/spec/test_server.rb +7 -6
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d88e4be6d69bedc0f976c9b73544a20ac08ab66d6b44ce1061d1374f9d2a9dc8
|
4
|
+
data.tar.gz: 5b2986943b8bbeb339d0c31d0a98c5847a1a86141d5e754adaf0bd01e3d8d60f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b75df7c37cbcca0886eade3e47b082cde0468331c954d0605130cba564bb7718d777628599fea7332e2ae1ef9f15b80ce77072352a109dadbf9749fea049572
|
7
|
+
data.tar.gz: ffc57b47280776fc7be3cb2866699f32f90a2e036b2dca703ac4262aa77750032ffb54700437958ba7b4948c934d5ea6e41f2acad4e7e71ddec84a98f18edabf
|
data/.github/workflows/check.yml
CHANGED
@@ -18,6 +18,7 @@ jobs:
|
|
18
18
|
- '3.0'
|
19
19
|
- '3.1'
|
20
20
|
- '3.2'
|
21
|
+
- '3.3'
|
21
22
|
- jruby-9.3
|
22
23
|
- jruby-9.4
|
23
24
|
fail-fast: false
|
@@ -34,7 +35,6 @@ jobs:
|
|
34
35
|
strategy:
|
35
36
|
matrix:
|
36
37
|
container:
|
37
|
-
- rspec/ci:1.8.7
|
38
38
|
- rspec/ci:1.9.3
|
39
39
|
- ruby:2.0
|
40
40
|
- ruby:2.1
|
@@ -54,8 +54,8 @@ jobs:
|
|
54
54
|
- '3.0'
|
55
55
|
- '3.1'
|
56
56
|
- '3.2'
|
57
|
+
- '3.3'
|
57
58
|
fail-fast: false
|
58
|
-
continue-on-error: ${{ matrix.ruby == '3.2' }}
|
59
59
|
steps:
|
60
60
|
- uses: actions/checkout@v3
|
61
61
|
- uses: ruby/setup-ruby@v1
|
data/.rubocop.yml
CHANGED
@@ -15,9 +15,6 @@ Layout/CaseIndentation:
|
|
15
15
|
Layout/EndAlignment:
|
16
16
|
EnforcedStyleAlignWith: variable
|
17
17
|
|
18
|
-
Layout/FirstHashElementIndentation:
|
19
|
-
EnforcedStyle: consistent
|
20
|
-
|
21
18
|
Layout/LineLength:
|
22
19
|
Max: 120
|
23
20
|
|
@@ -25,9 +22,6 @@ Layout/SpaceBeforeBlockBraces:
|
|
25
22
|
EnforcedStyle: no_space
|
26
23
|
EnforcedStyleForEmptyBraces: no_space
|
27
24
|
|
28
|
-
Lint/PercentStringArray: # broken in rubocop 0.55.0
|
29
|
-
Enabled: false
|
30
|
-
|
31
25
|
Metrics/BlockLength:
|
32
26
|
Exclude:
|
33
27
|
- 'spec/**/*.rb'
|
@@ -41,42 +35,18 @@ Metrics/MethodLength:
|
|
41
35
|
Naming/MethodParameterName:
|
42
36
|
Enabled: false
|
43
37
|
|
44
|
-
Style/AccessorGrouping:
|
45
|
-
Enabled: false
|
46
|
-
|
47
38
|
Style/Alias:
|
48
39
|
EnforcedStyle: prefer_alias_method
|
49
40
|
|
50
|
-
Style/
|
51
|
-
Enabled: false
|
52
|
-
|
53
|
-
Style/Encoding:
|
54
|
-
Enabled: false
|
55
|
-
|
56
|
-
Style/FileRead:
|
41
|
+
Style/ArgumentsForwarding:
|
57
42
|
Enabled: false
|
58
43
|
|
59
|
-
Style/
|
60
|
-
Enabled: true
|
61
|
-
|
62
|
-
Style/HashSyntax:
|
63
|
-
EnforcedStyle: hash_rockets
|
64
|
-
|
65
|
-
Style/HashTransformKeys:
|
66
|
-
Enabled: false
|
67
|
-
|
68
|
-
Style/HashTransformValues:
|
69
|
-
Enabled: false
|
70
|
-
|
71
|
-
Style/IfUnlessModifier:
|
44
|
+
Style/EmptyCaseCondition:
|
72
45
|
Enabled: false
|
73
46
|
|
74
47
|
Style/NumericPredicate:
|
75
48
|
Enabled: false
|
76
49
|
|
77
|
-
Style/ParallelAssignment:
|
78
|
-
Enabled: false
|
79
|
-
|
80
50
|
Style/SafeNavigation:
|
81
51
|
Enabled: false
|
82
52
|
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v3.4.0 (2024-01-16)
|
6
|
+
|
7
|
+
* Provide access to media types using media_type and media_types methods [#22](https://github.com/toy/image_size/issues/22) [@toy](https://github.com/toy)
|
8
|
+
* Allow fetching from HTTP server by requiring image_size/uri [@toy](https://github.com/toy)
|
9
|
+
* Fix for ArgumentError when requiring only image_size/uri_reader (without image_size) [@toy](https://github.com/toy)
|
10
|
+
* Require ruby 1.9.3 [@toy](https://github.com/toy)
|
11
|
+
|
5
12
|
## v3.3.0 (2023-05-30)
|
6
13
|
|
7
14
|
* Support `HEIF` (`HEIC` and `AVIF`) images [#19](https://github.com/toy/image_size/issues/19) [@toy](https://github.com/toy)
|
data/README.markdown
CHANGED
@@ -26,7 +26,7 @@ gem 'image_size', '~> 3.0'
|
|
26
26
|
```ruby
|
27
27
|
image_size = ImageSize.path('spec/images/jpeg/436x429.jpeg')
|
28
28
|
|
29
|
-
image_size.format #=> :
|
29
|
+
image_size.format #=> :jpeg
|
30
30
|
image_size.width #=> 436
|
31
31
|
image_size.height #=> 429
|
32
32
|
image_size.w #=> 436
|
@@ -38,6 +38,8 @@ image_size.size.width #=> 436
|
|
38
38
|
image_size.size.height #=> 429
|
39
39
|
image_size.size.w #=> 436
|
40
40
|
image_size.size.h #=> 429
|
41
|
+
image_size.media_type #=> "image/jpeg"
|
42
|
+
image_size.media_types #=> ["image/jpeg"]
|
41
43
|
```
|
42
44
|
|
43
45
|
Or using `IO` object:
|
@@ -96,8 +98,7 @@ If server recognises Range header, only needed chunks will be fetched even for T
|
|
96
98
|
of data will be fetched, in most cases first few kilobytes (TIFF images is an exception).
|
97
99
|
|
98
100
|
```ruby
|
99
|
-
require 'image_size'
|
100
|
-
require 'image_size/uri_reader'
|
101
|
+
require 'image_size/uri'
|
101
102
|
|
102
103
|
url = 'http://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_1350692_33_images.jpg'
|
103
104
|
p ImageSize.url(url).size
|
@@ -144,4 +145,4 @@ puts Benchmark.measure{ p ImageSize.url(url).size }
|
|
144
145
|
This code is free to use under the terms of the [Ruby's licence](LICENSE.txt).
|
145
146
|
|
146
147
|
Original author: Keisuke Minami <keisuke@rccn.com>.\
|
147
|
-
Further development 2010-
|
148
|
+
Further development 2010-2024 Ivan Kuchin https://github.com/toy/image_size
|
data/image_size.gemspec
CHANGED
@@ -2,13 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'image_size'
|
5
|
-
s.version = '3.
|
5
|
+
s.version = '3.4.0'
|
6
6
|
s.summary = %q{Measure image size/dimensions using pure Ruby}
|
7
7
|
s.description = %q{Measure following file dimensions: apng, avif, bmp, cur, emf, gif, heic, heif, 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}"
|
9
9
|
s.authors = ['Keisuke Minami', 'Ivan Kuchin']
|
10
10
|
s.license = 'Ruby'
|
11
11
|
|
12
|
+
s.required_ruby_version = '>= 1.9.3'
|
13
|
+
|
12
14
|
s.metadata = {
|
13
15
|
'bug_tracker_uri' => "https://github.com/toy/#{s.name}/issues",
|
14
16
|
'changelog_uri' => "https://github.com/toy/#{s.name}/blob/master/CHANGELOG.markdown",
|
data/lib/image_size/isobmff.rb
CHANGED
@@ -62,11 +62,11 @@ class ImageSize
|
|
62
62
|
end
|
63
63
|
|
64
64
|
attributes = {
|
65
|
-
:
|
66
|
-
:
|
67
|
-
:
|
68
|
-
:
|
69
|
-
:
|
65
|
+
type: type,
|
66
|
+
offset: offset,
|
67
|
+
size: size,
|
68
|
+
relative_data_offset: relative_data_offset,
|
69
|
+
index: index,
|
70
70
|
}
|
71
71
|
|
72
72
|
if @full.include?(type)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ImageSize
|
4
|
+
MEDIA_TYPES = {
|
5
|
+
apng: %w[image/apng image/vnd.mozilla.apng],
|
6
|
+
avif: %w[image/avif],
|
7
|
+
bmp: %w[image/bmp],
|
8
|
+
cur: %w[image/vnd.microsoft.icon],
|
9
|
+
emf: %w[image/emf],
|
10
|
+
gif: %w[image/gif],
|
11
|
+
heic: %w[image/heic image/heif],
|
12
|
+
ico: %w[image/x-icon image/vnd.microsoft.icon],
|
13
|
+
j2c: %w[image/j2c],
|
14
|
+
jp2: %w[image/jp2],
|
15
|
+
jpeg: %w[image/jpeg],
|
16
|
+
jpx: %w[image/jpx],
|
17
|
+
mng: %w[video/x-mng image/x-mng],
|
18
|
+
pam: %w[image/x-portable-arbitrarymap],
|
19
|
+
pbm: %w[image/x-portable-bitmap image/x-portable-anymap],
|
20
|
+
pcx: %w[image/x-pcx image/vnd.zbrush.pcx],
|
21
|
+
pgm: %w[image/x-portable-graymap image/x-portable-anymap],
|
22
|
+
png: %w[image/png],
|
23
|
+
ppm: %w[image/x-portable-pixmap image/x-portable-anymap],
|
24
|
+
psd: %w[image/vnd.adobe.photoshop],
|
25
|
+
svg: %w[image/svg+xml],
|
26
|
+
swf: %w[application/x-shockwave-flash application/vnd.adobe.flash.movie],
|
27
|
+
tiff: %w[image/tiff],
|
28
|
+
webp: %w[image/webp],
|
29
|
+
xbm: %w[image/x-xbitmap],
|
30
|
+
xpm: %w[image/x-xpixmap],
|
31
|
+
}.freeze
|
32
|
+
end
|
data/lib/image_size.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'image_size/isobmff'
|
5
5
|
require 'image_size/format_error'
|
6
|
+
require 'image_size/media_types'
|
6
7
|
require 'image_size/reader'
|
7
8
|
require 'image_size/seekable_io_reader'
|
8
9
|
require 'image_size/stream_io_reader'
|
@@ -69,6 +70,19 @@ class ImageSize
|
|
69
70
|
Size.new([width, height]) if format
|
70
71
|
end
|
71
72
|
|
73
|
+
# Media type (formerly known as a MIME type)
|
74
|
+
def media_type
|
75
|
+
MEDIA_TYPES.fetch(format, []).first
|
76
|
+
end
|
77
|
+
|
78
|
+
# All media types:
|
79
|
+
# * commonly used and official like for apng and ico
|
80
|
+
# * main and compatible like for heic and pnm (pbm, pgm, ppm)
|
81
|
+
# * multiple unregistered like for mng
|
82
|
+
def media_types
|
83
|
+
MEDIA_TYPES.fetch(format, [])
|
84
|
+
end
|
85
|
+
|
72
86
|
private
|
73
87
|
|
74
88
|
SVG_R = /<svg\b([^>]*)>/.freeze
|
@@ -139,17 +153,13 @@ private
|
|
139
153
|
end
|
140
154
|
|
141
155
|
def size_of_mng(ir)
|
142
|
-
unless ir[12, 4] == 'MHDR'
|
143
|
-
raise FormatError, 'MHDR not in place for MNG'
|
144
|
-
end
|
156
|
+
raise FormatError, 'MHDR not in place for MNG' unless ir[12, 4] == 'MHDR'
|
145
157
|
|
146
158
|
ir.unpack(16, 8, 'NN')
|
147
159
|
end
|
148
160
|
|
149
161
|
def size_of_png(ir)
|
150
|
-
unless ir[12, 4] == 'IHDR'
|
151
|
-
raise FormatError, 'IHDR not in place for PNG'
|
152
|
-
end
|
162
|
+
raise FormatError, 'IHDR not in place for PNG' unless ir[12, 4] == 'IHDR'
|
153
163
|
|
154
164
|
ir.unpack(16, 8, 'NN')
|
155
165
|
end
|
@@ -167,14 +177,12 @@ private
|
|
167
177
|
loop do
|
168
178
|
offset += 1 until [nil, section_marker].include? ir[offset, 1]
|
169
179
|
offset += 1 until section_marker != ir[offset + 1, 1]
|
170
|
-
raise FormatError, 'EOF in JPEG'
|
180
|
+
raise FormatError, 'EOF in JPEG' unless ir[offset, 1]
|
171
181
|
|
172
182
|
code, length = ir.unpack(offset, 4, 'xCn')
|
173
183
|
offset += 4
|
174
184
|
|
175
|
-
if JPEG_CODE_CHECK.include?(code)
|
176
|
-
return ir.unpack(offset + 1, 4, 'nn').reverse
|
177
|
-
end
|
185
|
+
return ir.unpack(offset + 1, 4, 'nn').reverse if JPEG_CODE_CHECK.include?(code)
|
178
186
|
|
179
187
|
offset += length - 2
|
180
188
|
end
|
@@ -239,9 +247,7 @@ private
|
|
239
247
|
def size_of_xpm(ir)
|
240
248
|
length = 1024
|
241
249
|
until (data = ir[0, length]) =~ /"\s*(\d+)\s+(\d+)(\s+\d+\s+\d+){1,2}\s*"/m
|
242
|
-
if data.length != length
|
243
|
-
raise FormatError, 'XPM size not found'
|
244
|
-
end
|
250
|
+
raise FormatError, 'XPM size not found' if data.length != length
|
245
251
|
|
246
252
|
length += 1024
|
247
253
|
end
|
@@ -270,7 +276,7 @@ private
|
|
270
276
|
tag, type = ifd.unpack(endian2b * 2)
|
271
277
|
offset += 12
|
272
278
|
|
273
|
-
next
|
279
|
+
next unless packspec[type]
|
274
280
|
|
275
281
|
value = ifd[8, 4].unpack(packspec[type])[0]
|
276
282
|
case tag
|
@@ -339,8 +345,8 @@ private
|
|
339
345
|
end
|
340
346
|
|
341
347
|
JP2_WALKER = ImageSize::ISOBMFF.new(
|
342
|
-
:
|
343
|
-
:
|
348
|
+
recurse: %w[jp2h],
|
349
|
+
last: %w[jp2h]
|
344
350
|
)
|
345
351
|
def size_of_jp2(ir)
|
346
352
|
JP2_WALKER.recurse(ir) do |box|
|
@@ -370,9 +376,9 @@ private
|
|
370
376
|
end
|
371
377
|
|
372
378
|
HEIF_WALKER = ImageSize::ISOBMFF.new(
|
373
|
-
:
|
374
|
-
:
|
375
|
-
:
|
379
|
+
recurse: %w[meta iprp ipco],
|
380
|
+
full: %w[meta hdlr pitm ipma ispe],
|
381
|
+
last: %w[meta]
|
376
382
|
)
|
377
383
|
def size_of_heif(ir)
|
378
384
|
pitm = nil
|
@@ -29,7 +29,7 @@ describe ImageSize::ChunkyReader do
|
|
29
29
|
{
|
30
30
|
'empty string' => '',
|
31
31
|
'a bit of data' => 'foo bar baz',
|
32
|
-
'a lot of data' => File.
|
32
|
+
'a lot of data' => File.binread('GPL'),
|
33
33
|
}.each do |data_description, data|
|
34
34
|
{
|
35
35
|
'default' => test_reader.new(data),
|
@@ -53,8 +53,8 @@ describe ImageSize::ISOBMFF do
|
|
53
53
|
|
54
54
|
it do
|
55
55
|
is_expected.to yield_successive_args(
|
56
|
-
having_attributes(:
|
57
|
-
having_attributes(:
|
56
|
+
having_attributes(type: 'abcd', data_offset: 8, data_size: 42),
|
57
|
+
having_attributes(type: 'efgh', data_offset: 58, data_size: 10)
|
58
58
|
)
|
59
59
|
end
|
60
60
|
end
|
@@ -74,14 +74,14 @@ describe ImageSize::ISOBMFF do
|
|
74
74
|
describe 'for a box without content' do
|
75
75
|
let(:data){ boxes.build{ box('test', 8) } }
|
76
76
|
|
77
|
-
it{ is_expected.to yield_successive_args(having_attributes(:
|
77
|
+
it{ is_expected.to yield_successive_args(having_attributes(type: 'test', data_offset: 8, data_size: 0)) }
|
78
78
|
end
|
79
79
|
|
80
80
|
describe 'for a box with content' do
|
81
81
|
let(:data){ boxes.build{ box('test', 8 + 42) } }
|
82
82
|
|
83
83
|
it do
|
84
|
-
is_expected.to yield_successive_args(having_attributes(:
|
84
|
+
is_expected.to yield_successive_args(having_attributes(type: 'test', data_offset: 8, data_size: 42))
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -100,7 +100,7 @@ describe ImageSize::ISOBMFF do
|
|
100
100
|
let(:data){ boxes.build{ box('test', 0) } }
|
101
101
|
|
102
102
|
it do
|
103
|
-
is_expected.to yield_successive_args(having_attributes(:
|
103
|
+
is_expected.to yield_successive_args(having_attributes(type: 'test', data_offset: 8, data_size: nil))
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
@@ -116,7 +116,7 @@ describe ImageSize::ISOBMFF do
|
|
116
116
|
let(:data){ boxes.build{ box('test', 1, 16) } }
|
117
117
|
|
118
118
|
it do
|
119
|
-
is_expected.to yield_successive_args(having_attributes(:
|
119
|
+
is_expected.to yield_successive_args(having_attributes(type: 'test', data_offset: 16, data_size: 0))
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
@@ -124,12 +124,12 @@ describe ImageSize::ISOBMFF do
|
|
124
124
|
let(:data){ boxes.build{ box('test', 1, 16 + 42) } }
|
125
125
|
|
126
126
|
it do
|
127
|
-
is_expected.to yield_successive_args(having_attributes(:
|
127
|
+
is_expected.to yield_successive_args(having_attributes(type: 'test', data_offset: 16, data_size: 42))
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
131
|
describe 'for a full box' do
|
132
|
-
let(:options){ { :
|
132
|
+
let(:options){ { full: %w[test] } }
|
133
133
|
|
134
134
|
let(:data) do
|
135
135
|
boxes.build do
|
@@ -141,18 +141,18 @@ describe ImageSize::ISOBMFF do
|
|
141
141
|
it do
|
142
142
|
is_expected.to yield_successive_args(
|
143
143
|
having_attributes(
|
144
|
-
:
|
145
|
-
:
|
146
|
-
:
|
147
|
-
:
|
148
|
-
:
|
144
|
+
type: 'test',
|
145
|
+
data_offset: 12,
|
146
|
+
data_size: 38,
|
147
|
+
version: 0x61,
|
148
|
+
flags: 0x626364
|
149
149
|
)
|
150
150
|
)
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
154
|
describe 'for a big full box' do
|
155
|
-
let(:options){ { :
|
155
|
+
let(:options){ { full: %w[test] } }
|
156
156
|
|
157
157
|
let(:data) do
|
158
158
|
boxes.build do
|
@@ -164,11 +164,11 @@ describe ImageSize::ISOBMFF do
|
|
164
164
|
it do
|
165
165
|
is_expected.to yield_successive_args(
|
166
166
|
having_attributes(
|
167
|
-
:
|
168
|
-
:
|
169
|
-
:
|
170
|
-
:
|
171
|
-
:
|
167
|
+
type: 'test',
|
168
|
+
data_offset: 20,
|
169
|
+
data_size: 38,
|
170
|
+
version: 0x61,
|
171
|
+
flags: 0x626364
|
172
172
|
)
|
173
173
|
)
|
174
174
|
end
|
@@ -206,8 +206,8 @@ describe ImageSize::ISOBMFF do
|
|
206
206
|
|
207
207
|
it do
|
208
208
|
is_expected.to yield_successive_args(
|
209
|
-
having_attributes(:
|
210
|
-
having_attributes(:
|
209
|
+
having_attributes(type: 'fooo', data_offset: 16, data_size: 0),
|
210
|
+
having_attributes(type: 'barr', data_offset: 24, data_size: 0)
|
211
211
|
)
|
212
212
|
end
|
213
213
|
end
|
@@ -230,7 +230,7 @@ describe ImageSize::ISOBMFF do
|
|
230
230
|
let(:length){ 8 }
|
231
231
|
|
232
232
|
it do
|
233
|
-
is_expected.to yield_successive_args(having_attributes(:
|
233
|
+
is_expected.to yield_successive_args(having_attributes(type: 'fooo', data_offset: 16, data_size: 0))
|
234
234
|
end
|
235
235
|
end
|
236
236
|
end
|
@@ -256,24 +256,24 @@ describe ImageSize::ISOBMFF do
|
|
256
256
|
end
|
257
257
|
|
258
258
|
context 'when configured to recures all' do
|
259
|
-
let(:options){ { :
|
259
|
+
let(:options){ { recurse: %w[fooA barA barB bazA] } }
|
260
260
|
|
261
261
|
it 'recurses complete tree' do
|
262
262
|
enum = instance.to_enum(:recurse, string_reader)
|
263
263
|
|
264
|
-
expect(enum.next).to have_attributes(:
|
264
|
+
expect(enum.next).to have_attributes(type: 'fooA', data_offset: 8, data_size: 10)
|
265
265
|
|
266
|
-
expect(enum.next).to have_attributes(:
|
266
|
+
expect(enum.next).to have_attributes(type: 'fooB', data_offset: 16, data_size: 2)
|
267
267
|
|
268
|
-
expect(enum.next).to have_attributes(:
|
268
|
+
expect(enum.next).to have_attributes(type: 'barA', data_offset: 26, data_size: 18)
|
269
269
|
|
270
|
-
expect(enum.next).to have_attributes(:
|
270
|
+
expect(enum.next).to have_attributes(type: 'barB', data_offset: 34, data_size: 10)
|
271
271
|
|
272
|
-
expect(enum.next).to have_attributes(:
|
272
|
+
expect(enum.next).to have_attributes(type: 'barC', data_offset: 42, data_size: 2)
|
273
273
|
|
274
|
-
expect(enum.next).to have_attributes(:
|
274
|
+
expect(enum.next).to have_attributes(type: 'bazA', data_offset: 52, data_size: 10)
|
275
275
|
|
276
|
-
expect(enum.next).to have_attributes(:
|
276
|
+
expect(enum.next).to have_attributes(type: 'bazB', data_offset: 60, data_size: 2)
|
277
277
|
|
278
278
|
expect{ enum.next }.to raise_exception(StopIteration)
|
279
279
|
end
|
@@ -284,18 +284,18 @@ describe ImageSize::ISOBMFF do
|
|
284
284
|
end
|
285
285
|
|
286
286
|
context 'when configured to recurse part' do
|
287
|
-
let(:options){ { :
|
287
|
+
let(:options){ { recurse: %w[barA] } }
|
288
288
|
|
289
289
|
it 'recurses requested part' do
|
290
290
|
enum = instance.to_enum(:recurse, string_reader)
|
291
291
|
|
292
|
-
expect(enum.next).to have_attributes(:
|
292
|
+
expect(enum.next).to have_attributes(type: 'fooA', data_offset: 8, data_size: 10)
|
293
293
|
|
294
|
-
expect(enum.next).to have_attributes(:
|
294
|
+
expect(enum.next).to have_attributes(type: 'barA', data_offset: 26, data_size: 18)
|
295
295
|
|
296
|
-
expect(enum.next).to have_attributes(:
|
296
|
+
expect(enum.next).to have_attributes(type: 'barB', data_offset: 34, data_size: 10)
|
297
297
|
|
298
|
-
expect(enum.next).to have_attributes(:
|
298
|
+
expect(enum.next).to have_attributes(type: 'bazA', data_offset: 52, data_size: 10)
|
299
299
|
|
300
300
|
expect{ enum.next }.to raise_exception(StopIteration)
|
301
301
|
end
|
@@ -311,11 +311,11 @@ describe ImageSize::ISOBMFF do
|
|
311
311
|
it 'does not recurse' do
|
312
312
|
enum = instance.to_enum(:recurse, string_reader)
|
313
313
|
|
314
|
-
expect(enum.next).to have_attributes(:
|
314
|
+
expect(enum.next).to have_attributes(type: 'fooA', data_offset: 8, data_size: 10)
|
315
315
|
|
316
|
-
expect(enum.next).to have_attributes(:
|
316
|
+
expect(enum.next).to have_attributes(type: 'barA', data_offset: 26, data_size: 18)
|
317
317
|
|
318
|
-
expect(enum.next).to have_attributes(:
|
318
|
+
expect(enum.next).to have_attributes(type: 'bazA', data_offset: 52, data_size: 10)
|
319
319
|
|
320
320
|
expect{ enum.next }.to raise_exception(StopIteration)
|
321
321
|
end
|
@@ -326,20 +326,20 @@ describe ImageSize::ISOBMFF do
|
|
326
326
|
end
|
327
327
|
|
328
328
|
context 'when configured to stop' do
|
329
|
-
let(:options){ { :
|
329
|
+
let(:options){ { recurse: %w[fooA barA barB bazA], last: %w[barA] } }
|
330
330
|
|
331
331
|
it 'recurses complete tree' do
|
332
332
|
enum = instance.to_enum(:recurse, string_reader)
|
333
333
|
|
334
|
-
expect(enum.next).to have_attributes(:
|
334
|
+
expect(enum.next).to have_attributes(type: 'fooA', data_offset: 8, data_size: 10)
|
335
335
|
|
336
|
-
expect(enum.next).to have_attributes(:
|
336
|
+
expect(enum.next).to have_attributes(type: 'fooB', data_offset: 16, data_size: 2)
|
337
337
|
|
338
|
-
expect(enum.next).to have_attributes(:
|
338
|
+
expect(enum.next).to have_attributes(type: 'barA', data_offset: 26, data_size: 18)
|
339
339
|
|
340
|
-
expect(enum.next).to have_attributes(:
|
340
|
+
expect(enum.next).to have_attributes(type: 'barB', data_offset: 34, data_size: 10)
|
341
341
|
|
342
|
-
expect(enum.next).to have_attributes(:
|
342
|
+
expect(enum.next).to have_attributes(type: 'barC', data_offset: 42, data_size: 2)
|
343
343
|
|
344
344
|
expect{ enum.next }.to raise_exception(StopIteration)
|
345
345
|
end
|
data/spec/image_size_spec.rb
CHANGED
@@ -10,6 +10,10 @@ require 'shellwords'
|
|
10
10
|
|
11
11
|
require 'test_server'
|
12
12
|
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.order = :random
|
15
|
+
end
|
16
|
+
|
13
17
|
describe ImageSize do
|
14
18
|
before :all do
|
15
19
|
@server = TestServer.new
|
@@ -19,6 +23,19 @@ describe ImageSize do
|
|
19
23
|
@server.finish
|
20
24
|
end
|
21
25
|
|
26
|
+
def retry_on(exception_class)
|
27
|
+
attempt = 1
|
28
|
+
begin
|
29
|
+
yield
|
30
|
+
rescue exception_class => e
|
31
|
+
warn "Attempt #{attempt}: #{e.inspect}"
|
32
|
+
raise unless attempt < 3
|
33
|
+
|
34
|
+
attempt += 1
|
35
|
+
retry
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
22
39
|
def supported_formats
|
23
40
|
ImageSize.private_instance_methods.map{ |name| name[/\Asize_of_(.*)\z/, 1] }.compact.sort
|
24
41
|
end
|
@@ -45,19 +62,26 @@ describe ImageSize do
|
|
45
62
|
describe "for #{path}" do
|
46
63
|
let(:name){ File.basename(path) }
|
47
64
|
let(:attributes) do
|
48
|
-
match = /(\d+)x(\d+)\.([^.]+)$/.match(name)
|
49
|
-
|
65
|
+
if (match = /(\d+)x(\d+)\.([^.]+)$/.match(name))
|
66
|
+
width = match[1].to_i
|
67
|
+
height = match[2].to_i
|
68
|
+
format = match[3].to_sym
|
69
|
+
end
|
50
70
|
size = format && [width, height]
|
71
|
+
media_types = ImageSize::MEDIA_TYPES[format] || []
|
72
|
+
media_type = format && media_types.first.to_s
|
51
73
|
{
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
74
|
+
format: format,
|
75
|
+
width: width,
|
76
|
+
height: height,
|
77
|
+
w: width,
|
78
|
+
h: height,
|
79
|
+
size: size,
|
80
|
+
media_type: media_type,
|
81
|
+
media_types: media_types,
|
58
82
|
}
|
59
83
|
end
|
60
|
-
let(:file_data){ File.
|
84
|
+
let(:file_data){ File.binread(path) }
|
61
85
|
let(:file_size){ file_data.length }
|
62
86
|
|
63
87
|
before do
|
@@ -148,14 +172,18 @@ describe ImageSize do
|
|
148
172
|
context 'supporting range' do
|
149
173
|
context 'without redirects' do
|
150
174
|
it 'gets format and dimensions' do
|
151
|
-
image_size =
|
175
|
+
image_size = retry_on Timeout::Error do
|
176
|
+
ImageSize.url(file_url)
|
177
|
+
end
|
152
178
|
expect(image_size).to have_attributes(attributes)
|
153
179
|
end
|
154
180
|
end
|
155
181
|
|
156
182
|
context 'with redirects' do
|
157
183
|
it 'gets format and dimensions' do
|
158
|
-
image_size =
|
184
|
+
image_size = retry_on Timeout::Error do
|
185
|
+
ImageSize.url("#{file_url}?redirect=5")
|
186
|
+
end
|
159
187
|
expect(image_size).to have_attributes(attributes)
|
160
188
|
end
|
161
189
|
end
|
@@ -163,7 +191,9 @@ describe ImageSize do
|
|
163
191
|
context 'with too many redirects' do
|
164
192
|
it 'gets format and dimensions' do
|
165
193
|
expect do
|
166
|
-
|
194
|
+
retry_on Timeout::Error do
|
195
|
+
ImageSize.url("#{file_url}?redirect=6")
|
196
|
+
end
|
167
197
|
end.to raise_error(/Too many redirects/)
|
168
198
|
end
|
169
199
|
end
|
@@ -172,14 +202,18 @@ describe ImageSize do
|
|
172
202
|
context 'not supporting range' do
|
173
203
|
context 'without redirects' do
|
174
204
|
it 'gets format and dimensions' do
|
175
|
-
image_size =
|
205
|
+
image_size = retry_on Timeout::Error do
|
206
|
+
ImageSize.url("#{file_url}?ignore_range")
|
207
|
+
end
|
176
208
|
expect(image_size).to have_attributes(attributes)
|
177
209
|
end
|
178
210
|
end
|
179
211
|
|
180
212
|
context 'with redirects' do
|
181
213
|
it 'gets format and dimensions' do
|
182
|
-
image_size =
|
214
|
+
image_size = retry_on Timeout::Error do
|
215
|
+
ImageSize.url("#{file_url}?ignore_range&redirect=5")
|
216
|
+
end
|
183
217
|
expect(image_size).to have_attributes(attributes)
|
184
218
|
end
|
185
219
|
end
|
@@ -187,7 +221,9 @@ describe ImageSize do
|
|
187
221
|
context 'with too many redirects' do
|
188
222
|
it 'gets format and dimensions' do
|
189
223
|
expect do
|
190
|
-
|
224
|
+
retry_on Timeout::Error do
|
225
|
+
ImageSize.url("#{file_url}?ignore_range&redirect=6")
|
226
|
+
end
|
191
227
|
end.to raise_error(/Too many redirects/)
|
192
228
|
end
|
193
229
|
end
|
@@ -203,8 +239,8 @@ describe ImageSize do
|
|
203
239
|
end
|
204
240
|
|
205
241
|
{
|
206
|
-
:
|
207
|
-
:
|
242
|
+
png: "\211PNG\r\n\032\n",
|
243
|
+
jpeg: "\377\330",
|
208
244
|
}.each do |type, data|
|
209
245
|
it "raises FormatError if invalid #{type} given" do
|
210
246
|
expect do
|
data/spec/test_server.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'webrick'
|
4
|
+
require 'stringio'
|
4
5
|
|
5
6
|
class TestServer
|
6
7
|
attr_reader :base_url
|
7
8
|
|
8
9
|
def initialize(host = '127.0.0.1')
|
9
10
|
server_options = {
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
11
|
+
Logger: WEBrick::Log.new(StringIO.new),
|
12
|
+
AccessLog: [],
|
13
|
+
BindAddress: host,
|
14
|
+
Port: 0, # get the next available port
|
15
|
+
DocumentRoot: '.',
|
16
|
+
RequestCallback: proc do |req, res|
|
16
17
|
redirect = req.query['redirect'].to_i
|
17
18
|
if redirect > 0
|
18
19
|
res.set_redirect(
|
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.
|
4
|
+
version: 3.4.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:
|
12
|
+
date: 2024-01-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -76,10 +76,12 @@ files:
|
|
76
76
|
- lib/image_size/chunky_reader.rb
|
77
77
|
- lib/image_size/format_error.rb
|
78
78
|
- lib/image_size/isobmff.rb
|
79
|
+
- lib/image_size/media_types.rb
|
79
80
|
- lib/image_size/reader.rb
|
80
81
|
- lib/image_size/seekable_io_reader.rb
|
81
82
|
- lib/image_size/stream_io_reader.rb
|
82
83
|
- lib/image_size/string_reader.rb
|
84
|
+
- lib/image_size/uri.rb
|
83
85
|
- lib/image_size/uri_reader.rb
|
84
86
|
- spec/image_size/chunky_reader_spec.rb
|
85
87
|
- spec/image_size/isobmff_spec.rb
|
@@ -138,7 +140,7 @@ licenses:
|
|
138
140
|
metadata:
|
139
141
|
bug_tracker_uri: https://github.com/toy/image_size/issues
|
140
142
|
changelog_uri: https://github.com/toy/image_size/blob/master/CHANGELOG.markdown
|
141
|
-
documentation_uri: https://www.rubydoc.info/gems/image_size/3.
|
143
|
+
documentation_uri: https://www.rubydoc.info/gems/image_size/3.4.0
|
142
144
|
source_code_uri: https://github.com/toy/image_size
|
143
145
|
post_install_message:
|
144
146
|
rdoc_options: []
|
@@ -148,14 +150,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
148
150
|
requirements:
|
149
151
|
- - ">="
|
150
152
|
- !ruby/object:Gem::Version
|
151
|
-
version:
|
153
|
+
version: 1.9.3
|
152
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
155
|
requirements:
|
154
156
|
- - ">="
|
155
157
|
- !ruby/object:Gem::Version
|
156
158
|
version: '0'
|
157
159
|
requirements: []
|
158
|
-
rubygems_version: 3.4.
|
160
|
+
rubygems_version: 3.4.20
|
159
161
|
signing_key:
|
160
162
|
specification_version: 4
|
161
163
|
summary: Measure image size/dimensions using pure Ruby
|