static void CreateThumbnail(string[] args) { // Parse args if (args.Length < 1) { Console.WriteLine( "Usage: {0} <Config-File>", Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName) ); return; } string configFile = args[0]; if (!configFile.ToLower().EndsWith(".config")) { configFile = Path.Combine("res", "Config", $"{configFile}.config"); } // Load in the requested config file var config = new Config(configFile); // Load the background image if (!config.Required("the background image", out string backgroundImage, "background")) { return; } using (var background = Helpers.LoadImage(backgroundImage.ToOS())) { // Create a surface of matching size var info = new SKImageInfo(background.Width, background.Height, Helpers.RGBA); using (var surface = SKSurface.Create(info)) { // Clear the canvas var canvas = surface.Canvas; canvas.Clear(new SKColor(0, 0, 0, 0)); // Draw the background canvas.DrawImage(background, 0.0f, 0.0f); // Determine the center-line if (!config.Required("the center line's vertical position", out string configCenterLine, "centerline")) { return; } float centerLine = configCenterLine.ParseAsDistance(info.Height); // Read padding from config if (!config.Required("the padding on left/right", out string configPaddingHorizontal, "padding", "horizontal")) { return; } float paddingHorizontal = configPaddingHorizontal.ParseAsDistance(info.Width); if (!config.Required("the padding below the logo", out string configPaddingLogoBottom, "padding", "logo.bottom")) { return; } float paddingLogoBottom = configPaddingLogoBottom.ParseAsDistance(info.Height); if (!config.Required("the padding above the text", out string configPaddingTextTop, "padding", "text.top")) { return; } float paddingTextTop = configPaddingTextTop.ParseAsDistance(info.Height); if (!config.Required("the padding on top/bottom", out string configPaddingVertical, "padding", "vertical")) { return; } float paddingVertical = configPaddingVertical.ParseAsDistance(info.Height); // Draw the game logo if (!config.Required("the game logo", out string logoImage, "logo")) { return; } if (!logoImage.ToLower().EndsWith(".png")) { logoImage = $"res/Logos/{logoImage}.png"; } using (var logo = Helpers.LoadImage(logoImage.ToOS())) { // Calculate the scale for the logo var bottomCenter = new SKPoint(info.Width * 0.5f, centerLine - paddingLogoBottom); float logoScale = Math.Min( (bottomCenter.X - paddingHorizontal) / logo.Width * 2.0f, (bottomCenter.Y - paddingVertical) / logo.Height ); // Draw the logo canvas.DrawImage(logo, new SKRect( bottomCenter.X - logoScale * logo.Width * 0.5f, bottomCenter.Y - logoScale * logo.Height, bottomCenter.X + logoScale * logo.Width * 0.5f, bottomCenter.Y )); } // Parse the font configuration if (!config.Required("if the font displays in all caps", out string configAllCaps, "text", "all.caps")) { return; } bool allCaps = configAllCaps.Equals("true", StringComparison.CurrentCultureIgnoreCase); if (!config.Required("the font", out string fontFile, "text", "font")) { return; } if (!fontFile.ToLower().EndsWith(".ttf")) { fontFile = $"res/Fonts/{fontFile}/{fontFile}.ttf"; } if (!config.Required("the maximum font size", out string configFontSize, "text", "size")) { return; } if (!configFontSize.EndsWith("px")) { Console.WriteLine("The font size must be in pixels"); return; } float fontSize = float.Parse(configFontSize.Substring(0, configFontSize.Length - 2)); // Get the video title and episode if (!config.Required("the video's episode", out string configEpisode, "video", "episode")) { return; } int episode = int.Parse(configEpisode); if (!config.Required("the video's title", out string title, "video", "title")) { return; } string content = $"#{episode} {title}"; // Draw some text at the center using (var minecrafter3 = Helpers.LoadFont(fontFile.ToOS())) { // Determine the scale for the text var paint = new SKPaint { Color = new SKColor(255, 255, 255, 255), IsAntialias = false, Style = SKPaintStyle.Fill, TextSize = fontSize, Typeface = minecrafter3 }; var topCenter = new SKPoint(info.Width * 0.5f, centerLine + paddingTextTop); var size = paint.MeasureTextExt(content, allCaps); paint.TextSize *= Math.Min(1.0f, Math.Min( (topCenter.X - paddingHorizontal) / size.Width * 2.0f, (info.Height - topCenter.Y - paddingVertical) / size.Height )); // Draw the text canvas.DrawTextExt( content, topCenter.X, topCenter.Y, paint, HAlign.Center, VAlign.Top, allCaps ); } // Diagnostic marker if (config.TryGet(out string configRenderCenter, "rendering", "center") && configRenderCenter.Equals("true", StringComparison.CurrentCultureIgnoreCase)) { canvas.DrawCircle( info.Width * 0.5f, centerLine, 25.0f, new SKPaint { Color = new SKColor(255, 0, 0, 255), IsAntialias = false, Style = SKPaintStyle.Fill } ); } // Save to a file if (!config.Required("the output directory", out string configOutputDir, "video", "output.directory")) { return; } string outputDir = Path.GetFullPath(configOutputDir.ToOS()); if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } surface.SaveToFile(Path.Combine(outputDir, $"Episode_{episode.ToString("D3")}.png")); } } }