diff --git a/Helper.cs b/Helper.cs index 4069ef5..4e4f419 100644 --- a/Helper.cs +++ b/Helper.cs @@ -4,8 +4,9 @@ using System.Linq; using System.Xml.Linq; using System.ComponentModel; using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; +using System.Runtime.InteropServices; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; static class Helper { @@ -42,24 +43,21 @@ static class Helper static class BitmapHelper { - public static (int[] bitmap, int width, int height) LoadBitmap(string filename) + public static (int[], int, int) LoadBitmap(string filename) { - Bitmap bitmap = new(filename); - int width = bitmap.Width, height = bitmap.Height; - var bits = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - int[] result = new int[bitmap.Width * bitmap.Height]; - System.Runtime.InteropServices.Marshal.Copy(bits.Scan0, result, 0, result.Length); - bitmap.UnlockBits(bits); - bitmap.Dispose(); + using var image = Image.Load(filename); + int width = image.Width, height = image.Height; + int[] result = new int[width * height]; + image.CopyPixelDataTo(MemoryMarshal.Cast(result)); return (result, width, height); } - public static void SaveBitmap(int[] data, int width, int height, string filename) + unsafe public static void SaveBitmap(int[] data, int width, int height, string filename) { - Bitmap result = new(width, height); - var bits = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); - System.Runtime.InteropServices.Marshal.Copy(data, 0, bits.Scan0, data.Length); - result.UnlockBits(bits); - result.Save(filename); + fixed (int* pData = data) + { + using var image = Image.WrapMemory(pData, width, height); + image.SaveAsPng(filename); + } } } diff --git a/README.md b/README.md index 5d78733..c34c460 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ On each step the number of non-zero coefficients decreases and in the end we hav It may happen that during propagation all the coefficients for a certain pixel become zero. That means that the algorithm has run into a contradiction and can not continue. The problem of determining whether a certain bitmap allows other nontrivial bitmaps satisfying condition (C1) is NP-hard, so it's impossible to create a fast solution that always finishes. In practice, however, the algorithm runs into contradictions surprisingly rarely. -Wave Function Collapse algorithm has been implemented in [C++](https://github.com/math-fehr/fast-wfc), [Python](https://github.com/ikarth/wfc_2019f), [Kotlin](https://github.com/j-roskopf/WFC), [Rust](https://github.com/sdleffler/collapse), [Julia](https://github.com/roberthoenig/WaveFunctionCollapse.jl), [Go](https://github.com/shawnridgeway/wfc), [Haxe](https://github.com/Mitim-84/WFC-Gen), [Java](https://github.com/sjcasey21/wavefunctioncollapse), [Clojure](https://github.com/sjcasey21/wavefunctioncollapse-clj), [JavaScript](https://github.com/kchapelier/wavefunctioncollapse) and adapted to [Unity](https://selfsame.itch.io/unitywfc), [Unreal Engine 5](https://docs.unrealengine.com/5.0/en-US/BlueprintAPI/WaveFunctionCollapse/) and [Houdini](https://www.sidefx.com/tutorials/wfc-dungeon-generator/). You can download official executables from [itch.io](https://exutumno.itch.io/wavefunctioncollapse) or [run it in the browser](http://www.kchapelier.com/wfc-example/overlapping-model.html). WFC generates levels in [Bad North](https://www.badnorth.com/), [Caves of Qud](https://store.steampowered.com/app/333640/Caves_of_Qud/), [Dead Static Drive](https://twitter.com/deadstaticdrive), [Townscaper](https://store.steampowered.com/app/1291340/Townscaper/), [Matrix Awakens](https://www.youtube.com/watch?v=usJrcwN6T4I), [several](https://arcadia-clojure.itch.io/proc-skater-2016) [smaller](https://arcadia-clojure.itch.io/swapland) [games](https://marian42.itch.io/wfc) and many prototypes. It led to [new](https://escholarship.org/uc/item/3rm1w0mn) [research](https://hal.inria.fr/hal-01706539v3/document). For [more](https://twitter.com/OskSta/status/784847588893814785) [related](https://twitter.com/dwtw/status/810166761270243328) [work](https://github.com/mewo2/oisin), [explanations](https://trasevol.dog/2017/09/01/di19/), [interactive demos](http://oskarstalberg.com/game/wave/wave.html), [guides](https://www.dropbox.com/s/zeiat1w8zre9ro8/Knots%20breakdown.png?dl=0), [tutorials](http://www.procjam.com/tutorials/wfc/) and [examples](https://twitter.com/ExUtumno/status/895684431477747715) see the [ports, forks and spinoffs section](https://github.com/mxgmn/WaveFunctionCollapse#notable-ports-forks-and-spinoffs). +Wave Function Collapse algorithm has been implemented in [C++](https://github.com/math-fehr/fast-wfc), [Python](https://github.com/ikarth/wfc_2019f), [Kotlin](https://github.com/j-roskopf/WFC), [Rust](https://github.com/sdleffler/collapse), [Julia](https://github.com/roberthoenig/WaveFunctionCollapse.jl), [Go](https://github.com/shawnridgeway/wfc), [Haxe](https://github.com/Mitim-84/WFC-Gen), [Java](https://github.com/sjcasey21/wavefunctioncollapse), [Clojure](https://github.com/sjcasey21/wavefunctioncollapse-clj), [JavaScript](https://github.com/kchapelier/wavefunctioncollapse) and adapted to [Unity](https://selfsame.itch.io/unitywfc), [Unreal Engine 5](https://docs.unrealengine.com/5.0/en-US/BlueprintAPI/WaveFunctionCollapse/) and [Houdini](https://www.sidefx.com/tutorials/wfc-dungeon-generator/). You can [build WFC from source](https://github.com/mxgmn/WaveFunctionCollapse#how-to-build), download an official [release](https://github.com/mxgmn/WaveFunctionCollapse/releases) for Windows, download an interactive graphical version from [itch.io](https://exutumno.itch.io/wavefunctioncollapse) or [run it in the browser](http://www.kchapelier.com/wfc-example/overlapping-model.html). WFC generates levels in [Bad North](https://www.badnorth.com/), [Caves of Qud](https://store.steampowered.com/app/333640/Caves_of_Qud/), [Dead Static Drive](https://twitter.com/deadstaticdrive), [Townscaper](https://store.steampowered.com/app/1291340/Townscaper/), [Matrix Awakens](https://www.youtube.com/watch?v=usJrcwN6T4I), [several](https://arcadia-clojure.itch.io/proc-skater-2016) [smaller](https://arcadia-clojure.itch.io/swapland) [games](https://marian42.itch.io/wfc) and many prototypes. It led to [new](https://escholarship.org/uc/item/3rm1w0mn) [research](https://hal.inria.fr/hal-01706539v3/document). For [more](https://twitter.com/OskSta/status/784847588893814785) [related](https://twitter.com/dwtw/status/810166761270243328) [work](https://github.com/mewo2/oisin), [explanations](https://trasevol.dog/2017/09/01/di19/), [interactive demos](http://oskarstalberg.com/game/wave/wave.html), [guides](https://www.dropbox.com/s/zeiat1w8zre9ro8/Knots%20breakdown.png?dl=0), [tutorials](http://www.procjam.com/tutorials/wfc/) and [examples](https://twitter.com/ExUtumno/status/895684431477747715) see the [ports, forks and spinoffs section](https://github.com/mxgmn/WaveFunctionCollapse#notable-ports-forks-and-spinoffs). Watch a video demonstration of WFC algorithm on YouTube: [https://youtu.be/DOQTr2Xmlz0](https://youtu.be/DOQTr2Xmlz0) diff --git a/WaveFunctionCollapse.csproj b/WaveFunctionCollapse.csproj index 82d6ca2..1bc65dd 100644 --- a/WaveFunctionCollapse.csproj +++ b/WaveFunctionCollapse.csproj @@ -9,7 +9,7 @@ - +