Skip to content

Commit 29ffad9

Browse files
committed
code simplification, faster image io, better project file
1 parent 3e8debe commit 29ffad9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+186
-213
lines changed

Helper.cs

+27-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
/*
2-
The MIT License(MIT)
3-
Copyright(c) mxgmn 2016.
4-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6-
The software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
7-
*/
1+
// Copyright (C) 2016 Maxim Gumin, The MIT License (MIT)
82

93
using System.Linq;
104
using System.Xml.Linq;
115
using System.ComponentModel;
126
using System.Collections.Generic;
7+
using System.Drawing;
8+
using System.Drawing.Imaging;
139

1410
static class Helper
1511
{
@@ -43,3 +39,27 @@ public static T Get<T>(this XElement xelem, string attribute, T defaultT = defau
4339

4440
public static IEnumerable<XElement> Elements(this XElement xelement, params string[] names) => xelement.Elements().Where(e => names.Any(n => n == e.Name));
4541
}
42+
43+
static class BitmapHelper
44+
{
45+
public static (int[] bitmap, int width, int height) LoadBitmap(string filename)
46+
{
47+
Bitmap bitmap = new(filename);
48+
int width = bitmap.Width, height = bitmap.Height;
49+
var bits = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
50+
int[] result = new int[bitmap.Width * bitmap.Height];
51+
System.Runtime.InteropServices.Marshal.Copy(bits.Scan0, result, 0, result.Length);
52+
bitmap.UnlockBits(bits);
53+
bitmap.Dispose();
54+
return (result, width, height);
55+
}
56+
57+
public static void SaveBitmap(int[] data, int width, int height, string filename)
58+
{
59+
Bitmap result = new(width, height);
60+
var bits = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
61+
System.Runtime.InteropServices.Marshal.Copy(data, 0, bits.Scan0, data.Length);
62+
result.UnlockBits(bits);
63+
result.Save(filename);
64+
}
65+
}

LICENSE

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
MIT License
2+
3+
Copyright (c) 2016 Maxim Gumin
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+
23+
Provided image samples and tiles are not part of WaveFunctionCollapse software.

LICENSE.md

-1
This file was deleted.

Model.cs

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
/*
2-
The MIT License(MIT)
3-
Copyright(c) mxgmn 2016.
4-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6-
The software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
7-
*/
1+
// Copyright (C) 2016 Maxim Gumin, The MIT License (MIT)
82

93
using System;
104

@@ -25,9 +19,9 @@ abstract class Model
2519
protected double[] weights;
2620
double[] weightLogWeights, distribution;
2721

28-
int[] sumsOfOnes;
22+
protected int[] sumsOfOnes;
2923
double sumOfWeights, sumOfWeightLogWeights, startingEntropy;
30-
double[] sumsOfWeights, sumsOfWeightLogWeights, entropies;
24+
protected double[] sumsOfWeights, sumsOfWeightLogWeights, entropies;
3125

3226
public enum Heuristic { Entropy, MRV, Scanline };
3327
Heuristic heuristic;
@@ -231,7 +225,7 @@ void Clear()
231225
}
232226
}
233227

234-
public abstract System.Drawing.Bitmap Graphics();
228+
public abstract void Save(string filename);
235229

236230
protected static int[] dx = { -1, 0, 1, 0 };
237231
protected static int[] dy = { 0, 1, 0, -1 };

OverlappingModel.cs

+52-108
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,38 @@
1-
/*
2-
The MIT License(MIT)
3-
Copyright(c) mxgmn 2016.
4-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6-
The software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
7-
*/
1+
// Copyright (C) 2016 Maxim Gumin, The MIT License (MIT)
82

93
using System;
10-
using System.Drawing;
11-
using System.Drawing.Imaging;
124
using System.Collections.Generic;
135

146
class OverlappingModel : Model
157
{
16-
byte[][] patterns;
17-
List<Color> colors;
8+
List<byte[]> patterns;
9+
List<int> colors;
1810

1911
public OverlappingModel(string name, int N, int width, int height, bool periodicInput, bool periodic, int symmetry, bool ground, Heuristic heuristic)
2012
: base(width, height, N, periodic, heuristic)
2113
{
22-
var bitmap = new Bitmap($"samples/{name}.png");
23-
int SX = bitmap.Width, SY = bitmap.Height;
24-
byte[,] sample = new byte[SX, SY];
25-
colors = new List<Color>();
26-
27-
for (int y = 0; y < SY; y++) for (int x = 0; x < SX; x++)
28-
{
29-
Color color = bitmap.GetPixel(x, y);
30-
31-
int i = 0;
32-
foreach (var c in colors)
33-
{
34-
if (c == color) break;
35-
i++;
36-
}
37-
38-
if (i == colors.Count) colors.Add(color);
39-
sample[x, y] = (byte)i;
40-
}
41-
42-
int C = colors.Count;
43-
long W = C.ToPower(N * N);
14+
var (bitmap, SX, SY) = BitmapHelper.LoadBitmap($"samples/{name}.png");
15+
byte[] sample = new byte[bitmap.Length];
16+
colors = new List<int>();
17+
for (int i = 0; i < sample.Length; i++)
18+
{
19+
int color = bitmap[i];
20+
int k = 0;
21+
for (; k < colors.Count; k++) if (colors[k] == color) break;
22+
if (k == colors.Count) colors.Add(color);
23+
sample[i] = (byte)k;
24+
}
4425

45-
byte[] pattern(Func<int, int, byte> f)
26+
static byte[] pattern(Func<int, int, byte> f, int N)
4627
{
4728
byte[] result = new byte[N * N];
4829
for (int y = 0; y < N; y++) for (int x = 0; x < N; x++) result[x + y * N] = f(x, y);
4930
return result;
5031
};
32+
static byte[] rotate(byte[] p, int N) => pattern((x, y) => p[N - 1 - y + x * N], N);
33+
static byte[] reflect(byte[] p, int N) => pattern((x, y) => p[N - 1 - x + y * N], N);
5134

52-
byte[] patternFromSample(int x, int y) => pattern((dx, dy) => sample[(x + dx) % SX, (y + dy) % SY]);
53-
byte[] rotate(byte[] p) => pattern((x, y) => p[N - 1 - y + x * N]);
54-
byte[] reflect(byte[] p) => pattern((x, y) => p[N - 1 - x + y * N]);
55-
56-
long index(byte[] p)
35+
static long hash(byte[] p, int C)
5736
{
5837
long result = 0, power = 1;
5938
for (int i = 0; i < p.Length; i++)
@@ -64,70 +43,45 @@ long index(byte[] p)
6443
return result;
6544
};
6645

67-
byte[] patternFromIndex(long ind)
68-
{
69-
long residue = ind, power = W;
70-
byte[] result = new byte[N * N];
71-
72-
for (int i = 0; i < result.Length; i++)
73-
{
74-
power /= C;
75-
int count = 0;
76-
77-
while (residue >= power)
78-
{
79-
residue -= power;
80-
count++;
81-
}
82-
83-
result[i] = (byte)count;
84-
}
85-
86-
return result;
87-
};
88-
89-
var weights = new Dictionary<long, int>();
90-
var ordering = new List<long>();
46+
patterns = new();
47+
Dictionary<long, int> patternIndices = new();
48+
List<double> weightList = new();
9149

92-
for (int y = 0; y < (periodicInput ? SY : SY - N + 1); y++) for (int x = 0; x < (periodicInput ? SX : SX - N + 1); x++)
50+
int C = colors.Count;
51+
int xmax = periodicInput ? SX : SX - N + 1;
52+
int ymax = periodicInput ? SY : SY - N + 1;
53+
for (int y = 0; y < ymax; y++) for (int x = 0; x < xmax; x++)
9354
{
9455
byte[][] ps = new byte[8][];
9556

96-
ps[0] = patternFromSample(x, y);
97-
ps[1] = reflect(ps[0]);
98-
ps[2] = rotate(ps[0]);
99-
ps[3] = reflect(ps[2]);
100-
ps[4] = rotate(ps[2]);
101-
ps[5] = reflect(ps[4]);
102-
ps[6] = rotate(ps[4]);
103-
ps[7] = reflect(ps[6]);
57+
ps[0] = pattern((dx, dy) => sample[(x + dx) % SX + (y + dy) % SY * SX], N);
58+
ps[1] = reflect(ps[0], N);
59+
ps[2] = rotate(ps[0], N);
60+
ps[3] = reflect(ps[2], N);
61+
ps[4] = rotate(ps[2], N);
62+
ps[5] = reflect(ps[4], N);
63+
ps[6] = rotate(ps[4], N);
64+
ps[7] = reflect(ps[6], N);
10465

10566
for (int k = 0; k < symmetry; k++)
10667
{
107-
long ind = index(ps[k]);
108-
if (weights.ContainsKey(ind)) weights[ind]++;
68+
byte[] p = ps[k];
69+
long h = hash(p, C);
70+
if (patternIndices.TryGetValue(h, out int index)) weightList[index] = weightList[index] + 1;
10971
else
11072
{
111-
weights.Add(ind, 1);
112-
ordering.Add(ind);
73+
patternIndices.Add(h, weightList.Count);
74+
weightList.Add(1.0);
75+
patterns.Add(p);
11376
}
11477
}
11578
}
11679

117-
T = weights.Count;
80+
weights = weightList.ToArray();
81+
T = weights.Length;
11882
this.ground = ground;
119-
patterns = new byte[T][];
120-
base.weights = new double[T];
12183

122-
int counter = 0;
123-
foreach (long w in ordering)
124-
{
125-
patterns[counter] = patternFromIndex(w);
126-
base.weights[counter] = weights[w];
127-
counter++;
128-
}
129-
130-
bool agrees(byte[] p1, byte[] p2, int dx, int dy)
84+
static bool agrees(byte[] p1, byte[] p2, int dx, int dy, int N)
13185
{
13286
int xmin = dx < 0 ? 0 : dx, xmax = dx < 0 ? dx + N : N, ymin = dy < 0 ? 0 : dy, ymax = dy < 0 ? dy + N : N;
13387
for (int y = ymin; y < ymax; y++) for (int x = xmin; x < xmax; x++) if (p1[x + N * y] != p2[x - dx + N * (y - dy)]) return false;
@@ -141,18 +95,16 @@ bool agrees(byte[] p1, byte[] p2, int dx, int dy)
14195
for (int t = 0; t < T; t++)
14296
{
14397
List<int> list = new();
144-
for (int t2 = 0; t2 < T; t2++) if (agrees(patterns[t], patterns[t2], dx[d], dy[d])) list.Add(t2);
98+
for (int t2 = 0; t2 < T; t2++) if (agrees(patterns[t], patterns[t2], dx[d], dy[d], N)) list.Add(t2);
14599
propagator[d][t] = new int[list.Count];
146100
for (int c = 0; c < list.Count; c++) propagator[d][t][c] = list[c];
147101
}
148102
}
149103
}
150104

151-
public override Bitmap Graphics()
105+
public override void Save(string filename)
152106
{
153-
Bitmap result = new(MX, MY);
154-
int[] bitmapData = new int[result.Height * result.Width];
155-
107+
int[] bitmap = new int[MX * MY];
156108
if (observed[0] >= 0)
157109
{
158110
for (int y = 0; y < MY; y++)
@@ -161,8 +113,7 @@ public override Bitmap Graphics()
161113
for (int x = 0; x < MX; x++)
162114
{
163115
int dx = x < MX - N + 1 ? 0 : N - 1;
164-
Color c = colors[patterns[observed[x - dx + (y - dy) * MX]][dx + dy * N]];
165-
bitmapData[x + y * MX] = unchecked((int)0xff000000 | (c.R << 16) | (c.G << 8) | c.B);
116+
bitmap[x + y * MX] = colors[patterns[observed[x - dx + (y - dy) * MX]][dx + dy * N]];
166117
}
167118
}
168119
}
@@ -172,7 +123,6 @@ public override Bitmap Graphics()
172123
{
173124
int contributors = 0, r = 0, g = 0, b = 0;
174125
int x = i % MX, y = i / MX;
175-
176126
for (int dy = 0; dy < N; dy++) for (int dx = 0; dx < N; dx++)
177127
{
178128
int sx = x - dx;
@@ -186,21 +136,15 @@ public override Bitmap Graphics()
186136
for (int t = 0; t < T; t++) if (wave[s][t])
187137
{
188138
contributors++;
189-
Color color = colors[patterns[t][dx + dy * N]];
190-
r += color.R;
191-
g += color.G;
192-
b += color.B;
139+
int argb = colors[patterns[t][dx + dy * N]];
140+
r += (argb & 0xff0000) >> 16;
141+
g += (argb & 0xff00) >> 8;
142+
b += argb & 0xff;
193143
}
194144
}
195-
196-
bitmapData[i] = unchecked((int)0xff000000 | ((r / contributors) << 16) | ((g / contributors) << 8) | b / contributors);
145+
bitmap[i] = unchecked((int)0xff000000 | ((r / contributors) << 16) | ((g / contributors) << 8) | b / contributors);
197146
}
198147
}
199-
200-
var bits = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
201-
System.Runtime.InteropServices.Marshal.Copy(bitmapData, 0, bits.Scan0, bitmapData.Length);
202-
result.UnlockBits(bits);
203-
204-
return result;
148+
BitmapHelper.SaveBitmap(bitmap, MX, MY, filename);
205149
}
206150
}

Program.cs

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
/*
2-
The MIT License(MIT)
3-
Copyright(c) mxgmn 2016.
4-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6-
The software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
7-
*/
1+
// Copyright (C) 2016 Maxim Gumin, The MIT License (MIT)
82

93
using System;
104
using System.Xml.Linq;
@@ -15,6 +9,8 @@ static class Program
159
static void Main()
1610
{
1711
Stopwatch sw = Stopwatch.StartNew();
12+
var folder = System.IO.Directory.CreateDirectory("output");
13+
foreach (var file in folder.GetFiles()) file.Delete();
1814

1915
Random random = new();
2016
XDocument xdoc = XDocument.Load("samples.xml");
@@ -60,8 +56,9 @@ static void Main()
6056
if (success)
6157
{
6258
Console.WriteLine("DONE");
63-
model.Graphics().Save($"{name} {seed}.png");
64-
if (model is SimpleTiledModel stmodel && xelem.Get("textOutput", false)) System.IO.File.WriteAllText($"{name} {seed}.txt", stmodel.TextOutput());
59+
model.Save($"output/{name} {seed}.png");
60+
if (model is SimpleTiledModel stmodel && xelem.Get("textOutput", false))
61+
System.IO.File.WriteAllText($"output/{name} {seed}.txt", stmodel.TextOutput());
6562
break;
6663
}
6764
else Console.WriteLine("CONTRADICTION");

0 commit comments

Comments
 (0)