实现图像合并功能
This commit is contained in:
parent
21232e48ef
commit
9f4ff27079
@ -1,6 +1,7 @@
|
|||||||
using ImageMagick;
|
using ImageMagick;
|
||||||
using NLua;
|
using NLua;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Xml.Linq;
|
||||||
namespace ArtemisFgTools
|
namespace ArtemisFgTools
|
||||||
{
|
{
|
||||||
internal class Program
|
internal class Program
|
||||||
@ -15,14 +16,40 @@ namespace ArtemisFgTools
|
|||||||
}
|
}
|
||||||
static void Main()
|
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<object, object>? dictionary = ParseLuaTable(luaFilePath);
|
Dictionary<object, object>? dictionary = ParseLuaTable(luaFilePath);
|
||||||
|
|
||||||
if (dictionary != null)
|
if (dictionary != null)
|
||||||
{
|
{
|
||||||
if (dictionary["fg"] is Dictionary<object, object> fgDictionary)
|
if (dictionary["fg"] is Dictionary<object, object> fgDictionary)
|
||||||
{
|
{
|
||||||
var size = fgDictionary["size"] as List<object>;
|
if (fgDictionary["size"] is not List<object> size || size.Count == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("size not found or empty");
|
||||||
|
}
|
||||||
fgDictionary.Remove("size");
|
fgDictionary.Remove("size");
|
||||||
|
|
||||||
//convert to FgObject
|
//convert to FgObject
|
||||||
@ -40,13 +67,73 @@ namespace ArtemisFgTools
|
|||||||
Console.WriteLine("fg object has null value");
|
Console.WriteLine("fg object has null value");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
path = path[4..]; // remove :fg/../
|
||||||
fgObjects.Add(new FgObject(path, head, fuku, pose, face));
|
fgObjects.Add(new FgObject(path, head, fuku, pose, face));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Console.WriteLine($"fg count: {fgObjects.Count}");
|
foreach (var fgObject in fgObjects)
|
||||||
//Todo: Combine fgObjects with image position
|
{
|
||||||
List<int> comment = ReadPngComment("G:/x221.local/fg/baa/fa/a0001.png");
|
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];
|
||||||
|
}
|
||||||
|
// <head><siz><pose[0]><fuku><pose[1]>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
|
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<int> comment1 = ReadPngComment(firstImage.Comment); //base
|
||||||
|
using MagickImage secondImage = new(layerImg);
|
||||||
|
List<int> 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<int> 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<object, object>? ParseLuaTable(string luaFilePath)
|
static Dictionary<object, object>? ParseLuaTable(string luaFilePath)
|
||||||
{
|
{
|
||||||
Lua lua = new();
|
Lua lua = new();
|
||||||
@ -164,42 +280,30 @@ namespace ArtemisFgTools
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<int> ReadPngComment(string filePath)
|
public static List<int> ReadPngComment(string? comment)
|
||||||
{
|
{
|
||||||
if (File.Exists(filePath))
|
if (comment != null)
|
||||||
{
|
{
|
||||||
// Read image from file
|
string pattern = @"^pos,(\d+),(\d+),(\d+),(\d+)$";
|
||||||
using var image = new MagickImage(filePath);
|
Match match = Regex.Match(comment, pattern);
|
||||||
|
if (match.Success)
|
||||||
if (image.Comment != null)
|
|
||||||
{
|
{
|
||||||
string pattern = @"^pos,(\d+),(\d+),(\d+),(\d+)$";
|
int x = int.Parse(match.Groups[1].Value);
|
||||||
Match match = Regex.Match(image.Comment, pattern);
|
int y = int.Parse(match.Groups[2].Value);
|
||||||
if (match.Success)
|
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];
|
return [x, y, w, h];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Unexpected result");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception("Comment not found");
|
throw new Exception("Unexpected result");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception("File does not exist.");
|
throw new Exception("Comment not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user