2018-06-24 02:56:03 -05:00
using System ;
using System.Collections.Generic ;
2018-07-02 23:31:16 -05:00
using System.Collections.ObjectModel ;
2018-06-24 02:56:03 -05:00
using System.ComponentModel ;
2018-07-24 02:12:53 -05:00
using System.IO ;
2018-06-24 02:56:03 -05:00
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
2018-09-12 21:35:06 -05:00
using butterflow_ui.Properties ;
2018-06-24 02:56:03 -05:00
using csmic ;
namespace butterflow_ui
{
2018-07-03 18:59:28 -05:00
/// <summary> The butterflow options configuration. Contians all the options necessary to run butterflow and process a video. </summary>
2018-07-02 23:31:16 -05:00
public class OptionsConfiguration : PropertyChangedAlerter
2018-06-24 02:56:03 -05:00
{
#region Members
2018-07-09 14:49:48 -05:00
/// <summary> The default pyramid scale setting. </summary>
2018-07-03 23:26:42 -05:00
private const decimal DEFAULT_PYRAMID_SCALE = 0.5 m ;
2018-07-09 14:49:48 -05:00
/// <summary> The default levels setting. </summary>
2018-07-03 23:26:42 -05:00
private const int DEFAULT_LEVELS = 3 ;
2018-07-09 14:49:48 -05:00
/// <summary> The default window size setting. </summary>
2018-07-03 23:26:42 -05:00
private const int DEFAULT_WINDOW_SIZE = 25 ;
2018-07-09 14:49:48 -05:00
/// <summary> The default iterations setting. </summary>
2018-07-03 23:26:42 -05:00
private const int DEFAULT_ITERATIONS = 3 ;
2018-07-09 14:49:48 -05:00
/// <summary> The default pixel neighborhood setting. </summary>
2018-07-03 23:26:42 -05:00
private const int DEFAULT_PIXEL_NEIGHBORHOOD = 5 ;
2018-07-09 14:49:48 -05:00
/// <summary> The default smooth derivative standard deviation setting. </summary>
2018-07-03 23:26:42 -05:00
private const decimal DEFAULT_SMOOTH_DERIVATIVE_STANDARD_DEVIATION = 1.1 m ;
2018-07-09 14:49:48 -05:00
/// <summary> The default flow filter type setting. </summary>
2018-07-03 23:26:42 -05:00
private const FlowFilterType DEFAULT_FLOW_FILTER_TYPE = FlowFilterType . box ;
2018-07-24 02:12:53 -05:00
/// <summary> The output file format when operating on more than one video. </summary>
private const string OUTPUT_FILE_FORMAT = "{0}_{1}" ;
2018-07-03 23:26:42 -05:00
2018-07-04 18:11:25 -05:00
/// <summary> An input interpreter used for converting string values to numeric values. </summary>
2018-07-05 02:00:37 -05:00
[NonSerialized]
2018-06-24 02:56:03 -05:00
private InputInterpreter interpreter = new InputInterpreter ( ) ;
2018-07-03 18:59:28 -05:00
/// <summary> The aspect ratio used for calculating heights when the aspect ratio is locked. </summary>
private decimal aspectRatio = 0 ;
2018-06-24 02:56:03 -05:00
2018-07-09 14:49:48 -05:00
/// <summary> The playback rate. </summary>
2018-06-24 02:56:03 -05:00
private string playbackRate ;
2018-07-09 14:49:48 -05:00
/// <summary> A value indicating whether or not to keep the original audio in the final video. </summary>
2018-06-24 02:56:03 -05:00
private bool keepAudio ;
2018-07-09 14:49:48 -05:00
/// <summary> The width of the output video. </summary>
2018-06-24 02:56:03 -05:00
private int width ;
2018-07-09 14:49:48 -05:00
/// <summary> The height of the output video. </summary>
2018-06-24 02:56:03 -05:00
private int height ;
2018-07-09 14:49:48 -05:00
/// <summary> A value indicating whether or not to render unspecified subregions. </summary>
private bool keepSubregions ;
/// <summary> A value indicating whether or not to render the final video with lossless quality. </summary>
2018-06-24 03:29:34 -05:00
private bool losslessQuality ;
2018-07-09 14:49:48 -05:00
/// <summary> A value indicating whether or not to tune processing for smooth motion. </summary>
2018-07-03 18:59:28 -05:00
private bool smoothMotion ;
2018-07-09 14:49:48 -05:00
/// <summary> A value indicating whether or not to lock the aspect ratio to the <seealso cref="width"/> of the video. </summary>
2018-07-03 18:59:28 -05:00
private bool lockAspectRatio ;
2018-07-24 02:12:53 -05:00
/// <summary> The video input files. </summary>
private IEnumerable < string > videoInput ;
2018-07-09 14:49:48 -05:00
/// <summary> The video output file. </summary>
2018-07-01 17:02:50 -05:00
private string videoOutput ;
2018-07-09 14:49:48 -05:00
/// <summary> A value indicating whether or not to use fast pyramids when processing a video. </summary>
2018-07-03 18:59:28 -05:00
private bool fastPyramid ;
2018-07-09 14:49:48 -05:00
/// <summary> The pyramid scale setting. </summary>
2018-07-03 18:59:28 -05:00
private decimal pyramidScale ;
2018-07-09 14:49:48 -05:00
/// <summary> The level size setting. </summary>
2018-07-03 18:59:28 -05:00
private int levels ;
2018-07-09 14:49:48 -05:00
/// <summary> Size of the windowing average. </summary>
2018-07-03 18:59:28 -05:00
private int windowSize ;
2018-07-09 14:49:48 -05:00
/// <summary> The number of iterations per pyramid level. </summary>
2018-07-03 18:59:28 -05:00
private int iterations ;
2018-07-09 14:49:48 -05:00
/// <summary> The size of pixel neighborhood. </summary>
2018-07-03 18:59:28 -05:00
private int pixelNeighborhood ;
2018-07-09 14:49:48 -05:00
/// <summary> The standard deviation of smooth derivatives </summary>
2018-07-03 18:59:28 -05:00
private decimal smoothDerivativeStandardDeviation ;
2018-07-09 14:49:48 -05:00
/// <summary> Type of the flow filter to use for processing. </summary>
2018-07-03 23:26:42 -05:00
private FlowFilterType flowFilterType = FlowFilterType . box ;
2018-07-09 14:49:48 -05:00
/// <summary> The subregions of the video on which to process. </summary>
2018-07-02 23:31:16 -05:00
private ObservableCollection < ButterflowSubregion > subregions = new ObservableCollection < ButterflowSubregion > ( ) ;
2018-06-24 02:56:03 -05:00
#endregion
#region Properties
2018-07-01 17:02:50 -05:00
/// <summary> Gets the command line output given the current configuration. </summary>
/// <value> The command line output. </value>
public string CommandLineOutput
{
get
{
return ToButterflowArguments ( ) ;
}
}
2018-07-24 02:12:53 -05:00
/// <summary> Gets a value indicating whether butterflow will process multiple files. </summary>
/// <value> True if butterflow will process multiple files, false if not. </value>
public bool MultipleFiles
{
get
{
return this . VideoInput ! = null & & this . VideoInput . Count ( ) > 1 ;
}
}
2018-06-24 02:56:03 -05:00
/// <summary> Gets or sets the playback rate. </summary>
/// <value> The playback rate. </value>
public string PlaybackRate
{
get
{
return this . playbackRate ;
}
set
{
this . playbackRate = value ;
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( ) ;
2018-06-24 02:56:03 -05:00
}
}
/// <summary> Gets or sets a value indicating whether the keep audio. </summary>
2018-07-09 14:49:48 -05:00
/// <value> True if keeping audio in the final video, false if not. </value>
2018-06-24 02:56:03 -05:00
public bool KeepAudio
{
get
{
return this . keepAudio ;
}
set
{
this . keepAudio = value ;
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( ) ;
2018-06-24 02:56:03 -05:00
}
}
2018-07-03 18:59:28 -05:00
/// <summary> Gets or sets a value indicating whether the butterflow should be turned toward smooth motion. </summary>
/// <value> True if tuned toward smooth motion, false if not. </value>
public bool SmoothMotion
{
get
{
return this . smoothMotion ;
}
set
{
this . smoothMotion = value ;
OnPropertyChanged ( ) ;
}
}
/// <summary> Gets or sets a value indicating whether to lock aspect ratio of the video. </summary>
/// <value> True if locking aspect ratio of the video, false if not. </value>
public bool LockAspectRatio
{
get
{
return this . lockAspectRatio ;
}
set
{
2018-07-03 23:26:42 -05:00
if ( value & & this . width ! = 0 & & this . height ! = 0 )
2018-07-03 18:59:28 -05:00
{
this . aspectRatio = Convert . ToDecimal ( this . height ) / Convert . ToDecimal ( this . width ) ;
}
this . lockAspectRatio = value ;
OnPropertyChanged ( ) ;
}
}
2018-07-01 17:02:50 -05:00
/// <summary> Gets or sets the width of the video output. </summary>
/// <value> The width of the video output. </value>
2018-06-24 02:56:03 -05:00
public string Width
{
get
{
return this . width . ToString ( ) ;
}
set
{
2018-07-03 18:59:28 -05:00
var oldWidth = this . width ;
2018-06-24 02:56:03 -05:00
interpreter . Interpret ( value ) ;
this . width = interpreter . Int ;
2018-07-03 18:59:28 -05:00
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( ) ;
2018-07-03 18:59:28 -05:00
if ( this . lockAspectRatio )
{
interpreter . Interpret ( string . Format ( "{0} * {1}" , this . aspectRatio , this . width ) ) ;
this . height = interpreter . Int ;
OnPropertyChanged ( "Height" ) ;
}
2018-06-24 02:56:03 -05:00
}
}
2018-07-01 17:02:50 -05:00
/// <summary> Gets or sets the height of the video output. </summary>
/// <value> The height of the video output. </value>
2018-06-24 02:56:03 -05:00
public string Height
{
get
{
return this . height . ToString ( ) ;
}
set
{
interpreter . Interpret ( value ) ;
this . height = interpreter . Int ;
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( ) ;
2018-06-24 02:56:03 -05:00
}
}
2018-07-03 23:26:42 -05:00
/// <summary> Gets or sets a value indicating whether the keep subregions that are not explicitly specified. </summary>
/// <value> True if keeping subregions not explicitly specified, false if not. </value>
public bool KeepSubregions
2018-07-01 17:02:50 -05:00
{
get
{
2018-07-09 14:49:48 -05:00
return this . keepSubregions ;
2018-07-01 17:02:50 -05:00
}
set
{
2018-07-09 14:49:48 -05:00
this . keepSubregions = value ;
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( ) ;
2018-07-01 17:02:50 -05:00
}
}
2018-06-24 03:29:34 -05:00
/// <summary> Gets or sets a value indicating whether the result is rendered in lossless quality. </summary>
/// <value> True if lossless quality is selected, false if not. </value>
public bool LosslessQuality
{
get
{
return this . losslessQuality ;
}
set
{
this . losslessQuality = value ;
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( ) ;
2018-06-24 03:29:34 -05:00
}
}
2018-07-01 17:02:50 -05:00
/// <summary> Gets or sets the video input file path. </summary>
/// <value> The video input file path. </value>
2018-07-24 02:12:53 -05:00
public IEnumerable < string > VideoInput
2018-07-01 17:02:50 -05:00
{
get
{
return this . videoInput ;
}
set
{
this . videoInput = value ;
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( ) ;
2018-07-24 02:12:53 -05:00
OnPropertyChanged ( "MultipleFiles" ) ;
2018-07-01 17:02:50 -05:00
}
}
/// <summary> Gets or sets the video output file path. </summary>
/// <value> The video output file path. </value>
public string VideoOutput
{
get
{
return this . videoOutput ;
}
set
{
this . videoOutput = value ;
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( ) ;
}
}
2018-07-03 18:59:28 -05:00
/// <summary> Gets or sets a value indicating whether to use fast pyramids. </summary>
/// <value> True if using fast pyramids, false if not. </value>
public bool FastPyramid
{
get
{
return this . fastPyramid ;
}
set
{
this . fastPyramid = value ;
OnPropertyChanged ( ) ;
}
}
/// <summary> Gets or sets the pyramid scale factor. </summary>
/// <value> The pyramid scale factor. </value>
public string PyramidScale
{
get
{
return this . pyramidScale . ToString ( ) ;
}
set
{
interpreter . Interpret ( value ) ;
this . pyramidScale = interpreter . Decimal ;
OnPropertyChanged ( ) ;
}
}
/// <summary> Gets or sets the number of pyramid layers. </summary>
/// <value> The number of pyramid layers. </value>
public string Levels
{
get
{
return this . levels . ToString ( ) ;
}
set
{
interpreter . Interpret ( value ) ;
this . levels = interpreter . Int ;
OnPropertyChanged ( ) ;
}
}
/// <summary> Gets or sets the size of the windowing average. </summary>
/// <value> The size of the windowing average. </value>
public string WindowSize
{
get
{
return this . windowSize . ToString ( ) ;
}
set
{
interpreter . Interpret ( value ) ;
this . windowSize = interpreter . Int ;
OnPropertyChanged ( ) ;
}
}
/// <summary> Gets or sets the number of iterations at each pyramid level. </summary>
/// <value> The number of iterations at each pyramid level. </value>
public string Iterations
{
get
{
return this . iterations . ToString ( ) ;
}
set
{
interpreter . Interpret ( value ) ;
this . iterations = interpreter . Int ;
OnPropertyChanged ( ) ;
}
}
/// <summary> Gets or sets the size of the pixel neighborhood. </summary>
/// <value> The size of the pixel neighborhood. </value>
2018-07-04 19:46:33 -05:00
/// <remarks> Per butterflow's documentation, the valid range for --poly-n is {5,7}. </remarks>
2018-07-03 18:59:28 -05:00
public string PixelNeighborhood
{
get
{
return this . pixelNeighborhood . ToString ( ) ;
}
set
{
interpreter . Interpret ( value ) ;
2018-07-03 23:26:42 -05:00
2018-07-04 19:46:33 -05:00
if ( interpreter . Int > = 5 & & interpreter . Int < = 7 )
2018-07-03 23:26:42 -05:00
{
this . pixelNeighborhood = interpreter . Int ;
}
2018-07-03 18:59:28 -05:00
OnPropertyChanged ( ) ;
}
}
/// <summary> Gets or sets the standard deviation of smooth derivatives. </summary>
/// <value> The standard deviation of smooth derivatives. </value>
public string SmoothDerivativeStandardDeviation
{
get
{
return this . smoothDerivativeStandardDeviation . ToString ( ) ;
}
set
{
interpreter . Interpret ( value ) ;
this . smoothDerivativeStandardDeviation = interpreter . Decimal ;
OnPropertyChanged ( ) ;
}
}
2018-07-03 23:26:42 -05:00
/// <summary> Gets or sets the type of the flow filter used for optical flow calculations. </summary>
/// <value> The type of the flow filter used for optical flow calculations. </value>
public FlowFilterType FlowFilterType
{
get
{
return this . flowFilterType ;
}
set
{
this . flowFilterType = value ;
OnPropertyChanged ( ) ;
}
}
2018-07-02 23:31:16 -05:00
/// <summary> Gets or sets the subregions of the video on which to work. </summary>
/// <value> The subregions of the video. </value>
public ObservableCollection < ButterflowSubregion > Subregions
{
get
{
return this . subregions ;
}
set
{
this . subregions = value ;
OnPropertyChanged ( ) ;
}
}
#endregion
#region Contructors
/// <summary> Default constructor. </summary>
public OptionsConfiguration ( )
{
2018-07-03 23:26:42 -05:00
// Set default values
this . pyramidScale = DEFAULT_PYRAMID_SCALE ;
this . levels = DEFAULT_LEVELS ;
this . windowSize = DEFAULT_WINDOW_SIZE ;
this . iterations = DEFAULT_ITERATIONS ;
this . pixelNeighborhood = DEFAULT_PIXEL_NEIGHBORHOOD ;
this . smoothDerivativeStandardDeviation = DEFAULT_SMOOTH_DERIVATIVE_STANDARD_DEVIATION ;
this . flowFilterType = DEFAULT_FLOW_FILTER_TYPE ;
2018-07-24 02:12:53 -05:00
this . videoInput = new string [ 0 ] ;
2018-07-03 23:26:42 -05:00
this . subregions . CollectionChanged + = Subregions_CollectionChanged ; ;
2018-07-02 23:31:16 -05:00
}
2018-07-03 23:26:42 -05:00
/// <summary> Event handler. Called by Subregions for collection changed events. </summary>
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Notify collection changed event information. </param>
private void Subregions_CollectionChanged ( object sender , System . Collections . Specialized . NotifyCollectionChangedEventArgs e )
2018-07-02 23:31:16 -05:00
{
2018-07-03 18:59:28 -05:00
if ( e . NewItems ! = null )
2018-07-02 23:31:16 -05:00
{
2018-07-03 18:59:28 -05:00
foreach ( ButterflowSubregion newItem in e . NewItems )
2018-07-02 23:31:16 -05:00
{
newItem . PropertyChanged + = SubregionPropertyChanged ;
}
}
2018-07-03 18:59:28 -05:00
if ( e . OldItems ! = null )
2018-07-02 23:31:16 -05:00
{
2018-07-03 18:59:28 -05:00
foreach ( ButterflowSubregion oldItem in e . OldItems )
2018-07-02 23:31:16 -05:00
{
oldItem . PropertyChanged - = SubregionPropertyChanged ;
}
2018-07-01 17:02:50 -05:00
}
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( "CommandLineOutput" ) ;
2018-07-01 17:02:50 -05:00
}
2018-06-24 02:56:03 -05:00
#endregion
#region Methods
2019-01-06 00:20:29 -06:00
/// <summary> Subregion property changed. </summary>
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Property changed event information. </param>
2018-07-02 23:31:16 -05:00
private void SubregionPropertyChanged ( object sender , PropertyChangedEventArgs e )
2018-06-24 02:56:03 -05:00
{
2018-07-02 23:31:16 -05:00
OnPropertyChanged ( "CommandLineOutput" ) ;
2018-07-01 17:02:50 -05:00
}
2019-01-06 00:20:29 -06:00
/// <summary> Force the object's properties to report as updated. </summary>
public void ForceUpdate ( )
{
OnPropertyChanged ( ) ;
}
2018-07-05 02:00:37 -05:00
/// <summary> Converts this object to a <seealso cref="OptionsConfigurationFile"/>. </summary>
/// <returns> This object as an OptionsConfigurationFile. </returns>
public OptionsConfigurationFile ToFile ( )
{
var file = new OptionsConfigurationFile ( )
{
FastPyramid = this . fastPyramid ,
FlowFilterType = this . flowFilterType ,
Iterations = this . iterations ,
KeepAudio = this . keepAudio ,
2018-07-09 14:49:48 -05:00
KeepSubregions = this . keepSubregions ,
2018-07-05 02:00:37 -05:00
Levels = this . levels ,
LockAspectRatio = this . lockAspectRatio ,
LosslessQuality = this . losslessQuality ,
PixelNeighborhood = this . pixelNeighborhood ,
PlaybackRate = this . playbackRate ,
PyramidScale = this . pyramidScale ,
SmoothDerivativeStandardDeviation = this . smoothDerivativeStandardDeviation ,
SmoothMotion = this . smoothMotion ,
WindowSize = this . windowSize
} ;
return file ;
}
/// <summary> Loads an option configuration file's contents into the <seealso cref="OptionsConfiguration"/>. </summary>
/// <param name="file"> The file to load. </param>
public void LoadFile ( OptionsConfigurationFile file )
{
this . FastPyramid = file . FastPyramid ;
this . FlowFilterType = file . FlowFilterType ;
this . Iterations = file . Iterations . ToString ( ) ;
this . KeepAudio = file . KeepAudio ;
this . KeepSubregions = file . KeepSubregions ;
this . Levels = file . Levels . ToString ( ) ;
this . LockAspectRatio = file . LockAspectRatio ;
this . LosslessQuality = file . LosslessQuality ;
this . PixelNeighborhood = file . PixelNeighborhood . ToString ( ) ;
this . PlaybackRate = file . PlaybackRate ;
this . PyramidScale = file . PyramidScale . ToString ( ) ;
this . SmoothDerivativeStandardDeviation = file . SmoothDerivativeStandardDeviation . ToString ( ) ;
this . SmoothMotion = file . SmoothMotion ;
this . WindowSize = file . WindowSize . ToString ( ) ;
}
2018-07-01 17:02:50 -05:00
/// <summary> Converts this object to a butterflow options. </summary>
/// <returns> This object as a string. </returns>
2018-07-24 02:12:53 -05:00
public string ToButterflowArguments ( int videoInputIndex = 0 )
2018-07-01 17:02:50 -05:00
{
2018-07-03 23:26:42 -05:00
var stringBuilder = new StringBuilder ( "-v " ) ; // Verbose
2018-07-01 17:02:50 -05:00
2018-07-03 23:26:42 -05:00
if ( this . LockAspectRatio )
2018-07-01 17:02:50 -05:00
{
stringBuilder . AppendFormat ( "-vs {0}:-1 " , this . Width ) ;
}
else
{
stringBuilder . AppendFormat ( "-vs {0}:{1} " , this . Width , this . Height ) ;
}
2019-01-06 00:20:29 -06:00
if ( Settings . Default . Device = = 0 )
{
stringBuilder . Append ( "-sw " ) ;
}
if ( Settings . Default . Device > 0 )
2018-09-12 21:35:06 -05:00
{
stringBuilder . AppendFormat ( "-device {0} " , Settings . Default . Device ) ;
}
2018-07-02 23:31:16 -05:00
if ( ! string . IsNullOrWhiteSpace ( this . PlaybackRate ) ) stringBuilder . AppendFormat ( "-r {0} " , this . PlaybackRate ) ;
2018-07-01 17:02:50 -05:00
if ( this . KeepAudio ) stringBuilder . Append ( "-audio " ) ;
if ( this . LosslessQuality ) stringBuilder . Append ( "-l " ) ;
2018-07-02 23:31:16 -05:00
if ( this . Subregions . Any ( ) )
{
2018-07-04 00:23:00 -05:00
stringBuilder . Append ( "-s " ) ;
2018-07-02 23:31:16 -05:00
foreach ( var anon in this . Subregions . Select ( ( sr , index ) = > new { Index = index , Subregion = sr } ) )
{
string format = "ss\\.fff" ;
if ( anon . Index > 0 )
{
stringBuilder . Append ( ":" ) ;
}
if ( anon . Subregion . Start . TotalHours > 1 )
{
format = "h\\:m\\:s\\.fff" ;
}
else if ( anon . Subregion . Start . TotalMinutes > 1 )
{
format = "m\\:s\\.fff" ;
}
stringBuilder . AppendFormat ( "a={0},b={1},{2}={3}" , anon . Subregion . Start . ToString ( format ) , anon . Subregion . ToEnd ? "end" : anon . Subregion . End . ToString ( format ) , anon . Subregion . SubregionType , anon . Subregion . Value ) ;
}
stringBuilder . Append ( " " ) ;
}
2018-07-03 23:26:42 -05:00
if ( this . KeepSubregions ) stringBuilder . Append ( "-k " ) ;
if ( this . SmoothMotion ) stringBuilder . Append ( "-sm " ) ;
if ( this . FastPyramid ) stringBuilder . Append ( "--fast-pyr " ) ;
if ( this . pyramidScale ! = DEFAULT_PYRAMID_SCALE ) stringBuilder . AppendFormat ( "--pyr-scale {0} " , this . PyramidScale ) ;
if ( this . levels ! = DEFAULT_LEVELS ) stringBuilder . AppendFormat ( "--levels {0} " , this . Levels ) ;
if ( this . windowSize ! = DEFAULT_WINDOW_SIZE ) stringBuilder . AppendFormat ( "--winsize {0} " , this . WindowSize ) ;
if ( this . iterations ! = DEFAULT_ITERATIONS ) stringBuilder . AppendFormat ( "--iters {0} " , this . Iterations ) ;
if ( this . pixelNeighborhood ! = DEFAULT_PIXEL_NEIGHBORHOOD ) stringBuilder . AppendFormat ( "--poly-n {0} " , this . PixelNeighborhood ) ;
if ( this . smoothDerivativeStandardDeviation ! = DEFAULT_SMOOTH_DERIVATIVE_STANDARD_DEVIATION ) stringBuilder . AppendFormat ( "--poly-s {0} " , this . SmoothDerivativeStandardDeviation ) ;
if ( this . FlowFilterType ! = DEFAULT_FLOW_FILTER_TYPE ) stringBuilder . AppendFormat ( "-ff {0} " , this . FlowFilterType ) ;
2018-07-04 00:16:54 -05:00
2018-07-24 02:12:53 -05:00
if ( ! string . IsNullOrWhiteSpace ( this . VideoOutput ) )
{
string videoOutputFile = string . Empty ;
if ( this . MultipleFiles )
{
var format = new StringBuilder ( Path . GetFileNameWithoutExtension ( this . VideoOutput ) ) ;
format . Append ( "_{0:" ) ;
for ( int i = 0 ; i < this . videoInput . Count ( ) . ToString ( ) . Length ; i + + )
{
format . Append ( "0" ) ;
}
format . Append ( "}" ) ;
format . Append ( Path . GetExtension ( this . VideoOutput ) ) ;
var newName = string . Format ( format . ToString ( ) , videoInputIndex + 1 ) ; // Since the index is zero based, we will add one to make the output more human readable.
videoOutputFile = Path . Combine ( Path . GetDirectoryName ( this . VideoOutput ) , newName ) ;
}
else
{
videoOutputFile = this . VideoOutput ;
}
stringBuilder . AppendFormat ( "-o \"{0}\" " , videoOutputFile ) ;
}
if ( this . VideoInput . Any ( ) )
{
stringBuilder . AppendFormat ( "\"{0}\"" , this . VideoInput . ElementAt ( videoInputIndex ) ) ;
}
2018-07-03 23:26:42 -05:00
2018-07-01 17:02:50 -05:00
return stringBuilder . ToString ( ) ;
}
/// <summary> Returns a string that represents the current object. </summary>
/// <returns> A string that represents the current object. </returns>
public override string ToString ( )
{
return ToButterflowArguments ( ) ;
2018-06-24 02:56:03 -05:00
}
#endregion
}
}