class Tracksperanto::Export::FlameStabilizer
TODO: this exporter is MAJORLY slow now
Constants
- COLOR
- DATETIME_FORMAT
Public Class Methods
desc_and_extension()
click to toggle source
# File lib/export/flame_stabilizer.rb, line 7 def self.desc_and_extension "flame.stabilizer" end
human_name()
click to toggle source
# File lib/export/flame_stabilizer.rb, line 11 def self.human_name "Flame/Smoke 2D Stabilizer setup" end
Public Instance Methods
end_export()
click to toggle source
# File lib/export/flame_stabilizer.rb, line 22 def end_export # Now make another writer, this time for our main IO @writer = FlameChannelParser::Builder.new(@io) # Now we know how many trackers we have so we can write the header # data along with NbTrackers write_header_with_number_of_trackers(@counter) # Now write everything that we accumulated earlier into the base IO @temp.rewind @io.write(@temp.read) until @temp.eof? @temp.close! # Send the ChannelEnd command and list the trackers @writer.channel_end @counter.times do |i| @writer.write_unterminated_block!("tracker", i) do |t| t.active true t.color_hash!("colour", 0, 100, 0) t.fixed_ref true t.fixed_x false t.fixed_y false t.tolerance 100 end end # Write the finalizing "End" @writer.write_loose!("end") end
end_tracker_segment()
click to toggle source
# File lib/export/flame_stabilizer.rb, line 67 def end_tracker_segment # We write these at tracker end since we need to know in advance # how many keyframes they should contain write_shift_channel("shift/x", @x_shift_values) write_shift_channel("shift/y", @y_shift_values) # And finish with the offset channels. The order of channels is important! # (otherwise the last tracker's shift animation is not imported by Flame) # https://github.com/guerilla-di/tracksperanto/issues/1 write_offset_channels end
export_point(frame, abs_float_x, abs_float_y, float_residual)
click to toggle source
# File lib/export/flame_stabilizer.rb, line 57 def export_point(frame, abs_float_x, abs_float_y, float_residual) flame_frame = frame + 1 if @write_first_frame export_first_point(flame_frame, abs_float_x, abs_float_y) @write_first_frame = false else export_remaining_point(flame_frame, abs_float_x, abs_float_y) end end
start_export( img_width, img_height)
click to toggle source
# File lib/export/flame_stabilizer.rb, line 15 def start_export( img_width, img_height) @counter = 0 @width, @height = img_width, img_height @temp = Tracksperanto::BufferIO.new @writer = FlameChannelParser::Builder.new(@temp) end
start_tracker_segment(tracker_name)
click to toggle source
# File lib/export/flame_stabilizer.rb, line 52 def start_tracker_segment(tracker_name) @counter += 1 @write_first_frame = true end
Private Instance Methods
export_first_point(flame_frame, abs_float_x, abs_float_y)
click to toggle source
# File lib/export/flame_stabilizer.rb, line 88 def export_first_point(flame_frame, abs_float_x, abs_float_y) @base_x, @base_y = abs_float_x, abs_float_y write_first_frame(abs_float_x, abs_float_y) # For Flame to recognize the reference frame of the Shift channel # we need it to contain zero as an int, not as a float. The shift proceeds # from there. @x_shift_values = [[flame_frame, 0]] @y_shift_values = [[flame_frame, 0]] end
export_remaining_point(flame_frame, abs_float_x, abs_float_y)
click to toggle source
# File lib/export/flame_stabilizer.rb, line 81 def export_remaining_point(flame_frame, abs_float_x, abs_float_y) # Just continue buffering the upcoming shift keyframes and flush them in the end shift_x, shift_y = @base_x - abs_float_x, @base_y - abs_float_y @x_shift_values.push([flame_frame, shift_x]) @y_shift_values.push([flame_frame, shift_y]) end
prefix(tracker_channel)
click to toggle source
# File lib/export/flame_stabilizer.rb, line 117 def prefix(tracker_channel) "tracker%d/%s" % [@counter, tracker_channel] end
write_deltax_and_deltay_channels()
click to toggle source
# File lib/export/flame_stabilizer.rb, line 212 def write_deltax_and_deltay_channels # This is used for deltax and deltay (offset tracking). # We set it to zero and lock %w( ref/dx ref/dy).map(&method(:prefix)).each do | chan, v | @writer.channel(chan) do | c | c.extrapolation("constant") c.value 0 c.colour(COLOR) c.size 2 c.key_version 1 c.key(0) do | k | k.frame 0 k.value 0 k.value_lock true k.delete_lock true k.interpolation :constant end c.key(1) do | k | k.frame 1 k.value 0 k.value_lock true k.delete_lock true k.interpolation :constant end end # Chan block end end
write_first_frame(x, y)
click to toggle source
# File lib/export/flame_stabilizer.rb, line 145 def write_first_frame(x, y) write_track_channels write_track_width_and_height write_ref_width_and_height write_ref_channels(x, y) write_deltax_and_deltay_channels end
write_header_with_number_of_trackers(number_of_trackers)
click to toggle source
# File lib/export/flame_stabilizer.rb, line 121 def write_header_with_number_of_trackers(number_of_trackers) @writer.stabilizer_file_version "5.0" @writer.creation_date(Time.now.strftime(DATETIME_FORMAT)) @writer.linebreak!(2) @writer.nb_trackers number_of_trackers @writer.selected 0 @writer.frame_width @width @writer.frame_height @height @writer.auto_key true @writer.motion_path true @writer.icons true @writer.auto_pan false # hate it! @writer.edit_mode 0 @writer.format 0 @writer.color_hash!("padding", 0, 100, 0) @writer.oversampling false @writer.opacity 50 @writer.zoom 3 @writer.field false @writer.backward false @writer.anim end
write_offset_channels()
click to toggle source
# File lib/export/flame_stabilizer.rb, line 240 def write_offset_channels %w(offset/x offset/y).map(&method(:prefix)).each do | c | @writer.channel(c) do | chan | chan.extrapolation :constant chan.value 0 end end end
write_ref_channels(ref_x, ref_y)
click to toggle source
The Ref channel contains the reference for the shift channel in absolute coordinates, and is set as float. Since we do not “snap” the tracker in the process it's enough for us to make one keyframe in the ref channels at the same frame as the first shift keyframe
# File lib/export/flame_stabilizer.rb, line 193 def write_ref_channels(ref_x, ref_y) %w( ref/x ref/y).map(&method(:prefix)).zip([ref_x, ref_y]).each do | cname, default | @writer.channel(cname) do | c | c.extrapolation("constant") c.value(default) c.colour(COLOR) c.key_version 1 c.size 1 c.key(0) do | k | k.frame 1 k.value default k.interpolation :constant k.left_slope 2.4 k.right_slope 2.4 end end end end
write_ref_width_and_height()
click to toggle source
The size of the reference area
# File lib/export/flame_stabilizer.rb, line 179 def write_ref_width_and_height %w( ref/width ref/height).map(&method(:prefix)).each do | channel_name | @writer.channel(channel_name) do | c | c.extrapolation :linear c.value 10 c.colour COLOR end end end
write_shift_channel(name_without_prefix, values)
click to toggle source
The shift channel is what determines how the tracking point moves.
# File lib/export/flame_stabilizer.rb, line 99 def write_shift_channel(name_without_prefix, values) @writer.channel(prefix(name_without_prefix)) do | c | c.extrapolation :constant c.value values[0][1] c.key_version 1 c.size values.length values.each_with_index do | (f, v), i | c.key(i) do | k | k.frame f k.value v k.interpolation :linear k.left_slope 2.4 k.right_slope 2.4 end end end end
write_track_channels()
click to toggle source
# File lib/export/flame_stabilizer.rb, line 153 def write_track_channels ctr_x, ctr_y = @width / 2, @height / 2 # track determines where the tracking box is, and should be in the center # of the image for Flame to compute all other shifts properly %w( track/x track/y).map(&method(:prefix)).zip([ctr_x, ctr_y]).each do | cname, default | @writer.channel(cname) do | c | c.extrapolation("constant") c.value(default.to_i) c.colour(COLOR) end end end
write_track_width_and_height()
click to toggle source
The size of the tracking area
# File lib/export/flame_stabilizer.rb, line 168 def write_track_width_and_height %w( track/width track/height ).map(&method(:prefix)).each do | channel_name | @writer.channel(channel_name) do | c | c.extrapolation :linear c.value 15 c.colour COLOR end end end