depix 2.0.0 → 3.0.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.
- data/.travis.yml +4 -0
- data/DPX_HEADER_STRUCTURE.rdoc +5 -5
- data/Gemfile +13 -0
- data/History.txt +14 -0
- data/README.rdoc +15 -3
- data/Rakefile +28 -14
- data/bin/{depix-describe → depix_describe} +5 -4
- data/bin/depix_fix_headers +39 -0
- data/depix.gemspec +93 -0
- data/lib/depix.rb +2 -12
- data/lib/depix/binary/fields.rb +74 -32
- data/lib/depix/binary/{descriptor.rb → rdoc_generator.rb} +5 -1
- data/lib/depix/binary/structure.rb +9 -4
- data/lib/depix/describe.rb +53 -0
- data/lib/depix/reader.rb +15 -40
- data/lib/depix/structs.rb +5 -5
- data/lib/depix/synthetics.rb +12 -2
- data/test/samples/scratch.dpx +0 -0
- data/test/{test_dict.rb → test_binary.rb} +35 -18
- data/test/test_depix.rb +21 -12
- data/test/test_describe.rb +26 -0
- data/test/test_fix_headers.rb +19 -0
- metadata +113 -63
- data/Manifest.txt +0 -28
- data/lib/depix/struct_explainer.rb +0 -59
@@ -1,5 +1,9 @@
|
|
1
|
+
require "stringio"
|
2
|
+
|
1
3
|
# Generates a description of the structure in RDoc format
|
2
|
-
class Depix::Binary::
|
4
|
+
class Depix::Binary::RdocGenerator
|
5
|
+
include Depix::Binary::Fields
|
6
|
+
|
3
7
|
attr_accessor :io, :attr_template, :struct_template
|
4
8
|
|
5
9
|
TPL = <<eof
|
@@ -63,8 +63,14 @@ class Depix::Binary::Structure
|
|
63
63
|
attr_accessor name
|
64
64
|
fields << U16Field.new( {:name => name }.merge(opts) )
|
65
65
|
end
|
66
|
-
|
67
|
-
|
66
|
+
|
67
|
+
# Define a blanking field (it's return value is always nil)
|
68
|
+
def self.blanking(name, *extras)
|
69
|
+
length, opts = count_and_opts_from(extras)
|
70
|
+
attr_accessor name
|
71
|
+
fields << BlankingField.new( {:name => name, :length => length}.merge(opts) )
|
72
|
+
end
|
73
|
+
|
68
74
|
# Define a small unsigned integer
|
69
75
|
def self.u8(name, *extras)
|
70
76
|
count, opts = count_and_opts_from(extras)
|
@@ -182,7 +188,7 @@ class Depix::Binary::Structure
|
|
182
188
|
def self.pack(instance, buffer = nil)
|
183
189
|
|
184
190
|
# Preallocate a buffer just as big as me since we want everything to remain at fixed offsets
|
185
|
-
buffer ||= (
|
191
|
+
buffer ||= (0xFF.chr * length)
|
186
192
|
|
187
193
|
# We need to enforce ASCII-8bit encoding which in Ruby parlance is actually "bytestream"
|
188
194
|
byteify_string(buffer) unless RUBY_VERSION < '1.9.0'
|
@@ -204,7 +210,6 @@ class Depix::Binary::Structure
|
|
204
210
|
|
205
211
|
# Validate the passed value using the format the field supports
|
206
212
|
f.validate!(val)
|
207
|
-
|
208
213
|
packed = f.pack(val)
|
209
214
|
|
210
215
|
# Signal offset violation
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Returns terminal-ready colorized descriptions of DPX headers per file
|
2
|
+
class Depix::Describe
|
3
|
+
include Term::ANSIColor
|
4
|
+
|
5
|
+
# Returns a printable report on all the headers present in the file at the path passed
|
6
|
+
def describe(path, compact = false)
|
7
|
+
struct = Depix.from_file(path, compact)
|
8
|
+
describe_struct(struct) + describe_synthetics_of_struct(struct)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns descriptions of the shorthand synthetic properties
|
12
|
+
def describe_synthetics(path, compact)
|
13
|
+
struct = Depix.from_file(path, compact)
|
14
|
+
describe_synthetics_of_struct(struct)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
# Describe a filled DPX structure
|
20
|
+
def describe_struct(result, pad_offset = 0)
|
21
|
+
result.class.fields.inject([]) do | info, field |
|
22
|
+
value = result.send(field.name)
|
23
|
+
parts = []
|
24
|
+
if value
|
25
|
+
parts << " " * pad_offset
|
26
|
+
parts << red { field.name.to_s }
|
27
|
+
parts << "(#{field.desc})" if field.desc
|
28
|
+
parts << if field.is_a?(Depix::Binary::Fields::InnerField)
|
29
|
+
describe_struct(value, pad_offset + 1)
|
30
|
+
elsif field.is_a?(Depix::Binary::Fields::ArrayField)
|
31
|
+
value.map { | v | v.is_a?(Depix::Binary::Structure) ? describe_struct(v, pad_offset + 1) : v }
|
32
|
+
else
|
33
|
+
blue { value.to_s }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
if parts.any?
|
37
|
+
info << parts.join(' ')
|
38
|
+
end
|
39
|
+
info
|
40
|
+
end.map{|e| (' ' * pad_offset) + e }.join("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def describe_synthetics_of_struct(struct)
|
45
|
+
fields = Depix::Synthetics.instance_methods.reject{|m| m.to_s.include?('=')}.map do | m |
|
46
|
+
[red{ m.to_s }, blue { struct.send(m).to_s }].join(' : ')
|
47
|
+
end
|
48
|
+
fields.unshift("============")
|
49
|
+
fields.unshift(bold { "\nSynthetic properties" })
|
50
|
+
fields.join("\n")
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/lib/depix/reader.rb
CHANGED
@@ -1,19 +1,7 @@
|
|
1
|
+
require 'term/ansicolor'
|
2
|
+
|
1
3
|
module Depix
|
2
4
|
class Reader
|
3
|
-
|
4
|
-
# Returns a printable report on all the headers present in the file at the path passed
|
5
|
-
def describe_file(path, compact = false)
|
6
|
-
header = File.open(path, 'r') { |f| f.read(DPX.length) }
|
7
|
-
struct = parse(header, false)
|
8
|
-
describe_struct(struct) + describe_synthetics_of_struct(struct)
|
9
|
-
end
|
10
|
-
|
11
|
-
def describe_synthetics_of_struct(struct)
|
12
|
-
Synthetics.instance_methods.reject{|m| m.to_s.include?('=')}.map do | m |
|
13
|
-
[m, struct.send(m)].join(' : ')
|
14
|
-
end.unshift("============").unshift("\nSynthetic properties").join("\n")
|
15
|
-
end
|
16
|
-
|
17
5
|
# Parse DPX headers at the start of file
|
18
6
|
def from_file(path, compact)
|
19
7
|
header = File.open(path, 'r') { |f| f.read(DPX.length) }
|
@@ -24,7 +12,19 @@ module Depix
|
|
24
12
|
end
|
25
13
|
end
|
26
14
|
|
27
|
-
# Parse a DPX header (blob of bytes starting at the magic word)
|
15
|
+
# Parse a DPX header (blob of bytes starting at the magic word). The "compact"
|
16
|
+
# flag specifies whether a full-blown parser has to be used. This has substantial
|
17
|
+
# speed implications. For example:
|
18
|
+
# Reading DPX header 1000 times, all data
|
19
|
+
# 1.220000 0.080000 1.300000 ( 1.898979)
|
20
|
+
# Reading DPX header 1000 times, compact data
|
21
|
+
# 0.480000 0.050000 0.530000 ( 0.766509)
|
22
|
+
# This is 2.5 times faster when using compact header form. The compact header form
|
23
|
+
# is usually sufficient for reliable sequence data (it only takes fields which change)
|
24
|
+
# from one frame to another.
|
25
|
+
#
|
26
|
+
# When using the compact form a CompactDPX structure will be returned instead of the
|
27
|
+
# full-blown DPX structure.
|
28
28
|
def parse(data, compact)
|
29
29
|
magic = data[0..3]
|
30
30
|
raise InvalidHeader, "No magic bytes found at start" unless %w( SDPX XPDS).include?(magic)
|
@@ -42,30 +42,5 @@ module Depix
|
|
42
42
|
struct = compact ? CompactDPX : DPX
|
43
43
|
is_le ? struct.apply_le!(data) : struct.apply!(data)
|
44
44
|
end
|
45
|
-
|
46
|
-
# Describe a filled DPX structure
|
47
|
-
def describe_struct(result, pad_offset = 0)
|
48
|
-
result.class.fields.inject([]) do | info, field |
|
49
|
-
value = result.send(field.name)
|
50
|
-
parts = []
|
51
|
-
if value
|
52
|
-
parts << field.desc if field.desc
|
53
|
-
parts << if field.is_a?(Depix::Binary::Fields::InnerField)
|
54
|
-
describe_struct(value, pad_offset + 1)
|
55
|
-
elsif field.is_a?(ArrayField)
|
56
|
-
# Exception for image elements
|
57
|
-
value = result.image_elements[0...result.number_elements] if field.name == :image_elements
|
58
|
-
value.map { | v | v.is_a?(Depix::Binary::Structure) ? describe_struct(v, pad_offset + 2) : v }
|
59
|
-
else
|
60
|
-
value
|
61
|
-
end
|
62
|
-
end
|
63
|
-
if parts.any?
|
64
|
-
info << parts.join(' ')
|
65
|
-
end
|
66
|
-
info
|
67
|
-
end.map{|e| (' ' * pad_offset) + e }.join("\n")
|
68
|
-
end
|
69
|
-
|
70
45
|
end
|
71
46
|
end
|
data/lib/depix/structs.rb
CHANGED
@@ -18,7 +18,7 @@ module Depix
|
|
18
18
|
char :copyright, 200, :desc => 'Copyright'
|
19
19
|
|
20
20
|
u32 :encrypt_key, :desc => 'Encryption key'
|
21
|
-
|
21
|
+
blanking :reserve, 104
|
22
22
|
end
|
23
23
|
|
24
24
|
class FilmInfo < Binary::Structure
|
@@ -38,7 +38,7 @@ module Depix
|
|
38
38
|
|
39
39
|
char :frame_id, 32, :desc => 'Frame identification (keyframe)'
|
40
40
|
char :slate, 100, :desc => 'Slate information'
|
41
|
-
|
41
|
+
blanking :reserve, 56
|
42
42
|
end
|
43
43
|
|
44
44
|
class ImageElement < Binary::Structure
|
@@ -82,7 +82,7 @@ module Depix
|
|
82
82
|
array :border, :u16, 4, :desc => 'Border validity: XL, XR, YT, YB'
|
83
83
|
array :aspect_ratio , :u32, 2, :desc => "Aspect (H:V)"
|
84
84
|
|
85
|
-
|
85
|
+
blanking :reserve, 28
|
86
86
|
end
|
87
87
|
|
88
88
|
class TelevisionInfo < Binary::Structure
|
@@ -104,7 +104,7 @@ module Depix
|
|
104
104
|
r32 :break_point, :desc => 'Break point (?)'
|
105
105
|
r32 :white_level, :desc => 'White level'
|
106
106
|
r32 :integration_times, :desc => 'Integration times (S)'
|
107
|
-
|
107
|
+
blanking :reserve, 4 # As long as a real
|
108
108
|
end
|
109
109
|
|
110
110
|
class UserInfo < Binary::Structure
|
@@ -123,7 +123,7 @@ module Depix
|
|
123
123
|
elements[0].req = true
|
124
124
|
end
|
125
125
|
|
126
|
-
|
126
|
+
blanking :reserve, 52
|
127
127
|
|
128
128
|
# Only expose the elements present
|
129
129
|
def image_elements #:nodoc:
|
data/lib/depix/synthetics.rb
CHANGED
@@ -52,13 +52,23 @@ module Depix::Synthetics
|
|
52
52
|
Depix::COMPONENT_TYPE.invert[image.image_elements[0].descriptor]
|
53
53
|
end
|
54
54
|
|
55
|
+
# Returns the pixel aspect
|
56
|
+
def pixel_aspect
|
57
|
+
(orientation.aspect_ratio[0].to_f / orientation.aspect_ratio[1].to_f)
|
58
|
+
end
|
59
|
+
|
55
60
|
# Aspect in it's traditional representation (1.77 for 16x9 and so on)
|
56
61
|
def aspect
|
57
|
-
"%.2f" % (
|
62
|
+
"%.2f" % (image.pixels_per_line / image.lines_per_element.to_f * pixel_aspect)
|
58
63
|
end
|
59
64
|
|
60
65
|
# Is this DPX file little-endian?
|
61
|
-
def
|
66
|
+
def little_endian?
|
62
67
|
file.magic == 'XPDS'
|
63
68
|
end
|
69
|
+
|
70
|
+
def le?
|
71
|
+
# $stderr.puts "Depix::Synthetics.le? is deprecated, use little_endian? instead"
|
72
|
+
little_endian?
|
73
|
+
end
|
64
74
|
end
|
Binary file
|
@@ -1,4 +1,10 @@
|
|
1
|
+
# coding: ASCII-8BIT
|
2
|
+
|
3
|
+
# Pay attention. The test verifies packing into bit blobs. These are much nahdier
|
4
|
+
# to compare and check as US-ASCII. Even though I am completely into Unicode this is exactly
|
5
|
+
# the moment to NOT use it.
|
1
6
|
require 'test/unit'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/depix' unless defined?(Depix)
|
2
8
|
|
3
9
|
include Depix::Binary
|
4
10
|
include Depix::Binary::Fields
|
@@ -227,13 +233,13 @@ class TestArrayField < Test::Unit::TestCase
|
|
227
233
|
|
228
234
|
def test_pack_pads_properly
|
229
235
|
f = ArrayField.new :members => [U32Field.new, R32Field.new, R32Field.new]
|
230
|
-
assert_equal "\
|
236
|
+
assert_equal "\x00\x00\x00\x1A?\x80\x00\x00@\x00\x00\x00", f.pack([26,1.0, 2.0])
|
231
237
|
assert_equal f.length, f.pack([1.0, 2.0]).length
|
232
238
|
end
|
233
239
|
|
234
240
|
def test_does_not_try_to_pack_nil_values
|
235
241
|
f = ArrayField.new(:members => [AlwaysInvalidField.new(:length => 2)])
|
236
|
-
assert_equal
|
242
|
+
assert_equal 0xFF.chr * 2, f.pack([nil])
|
237
243
|
end
|
238
244
|
|
239
245
|
end
|
@@ -329,7 +335,7 @@ class TestWideIntField < Test::Unit::TestCase
|
|
329
335
|
def test_pack
|
330
336
|
w = U32Field.new
|
331
337
|
assert_equal "\000\000\000\036", w.pack(30)
|
332
|
-
assert_equal "\
|
338
|
+
assert_equal "\xFF\xFF\xFF\xFF", w.pack(nil)
|
333
339
|
end
|
334
340
|
end
|
335
341
|
|
@@ -345,7 +351,7 @@ class TestCharField < Test::Unit::TestCase
|
|
345
351
|
def test_char_field_pads
|
346
352
|
f = CharField.new :name => :foo, :length => 15
|
347
353
|
|
348
|
-
assert_equal "
|
354
|
+
assert_equal "Z15", f.pattern
|
349
355
|
assert_equal 15, f.length
|
350
356
|
assert_equal String, f.rtype
|
351
357
|
end
|
@@ -379,8 +385,8 @@ class TestCharField < Test::Unit::TestCase
|
|
379
385
|
def test_char_field_packs
|
380
386
|
f = CharField.new(:length => 6)
|
381
387
|
assert_equal "xx\000\000\000\000", f.pack("xx")
|
382
|
-
assert_equal "\
|
383
|
-
assert_equal "\
|
388
|
+
assert_equal "\xFF\xFF\xFF\xFF\xFF\xFF", f.pack("")
|
389
|
+
assert_equal "\xFF\xFF\xFF\xFF\xFF\xFF", f.pack(nil)
|
384
390
|
end
|
385
391
|
end
|
386
392
|
|
@@ -391,21 +397,17 @@ class TestFloatField < Test::Unit::TestCase
|
|
391
397
|
f = R32Field.new :name => :foo
|
392
398
|
conform_field!(f)
|
393
399
|
|
394
|
-
the_nan = Class.new do
|
395
|
-
def nan?; true; end
|
396
|
-
end.new
|
397
|
-
|
398
400
|
assert_equal "g", f.pattern
|
399
401
|
assert_equal 4, f.length
|
400
402
|
assert_equal :foo, f.name
|
401
403
|
assert_equal Float, f.rtype
|
402
|
-
assert_equal nil, f.clean(the_nan)
|
403
404
|
end
|
404
405
|
|
405
406
|
def test_pack
|
406
407
|
w = R32Field.new
|
407
408
|
assert_equal "@fff", w.pack(3.6)
|
408
|
-
|
409
|
+
blank = 0xFF.chr * 4
|
410
|
+
assert_equal blank, w.pack(nil)
|
409
411
|
end
|
410
412
|
end
|
411
413
|
|
@@ -538,13 +540,13 @@ class TestFieldEmit < Test::Unit::TestCase
|
|
538
540
|
f = CharField.new
|
539
541
|
conform_field!(f)
|
540
542
|
|
541
|
-
assert_equal "
|
543
|
+
assert_equal "Z1", f.pattern
|
542
544
|
assert_equal 1, f.length
|
543
545
|
|
544
546
|
f = CharField.new :length => 3
|
545
547
|
conform_field!(f)
|
546
548
|
|
547
|
-
assert_equal "
|
549
|
+
assert_equal "Z3", f.pattern
|
548
550
|
assert_equal 3, f.length
|
549
551
|
end
|
550
552
|
|
@@ -601,7 +603,7 @@ class TestStructure < Test::Unit::TestCase
|
|
601
603
|
c.fields << CharField.new
|
602
604
|
|
603
605
|
assert_respond_to c, :pattern
|
604
|
-
assert_equal '
|
606
|
+
assert_equal 'Z1Z1', c.pattern
|
605
607
|
assert_equal 2, c.length
|
606
608
|
end
|
607
609
|
|
@@ -645,7 +647,22 @@ class TestStructureConsume < Test::Unit::TestCase
|
|
645
647
|
end
|
646
648
|
|
647
649
|
class TestStructureEmitDSL < Test::Unit::TestCase
|
648
|
-
|
650
|
+
|
651
|
+
def test_dict_emit_char
|
652
|
+
c = Class.new(Structure)
|
653
|
+
c.blanking :reserved, :length => 48, :desc => "Reserved"
|
654
|
+
assert c.instance_methods.map{|e| e.to_s }.include?("reserved"),
|
655
|
+
"Should create the tag accessor"
|
656
|
+
|
657
|
+
assert_equal 1, c.fields.length
|
658
|
+
field = c.fields[0]
|
659
|
+
|
660
|
+
assert_equal 48, field.length
|
661
|
+
assert_equal "Z48", field.pattern
|
662
|
+
assert_equal :reserved, field.name
|
663
|
+
end
|
664
|
+
|
665
|
+
|
649
666
|
def test_dict_emit_char
|
650
667
|
c = Class.new(Structure)
|
651
668
|
c.char :tag, :desc => "Some name"
|
@@ -656,7 +673,7 @@ class TestStructureEmitDSL < Test::Unit::TestCase
|
|
656
673
|
field = c.fields[0]
|
657
674
|
|
658
675
|
assert_equal 1, field.length
|
659
|
-
assert_equal "
|
676
|
+
assert_equal "Z1", field.pattern
|
660
677
|
assert_equal :tag, field.name
|
661
678
|
end
|
662
679
|
|
@@ -669,7 +686,7 @@ class TestStructureEmitDSL < Test::Unit::TestCase
|
|
669
686
|
assert_equal 1, c.fields.length
|
670
687
|
field = c.fields[0]
|
671
688
|
assert_equal 3, field.length
|
672
|
-
assert_equal "
|
689
|
+
assert_equal "Z3", field.pattern
|
673
690
|
assert_equal :joe, field.name
|
674
691
|
end
|
675
692
|
|
data/test/test_depix.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__)) + '/../lib/depix'
|
2
1
|
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/depix' unless defined?(Depix)
|
3
3
|
require "fileutils"
|
4
4
|
|
5
5
|
SAMPLE_DPX = File.dirname(__FILE__) + '/samples/E012_P001_L000002_lin.0001.dpx'
|
@@ -24,7 +24,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
24
24
|
|
25
25
|
assert_equal 320, parsed.image.pixels_per_line
|
26
26
|
assert_equal 240, parsed.image.lines_per_element
|
27
|
-
|
27
|
+
|
28
28
|
assert_equal 1, parsed.image.number_elements
|
29
29
|
assert_equal 1, parsed.image.image_elements.length
|
30
30
|
ie = parsed.image.image_elements[0]
|
@@ -45,8 +45,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
45
45
|
assert_equal 0, ie.end_of_line_padding
|
46
46
|
assert_equal 0, ie.end_of_image_padding
|
47
47
|
assert_equal "IMAGE DESCRIPTION DATA ", ie.description
|
48
|
-
assert_equal "E012",
|
49
|
-
parsed.orientation.device #- this is where Flame writes the reel
|
48
|
+
assert_equal "E012", parsed.orientation.device #- this is where Flame writes the reel
|
50
49
|
|
51
50
|
assert_equal 853, parsed.orientation.aspect_ratio[0]
|
52
51
|
assert_equal 640, parsed.orientation.aspect_ratio[1]
|
@@ -66,7 +65,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
66
65
|
|
67
66
|
def test_syntethics
|
68
67
|
assert_nothing_raised { Depix::Synthetics }
|
69
|
-
|
68
|
+
|
70
69
|
file = SAMPLE_DPX
|
71
70
|
parsed = Depix.from_file(file)
|
72
71
|
assert_equal false, parsed.le?
|
@@ -75,7 +74,16 @@ class ReaderTest < Test::Unit::TestCase
|
|
75
74
|
assert_equal :RGB, parsed.component_type
|
76
75
|
assert_equal :Linear, parsed.colorimetric
|
77
76
|
assert_equal "E012", parsed.flame_reel
|
78
|
-
assert_equal "1.
|
77
|
+
assert_equal "1.78", parsed.aspect
|
78
|
+
|
79
|
+
file = File.dirname(SAMPLE_DPX) + "/scratch.dpx"
|
80
|
+
parsed = Depix.from_file(file)
|
81
|
+
assert_equal 1, parsed.pixel_aspect, "Should parse square pixels"
|
82
|
+
assert_equal "1.78", parsed.aspect, "Should parse 16x9 aspect"
|
83
|
+
|
84
|
+
file = File.dirname(SAMPLE_DPX) + "/026_FROM_HERO_TAPE_5-3-1_MOV.0029.dpx"
|
85
|
+
parsed = Depix.from_file(file)
|
86
|
+
assert_equal "2.37", parsed.aspect, "Should parse 2.37 Viper aspect"
|
79
87
|
end
|
80
88
|
|
81
89
|
def test_parsed_properly_using_compact_structs
|
@@ -83,12 +91,6 @@ class ReaderTest < Test::Unit::TestCase
|
|
83
91
|
assert_nothing_raised { Depix.from_file(file, compact = true) }
|
84
92
|
end
|
85
93
|
|
86
|
-
def test_describe
|
87
|
-
desc = Depix.describe_file(SAMPLE_DPX)
|
88
|
-
assert_match(/320/, desc)
|
89
|
-
assert_match(/Offset to data for this image element/, desc)
|
90
|
-
end
|
91
|
-
|
92
94
|
def test_packing
|
93
95
|
original_header = File.read(SAMPLE_DPX)[0...Depix::DPX.length]
|
94
96
|
|
@@ -135,6 +137,13 @@ class ReaderTest < Test::Unit::TestCase
|
|
135
137
|
assert_in_delta 25, dpx.film.frame_rate, 0.01
|
136
138
|
end
|
137
139
|
|
140
|
+
def test_fields_properly_niled
|
141
|
+
dpx = Depix.from_file(File.dirname(__FILE__) + "/samples/scratch.dpx")
|
142
|
+
assert_equal "Assimilate,SCRATCH", dpx.file.creator
|
143
|
+
[:project, :copyright, :encrypt_key, :reserve].each do | field |
|
144
|
+
assert_nil dpx.file.send(field), "The blanking field #{field.inspect} should have been decoded as nil"
|
145
|
+
end
|
146
|
+
end
|
138
147
|
end
|
139
148
|
|
140
149
|
class EditorTest < Test::Unit::TestCase
|