diff --git a/.gitignore b/.gitignore
index f2999ca..31acff3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,7 +28,6 @@
[Oo]bj/
_UpgradeReport_Files/
[Pp]ackages/
-/.contest
Thumbs.db
Desktop.ini
diff --git a/.idea/.idea.StitchATon/.idea/.gitignore b/.idea/.idea.StitchATon/.idea/.gitignore
deleted file mode 100644
index 78e63ec..0000000
--- a/.idea/.idea.StitchATon/.idea/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Rider ignored files
-/.idea.StitchATon.iml
-/contentModel.xml
-/projectSettingsUpdater.xml
-/modules.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/.idea.StitchATon/.idea/encodings.xml b/.idea/.idea.StitchATon/.idea/encodings.xml
deleted file mode 100644
index df87cf9..0000000
--- a/.idea/.idea.StitchATon/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.StitchATon/.idea/indexLayout.xml b/.idea/.idea.StitchATon/.idea/indexLayout.xml
deleted file mode 100644
index 7b08163..0000000
--- a/.idea/.idea.StitchATon/.idea/indexLayout.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.StitchATon/.idea/vcs.xml b/.idea/.idea.StitchATon/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/.idea.StitchATon/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/LocalNuget/.gitignore b/LocalNuget/.gitignore
deleted file mode 100644
index fbe7bcd..0000000
--- a/LocalNuget/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.nupkg
\ No newline at end of file
diff --git a/NuGet.Config b/NuGet.Config
deleted file mode 100644
index 954ec62..0000000
--- a/NuGet.Config
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/README.md b/README.md
deleted file mode 100644
index ba4bfaa..0000000
--- a/README.md
+++ /dev/null
@@ -1,120 +0,0 @@
-# I Paid for 4 GB of RAM So I Will Use The Whole 4 GB of RAM (and Probably More)
-Submission for Stitch-A-Ton Contest.
-
-## Prerequisites
-- **Dotnet installation**
-- **~4 GB** of memory on heavier operations. Command below sets the swap file size to 4GB.
- ```
- sudo dphys-swapfile swapoff
- sudo sed -i 's/^\(CONF_SWAPSIZE=\).*/\14096/' /etc/dphys-swapfile
- sudo dphys-swapfile setup
- sudo dphys-swapfile swapon
- sudo reboot
- ```
- If the test cases does not request a large portion of the canvas ***AND*** resizes it to a relatively still large ratio (i,e, ~0.9) **at the same time**, this might not be necessary.
-- **Access to** the `mkfifo` command, satisfied by default bar very special cases
-- **OpenCVSharp4 Runtime for Raspberry Pi 5**
-
- If running via dotnet run, Download the `.nupkg` file [here](https://null.formulatrix.dev/reinardras/stitch_something/releases/tag/0.0.0) and save on `LocalNuget` before running. Otherwise it shouldn't be necessary.
-
- If there's still a problem with library being missing, download the `.so` file and put it on `/usr/local/lib`.
-
-
-## Running
-
-Either of these method works.
-
-### Via dotnet run
-
-On root directory:
-```
-ASSET_PATH_RO= dotnet run --project StitchATon --profile deploy
-```
-
-The API is accessible at `:5255`, providing the following api:
-- [POST] `api/image/generate`: complies with competition guidelines
-- [GET] `api/image/sanity`: generates a predefined crop region:
-
- `G6:I8`, `(.1, .1)` offset, `(.8,.8)` crop, at 0.6 scale.
-
-To browse the API, prepend `ASPNETCORE_ENVIRONMENT=Development` to the command and go to `/swagger/index.html`.
-
-
-### Via releases
-
-Download [here](https://null.formulatrix.dev/reinardras/stitch_something/releases/).
-
-Run with the same parameters:
-
-```
-ASSET_PATH_RO= ./StitchATon --profile deploy
-```
-
-## Writeup
-
-This submission contains no specific magic in the image processing, just OpenCVSharp stretched to the best of its ability according to my knowledge. This section contains a brief overview of the main features.
-
-Per the writer's knowledge, the end result is **fast enough for the operation to be bottlenecked by network transfer speed** instead of image processing, except when resizing.
-
-*(note: I don't do rigorous benchmarks for that, take it with a grain of salt)*
-
-### Canvas Memory Usage
-During initialization, a blank 55x31 of 720x720 canvas is created, along with a 55*31 grid of enums indicating whether a chunk is already loaded, is currently being loaded, or ready to use.
-
-The memory usage of this canvas follows what chunks has been loaded into it, topping at ~2.6GB when all chunks are loaded.
-
-When multiple requests refer to the same region of the canvas, it doesn't need to be loaded again.
-
-### Coordinate Processing
-When parsing the request, it's possible that the requested canvas size doesn't correspond to what chunks that will actually be read; for example `A1:A3` at no offset and `(0.2, 1)` crop will only read some parts of `A1` chunk.
-
-```
- canvas
-┌─────────────────┬─────────────────┬─────────────────┐
-│ ┌───────────┐ │ │ │
-│ │ │ │ │ │
-│ │ final │ │ │ │
-│ │ result │ │ │ │
-│ │ │ │ │ │
-│ └───────────┘ │ │ │
-└─────────────────┴─────────────────┴─────────────────┘
-```
-
-To handle that, the resulting global crop RoI is calculated first and the chunks that are *actually* needed is identified (referred as *Adapted Sectors of Interest*).
-
-### Chunk Loading
-OpenCV Mats are thread safe given any operation is performed on non-overlapping regions of it. This allows multitasking reading the chunk to the main canvas.
-
-After coordinate processing, chunks in the adapted SoI are checked for their load status, then processed accordingly.
-
-The status "Currently being loaded" is relevant when multiple requests requiring the same chunk(s) are underway; on such case the loader that checks later spinlocks until it's done loading.
-
-**This mechanism enables the shared canvas to serve multiple processes.**
-
-### Encoding and Serving Cropped Image
-After the needed chunks are certain to be loaded to the main canvas, next is cropping it; which is a trivial operation in OpenCV, not requiring any extra memory since it still refers to the main canvas.
-
-What's not trivial is *encoding* it, which after some quick tests shows to take longer than reading and decoding multiple images from the canvas.
-
-OpenCV provides two functions that can help decode to PNG:
-- `Cv2.ImWrite` that writes to a file, and
-- `Cv2.ImEncode` that writes to a byte array.
-
-Both of these requires the encoding to finish before the resulting data can be used.
-
-To alleviate this problem, a **named pipe** (some sort of file pointer that works as a pipe buffer) is used; `ImWrite`-ing to said named pipe and have ASP.NET read from it. By doing this:
-- The encode and send process is parallelized
-- No extra memory needs to be allocated to encode the image; either on storage or RAM
-
-### (Unsolved) Resizing
-
-This remains as the only pain point that's not straightforward to solve. If no resize is requested, it's solvable by cropping off the main canvas and encoding it to a named pipe; eliminating a lot of time and memory overhead on the way.
-
-If resize is requested, a new Mat containing the resized image needs to be allocated.
-
-Ideas for this problem:
-- resize function that outputs a stream,
-- Imencode/imwrite function that accepts a stream.
-
-
-
diff --git a/StitchATon.Bench/Program.cs b/StitchATon.Bench/Program.cs
deleted file mode 100644
index c0ad218..0000000
--- a/StitchATon.Bench/Program.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using System.Diagnostics;
-using BenchmarkDotNet.Attributes;
-using Microsoft.Extensions.Logging.Abstractions;
-using OpenCvSharp;
-using StitchATon.Services;
-
-namespace StitchATon.Bench;
-
-public class Program
-{
- static readonly ImageProvider Ip = new ( new ImageProvider.Config(
- "/home/retorikal/Downloads/tiles1705/",
- 720,
- 55,
- 31),
- NullLogger.Instance );
- // static ImageProvider ip = new ( "/mnt/ramdisk/" );
-
- static async Task Fn1()
- {
- using var im = await Ip.GetImage(
- new Rect( new Point( 0, 0 ), new Size( 2, 1 ) ),
- new Point2f( 0, 0 ),
- new Point2f( 1, 1 ) );
- // Cv2.ImEncode(".png", im, out _);
- Cv2.ImWrite("/tmp/im1.png", im );
- }
-
- static async Task Fn2()
- {
- using var im = await Ip.GetImage(
- new Rect( new Point( 1, 1 ), new Size( 3, 3 ) ),
- new Point2f( 0, 0 ),
- new Point2f( 1, 1 ) );
- // Cv2.ImEncode(".png", im, out _);
- // Cv2.ImWrite("/tmp/im2.png", im2 );
- }
-
- static async Task Fn3()
- {
- using var im = await Ip.GetImage(
- new Rect( new Point( 2, 2 ), new Size( 3, 3 ) ),
- new Point2f( 0.2f, 0.2f ),
- new Point2f( .6f, .6f ) );
- // Cv2.ImEncode(".png", im, out _);
- // Cv2.ImWrite("/tmp/im3.png", im3 );
- }
-
- static async Task Fn4()
- {
- using var im = await Ip.GetImage(
- new Rect( new Point( 0, 0 ), new Size( 10, 10 ) ),
- new Point2f( 0.2f, 0.2f ),
- new Point2f( .6f, .6f ) );
- // Cv2.ImEncode(".png", im, out _);
- // Cv2.ImWrite("/tmp/im4.png", im4 );
- }
-
-
- // [Benchmark]
- static async Task Conc()
- {
- await Task.WhenAll(
- Fn1(),
- Fn2(),
- Fn3(),
- Fn4()
- );
- }
-
- // [Benchmark]
- static async Task Serial()
- {
- await Fn1();
- await Fn2();
- await Fn3();
- await Fn4();
- }
-
- public static ProcessStartInfo MkfifoPs = new("mkfifo", "/tmp/out.png");
- public static ProcessStartInfo RmfifoPs = new("rm", "/tmp/out.png");
-
- [Benchmark]
- public void Mkfifo()
- {
- Process.Start( MkfifoPs )?.WaitForExit();
- Process.Start( RmfifoPs )?.WaitForExit();
- }
-
- public async static Task Main( string[] args )
- {
-
- await Fn1();
- // var summary = BenchmarkRunner.Run();
- // var stopwatch = Stopwatch.StartNew();
- //
- //
- // stopwatch.Stop();
- // Console.WriteLine( $"Elapsed time: {stopwatch.ElapsedMilliseconds} ms" );
- //
- // var stopwatchAfter = Stopwatch.StartNew();
- // await Fn4();
- // stopwatchAfter.Stop();
- // Console.WriteLine( $"Elapsed time: {stopwatchAfter.ElapsedMilliseconds} ms" );
- }
-}
\ No newline at end of file
diff --git a/StitchATon.Bench/StitchATon.Bench.csproj b/StitchATon.Bench/StitchATon.Bench.csproj
deleted file mode 100644
index 64451d0..0000000
--- a/StitchATon.Bench/StitchATon.Bench.csproj
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- Exe
- net8.0
- enable
- enable
- StitchATon.Bench
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/StitchATon.sln b/StitchATon.sln
deleted file mode 100644
index e553226..0000000
--- a/StitchATon.sln
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StitchATon", "StitchATon\StitchATon.csproj", "{CE9E5242-9FC1-4B19-BD20-C6A2103C2DC8}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StitchATon.Bench", "StitchATon.Bench\StitchATon.Bench.csproj", "{84B2813B-56FB-4DB8-999D-9F363DBF5E19}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {CE9E5242-9FC1-4B19-BD20-C6A2103C2DC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CE9E5242-9FC1-4B19-BD20-C6A2103C2DC8}.Release|Any CPU.Build.0 = Release|Any CPU
- {CE9E5242-9FC1-4B19-BD20-C6A2103C2DC8}.Debug|Any CPU.ActiveCfg = Release|Any CPU
- {CE9E5242-9FC1-4B19-BD20-C6A2103C2DC8}.Debug|Any CPU.Build.0 = Release|Any CPU
- {84B2813B-56FB-4DB8-999D-9F363DBF5E19}.Debug|Any CPU.ActiveCfg = Release|Any CPU
- {84B2813B-56FB-4DB8-999D-9F363DBF5E19}.Debug|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
-EndGlobal
diff --git a/StitchATon/Controller.cs b/StitchATon/Controller.cs
deleted file mode 100644
index 0b8aa0a..0000000
--- a/StitchATon/Controller.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.ObjectPool;
-using OpenCvSharp;
-using StitchATon.DTO;
-using StitchATon.Services;
-using StitchATon.Utility;
-
-namespace StitchATon;
-
-[ApiController]
-[Route("api/image/")]
-public class ImageController( ImageProvider ip, ObjectPool npPool, ILogger logger ) : ControllerBase
-{
- [HttpPost]
- [Route("generate")]
- public async Task GetImage([FromBody] GenerateInput generateInput)
- {
- logger.LogInformation( $"GetImage requested at {generateInput.CanvasRect}" );
-
- var namedPipe = npPool.Get();
- var imagePath = namedPipe.PipeFullname;
-
- using var roiIm = await ip.GetImage(
- generateInput.ParsedCanvasRect(),
- generateInput.ParsedCropOffset(),
- generateInput.ParsedCropSize()
- );
-
- var scaledSize = new Size(
- roiIm.Cols * generateInput.OutputScale,
- roiIm.Rows * generateInput.OutputScale
- );
- Mat resizedIm = new();
-
- if( scaledSize == roiIm.Size() )
- resizedIm = roiIm;
- else
- Cv2.Resize( roiIm, resizedIm, scaledSize );
-
- // Spawn new task to write to the named pipe
- Task.Run( () =>
- {
- Cv2.ImWrite( imagePath, resizedIm );
- resizedIm.Dispose();
- } );
-
- // Stream the named pipe as output
- var fileStream = new FileStream(
- imagePath,
- FileMode.Open,
- FileAccess.Read,
- FileShare.Read,
- 4096,
- FileOptions.Asynchronous | FileOptions.SequentialScan);
-
- return File(fileStream, "image/png");
- }
-
- [HttpGet]
- [Route("sanity")]
- public async Task GetImageSanityTest()
- {
- var namedPipe = npPool.Get();
- var imagePath = namedPipe.PipeFullname;
-
- using var roiIm = await ip.GetImage(
- new Rect( new Point( 5, 6 ), new Size( 3, 3 ) ),
- new Point2f( .1f, .1f ),
- new Point2f( .8f, .8f ) );
-
- var mul = .7;
- var scaledSize = new Size(roiIm.Cols * mul , roiIm.Rows * mul);
- Mat resizedIm = new();
-
- if( scaledSize == roiIm.Size() )
- resizedIm = roiIm;
- else
- Cv2.Resize( roiIm, resizedIm, scaledSize );
-
- // Spawn new task to write to the named pipe
- Task.Run( () =>
- {
- Cv2.ImWrite( imagePath, resizedIm );
- resizedIm.Dispose();
- } );
-
- // Stream the named pipe as output
- var fileStream = new FileStream(
- imagePath,
- FileMode.Open,
- FileAccess.Read,
- FileShare.Read,
- 4096,
- FileOptions.Asynchronous | FileOptions.SequentialScan);
-
- return File(fileStream, "image/png");
- }
-}
diff --git a/StitchATon/DTO/Generate.cs b/StitchATon/DTO/Generate.cs
deleted file mode 100644
index 8e05eb3..0000000
--- a/StitchATon/DTO/Generate.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using JetBrains.Annotations;
-using OpenCvSharp;
-
-namespace StitchATon.DTO;
-
-public class GenerateInput
-{
- public required string CanvasRect { get; [UsedImplicitly] init; }
- public required float[] CropOffset { get; [UsedImplicitly] init; }
- public required float[] CropSize { get; [UsedImplicitly] init; }
- public required float OutputScale { get; [UsedImplicitly] init; }
-
- public Rect ParsedCanvasRect()
- {
- var corners = CanvasRect.Split( ":" );
- var c1 = ParseCanvasCoord( corners[0] );
- var c2 = ParseCanvasCoord( corners[1] );
-
- return new Rect(
- int.Min( c1.X, c2.X ),
- int.Min( c1.Y, c2.Y ),
- int.Abs( c1.X - c2.X ) + 1, // Inclusive bbox
- int.Abs( c1.Y - c2.Y ) + 1 // Inclusive bbox
- );
- }
-
- private Point ParseCanvasCoord(string labwareCoord)
- {
- int y = 0;
- int x = 0;
- foreach( var c in labwareCoord )
- {
- if( 'A' <= c && c <= 'Z' )
- y = ( y * 26 ) + ( c - 'A' + 1);
- else
- x = ( x * 10 ) + ( c - '0' );
- }
-
- y--;
- x--;
-
- return new(x, y);
- }
-
- public Point2f ParsedCropOffset() => new( CropOffset[0], CropOffset[1] );
-
- public Point2f ParsedCropSize() => new( CropSize[0], CropSize[1] );
-}
\ No newline at end of file
diff --git a/StitchATon/Program.cs b/StitchATon/Program.cs
deleted file mode 100644
index 5b69be0..0000000
--- a/StitchATon/Program.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System.Text.Json;
-using Microsoft.Extensions.ObjectPool;
-using StitchATon.Services;
-using StitchATon.Utility;
-
-
-var builder = WebApplication.CreateBuilder( args );
-
-builder.Services.AddEndpointsApiExplorer();
-builder.Services.AddSwaggerGen();
-
-var path = Environment.GetEnvironmentVariable( "ASSET_PATH_RO" );
-if( path == null )
- throw new ArgumentException("Please supply the directory path on ASSET_PATH_RO env var");
-
-// Image Loader
-builder.Services.AddSingleton( new ImageProvider.Config(
- path,
- 720,
- 55,
- 31) );
-builder.Services.AddSingleton();
-
-// FIFO named pipe pool
-builder.Services.AddSingleton>( new DefaultObjectPool(
- new DefaultPooledObjectPolicy(),
- 10 ) );
-builder.Services.AddControllers().AddJsonOptions( options =>
- {
- options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower;
- options.JsonSerializerOptions.WriteIndented = true;
- }
-
- );
-builder.Logging.AddConsole();
-
-var app = builder.Build();
-
-// Configure the HTTP request pipeline.
-if( app.Environment.IsDevelopment() )
-{
- app.UseSwagger();
- app.UseSwaggerUI();
-}
-
-app.UseCors();
-app.UseRouting();
-app.MapControllers();
-
-app.Run();
diff --git a/StitchATon/Properties/launchSettings.json b/StitchATon/Properties/launchSettings.json
deleted file mode 100644
index c8b7b7d..0000000
--- a/StitchATon/Properties/launchSettings.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "$schema": "http://json.schemastore.org/launchsettings.json",
- "iisSettings": {
- "windowsAuthentication": false,
- "anonymousAuthentication": true,
- "iisExpress": {
- "applicationUrl": "http://localhost:24734",
- "sslPort": 44313
- }
- },
- "profiles": {
- "deploy": {
- "commandName": "Project",
- "dotnetRunMessages": true,
- "launchBrowser": true,
- "launchUrl": "swagger",
- "applicationUrl": "http://localhost:5255"
- },
- "http": {
- "commandName": "Project",
- "dotnetRunMessages": true,
- "launchBrowser": true,
- "launchUrl": "swagger",
- "applicationUrl": "http://localhost:5255",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development",
- "ASSET_PATH_RO": "/home/retorikal/Downloads/tiles1705/"
- }
- },
- "https": {
- "commandName": "Project",
- "dotnetRunMessages": true,
- "launchBrowser": true,
- "launchUrl": "swagger",
- "applicationUrl": "https://localhost:7105;http://localhost:5255",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development",
- "ASSET_PATH_RO": "/home/retorikal/Downloads/tiles1705/"
- }
- },
- "IIS Express": {
- "commandName": "IISExpress",
- "launchBrowser": true,
- "launchUrl": "swagger",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development",
- "ASSET_PATH_RO": "/home/retorikal/Downloads/tiles1705/"
- }
- }
- }
-}
diff --git a/StitchATon/Services/ImageProvider.cs b/StitchATon/Services/ImageProvider.cs
deleted file mode 100644
index ea119b4..0000000
--- a/StitchATon/Services/ImageProvider.cs
+++ /dev/null
@@ -1,172 +0,0 @@
-using OpenCvSharp;
-using StitchATon.Utility;
-
-namespace StitchATon.Services;
-
-public class ImageProvider
-{
- // Terminology
- // Chunk: 720*720 region thingy
- // Sector: Area defined in image chunk coordinates
- // Region: Area defined in image pixel coordinates
-
- public class Config(string imagePath, int sectorDim, int w, int h)
- {
- public string ImagePath = imagePath;
- public int SectorDim = sectorDim;
- public int W = w;
- public int H = h;
- }
-
- private Grid2D _ready;
- private Mat _canvas;
- private readonly Config _config;
- private ILogger _logger;
-
- enum ImageStatus
- {
- Blank,
- Loading,
- Ready
- }
-
- public ImageProvider( Config config, ILogger logger )
- {
- _config = config;
- _logger = logger;
- _ready = new Grid2D( _config.W, _config.H );
- _canvas = new Mat(
- _config.H * _config.SectorDim,
- _config.W * _config.SectorDim,
- MatType.CV_8UC3
- );
- }
-
- string GetImagePath( int x, int y )
- {
- x++;
- y++;
-
- string letter = string.Empty;
-
- while (y > 0)
- {
- y--; // Adjust to make A=0, B=1, ..., Z=25 for modulo operation
- int remainder = y % 26;
- char digit = (char)('A' + remainder);
- letter = digit + letter;
- y /= 26;
- }
-
- var filename = $"{letter}{x}.png";
- return Path.Join( _config.ImagePath, filename );
- }
-
- async Task LoadImage( int x, int y )
- {
- _ready[x, y] = ImageStatus.Loading;
- string path = GetImagePath( x, y );
- _logger.LogInformation( $"{path} not loaded yet, reading" );
- using Mat image = await Task.Run( () => Cv2.ImRead( path ) );
- image.CopyTo( GetChunkMat(x, y) );
- _ready[x, y] = ImageStatus.Ready;
- }
-
- // After this function is run, it is guaranteed that all images concerned within the SoI is loaded to the grand canvas.
- // Has a flagging mechanism to just wait if another call of this function is currently loading it.
- async Task LoadImages(Rect soi)
- {
-
- _logger.LogInformation( $"{soi.Width * soi.Height} chunks required" );
-
- List? loadTasks = null;
- List<(int x, int y)>? loadedByOthers = null;
-
- for( int x = soi.Left; x < soi.Right; x++ )
- for( int y = soi.Top; y < soi.Bottom; y++ )
- switch( _ready[x, y] )
- {
- case ImageStatus.Blank:
- if( loadTasks == null )
- loadTasks = new List( soi.Width * soi.Height );
- loadTasks.Add( LoadImage( x, y ) );
- break;
- case ImageStatus.Loading:
- if( loadedByOthers == null )
- loadedByOthers = new List<(int, int)>( 5 );
- loadedByOthers.Add( (x, y) );
- break;
- }
-
- if( loadTasks != null )
- {
- await Task.WhenAll( loadTasks );
- _logger.LogInformation( $"Finished loading {loadTasks.Count} images" );
- }
-
- // Spinlock until all images are loaded. 1ms delay to prevent processor overload
- while( loadedByOthers != null && loadedByOthers.Count != 0 )
- {
- await Task.Delay( 1 );
- loadedByOthers.RemoveAll( coord => _ready[coord.x, coord.y] == ImageStatus.Ready );
- }
- }
-
- Mat GetChunkMat( int x, int y )
- {
- var roi = new Rect(
- _config.SectorDim * x,
- _config.SectorDim * y,
- _config.SectorDim,
- _config.SectorDim
- );
-
- return _canvas[roi];
- }
-
- Rect GetGlobalRoi( Rect soi, Point2f roiOffsetRatio, Point2f roiSizeRatio )
- {
- var soiSizePx = new Size(
- soi.Size.Width * _config.SectorDim,
- soi.Size.Height * _config.SectorDim );
-
- return new Rect(
- ( soi.X * _config.SectorDim ) + (int)( soiSizePx.Width * roiOffsetRatio.X ),
- ( soi.Y * _config.SectorDim ) + (int)( soiSizePx.Height * roiOffsetRatio.Y ),
- (int)( soiSizePx.Width * roiSizeRatio.X ),
- (int)( soiSizePx.Height * roiSizeRatio.Y )
- );
- }
-
- Rect GetSoi( Rect roi )
- {
- var tl = roi.TopLeft;
- var br = roi.BottomRight;
-
- var soiTl = new Point(
- tl.X / _config.SectorDim,
- tl.Y / _config.SectorDim
- );
-
- var soiBr = new Point(
- (int) Math.Ceiling( br.X / (float) _config.SectorDim ),
- (int) Math.Ceiling( br.Y / (float) _config.SectorDim )
- );
-
- return new Rect(
- soiTl.X,
- soiTl.Y,
- soiBr.X - soiTl.X,
- soiBr.Y - soiTl.Y );
- }
-
- public async Task GetImage( Rect soi, Point2f roiOffsetRatio, Point2f roiSizeRatio )
- {
- var globalRoi = GetGlobalRoi( soi, roiOffsetRatio, roiSizeRatio);
- var adaptedSoi = GetSoi( globalRoi );
-
- await LoadImages( adaptedSoi );
-
- return _canvas[globalRoi];
- }
-}
\ No newline at end of file
diff --git a/StitchATon/StitchATon.csproj b/StitchATon/StitchATon.csproj
deleted file mode 100644
index c0dc6f0..0000000
--- a/StitchATon/StitchATon.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- net8.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/StitchATon/Utility/Grid2D.cs b/StitchATon/Utility/Grid2D.cs
deleted file mode 100644
index 46a922d..0000000
--- a/StitchATon/Utility/Grid2D.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-namespace StitchATon.Utility;
-
-public class Grid2D
-{
- private T[] _buffer;
- public readonly int W;
- public readonly int H;
-
- public Grid2D( int width, int height )
- {
- W = width;
- H = height;
- _buffer = new T[W * H];
- }
-
- private int Map( int x, int y )
- {
- return x + ( y * W );
- }
-
- public T this[ int x, int y ]
- {
- get => _buffer[Map( x, y )];
- set => _buffer[Map( x, y )] = value;
- }
-}
\ No newline at end of file
diff --git a/StitchATon/Utility/NamedPipe.cs b/StitchATon/Utility/NamedPipe.cs
deleted file mode 100644
index 0fea233..0000000
--- a/StitchATon/Utility/NamedPipe.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System.Diagnostics;
-
-namespace StitchATon.Utility;
-
-public class PngNamedPipe : IDisposable
-{
- private ProcessStartInfo _mkfifoPs = new("mkfifo");
- private ProcessStartInfo _rmfifoPs = new("rm");
- public readonly string PipeFullname = Path.Join( Path.GetTempPath(), Guid.NewGuid() + ".png" );
-
- public PngNamedPipe( )
- {
- _mkfifoPs.Arguments = PipeFullname;
- Process.Start( _mkfifoPs )?.WaitForExit();
- }
-
- public void Dispose()
- {
- _rmfifoPs.Arguments = PipeFullname;
- Process.Start( _rmfifoPs );
- }
-}
\ No newline at end of file
diff --git a/StitchATon/appsettings.Development.json b/StitchATon/appsettings.Development.json
deleted file mode 100644
index 7e8b4b2..0000000
--- a/StitchATon/appsettings.Development.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning",
- "StitchATon.Controller": "Information"
- }
- }
-}
diff --git a/StitchATon/appsettings.json b/StitchATon/appsettings.json
deleted file mode 100644
index f769bb8..0000000
--- a/StitchATon/appsettings.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning",
- "StitchATon.Controller": "Information"
- }
- },
- "AllowedHosts": "*"
-}
diff --git a/mise.toml b/mise.toml
deleted file mode 100644
index 5b17a42..0000000
--- a/mise.toml
+++ /dev/null
@@ -1,92 +0,0 @@
-# Quick Guide
-# - install mise
-# - download the asset and extract them to ASSET_PATH_RO
-# - mise trust mise.toml
-# - mise run verify-asset
-# - require hashdeep
-# `hashdeep` package in debian
-# or `md5deep` package in fedora
-# or uncomment `tools."http:hashdeep"` below in windows
-# - mise run serve
-# - mise run arrange
-# - mise run action
-# - mise run assert
-# - mise run bench
-
-[env]
-ASSET_PATH_RO = "{{ [xdg_cache_home, 'stitch-a-ton', 'asset'] | join_path }}"
-CONTEST_HOST = "http://localhost:7007"
-CONTEST_API = "/api/image/generate"
-CONTEST_OUTPUT = "{{ [cwd, '.contest'] | join_path }}"
-DOTNET_ENVIRONMENT = "Production"
-ANSWER_COMMIT_HASH = "89a07b40bf0414212c96945671a012035d375a25"
-
-[tools]
-dotnet = "8"
-xh = "latest"
-uv = "latest"
-k6 = "latest"
-
-# uncomment these if you're on windows
-#[tools."http:hashdeep"]
-#version = "4.4"
-
-#[tools."http:hashdeep".platforms]
-#windows-x64 = {url = "https://github.com/jessek/hashdeep/releases/download/v4.4/md5deep-4.4.zip"}
-
-[tasks.setup]
-run = '''
-{% if env.CONTEST_OUTPUT is not exists %}
-mkdir .contest
-{% endif %}
-'''
-
-[tasks.verify-asset]
-dir = "{{ env.ASSET_PATH_RO }}"
-run = '''
-xh get https://null.formulatrix.dev/Contest/stitch-a-ton-answer/raw/commit/{{ env.ANSWER_COMMIT_HASH }}/asset.txt -o ../asset.txt
-hashdeep -arbvk ../asset.txt .
-'''
-
-[tasks.arrange]
-depends = ['setup']
-dir = "{{ env.CONTEST_OUTPUT }}"
-outputs = ['answer.json', 'action.py', 'assert.py', 'bench.js', 'fuzzy.json']
-run = '''
-xh get https://null.formulatrix.dev/Contest/stitch-a-ton-answer/raw/commit/{{ env.ANSWER_COMMIT_HASH }}/answer.json -o answer.json
-xh get https://null.formulatrix.dev/Contest/stitch-a-ton-answer/raw/commit/{{ env.ANSWER_COMMIT_HASH }}/action.py -o action.py
-xh get https://null.formulatrix.dev/Contest/stitch-a-ton-answer/raw/commit/{{ env.ANSWER_COMMIT_HASH }}/assert.py -o assert.py
-xh get https://null.formulatrix.dev/Contest/stitch-a-ton-answer/raw/commit/{{ env.ANSWER_COMMIT_HASH }}/bench.js -o bench.js
-xh get https://null.formulatrix.dev/Contest/stitch-a-ton-answer/raw/commit/{{ env.ANSWER_COMMIT_HASH }}/fuzzy.json -o fuzzy.json
-'''
-
-[tasks.serve]
-run = "dotnet run -c Release --no-launch-profile --urls {{env.CONTEST_HOST}} --project StitchATon"
-
-[tasks.quick]
-depends = ['arrange']
-dir = "{{ env.CONTEST_OUTPUT }}"
-run = '''
-xh post {{env.CONTEST_HOST}}{{env.CONTEST_ENDPOINT}} canvas_rect=A1:H12 crop_offset:=[0,0] crop_size:=[1,1] output_scale:=0.25 -o quick.png
-'''
-
-[tasks.action]
-depends = ['arrange']
-dir = "{{ env.CONTEST_OUTPUT }}"
-run = '''
-uv run --no-config --script {{ [env.CONTEST_OUTPUT, 'action.py'] | join_path }}
-'''
-
-[tasks.assert]
-depends = ['arrange']
-dir = "{{ env.CONTEST_OUTPUT }}"
-run = '''
-uvx --no-config --with-requirements assert.py pytest assert.py
-'''
-
-[tasks.bench]
-depends = ['arrange']
-dir = "{{ env.CONTEST_OUTPUT }}"
-run = '''
-k6 run -e TARGET_URL="{{ env.CONTEST_HOST }}{{ env.CONTEST_API }}" bench.js
-'''