1329343592

Hello there.
I am using Unity and Spine now.
Now I need a software tool to automatically crop the image. I need to crop the image the way I want and then import it into Unity Engine.
I found the source code of this Spine handler on the Internet, but it can only automatically crop a single Atlas file. Now I need your help. I don't understand the implementation of the program code. I need your help to change this program to a program that can automatically crop multiple atlas files. I mean keeping all the features, but I can select multiple atlas files!
Because I have thousands of folders containing Atlas files and png images.

This is the Form code of the program:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace GetPicture
{
public class Form1 : Form
{
public Picture pic;

public List<int> listWidth = new List<int>();

public List<int> listHeight = new List<int>();

public List<int> listIndex = new List<int>();

public List<bool> listRotate = new List<bool>();

public List<string> listName = new List<string>();

public List<Point> listPos = new List<Point>();

public List<Point> listOrigSize = new List<Point>();

public List<Point> listOffset = new List<Point>();

public List<Picture> listPic = new List<Picture>();

private StringBuilder sb;

public string picPathName;

public string picInfoName;

public int imageWidth;

public int imageHeight;

private Bitmap oldBmp;

private IContainer components;

private PictureBox loaded_pictures;

private Button GetPictureInfoPath;

private Button CutImage;

private TextBox picPath;

private TextBox picInfoPath;

private GroupBox groupBox1;

private GroupBox groupBox2;

private GroupBox groupBox3;

private TextBox textBox1;

public Form1()
{
InitializeComponent();
Text = "切图";
sb = new StringBuilder(textBox1.Text);
}

public void GetPictureInfoPath_Click(object sender, EventArgs e)
{
sb.Clear();
textBox1.Clear();
clear();
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Multiselect = true;
openFileDialog.Title = "请选择文件";
openFileDialog.Filter = "所有文件([i].[/i])|*.atlas";

if (openFileDialog.ShowDialog() == DialogResult.OK)
{
picInfoName = openFileDialog.FileName;
picInfoPath.Text = picInfoName;
picPath.Text = Path.GetDirectoryName(picInfoName) + "\\" + Path.GetFileNameWithoutExtension(picInfoName) + ".png";
if (!checkFileExsit(picPath.Text))
{
MessageBox.Show("
请检查本地图片文件名和描述文件文件名是否一致");
return;
}
try
{
oldBmp = (Bitmap)Image.FromFile(picPath.Text);
loaded_pictures.Image = new Bitmap(Image.FromFile(picPath.Text), loaded_pictures.Width, loaded_pictures.Height);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
string input = File.ReadAllText(openFileDialog.FileName);
Regex regex = new Regex("
(?<name>(^[^:,]+$))", RegexOptions.IgnoreCase | RegexOptions.Multiline);
MatchCollection matchCollection = regex.Matches(input);
int num = 0;
foreach (Match item4 in matchCollection)
{
if (num >= 1)
{
listName.Add(item4.Groups["
name"].Value);
}
num++;
}
Regex regex2 = new Regex("
(\\s[i]xy\\:\\s[/i](?<x>(\\d+))\\s[i]\\,\\s[/i](?<y>(\\d+))\\s*)", RegexOptions.IgnoreCase | RegexOptions.Multiline);
MatchCollection matchCollection2 = regex2.Matches(input);
foreach (Match item5 in matchCollection2)
{
Point item = new Point(0, 0);
item.X = int.Parse(item5.Groups["
x"].Value);
item.Y = int.Parse(item5.Groups["
y"].Value);
listPos.Add(item);
}
Regex regex3 = new Regex("
(\\n\\s+size\\:\\s[i](?<x>(\\d+))\\s[/i]\\,\\s[i](?<y>(\\d+))\\s[/i])", RegexOptions.IgnoreCase);
MatchCollection matchCollection3 = regex3.Matches(input);
foreach (Match item6 in matchCollection3)
{
listWidth.Add(int.Parse(item6.Groups["
x"].Value));
listHeight.Add(int.Parse(item6.Groups["
y"].Value));
}
Regex regex4 = new Regex("
(\\s[i]orig\\:\\s[/i](?<x>(\\d+))\\s[i]\\,\\s[/i](?<y>(\\d+))\\s*)", RegexOptions.IgnoreCase | RegexOptions.Multiline);
MatchCollection matchCollection4 = regex4.Matches(input);
foreach (Match item7 in matchCollection4)
{
Point item2 = new Point(0, 0);
item2.X = int.Parse(item7.Groups["
x"].Value);
item2.Y = int.Parse(item7.Groups["
y"].Value);
listOrigSize.Add(item2);
}
Regex regex5 = new Regex("
(\\s[i]offset\\:\\s[/i](?<x>(\\d+))\\s[i]\\,\\s[/i](?<y>(\\d+))\\s*)", RegexOptions.IgnoreCase | RegexOptions.Multiline);
MatchCollection matchCollection5 = regex5.Matches(input);
foreach (Match item8 in matchCollection5)
{
Point item3 = new Point(0, 0);
item3.X = int.Parse(item8.Groups["
x"].Value);
item3.Y = int.Parse(item8.Groups["
y"].Value);
listOffset.Add(item3);
}
Regex regex6 = new Regex("
(\\s[i]index\\:\\s[/i](?<index>([-]?([1-9][0-9][i]|0)(\\.[0-9]+)?%?)\\s[/i]))", RegexOptions.IgnoreCase | RegexOptions.Multiline);
MatchCollection matchCollection6 = regex6.Matches(input);
foreach (Match item9 in matchCollection6)
{
listIndex.Add(int.Parse(item9.Groups["
index"].Value));
}
Regex regex7 = new Regex("
(\\s[i]rotate\\:\\s[/i](?<rotate>(\\w+)))", RegexOptions.IgnoreCase | RegexOptions.Multiline);
MatchCollection matchCollection7 = regex7.Matches(input);
foreach (Match item10 in matchCollection7)
{
if (item10.Groups["
rotate"].Value.Equals("true"))
{
listRotate.Add(item: true);
}
else
{
listRotate.Add(item: false);
}
}
}
fillStruct();
}

public void CutImage_Click(object sender, EventArgs e)
{
textBox1.Text = sb.AppendLine("
*[i][b][i][b][i][b]开始处理[/b][/i][/b][/i][/b][/i]*").ToString();
for (int i = 0; i < listPic.Count(); i++)
{
if (listPic[i].index == -1)
{
Cut(listPic[i].startPos, listPic[i].width, listPic[i].height, listPic[i].pictureName.Replace("
\r", string.Empty), listPic[i].isRotate, listPic[i].origSize, listPic[i].offset);
textBox1.Text = sb.AppendLine(listPic[i].pictureName.Replace("
\r", string.Empty)).ToString();
}
else
{
Cut(listPic[i].startPos, listPic[i].width, listPic[i].height, listPic[i].pictureName.Replace("
\r", string.Empty) + "_" + listPic[i].index, listPic[i].isRotate, listPic[i].origSize, listPic[i].offset);
textBox1.Text = sb.AppendLine(listPic[i].pictureName.Replace("
\r", string.Empty) + "_" + listPic[i].index).ToString();
}
textBox1.Focus();
textBox1.Select(textBox1.TextLength, 0);
textBox1.ScrollToCaret();
}
textBox1.Text = sb.AppendLine("
*[i][b][i][b][i][b]处理完成[/b][/i][/b][/i][/b][/i]*").ToString();
textBox1.Focus();
textBox1.Select(textBox1.TextLength, 0);
textBox1.ScrollToCaret();
clear();
DialogResult dialogResult = MessageBox.Show("
确定打开文件夹么", "提示", MessageBoxButtons.OKCancel);
if (dialogResult == DialogResult.OK)
{
string arguments = Path.GetDirectoryName(picPath.Text) + "
\\" + Path.GetFileNameWithoutExtension(picPath.Text) + "_ReversePic\\";
Process.Start("
explorer.exe", arguments);
}
else
{
_ = 2;
}
}

public void Cut(Point pos, int cutWidth, int cutHeight, string name, bool isRotate, Point orig, Point offset)
{
Bitmap bitmap = new Bitmap(picPath.Text);
Bitmap bitmap2 = new Bitmap(bitmap);
Bitmap bitmap3;
if (isRotate)
{
bitmap3 = bitmap2.Clone(new Rectangle(pos.X, pos.Y, cutHeight, cutWidth), bitmap2.PixelFormat);
bitmap3.RotateFlip(RotateFlipType.Rotate90FlipNone);
}
else
{
bitmap3 = bitmap2.Clone(new Rectangle(pos.X, pos.Y, cutWidth, cutHeight), bitmap2.PixelFormat);
}
Bitmap bitmap4 = new Bitmap(orig.X, orig.Y);
Graphics graphics = Graphics.FromImage(bitmap4);
string text = Path.GetDirectoryName(picPath.Text) + "
\\" + Path.GetFileNameWithoutExtension(picPath.Text) + "_ReversePic\\";
if (!Directory.Exists(text))
{
DirectoryInfo directoryInfo = new DirectoryInfo(text);
directoryInfo.Create();
}
if (!string.IsNullOrEmpty(Path.GetDirectoryName(name)))
{
graphics.DrawImageUnscaled(bitmap3, offset.X, offset.Y);
string text2 = text + "
\\" + Path.GetDirectoryName(name) + "\\";
if (!Directory.Exists(text2))
{
DirectoryInfo directoryInfo2 = new DirectoryInfo(text2);
directoryInfo2.Create();
}
bitmap4.Save(text2 + Path.GetFileNameWithoutExtension(name) + "
.png", ImageFormat.Png);
}
else
{
graphics.DrawImageUnscaled(bitmap3, offset.X, offset.Y);
bitmap4.Save(text + Path.GetFileNameWithoutExtension(name) + "
.png", ImageFormat.Png);
}
bitmap.Dispose();
bitmap2.Dispose();
bitmap4.Dispose();
}

public void fillStruct()
{
Console.Write("
{0}, {1}, {2}, {3}\n", listName.Count(), listWidth.Count(), listHeight.Count(), listPos.Count());
for (int i = 0; i < listName.Count(); i++)
{
pic.pictureName = listName[i];
pic.width = listWidth[i];
pic.height = listHeight[i];
pic.startPos = listPos[i];
pic.origSize = listOrigSize[i];
pic.offset = listOffset[i];
pic.index = listIndex[i];
pic.isRotate = listRotate[i];
listPic.Add(pic);
}
}

public void clear()
{
listWidth.Clear();
listHeight.Clear();
listName.Clear();
listIndex.Clear();
listRotate.Clear();
listPos.Clear();
listOrigSize.Clear();
listOffset.Clear();
listPic.Clear();
}

public bool checkFileExsit(string fileName)
{
bool flag = false;
if (File.Exists(fileName))
{
return true;
}
return false;
}

protected override void Dispose(bool disposing)
{
if (disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}

private void InitializeComponent()
{
this.loaded_pictures = new System.Windows.Forms.PictureBox();
this.GetPictureInfoPath = new System.Windows.Forms.Button();
this.CutImage = new System.Windows.Forms.Button();
this.picPath = new System.Windows.Forms.TextBox();
this.picInfoPath = new System.Windows.Forms.TextBox();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.textBox1 = new System.Windows.Forms.TextBox();
((System.ComponentModel.ISupportInitialize)(this.loaded_pictures)).BeginInit();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.SuspendLayout();
//
// loaded_pictures
//
this.loaded_pictures.BackColor = System.Drawing.SystemColors.ButtonHighlight;
this.loaded_pictures.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.loaded_pictures.Location = new System.Drawing.Point(20, 25);
this.loaded_pictures.Name = "
loaded_pictures";
this.loaded_pictures.Size = new System.Drawing.Size(280, 280);
this.loaded_pictures.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.loaded_pictures.TabIndex = 1;
this.loaded_pictures.TabStop = false;
//
// GetPictureInfoPath
//
this.GetPictureInfoPath.Location = new System.Drawing.Point(564, 27);
this.GetPictureInfoPath.Name = "
GetPictureInfoPath";
this.GetPictureInfoPath.Size = new System.Drawing.Size(76, 54);
this.GetPictureInfoPath.TabIndex = 2;
this.GetPictureInfoPath.Text = "
Open the Atlas file";
this.GetPictureInfoPath.UseVisualStyleBackColor = true;
this.GetPictureInfoPath.Click += new System.EventHandler(this.GetPictureInfoPath_Click);
//
// CutImage
//
this.CutImage.Location = new System.Drawing.Point(288, 486);
this.CutImage.Name = "
CutImage";
this.CutImage.Size = new System.Drawing.Size(102, 42);
this.CutImage.TabIndex = 3;
this.CutImage.Text = "
cut";
this.CutImage.UseVisualStyleBackColor = true;
this.CutImage.Click += new System.EventHandler(this.CutImage_Click);
//
// picPath
//
this.picPath.Location = new System.Drawing.Point(20, 60);
this.picPath.Name = "
picPath";
this.picPath.ReadOnly = true;
this.picPath.Size = new System.Drawing.Size(524, 21);
this.picPath.TabIndex = 4;
//
// picInfoPath
//
this.picInfoPath.Location = new System.Drawing.Point(20, 29);
this.picInfoPath.Name = "
picInfoPath";
this.picInfoPath.Size = new System.Drawing.Size(524, 21);
this.picInfoPath.TabIndex = 5;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.picPath);
this.groupBox1.Controls.Add(this.picInfoPath);
this.groupBox1.Controls.Add(this.GetPictureInfoPath);
this.groupBox1.Location = new System.Drawing.Point(12, 14);
this.groupBox1.Name = "
groupBox1";
this.groupBox1.Size = new System.Drawing.Size(659, 100);
this.groupBox1.TabIndex = 6;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "
Picture selection (note: please put pictures and \"atlas\" files in the same direct" +
"ory, the picture file name needs to be the same as the atlas file name";
//
// groupBox2
//
this.groupBox2.Controls.Add(this.loaded_pictures);
this.groupBox2.Location = new System.Drawing.Point(12, 138);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(320, 320);
this.groupBox2.TabIndex = 7;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "图片显示区域";
//
// groupBox3
//
this.groupBox3.Controls.Add(this.textBox1);
this.groupBox3.Location = new System.Drawing.Point(351, 138);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(320, 320);
this.groupBox3.TabIndex = 8;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "图片列表";
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(21, 25);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.textBox1.Size = new System.Drawing.Size(280, 280);
this.textBox1.TabIndex = 0;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(691, 537);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.CutImage);
this.Name = "Form1";
this.Text = "cut";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.loaded_pictures)).EndInit();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.ResumeLayout(false);

}

private void Form1_Load(object sender, EventArgs e)
{

}
}
}
I have put the complete project file on the cloud disk, and click the green button on the link webpage to download it.
The project was opened with Visual Studio 2019 and above. You can also open the project in other versions of Visual Studio in other ways.

https://www.jianguoyun.com/p/DY_14ZwQ66mdCBjZvvoC

Please send me the project after completion, thank you very much!
God bless you!
1329343592
  • Mensajes: 9

Harald

Why do you need to crop exported atlas pages?
In general it is not encouraged to crop atlas pages, but instead pack only the desired images and leave out unneeded images when packing. Is this an option in your case? If yes, you could use the Texture Packer separately from the skeleton export, as described here. Note that you can pack by folder structure as well.

If you just want to remove whitespace, there are options Strip whitespace x and Strip whitespace y available in the Texture Atlas Export Settings.
Avatar de Usuario
Harald

Harri
  • Mensajes: 1730


Volver a Unity