沒找到c#版本的,於是打算自己寫一下
參考鏈接來源:https://blog.csdn.net/w88219003/article/details/41909421
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
namespace ConsoleApp11
{
/// <summary>
///
/// </summary>
public struct Vector2Int
{
public int X { get; set; }
public int Y { get; set; }
public override bool Equals(object obj)
{
if(!(obj is Vector2Int other))
{
return false;
}
return other.X == X && other.Y == Y;
}
public override int GetHashCode()
{
return X.GetHashCode() + Y.GetHashCode();
}
public static bool operator ==(Vector2Int left, Vector2Int right)
{
return left.Equals(right);
}
public static bool operator !=(Vector2Int left, Vector2Int right)
{
return !(left == right);
}
public override string ToString()
{
return $"({X},{Y})";
}
}
/// <summary>
///
/// </summary>
public class PNGData
{
private string[] name = Array.Empty<string>();
/// <summary>
/// 名字
/// </summary>
public string[] GetName()
{
return name;
}
/// <summary>
/// 名字
/// </summary>
public void SetName(string[] value)
{
name = value;
}
/// <summary>
/// 旋轉
/// </summary>
public bool Rotate { get; set; }
/// <summary>
/// 座標
/// </summary>
public Vector2Int Position { get; set; }
/// <summary>
/// 大小
/// </summary>
public Vector2Int Size { get; set; }
/// <summary>
/// ...
/// </summary>
public Vector2Int Orig { get; set; }
/// <summary>
/// 偏移
/// </summary>
public Vector2Int Offset { get; set; }
/// <summary>
/// 索引
/// </summary>
public int Index { get; set; }
public override string ToString()
{
return $"{GetName()},Position{Position},Size{Size}";
}
public string GetAndCreateFullPath(string folder)
{
for(int i = 0; i < name.Length; ++i)
{
string n = name[i];
if (i == name.Length - 1)
{
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
}
folder += n;
if (i == name.Length - 1)
{
folder += ".png";
}
else
{
folder += "\\";
}
}
return folder;
}
}
/// <summary>
///
/// </summary>
public class AtlasFileData
{
/// <summary>
/// 文件名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 文件夾
/// </summary>
public string Folder { get; set; }
/// <summary>
/// 文件大小
/// </summary>
public Vector2Int Size { get; set; }
/// <summary>
/// 文件格式
/// </summary>
public string Format { get; set; }
/// <summary>
/// 文件格式
/// </summary>
public string Filter { get; set; }
/// <summary>
///
/// </summary>
public string Repeat { get; set; }
/// <summary>
///
/// </summary>
public List<PNGData> PNG { get; } = new List<PNGData>();
}
/// <summary>
/// 解析圖集
/// </summary>
public static class AtlasParser
{
/// <summary>
/// 指定atlas文件的全路徑然後加載,加載出來的圖片默認在當前文件夾下的子文件夾中
/// </summary>
/// <param name="inputPath">atlas文件的全路徑</param>
public static bool Load(string inputPath)
{
if (string.IsNullOrEmpty(inputPath))
{
return false;
}
if (!inputPath.EndsWith(".atlas"))
{
return false;
}
inputPath = inputPath.Replace('/', '\\');
string folder = inputPath.Substring(0, inputPath.LastIndexOf('\\') + 1);
//debug
Console.WriteLine($"圖集路徑:{inputPath}");
List<AtlasFileData> atlases = new List<AtlasFileData>();
using (var fs = new FileStream(inputPath, FileMode.Open, FileAccess.Read))
{
using (var reader = new StreamReader(fs, Encoding.UTF8))
{
//跳過下一行
bool skipNext = false;
while (!reader.EndOfStream)
{
var curAtlas = Parse(new AtlasFileData(), reader, ref skipNext);
if (curAtlas != null)
{
curAtlas.Folder = folder;
atlases.Add(curAtlas);
}
}
}
}
//debug
Console.WriteLine($"解析完畢,數量:{atlases.Count}");
foreach (var atlas in atlases)
{
Split(atlas);
}
return true;
}
private static void Split(AtlasFileData fileData)
{
string fullSourcePath = $"{fileData.Folder}{fileData.Name}";
if (!File.Exists(fullSourcePath))
{
Console.WriteLine($"路徑不存在:{fullSourcePath}");
return;
}
string folderName = fileData.Name.Substring(0, fileData.Name.LastIndexOf('.'));
string folderPath = $"{fileData.Folder}{folderName}\\";
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
//debug
Console.WriteLine();
Console.WriteLine($"開始分割圖片至文件夾:{folderPath}");
Bitmap source = new Bitmap(fullSourcePath);
foreach(var png in fileData.PNG)
{
var nameDepth = png.GetName();
if(nameDepth.Length == 0)
{
//debug
Console.WriteLine($"png圖片的名字不能爲空");
continue;
}
int x, y, z, w = 0;
if (png.Rotate)
{
x = png.Position.X;
y = png.Position.Y;
z = x + png.Size.Y;
w = y + png.Size.X;
}
else
{
x = png.Position.X;
y = png.Position.Y;
z = x + png.Size.X;
w = y + png.Size.Y;
}
int width = z - x;
int height = w - y;
Bitmap b = new Bitmap(width, height);
try
{
using (Graphics g = Graphics.FromImage(b))
{
//清空畫布並以透明背景色填充
g.Clear(Color.Transparent);
//在指定位置並且按指定大小繪製原圖片的指定部分
g.DrawImage(source, new Rectangle(0, 0, width, height), x, y, width, height, GraphicsUnit.Pixel);
//
if (png.Rotate)
{
b.RotateFlip(RotateFlipType.Rotate270FlipNone);
}
else
{
b.RotateFlip(RotateFlipType.RotateNoneFlipNone);
}
string fullPNGPath = png.GetAndCreateFullPath(folderPath);
b.Save(fullPNGPath, System.Drawing.Imaging.ImageFormat.Png);
//debug
Console.WriteLine($"圖片已保存至:{fullPNGPath}");
}
}
catch (Exception e)
{
throw e;
}
finally
{
b.Dispose();
}
}
source.Dispose();
}
private static bool ReadFileName(AtlasFileData fileData, StreamReader reader)
{
if (reader.EndOfStream)
{
return false;
}
string line = reader.ReadLine();
fileData.Name = line;
return true;
}
private static bool ReadFileSize(AtlasFileData fileData, StreamReader reader)
{
if (reader.EndOfStream)
{
return false;
}
string line = reader.ReadLine();
if (!line.StartsWith("size:"))
{
return false;
}
line = line.Substring(5);
var coll = line.Split(',');
if(coll.Length != 2)
{
return false;
}
fileData.Size = new Vector2Int()
{
X = Convert.ToInt32(coll[0]),
Y = Convert.ToInt32(coll[1])
};
return true;
}
private static bool ReadFileFormat(AtlasFileData fileData, StreamReader reader)
{
if (reader.EndOfStream)
{
return false;
}
string line = reader.ReadLine();
if (!line.StartsWith("format:"))
{
return false;
}
line = line.Substring(7);
fileData.Format = line;
return true;
}
private static bool ReadFileFilter(AtlasFileData fileData, StreamReader reader)
{
if (reader.EndOfStream)
{
return false;
}
string line = reader.ReadLine();
if (!line.StartsWith("filter:"))
{
return false;
}
line = line.Substring(7);
fileData.Filter = line;
return true;
}
private static bool ReadFileRepeatMode(AtlasFileData fileData, StreamReader reader)
{
if (reader.EndOfStream)
{
return false;
}
string line = reader.ReadLine();
if (!line.StartsWith("repeat:"))
{
return false;
}
line = line.Substring(7);
fileData.Repeat = line;
return true;
}
private static AtlasFileData Parse(AtlasFileData fileData, StreamReader reader,ref bool skipNext)
{
if (!skipNext)
{
reader.ReadLine();
}
//讀取文件名
if (!ReadFileName(fileData, reader))
{
return null;
}
//讀取大小
if (!ReadFileSize(fileData, reader))
{
return null;
}
//讀取格式
if (!ReadFileFormat(fileData, reader))
{
return null;
}
//讀取格式
if (!ReadFileFilter(fileData, reader))
{
return null;
}
//讀取
if (!ReadFileRepeatMode(fileData, reader))
{
return null;
}
//開始讀取圖集數據
while (!reader.EndOfStream)
{
//讀取png名字
var pngData = ReadPNGData(reader, ref skipNext);
if(pngData == null)
{
return fileData;
}
fileData.PNG.Add(pngData);
}
return fileData;
}
private static bool ParsePNGName(PNGData pngData,string line)
{
var name = line.Split('/');
pngData.SetName(name);
return true;
}
private static bool ParsePNGRotate(PNGData pngData,string line)
{
line = line.Trim(' ');
var coll = line.Split(':');
if (coll.Length != 2)
{
return false;
}
if(coll[0]!= "rotate")
{
return false;
}
pngData.Rotate = Convert.ToBoolean(coll[1]);
return true;
}
private static bool ParsePNGXY(PNGData pngData, string line)
{
line = line.Trim(' ');
var coll = line.Split(':');
if (coll.Length != 2)
{
return false;
}
if (coll[0] != "xy")
{
return false;
}
coll = coll[1].Split(',');
pngData.Position = new Vector2Int()
{
X = Convert.ToInt32(coll[0]),
Y = Convert.ToInt32(coll[1])
};
return true;
}
private static bool ParsePNGSize(PNGData pngData, string line)
{
line = line.Trim(' ');
var coll = line.Split(':');
if (coll.Length != 2)
{
return false;
}
if (coll[0] != "size")
{
return false;
}
coll = coll[1].Split(',');
pngData.Size = new Vector2Int()
{
X = Convert.ToInt32(coll[0]),
Y = Convert.ToInt32(coll[1])
};
return true;
}
private static bool ParsePNGOrig(PNGData pngData, string line)
{
line = line.Trim(' ');
var coll = line.Split(':');
if (coll.Length != 2)
{
return false;
}
if (coll[0] != "orig")
{
return false;
}
coll = coll[1].Split(',');
pngData.Orig = new Vector2Int()
{
X = Convert.ToInt32(coll[0]),
Y = Convert.ToInt32(coll[1])
};
return true;
}
private static bool ParsePNGOffset(PNGData pngData, string line)
{
line = line.Trim(' ');
var coll = line.Split(':');
if (coll.Length != 2)
{
return false;
}
if (coll[0] != "offset")
{
return false;
}
coll = coll[1].Split(',');
pngData.Offset = new Vector2Int()
{
X = Convert.ToInt32(coll[0]),
Y = Convert.ToInt32(coll[1])
};
return true;
}
private static bool ParsePNGIndex(PNGData pngData, string line)
{
line = line.Trim(' ');
var coll = line.Split(':');
if (coll.Length != 2)
{
return false;
}
if (coll[0] != "index")
{
return false;
}
pngData.Index = Convert.ToInt32(coll[1]);
return true;
}
private static PNGData ReadPNGData(StreamReader reader, ref bool skipNext)
{
string line = reader.ReadLine();
//讀取到空行
if (string.IsNullOrEmpty(line))
{
skipNext = true;
return null;
}
PNGData pngData = new PNGData();
//讀取名字
if (!ParsePNGName(pngData, line))
{
return null;
}
//讀取rotate
line = reader.ReadLine();
if (!ParsePNGRotate(pngData, line))
{
return null;
}
//讀取xy
line = reader.ReadLine();
if (!ParsePNGXY(pngData, line))
{
return null;
}
//讀取size
line = reader.ReadLine();
if (!ParsePNGSize(pngData, line))
{
return null;
}
//讀取orig
line = reader.ReadLine();
if (!ParsePNGOrig(pngData, line))
{
return null;
}
//讀取offset
line = reader.ReadLine();
if (!ParsePNGOffset(pngData, line))
{
return null;
}
//讀取index
line = reader.ReadLine();
if (!ParsePNGIndex(pngData, line))
{
return null;
}
return pngData;
}
}
}
測試
using System;
using System.IO;
using System.Threading.Tasks;
namespace ConsoleApp11
{
class Program
{
static bool isloading = false;
static void Main(string[] args)
{
while (true)
{
if (isloading)
{
continue;
}
Console.WriteLine("1.Q鍵退出 2.空格鍵執行解析");
ConsoleKeyInfo key = Console.ReadKey();
if(key.Key == ConsoleKey.Q)
{
//退出
Console.WriteLine("退出程序");
break;
}
else if(key.Key == ConsoleKey.Spacebar)
{
Console.WriteLine("請輸入atlas文件全路徑");
string line = Console.ReadLine();
if(string.IsNullOrEmpty(line) || !File.Exists(line))
{
Console.WriteLine("路徑不存在");
}
else
{
Load(line);
}
}
}
Console.ReadKey();
}
static async void Load(string path)
{
isloading = true;
var result = await Task.Run(() => {
return AtlasParser.Load(path);
});
isloading = false;
Console.WriteLine();
if(result)
{
Console.WriteLine($"執行完畢!結果:成功...");
}
else
{
Console.WriteLine($"執行完畢!結果:失敗...");
}
}
}
}