format_parser 0.16.1 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/format_parser.rb +8 -23
- data/lib/format_parser/version.rb +1 -1
- data/lib/parsers/aiff_parser.rb +2 -2
- data/lib/parsers/bmp_parser.rb +34 -6
- data/lib/parsers/cr2_parser.rb +2 -2
- data/lib/parsers/dpx_parser.rb +2 -2
- data/lib/parsers/exif_parser.rb +8 -2
- data/lib/parsers/fdx_parser.rb +2 -2
- data/lib/parsers/flac_parser.rb +2 -2
- data/lib/parsers/gif_parser.rb +2 -2
- data/lib/parsers/jpeg_parser.rb +4 -0
- data/lib/parsers/moov_parser.rb +2 -2
- data/lib/parsers/mp3_parser.rb +2 -2
- data/lib/parsers/ogg_parser.rb +2 -2
- data/lib/parsers/pdf_parser.rb +2 -2
- data/lib/parsers/png_parser.rb +2 -2
- data/lib/parsers/psd_parser.rb +2 -2
- data/lib/parsers/tiff_parser.rb +2 -2
- data/lib/parsers/wav_parser.rb +2 -2
- data/lib/parsers/zip_parser.rb +2 -2
- data/spec/parsers/bmp_parser_spec.rb +28 -0
- data/spec/parsers/exif_parser_spec.rb +9 -5
- data/spec/parsers/zip_parser_spec.rb +2 -2
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45efce1fcb5395b66713b4704911473a6aaf6beab8dced2275299d05d42f051c
|
4
|
+
data.tar.gz: 760d1d686400e97cb58296bbf06862be7a19fedd6b2684075530c089d6685eac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f3b357ff7b4121c4cad07a82ca94f13a4e92f3657e8984aa61a1c1a67f6144f726174a09b3b99c3c29b75dcd4c81970a5613e0e5a79e7c4eef52dbcdb779a50
|
7
|
+
data.tar.gz: 712e87ef7d506abcf7096d16c738058320dac9c1f2b2557ce08c6576748b37d3041bbe3d43260dcf846bfa7062a5de2840e30782e8c8edaabd15a6b19146d344
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 0.17.0
|
2
|
+
* Remove parser factories. A parser should respond to `likely_match?` and `call`. If a parser has to be instantiated anew for
|
3
|
+
every call the parser should take care of instantiating itself.
|
4
|
+
* Add support for BMP files with core headers (older version of the BMP format)
|
5
|
+
|
6
|
+
## 0.16.2
|
7
|
+
* All EXIF: Deal with EXIF orientations that get parsed as an array of [Orientation, nil] due to incorrect padding
|
8
|
+
|
1
9
|
## 0.16.1
|
2
10
|
* All EXIF: Make sure the 0 orientation does not get silently treated as orientation 8, mislabling
|
3
11
|
images which are not rotated as being rotated (orientation changed)
|
data/lib/format_parser.rb
CHANGED
@@ -244,40 +244,25 @@ module FormatParser
|
|
244
244
|
|
245
245
|
fitting_by_natures = assemble_parser_set[@parsers_per_nature, desired_natures]
|
246
246
|
fitting_by_formats = assemble_parser_set[@parsers_per_format, desired_formats]
|
247
|
-
|
247
|
+
parsers = fitting_by_natures & fitting_by_formats
|
248
248
|
|
249
|
-
if
|
249
|
+
if parsers.empty?
|
250
250
|
raise ArgumentError, "No parsers provide both natures #{desired_natures.inspect} and formats #{desired_formats.inspect}"
|
251
251
|
end
|
252
252
|
|
253
253
|
# Order the parsers according to their priority value. The ones having a lower
|
254
254
|
# value will sort higher and will be applied sooner
|
255
|
-
|
256
|
-
@parser_priorities[
|
255
|
+
parsers_in_order_of_priority = parsers.to_a.sort do |parser_a, parser_b|
|
256
|
+
@parser_priorities[parser_a] <=> @parser_priorities[parser_b]
|
257
257
|
end
|
258
258
|
|
259
259
|
# If there is one parser that is more likely to match, place it first
|
260
|
-
if first_match =
|
261
|
-
|
262
|
-
|
260
|
+
if first_match = parsers_in_order_of_priority.find { |f| f.respond_to?(:likely_match?) && f.likely_match?(filename_hint) }
|
261
|
+
parsers_in_order_of_priority.delete(first_match)
|
262
|
+
parsers_in_order_of_priority.unshift(first_match)
|
263
263
|
end
|
264
264
|
|
265
|
-
|
266
|
-
end
|
267
|
-
|
268
|
-
# Instantiates a parser object (an object that responds to `#call`) from a given class
|
269
|
-
# or returns the parameter as is if it is callable by itself - i.e. if it is a Proc
|
270
|
-
#
|
271
|
-
# @param callable_or_responding_to_new[#call, #new] a callable or a Class/Module
|
272
|
-
# @return [#call] a parser that can be called with an IO-ish argument
|
273
|
-
def self.instantiate_parser(callable_or_responding_to_new)
|
274
|
-
if callable_or_responding_to_new.respond_to?(:call)
|
275
|
-
callable_or_responding_to_new
|
276
|
-
elsif callable_or_responding_to_new.respond_to?(:new)
|
277
|
-
callable_or_responding_to_new.new
|
278
|
-
else
|
279
|
-
raise ArgumentError, 'A parser should be either a class with an instance method #call or a Proc'
|
280
|
-
end
|
265
|
+
parsers_in_order_of_priority
|
281
266
|
end
|
282
267
|
|
283
268
|
def self.string_to_lossy_utf8(str)
|
data/lib/parsers/aiff_parser.rb
CHANGED
@@ -18,7 +18,7 @@ class FormatParser::AIFFParser
|
|
18
18
|
'ANNO',
|
19
19
|
]
|
20
20
|
|
21
|
-
def
|
21
|
+
def likely_match?(filename)
|
22
22
|
filename =~ /\.aiff?$/i
|
23
23
|
end
|
24
24
|
|
@@ -84,5 +84,5 @@ class FormatParser::AIFFParser
|
|
84
84
|
(sign == '1' ? -1.0 : 1.0) * (fraction.to_f / ((1 << 63) - 1)) * (2**exponent)
|
85
85
|
end
|
86
86
|
|
87
|
-
FormatParser.register_parser
|
87
|
+
FormatParser.register_parser new, natures: :audio, formats: :aiff
|
88
88
|
end
|
data/lib/parsers/bmp_parser.rb
CHANGED
@@ -4,9 +4,9 @@ class FormatParser::BMPParser
|
|
4
4
|
include FormatParser::IOUtils
|
5
5
|
|
6
6
|
VALID_BMP = 'BM'
|
7
|
-
PERMISSIBLE_PIXEL_ARRAY_LOCATIONS =
|
7
|
+
PERMISSIBLE_PIXEL_ARRAY_LOCATIONS = 26..512
|
8
8
|
|
9
|
-
def
|
9
|
+
def likely_match?(filename)
|
10
10
|
filename =~ /\.bmp$/i
|
11
11
|
end
|
12
12
|
|
@@ -21,14 +21,41 @@ class FormatParser::BMPParser
|
|
21
21
|
return unless PERMISSIBLE_PIXEL_ARRAY_LOCATIONS.cover?(pix_array_location)
|
22
22
|
|
23
23
|
dib_header = safe_read(io, 40)
|
24
|
+
header_size = dib_header.unpack('V')[0]
|
25
|
+
case header_size
|
26
|
+
when 12 # OS21XBITMAPHEADER
|
27
|
+
parse_bitmap_core_header(dib_header)
|
28
|
+
else # More modern implementations
|
29
|
+
parse_modern_header(dib_header)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_bitmap_core_header(dib_header)
|
34
|
+
_header_size, width, height, _num_color_planes, bit_depth = dib_header.unpack('VSSSS')
|
35
|
+
|
36
|
+
# In core bitmap format an unsigned int is used for dimensions,
|
37
|
+
# no inverse scan order is possible
|
38
|
+
data_order = :normal
|
39
|
+
|
40
|
+
FormatParser::Image.new(
|
41
|
+
format: :bmp,
|
42
|
+
width_px: width,
|
43
|
+
height_px: height,
|
44
|
+
color_mode: :rgb,
|
45
|
+
intrinsics: {
|
46
|
+
data_order: data_order,
|
47
|
+
bits_per_pixel: bit_depth
|
48
|
+
}
|
49
|
+
)
|
50
|
+
end
|
24
51
|
|
25
|
-
|
52
|
+
def parse_modern_header(dib_header)
|
53
|
+
_header_size, width, height, _planes, bits_per_pixel,
|
26
54
|
_compression_method, _image_size, horizontal_res,
|
27
55
|
vertical_res, _n_colors, _i_colors = dib_header.unpack('Vl<2v2V2l<2V2')
|
28
56
|
|
29
57
|
# There are cases where the height might by negative indicating the data
|
30
58
|
# is ordered from top to bottom instead of bottom to top
|
31
|
-
# http://www.dragonwins.com/domains/getteched/bmp/bmpfileformat.htm#The%20Image%20Header
|
32
59
|
data_order = height < 0 ? :inverse : :normal
|
33
60
|
|
34
61
|
FormatParser::Image.new(
|
@@ -39,10 +66,11 @@ class FormatParser::BMPParser
|
|
39
66
|
intrinsics: {
|
40
67
|
vertical_resolution: vertical_res,
|
41
68
|
horizontal_resolution: horizontal_res,
|
42
|
-
data_order: data_order
|
69
|
+
data_order: data_order,
|
70
|
+
bits_per_pixel: bits_per_pixel,
|
43
71
|
}
|
44
72
|
)
|
45
73
|
end
|
46
74
|
|
47
|
-
FormatParser.register_parser
|
75
|
+
FormatParser.register_parser new, natures: :image, formats: :bmp
|
48
76
|
end
|
data/lib/parsers/cr2_parser.rb
CHANGED
@@ -7,7 +7,7 @@ class FormatParser::CR2Parser
|
|
7
7
|
TIFF_HEADER = [0x49, 0x49, 0x2a, 0x00]
|
8
8
|
CR2_HEADER = [0x43, 0x52, 0x02, 0x00]
|
9
9
|
|
10
|
-
def
|
10
|
+
def likely_match?(filename)
|
11
11
|
filename =~ /\.cr2$/i
|
12
12
|
end
|
13
13
|
|
@@ -44,5 +44,5 @@ class FormatParser::CR2Parser
|
|
44
44
|
nil
|
45
45
|
end
|
46
46
|
|
47
|
-
FormatParser.register_parser
|
47
|
+
FormatParser.register_parser new, natures: :image, formats: :cr2
|
48
48
|
end
|
data/lib/parsers/dpx_parser.rb
CHANGED
@@ -19,7 +19,7 @@ class FormatParser::DPXParser
|
|
19
19
|
|
20
20
|
private_constant :ByteOrderHintIO
|
21
21
|
|
22
|
-
def
|
22
|
+
def likely_match?(filename)
|
23
23
|
filename =~ /\.dpx$/i
|
24
24
|
end
|
25
25
|
|
@@ -59,5 +59,5 @@ class FormatParser::DPXParser
|
|
59
59
|
)
|
60
60
|
end
|
61
61
|
|
62
|
-
FormatParser.register_parser
|
62
|
+
FormatParser.register_parser new, natures: :image, formats: :dpx
|
63
63
|
end
|
data/lib/parsers/exif_parser.rb
CHANGED
@@ -42,7 +42,7 @@ module FormatParser::EXIFParser
|
|
42
42
|
|
43
43
|
class EXIFResult < SimpleDelegator
|
44
44
|
def rotated?
|
45
|
-
|
45
|
+
orientation.to_i > 4
|
46
46
|
end
|
47
47
|
|
48
48
|
def to_json(*maybe_coder)
|
@@ -52,7 +52,11 @@ module FormatParser::EXIFParser
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def orientation
|
55
|
-
|
55
|
+
# In some EXIF tags the value type is set oddly - it unpacks into multiple values,
|
56
|
+
# and it will look like this: [#<EXIFR::TIFF::Orientation:TopLeft(1)>, nil]
|
57
|
+
orientation_values = Array(__getobj__.orientation)
|
58
|
+
last_usable_value = orientation_values.compact[-1] # Use the last non-nil one
|
59
|
+
last_usable_value.to_i
|
56
60
|
end
|
57
61
|
|
58
62
|
def orientation_sym
|
@@ -162,4 +166,6 @@ module FormatParser::EXIFParser
|
|
162
166
|
raw_exif_data ? EXIFResult.new(raw_exif_data) : nil
|
163
167
|
end
|
164
168
|
end
|
169
|
+
|
170
|
+
extend self
|
165
171
|
end
|
data/lib/parsers/fdx_parser.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class FormatParser::FDXParser
|
2
2
|
include FormatParser::IOUtils
|
3
3
|
|
4
|
-
def
|
4
|
+
def likely_match?(filename)
|
5
5
|
filename =~ /\.fdx$/i
|
6
6
|
end
|
7
7
|
|
@@ -30,5 +30,5 @@ class FormatParser::FDXParser
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
FormatParser.register_parser
|
33
|
+
FormatParser.register_parser new, natures: :document, formats: :fdx
|
34
34
|
end
|
data/lib/parsers/flac_parser.rb
CHANGED
@@ -5,7 +5,7 @@ class FormatParser::FLACParser
|
|
5
5
|
MAGIC_BYTE_STRING = 'fLaC'
|
6
6
|
BLOCK_HEADER_BYTES = 4
|
7
7
|
|
8
|
-
def
|
8
|
+
def likely_match?(filename)
|
9
9
|
filename =~ /\.flac$/i
|
10
10
|
end
|
11
11
|
|
@@ -75,5 +75,5 @@ class FormatParser::FLACParser
|
|
75
75
|
s.unpack('B*')[0].to_i(2)
|
76
76
|
end
|
77
77
|
|
78
|
-
FormatParser.register_parser
|
78
|
+
FormatParser.register_parser new, natures: :audio, formats: :flac
|
79
79
|
end
|
data/lib/parsers/gif_parser.rb
CHANGED
@@ -4,7 +4,7 @@ class FormatParser::GIFParser
|
|
4
4
|
HEADERS = ['GIF87a', 'GIF89a'].map(&:b)
|
5
5
|
NETSCAPE_AND_AUTHENTICATION_CODE = 'NETSCAPE2.0'
|
6
6
|
|
7
|
-
def
|
7
|
+
def likely_match?(filename)
|
8
8
|
filename =~ /\.gif$/i
|
9
9
|
end
|
10
10
|
|
@@ -48,5 +48,5 @@ class FormatParser::GIFParser
|
|
48
48
|
)
|
49
49
|
end
|
50
50
|
|
51
|
-
FormatParser.register_parser
|
51
|
+
FormatParser.register_parser new, natures: :image, formats: :gif, priority: 0
|
52
52
|
end
|
data/lib/parsers/jpeg_parser.rb
CHANGED
data/lib/parsers/moov_parser.rb
CHANGED
@@ -11,7 +11,7 @@ class FormatParser::MOOVParser
|
|
11
11
|
'm4a ' => :m4a,
|
12
12
|
}
|
13
13
|
|
14
|
-
def
|
14
|
+
def likely_match?(filename)
|
15
15
|
filename =~ /\.(mov|m4a|ma4|mp4|aac)$/i
|
16
16
|
end
|
17
17
|
|
@@ -87,5 +87,5 @@ class FormatParser::MOOVParser
|
|
87
87
|
maybe_atom_size >= minimum_ftyp_atom_size && maybe_ftyp_atom_signature == 'ftyp'
|
88
88
|
end
|
89
89
|
|
90
|
-
FormatParser.register_parser
|
90
|
+
FormatParser.register_parser new, natures: :video, formats: FTYP_MAP.values, priority: 1
|
91
91
|
end
|
data/lib/parsers/mp3_parser.rb
CHANGED
@@ -53,7 +53,7 @@ class FormatParser::MP3Parser
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
56
|
+
def likely_match?(filename)
|
57
57
|
filename =~ /\.mp3$/i
|
58
58
|
end
|
59
59
|
|
@@ -297,5 +297,5 @@ class FormatParser::MP3Parser
|
|
297
297
|
attrs
|
298
298
|
end
|
299
299
|
|
300
|
-
FormatParser.register_parser
|
300
|
+
FormatParser.register_parser new, natures: :audio, formats: :mp3, priority: 99
|
301
301
|
end
|
data/lib/parsers/ogg_parser.rb
CHANGED
@@ -6,7 +6,7 @@ class FormatParser::OggParser
|
|
6
6
|
# Maximum size of an Ogg page
|
7
7
|
MAX_POSSIBLE_PAGE_SIZE = 65307
|
8
8
|
|
9
|
-
def
|
9
|
+
def likely_match?(filename)
|
10
10
|
filename =~ /\.ogg$/i
|
11
11
|
end
|
12
12
|
|
@@ -218,5 +218,5 @@ class FormatParser::OggParser
|
|
218
218
|
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
219
219
|
].freeze
|
220
220
|
|
221
|
-
FormatParser.register_parser
|
221
|
+
FormatParser.register_parser new, natures: :audio, formats: :ogg
|
222
222
|
end
|
data/lib/parsers/pdf_parser.rb
CHANGED
@@ -9,7 +9,7 @@ class FormatParser::PDFParser
|
|
9
9
|
#
|
10
10
|
PDF_MARKER = /%PDF-1\.[0-8]{1}/
|
11
11
|
|
12
|
-
def
|
12
|
+
def likely_match?(filename)
|
13
13
|
filename =~ /\.(pdf|ai)$/i
|
14
14
|
end
|
15
15
|
|
@@ -21,5 +21,5 @@ class FormatParser::PDFParser
|
|
21
21
|
FormatParser::Document.new(format: :pdf)
|
22
22
|
end
|
23
23
|
|
24
|
-
FormatParser.register_parser
|
24
|
+
FormatParser.register_parser new, natures: :document, formats: :pdf, priority: 1
|
25
25
|
end
|
data/lib/parsers/png_parser.rb
CHANGED
@@ -15,7 +15,7 @@ class FormatParser::PNGParser
|
|
15
15
|
6 => true,
|
16
16
|
}
|
17
17
|
|
18
|
-
def
|
18
|
+
def likely_match?(filename)
|
19
19
|
filename =~ /\.png$/i
|
20
20
|
end
|
21
21
|
|
@@ -75,5 +75,5 @@ class FormatParser::PNGParser
|
|
75
75
|
end
|
76
76
|
|
77
77
|
# Give it priority 1 since priority 0 is reserved for JPEG, our most popular
|
78
|
-
FormatParser.register_parser
|
78
|
+
FormatParser.register_parser new, natures: :image, formats: :png, priority: 1
|
79
79
|
end
|
data/lib/parsers/psd_parser.rb
CHANGED
@@ -3,7 +3,7 @@ class FormatParser::PSDParser
|
|
3
3
|
|
4
4
|
PSD_HEADER = [0x38, 0x42, 0x50, 0x53]
|
5
5
|
|
6
|
-
def
|
6
|
+
def likely_match?(filename)
|
7
7
|
filename =~ /\.psd$/i # Maybe also PSB at some point
|
8
8
|
end
|
9
9
|
|
@@ -23,5 +23,5 @@ class FormatParser::PSDParser
|
|
23
23
|
)
|
24
24
|
end
|
25
25
|
|
26
|
-
FormatParser.register_parser
|
26
|
+
FormatParser.register_parser new, natures: :image, formats: :psd
|
27
27
|
end
|
data/lib/parsers/tiff_parser.rb
CHANGED
@@ -5,7 +5,7 @@ class FormatParser::TIFFParser
|
|
5
5
|
MAGIC_LE = [0x49, 0x49, 0x2A, 0x0].pack('C4')
|
6
6
|
MAGIC_BE = [0x4D, 0x4D, 0x0, 0x2A].pack('C4')
|
7
7
|
|
8
|
-
def
|
8
|
+
def likely_match?(filename)
|
9
9
|
filename =~ /\.tiff?$/i
|
10
10
|
end
|
11
11
|
|
@@ -43,5 +43,5 @@ class FormatParser::TIFFParser
|
|
43
43
|
safe_read(io, 2) == 'CR'
|
44
44
|
end
|
45
45
|
|
46
|
-
FormatParser.register_parser
|
46
|
+
FormatParser.register_parser new, natures: :image, formats: :tif
|
47
47
|
end
|
data/lib/parsers/wav_parser.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class FormatParser::WAVParser
|
2
2
|
include FormatParser::IOUtils
|
3
3
|
|
4
|
-
def
|
4
|
+
def likely_match?(filename)
|
5
5
|
filename =~ /\.wav$/i
|
6
6
|
end
|
7
7
|
|
@@ -99,5 +99,5 @@ class FormatParser::WAVParser
|
|
99
99
|
)
|
100
100
|
end
|
101
101
|
|
102
|
-
FormatParser.register_parser
|
102
|
+
FormatParser.register_parser new, natures: :audio, formats: :wav
|
103
103
|
end
|
data/lib/parsers/zip_parser.rb
CHANGED
@@ -5,7 +5,7 @@ class FormatParser::ZIPParser
|
|
5
5
|
include OfficeFormats
|
6
6
|
include FormatParser::IOUtils
|
7
7
|
|
8
|
-
def
|
8
|
+
def likely_match?(filename)
|
9
9
|
filename =~ /\.(zip|docx|keynote|numbers|pptx|xlsx)$/i
|
10
10
|
end
|
11
11
|
|
@@ -58,5 +58,5 @@ class FormatParser::ZIPParser
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
FormatParser.register_parser
|
61
|
+
FormatParser.register_parser new, natures: [:archive, :document], formats: :zip, priority: 2
|
62
62
|
end
|
@@ -17,6 +17,7 @@ describe FormatParser::BMPParser do
|
|
17
17
|
expect(parsed.intrinsics[:vertical_resolution]).to eq(2834)
|
18
18
|
expect(parsed.intrinsics[:horizontal_resolution]).to eq(2834)
|
19
19
|
expect(parsed.intrinsics[:data_order]).to eq(:normal)
|
20
|
+
expect(parsed.intrinsics[:bits_per_pixel]).to eq(24)
|
20
21
|
end
|
21
22
|
|
22
23
|
it 'parses a BMP file with negative height_px values (divergent scan order)' do
|
@@ -35,6 +36,7 @@ describe FormatParser::BMPParser do
|
|
35
36
|
expect(parsed.intrinsics[:vertical_resolution]).to eq(2835)
|
36
37
|
expect(parsed.intrinsics[:horizontal_resolution]).to eq(2835)
|
37
38
|
expect(parsed.intrinsics[:data_order]).to eq(:inverse)
|
39
|
+
expect(parsed.intrinsics[:bits_per_pixel]).to eq(24)
|
38
40
|
end
|
39
41
|
|
40
42
|
it 'parses a BMP where the pixel array location is other than 54' do
|
@@ -52,6 +54,32 @@ describe FormatParser::BMPParser do
|
|
52
54
|
expect(parsed.intrinsics).not_to be_nil
|
53
55
|
end
|
54
56
|
|
57
|
+
it 'parses various BMP headers' do
|
58
|
+
bmp_path = fixtures_dir + '/BMP/test_v5header.bmp'
|
59
|
+
parsed = subject.call(File.open(bmp_path, 'rb'))
|
60
|
+
|
61
|
+
expect(parsed).not_to be_nil
|
62
|
+
expect(parsed.nature).to eq(:image)
|
63
|
+
expect(parsed.format).to eq(:bmp)
|
64
|
+
expect(parsed.color_mode).to eq(:rgb)
|
65
|
+
expect(parsed.width_px).to eq(40)
|
66
|
+
expect(parsed.height_px).to eq(27)
|
67
|
+
expect(parsed.intrinsics[:bits_per_pixel]).to eq(24)
|
68
|
+
expect(parsed.intrinsics[:data_order]).to eq(:normal)
|
69
|
+
|
70
|
+
bmp_path = fixtures_dir + '/BMP/test_coreheader.bmp'
|
71
|
+
parsed = subject.call(File.open(bmp_path, 'rb'))
|
72
|
+
|
73
|
+
expect(parsed).not_to be_nil
|
74
|
+
expect(parsed.nature).to eq(:image)
|
75
|
+
expect(parsed.format).to eq(:bmp)
|
76
|
+
expect(parsed.color_mode).to eq(:rgb)
|
77
|
+
expect(parsed.width_px).to eq(40)
|
78
|
+
expect(parsed.height_px).to eq(27)
|
79
|
+
expect(parsed.intrinsics[:bits_per_pixel]).to eq(24)
|
80
|
+
expect(parsed.intrinsics[:data_order]).to eq(:normal)
|
81
|
+
end
|
82
|
+
|
55
83
|
it 'refuses to parse a BMP where the pixel array location is very large' do
|
56
84
|
junk_data = [
|
57
85
|
'BM',
|
@@ -1,15 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FormatParser::EXIFParser do
|
4
|
-
let(:subject) do
|
5
|
-
Object.new.tap { |o| o.extend FormatParser::EXIFParser }
|
6
|
-
end
|
7
|
-
|
8
4
|
describe 'is able to correctly parse orientation for all the TIFF EXIF examples from FastImage' do
|
9
5
|
Dir.glob(fixtures_dir + '/exif-orientation-testimages/tiff-*/*.tif').each do |tiff_path|
|
10
6
|
filename = File.basename(tiff_path)
|
11
7
|
it "is able to parse #{filename}" do
|
12
|
-
result =
|
8
|
+
result = described_class.exif_from_tiff_io(File.open(tiff_path, 'rb'))
|
13
9
|
expect(result).not_to be_nil
|
14
10
|
expect(result.orientation_sym).to be_kind_of(Symbol)
|
15
11
|
# Filenames in this dir correspond with the orientation of the file
|
@@ -18,6 +14,14 @@ describe FormatParser::EXIFParser do
|
|
18
14
|
end
|
19
15
|
end
|
20
16
|
|
17
|
+
it 'is able to deal with an orientation tag which a tuple value for orientation' do
|
18
|
+
path = fixtures_dir + '/EXIF/double_orientation.exif.bin'
|
19
|
+
exif_data = File.open(path, 'rb') do |f|
|
20
|
+
described_class.exif_from_tiff_io(f)
|
21
|
+
end
|
22
|
+
expect(exif_data.orientation).to eq(1)
|
23
|
+
end
|
24
|
+
|
21
25
|
describe 'IOExt' do
|
22
26
|
it 'supports readbyte' do
|
23
27
|
io = FormatParser::EXIFParser::IOExt.new(StringIO.new('hello'))
|
@@ -2,8 +2,8 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe FormatParser::ZIPParser do
|
4
4
|
it 'provides filename hints' do
|
5
|
-
expect(
|
6
|
-
expect(
|
5
|
+
expect(subject).to be_likely_match('file.zip')
|
6
|
+
expect(subject).not_to be_likely_match('file.tif')
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'parses a ZIP archive with Zip64 extra fields (due to the number of files)' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: format_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Berman
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ks
|
@@ -303,8 +303,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
303
303
|
- !ruby/object:Gem::Version
|
304
304
|
version: '0'
|
305
305
|
requirements: []
|
306
|
-
|
307
|
-
rubygems_version: 2.7.6
|
306
|
+
rubygems_version: 3.0.6
|
308
307
|
signing_key:
|
309
308
|
specification_version: 4
|
310
309
|
summary: A library for efficient parsing of file metadata
|