depix 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/README.txt +1 -1
- data/bin/depix-describe +5 -1
- data/lib/depix.rb +31 -5
- data/lib/depix/dict.rb +16 -2
- data/test/test_depix.rb +18 -4
- data/test/test_dict.rb +43 -7
- metadata +2 -2
data/History.txt
CHANGED
data/README.txt
CHANGED
@@ -8,7 +8,7 @@ Read DPX file metadata
|
|
8
8
|
|
9
9
|
== SYNOPSIS:
|
10
10
|
|
11
|
-
meta = Depix
|
11
|
+
meta = Depix.from_file(dpx_file_path)
|
12
12
|
puts meta.time_code #=> 10:00:00:02
|
13
13
|
|
14
14
|
The data returned is described in the DPX_HEADER_STRUCTURE[link:files/DPX_HEADER_STRUCTURE_txt.html]. It's
|
data/bin/depix-describe
CHANGED
@@ -15,5 +15,9 @@ end.parse!
|
|
15
15
|
ARGV.each do | file |
|
16
16
|
puts "Describing DPX #{file}. Empty elements are omitted.\n\n"
|
17
17
|
puts "===================================================\n\n"
|
18
|
-
|
18
|
+
begin
|
19
|
+
puts Depix.describe_file(file, options[:compact])
|
20
|
+
rescue Depix::InvalidHeader
|
21
|
+
puts " - Invalid header data"
|
22
|
+
end
|
19
23
|
end
|
data/lib/depix.rb
CHANGED
@@ -8,7 +8,9 @@ require File.dirname(__FILE__) + '/depix/compact_structs'
|
|
8
8
|
require File.dirname(__FILE__) + '/depix/enums'
|
9
9
|
|
10
10
|
module Depix
|
11
|
-
VERSION = '1.0.
|
11
|
+
VERSION = '1.0.3'
|
12
|
+
|
13
|
+
class InvalidHeader < RuntimeError; end
|
12
14
|
|
13
15
|
# Offers convenience access to a few common attributes bypassing the piecemeal structs
|
14
16
|
module Synthetics
|
@@ -16,8 +18,10 @@ module Depix
|
|
16
18
|
[film.id, film.type, film.offset, film.prefix, film.count].compact.join(' ')
|
17
19
|
end
|
18
20
|
|
21
|
+
# Return the flame reel name. The data after the first null byte is not meant to be seen and is used by Flame internally
|
22
|
+
# as it seems
|
19
23
|
def flame_reel
|
20
|
-
orientation.device.
|
24
|
+
orientation.device.split("\000").shift
|
21
25
|
end
|
22
26
|
|
23
27
|
def time_code
|
@@ -71,16 +75,38 @@ module Depix
|
|
71
75
|
|
72
76
|
def from_file(path, compact)
|
73
77
|
header = File.open(path, 'r') { |f| f.read(DPX.length) }
|
74
|
-
|
78
|
+
begin
|
79
|
+
parse(header, compact)
|
80
|
+
rescue InvalidHeader => e
|
81
|
+
raise InvalidHeader, "Invalid header in file #{path}"
|
82
|
+
end
|
75
83
|
end
|
76
84
|
|
77
85
|
# The hear of Depix
|
78
86
|
def parse(data, compact)
|
79
87
|
magic = data[0..3]
|
88
|
+
|
89
|
+
raise InvalidHeader unless %w( SDPX XPDS).include?(magic)
|
90
|
+
|
80
91
|
struct = compact ? CompactDPX : DPX
|
81
92
|
|
82
|
-
|
83
|
-
|
93
|
+
is_be = (magic == "SDPX")
|
94
|
+
version_check = FileInfo.only(:magic, :version)
|
95
|
+
|
96
|
+
result = begin
|
97
|
+
if is_be
|
98
|
+
version_check.consume!(data.unpack(version_check.pattern))
|
99
|
+
else
|
100
|
+
version_check.consume!(data.unpack(make_le(version_check.pattern)))
|
101
|
+
end
|
102
|
+
rescue ArgumentError
|
103
|
+
raise InvalidHeader
|
104
|
+
end
|
105
|
+
|
106
|
+
raise InvalidHeader unless result.version == "V1.0"
|
107
|
+
|
108
|
+
template = is_be ? DPX.pattern : make_le(DPX.pattern)
|
109
|
+
struct.consume!(data.unpack(struct.pattern))
|
84
110
|
end
|
85
111
|
|
86
112
|
# Describe a filled DPX structure
|
data/lib/depix/dict.rb
CHANGED
@@ -54,6 +54,7 @@ module Depix
|
|
54
54
|
|
55
55
|
class U32Field < Field
|
56
56
|
BLANK = 0xFFFFFFFF
|
57
|
+
undef :length=, :pattern=
|
57
58
|
|
58
59
|
def pattern
|
59
60
|
"N"
|
@@ -69,6 +70,7 @@ module Depix
|
|
69
70
|
end
|
70
71
|
|
71
72
|
class U8Field < Field
|
73
|
+
undef :length=, :pattern=
|
72
74
|
|
73
75
|
BLANK = 0xFF
|
74
76
|
|
@@ -90,6 +92,7 @@ module Depix
|
|
90
92
|
end
|
91
93
|
|
92
94
|
class Filler < Field
|
95
|
+
undef :pattern=
|
93
96
|
def pattern
|
94
97
|
"x#{length ? length.to_i : 1}"
|
95
98
|
end
|
@@ -102,6 +105,7 @@ module Depix
|
|
102
105
|
|
103
106
|
class U16Field < Field
|
104
107
|
BLANK = 0xFFFF
|
108
|
+
undef :length=, :pattern=
|
105
109
|
|
106
110
|
def pattern
|
107
111
|
"n"
|
@@ -121,6 +125,8 @@ module Depix
|
|
121
125
|
end
|
122
126
|
|
123
127
|
class R32Field < Field
|
128
|
+
undef :length=, :pattern=
|
129
|
+
|
124
130
|
def pattern
|
125
131
|
"g"
|
126
132
|
end
|
@@ -140,6 +146,12 @@ module Depix
|
|
140
146
|
|
141
147
|
class CharField < Field
|
142
148
|
BLANK = "\0"
|
149
|
+
undef :pattern=
|
150
|
+
|
151
|
+
BLANKING_VALUES = [0x00.chr, 0xFF.chr]
|
152
|
+
BLANKING_PATTERNS = BLANKING_VALUES.inject([]) do | p, char |
|
153
|
+
p << /^(#{char}+)/ << /(#{char}+)$/
|
154
|
+
end
|
143
155
|
|
144
156
|
def pattern
|
145
157
|
"A#{(length || 1).to_i}"
|
@@ -149,8 +161,8 @@ module Depix
|
|
149
161
|
if v == BLANK
|
150
162
|
nil
|
151
163
|
else
|
152
|
-
|
153
|
-
|
164
|
+
2.times { BLANKING_PATTERNS.each{|p| v.gsub!(p, '')} }
|
165
|
+
v.empty? ? nil : v
|
154
166
|
end
|
155
167
|
end
|
156
168
|
|
@@ -320,6 +332,8 @@ module Depix
|
|
320
332
|
|
321
333
|
anon = Class.new(self)
|
322
334
|
anon.fields.replace(distillate)
|
335
|
+
only_items = distillate.map{|n| n.name }
|
336
|
+
|
323
337
|
anon
|
324
338
|
end
|
325
339
|
|
data/test/test_depix.rb
CHANGED
@@ -4,7 +4,7 @@ require 'test/unit'
|
|
4
4
|
class ReaderTest < Test::Unit::TestCase
|
5
5
|
|
6
6
|
SAMPLE_DPX = File.dirname(__FILE__) + '/samples/E012_P001_L000002_lin.0001.dpx'
|
7
|
-
|
7
|
+
|
8
8
|
def test_parsed_properly
|
9
9
|
file = SAMPLE_DPX
|
10
10
|
parsed = Depix.from_file(file)
|
@@ -38,8 +38,10 @@ class ReaderTest < Test::Unit::TestCase
|
|
38
38
|
assert_equal 8192, parsed.image.image_elements[0].data_offset
|
39
39
|
assert_equal 0, parsed.image.image_elements[0].end_of_line_padding
|
40
40
|
assert_equal 0, parsed.image.image_elements[0].end_of_image_padding
|
41
|
-
assert_equal "IMAGE DESCRIPTION DATA
|
42
|
-
assert_equal "
|
41
|
+
assert_equal "IMAGE DESCRIPTION DATA \000P", parsed.image.image_elements[0].description
|
42
|
+
assert_equal "E012\000\000\000\000x\340\264\020\000\000\000\000\005",
|
43
|
+
parsed.orientation.device #- this is where Flame writes the reel
|
44
|
+
|
43
45
|
assert_equal 853, parsed.orientation.aspect_ratio[0]
|
44
46
|
assert_equal 640, parsed.orientation.aspect_ratio[1]
|
45
47
|
|
@@ -66,7 +68,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
66
68
|
assert_equal "01:15:11:18", parsed.time_code.to_s
|
67
69
|
assert_equal :RGB, parsed.component_type
|
68
70
|
assert_equal :Linear, parsed.colorimetric
|
69
|
-
assert_equal "
|
71
|
+
assert_equal "E012", parsed.flame_reel
|
70
72
|
end
|
71
73
|
|
72
74
|
def test_parsed_properly_using_compact_structs
|
@@ -81,4 +83,16 @@ class ReaderTest < Test::Unit::TestCase
|
|
81
83
|
assert_match(/Offset to data for this image element/, desc)
|
82
84
|
end
|
83
85
|
end
|
86
|
+
|
87
|
+
def test_parsing_something_else_should_raise
|
88
|
+
s = "Mary had a little lamb"
|
89
|
+
assert_raise(Depix::InvalidHeader) { Depix.from_string(s) }
|
90
|
+
|
91
|
+
s = "Mary had a little lamb" * 1000
|
92
|
+
assert_raise(Depix::InvalidHeader) { Depix.from_string(s) }
|
93
|
+
|
94
|
+
s = "SDPX Mary had a little lamb" * 1000
|
95
|
+
assert_raise(Depix::InvalidHeader) { Depix.from_string(s) }
|
96
|
+
|
97
|
+
end
|
84
98
|
end
|
data/test/test_dict.rb
CHANGED
@@ -13,6 +13,10 @@ module FieldConformity
|
|
13
13
|
assert_respond_to f, :rtype
|
14
14
|
assert_respond_to f, :explain
|
15
15
|
end
|
16
|
+
|
17
|
+
def assert_method_removed(f, method)
|
18
|
+
fail("#{f.inspect} should not respond to #{method}") if f.respond_to?(method)
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
class FieldExplainsItself < Test::Unit::TestCase
|
@@ -124,9 +128,15 @@ class TestArrayField < Test::Unit::TestCase
|
|
124
128
|
conform_field!(f)
|
125
129
|
|
126
130
|
assert_respond_to f, :name=
|
127
|
-
|
128
|
-
|
129
|
-
|
131
|
+
|
132
|
+
assert_method_removed f, :length=
|
133
|
+
assert_method_removed f, :pattern=
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_array_does_not_allow_setting_length
|
137
|
+
f = ArrayField.new
|
138
|
+
assert_method_removed(f, :length=)
|
139
|
+
assert_method_removed(f, :pattern=)
|
130
140
|
end
|
131
141
|
|
132
142
|
def test_array_field_has_members
|
@@ -162,8 +172,8 @@ class TestInnerField < Test::Unit::TestCase
|
|
162
172
|
assert_respond_to f, :cast
|
163
173
|
assert_respond_to f, :cast=
|
164
174
|
|
165
|
-
|
166
|
-
|
175
|
+
assert_method_removed(f, :length=)
|
176
|
+
assert_method_removed(f, :pattern=)
|
167
177
|
end
|
168
178
|
|
169
179
|
def test_inner_field_asks_cast_for_pattern_and_length
|
@@ -173,6 +183,10 @@ class TestInnerField < Test::Unit::TestCase
|
|
173
183
|
casted = InnerField.new(:cast => sample)
|
174
184
|
assert_equal 123, casted.length
|
175
185
|
assert_equal 'C123', casted.pattern
|
186
|
+
|
187
|
+
assert_method_removed(casted, :length=)
|
188
|
+
assert_method_removed(casted, :pattern=)
|
189
|
+
|
176
190
|
end
|
177
191
|
|
178
192
|
def test_rtype_for_inner_field_is_cast
|
@@ -203,6 +217,7 @@ class TestCharField < Test::Unit::TestCase
|
|
203
217
|
def test_char_field_conforms_to_basics
|
204
218
|
f = CharField.new :name => :foo
|
205
219
|
conform_field!(f)
|
220
|
+
assert_method_removed(f, :pattern=)
|
206
221
|
end
|
207
222
|
|
208
223
|
def test_char_field_pads
|
@@ -213,14 +228,19 @@ class TestCharField < Test::Unit::TestCase
|
|
213
228
|
assert_equal String, f.rtype
|
214
229
|
end
|
215
230
|
|
216
|
-
def
|
231
|
+
def test_char_field_does_not_clean_inner_nulls
|
217
232
|
f = CharField.new :name => :foo, :length => 15
|
218
|
-
assert_equal "foo", f.clean("\0\0foo")
|
233
|
+
assert_equal "foo\0foo", f.clean("\0\0foo\0foo\0")
|
234
|
+
assert_equal "swoop\377\0bla", f.clean("\0\0\0\377\377swoop\377\0bla\0\0\0\377\377\377\377\0\0\0")
|
219
235
|
end
|
220
236
|
|
221
237
|
def test_char_field_clean_blank
|
222
238
|
f = CharField.new :name => :foo, :length => 15
|
223
239
|
assert_equal nil, f.clean("\0")
|
240
|
+
assert_equal nil, f.clean("\0\0\0\0\0\0")
|
241
|
+
assert_equal nil, f.clean("\0\0\0\377\377\0\0\0")
|
242
|
+
assert_equal "foo\0foo", f.clean("\0\0foo\0foo\0")
|
243
|
+
|
224
244
|
end
|
225
245
|
end
|
226
246
|
|
@@ -249,6 +269,10 @@ class TestSmallintField < Test::Unit::TestCase
|
|
249
269
|
def test_smallint_conformity
|
250
270
|
f = U8Field.new :name => :foo
|
251
271
|
conform_field!(f)
|
272
|
+
|
273
|
+
assert_method_removed(f, :pattern=)
|
274
|
+
assert_method_removed(f, :length=)
|
275
|
+
|
252
276
|
end
|
253
277
|
|
254
278
|
def test_smallint_operation
|
@@ -274,6 +298,9 @@ class TestDoubleField < Test::Unit::TestCase
|
|
274
298
|
def test_double_conformity
|
275
299
|
f = U16Field.new :name => :foo
|
276
300
|
conform_field!(f)
|
301
|
+
|
302
|
+
assert_method_removed(f, :pattern=)
|
303
|
+
assert_method_removed(f, :length=)
|
277
304
|
end
|
278
305
|
|
279
306
|
def test_double_operation
|
@@ -301,6 +328,10 @@ class TestFillerField < Test::Unit::TestCase
|
|
301
328
|
assert_equal "x1", f.pattern
|
302
329
|
end
|
303
330
|
|
331
|
+
def test_filler_does_not_allow_setting_pattern
|
332
|
+
assert_method_removed(Filler.new, :pattern=)
|
333
|
+
end
|
334
|
+
|
304
335
|
def test_pattern_discards_value
|
305
336
|
data = [1,2,3].pack("ccc")
|
306
337
|
filler = Filler.new(:length => 3)
|
@@ -596,11 +627,16 @@ class TestDictCompact < Test::Unit::TestCase
|
|
596
627
|
assert_equal distill.length, c.length, "The distilled struct should occupy the same space"
|
597
628
|
assert_equal 3, distill.fields.length
|
598
629
|
|
630
|
+
result = distill.apply!("abcdefhjhjkujkdkklsalierioeiore")
|
631
|
+
|
599
632
|
assert_kind_of Filler, distill.fields[0]
|
600
633
|
assert_equal 5, distill.fields[0].length
|
601
634
|
|
602
635
|
assert_kind_of Filler, distill.fields[2]
|
603
636
|
assert_equal 14, distill.fields[2].length
|
637
|
+
|
638
|
+
assert_nil result.some
|
639
|
+
assert_nil result.fourth
|
604
640
|
end
|
605
641
|
|
606
642
|
def test_get_filler
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: depix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-12-
|
12
|
+
date: 2008-12-23 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|