tracksperanto 1.8.1 → 1.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/Manifest.txt +3 -0
- data/README.txt +6 -1
- data/Rakefile +1 -0
- data/lib/export/equalizer3.rb +1 -1
- data/lib/export/equalizer4.rb +2 -2
- data/lib/export/flame_stabilizer.rb +80 -36
- data/lib/export/nuke_script.rb +1 -1
- data/lib/export/pftrack.rb +11 -7
- data/lib/export/pftrack_5.rb +8 -6
- data/lib/import/match_mover.rb +3 -0
- data/lib/pipeline/base.rb +17 -20
- data/lib/tracksperanto.rb +3 -1
- data/lib/tracksperanto/buffer_io.rb +48 -0
- data/lib/tracksperanto/flame_builder.rb +24 -17
- data/lib/tracksperanto/progressive_io.rb +4 -7
- data/lib/tracksperanto/returning.rb +6 -0
- data/test/export/samples/ref_flame.stabilizer +0 -18
- data/test/export/test_flame_stabilizer_export.rb +1 -1
- data/test/test_buffer_io.rb +22 -0
- data/test/test_flame_builder.rb +1 -0
- metadata +6 -2
data/History.txt
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
=== 1.8.2 / 2010-03-04
|
2
|
+
|
3
|
+
* Fix the bug in the Flame exporter that was convincing Flame that there is only one tracker in the setup
|
4
|
+
* Buffer temporary outputs to String buffers until they reach a certain size. Helps with tempfile pollution and IO speed
|
5
|
+
|
1
6
|
=== 1.8.1 / 2010-02-18
|
2
7
|
|
3
8
|
* Add Flame stabilizer export support
|
data/Manifest.txt
CHANGED
@@ -42,6 +42,7 @@ lib/middleware/slipper.rb
|
|
42
42
|
lib/pipeline/base.rb
|
43
43
|
lib/tracksperanto.rb
|
44
44
|
lib/tracksperanto/block_init.rb
|
45
|
+
lib/tracksperanto/buffer_io.rb
|
45
46
|
lib/tracksperanto/casts.rb
|
46
47
|
lib/tracksperanto/const_name.rb
|
47
48
|
lib/tracksperanto/ext_io.rb
|
@@ -49,6 +50,7 @@ lib/tracksperanto/flame_builder.rb
|
|
49
50
|
lib/tracksperanto/format_detector.rb
|
50
51
|
lib/tracksperanto/keyframe.rb
|
51
52
|
lib/tracksperanto/progressive_io.rb
|
53
|
+
lib/tracksperanto/returning.rb
|
52
54
|
lib/tracksperanto/safety.rb
|
53
55
|
lib/tracksperanto/simple_export.rb
|
54
56
|
lib/tracksperanto/tracker.rb
|
@@ -130,6 +132,7 @@ test/middleware/test_reformat_middleware.rb
|
|
130
132
|
test/middleware/test_scaler_middleware.rb
|
131
133
|
test/middleware/test_shift_middleware.rb
|
132
134
|
test/middleware/test_slip_middleware.rb
|
135
|
+
test/test_buffer_io.rb
|
133
136
|
test/test_const_name.rb
|
134
137
|
test/test_extio.rb
|
135
138
|
test/test_flame_builder.rb
|
data/README.txt
CHANGED
@@ -69,7 +69,7 @@ Import and export support:
|
|
69
69
|
* Syntheyes 2D tracking data exports
|
70
70
|
* 3DE point exports (as output by the default script) - versions 3 and 4
|
71
71
|
* MatchMover Pro .rz2
|
72
|
-
* MayaLive track export (square pixel aspect only)
|
72
|
+
* MayaLive track export (square pixel aspect only, you will need to write some extra code to convert that)
|
73
73
|
* Flame .stabilizer file
|
74
74
|
|
75
75
|
Import only:
|
@@ -98,6 +98,11 @@ are themselves arrays of Tracksperanto::Keyframe objects.
|
|
98
98
|
|
99
99
|
You can easily write an exporter. Refer to the Tracksperanto::Export::Base docs.
|
100
100
|
|
101
|
+
== Ading your own processing steps
|
102
|
+
|
103
|
+
You probably want to write a Middleware (consult the Tracksperanto::Middleware::Base docs). A Middleware is just like
|
104
|
+
an exporter, except that it wraps another exporter instead (so you can intercept export calls and massage the data as it is moving through).
|
105
|
+
|
101
106
|
== Limitations
|
102
107
|
|
103
108
|
Information about the search area, reference area and offset is not passed along (outside
|
data/Rakefile
CHANGED
data/lib/export/equalizer3.rb
CHANGED
@@ -14,7 +14,7 @@ class Tracksperanto::Export::Equalizer3 < Tracksperanto::Export::Base
|
|
14
14
|
def start_export( img_width, img_height)
|
15
15
|
@w, @h = img_width, img_height
|
16
16
|
# 3DE needs to know the number of keyframes in advance
|
17
|
-
@buffer =
|
17
|
+
@buffer = Tracksperanto::BufferIO.new
|
18
18
|
@highest_keyframe = 0
|
19
19
|
end
|
20
20
|
|
data/lib/export/equalizer4.rb
CHANGED
@@ -12,13 +12,13 @@ class Tracksperanto::Export::Equalizer4 < Tracksperanto::Export::Base
|
|
12
12
|
def start_export( img_width, img_height)
|
13
13
|
# 3DE needs to know the number of points in advance,
|
14
14
|
# so we will just buffer to a StringIO
|
15
|
-
@internal_io, @num_of_trackers =
|
15
|
+
@internal_io, @num_of_trackers = Tracksperanto::BufferIO.new, 0
|
16
16
|
end
|
17
17
|
|
18
18
|
def start_tracker_segment(tracker_name)
|
19
19
|
@internal_io.puts(tracker_name)
|
20
20
|
@num_of_trackers += 1
|
21
|
-
@tracker_buffer, @num_of_kfs =
|
21
|
+
@tracker_buffer, @num_of_kfs = Tracksperanto::BufferIO.new, 0
|
22
22
|
end
|
23
23
|
|
24
24
|
def export_point(frame, abs_float_x, abs_float_y, float_residual)
|
@@ -1,6 +1,9 @@
|
|
1
|
+
# TODO: this exporter is MAJORLY slow now
|
1
2
|
class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
2
3
|
|
3
4
|
COLOR = "50 50 50"
|
5
|
+
DATETIME_FORMAT = '%a %b %d %H:%M:%S %Y'
|
6
|
+
|
4
7
|
def self.desc_and_extension
|
5
8
|
"flame.stabilizer"
|
6
9
|
end
|
@@ -12,22 +15,27 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
12
15
|
def start_export( img_width, img_height)
|
13
16
|
@counter = 0
|
14
17
|
@width, @height = img_width, img_height
|
15
|
-
@temp =
|
18
|
+
@temp = Tracksperanto::BufferIO.new
|
16
19
|
@writer = Tracksperanto::FlameBuilder.new(@temp)
|
17
20
|
end
|
18
21
|
|
19
22
|
def end_export
|
23
|
+
# Now make another writer, this time for our main IO
|
20
24
|
@writer = Tracksperanto::FlameBuilder.new(@io)
|
21
|
-
|
25
|
+
|
26
|
+
# Now we know how many trackers we have so we can write the header
|
27
|
+
# data along with NbTrackers
|
28
|
+
write_header_with_number_of_trackers(@counter)
|
22
29
|
|
23
30
|
# Now write everything that we accumulated earlier into the base IO
|
24
31
|
@temp.rewind
|
25
32
|
@io.write(@temp.read) until @temp.eof?
|
26
33
|
@temp.close!
|
27
34
|
|
35
|
+
# Send the ChannelEnd command and list the trackers
|
28
36
|
@writer.channel_end
|
29
37
|
@counter.times do |i|
|
30
|
-
@writer.tracker
|
38
|
+
@writer.write_unterminated_block!("tracker", i) do |t|
|
31
39
|
t.active true
|
32
40
|
t.color_hash!("colour", 0, 100, 0)
|
33
41
|
t.fixed_ref true
|
@@ -40,30 +48,39 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
40
48
|
|
41
49
|
def start_tracker_segment(tracker_name)
|
42
50
|
@counter += 1
|
43
|
-
@tracker_name = tracker_name
|
44
|
-
@x_values, @y_values = [], []
|
45
51
|
@write_first_frame = true
|
46
52
|
end
|
47
53
|
|
48
54
|
def export_point(frame, abs_float_x, abs_float_y, float_residual)
|
55
|
+
flame_frame = frame + 1
|
49
56
|
if @write_first_frame
|
50
|
-
|
51
|
-
|
52
|
-
|
57
|
+
@base_x, @base_y = abs_float_x, abs_float_y
|
58
|
+
write_first_frame(abs_float_x, abs_float_y)
|
59
|
+
# For Flame to recognize the reference frame of the Shift channel
|
60
|
+
# we need it to contain zero as an int, not as a float. The shift proceeds
|
61
|
+
# from there.
|
62
|
+
@x_shift_values = [[flame_frame, 0]]
|
63
|
+
@y_shift_values = [[flame_frame, 0]]
|
64
|
+
@write_first_frame = false
|
53
65
|
else
|
54
|
-
|
55
|
-
@
|
66
|
+
# Just continue buffering the upcoming shift keyframes and flush them in the end
|
67
|
+
shift_x, shift_y = @base_x - abs_float_x, @base_y - abs_float_y
|
68
|
+
@x_shift_values.push([flame_frame, shift_x])
|
69
|
+
@y_shift_values.push([flame_frame, shift_y])
|
56
70
|
end
|
57
71
|
end
|
58
72
|
|
59
73
|
def end_tracker_segment
|
60
|
-
|
61
|
-
|
74
|
+
# We write these at tracker end since we need to know in advance
|
75
|
+
# how many keyframes they should contain
|
76
|
+
write_shift_channel("shift/x", @x_shift_values)
|
77
|
+
write_shift_channel("shift/y", @y_shift_values)
|
62
78
|
end
|
63
79
|
|
64
80
|
private
|
65
81
|
|
66
|
-
|
82
|
+
# The shift channel is what determines how the tracking point moves.
|
83
|
+
def write_shift_channel(name_without_prefix, values)
|
67
84
|
@writer.channel(prefix(name_without_prefix)) do | c |
|
68
85
|
c.extrapolation :constant
|
69
86
|
c.value values[0][1]
|
@@ -71,8 +88,8 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
71
88
|
c.size values.length
|
72
89
|
values.each_with_index do | (f, v), i |
|
73
90
|
c.key(i) do | k |
|
74
|
-
k.frame
|
75
|
-
k.value
|
91
|
+
k.frame f
|
92
|
+
k.value v
|
76
93
|
k.interpolation :linear
|
77
94
|
k.left_slope 2.4
|
78
95
|
k.right_slope 2.4
|
@@ -85,12 +102,12 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
85
102
|
["tracker#{@counter}", tracker_channel].join("/")
|
86
103
|
end
|
87
104
|
|
88
|
-
def
|
105
|
+
def write_header_with_number_of_trackers(number_of_trackers)
|
89
106
|
@writer.stabilizer_file_version "5.0"
|
90
|
-
@writer.creation_date(Time.now.strftime(
|
107
|
+
@writer.creation_date(Time.now.strftime(DATETIME_FORMAT))
|
91
108
|
@writer.linebreak!(2)
|
92
109
|
|
93
|
-
@writer.nb_trackers
|
110
|
+
@writer.nb_trackers number_of_trackers
|
94
111
|
@writer.selected 0
|
95
112
|
@writer.frame_width @width
|
96
113
|
@writer.frame_height @height
|
@@ -109,19 +126,31 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
109
126
|
@writer.anim
|
110
127
|
end
|
111
128
|
|
112
|
-
def write_first_frame(x, y
|
113
|
-
|
114
|
-
|
129
|
+
def write_first_frame(x, y)
|
130
|
+
write_track_channels
|
131
|
+
write_track_width_and_height
|
132
|
+
write_ref_width_and_height
|
133
|
+
write_ref_channels(x, y)
|
134
|
+
write_deltax_and_deltay_channels
|
135
|
+
write_offset_channels
|
136
|
+
end
|
137
|
+
|
138
|
+
def write_track_channels
|
139
|
+
ctr_x, ctr_y = @width / 2, @height / 2
|
115
140
|
|
116
|
-
|
117
|
-
|
141
|
+
# track determines where the tracking box is, and should be in the center
|
142
|
+
# of the image for Flame to compute all other shifts properly
|
143
|
+
%w( track/x track/y).map(&method(:prefix)).zip([ctr_x, ctr_y]).each do | cname, default |
|
118
144
|
@writer.channel(cname) do | c |
|
119
145
|
c.extrapolation("constant")
|
120
146
|
c.value(default.to_i)
|
121
147
|
c.colour(COLOR)
|
122
148
|
end
|
123
149
|
end
|
124
|
-
|
150
|
+
end
|
151
|
+
|
152
|
+
# The size of the tracking area
|
153
|
+
def write_track_width_and_height
|
125
154
|
%w( track/width track/height ).map(&method(:prefix)).each do | channel_name |
|
126
155
|
@writer.channel(channel_name) do | c |
|
127
156
|
c.extrapolation :linear
|
@@ -129,7 +158,10 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
129
158
|
c.colour COLOR
|
130
159
|
end
|
131
160
|
end
|
132
|
-
|
161
|
+
end
|
162
|
+
|
163
|
+
# The size of the reference area
|
164
|
+
def write_ref_width_and_height
|
133
165
|
%w( ref/width ref/height).map(&method(:prefix)).each do | channel_name |
|
134
166
|
@writer.channel(channel_name) do | c |
|
135
167
|
c.extrapolation :linear
|
@@ -137,8 +169,14 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
137
169
|
c.colour COLOR
|
138
170
|
end
|
139
171
|
end
|
140
|
-
|
141
|
-
|
172
|
+
end
|
173
|
+
|
174
|
+
# The Ref channel contains the reference for the shift channel in absolute
|
175
|
+
# coordinates, and is set as float. Since we do not "snap" the tracker in
|
176
|
+
# the process it's enough for us to make one keyframe in the ref channels
|
177
|
+
# at the same frame as the first shift keyframe
|
178
|
+
def write_ref_channels(ref_x, ref_y)
|
179
|
+
%w( ref/x ref/y).map(&method(:prefix)).zip([ref_x, ref_y]).each do | cname, default |
|
142
180
|
@writer.channel(cname) do | c |
|
143
181
|
c.extrapolation("constant")
|
144
182
|
c.value(default)
|
@@ -154,7 +192,11 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
154
192
|
end
|
155
193
|
end
|
156
194
|
end
|
157
|
-
|
195
|
+
end
|
196
|
+
|
197
|
+
def write_deltax_and_deltay_channels
|
198
|
+
# This is used for deltax and deltay (offset tracking).
|
199
|
+
# We set it to zero and lock
|
158
200
|
%w( ref/dx ref/dy).map(&method(:prefix)).each do | chan, v |
|
159
201
|
@writer.channel(chan) do | c |
|
160
202
|
c.extrapolation("constant")
|
@@ -177,14 +219,16 @@ class Tracksperanto::Export::FlameStabilizer < Tracksperanto::Export::Base
|
|
177
219
|
k.interpolation :constant
|
178
220
|
end
|
179
221
|
end # Chan block
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def write_offset_channels
|
226
|
+
%w(offset/x offset/y).map(&method(:prefix)).each do | c |
|
227
|
+
@writer.channel(c) do | chan |
|
228
|
+
chan.extrapolation :constant
|
229
|
+
chan.value 0
|
186
230
|
end
|
187
|
-
end
|
188
|
-
end
|
231
|
+
end
|
232
|
+
end
|
189
233
|
|
190
234
|
end
|
data/lib/export/nuke_script.rb
CHANGED
@@ -45,7 +45,7 @@ Constant {
|
|
45
45
|
# We allocate an IO for the file being output that will contain all the trackers,
|
46
46
|
# and then write that one into the script preceded by the preamble that sets length
|
47
47
|
# based on the last frame position in time
|
48
|
-
@trackers_io =
|
48
|
+
@trackers_io = Tracksperanto::BufferIO.new
|
49
49
|
end
|
50
50
|
|
51
51
|
# We accumulate a tracker and on end dump it out in one piece
|
data/lib/export/pftrack.rb
CHANGED
@@ -13,20 +13,24 @@ class Tracksperanto::Export::PFTrack4 < Tracksperanto::Export::Base
|
|
13
13
|
|
14
14
|
def start_tracker_segment(tracker_name)
|
15
15
|
# Setup for the next tracker
|
16
|
-
@
|
16
|
+
@frame_count = 0
|
17
17
|
@tracker_name = tracker_name
|
18
|
+
@tracker_io = Tracksperanto::BufferIO.new
|
18
19
|
end
|
19
20
|
|
20
21
|
def end_tracker_segment
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@
|
22
|
+
@io.write("\n\n")
|
23
|
+
@io.puts(@tracker_name.inspect) # autoquotes
|
24
|
+
@io.puts(@frame_count)
|
25
|
+
|
26
|
+
@tracker_io.rewind
|
27
|
+
@io.write(@tracker_io.read) until @tracker_io.eof?
|
28
|
+
@tracker_io.close!
|
26
29
|
end
|
27
30
|
|
28
31
|
def export_point(frame, abs_float_x, abs_float_y, float_residual)
|
32
|
+
@frame_count += 1
|
29
33
|
line = KEYFRAME_TEMPLATE % [frame, abs_float_x, abs_float_y, float_residual / 8]
|
30
|
-
@
|
34
|
+
@tracker_io.puts(line)
|
31
35
|
end
|
32
36
|
end
|
data/lib/export/pftrack_5.rb
CHANGED
@@ -10,11 +10,13 @@ class Tracksperanto::Export::PFTrack5 < Tracksperanto::Export::PFTrack4
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def end_tracker_segment
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@
|
13
|
+
@io.write("\n\n")
|
14
|
+
@io.puts(@tracker_name.inspect) # autoquotes
|
15
|
+
@io.puts("Primary".inspect) # For primary/secondary cam in stereo pair
|
16
|
+
@io.puts(@frame_count)
|
17
|
+
|
18
|
+
@tracker_io.rewind
|
19
|
+
@io.write(@tracker_io.read) until @tracker_io.eof?
|
20
|
+
@tracker_io.close!
|
19
21
|
end
|
20
22
|
end
|
data/lib/import/match_mover.rb
CHANGED
@@ -21,6 +21,7 @@ class Tracksperanto::Import::MatchMover < Tracksperanto::Import::Base
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def detect_format(io)
|
24
|
+
report_progress("Detecting width and height")
|
24
25
|
lines = (0..2).map{ io.gets }
|
25
26
|
last_line = lines[-1]
|
26
27
|
w, h, _ = last_line.scan(/(\d+)/).flatten
|
@@ -37,10 +38,12 @@ class Tracksperanto::Import::MatchMover < Tracksperanto::Import::Base
|
|
37
38
|
|
38
39
|
def extract_track(start_line, io)
|
39
40
|
tracker_name = start_line.scan(/\"([^\"]+)\"/).flatten[0]
|
41
|
+
report_progress("Extracting tracker #{tracker_name}")
|
40
42
|
t = Tracksperanto::Tracker.new(:name => tracker_name)
|
41
43
|
while(line = io.gets) do
|
42
44
|
return t if line =~ /\}/
|
43
45
|
t.keyframes.push(extract_key(line.strip)) if line =~ /^(\s+?)(\d)/
|
46
|
+
report_progress("Extracting keyframe")
|
44
47
|
end
|
45
48
|
raise "Track didn't close"
|
46
49
|
end
|
data/lib/pipeline/base.rb
CHANGED
@@ -59,9 +59,11 @@ class Tracksperanto::Pipeline::Base
|
|
59
59
|
# Yield middlewares to the block
|
60
60
|
yield(*middlewares) if block_given?
|
61
61
|
|
62
|
-
@converted_points, @converted_keyframes = run_export(read_data, importer, middlewares[-1])
|
63
|
-
|
64
|
-
|
62
|
+
@converted_points, @converted_keyframes = run_export(read_data, importer, middlewares[-1])
|
63
|
+
end
|
64
|
+
|
65
|
+
def report_progress(percent_complete, message)
|
66
|
+
@progress_block.call(percent_complete, message) if @progress_block
|
65
67
|
end
|
66
68
|
|
67
69
|
def detect_importer_or_use_options(path, opts)
|
@@ -87,31 +89,26 @@ class Tracksperanto::Pipeline::Base
|
|
87
89
|
def run_export(tracker_data_io, parser, processor)
|
88
90
|
points, keyframes, percent_complete = 0, 0, 0.0
|
89
91
|
|
90
|
-
|
92
|
+
report_progress(percent_complete, "Starting the parser")
|
91
93
|
|
92
94
|
# Report progress from the parser
|
93
|
-
parser.progress_block = lambda
|
94
|
-
yield(percent_complete, message) if block_given?
|
95
|
-
end
|
95
|
+
parser.progress_block = lambda { | m | report_progress(percent_complete, m) }
|
96
96
|
|
97
|
-
# Wrap the input in a progressive IO
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
# Setup a lambda that will spy on the reader and update the percentage.
|
102
|
-
# We will only broadcast messages that come from the parser though (complementing it
|
103
|
-
# with a percentage)
|
104
|
-
io_with_progress.progress_block = lambda do | offset, of_total |
|
97
|
+
# Wrap the input in a progressive IO, setup a lambda that will spy on the reader and
|
98
|
+
# update the percentage. We will only broadcast messages that come from the parser
|
99
|
+
# though (complementing it with a percentage)
|
100
|
+
io_with_progress = Tracksperanto::ProgressiveIO.new(tracker_data_io) do | offset, of_total |
|
105
101
|
percent_complete = (50.0 / of_total) * offset
|
106
102
|
end
|
103
|
+
@ios << io_with_progress
|
107
104
|
|
108
105
|
trackers = parser.parse(io_with_progress)
|
109
106
|
|
110
|
-
|
107
|
+
report_progress(percent_complete = 50.0, "Validating #{trackers.length} imported trackers")
|
111
108
|
|
112
109
|
validate_trackers!(trackers)
|
113
110
|
|
114
|
-
|
111
|
+
report_progress(percent_complete, "Starting export")
|
115
112
|
|
116
113
|
percent_per_tracker = (100.0 - percent_complete) / trackers.length
|
117
114
|
|
@@ -124,13 +121,13 @@ class Tracksperanto::Pipeline::Base
|
|
124
121
|
t.each_with_index do | kf, idx |
|
125
122
|
keyframes += 1
|
126
123
|
processor.export_point(kf.frame, kf.abs_x, kf.abs_y, kf.residual)
|
127
|
-
|
124
|
+
report_progress(percent_complete += kf_weight, "Writing keyframe #{idx+1} of #{t.name.inspect}, #{trackers.length - idx + 1} trackers to go")
|
128
125
|
end
|
129
126
|
processor.end_tracker_segment
|
130
127
|
end
|
131
128
|
processor.end_export
|
132
129
|
|
133
|
-
|
130
|
+
report_progress(100.0, "Wrote #{points} points and #{keyframes} keyframes")
|
134
131
|
|
135
132
|
[points, keyframes]
|
136
133
|
ensure
|
@@ -176,7 +173,7 @@ class Tracksperanto::Pipeline::Base
|
|
176
173
|
|
177
174
|
# Check that the trackers made by the parser are A-OK
|
178
175
|
def validate_trackers!(trackers)
|
179
|
-
trackers.reject!{|t| t.
|
176
|
+
trackers.reject!{|t| t.empty? }
|
180
177
|
raise "Could not recover any non-empty trackers from this file. Wrong import format maybe?" if trackers.empty?
|
181
178
|
end
|
182
179
|
end
|
data/lib/tracksperanto.rb
CHANGED
@@ -4,7 +4,7 @@ require 'tempfile'
|
|
4
4
|
|
5
5
|
module Tracksperanto
|
6
6
|
PATH = File.expand_path(File.dirname(__FILE__))
|
7
|
-
VERSION = '1.8.
|
7
|
+
VERSION = '1.8.2'
|
8
8
|
|
9
9
|
module Import; end
|
10
10
|
module Export; end
|
@@ -59,6 +59,7 @@ module Tracksperanto
|
|
59
59
|
end
|
60
60
|
|
61
61
|
%w(
|
62
|
+
returning
|
62
63
|
const_name
|
63
64
|
casts
|
64
65
|
block_init
|
@@ -69,6 +70,7 @@ end
|
|
69
70
|
format_detector
|
70
71
|
ext_io
|
71
72
|
progressive_io
|
73
|
+
buffer_io
|
72
74
|
simple_export
|
73
75
|
uv_coordinates
|
74
76
|
flame_builder
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
|
3
|
+
# BufferIO is used for writing big segments of text. When the segment is bigger than a certain number of bytes,
|
4
|
+
# the underlying memory buffer will be swapped with a tempfile
|
5
|
+
class Tracksperanto::BufferIO < DelegateClass(IO)
|
6
|
+
include Tracksperanto::Returning
|
7
|
+
|
8
|
+
IN_MEMORY_SIZE_LIMIT = 100_000
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
__setobj__(StringIO.new)
|
12
|
+
end
|
13
|
+
|
14
|
+
def write(s)
|
15
|
+
returning(super) { replace_with_tempfile_if_needed }
|
16
|
+
end
|
17
|
+
|
18
|
+
def puts(s)
|
19
|
+
returning(super) { replace_with_tempfile_if_needed }
|
20
|
+
end
|
21
|
+
|
22
|
+
def <<(s)
|
23
|
+
returning(super) { replace_with_tempfile_if_needed }
|
24
|
+
end
|
25
|
+
|
26
|
+
def putc(c)
|
27
|
+
returning(super) { replace_with_tempfile_if_needed }
|
28
|
+
end
|
29
|
+
|
30
|
+
def close!
|
31
|
+
__getobj__.close! if @tempfile_in
|
32
|
+
__setobj__(nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def replace_with_tempfile_if_needed
|
38
|
+
return if @tempfile_in
|
39
|
+
io = __getobj__
|
40
|
+
if io.pos > IN_MEMORY_SIZE_LIMIT
|
41
|
+
@tempfile_in = true
|
42
|
+
tf = Tempfile.new("tracksperanto-xbuf")
|
43
|
+
io.rewind
|
44
|
+
tf.write(io.read) until io.eof?
|
45
|
+
__setobj__(tf)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -12,6 +12,11 @@ class Tracksperanto::FlameBuilder
|
|
12
12
|
@io.puts(INDENT * (@indent + 1) + "End")
|
13
13
|
end
|
14
14
|
|
15
|
+
def write_unterminated_block!(name, value = nil, &blk)
|
16
|
+
value.nil? ? write_loose!(name) : write_tuple!(name, value)
|
17
|
+
yield(self.class.new(@io, @indent + 1))
|
18
|
+
end
|
19
|
+
|
15
20
|
def write_tuple!(key, value)
|
16
21
|
@io.puts("%s%s %s" % [INDENT * @indent, __camelize(key), __flameize(value)])
|
17
22
|
end
|
@@ -25,34 +30,36 @@ class Tracksperanto::FlameBuilder
|
|
25
30
|
end
|
26
31
|
|
27
32
|
def color_hash!(name, red, green, blue)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
write_unterminated_block!(name) do | b |
|
34
|
+
b.red(red)
|
35
|
+
b.green(green)
|
36
|
+
b.blue(blue)
|
37
|
+
end
|
33
38
|
end
|
34
39
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
self.class.send(:alias_method, meth, :__generic)
|
39
|
-
if block_given?
|
40
|
-
__generic(meth, arg) {|*a| yield(*a) if block_given? }
|
41
|
-
else
|
42
|
-
__generic(meth, arg)
|
40
|
+
def <<(some_verbatim_string)
|
41
|
+
some_verbatim_string.split("\n").each do | line |
|
42
|
+
@io.puts(["\t" * @indent, line].join)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
private
|
47
|
+
|
48
|
+
def method_missing(meth, arg = nil)
|
47
49
|
if block_given?
|
48
|
-
write_block!(meth, arg) {
|
50
|
+
write_block!(meth, arg) {|c| yield(c) }
|
49
51
|
else
|
50
|
-
arg.nil?
|
52
|
+
if arg.nil?
|
53
|
+
write_loose!(meth)
|
54
|
+
else
|
55
|
+
write_tuple!(meth, arg)
|
56
|
+
end
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
54
60
|
def __camelize(s)
|
55
|
-
|
61
|
+
@@camelizations ||= {}
|
62
|
+
@@camelizations[s] ||= s.to_s.gsub(/(^|_)(.)/) { $2.upcase }
|
56
63
|
end
|
57
64
|
|
58
65
|
def __flameize(v)
|
@@ -1,17 +1,17 @@
|
|
1
1
|
# Used for IO objects that need to report the current offset at each operation that changes the said offset
|
2
2
|
# (useful for building progress bars that report on a file read operation)
|
3
3
|
class Tracksperanto::ProgressiveIO < DelegateClass(IO)
|
4
|
-
|
5
|
-
# Should contain a block that accepts the current offset in bytes and the total size
|
6
|
-
attr_accessor :progress_block
|
4
|
+
include Tracksperanto::Returning
|
7
5
|
|
8
6
|
# Get or set the total size of the contained IO. If the passed IO is a File object
|
9
7
|
# the size will be preset automatically
|
10
8
|
attr_accessor :total_size
|
9
|
+
attr_accessor :progress_block
|
11
10
|
|
12
|
-
def initialize(with_file)
|
11
|
+
def initialize(with_file, &blk)
|
13
12
|
__setobj__(with_file)
|
14
13
|
@total_size = with_file.stat.size if with_file.respond_to?(:stat)
|
14
|
+
@progress_block = blk.to_proc if blk
|
15
15
|
end
|
16
16
|
|
17
17
|
def each(sep_string = $/, &blk)
|
@@ -69,9 +69,6 @@ class Tracksperanto::ProgressiveIO < DelegateClass(IO)
|
|
69
69
|
end
|
70
70
|
|
71
71
|
private
|
72
|
-
def returning(r)
|
73
|
-
yield; r
|
74
|
-
end
|
75
72
|
|
76
73
|
def notify_read
|
77
74
|
@progress_block.call(pos, @total_size) if @progress_block
|
@@ -101,14 +101,6 @@ Channel tracker1/ref/dx
|
|
101
101
|
Interpolation constant
|
102
102
|
End
|
103
103
|
End
|
104
|
-
Channel tracker1/offset/x
|
105
|
-
Extrapolation constant
|
106
|
-
Value 0
|
107
|
-
End
|
108
|
-
Channel tracker1/offset/y
|
109
|
-
Extrapolation constant
|
110
|
-
Value 0
|
111
|
-
End
|
112
104
|
Channel tracker1/ref/dy
|
113
105
|
Extrapolation constant
|
114
106
|
Value 0
|
@@ -495,14 +487,6 @@ Channel tracker2/ref/dx
|
|
495
487
|
Interpolation constant
|
496
488
|
End
|
497
489
|
End
|
498
|
-
Channel tracker2/offset/x
|
499
|
-
Extrapolation constant
|
500
|
-
Value 0
|
501
|
-
End
|
502
|
-
Channel tracker2/offset/y
|
503
|
-
Extrapolation constant
|
504
|
-
Value 0
|
505
|
-
End
|
506
490
|
Channel tracker2/ref/dy
|
507
491
|
Extrapolation constant
|
508
492
|
Value 0
|
@@ -821,7 +805,6 @@ Tracker 0
|
|
821
805
|
FixedX no
|
822
806
|
FixedY no
|
823
807
|
Tolerance 100
|
824
|
-
End
|
825
808
|
Tracker 1
|
826
809
|
Active yes
|
827
810
|
Colour
|
@@ -832,4 +815,3 @@ Tracker 1
|
|
832
815
|
FixedX no
|
833
816
|
FixedY no
|
834
817
|
Tolerance 100
|
835
|
-
End
|
@@ -7,7 +7,7 @@ class FlameStabilizerExportTestTest < Test::Unit::TestCase
|
|
7
7
|
def test_export_output_written
|
8
8
|
t = Time.local(2010, "Feb", 18, 17, 22, 12)
|
9
9
|
flexmock(Time).should_receive(:now).once.and_return(t)
|
10
|
-
ensure_same_output Tracksperanto::Export::FlameStabilizer, P
|
10
|
+
ensure_same_output Tracksperanto::Export::FlameStabilizer, P
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_exporter_meta
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestBufferIO < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_write_in_mem_has_a_stringio
|
6
|
+
io = Tracksperanto::BufferIO.new
|
7
|
+
9000.times { io.write("a") }
|
8
|
+
assert_kind_of StringIO, io.__getobj__
|
9
|
+
assert_nothing_raised { io.close! }
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_write_larger_than_max_swaps_tempfile
|
13
|
+
io = Tracksperanto::BufferIO.new
|
14
|
+
110_000.times { io.write("a") }
|
15
|
+
f = io.__getobj__
|
16
|
+
assert_kind_of Tempfile, f
|
17
|
+
f.rewind
|
18
|
+
assert_equal 110_000, f.read.length
|
19
|
+
flexmock(f).should_receive(:close!).once
|
20
|
+
io.close!
|
21
|
+
end
|
22
|
+
end
|
data/test/test_flame_builder.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tracksperanto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.2
|
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: 2010-
|
12
|
+
date: 2010-03-04 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/pipeline/base.rb
|
90
90
|
- lib/tracksperanto.rb
|
91
91
|
- lib/tracksperanto/block_init.rb
|
92
|
+
- lib/tracksperanto/buffer_io.rb
|
92
93
|
- lib/tracksperanto/casts.rb
|
93
94
|
- lib/tracksperanto/const_name.rb
|
94
95
|
- lib/tracksperanto/ext_io.rb
|
@@ -96,6 +97,7 @@ files:
|
|
96
97
|
- lib/tracksperanto/format_detector.rb
|
97
98
|
- lib/tracksperanto/keyframe.rb
|
98
99
|
- lib/tracksperanto/progressive_io.rb
|
100
|
+
- lib/tracksperanto/returning.rb
|
99
101
|
- lib/tracksperanto/safety.rb
|
100
102
|
- lib/tracksperanto/simple_export.rb
|
101
103
|
- lib/tracksperanto/tracker.rb
|
@@ -177,6 +179,7 @@ files:
|
|
177
179
|
- test/middleware/test_scaler_middleware.rb
|
178
180
|
- test/middleware/test_shift_middleware.rb
|
179
181
|
- test/middleware/test_slip_middleware.rb
|
182
|
+
- test/test_buffer_io.rb
|
180
183
|
- test/test_const_name.rb
|
181
184
|
- test/test_extio.rb
|
182
185
|
- test/test_flame_builder.rb
|
@@ -248,6 +251,7 @@ test_files:
|
|
248
251
|
- test/middleware/test_scaler_middleware.rb
|
249
252
|
- test/middleware/test_shift_middleware.rb
|
250
253
|
- test/middleware/test_slip_middleware.rb
|
254
|
+
- test/test_buffer_io.rb
|
251
255
|
- test/test_const_name.rb
|
252
256
|
- test/test_extio.rb
|
253
257
|
- test/test_flame_builder.rb
|