You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Gateway/Proxy/AvifConverter.cs

193 lines
6.4 KiB
C#

2 years ago
using System;
10 months ago
namespace UMC.ITME
2 years ago
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
/// <summary>
/// A executer for `cavif` which is a Encoder/converter for AVIF images.
/// Please have the native `cavif` libraries next to your application.
/// Grab prebuilt `cavif` from here: https://github.com/kornelski/cavif-rs/releases
/// </summary>
public static class AvifConverter
{
/// <summary>
/// Converts PNG/JPEG to AVIF format.
/// </summary>
public static Task<AvifConvertResult> EncodeImage(string imageFile, string outputImageFile = null, AvifConverterOptions options = null)
{
string converterPath = GetConverterPath();
string arguments = GenerateArgument(imageFile, outputImageFile, options);
return RunEncodeProcessAsync(converterPath, arguments);
}
private static string GenerateArgument(string imageFile, string outputImage = null, AvifConverterOptions options = null)
{
List<string> list = new List<string>(8);
if (options != null)
{
if (!options!.EmitMesage)
{
list.Add("--quiet");
}
if (options!.Overwrite)
{
list.Add("--overwrite");
}
if (options!.Speed.HasValue)
{
list.Add("--speed " + options!.Speed.Value);
}
if (options!.Quality.HasValue)
{
list.Add("--quality " + options!.Quality.Value);
}
if (options!.ColorRgb == true)
{
list.Add("--color rgb");
}
if (options!.DirtyAlpha == true)
{
list.Add("--dirty-alpha");
}
}
else
{
list.Add("--quiet");
list.Add("--overwrite");
}
if (outputImage != null)
{
list.Add("-o \"" + outputImage + "\"");
}
list.Add("\"" + imageFile + "\"");
return string.Join(" ", list);
}
private static string GetConverterPath()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return ".\\native\\cavif.exe";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return "./native/cavif";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return "./native/cavif";
}
else
{
throw new PlatformNotSupportedException();
}
}
private static Task<AvifConvertResult> RunEncodeProcessAsync(string aviflibExe, string arguments)
{
TaskCompletionSource<AvifConvertResult> tcs = new TaskCompletionSource<AvifConvertResult>();
try
{
Process process = new Process
{
StartInfo = {
FileName = aviflibExe,
Arguments = arguments,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
},
EnableRaisingEvents = true
};
process.Exited += delegate
{
string text = "";
while (!process.StandardOutput.EndOfStream)
{
text = text + process.StandardOutput.ReadLine() + Environment.NewLine;
}
bool success = process.ExitCode == 0;
tcs.SetResult(new AvifConvertResult(success, text));
process.Dispose();
};
process.Start();
}
catch (Exception ex)
{
return Task.FromResult(new AvifConvertResult(success: false, ex.Message));
}
return tcs.Task;
}
}
public class AvifConvertResult
{
public bool Success { get; }
public string Message { get; } = string.Empty;
public AvifConvertResult()
{
}
public AvifConvertResult(bool success)
{
Success = success;
}
public AvifConvertResult(bool success, string message)
{
Success = success;
Message = message;
}
}
/// <summary>
/// Read more about options here:
/// https://github.com/kornelski/cavif-rs
/// </summary>
public class AvifConverterOptions
{
/// <summary>
/// Quality from 1 (worst) to 100 (best), the default value is 80. The numbers have different meaning than JPEG's quality scale. Beware when comparing codecs. There is no lossless compression support.
/// </summary>
public int? Quality { get; set; }
/// <summary>
/// Encoding speed between 1 (best, but slowest) and 10 (fastest, but a blurry mess), the default value is 4. Speeds 1 and 2 are unbelievably slow, but make files ~3-5% smaller. Speeds 7 and above degrade compression significantly, and are not recommended.
/// </summary>
public int? Speed { get; set; }
/// <summary>
/// Replace files if there's .avif already. By default the existing files are overwritten.
/// </summary>
public bool Overwrite { get; set; } = true;
/// <summary>
/// Preserve RGB values of fully transparent pixels (not recommended). By default irrelevant color of transparent pixels is cleared to avoid wasting space.
/// </summary>
public bool? DirtyAlpha { get; set; }
/// <summary>
/// Encode using RGB instead of YCbCr color space. Makes colors closer to lossless, but makes files larger. Use only if you need to avoid even smallest color shifts.
/// </summary>
public bool? ColorRgb { get; set; }
/// <summary>
/// Generate output message
/// </summary>
public bool EmitMesage { get; set; }
}
}