mirror of https://github.com/n00mkrad/flowframes
Fix color hue shift when interpolating frames, support high bit depth frames
This commit is contained in:
parent
4eb1eac09c
commit
35b8d888d4
|
@ -20,6 +20,7 @@ namespace Flowframes
|
|||
public string outPath;
|
||||
public string FullOutPath { get; set; } = "";
|
||||
public AI ai;
|
||||
public string inPixFmt = "yuv420p";
|
||||
public Fraction inFps;
|
||||
public Fraction inFpsDetected;
|
||||
public Fraction outFps;
|
||||
|
@ -54,11 +55,17 @@ namespace Flowframes
|
|||
inFpsDetected = inFpsDetectedArg;
|
||||
inFps = inFpsArg;
|
||||
interpFactor = interpFactorArg;
|
||||
outFps = inFpsArg * (double)interpFactorArg;
|
||||
outItsScale = itsScale;
|
||||
outSettings = outSettingsArg;
|
||||
model = modelArg;
|
||||
|
||||
InitArgs();
|
||||
}
|
||||
|
||||
public void InitArgs ()
|
||||
{
|
||||
outFps = inFps * (double)interpFactor;
|
||||
|
||||
alpha = false;
|
||||
stepByStep = false;
|
||||
|
||||
|
@ -204,7 +211,7 @@ namespace Flowframes
|
|||
if (alpha || forceHqChroma) // Force PNG if alpha is enabled, or output is not 4:2:0 subsampled
|
||||
{
|
||||
if(type == FrameType.Both || type == FrameType.Import)
|
||||
framesExt = ".png";
|
||||
framesExt = ".tiff";
|
||||
|
||||
if (type == FrameType.Both || type == FrameType.Interp)
|
||||
interpExt = ".png";
|
||||
|
@ -212,7 +219,7 @@ namespace Flowframes
|
|||
else
|
||||
{
|
||||
if (type == FrameType.Both || type == FrameType.Import)
|
||||
framesExt = (Config.GetBool(Config.Key.jpegFrames) ? ".jpg" : ".png");
|
||||
framesExt = (Config.GetBool(Config.Key.jpegFrames) ? ".jpg" : ".tiff");
|
||||
|
||||
if (type == FrameType.Both || type == FrameType.Interp)
|
||||
interpExt = (Config.GetBool(Config.Key.jpegInterp) ? ".jpg" : ".png");
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace Flowframes.Forms.Main
|
|||
// Main Tab
|
||||
UiUtils.InitCombox(interpFactorCombox, 0);
|
||||
UiUtils.InitCombox(outSpeedCombox, 0);
|
||||
|
||||
|
||||
UiUtils.InitCombox(aiModel, 2);
|
||||
// Video Utils
|
||||
UiUtils.InitCombox(trimCombox, 0);
|
||||
|
@ -89,7 +89,7 @@ namespace Flowframes.Forms.Main
|
|||
UpdateOutputUi();
|
||||
}
|
||||
|
||||
public async void ResetOutputUi ()
|
||||
public async void ResetOutputUi()
|
||||
{
|
||||
comboxOutputEncoder.Items.Clear();
|
||||
Config.Set(Config.Key.PerformedHwEncCheck, false.ToString());
|
||||
|
@ -218,12 +218,23 @@ namespace Flowframes.Forms.Main
|
|||
public InterpSettings GetCurrentSettings()
|
||||
{
|
||||
SetTab(interpOptsTab.Name);
|
||||
string inPath = inputTbox.Text.Trim();
|
||||
string outPath = outputTbox.Text.Trim();
|
||||
AI ai = GetAi();
|
||||
float interpFactor = interpFactorCombox.GetFloat();
|
||||
float itsScale = outSpeedCombox.GetInt().Clamp(1, 64);
|
||||
return new InterpSettings(inPath, outPath, ai, currInFpsDetected, currInFps, interpFactor, itsScale, GetOutputSettings(), GetModel(ai));
|
||||
|
||||
var s = new InterpSettings()
|
||||
{
|
||||
inPath = inputTbox.Text.Trim(),
|
||||
outPath = outputTbox.Text.Trim(),
|
||||
ai = ai,
|
||||
inFpsDetected = currInFpsDetected,
|
||||
inFps = currInFps,
|
||||
interpFactor = interpFactorCombox.GetFloat(),
|
||||
outItsScale = outSpeedCombox.GetInt().Clamp(1, 64),
|
||||
outSettings = GetOutputSettings(),
|
||||
model = GetModel(ai),
|
||||
};
|
||||
|
||||
s.InitArgs();
|
||||
return s;
|
||||
}
|
||||
|
||||
public InterpSettings UpdateCurrentSettings(InterpSettings settings)
|
||||
|
@ -349,7 +360,7 @@ namespace Flowframes.Forms.Main
|
|||
return ai.FriendlyName + " - " + ai.Description;
|
||||
}
|
||||
|
||||
private void InitializeMainTab ()
|
||||
private void InitializeMainTab()
|
||||
{
|
||||
if (_mainTabInitialized)
|
||||
return;
|
||||
|
@ -416,7 +427,7 @@ namespace Flowframes.Forms.Main
|
|||
}
|
||||
}
|
||||
|
||||
private void SaveOutputSettings ()
|
||||
private void SaveOutputSettings()
|
||||
{
|
||||
var strings = new List<string>();
|
||||
if (comboxOutputFormat.Visible) strings.Add(comboxOutputFormat.Text);
|
||||
|
@ -692,7 +703,7 @@ namespace Flowframes.Forms.Main
|
|||
{
|
||||
if (!_initialized) return;
|
||||
|
||||
if(mainTabControl.SelectedTab == interpOptsTab)
|
||||
if (mainTabControl.SelectedTab == interpOptsTab)
|
||||
{
|
||||
aiCombox_SelectedIndexChanged(null, null);
|
||||
InitializeMainTab();
|
||||
|
|
|
@ -43,30 +43,56 @@ namespace Flowframes.Media
|
|||
|
||||
static string GetImgArgs(string extension, bool includePixFmt = true, bool alpha = false)
|
||||
{
|
||||
extension = extension.ToLowerInvariant().Remove(".").Replace("jpeg", "jpg");
|
||||
string pixFmt = "-pix_fmt rgb24";
|
||||
extension = extension.Lower().Remove(".").Replace("jpeg", "jpg");
|
||||
|
||||
string pixFmt = "yuv420p";
|
||||
|
||||
if (Interpolate.currentMediaFile != null && Interpolate.currentMediaFile.VideoStreams.Any())
|
||||
{
|
||||
pixFmt = Interpolate.currentMediaFile.VideoStreams.First().PixelFormat.Lower();
|
||||
}
|
||||
|
||||
bool inputHighBitDepth = pixFmt.Contains("p10") || pixFmt.Contains("p16");
|
||||
bool outputHighBitDepth = Interpolate.currentSettings.outSettings.PixelFormat.ToString().Lower().Contains("p10");
|
||||
|
||||
string args = "";
|
||||
|
||||
if (extension.Contains("png"))
|
||||
if (extension == "png")
|
||||
{
|
||||
pixFmt = alpha ? "rgba" : "rgb24";
|
||||
args = $"{pngCompr}";
|
||||
pixFmt = alpha ? "rgba" : "rgb24"; // PNG can't use YUV so we overwrite it with RGB
|
||||
args = pngCompr;
|
||||
}
|
||||
|
||||
if (extension.Contains("jpg"))
|
||||
else if (extension == "jpg")
|
||||
{
|
||||
pixFmt = "yuv420p";
|
||||
// Fallback to YUV420P if not in list of supported formats
|
||||
if (!new[] { "yuvj420p", "yuvj422p", "yuvj444p", "yuv420p", "yuv422p", "yuv444p" }.Contains(pixFmt))
|
||||
{
|
||||
pixFmt = "yuv420p";
|
||||
}
|
||||
|
||||
args = $"-q:v 1";
|
||||
}
|
||||
|
||||
if (extension.Contains("webp"))
|
||||
else if (extension == "tiff")
|
||||
{
|
||||
pixFmt = "yuv420p";
|
||||
// Fallback to YUV420P if not in list of supported formats
|
||||
if (!new[] { "rgb24", "rgb48le", "pal8", "rgba", "yuv420p", "yuv422p", "yuv440p", "yuv444p" }.Contains(pixFmt))
|
||||
{
|
||||
pixFmt = inputHighBitDepth && outputHighBitDepth ? "rgb48le" : "yuv420p";
|
||||
}
|
||||
}
|
||||
else if (extension == "webp")
|
||||
{
|
||||
// Fallback to YUV420P if not in list of supported formats
|
||||
if (!new[] { "bgra", "yuv420p", "yuva420p" }.Contains(pixFmt))
|
||||
{
|
||||
pixFmt = "yuv420p";
|
||||
}
|
||||
|
||||
args = $"-q:v 100";
|
||||
}
|
||||
|
||||
if (includePixFmt)
|
||||
args += $" -pix_fmt {pixFmt} -color_range full";
|
||||
args += $" -pix_fmt {pixFmt}";
|
||||
|
||||
return args;
|
||||
}
|
||||
|
@ -105,7 +131,7 @@ namespace Flowframes.Media
|
|||
}
|
||||
}
|
||||
|
||||
public static async Task CopyImages (string inpath, string outpath, bool showLog)
|
||||
public static async Task CopyImages(string inpath, string outpath, bool showLog)
|
||||
{
|
||||
if (showLog) Logger.Log($"Loading images from {new DirectoryInfo(inpath).Name}...");
|
||||
Directory.CreateDirectory(outpath);
|
||||
|
@ -129,14 +155,15 @@ namespace Flowframes.Media
|
|||
else
|
||||
{
|
||||
Logger.Log($"Symlink Import disabled, copying input frames...", true);
|
||||
await Task.Run(async () => {
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
foreach (KeyValuePair<string, string> moveFromToPair in moveFromTo)
|
||||
File.Copy(moveFromToPair.Key, moveFromToPair.Value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static bool AreImagesCompatible (string inpath, int maxHeight)
|
||||
static bool AreImagesCompatible(string inpath, int maxHeight)
|
||||
{
|
||||
NmkdStopwatch sw = new NmkdStopwatch();
|
||||
string[] validExtensions = Filetypes.imagesInterpCompat; // = new string[] { ".jpg", ".jpeg", ".png" };
|
||||
|
@ -310,7 +337,7 @@ namespace Flowframes.Media
|
|||
await RunFfmpeg(args, LogMode.Hidden);
|
||||
}
|
||||
|
||||
public static async Task GeneratePalette (string inputFile, string outputPath, int colors = 256)
|
||||
public static async Task GeneratePalette(string inputFile, string outputPath, int colors = 256)
|
||||
{
|
||||
string args = $"-i {inputFile.Wrap()} -vf palettegen={colors} {outputPath.Wrap()}";
|
||||
await Task.Run(() => AvProcess.RunFfmpegSync(args));
|
||||
|
|
|
@ -58,7 +58,9 @@ namespace Flowframes.Os
|
|||
l.Add($"inputPath = r'{inputPath}'");
|
||||
l.Add($"");
|
||||
|
||||
if (s.InterpSettings.inputIsFrames || (s.Dedupe && !s.Realtime))
|
||||
bool loadFrames = s.InterpSettings.inputIsFrames || (s.Dedupe && !s.Realtime);
|
||||
|
||||
if (loadFrames)
|
||||
{
|
||||
FileInfo[] frames = IoUtils.GetFileInfosSorted(s.InterpSettings.framesFolder, false, "*.*");
|
||||
string ext = frames.FirstOrDefault().Extension;
|
||||
|
@ -85,7 +87,7 @@ namespace Flowframes.Os
|
|||
l.Add($"clip = clip + firstFrame"); // Add to end (for seamless loop interpolation)
|
||||
}
|
||||
|
||||
l.Add(GetScaleLines(s));
|
||||
l.Add(GetScaleLines(s, loadFrames));
|
||||
|
||||
if (sc)
|
||||
l.Add($"clip = core.misc.SCDetect(clip=clip, threshold={s.SceneDetectSensitivity.ToStringDot()})"); // Scene detection
|
||||
|
@ -96,7 +98,7 @@ namespace Flowframes.Os
|
|||
if (s.Dedupe && !s.Realtime)
|
||||
l.Add(GetRedupeLines(s));
|
||||
|
||||
l.Add($"clip = vs.core.resize.Bicubic(clip, format=vs.YUV444P16, matrix_s=cMatrix)"); // Convert RGB to YUV
|
||||
l.Add($"clip = vs.core.resize.Bicubic(clip, format=vs.YUV444P16, matrix_s={(loadFrames ? "'470bg'" : "cMatrix")})"); // Convert RGB to YUV. Always use 470bg if input is frames
|
||||
|
||||
if (!s.Dedupe) // Ignore trimming code when using deduping that that already handles trimming in the frame order file
|
||||
{
|
||||
|
@ -131,7 +133,7 @@ namespace Flowframes.Os
|
|||
return vpyPath;
|
||||
}
|
||||
|
||||
static string GetScaleLines(VsSettings settings)
|
||||
static string GetScaleLines(VsSettings settings, bool loadFrames)
|
||||
{
|
||||
InterpSettings interp = settings.InterpSettings;
|
||||
bool resize = !interp.ScaledResolution.IsEmpty && interp.ScaledResolution != interp.InputResolution;
|
||||
|
@ -141,7 +143,7 @@ namespace Flowframes.Os
|
|||
s += $"cMatrix = '709'\n";
|
||||
s += $"\n";
|
||||
|
||||
if (!interp.inputIsFrames)
|
||||
if (!loadFrames)
|
||||
{
|
||||
s += "try:\n";
|
||||
s += " m = clip.get_frame(0).props._Matrix\n";
|
||||
|
|
Loading…
Reference in New Issue