using Livia.Properties; using System.IO; using System.IO.Compression; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace Livia.Utility; public static class LiviaUtility { public static void CreateFromDirectory(string fromPath, string outputFileName, CancellationToken token) { using FileStream zipToOpen = new(outputFileName, FileMode.Create); using ZipArchive archive = new(zipToOpen, ZipArchiveMode.Create); RecursiveAddToZip(fromPath, fromPath, archive, token); } private static void RecursiveAddToZip(string root, string folder, ZipArchive zipArchive, CancellationToken token) { DirectoryInfo directoryInfo = new(folder); foreach (FileInfo fileInfo in directoryInfo.GetFiles()) { if (token.IsCancellationRequested) { return; } string relativePath = Path.GetRelativePath(root, fileInfo.FullName); zipArchive.CreateEntryFromFile(fileInfo.FullName, relativePath); } foreach (DirectoryInfo directory in directoryInfo.GetDirectories()) { if (token.IsCancellationRequested) { return; } RecursiveAddToZip(root, directory.FullName, zipArchive, token); } } public static Dictionary ParseArgs(string[] args) { Dictionary result = new(); for (int i = 0; i < args.Length; i++) { string arg = args[i]; //First item in list is not argument if (!arg.StartsWith('-')) continue; arg = Regex.Replace(arg, "^-{1,2}", ""); if (result.ContainsKey(arg)) throw new ArgumentException(arg); //forward to next arg string argValue = string.Empty; for (int j = i + 1; j < args.Length; j++) { if (args[i + 1].StartsWith("-")) { break; } if (!string.IsNullOrEmpty(argValue)) argValue += " "; argValue += args[j]; i++; } result.Add(arg, argValue); } return result; } public static IEnumerable ReadFilesFromDir(string dir) { string[] files = Directory.GetFiles(dir); Array.Sort(files); return files; } public static async Task LoadBitmapAsync(string file) { await using FileStream fileStream = new(file, FileMode.Open, FileAccess.Read); await using MemoryStream memoryStream = new(); await fileStream.CopyToAsync(memoryStream); memoryStream.Position = 0; BitmapImage image = new(); image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.DecodePixelWidth = 1024; image.StreamSource = memoryStream; image.EndInit(); image.Freeze(); return image; } public static BitmapSource CreateTransparency(BitmapSource source, bool showBoundary) { FormatConvertedBitmap rgbaBitmap = new(); rgbaBitmap.BeginInit(); rgbaBitmap.Source = source; rgbaBitmap.DestinationFormat = PixelFormats.Bgra32; rgbaBitmap.EndInit(); rgbaBitmap.Freeze(); int bytesPerPixel = (rgbaBitmap.Format.BitsPerPixel + 7) / 8; int stride = bytesPerPixel * rgbaBitmap.PixelWidth; byte[] buffer = new byte[stride * rgbaBitmap.PixelHeight]; rgbaBitmap.CopyPixels(buffer, stride, 0); for (int y = 0; y < rgbaBitmap.PixelHeight; y++) { for (int x = 0; x < rgbaBitmap.PixelWidth; x++) { int i = stride * y + bytesPerPixel * x; byte b = buffer[i]; byte g = buffer[i + 1]; byte r = buffer[i + 2]; if (b + g + r == 0) { buffer[i + 3] = 0; // set transparent continue; } if (showBoundary) { bool isBoundary = false; //check all neighboring pixels for (int dx = -1; dx < 2; dx++) { for (int dy = -1; dy < 2; dy++) { if (dx == 0 && dy == 0) continue; if (!PixelIsEmpty(buffer, stride, bytesPerPixel, x + dx, y + dy, rgbaBitmap.PixelHeight, rgbaBitmap.PixelWidth)) continue; isBoundary = true; break; } if (isBoundary) break; } buffer[i + 3] = (byte)(isBoundary ? 200 : 128); } else { buffer[i + 3] = 128; } } } BitmapSource result = BitmapSource.Create(rgbaBitmap.PixelWidth, rgbaBitmap.PixelHeight, rgbaBitmap.DpiX, rgbaBitmap.DpiY, rgbaBitmap.Format, null, buffer, stride); result.Freeze(); return result; } private static bool PixelIsEmpty(IReadOnlyList buffer, int stride, int bytesPerPixel, int x, int y, int pixelHeight, int pixelWidth) { if (x < 0 || x >= pixelWidth) return true; if (y < 0 || y >= pixelHeight) return true; int i = stride * y + bytesPerPixel * x; byte b = buffer[i]; byte g = buffer[i + 1]; byte r = buffer[i + 2]; return b + g + r == 0; } public static string ParseServerString(string input) { string result = input; foreach (Match match in Regex.Matches(input, "{{[^{}]+}}")) { string key = match.Value[2..^2]; object dictValue = Application.Current.TryFindResource($"ServerString##{key}"); if (dictValue is string str) { result = result.Replace(match.Value, str); } } return result; } public static string GetLanguageOnlyString(string? language = null) { language ??= Settings.Default.Language; string[] splits = language.Split("-"); return splits.Length == 0 ? "zh" : splits[0]; } }