mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Add icon startup banner
This commit is contained in:
commit
354a498f21
9 changed files with 2555 additions and 2299 deletions
|
|
@ -228,9 +228,26 @@ namespace MinecraftClient
|
|||
/// <returns>True if startup can continue; false if config load failed and user chose to exit.</returns>
|
||||
internal static bool ProcessStartupState(StartupState state)
|
||||
{
|
||||
ConsoleIO.WriteLine($"Minecraft Console Client v{Version} - for MC {MCLowestVersion} to {MCHighestVersion} - Github.com/MCCTeam");
|
||||
if (BuildInfo is not null)
|
||||
ConsoleIO.WriteLineFormatted("§8" + BuildInfo);
|
||||
if (Config.Console.General.Display_Icon_Banner && ConsoleIO.Backend is Tui.TuiConsoleBackend tuiBanner)
|
||||
{
|
||||
var view = tuiBanner.GetView();
|
||||
if (view is not null)
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
var panel = Tui.MccBannerPanelBuilder.Build(BuildInfo);
|
||||
view.AppendControlToLog(panel);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowClassicBanner();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowClassicBanner();
|
||||
}
|
||||
|
||||
var cfg = state.ConfigResult;
|
||||
|
||||
|
|
@ -271,6 +288,13 @@ namespace MinecraftClient
|
|||
return true;
|
||||
}
|
||||
|
||||
private static void ShowClassicBanner()
|
||||
{
|
||||
ConsoleIO.WriteLine(string.Format(Translations.mcc_banner_classic, Version, MCLowestVersion, MCHighestVersion, "Github.com/MCCTeam"));
|
||||
if (BuildInfo is not null)
|
||||
ConsoleIO.WriteLineFormatted("§8" + BuildInfo);
|
||||
}
|
||||
|
||||
private static void MaybePrintClassicModeTuiRecommendation()
|
||||
{
|
||||
if (ConsoleIO.BasicIO
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -566,6 +566,9 @@ Custom colors are only available when using "vt100_24bit" color mode.</value>
|
|||
<data name="Console.General.ConsoleColorMode" xml:space="preserve">
|
||||
<value>Use "disable", "legacy_4bit", "vt100_4bit", "vt100_8bit" or "vt100_24bit". If a garbled code like "←[0m" appears on the terminal, you can try switching to "legacy_4bit" mode, or just disable it.</value>
|
||||
</data>
|
||||
<data name="Console.General.Display_Icon_Banner" xml:space="preserve">
|
||||
<value>Whether to display the MCC startup icon banner.</value>
|
||||
</data>
|
||||
<data name="Console.General.Display_Input" xml:space="preserve">
|
||||
<value>You can use "Ctrl+P" to print out the current input and cursor position.</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -2269,6 +2269,18 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
internal static string mcc_banner_classic {
|
||||
get {
|
||||
return ResourceManager.GetString("mcc.banner.classic", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string mcc_banner_label_mc_versions {
|
||||
get {
|
||||
return ResourceManager.GetString("mcc.banner.label_mc_versions", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string mcc_server_info_label_server {
|
||||
get {
|
||||
return ResourceManager.GetString("mcc.server_info.label_server", resourceCulture);
|
||||
|
|
|
|||
|
|
@ -830,6 +830,12 @@ Add the ID of this chat to "Authorized_Chat_Ids" field in the configuration file
|
|||
<data name="botname.TestBot" xml:space="preserve">
|
||||
<value>TestBot</value>
|
||||
</data>
|
||||
<data name="mcc.banner.classic" xml:space="preserve">
|
||||
<value>Minecraft Console Client v{0} - for MC {1} to {2} - {3}</value>
|
||||
</data>
|
||||
<data name="mcc.banner.label_mc_versions" xml:space="preserve">
|
||||
<value>Supported MC Versions:</value>
|
||||
</data>
|
||||
<data name="mcc.server_info.label_server" xml:space="preserve">
|
||||
<value>Server:</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -1210,6 +1210,9 @@ namespace MinecraftClient
|
|||
[TomlInlineComment("$Console.General.ConsoleColorMode$")]
|
||||
public ConsoleColorModeType ConsoleColorMode = ConsoleColorModeType.vt100_24bit;
|
||||
|
||||
[TomlInlineComment("$Console.General.Display_Icon_Banner$")]
|
||||
public bool Display_Icon_Banner = true;
|
||||
|
||||
[TomlInlineComment("$Console.General.Display_Input$")]
|
||||
public bool Display_Input = true;
|
||||
|
||||
|
|
|
|||
125
MinecraftClient/Tui/IconGridBuilder.cs
Normal file
125
MinecraftClient/Tui/IconGridBuilder.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace MinecraftClient.Tui
|
||||
{
|
||||
internal static class IconGridBuilder
|
||||
{
|
||||
internal static Grid BuildFromRgba(byte[] rgba, int srcWidth, int srcHeight, int displaySize)
|
||||
{
|
||||
int cellCols = displaySize;
|
||||
int cellRows = displaySize / 2;
|
||||
|
||||
var grid = new Grid();
|
||||
for (int c = 0; c < cellCols; c++)
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Auto));
|
||||
for (int r = 0; r < cellRows; r++)
|
||||
grid.RowDefinitions.Add(new RowDefinition(1, GridUnitType.Auto));
|
||||
|
||||
for (int row = 0; row < cellRows; row++)
|
||||
{
|
||||
for (int col = 0; col < cellCols; col++)
|
||||
{
|
||||
int topPixelY = row * 2;
|
||||
int bottomPixelY = row * 2 + 1;
|
||||
|
||||
var topColor = SamplePixel(rgba, srcWidth, srcHeight, col, topPixelY, cellCols, displaySize);
|
||||
var bottomColor = SamplePixel(rgba, srcWidth, srcHeight, col, bottomPixelY, cellCols, displaySize);
|
||||
|
||||
var cell = new TextBlock
|
||||
{
|
||||
Text = "\u2580",
|
||||
Foreground = new SolidColorBrush(topColor),
|
||||
Background = new SolidColorBrush(bottomColor),
|
||||
Padding = new Thickness(0),
|
||||
Margin = new Thickness(0),
|
||||
};
|
||||
|
||||
Grid.SetRow(cell, row);
|
||||
Grid.SetColumn(cell, col);
|
||||
grid.Children.Add(cell);
|
||||
}
|
||||
}
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
internal static Grid BuildFromBase64(string base64Data, int displaySize)
|
||||
{
|
||||
byte[] imageBytes;
|
||||
try
|
||||
{
|
||||
imageBytes = Convert.FromBase64String(base64Data);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Grid();
|
||||
}
|
||||
|
||||
return BuildFromImageBytes(imageBytes, displaySize) ?? new Grid();
|
||||
}
|
||||
|
||||
internal static Grid? BuildFromImageBytes(byte[] imageBytes, int displaySize)
|
||||
{
|
||||
int srcWidth, srcHeight;
|
||||
byte[] rgba;
|
||||
try
|
||||
{
|
||||
(srcWidth, srcHeight, rgba) = DecodeImageToRgba(imageBytes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return BuildFromRgba(rgba, srcWidth, srcHeight, displaySize);
|
||||
}
|
||||
|
||||
internal static (int Width, int Height, byte[] Rgba) DecodeImageToRgba(byte[] imageData)
|
||||
{
|
||||
using var image = new ImageMagick.MagickImage(imageData);
|
||||
int w = (int)image.Width;
|
||||
int h = (int)image.Height;
|
||||
|
||||
using var pixels = image.GetPixelsUnsafe();
|
||||
var rgba = new byte[w * h * 4];
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
var pixel = pixels.GetPixel(x, y)!;
|
||||
int idx = (y * w + x) * 4;
|
||||
var color = pixel.ToColor()!;
|
||||
rgba[idx] = (byte)(color.R >> 8);
|
||||
rgba[idx + 1] = (byte)(color.G >> 8);
|
||||
rgba[idx + 2] = (byte)(color.B >> 8);
|
||||
rgba[idx + 3] = (byte)(color.A >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
return (w, h, rgba);
|
||||
}
|
||||
|
||||
private static Color SamplePixel(byte[] rgba, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH)
|
||||
{
|
||||
int srcX = dstX * srcW / dstW;
|
||||
int srcY = dstY * srcH / dstH;
|
||||
srcX = Math.Clamp(srcX, 0, srcW - 1);
|
||||
srcY = Math.Clamp(srcY, 0, srcH - 1);
|
||||
|
||||
int idx = (srcY * srcW + srcX) * 4;
|
||||
if (idx + 3 >= rgba.Length)
|
||||
return Color.FromRgb(0, 0, 0);
|
||||
|
||||
byte r = rgba[idx];
|
||||
byte g = rgba[idx + 1];
|
||||
byte b = rgba[idx + 2];
|
||||
byte a = rgba[idx + 3];
|
||||
|
||||
return a < 128 ? Color.FromRgb(0, 0, 0) : Color.FromRgb(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
178
MinecraftClient/Tui/MccBannerPanelBuilder.cs
Normal file
178
MinecraftClient/Tui/MccBannerPanelBuilder.cs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Documents;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace MinecraftClient.Tui
|
||||
{
|
||||
internal static class MccBannerPanelBuilder
|
||||
{
|
||||
internal static Border Build(string? buildInfo)
|
||||
{
|
||||
var contentPanel = new DockPanel { Background = Brushes.Black };
|
||||
|
||||
var icon = BuildIcon();
|
||||
icon.VerticalAlignment = VerticalAlignment.Center;
|
||||
DockPanel.SetDock(icon, Dock.Left);
|
||||
contentPanel.Children.Add(icon);
|
||||
|
||||
var infoPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Vertical,
|
||||
Margin = new Thickness(1, 0, 0, 0),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
|
||||
AddTitle(infoPanel);
|
||||
AddVersionRange(infoPanel);
|
||||
AddGithub(infoPanel);
|
||||
|
||||
if (buildInfo is not null)
|
||||
AddBuildInfo(infoPanel, buildInfo);
|
||||
|
||||
contentPanel.Children.Add(infoPanel);
|
||||
|
||||
return new Border
|
||||
{
|
||||
BorderBrush = new SolidColorBrush(Color.FromRgb(80, 80, 80)),
|
||||
BorderThickness = new Thickness(1),
|
||||
Background = new SolidColorBrush(Color.FromArgb(240, 20, 20, 20)),
|
||||
Padding = new Thickness(1, 0),
|
||||
Child = contentPanel,
|
||||
Margin = new Thickness(0),
|
||||
};
|
||||
}
|
||||
|
||||
private static void AddTitle(StackPanel panel)
|
||||
{
|
||||
var row = new TextBlock();
|
||||
row.Inlines!.Add(new Run("Minecraft Console Client")
|
||||
{ Foreground = Pal.Gold, FontWeight = FontWeight.Bold });
|
||||
row.Inlines.Add(new Run($" v{Program.Version}") { Foreground = Pal.Aqua });
|
||||
panel.Children.Add(row);
|
||||
}
|
||||
|
||||
private static void AddVersionRange(StackPanel panel)
|
||||
{
|
||||
var row = new TextBlock();
|
||||
row.Inlines!.Add(Lbl(Translations.mcc_banner_label_mc_versions));
|
||||
row.Inlines.Add(Val(Program.MCLowestVersion, Pal.Green));
|
||||
row.Inlines.Add(new Run(" - ") { Foreground = Pal.Gray });
|
||||
row.Inlines.Add(Val(Program.MCHighestVersion, Pal.Green));
|
||||
panel.Children.Add(row);
|
||||
}
|
||||
|
||||
private static void AddGithub(StackPanel panel)
|
||||
{
|
||||
var row = new TextBlock();
|
||||
row.Inlines!.Add(Val("Github.com/MCCTeam", Pal.Gray));
|
||||
panel.Children.Add(row);
|
||||
}
|
||||
|
||||
private static void AddBuildInfo(StackPanel panel, string buildInfo)
|
||||
{
|
||||
panel.Children.Add(new TextBlock
|
||||
{
|
||||
Text = buildInfo,
|
||||
Foreground = Pal.DarkGray,
|
||||
});
|
||||
}
|
||||
|
||||
#region Icon
|
||||
|
||||
private static readonly Color B1 = Color.FromRgb(200, 200, 200); // bezel bright
|
||||
private static readonly Color B2 = Color.FromRgb(160, 160, 160); // bezel mid
|
||||
private static readonly Color B3 = Color.FromRgb(120, 120, 120); // bezel dark
|
||||
private static readonly Color S = Color.FromRgb(20, 20, 20); // screen bg
|
||||
private static readonly Color C = Color.FromRgb(55, 200, 55); // creeper green
|
||||
|
||||
// @formatter:off
|
||||
private static readonly Color[,] Pixels =
|
||||
{
|
||||
{ B1, B1, B1, B1, B1, B1, B1, B1, B1, B1, B1, B1, B1, B1, B1, B1, B2 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, C, C, S, S, C, C, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, C, C, S, S, C, C, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, S, C, C, S, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, C, C, C, C, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, C, C, C, C, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, C, S, S, C, S, S, B3 },
|
||||
{ B1, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, B3 },
|
||||
{ B2, B3, B3, B3, B3, B3, B3, B3, B3, B3, B3, B3, B3, B3, B3, B3, B3 },
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
private static Control BuildIcon()
|
||||
{
|
||||
int cols = Pixels.GetLength(1);
|
||||
int textRows = Pixels.GetLength(0) / 2;
|
||||
|
||||
var pixelGrid = new Grid();
|
||||
for (int c = 0; c < cols; c++)
|
||||
pixelGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Auto));
|
||||
for (int r = 0; r < textRows; r++)
|
||||
pixelGrid.RowDefinitions.Add(new RowDefinition(1, GridUnitType.Auto));
|
||||
|
||||
for (int row = 0; row < textRows; row++)
|
||||
{
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
var topColor = Pixels[row * 2, col];
|
||||
var bottomColor = Pixels[row * 2 + 1, col];
|
||||
|
||||
var cell = new TextBlock
|
||||
{
|
||||
Text = "\u2580",
|
||||
Foreground = new SolidColorBrush(topColor),
|
||||
Background = new SolidColorBrush(bottomColor),
|
||||
Padding = new Thickness(0),
|
||||
Margin = new Thickness(0),
|
||||
};
|
||||
|
||||
Grid.SetRow(cell, row);
|
||||
Grid.SetColumn(cell, col);
|
||||
pixelGrid.Children.Add(cell);
|
||||
}
|
||||
}
|
||||
|
||||
var prompt = new TextBlock
|
||||
{
|
||||
Text = " >_",
|
||||
Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255)),
|
||||
Background = new SolidColorBrush(S),
|
||||
Padding = new Thickness(0),
|
||||
Margin = new Thickness(0),
|
||||
HorizontalAlignment = HorizontalAlignment.Left,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
};
|
||||
Grid.SetRow(prompt, 1);
|
||||
Grid.SetColumn(prompt, 1);
|
||||
Grid.SetColumnSpan(prompt, 4);
|
||||
pixelGrid.Children.Add(prompt);
|
||||
|
||||
return pixelGrid;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static Run Lbl(string text) =>
|
||||
new(text + " ") { Foreground = Pal.Gray };
|
||||
|
||||
private static Run Val(string text, IBrush color) =>
|
||||
new(text) { Foreground = color };
|
||||
|
||||
private static class Pal
|
||||
{
|
||||
public static readonly IBrush Gray = new SolidColorBrush(Color.FromRgb(170, 170, 170));
|
||||
public static readonly IBrush DarkGray = new SolidColorBrush(Color.FromRgb(85, 85, 85));
|
||||
public static readonly IBrush Aqua = new SolidColorBrush(Color.FromRgb(85, 255, 255));
|
||||
public static readonly IBrush Green = new SolidColorBrush(Color.FromRgb(85, 255, 85));
|
||||
public static readonly IBrush Gold = new SolidColorBrush(Color.FromRgb(255, 170, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@ namespace MinecraftClient.Tui
|
|||
{
|
||||
Orientation = Orientation.Vertical,
|
||||
Margin = new Thickness(1, 0, 0, 0),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
|
||||
AddMotd(infoPanel, info);
|
||||
|
|
@ -47,7 +48,7 @@ namespace MinecraftClient.Tui
|
|||
Background = new SolidColorBrush(Color.FromArgb(240, 20, 20, 20)),
|
||||
Padding = new Thickness(1, 0),
|
||||
Child = contentPanel,
|
||||
Margin = new Thickness(0, 1),
|
||||
Margin = new Thickness(0),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -180,114 +181,8 @@ namespace MinecraftClient.Tui
|
|||
private static Run Value(string text, IBrush color) =>
|
||||
new(text) { Foreground = color };
|
||||
|
||||
#region Favicon Rendering
|
||||
|
||||
private static Grid BuildFaviconGrid(string base64Png, int displaySize)
|
||||
{
|
||||
byte[] pngBytes;
|
||||
try
|
||||
{
|
||||
pngBytes = Convert.FromBase64String(base64Png);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Grid();
|
||||
}
|
||||
|
||||
int srcWidth, srcHeight;
|
||||
byte[] rgba;
|
||||
try
|
||||
{
|
||||
(srcWidth, srcHeight, rgba) = DecodePngToRgba(pngBytes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Grid();
|
||||
}
|
||||
|
||||
int cellCols = displaySize;
|
||||
int cellRows = displaySize / 2;
|
||||
|
||||
var grid = new Grid();
|
||||
for (int c = 0; c < cellCols; c++)
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Auto));
|
||||
for (int r = 0; r < cellRows; r++)
|
||||
grid.RowDefinitions.Add(new RowDefinition(1, GridUnitType.Auto));
|
||||
|
||||
for (int row = 0; row < cellRows; row++)
|
||||
{
|
||||
for (int col = 0; col < cellCols; col++)
|
||||
{
|
||||
int topPixelY = row * 2;
|
||||
int bottomPixelY = row * 2 + 1;
|
||||
|
||||
var topColor = SamplePixel(rgba, srcWidth, srcHeight, col, topPixelY, cellCols, displaySize);
|
||||
var bottomColor = SamplePixel(rgba, srcWidth, srcHeight, col, bottomPixelY, cellCols, displaySize);
|
||||
|
||||
var cell = new TextBlock
|
||||
{
|
||||
Text = "\u2580",
|
||||
Foreground = new SolidColorBrush(topColor),
|
||||
Background = new SolidColorBrush(bottomColor),
|
||||
Padding = new Thickness(0),
|
||||
Margin = new Thickness(0),
|
||||
};
|
||||
|
||||
Grid.SetRow(cell, row);
|
||||
Grid.SetColumn(cell, col);
|
||||
grid.Children.Add(cell);
|
||||
}
|
||||
}
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
private static Color SamplePixel(byte[] rgba, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH)
|
||||
{
|
||||
int srcX = dstX * srcW / dstW;
|
||||
int srcY = dstY * srcH / dstH;
|
||||
srcX = Math.Clamp(srcX, 0, srcW - 1);
|
||||
srcY = Math.Clamp(srcY, 0, srcH - 1);
|
||||
|
||||
int idx = (srcY * srcW + srcX) * 4;
|
||||
if (idx + 3 >= rgba.Length)
|
||||
return Color.FromRgb(0, 0, 0);
|
||||
|
||||
byte r = rgba[idx];
|
||||
byte g = rgba[idx + 1];
|
||||
byte b = rgba[idx + 2];
|
||||
byte a = rgba[idx + 3];
|
||||
|
||||
return a < 128 ? Color.FromRgb(0, 0, 0) : Color.FromRgb(r, g, b);
|
||||
}
|
||||
|
||||
private static (int Width, int Height, byte[] Rgba) DecodePngToRgba(byte[] png)
|
||||
{
|
||||
using var image = new ImageMagick.MagickImage(png);
|
||||
int w = (int)image.Width;
|
||||
int h = (int)image.Height;
|
||||
|
||||
using var pixels = image.GetPixelsUnsafe();
|
||||
var rgba = new byte[w * h * 4];
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
var pixel = pixels.GetPixel(x, y)!;
|
||||
int idx = (y * w + x) * 4;
|
||||
var color = pixel.ToColor()!;
|
||||
rgba[idx] = (byte)(color.R >> 8);
|
||||
rgba[idx + 1] = (byte)(color.G >> 8);
|
||||
rgba[idx + 2] = (byte)(color.B >> 8);
|
||||
rgba[idx + 3] = (byte)(color.A >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
return (w, h, rgba);
|
||||
}
|
||||
|
||||
#endregion
|
||||
private static Grid BuildFaviconGrid(string base64Png, int displaySize) =>
|
||||
IconGridBuilder.BuildFromBase64(base64Png, displaySize);
|
||||
|
||||
private static class McColors
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue