image_size 3.3.0 → 3.5.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/dependabot.yml +8 -0
- data/.github/workflows/check.yml +13 -21
- data/.github/workflows/rubocop.yml +2 -2
- data/.rubocop.yml +5 -32
- data/.rubocop_todo.yml +0 -6
- data/CHANGELOG.markdown +16 -0
- data/README.markdown +53 -5
- data/image_size.gemspec +16 -5
- data/lib/image_size/chunky_reader.rb +2 -2
- data/lib/image_size/isobmff.rb +7 -7
- data/lib/image_size/media_types.rb +32 -0
- data/lib/image_size/reader.rb +4 -3
- data/lib/image_size/seekable_io_reader.rb +4 -0
- data/lib/image_size/stream_io_reader.rb +6 -0
- data/lib/image_size/string_reader.rb +4 -0
- data/lib/image_size/uri.rb +3 -0
- data/lib/image_size/uri_reader.rb +62 -10
- data/lib/image_size.rb +64 -36
- data/spec/image_size/chunky_reader_spec.rb +1 -1
- data/spec/image_size/isobmff_spec.rb +44 -44
- data/spec/image_size/seekable_io_reader_spec.rb +18 -23
- data/spec/image_size_spec.rb +262 -29
- data/spec/images/svg/768b.430x430.svg +11 -0
- data/spec/test_server.rb +34 -7
- metadata +10 -9
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'
|
|
@@ -35,14 +36,30 @@ class ImageSize
|
|
|
35
36
|
new(Pathname.new(path))
|
|
36
37
|
end
|
|
37
38
|
|
|
38
|
-
# Used for svg
|
|
39
|
+
# Used for svg and emf
|
|
39
40
|
def self.dpi
|
|
40
|
-
@dpi || 72
|
|
41
|
+
@dpi || 72.0
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
# Used for svg
|
|
44
|
+
# Used for svg and emf
|
|
44
45
|
def self.dpi=(dpi)
|
|
45
|
-
|
|
46
|
+
fail ArgumentError, "dpi should be nil or positive, got #{dpi}" unless dpi.nil? || dpi > 0
|
|
47
|
+
|
|
48
|
+
@dpi = dpi ? dpi.to_f : nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Size of chunk to use by IO and URI readers
|
|
52
|
+
def self.chunk_size
|
|
53
|
+
@chunk_size || 4096
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Set size of chunk to use by IO and URI readers
|
|
57
|
+
def self.chunk_size=(chunk_size)
|
|
58
|
+
unless chunk_size.nil? || (chunk_size.is_a?(Integer) && chunk_size > 0)
|
|
59
|
+
fail ArgumentError, "chunk_size should be a positive Integer or nil, got #{chunk_size}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
@chunk_size = chunk_size
|
|
46
63
|
end
|
|
47
64
|
|
|
48
65
|
# Given image as any class responding to read and eof? or data as String, finds its format and dimensions
|
|
@@ -50,6 +67,7 @@ class ImageSize
|
|
|
50
67
|
Reader.open(data) do |ir|
|
|
51
68
|
@format = detect_format(ir)
|
|
52
69
|
@width, @height = send("size_of_#{@format}", ir) if @format
|
|
70
|
+
@byte_size = ir.byte_size
|
|
53
71
|
end
|
|
54
72
|
end
|
|
55
73
|
|
|
@@ -64,11 +82,26 @@ class ImageSize
|
|
|
64
82
|
attr_reader :height
|
|
65
83
|
alias_method :h, :height
|
|
66
84
|
|
|
85
|
+
attr_reader :byte_size
|
|
86
|
+
|
|
67
87
|
# get image width and height as an array which to_s method returns "#{width}x#{height}"
|
|
68
88
|
def size
|
|
69
89
|
Size.new([width, height]) if format
|
|
70
90
|
end
|
|
71
91
|
|
|
92
|
+
# Media type (formerly known as a MIME type)
|
|
93
|
+
def media_type
|
|
94
|
+
media_types.first
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# All media types:
|
|
98
|
+
# * commonly used and official like for apng and ico
|
|
99
|
+
# * main and compatible like for heic and pnm (pbm, pgm, ppm)
|
|
100
|
+
# * multiple unregistered like for mng
|
|
101
|
+
def media_types
|
|
102
|
+
MEDIA_TYPES.fetch(format, [])
|
|
103
|
+
end
|
|
104
|
+
|
|
72
105
|
private
|
|
73
106
|
|
|
74
107
|
SVG_R = /<svg\b([^>]*)>/.freeze
|
|
@@ -139,17 +172,13 @@ private
|
|
|
139
172
|
end
|
|
140
173
|
|
|
141
174
|
def size_of_mng(ir)
|
|
142
|
-
unless ir[12, 4] == 'MHDR'
|
|
143
|
-
raise FormatError, 'MHDR not in place for MNG'
|
|
144
|
-
end
|
|
175
|
+
fail FormatError, 'MHDR not in place for MNG' unless ir[12, 4] == 'MHDR'
|
|
145
176
|
|
|
146
177
|
ir.unpack(16, 8, 'NN')
|
|
147
178
|
end
|
|
148
179
|
|
|
149
180
|
def size_of_png(ir)
|
|
150
|
-
unless ir[12, 4] == 'IHDR'
|
|
151
|
-
raise FormatError, 'IHDR not in place for PNG'
|
|
152
|
-
end
|
|
181
|
+
fail FormatError, 'IHDR not in place for PNG' unless ir[12, 4] == 'IHDR'
|
|
153
182
|
|
|
154
183
|
ir.unpack(16, 8, 'NN')
|
|
155
184
|
end
|
|
@@ -167,14 +196,12 @@ private
|
|
|
167
196
|
loop do
|
|
168
197
|
offset += 1 until [nil, section_marker].include? ir[offset, 1]
|
|
169
198
|
offset += 1 until section_marker != ir[offset + 1, 1]
|
|
170
|
-
|
|
199
|
+
fail FormatError, 'EOF in JPEG' unless ir[offset, 1]
|
|
171
200
|
|
|
172
201
|
code, length = ir.unpack(offset, 4, 'xCn')
|
|
173
202
|
offset += 4
|
|
174
203
|
|
|
175
|
-
if JPEG_CODE_CHECK.include?(code)
|
|
176
|
-
return ir.unpack(offset + 1, 4, 'nn').reverse
|
|
177
|
-
end
|
|
204
|
+
return ir.unpack(offset + 1, 4, 'nn').reverse if JPEG_CODE_CHECK.include?(code)
|
|
178
205
|
|
|
179
206
|
offset += length - 2
|
|
180
207
|
end
|
|
@@ -198,8 +225,7 @@ private
|
|
|
198
225
|
def size_of_ppm(ir)
|
|
199
226
|
header = ir[0, 1024]
|
|
200
227
|
header.gsub!(/^\#[^\n\r]*/m, '')
|
|
201
|
-
header
|
|
202
|
-
[$2.to_i, $3.to_i]
|
|
228
|
+
header.match(/^(?:P[1-6])\s+?(\d+)\s+?(\d+)/m)[1..2].map(&:to_i)
|
|
203
229
|
end
|
|
204
230
|
alias_method :size_of_pbm, :size_of_ppm
|
|
205
231
|
alias_method :size_of_pgm, :size_of_ppm
|
|
@@ -215,37 +241,37 @@ private
|
|
|
215
241
|
chunk = ir[offset, 32]
|
|
216
242
|
case chunk
|
|
217
243
|
when /\AWIDTH (\d+)\n/
|
|
218
|
-
width =
|
|
244
|
+
width = Regexp.last_match[1].to_i
|
|
219
245
|
when /\AHEIGHT (\d+)\n/
|
|
220
|
-
height =
|
|
246
|
+
height = Regexp.last_match[1].to_i
|
|
221
247
|
when /\AENDHDR\n/
|
|
222
248
|
break
|
|
223
249
|
when /\A(?:DEPTH|MAXVAL) \d+\n/, /\ATUPLTYPE \S+\n/
|
|
224
250
|
# ignore
|
|
225
251
|
else
|
|
226
|
-
|
|
252
|
+
fail FormatError, "Unexpected data in PAM header: #{chunk.inspect}"
|
|
227
253
|
end
|
|
228
|
-
offset +=
|
|
254
|
+
offset += Regexp.last_match[0].length
|
|
229
255
|
end
|
|
230
256
|
end
|
|
231
257
|
[width, height]
|
|
232
258
|
end
|
|
233
259
|
|
|
234
260
|
def size_of_xbm(ir)
|
|
235
|
-
ir[0, 1024]
|
|
236
|
-
[$1.to_i, $2.to_i]
|
|
261
|
+
ir[0, 1024].match(/^\#define\s*\S*\s*(\d+)\s*\n\#define\s*\S*\s*(\d+)/mi)[1..2].map(&:to_i)
|
|
237
262
|
end
|
|
238
263
|
|
|
239
264
|
def size_of_xpm(ir)
|
|
240
265
|
length = 1024
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
266
|
+
loop do
|
|
267
|
+
data = ir[0, length]
|
|
268
|
+
m = data.match(/"\s*(\d+)\s+(\d+)(?:\s+\d+\s+\d+){1,2}\s*"/m)
|
|
269
|
+
return m[1..2].map(&:to_i) if m
|
|
270
|
+
|
|
271
|
+
fail FormatError, 'XPM size not found' if data.length != length
|
|
245
272
|
|
|
246
273
|
length += 1024
|
|
247
274
|
end
|
|
248
|
-
[$1.to_i, $2.to_i]
|
|
249
275
|
end
|
|
250
276
|
|
|
251
277
|
def size_of_psd(ir)
|
|
@@ -265,12 +291,12 @@ private
|
|
|
265
291
|
width = height = nil
|
|
266
292
|
until width && height
|
|
267
293
|
ifd = ir.fetch(offset, 12)
|
|
268
|
-
|
|
294
|
+
fail FormatError, 'Reached end of directory entries in TIFF' if offset > num_dirent
|
|
269
295
|
|
|
270
296
|
tag, type = ifd.unpack(endian2b * 2)
|
|
271
297
|
offset += 12
|
|
272
298
|
|
|
273
|
-
next
|
|
299
|
+
next unless packspec[type]
|
|
274
300
|
|
|
275
301
|
value = ifd[8, 4].unpack(packspec[type])[0]
|
|
276
302
|
case tag
|
|
@@ -339,8 +365,8 @@ private
|
|
|
339
365
|
end
|
|
340
366
|
|
|
341
367
|
JP2_WALKER = ImageSize::ISOBMFF.new(
|
|
342
|
-
:
|
|
343
|
-
:
|
|
368
|
+
recurse: %w[jp2h],
|
|
369
|
+
last: %w[jp2h]
|
|
344
370
|
)
|
|
345
371
|
def size_of_jp2(ir)
|
|
346
372
|
JP2_WALKER.recurse(ir) do |box|
|
|
@@ -370,9 +396,9 @@ private
|
|
|
370
396
|
end
|
|
371
397
|
|
|
372
398
|
HEIF_WALKER = ImageSize::ISOBMFF.new(
|
|
373
|
-
:
|
|
374
|
-
:
|
|
375
|
-
:
|
|
399
|
+
recurse: %w[meta iprp ipco],
|
|
400
|
+
full: %w[meta hdlr pitm ipma ispe],
|
|
401
|
+
last: %w[meta]
|
|
376
402
|
)
|
|
377
403
|
def size_of_heif(ir)
|
|
378
404
|
pitm = nil
|
|
@@ -384,11 +410,11 @@ private
|
|
|
384
410
|
HEIF_WALKER.recurse(ir) do |box, _path|
|
|
385
411
|
case box.type
|
|
386
412
|
when 'hdlr'
|
|
387
|
-
|
|
413
|
+
fail FormatError, "hdlr box too small (#{box.data_size})" if box.data_size < 8
|
|
388
414
|
|
|
389
415
|
return nil unless ir[box.data_offset + 4, 4] == 'pict'
|
|
390
416
|
when 'pitm'
|
|
391
|
-
|
|
417
|
+
fail FormatError, 'second pitm box encountered' if pitm
|
|
392
418
|
|
|
393
419
|
pitm = box.version == 0 ? ir.unpack1(box.data_offset, 2, 'n') : ir.unpack1(box.data_offset, 4, 'N')
|
|
394
420
|
when 'ipma'
|
|
@@ -430,4 +456,6 @@ private
|
|
|
430
456
|
end
|
|
431
457
|
alias_method :size_of_avif, :size_of_heif
|
|
432
458
|
alias_method :size_of_heic, :size_of_heif
|
|
459
|
+
|
|
460
|
+
private_constant :SVG_R, :XML_R, :JPEG_CODE_CHECK, :JP2_WALKER, :EMF_UMAX, :EMF_SMAX, :HEIF_WALKER
|
|
433
461
|
end
|
|
@@ -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
|
|
@@ -6,45 +6,40 @@ require 'image_size/seekable_io_reader'
|
|
|
6
6
|
|
|
7
7
|
describe ImageSize::SeekableIOReader do
|
|
8
8
|
context :[] do
|
|
9
|
-
def
|
|
10
|
-
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def io
|
|
14
|
-
File.open('GPL', 'rb').tap do |io|
|
|
15
|
-
ios << io
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
after do
|
|
20
|
-
ios.pop.close until ios.empty?
|
|
9
|
+
def new_io(&block)
|
|
10
|
+
File.open('GPL', 'rb', &block)
|
|
21
11
|
end
|
|
22
12
|
|
|
23
13
|
def new_reader
|
|
24
|
-
|
|
14
|
+
new_io do |io|
|
|
15
|
+
yield ImageSize::SeekableIOReader.new(io)
|
|
16
|
+
end
|
|
25
17
|
end
|
|
26
18
|
|
|
27
|
-
let(:content){
|
|
19
|
+
let(:content){ new_io(&:read) }
|
|
28
20
|
|
|
29
21
|
it 'reads as expected when pieces are read consecutively' do
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
new_reader do |reader|
|
|
23
|
+
0.step(content.length + 4096, 100) do |offset|
|
|
24
|
+
expect(reader[offset, 100]).to eq(content[offset, 100])
|
|
25
|
+
end
|
|
33
26
|
end
|
|
34
27
|
end
|
|
35
28
|
|
|
36
29
|
it 'reads as expected when pieces are read backwards' do
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
new_reader do |reader|
|
|
31
|
+
(content.length + 4096).step(0, -100) do |offset|
|
|
32
|
+
expect(reader[offset, 100]).to eq(content[offset, 100])
|
|
33
|
+
end
|
|
40
34
|
end
|
|
41
35
|
end
|
|
42
36
|
|
|
43
37
|
it 'reads as expected when pieces are read in random order' do
|
|
44
38
|
100.times do
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
new_reader do |reader|
|
|
40
|
+
0.step(content.length + 4096, 100).to_a.shuffle.each do |offset|
|
|
41
|
+
expect(reader[offset, 100]).to eq(content[offset, 100])
|
|
42
|
+
end
|
|
48
43
|
end
|
|
49
44
|
end
|
|
50
45
|
end
|