Initial commit
This commit is contained in:
commit
8d4b2bc943
17 changed files with 389 additions and 0 deletions
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
**/bin/**
|
||||||
|
**/obj/**
|
||||||
|
**/node_modules/**
|
||||||
|
**/**.suo
|
||||||
|
**/**.user
|
||||||
13
.idea/.idea.StitchATon/.idea/.gitignore
generated
vendored
Normal file
13
.idea/.idea.StitchATon/.idea/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/.idea.StitchATon.iml
|
||||||
|
/modules.xml
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/contentModel.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
4
.idea/.idea.StitchATon/.idea/encodings.xml
generated
Normal file
4
.idea/.idea.StitchATon/.idea/encodings.xml
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
8
.idea/.idea.StitchATon/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.StitchATon/.idea/indexLayout.xml
generated
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/.idea.StitchATon/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.StitchATon/.idea/vcs.xml
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
16
StitchATon.sln
Normal file
16
StitchATon.sln
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApp", "WebApp\WebApp.csproj", "{C7ECADED-5C93-45BB-8F9F-27DCF06BAA59}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C7ECADED-5C93-45BB-8F9F-27DCF06BAA59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C7ECADED-5C93-45BB-8F9F-27DCF06BAA59}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C7ECADED-5C93-45BB-8F9F-27DCF06BAA59}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C7ECADED-5C93-45BB-8F9F-27DCF06BAA59}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
44
WebApp/Coordinate.cs
Normal file
44
WebApp/Coordinate.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
namespace WebApp;
|
||||||
|
|
||||||
|
internal record Coordinate
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public int Row { get; }
|
||||||
|
public int Col { get; }
|
||||||
|
public string Path => PATH + Name + ".png";
|
||||||
|
|
||||||
|
private const string PATH = "D:/tiles1705/";
|
||||||
|
|
||||||
|
public Coordinate(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
int row = 0;
|
||||||
|
int col = 0;
|
||||||
|
foreach (var item in name)
|
||||||
|
{
|
||||||
|
if (item >= 'A')
|
||||||
|
{
|
||||||
|
row = row * 26 + (item - 'A' + 1);
|
||||||
|
}
|
||||||
|
else if (item >= '1')
|
||||||
|
{
|
||||||
|
col = col * 10 + (item - '1' + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row = row;
|
||||||
|
Col = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Coordinate(int row, int col)
|
||||||
|
{
|
||||||
|
Row = row;
|
||||||
|
Col = col;
|
||||||
|
Name = Helper.ToLetters(row) + col;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
WebApp/Helper.cs
Normal file
17
WebApp/Helper.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace WebApp;
|
||||||
|
|
||||||
|
public static class Helper
|
||||||
|
{
|
||||||
|
public static string ToLetters(int number)
|
||||||
|
{
|
||||||
|
var result = "";
|
||||||
|
while (number > 0)
|
||||||
|
{
|
||||||
|
number--; // Adjust for 1-based indexing
|
||||||
|
char letter = (char)('A' + (number % 26));
|
||||||
|
result = letter + result;
|
||||||
|
number /= 26;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
130
WebApp/ImageGenerator.cs
Normal file
130
WebApp/ImageGenerator.cs
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using OpenCvSharp;
|
||||||
|
|
||||||
|
namespace WebApp;
|
||||||
|
|
||||||
|
public class ImageGenerator
|
||||||
|
{
|
||||||
|
private const string PATH = "D:/tiles1705/";
|
||||||
|
|
||||||
|
public byte[] GenerateImage(RequestBody requestBody)
|
||||||
|
{
|
||||||
|
var start = DateTime.Now;
|
||||||
|
|
||||||
|
string[] inputs = requestBody.CanvasRect.Split(":");
|
||||||
|
Coordinate coord0 = new Coordinate(inputs[0]);
|
||||||
|
Coordinate coord1 = new Coordinate(inputs[1]);
|
||||||
|
(var matrix, _, _) = GenerateDict(coord0, coord1);
|
||||||
|
|
||||||
|
ConcurrentDictionary<int, Mat> rows = new();
|
||||||
|
Parallel.ForEach(matrix, pair =>
|
||||||
|
{
|
||||||
|
Mat row = new Mat();
|
||||||
|
List<Mat> mats = new();
|
||||||
|
foreach (var coord in pair.Value)
|
||||||
|
{
|
||||||
|
string fileName = PATH + coord.Name + ".png";
|
||||||
|
mats.Add(new Mat( fileName ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Cv2.HConcat(mats, row);
|
||||||
|
rows[pair.Key] = row;
|
||||||
|
});
|
||||||
|
|
||||||
|
Mat output = new Mat();
|
||||||
|
Cv2.VConcat(rows.Values, output);
|
||||||
|
|
||||||
|
var result = output.ImEncode();
|
||||||
|
var end = DateTime.Now;
|
||||||
|
var elapsed = end - start;
|
||||||
|
Console.WriteLine($"Elapsed: {elapsed.TotalMilliseconds} ms");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GenerateImage2(RequestBody requestBody)
|
||||||
|
{
|
||||||
|
var start = DateTime.Now;
|
||||||
|
Coordinate a1 = new Coordinate("A1");
|
||||||
|
Mat a1Mat = new Mat(a1.Path);
|
||||||
|
|
||||||
|
string[] inputs = requestBody.CanvasRect.Split(":");
|
||||||
|
Coordinate coord0 = new Coordinate(inputs[0]);
|
||||||
|
Coordinate coord1 = new Coordinate(inputs[1]);
|
||||||
|
|
||||||
|
double scale = requestBody.OutputScale;
|
||||||
|
|
||||||
|
(var matrix, int rowCount, int colCount) = GenerateMatrix(coord0, coord1);
|
||||||
|
Mat temp = GenerateTempMat(a1Mat, rowCount, colCount);
|
||||||
|
|
||||||
|
Parallel.ForEach(matrix, item =>
|
||||||
|
{
|
||||||
|
Mat mat = new Mat(item.Path);
|
||||||
|
Rect rect = new Rect((item.Col - 1) * a1Mat.Cols, (item.Row - 1) * a1Mat.Rows, a1Mat.Cols, a1Mat.Rows);
|
||||||
|
mat.CopyTo(temp[rect]);
|
||||||
|
});
|
||||||
|
|
||||||
|
double newWidth = temp.Width * scale;
|
||||||
|
double newHeight = temp.Height * scale;
|
||||||
|
|
||||||
|
temp.Resize(new Size(newWidth, newHeight));
|
||||||
|
var result = temp.ImEncode();
|
||||||
|
var end = DateTime.Now;
|
||||||
|
var elapsed = end - start;
|
||||||
|
Console.WriteLine($"Elapsed: {elapsed.TotalMilliseconds} ms");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal (List<Coordinate> Matrix, int RowCount, int ColCount) GenerateMatrix(Coordinate coordinate1, Coordinate coordinate2)
|
||||||
|
{
|
||||||
|
int minRow = Math.Min(coordinate1.Row, coordinate2.Row);
|
||||||
|
int maxRow = Math.Max(coordinate1.Row, coordinate2.Row);
|
||||||
|
int minCol = Math.Min(coordinate1.Col, coordinate2.Col);
|
||||||
|
int maxCol = Math.Max(coordinate1.Col, coordinate2.Col);
|
||||||
|
|
||||||
|
int rowCount = maxRow - minRow + 1;
|
||||||
|
int colCount = maxCol - minCol + 1;
|
||||||
|
|
||||||
|
// Initialize collections
|
||||||
|
List<Coordinate> results = new List<Coordinate>(rowCount*colCount);
|
||||||
|
for (int i = 1; i <= rowCount; i++)
|
||||||
|
{
|
||||||
|
for (int j = 1; j <= colCount; j++)
|
||||||
|
{
|
||||||
|
results.Add(new Coordinate(i,j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (results, rowCount, colCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal (ConcurrentDictionary<int,List<Coordinate>> Matrix, int RowCount, int ColCount) GenerateDict(Coordinate coordinate1, Coordinate coordinate2)
|
||||||
|
{
|
||||||
|
ConcurrentDictionary<int,List<Coordinate>> results = new();
|
||||||
|
int minRow = Math.Min(coordinate1.Row, coordinate2.Row);
|
||||||
|
int maxRow = Math.Max(coordinate1.Row, coordinate2.Row);
|
||||||
|
int minCol = Math.Min(coordinate1.Col, coordinate2.Col);
|
||||||
|
int maxCol = Math.Max(coordinate1.Col, coordinate2.Col);
|
||||||
|
|
||||||
|
int rowCount = maxRow - minRow + 1;
|
||||||
|
int colCount = maxCol - minCol + 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < rowCount; i++)
|
||||||
|
{
|
||||||
|
List<Coordinate> result = new();
|
||||||
|
for (int j = 0; j < colCount; j++)
|
||||||
|
{
|
||||||
|
int row = minRow + i;
|
||||||
|
int col = minCol + j;
|
||||||
|
result.Add(new Coordinate(row, col));
|
||||||
|
}
|
||||||
|
results[i] = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (results, rowCount, colCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Mat GenerateTempMat(Mat reference, int rowCount, int colCount)
|
||||||
|
{
|
||||||
|
return new Mat(reference.Rows * rowCount, reference.Cols * colCount, reference.Type());
|
||||||
|
}
|
||||||
|
}
|
||||||
44
WebApp/Program.cs
Normal file
44
WebApp/Program.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using WebApp;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (builder.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
builder.Services.AddSwaggerGen(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Stitch a Ton", Description = "Meizar's stitch a ton solution", Version = "v1" });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Stitch a Ton");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.MapPost("/api/image/generate",
|
||||||
|
( RequestBody requestBody ) =>
|
||||||
|
{
|
||||||
|
ImageGenerator imageGenerator = new ImageGenerator();
|
||||||
|
var png = imageGenerator.GenerateImage2( requestBody );
|
||||||
|
return Results.File(png, "image/png", "result.png");
|
||||||
|
})
|
||||||
|
.WithName("ImageGenerator")
|
||||||
|
.Produces(StatusCodes.Status200OK, contentType:"image/png");
|
||||||
|
|
||||||
|
app.Run();
|
||||||
41
WebApp/Properties/launchSettings.json
Normal file
41
WebApp/Properties/launchSettings.json
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:47070",
|
||||||
|
"sslPort": 44330
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:5184",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "https://localhost:7224;http://localhost:5184",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
WebApp/RequestBody.cs
Normal file
9
WebApp/RequestBody.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace WebApp;
|
||||||
|
|
||||||
|
public record struct RequestBody(
|
||||||
|
[property: JsonPropertyName("canvas_rect")]
|
||||||
|
string CanvasRect,
|
||||||
|
[property: JsonPropertyName("output_scale")]
|
||||||
|
double OutputScale );
|
||||||
16
WebApp/WebApp.csproj
Normal file
16
WebApp/WebApp.csproj
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<RootNamespace>WebApp</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="OpenCvSharp4" Version="4.11.0.20250507" />
|
||||||
|
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.11.0.20250507" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
6
WebApp/WebApplication.http
Normal file
6
WebApp/WebApplication.http
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
@WebApplication_HostAddress = http://localhost:5184
|
||||||
|
|
||||||
|
GET {{WebApplication_HostAddress}}/weatherforecast/
|
||||||
|
Accept: application/json
|
||||||
|
|
||||||
|
###
|
||||||
8
WebApp/appsettings.Development.json
Normal file
8
WebApp/appsettings.Development.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
WebApp/appsettings.json
Normal file
9
WebApp/appsettings.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
7
global.json
Normal file
7
global.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"rollForward": "latestMajor",
|
||||||
|
"allowPrerelease": true
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue