format_parser 0.16.1 → 0.17.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/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
|