render service with test layer

+grpc interaction
This commit is contained in:
THE_KONDRAT 2025-04-27 14:19:57 +03:00
parent 33010ffe5e
commit 74e4698c43
27 changed files with 313 additions and 174 deletions

View File

@ -1,77 +0,0 @@
using System;
namespace Domain;
public class ConsoleImageDrawer
{
private char[,]? _image; // Изображение хранится внутри класса
// 1. Нарисовать изображение
public void DrawImage(char[,] image)
{
Console.Clear();
_image = image;
for (int i = 0; i < _image.GetLength(0); i++)
{
for (int j = 0; j < _image.GetLength(1); j++)
{
Console.SetCursorPosition(j, i);
Console.Write(_image[i, j]);
}
}
}
// 2. Заменить фон в указанной области на цвет
public void SetBackgroundColor(int startRow, int startCol, int height, int width, ConsoleColor color)
{
if (_image == null)
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Image is not set");
Console.ForegroundColor = ConsoleColor.Black;
return;
}
Console.BackgroundColor = color;
for (int i = startRow; i < Math.Min(startRow + height, _image.GetLength(0)); i++)
{
for (int j = startCol; j < Math.Min(startCol + width, _image.GetLength(1)); j++)
{
Console.SetCursorPosition(j, i);
Console.Write(_image[i, j]);
}
}
Console.ResetColor(); // Сброс цвета
}
// 3. Отменить фон (вернуть черный)
public void ResetBackgroundColor(int startRow, int startCol, int height, int width)
{
SetBackgroundColor(startRow, startCol, height, width, ConsoleColor.Black);
}
// 4. Изменить цвет указанного символа
public void SetCharacterColor(int row, int col, ConsoleColor foregroundColor)
{
if (_image == null)
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Image is not set");
Console.ForegroundColor = ConsoleColor.Black;
return;
}
if (row >= 0 && row < _image.GetLength(0) && col >= 0 && col < _image.GetLength(1))
{
Console.SetCursorPosition(col, row);
Console.ForegroundColor = foregroundColor;
Console.Write(_image[row, col]);
Console.ResetColor(); // Сброс цвета
}
}
// 5. Стереть изображение
public void ClearImage()
{
Console.Clear();
}
}

View File

@ -1,6 +1,6 @@
using System.Text;
namespace Domain.Somthing;
namespace Domain.Something;
public class ExpIniFileGenerator(uint rowCount, uint oddColumnCount, uint evenColumnCount)
{

View File

@ -1,8 +0,0 @@
namespace Domain.Abstractions;
public interface ILayer
{
public uint Order { get; }
public OpticalSchema OpticalSchema { get; }
public Task Execute();
}

View File

@ -0,0 +1,13 @@
using SkiaSharp;
namespace Domain;
public interface ILayer
{
public uint Order { get; }
public OpticalSchema OpticalSchema { get; }
public SKBitmap Image { get; }
public SKBitmap? Mask { get; }
public bool InvertMask { get; }
public Task Prerender();
public Task<SKBitmap> Render(uint u, uint u1, uint frameWidth, uint frameHeight, SKBitmap automask);
}

View File

@ -0,0 +1,8 @@
namespace Domain;
public interface IRenderManager
{
public Task<Guid> StartRender(Project project);
public Task StopRender(Guid renderId);
IEnumerable<Guid> GetActiveRenders();
}

0
Domain/Project.cs Normal file
View File

0
Domain/Render.cs Normal file
View File

0
Domain/RenderManager.cs Normal file
View File

View File

@ -0,0 +1,92 @@
using Domain.Abstractions;
using Domain.Interfaces;
using Domain.Something;
using SkiaSharp;
namespace Domain;
public class BigFrameRender : RenderPartBase
{
private readonly uint _bigFrameWidth;
private readonly uint _bigFrameHeight;
public BigFrameRender(IEnumerable<ILayer> layers, uint row, uint col, uint bigFrameWidth, uint bigFrameHeight, Guid renderId) :
base(layers, row, col, renderId)
{
_bigFrameWidth = bigFrameWidth;
_bigFrameHeight = bigFrameHeight;
}
public override async Task<IEnumerable<ExpIniFileGenerator.FrameExpInfo>> Execute(CancellationToken cancellationToken)
{
var frameExpInfos = new List<ExpIniFileGenerator.FrameExpInfo>();
BigFrameLayerRenderResult? previousLayerResult = null;
// _drawer.SetBackgroundColor((int)y, (int)x, (int)currentFrameHeight, (int)currentFrameWidth, ConsoleColor.DarkBlue);
foreach (var layer in _layers.OrderBy(q => q.Order))
{
previousLayerResult = await RenderBigFrame(layer, _col, _row, _bigFrameWidth, _bigFrameHeight, previousLayerResult);
}
if (previousLayerResult != null)
{
//split bigFrame
for (uint row = 0; row < _bigFrameHeight; row++)
{
for (uint col = 0; col < _bigFrameWidth; col++)
{
try
{
// Task.Delay(20).Wait();
var frameInfo = new ExpIniFileGenerator.FrameExpInfo{ Row = row, Column = col };
// if (!IsImageEmpty(previousLayerResult.Frame[col,row]))
// {
// frameInfo.IsContainAnything = true;
// await SaveImage(previousLayerResult.Frame[col, row], "");
// }
frameExpInfos.Add(frameInfo);
}
catch (Exception ex)
{
}
}
}
}
return frameExpInfos;
}
private async Task<BigFrameLayerRenderResult> RenderBigFrame(ILayer layer, uint x, uint y, uint bigFrameWidth, uint bigFrameHeight, BigFrameLayerRenderResult? previousLayerResult)
{
var automask = previousLayerResult?.Frame ?? new SKBitmap(Convert.ToInt32(bigFrameWidth), Convert.ToInt32(bigFrameHeight));
var result = new BigFrameLayerRenderResult()
{
Frame = new SKBitmap(Convert.ToInt32(bigFrameWidth), Convert.ToInt32(bigFrameHeight)),
};
result.Frame = await layer.Render(x, y, bigFrameWidth, bigFrameHeight, automask);
return result;
}
private bool IsImageEmpty(char image)
{
return image is '\0' or ' ';
}
private async Task SaveImage(char image, string destination)
{
//destinationn is object
//
await Task.Delay(200);
}
protected override Task RenderImage()
{
throw new NotImplementedException();
}
public override long EstimateMemoryUsage()
{
return 10;
}
}

View File

@ -0,0 +1,6 @@
namespace Domain.RenderPart;
// public class FrameRenderPart : RenderPartBase
// {
//
// }

View File

@ -0,0 +1,46 @@
using System.Collections;
using Domain.Abstractions;
using Domain.Interfaces;
using Domain.Something;
namespace Domain;
public abstract class RenderPartBase : IFrameRender
{
protected readonly IEnumerable<ILayer> _layers;
protected uint _row;
protected uint _col;
public Guid RenderId { get; private set; }
protected RenderPartBase(IEnumerable<ILayer> layers, uint row, uint col, Guid renderId)
{
_layers = layers;
_row = row;
_col = col;
RenderId = renderId;
}
public abstract Task<IEnumerable<ExpIniFileGenerator.FrameExpInfo>> Execute(CancellationToken cancellationToken);
public abstract long EstimateMemoryUsage();
protected abstract Task RenderImage();
protected virtual Task<ExpIniFileGenerator.FrameExpInfo> CreateFrameInfo()
{
throw new NotImplementedException();
return Task.FromResult(new ExpIniFileGenerator.FrameExpInfo());
}
protected virtual uint SetFrameNumber(uint row, uint column, uint columnsInRow)
{
return column + (row * columnsInRow);
}
protected Task SaveFrame()
{
return Task.CompletedTask;
}
}

View File

@ -0,0 +1,23 @@
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
USER $APP_UID
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["Make3.RenderServer/Make3.RenderServer.csproj", "Make3.RenderServer/"]
RUN dotnet restore "Make3.RenderServer/Make3.RenderServer.csproj"
COPY . .
WORKDIR "/src/Make3.RenderServer"
RUN dotnet build "./Make3.RenderServer.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./Make3.RenderServer.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Make3.RenderServer.dll"]

View File

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4"/>
</ItemGroup>
<ItemGroup>
<Content Include="..\.dockerignore">
<Link>.dockerignore</Link>
</Content>
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
@Make3.RenderServer_HostAddress = http://localhost:5198
GET {{Make3.RenderServer_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -0,0 +1,41 @@
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast");
app.Run();
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

View File

@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7264;http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

17
Make3.Renderer/Layer1.cs Normal file
View File

@ -0,0 +1,17 @@
using Domain.Abstractions;
namespace Domain.ConcreteLayers;
public class Layer1 : ILayer
{
public uint Order { get; set; }
public OpticalSchema OpticalSchema { get; set; }
public char[,] Image { get; set; }
public char[,]? Mask { get; set; }
public bool InvertMask { get; set; }
public Task Execute()
{
throw new NotImplementedException();
}
}

View File

@ -1,26 +0,0 @@
using Domain;
using Domain.Abstractions;
namespace Make3.Renderer.Layers;
internal abstract class LayerBase : ILayer
{
public uint Order { get; private set; }
public abstract OpticalSchema OpticalSchema { get; }
protected LayerBase(uint order)
{
Order = order;
}
public async Task Execute()
{
await Render();
}
protected virtual Task Render()
{
throw new NotImplementedException();
}
}

View File

@ -1,45 +0,0 @@
using Domain;
namespace Make3.Renderer.Layers.TrekoLayers
{
internal class Treko : LayerBase
{
public override OpticalSchema OpticalSchema => OpticalSchema.Sp0;
internal Treko(uint order) : base(order) { }
protected override Task Render()
{
var a = Step3(Step2(Step1()));
//return base.Render();
return Task.CompletedTask;
}
protected string Step1()
{
Step1_1();
return "";
}
protected string Step1_1()
{
return "";
}
private string Step2(string inputValue)
{
return "nothing";
}
private int Step3(string inputValue)
{
return 0;
}
}
}

View File

@ -1,17 +0,0 @@
using Domain;
namespace Make3.Renderer.Layers.TrekoLayers
{
internal class Treko3d : LayerBase
{
public override OpticalSchema OpticalSchema => OpticalSchema.Sp0;
internal Treko3d(uint order) : base(order) { }
protected override Task Render()
{
return base.Render();
}
}
}