More reliable float->fraction conversion, fixed manual fps input

This commit is contained in:
N00MKRAD
2021-04-04 21:54:26 +02:00
parent deb88d43c2
commit f51c10bef0
4 changed files with 9 additions and 56 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Windows.Navigation;
namespace Flowframes.Data
{
@@ -42,9 +43,9 @@ namespace Flowframes.Data
public Fraction(float value)
{
int[] frac = value.ToFraction();
Numerator = frac[0];
Denominator = frac[1];
Numerator = (value * 10000f).RoundToInt();
Denominator = 10000;
this = GetReduced();
}
public Fraction(string text)

View File

@@ -7,6 +7,7 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using Flowframes.Data;
namespace Flowframes
{
@@ -185,57 +186,5 @@ namespace Flowframes
{
return str.Split(new string[] { trimStr }, StringSplitOptions.None);
}
public static int[] ToFraction(this float value, double accuracy = 0.02)
{
int sign = Math.Sign(value);
if (sign == -1)
value = Math.Abs(value);
// Accuracy is the maximum relative error; convert to absolute maxError
double maxError = sign == 0 ? accuracy : value * accuracy;
int n = (int)Math.Floor(value);
value -= n;
if (value < maxError)
return new int[] { sign * n, 1 };
if (1 - maxError < value)
return new int[] { sign * (n + 1), 1 };
// The lower fraction is 0/1
int lower_n = 0;
int lower_d = 1;
// The upper fraction is 1/1
int upper_n = 1;
int upper_d = 1;
while (true)
{
// The middle fraction is (lower_n + upper_n) / (lower_d + upper_d)
int middle_n = lower_n + upper_n;
int middle_d = lower_d + upper_d;
if (middle_d * (value + maxError) < middle_n)
{
// real + error < middle : middle is our new upper
upper_n = middle_n;
upper_d = middle_d;
}
else if (middle_n < (value - maxError) * middle_d)
{
// middle < real - error : middle is our new lower
lower_n = middle_n;
lower_d = middle_d;
}
else
{
return new int[] {(n * middle_d + middle_n) * sign, middle_d};
}
}
}
}
}

View File

@@ -288,6 +288,9 @@ namespace Flowframes
{
float fpsOut = fpsInTbox.GetFloat() * interpFactorCombox.GetFloat();
fpsOutTbox.Text = fpsOut.ToString();
if (!fpsInTbox.ReadOnly)
currInFps = new Fraction(fpsInTbox.GetFloat());
}
private void interpFactorCombox_SelectedIndexChanged(object sender, EventArgs e)

View File

@@ -73,7 +73,7 @@ namespace Flowframes.Media
if (logMode != LogMode.Hidden)
Logger.Log((resampleFps <= 0) ? $"Encoding GIF..." : $"Encoding GIF resampled to {resampleFps.ToString().Replace(",", ".")} FPS...");
string vfrFilename = Path.GetFileName(framesFile);
string paletteFilter = palette ? $"-vf \"split[s0][s1];[s0]palettegen={colors}[p];[s1][p]paletteuse=dither=bayer\"" : "";
string paletteFilter = palette ? $"-vf \"split[s0][s1];[s0]palettegen={colors}[p];[s1][p]paletteuse=dither=bayer:bayer_scale=2\"" : "";
string fpsFilter = (resampleFps <= 0) ? "" : $"fps=fps={resampleFps.ToStringDot()}";
string vf = FormatUtils.ConcatStrings(new string[] { paletteFilter, fpsFilter });
string args = $"-f concat -r {rate} -i {vfrFilename.Wrap()} -f gif {vf} {outPath.Wrap()}";