From 9f4ff27079a310621161a6a8fd4382337e1542f9 Mon Sep 17 00:00:00 2001 From: Chenx221 Date: Sun, 28 Jul 2024 16:37:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=9B=BE=E5=83=8F=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ArtemisFgTools/Program.cs | 162 +++++++++++++++++++++++++++++++------- 1 file changed, 133 insertions(+), 29 deletions(-) diff --git a/ArtemisFgTools/Program.cs b/ArtemisFgTools/Program.cs index 22ae688..0375b9c 100644 --- a/ArtemisFgTools/Program.cs +++ b/ArtemisFgTools/Program.cs @@ -1,6 +1,7 @@ using ImageMagick; using NLua; using System.Text.RegularExpressions; +using System.Xml.Linq; namespace ArtemisFgTools { internal class Program @@ -15,14 +16,40 @@ namespace ArtemisFgTools } static void Main() { - string luaFilePath = "G:/x221.local/pc/ja/extra/exlist.ipt"; + Console.WriteLine("请输入立绘fg文件夹的所在路径(无需\"\"):"); + string? fgImagePath = Console.ReadLine(); + + Console.WriteLine("请输入exlist.ipt的文件路径:"); + string? luaFilePath = Console.ReadLine(); + + Console.WriteLine("请输入保存位置:"); + string? savePath = Console.ReadLine(); + + if (string.IsNullOrEmpty(fgImagePath) || string.IsNullOrEmpty(luaFilePath) || string.IsNullOrEmpty(savePath)) + { + Console.WriteLine("路径不能为空"); + return; + } + if (!Directory.Exists(fgImagePath) || !File.Exists(luaFilePath)) + { + Console.WriteLine("路径不存在"); + return; + } + if (!Directory.Exists(savePath)) + { + Directory.CreateDirectory(savePath); + } + Dictionary? dictionary = ParseLuaTable(luaFilePath); if (dictionary != null) { if (dictionary["fg"] is Dictionary fgDictionary) { - var size = fgDictionary["size"] as List; + if (fgDictionary["size"] is not List size || size.Count == 0) + { + throw new Exception("size not found or empty"); + } fgDictionary.Remove("size"); //convert to FgObject @@ -40,13 +67,73 @@ namespace ArtemisFgTools Console.WriteLine("fg object has null value"); continue; } + path = path[4..]; // remove :fg/../ fgObjects.Add(new FgObject(path, head, fuku, pose, face)); } } - Console.WriteLine($"fg count: {fgObjects.Count}"); - //Todo: Combine fgObjects with image position - List comment = ReadPngComment("G:/x221.local/fg/baa/fa/a0001.png"); + foreach (var fgObject in fgObjects) + { + foreach (var siz in size) + { + if (siz != null && fgObject.Path != null) + { + string savePathWithSizePart = Path.Combine(savePath, fgObject.Path, siz.ToString() ?? string.Empty); + string pathWithSize = Path.Combine(fgImagePath, fgObject.Path, siz.ToString() ?? string.Empty); + foreach (var pose in fgObject.Pose) + { + foreach (var fuku in fgObject.Fuku) + { + bool special = false; + string fuku_current = fuku; + //if the tail of fuku is |0099, spec to true & remove |0099 + if (fuku.EndsWith("|0099")) + { + special = true; + fuku_current = fuku[0..^5]; + } + // 0 + // *sp:fuku: 02 | 0099→02fuku & 0099face + string baseImg = Path.Combine(pathWithSize, $"{fgObject.Head}{siz}{pose[0]}{fuku_current}{pose[1]}0.png"); + foreach (var face in fgObject.Face[pose[0]]) + { + string layerImg = Path.Combine(pathWithSize, $"{face}.png"); + string layer2Img = special ? Path.Combine(pathWithSize, $"{pose[0]}0099.png") : ""; //眼镜 + string savePathWithAll = Path.Combine(savePathWithSizePart, $"{fgObject.Head}{siz}{pose[0]}{fuku_current}{pose[1]}0_{face}" + (special ? ($"_{pose[0]}0099.png") : (".png"))); + ProcessAndSave(baseImg, layerImg, layer2Img, savePathWithAll, special); + } + } + } + } + } + string siz2 = "fa"; //别急着换下一个,还有个fa //这里的代码和上面那块一样 + if (fgObject.Path != null) + { + string savePathWithSizePart = Path.Combine(savePath, fgObject.Path, siz2.ToString() ?? string.Empty); + string pathWithSize = Path.Combine(fgImagePath, fgObject.Path, siz2.ToString() ?? string.Empty); + foreach (var pose in fgObject.Pose) + { + foreach (var fuku in fgObject.Fuku) + { + bool special = false; + string fuku_current = fuku; + if (fuku.EndsWith("|0099")) + { + special = true; + fuku_current = fuku[0..^5]; + } + string baseImg = Path.Combine(pathWithSize, $"{fgObject.Head}no{pose[0]}{fuku_current}{pose[1]}0.png"); + foreach (var face in fgObject.Face[pose[0]]) + { + string layerImg = Path.Combine(pathWithSize, $"{face}.png"); + string layer2Img = special ? Path.Combine(pathWithSize, $"{pose[0]}0099.png") : ""; + string savePathWithAll = Path.Combine(savePathWithSizePart, $"{fgObject.Head}no{pose[0]}{fuku_current}{pose[1]}0_{face}" + (special ? ($"_{pose[0]}0099.png") : (".png"))); + ProcessAndSave(baseImg, layerImg, layer2Img, savePathWithAll, special); + } + } + } + } + } } else { @@ -55,6 +142,35 @@ namespace ArtemisFgTools } } + private static void ProcessAndSave(string baseImg, string layerImg, string layer2Img, string target, bool special) + { + string? directory = Path.GetDirectoryName(target); + if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + using MagickImage firstImage = new(baseImg); + List comment1 = ReadPngComment(firstImage.Comment); //base + using MagickImage secondImage = new(layerImg); + List comment2 = ReadPngComment(secondImage.Comment); //face + int x = comment2[0] - comment1[0]; // face x - base x + int y = comment2[1] - comment1[1]; // face y - base y + firstImage.Composite(secondImage, x, y, CompositeOperator.Over); + if (special) + { + using MagickImage thirdImage = new(layer2Img); + List comment3 = ReadPngComment(thirdImage.Comment); //face + x = comment3[0] - comment1[0]; // face x - base x + y = comment3[1] - comment1[1]; // face y - base y + firstImage.Composite(thirdImage, x, y, CompositeOperator.Over); + } + //确保target所处位置文件夹是存在的,不存在则创建 + + firstImage.Write(target); + Console.WriteLine($"{Path.GetFileName(target)}图像合并完成!"); + } + static Dictionary? ParseLuaTable(string luaFilePath) { Lua lua = new(); @@ -164,42 +280,30 @@ namespace ArtemisFgTools return result; } - public static List ReadPngComment(string filePath) + public static List ReadPngComment(string? comment) { - if (File.Exists(filePath)) + if (comment != null) { - // Read image from file - using var image = new MagickImage(filePath); - - if (image.Comment != null) + string pattern = @"^pos,(\d+),(\d+),(\d+),(\d+)$"; + Match match = Regex.Match(comment, pattern); + if (match.Success) { - string pattern = @"^pos,(\d+),(\d+),(\d+),(\d+)$"; - Match match = Regex.Match(image.Comment, pattern); - if (match.Success) - { - int x = int.Parse(match.Groups[1].Value); - int y = int.Parse(match.Groups[2].Value); - int w = int.Parse(match.Groups[3].Value); - int h = int.Parse(match.Groups[4].Value); + int x = int.Parse(match.Groups[1].Value); + int y = int.Parse(match.Groups[2].Value); + int w = int.Parse(match.Groups[3].Value); + int h = int.Parse(match.Groups[4].Value); - return [x, y, w, h]; - } - else - { - throw new Exception("Unexpected result"); - } + return [x, y, w, h]; } else { - throw new Exception("Comment not found"); + throw new Exception("Unexpected result"); } } else { - throw new Exception("File does not exist."); + throw new Exception("Comment not found"); } } - - } }