depix 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|