1
|
using System;
|
2
|
using System.Collections.Generic;
|
3
|
using System.Drawing;
|
4
|
using System.Drawing.Imaging;
|
5
|
using System.IO;
|
6
|
using System.Text;
|
7
|
|
8
|
namespace TextureEditing
|
9
|
{
|
10
|
/// <summary>
|
11
|
/// Edits input pngs
|
12
|
/// </summary>
|
13
|
class MapEditor
|
14
|
{
|
15
|
/// <summary> Path to data </summary>
|
16
|
string dataPath;
|
17
|
/// <summary> Path to output folder </summary>
|
18
|
string outPath;
|
19
|
|
20
|
/// <summary>
|
21
|
/// Constructor
|
22
|
/// </summary>
|
23
|
/// <param name="dataPath">Path to data</param>
|
24
|
/// <param name="outPath">Path to output folder</param>
|
25
|
public MapEditor(string dataPath, string outPath)
|
26
|
{
|
27
|
this.dataPath = dataPath;
|
28
|
this.outPath = outPath;
|
29
|
}
|
30
|
|
31
|
/// <summary>
|
32
|
/// Crop all pngs from input data folder
|
33
|
/// </summary>
|
34
|
public void EditAllPngs()
|
35
|
{
|
36
|
// does dataPath folder exist
|
37
|
if (!Directory.Exists(dataPath))
|
38
|
{
|
39
|
Console.WriteLine("Path does not exist");
|
40
|
return;
|
41
|
}
|
42
|
|
43
|
List<PngEdited> cropped = new List<PngEdited>();
|
44
|
|
45
|
// for all files
|
46
|
string[] files = Directory.GetFiles(dataPath);
|
47
|
foreach (string f in files)
|
48
|
{
|
49
|
Console.WriteLine("Processing file " + f);
|
50
|
Bitmap img = new Bitmap(f);
|
51
|
var newpng = Crop(img);
|
52
|
newpng.name = Path.GetFileName(f);
|
53
|
PositionInOriginal(img, newpng);
|
54
|
PositionOfCentroid(newpng);
|
55
|
cropped.Add(newpng);
|
56
|
|
57
|
newpng.Save(outPath + "/" + newpng.name);
|
58
|
}
|
59
|
SaveTxt(cropped);
|
60
|
|
61
|
/*
|
62
|
int c = 0;
|
63
|
foreach (PngEdited p in cropped)
|
64
|
{
|
65
|
c++;
|
66
|
TestImage(p, c);
|
67
|
}
|
68
|
*/
|
69
|
}
|
70
|
|
71
|
/// <summary>
|
72
|
/// Testing method
|
73
|
/// Prints out cropped image positioned back to original map and image with visible centroid
|
74
|
/// </summary>
|
75
|
/// <param name="pngEdited">Output image</param>
|
76
|
/// <param name="i">Number of image</param>
|
77
|
private void TestImage(PngEdited pngEdited, int i)
|
78
|
{
|
79
|
Bitmap png = new Bitmap("./bory-buildings.png");
|
80
|
Bitmap newpng = pngEdited.png;
|
81
|
|
82
|
Bitmap centroid = new Bitmap(20, 20);
|
83
|
for (int h = 0; h < centroid.Height; h++)
|
84
|
for (int w = 0; w < centroid.Width; w++)
|
85
|
centroid.SetPixel(w, h, Color.Red);
|
86
|
|
87
|
|
88
|
int xPos = (int)((newpng.Width / 100.0f) * pngEdited.xCentr) - 10;
|
89
|
int yPos = (int)((newpng.Height / 100.0f) * (100 - pngEdited.yCentr)) - 10;
|
90
|
|
91
|
Bitmap centroidTest = new Bitmap(newpng.Width, newpng.Height);
|
92
|
using (Graphics g = Graphics.FromImage(centroidTest))
|
93
|
{
|
94
|
g.DrawImage(newpng, new Rectangle(0, 0, newpng.Width, newpng.Height), new Rectangle(0, 0, newpng.Width, newpng.Height), GraphicsUnit.Pixel);
|
95
|
g.DrawImage(centroid, new Rectangle(xPos, yPos, 20, 20), new Rectangle(0, 0, centroidTest.Width, centroidTest.Height), GraphicsUnit.Pixel);
|
96
|
|
97
|
centroidTest.Save($"testCentroidOut{i}.png", ImageFormat.Png);
|
98
|
}
|
99
|
|
100
|
for (int h = 0; h < newpng.Height; h++)
|
101
|
for (int w = 0; w < newpng.Width; w++)
|
102
|
{
|
103
|
if (newpng.GetPixel(w, h).A != 0)
|
104
|
{
|
105
|
newpng.SetPixel(w, h, Color.Red);
|
106
|
}
|
107
|
}
|
108
|
|
109
|
xPos = (int) ((png.Width / 100.0f) * pngEdited.xPerc);
|
110
|
yPos = (int)((png.Height / 100.0f) * (100-pngEdited.yPerc)) - newpng.Height;
|
111
|
|
112
|
using (Graphics g = Graphics.FromImage(png))
|
113
|
{
|
114
|
g.DrawImage(newpng, new Rectangle(xPos, yPos, newpng.Width, newpng.Height), new Rectangle(0, 0, newpng.Width, newpng.Height), GraphicsUnit.Pixel);
|
115
|
png.Save($"testOut{i}.png", ImageFormat.Png);
|
116
|
}
|
117
|
}
|
118
|
|
119
|
/// <summary>
|
120
|
/// Compute the position of centroid. Coordinates are computed in % from bottom left corner of cropped png
|
121
|
/// </summary>
|
122
|
/// <param name="newpng">Output png in instance PngEdited</param>
|
123
|
private void PositionOfCentroid(PngEdited newpng)
|
124
|
{
|
125
|
// from all non transparent pixels
|
126
|
int coordY = 0, coordX = 0;
|
127
|
int count = 0;
|
128
|
for (int h = 0; h < newpng.png.Height; h++)
|
129
|
for (int w = 0; w < newpng.png.Width; w++)
|
130
|
{
|
131
|
if (newpng.png.GetPixel(w, h).A != 0 )
|
132
|
{
|
133
|
count++;
|
134
|
coordY += h;
|
135
|
coordX += w;
|
136
|
}
|
137
|
}
|
138
|
|
139
|
// coordinates
|
140
|
newpng.xCentr = coordX / count;
|
141
|
newpng.yCentr = coordY / count;
|
142
|
|
143
|
// to %
|
144
|
float onePercX = newpng.png.Width / 100.0f;
|
145
|
float percX = newpng.xCentr / onePercX;
|
146
|
newpng.xCentr = percX;
|
147
|
|
148
|
float onePercY = newpng.png.Height / 100.0f;
|
149
|
float percY = 100 - (newpng.yCentr / onePercY);
|
150
|
newpng.yCentr = percY;
|
151
|
}
|
152
|
|
153
|
/// <summary>
|
154
|
/// Find the position of cropped image in original. Coordinates of bottom left corner are computed in % from bottom left corner of original
|
155
|
/// </summary>
|
156
|
/// <param name="img">Original</param>
|
157
|
/// <param name="newpng">New image</param>
|
158
|
private void PositionInOriginal(Bitmap img, PngEdited newpng)
|
159
|
{
|
160
|
// left bottom corner
|
161
|
int xLeft = newpng.xStart;
|
162
|
int yLeft = newpng.yEnd;
|
163
|
|
164
|
// compute percentages
|
165
|
float onePercX = img.Width / 100.0f;
|
166
|
float percX = xLeft / onePercX;
|
167
|
newpng.xPerc = percX;
|
168
|
|
169
|
float onePercY = img.Height / 100.0f;
|
170
|
float percY = 100 - (yLeft / onePercY);
|
171
|
newpng.yPerc = percY;
|
172
|
}
|
173
|
|
174
|
/// <summary>
|
175
|
/// Save information about output files as csv
|
176
|
/// [name];[x coordinate of bottom left corner];[y coordinate of bottom left corner];[x coordinate of centroid];[y coordinate of centroid]
|
177
|
/// Coordinates of bottom left corner are computed in % from bottom left corner of original, coordinates of centroid are computed in % from bottom left corner of output png
|
178
|
/// </summary>
|
179
|
/// <param name="cropped"></param>
|
180
|
private void SaveTxt(List<PngEdited> cropped)
|
181
|
{
|
182
|
string res = "";
|
183
|
|
184
|
foreach (PngEdited png in cropped)
|
185
|
res += $"{png.name};{png.xPerc};{png.yPerc};{png.xCentr};{png.yCentr}\n";
|
186
|
|
187
|
File.WriteAllBytes(outPath + "/output.csv", Encoding.ASCII.GetBytes(res));
|
188
|
}
|
189
|
|
190
|
/// <summary>
|
191
|
/// Crop image so it does not contain any transparent padding
|
192
|
/// </summary>
|
193
|
/// <param name="img">Original image</param>
|
194
|
/// <returns>Cropped image as PngEdited instance</returns>
|
195
|
private PngEdited Crop(Bitmap img)
|
196
|
{
|
197
|
PngEdited res = new PngEdited();
|
198
|
|
199
|
int xFrom = img.Width, xTo = 0;
|
200
|
int yFrom = img.Height, yTo = 0;
|
201
|
|
202
|
// find start + end of x and y
|
203
|
for (int h = 0; h < img.Height; h++)
|
204
|
for (int w = 0; w < img.Width; w++)
|
205
|
{
|
206
|
if (img.GetPixel(w, h).A != 0 && xFrom > w)
|
207
|
xFrom = w;
|
208
|
|
209
|
if (img.GetPixel(w, h).A != 0 && xTo < w)
|
210
|
xTo = w;
|
211
|
|
212
|
if (img.GetPixel(w, h).A != 0 && yFrom > h)
|
213
|
yFrom = h;
|
214
|
|
215
|
if (img.GetPixel(w, h).A != 0 && yTo < h)
|
216
|
yTo = h;
|
217
|
}
|
218
|
|
219
|
|
220
|
// crop
|
221
|
Bitmap cropped = new Bitmap(xTo - xFrom + 1, yTo - yFrom + 1);
|
222
|
using (Graphics g = Graphics.FromImage(cropped))
|
223
|
{
|
224
|
g.DrawImage(img, new Rectangle(0, 0, cropped.Width, cropped.Height), new Rectangle(xFrom, yFrom, cropped.Width, cropped.Height), GraphicsUnit.Pixel);
|
225
|
res.png = cropped;
|
226
|
}
|
227
|
|
228
|
res.xStart = xFrom;
|
229
|
res.xEnd = xTo;
|
230
|
res.yStart = yFrom;
|
231
|
res.yEnd = yTo;
|
232
|
|
233
|
return res;
|
234
|
}
|
235
|
|
236
|
}
|
237
|
}
|