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.
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
@@ -21,7 +21,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
21
21
  * <tt>project</tt> (String) Project name
22
22
  * <tt>copyright</tt> (String) Copyright
23
23
  * <tt>encrypt_key</tt> Encryption key
24
- * <tt>reserve</tt> (String)
24
+ * <tt>reserve</tt> (NilClass)
25
25
  * <tt>image</tt> (Depix::ImageInfo) Image information - required:
26
26
  * <tt>orientation</tt> (Integer) Orientation descriptor - required
27
27
  * <tt>number_elements</tt> (Integer) How many elements to scan - required
@@ -43,7 +43,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
43
43
  * <tt>end_of_line_padding</tt> End-of-line padding for this image element
44
44
  * <tt>end_of_image_padding</tt> End-of-line padding for this image element
45
45
  * <tt>description</tt> (String)
46
- * <tt>reserve</tt> (String)
46
+ * <tt>reserve</tt> (NilClass)
47
47
  * <tt>orientation</tt> (Depix::OrientationInfo) Orientation - required:
48
48
  * <tt>x_offset</tt>
49
49
  * <tt>y_offset</tt>
@@ -57,7 +57,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
57
57
  * <tt>serial</tt> (String) Input device serial number
58
58
  * <tt>border</tt> (Array of 4 Integer fields) Border validity: XL, XR, YT, YB:
59
59
  * <tt>aspect_ratio</tt> (Array of 2 fields) Aspect (H:V):
60
- * <tt>reserve</tt> (String)
60
+ * <tt>reserve</tt> (NilClass)
61
61
  * <tt>film</tt> (Depix::FilmInfo) Film industry info - required:
62
62
  * <tt>id</tt> (String) Film mfg. ID code (2 digits from film edge code)
63
63
  * <tt>type</tt> (String) Film type (2 digits from film edge code)
@@ -72,7 +72,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
72
72
  * <tt>shutter_angle</tt> (Float) Shutter angle
73
73
  * <tt>frame_id</tt> (String) Frame identification (keyframe)
74
74
  * <tt>slate</tt> (String) Slate information
75
- * <tt>reserve</tt> (String)
75
+ * <tt>reserve</tt> (NilClass)
76
76
  * <tt>television</tt> (Depix::TelevisionInfo) TV industry info - required:
77
77
  * <tt>time_code</tt> Timecode, formatted as HH:MM:SS:FF in the 4 higher bits of each 8bit group
78
78
  * <tt>user_bits</tt> Timecode UBITs
@@ -90,7 +90,7 @@ DPX metadata gets returned as a Depix::DPX object with nested properties.
90
90
  * <tt>break_point</tt> (Float) Break point (?)
91
91
  * <tt>white_level</tt> (Float) White level
92
92
  * <tt>integration_times</tt> (Float) Integration times (S)
93
- * <tt>reserve</tt> (Float)
93
+ * <tt>reserve</tt> (NilClass)
94
94
  * <tt>user</tt> (Depix::UserInfo) User info - required:
95
95
  * <tt>id</tt> (String) Name of the user data tag
96
96
  * <tt>user_data_ptr</tt>
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # --ruby--
2
+ source :rubygems
3
+
4
+ gem"timecode", "~> 1.0"
5
+ gem "progressbar", "~> 0.9"
6
+ gem "sequencer", "~> 1.0"
7
+ gem "term-ansicolor"
8
+
9
+ group :development do
10
+ gem "jeweler"
11
+ gem "rake"
12
+ gem "cli_test", "~>1.0"
13
+ end
@@ -1,3 +1,17 @@
1
+ === 3.0.0 / 2011-11-29
2
+
3
+ * Use jeweler for gem builds
4
+ * depix-describe renamed with a dash. Sorry folks.
5
+ * Adds depix_fix_headers to fix wonky headers with, for instance, improper null-termination
6
+ * Multiple bug fixes
7
+ * Padded reserved fields not shown anymore
8
+ * More fields that have invalid values resolve to nil now
9
+ * fixed that Synthetics#aspect would return pixel aspect and not image aspect
10
+
11
+ === 2.0.1 / 2011-11-09
12
+
13
+ * Fix the errors in depix-describe
14
+
1
15
  === 2.0.0 / 2011-06-14
2
16
 
3
17
  * Depix::Binary is now public, and it's a nice library. Check it out.
@@ -27,17 +27,29 @@ have the same name as the specified fields.
27
27
 
28
28
  The gem also contains an executable called depix-desribe which can be used from the command line
29
29
 
30
- $book depix-describe 001_PTAPE_001.001.dpx
30
+ $depix_describe 001_PTAPE_001.001.dpx
31
31
 
32
32
  for a long description or
33
33
 
34
- $book depix-describe -s 001_PTAPE_001.001.dpx
34
+ $depix_describe -s 001_PTAPE_001.001.dpx
35
+
36
+ for a short description.
37
+
38
+ If you have a file that does not import into some application you could run "fix headers" on it to comb
39
+ out invalid data (or data some systems do not approve of). To do so, run depix_fix_headers. Note that the files
40
+ will be modified in-place
41
+
42
+ $depix_fix_headers 001_PTAPE_001.001.dpx
43
+
44
+ or for a whole sequence - just supply the -s flag and pass one file
45
+
46
+ $depix_fix_headers -s 001_PTAPE_001.001.dpx
35
47
 
36
- for a short description
37
48
 
38
49
  == NOTES:
39
50
 
40
51
  Autodesk IFFS systems write the reel name for the file to the orientation.device field, some scanners write it into user data.
52
+ Currently unpacking slots which contain invalid reals and ints will yield the maximum possible value for the type
41
53
 
42
54
  == REQUIREMENTS:
43
55
 
data/Rakefile CHANGED
@@ -1,20 +1,34 @@
1
1
  require 'rubygems'
2
- require 'hoe'
3
2
  require './lib/depix'
3
+ require 'jeweler'
4
4
 
5
- Hoe.spec('depix') do |p|
6
- p.version = Depix::VERSION
7
- p.developer('Julik Tarkhanov', 'me@julik.nl')
8
- p.rubyforge_name = 'guerilla-di'
9
- p.extra_deps << ['timecode']
10
- p.remote_rdoc_dir = 'depix'
11
- p.readme_file = 'README.rdoc'
12
- p.extra_rdoc_files = FileList['*.rdoc']
13
-
14
- p.clean_globs = %w( **/.DS_Store )
5
+ Jeweler::Tasks.new do |gem|
6
+ gem.version = Depix::VERSION
7
+ gem.name = "depix"
8
+ gem.summary = "Read and write DPX file headers"
9
+ gem.description = "Allos you to edit headers and read their contents parsed into Ruby objects"
10
+ gem.email = "me@julik.nl"
11
+ gem.homepage = "http://guerilla-di.org/depix"
12
+ gem.authors = ["Julik Tarkhanov"]
13
+ gem.extra_rdoc_files << "DEVELOPER_DOCS.rdoc"
14
+ gem.license = 'MIT'
15
+ gem.executables = ["depix_describe", "depix_fix_headers"]
16
+ gem.extra_rdoc_files = FileList['*.rdoc']
15
17
  end
16
18
 
17
- task :describe_structs do
18
- require File.dirname(__FILE__) + '/lib/depix/struct_explainer'
19
- File.open('DPX_HEADER_STRUCTURE.rdoc', 'w') {|f| f << RdocExplainer.new.get_rdoc_for(Depix::DPX) }
19
+ Jeweler::RubygemsDotOrgTasks.new
20
+
21
+ require 'rake/testtask'
22
+ desc "Run all tests"
23
+ Rake::TestTask.new("test") do |t|
24
+ t.libs << "test"
25
+ t.pattern = 'test/**/test_*.rb'
26
+ t.verbose = true
27
+ end
28
+
29
+ task :default => [ :test ]
30
+
31
+ task :document_structs do
32
+ require './lib/depix/binary/descriptor'
33
+ File.open('DPX_HEADER_STRUCTURE.rdoc', 'w') {|f| f << Depix::Binary::RdocGenerator.new.get_rdoc_for(Depix::DPX) }
20
34
  end
@@ -5,7 +5,7 @@ require 'optparse'
5
5
 
6
6
  options = {}
7
7
  OptionParser.new do |opts|
8
- opts.banner = "Usage: depix-describe somefile.dpx anotherfile.dpx [options]"
8
+ opts.banner = "Usage: depix_describe somefile.dpx anotherfile.dpx [options]"
9
9
 
10
10
  opts.on("-c", "--compact", "Compact output (only fields that change per frame)") do |v|
11
11
  options[:compact] = true
@@ -18,15 +18,16 @@ OptionParser.new do |opts|
18
18
  end.parse!
19
19
 
20
20
  ARGV.each do | file |
21
+ puts "\n"
21
22
  puts "Describing DPX #{file}. Empty elements are omitted."
22
23
  puts "===================================================\n"
23
24
  begin
24
25
  if options[:synthetics]
25
- puts Depix.describe_brief(file)
26
+ puts Depix::Describe.new.describe_brief(file)
26
27
  elsif options[:compact]
27
- puts Depix.describe_file(file, true)
28
+ puts Depix::Describe.new.describe(file, true)
28
29
  else
29
- puts Depix.describe_file(file)
30
+ puts Depix::Describe.new.describe(file)
30
31
  end
31
32
  rescue Depix::InvalidHeader
32
33
  puts " - Invalid header data"
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/depix'
4
+ require "rubygems"
5
+ require 'optparse'
6
+ require "progressbar"
7
+ require "sequencer"
8
+
9
+ options = {}
10
+ OptionParser.new do |opts|
11
+ opts.banner = "Usage: depix_fix_headers somefile.dpx anotherfile.dpx" + "\n" +
12
+ "For sequences: depix_fix_headers -s one_file_from_the_sequence.dpx"
13
+
14
+ opts.on("-s", "--sequence", "Detect a sequence instead (pass one file from the sequence)") do |v|
15
+ $sequence = true
16
+ end
17
+ end.parse!
18
+
19
+ files = if $sequence
20
+ paths = []
21
+ Sequencer.from_single_file(ARGV.shift).each_path do | p |
22
+ paths.push(p)
23
+ end
24
+ paths
25
+ else
26
+ ARGV
27
+ end
28
+
29
+ raise "No files provided" unless files.any?
30
+
31
+ header = "Fixing headers in %d files" % files.length
32
+ pbar = ProgressBar.new(header, files.length)
33
+ pbar.format = "%-#{header.length}s %3d%% %s %s"
34
+
35
+ files.each do | file |
36
+ pbar.inc
37
+ Depix::Editor.new(file).commit!
38
+ end
39
+ puts ""
@@ -0,0 +1,93 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "depix"
8
+ s.version = "3.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Julik Tarkhanov"]
12
+ s.date = "2011-11-29"
13
+ s.description = "Allos you to edit headers and read their contents parsed into Ruby objects"
14
+ s.email = "me@julik.nl"
15
+ s.executables = ["depix_describe", "depix_fix_headers"]
16
+ s.extra_rdoc_files = [
17
+ "DPX_HEADER_STRUCTURE.rdoc",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".gemtest",
22
+ ".travis.yml",
23
+ "DPX_HEADER_STRUCTURE.rdoc",
24
+ "Gemfile",
25
+ "History.txt",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "bin/depix_describe",
29
+ "bin/depix_fix_headers",
30
+ "depix.gemspec",
31
+ "lib/depix.rb",
32
+ "lib/depix/binary/fields.rb",
33
+ "lib/depix/binary/rdoc_generator.rb",
34
+ "lib/depix/binary/structure.rb",
35
+ "lib/depix/compact_structs.rb",
36
+ "lib/depix/describe.rb",
37
+ "lib/depix/editor.rb",
38
+ "lib/depix/enums.rb",
39
+ "lib/depix/reader.rb",
40
+ "lib/depix/structs.rb",
41
+ "lib/depix/synthetics.rb",
42
+ "test/samples/026_FROM_HERO_TAPE_5-3-1_MOV.0029.dpx",
43
+ "test/samples/E012_P001_L000002_lin.0001.dpx",
44
+ "test/samples/E012_P001_L000002_lin.0002.dpx",
45
+ "test/samples/E012_P001_L000002_log.0001.dpx",
46
+ "test/samples/E012_P001_L000002_log.0002.dpx",
47
+ "test/samples/from_nuke_no_TC_meta.dpx",
48
+ "test/samples/gluetools_file_header.dpx",
49
+ "test/samples/little_endian.dpx",
50
+ "test/samples/northlight_tc_mode_mismatch.dpx",
51
+ "test/samples/scratch.dpx",
52
+ "test/test_binary.rb",
53
+ "test/test_depix.rb",
54
+ "test/test_describe.rb",
55
+ "test/test_fix_headers.rb"
56
+ ]
57
+ s.homepage = "http://guerilla-di.org/depix"
58
+ s.licenses = ["MIT"]
59
+ s.require_paths = ["lib"]
60
+ s.rubygems_version = "1.8.11"
61
+ s.summary = "Read and write DPX file headers"
62
+
63
+ if s.respond_to? :specification_version then
64
+ s.specification_version = 3
65
+
66
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
67
+ s.add_runtime_dependency(%q<timecode>, ["~> 1.0"])
68
+ s.add_runtime_dependency(%q<progressbar>, ["~> 0.9"])
69
+ s.add_runtime_dependency(%q<sequencer>, ["~> 1.0"])
70
+ s.add_runtime_dependency(%q<term-ansicolor>, [">= 0"])
71
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
72
+ s.add_development_dependency(%q<rake>, [">= 0"])
73
+ s.add_development_dependency(%q<cli_test>, ["~> 1.0"])
74
+ else
75
+ s.add_dependency(%q<timecode>, ["~> 1.0"])
76
+ s.add_dependency(%q<progressbar>, ["~> 0.9"])
77
+ s.add_dependency(%q<sequencer>, ["~> 1.0"])
78
+ s.add_dependency(%q<term-ansicolor>, [">= 0"])
79
+ s.add_dependency(%q<jeweler>, [">= 0"])
80
+ s.add_dependency(%q<rake>, [">= 0"])
81
+ s.add_dependency(%q<cli_test>, ["~> 1.0"])
82
+ end
83
+ else
84
+ s.add_dependency(%q<timecode>, ["~> 1.0"])
85
+ s.add_dependency(%q<progressbar>, ["~> 0.9"])
86
+ s.add_dependency(%q<sequencer>, ["~> 1.0"])
87
+ s.add_dependency(%q<term-ansicolor>, [">= 0"])
88
+ s.add_dependency(%q<jeweler>, [">= 0"])
89
+ s.add_dependency(%q<rake>, [">= 0"])
90
+ s.add_dependency(%q<cli_test>, ["~> 1.0"])
91
+ end
92
+ end
93
+
@@ -12,9 +12,10 @@ require File.expand_path(File.dirname(__FILE__)) + '/depix/synthetics'
12
12
  require File.expand_path(File.dirname(__FILE__)) + '/depix/reader'
13
13
  require File.expand_path(File.dirname(__FILE__)) + '/depix/editor'
14
14
 
15
+ require File.expand_path(File.dirname(__FILE__)) + '/depix/describe'
15
16
 
16
17
  module Depix
17
- VERSION = '2.0.0'
18
+ VERSION = '3.0.0'
18
19
 
19
20
  class InvalidHeader < RuntimeError; end
20
21
 
@@ -31,15 +32,4 @@ module Depix
31
32
  def self.from_string(string, compact = false)
32
33
  Reader.new.parse(string, compact)
33
34
  end
34
-
35
- # Retrurn a formatted description of the DPX file at path. Empty values are omitted.
36
- def self.describe_file(path, compact = false)
37
- Reader.new.describe_file(path, compact)
38
- end
39
-
40
- # Return a formatted description of the DPX file at path, showing only synthetic attributes
41
- def self.describe_brief(path)
42
- Reader.new.describe_synthetics_of_struct(from_file(path))
43
- end
44
-
45
35
  end
@@ -1,15 +1,15 @@
1
- module Depix
2
- module Binary
3
- module Fields
1
+ # coding: ASCII-8BIT
2
+ module Depix; module Binary; module Fields
4
3
 
5
4
  # Base class for a padded field in a struct
6
5
  class Field
7
- attr_accessor :name, # Field name
8
- :length, # Field length in bytes, including any possible padding
9
- :pattern, # The unpack pattern that defines the field
10
- :req, # Is the field required?
11
- :desc, # Field description
12
- :rtype # To which Ruby type this has to be cast (and which type is accepted as value)
6
+ attr_accessor :name # Field name
7
+ attr_accessor :length # Field length in bytes, including any possible padding
8
+ attr_accessor :pattern # The unpack pattern that defines the field
9
+ attr_accessor :req # Is the field required?
10
+ attr_accessor :desc # Field description
11
+ attr_accessor :rtype # To which Ruby type this has to be cast (and which type is accepted as value)
12
+
13
13
  alias_method :req?, :req
14
14
 
15
15
  # Hash init
@@ -53,6 +53,11 @@ module Depix
53
53
  [value].pack(pattern)
54
54
  end
55
55
  end
56
+
57
+ private
58
+ def blanking?(blob)
59
+ blob.nil? || blob.empty? || blob == (0xFF.chr * length)
60
+ end
56
61
  end
57
62
 
58
63
  # unit32 field
@@ -84,7 +89,7 @@ module Depix
84
89
  # uint8 field
85
90
  class U8Field < Field
86
91
  undef :length=, :pattern=
87
-
92
+
88
93
  BLANK = 0xFF
89
94
 
90
95
  def pattern
@@ -144,26 +149,36 @@ module Depix
144
149
  end
145
150
 
146
151
  def clean(v)
147
- v == BLANK ? nil : v
152
+ (v == BLANK || v == -1) ? nil : v
148
153
  end
149
154
 
150
155
  def validate!(value)
151
156
  super(value)
152
157
  raise "#{name} value #{value} out of bounds for 16bit unsigned int" if (value < 0 || value >= BLANK)
153
158
  end
159
+
154
160
  end
155
161
 
156
- # real32 field
162
+ # real32 field. Now, there is some lap dancing to be done here.
163
+ # The DPX files in the wild define nonexistant data as a charfield with all
164
+ # it's bits set (four times 0xFF byte). This is easy to verify with a string
165
+ # but practically useless once the charfield has been unpacked into a float.
166
+ # Therefore we first unpack the value as a charfield, then we check whether it's all
167
+ # blanking, and if it is we return nil. If it's not "all bits set" though what we will do
168
+ # is try to decode it again using the real float unpack pattern. The same dance
169
+ # happens reciprocally when repacking the data.
157
170
  class R32Field < Field
158
171
  undef :length=, :pattern=
159
- BLANK = 0xFFFFFFFF
172
+ BLANK = (0xFF.chr * 4)
173
+ PATTERN_BE = "g"
174
+ PATTERN_LE = "n"
160
175
 
161
176
  def pattern
162
177
  "g"
163
178
  end
164
179
 
165
180
  def clean(v)
166
- v.nan? ? nil : v
181
+ (v.nil? || v.nan?) ? nil : v
167
182
  end
168
183
 
169
184
  def length
@@ -173,34 +188,35 @@ module Depix
173
188
  def rtype
174
189
  Float
175
190
  end
191
+
192
+ # The packing of NaN
193
+ # [12] pry(main)> value = 0 / 0.0
194
+ # => NaN
195
+ # [13] pry(main)> [value].pack("g")
196
+ # => "\xFF\xC0\x00\x00"
197
+ # [14] pry(main)> [value].pack("g")
198
+ def pack(value)
199
+ (value.nil? || value.nan? ) ? BLANK : [value].pack("g")
200
+ end
176
201
  end
177
202
 
178
203
  # null-terminated string field with fixed padding
179
204
  class CharField < Field
180
- BLANK = "\0"
181
205
  undef :pattern=
182
206
 
183
- BLANKING_VALUES = [0x00.chr, 0xFF.chr]
184
- BLANKING_PATTERNS = BLANKING_VALUES.inject([]) do | p, char |
185
- p << /^([#{char}]+)/ << /([#{char}]+)$/mu
186
- end
187
-
188
207
  def initialize(opts = {})
189
208
  super({:length => 1}.merge(opts))
190
209
  end
191
210
 
192
211
  def pattern
193
- "A#{(length || 1).to_i}"
212
+ "Z#{length}"
194
213
  end
195
214
 
196
215
  def clean(v)
197
- if v == BLANK
198
- nil
199
- else
200
- # Truncate everything from the null byte up
201
- upto_nulb = v.split(0x00.chr).shift
202
- (upto_nulb.nil? || upto_nulb.empty?) ? nil : upto_nulb
203
- end
216
+ # Use the pack->unpack trick to remove null-termination
217
+ v = pack(v.to_s).unpack(pattern)[0]
218
+ # Blanked fields are 0xFF all the way
219
+ blanking?(v) ? nil : v
204
220
  end
205
221
 
206
222
  def rtype
@@ -213,7 +229,35 @@ module Depix
213
229
  end
214
230
 
215
231
  def pack(value)
216
- value.ljust(length, "\000") rescue ("\000" * length)
232
+ unless blanking?(value)
233
+ [value].pack(pattern)
234
+ else
235
+ 0xFF.chr * length
236
+ end
237
+ end
238
+ end
239
+
240
+ # For reserved fields and blanking
241
+ class BlankingField < CharField
242
+
243
+ def validate!(value)
244
+ raise "The value of this field should be nil" unless value.nil?
245
+ end
246
+
247
+ def pattern
248
+ "Z#{length}"
249
+ end
250
+
251
+ def clean(v)
252
+ nil
253
+ end
254
+
255
+ def rtype
256
+ NilClass
257
+ end
258
+
259
+ def pack(value)
260
+ 0xFF.chr * length
217
261
  end
218
262
  end
219
263
 
@@ -297,6 +341,4 @@ module Depix
297
341
  cast.pack(value)
298
342
  end
299
343
  end
300
- end
301
- end
302
- end
344
+ end; end; end