Не знаю

This commit is contained in:
Nick 2025-06-28 03:00:25 +03:00
parent 2f721d6514
commit 4f4b80255d
21 changed files with 561 additions and 84 deletions

View File

@ -1,4 +1,6 @@
using SkiaSharp;
using Domain.Interfaces;
using Make3.CommonTypes.Interfaces;
using Make3.CommonTypes.Interfaces.Matrices;
namespace Domain;
@ -10,6 +12,10 @@ public class BigFrameLayerRenderResult
public uint FrameSizeY { get; set; }
// или пиксели?
public SKBitmap Frame { get; set; } //типа автомаска
public required IBinaryMask Automask { get; set; } //типа автомаска
public double[,] Table1 { get; set; }
public double[,] Table2 { get; set; }
public double[,] Table3 { get; set; }
public double[,] Table4 { get; set; }
public List<ExpIniFileGenerator.FrameExpInfo> FrameInfos { get; set; } = [];
}

View File

@ -8,7 +8,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SkiaSharp" Version="3.116.1" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="14.6.0" />
<PackageReference Include="Make3.CommonTypes" Version="1.0.4" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,28 @@
namespace Domain.Entities;
public class BinaryMask2(uint width, uint height)
{
public uint Width { get; init; } = width;
public uint Height { get; init; } = height;
private readonly bool[] _data = new bool[width * height];
public void MakeOpaque(uint x, uint y)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(x, Width);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(y, Height);
_data[y * Width + x] = true;
}
public bool IsOpaque(uint x, uint y)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(x, Width);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(y, Height);
return _data[y * Width + x];
}
public bool IsTransparent(uint x, uint y)
{
return !IsOpaque(x, y);
}
}

View File

@ -0,0 +1,12 @@
using Make3.CommonTypes.Interfaces;
namespace Domain.Entities;
public class IntermediateRenderResult
{
public required IBinaryMask Automask { get; set; } //типа автомаска
public double[,] Table1 { get; set; }
public double[,] Table2 { get; set; }
public double[,] Table3 { get; set; }
public double[,] Table4 { get; set; }
}

View File

@ -1,13 +1,17 @@
using SkiaSharp;
using Domain.Entities;
using ImageMagick;
using Make3.CommonTypes.Interfaces;
namespace Domain.Interfaces;
public interface ILayer
{
public uint Order { get; }
public OpticalSchema OpticalSchema { get; }
public SKBitmap Image { get; }
public SKBitmap? Mask { get; }
public MagickImage Image { get; }
public IBinaryMask? Mask { get; }
public bool InvertMask { get; }
public Task Prerender();
public Task<SKBitmap> Render(uint x, uint y, uint frameWidth, uint frameHeight, SKBitmap automask);
// public Task<MagickImage> Render(uint x, uint y, uint frameWidth, uint frameHeight, MagickImage automask);
public Task<IntermediateRenderResult> Render(uint x, uint y, uint frameWidth, uint frameHeight, IBinaryMask automask);
}

View File

@ -2,7 +2,7 @@ namespace Domain.Interfaces;
public interface IRenderManager
{
public Task<Guid> StartRender(Project project);
public Task<Guid> StartRender(Project.Project project);
public Task StopRender(Guid renderId);
IEnumerable<Guid> GetActiveRenders();
}

View File

@ -0,0 +1,11 @@
namespace Domain.Project;
public class HardwareSettings
{
public double Ppu { get; set; }
public double UnitSize { get; set; }
public required IlluminationLevels IlluminationLevels { get; set; }
public required Resolution MatrixResolution { get; set; }
public required Resolution FrameResolution { get; set; }
public required Size FrameSize { get; set; }
}

View File

@ -0,0 +1,3 @@
namespace Domain.Project;
public record IlluminationLevels(byte Zero, byte LinearLow, byte LinearHigh);

View File

@ -1,10 +1,11 @@
using Domain.Interfaces;
namespace Domain;
namespace Domain.Project;
public class Project
{
public Guid Id { get; set; }
public IEnumerable<ILayer> Layers { get; set; } = [];
public uint Width { get; set; }
public uint Height { get; set; }
public required HardwareSettings HardwareSettings { get; set; }
}

View File

@ -0,0 +1,3 @@
namespace Domain.Project;
public record Resolution(uint X, uint Y);

9
Domain/Project/Size.cs Normal file
View File

@ -0,0 +1,9 @@
namespace Domain.Project;
public record Size(decimal Width, decimal Height, SizeUnit Unit);
public enum SizeUnit
{
um,
mm
}

View File

@ -1,6 +1,9 @@
using System.Threading.Channels;
using Domain.Interfaces;
using Domain.RenderPart;
using Make3.CommonTypes.Interfaces.Matrices;
//using Make3.CommonTypes.BinaryMask;
namespace Domain;
@ -15,9 +18,13 @@ public class Render
private readonly bool _useBigFrames = true;
private readonly CancellationTokenSource _cancellationTokenSource = new();
//private readonly BinaryMaskFactory _binaryMaskFactory;
private IMatrixAbstractFactory BinaryMaskFactory;
private readonly IMatrixAbstractFactory _binaryMaskFactory;
public Render(Project project)
public Render(Project.Project project, IMatrixAbstractFactory binaryMaskFactory)
{
_binaryMaskFactory = binaryMaskFactory;
Id = Guid.NewGuid();
ProjectId = project.Id;
_width = project.Width;
@ -56,7 +63,7 @@ public class Render
for (uint x = 0; x < _width; x += bigFrameWidth)
{
uint currentBigFrameWidth = Math.Min(bigFrameWidth, _width - x);
var bigFrameRender = new BigFrameRender(_layers, x, y, currentBigFrameWidth, currentBigFrameHeight, Id);
var bigFrameRender = new BigFrameRender(_binaryMaskFactory, _layers, x, y, currentBigFrameWidth, currentBigFrameHeight, Id);
await channel.Writer.WriteAsync(bigFrameRender);
}
}

View File

@ -1,6 +1,8 @@
using System.Collections.Concurrent;
using System.Threading.Channels;
using Domain.Interfaces;
//using Make3.CommonTypes.BinaryMask;
using Make3.CommonTypes.Interfaces.Matrices;
namespace Domain;
@ -8,9 +10,12 @@ public class RenderManager : IRenderManager
{
private readonly Channel<IFrameRender> _taskChannel;
private readonly ConcurrentDictionary<Guid, Render> _renders = [];
//private readonly BinaryMaskFactory _binaryMaskFactory;
private IMatrixAbstractFactory _binaryMaskFactory;
public RenderManager(int channelCapacity = 5)
public RenderManager(IMatrixAbstractFactory binaryMaskFactory, int channelCapacity = 5)
{
_binaryMaskFactory = binaryMaskFactory;
var options = new BoundedChannelOptions(channelCapacity)
{
FullMode = BoundedChannelFullMode.Wait // Ожидание при переполнении канала
@ -18,15 +23,26 @@ public class RenderManager : IRenderManager
_taskChannel = Channel.CreateBounded<IFrameRender>(options);
}
public Task<Guid> StartRender(Project project)
// public Task<Guid> StartRender(Project project)
// {
// var render = new Render(project);
// if (_renders.TryAdd(render.Id, render))
// {
// _ =render.Run(_taskChannel);
// }
// _ = ProcessQueue();
// return Task.FromResult(render.Id);
// }
// public Task<Guid> StartRender(Project project)
public async Task<Guid> StartRender(Project.Project project)
{
var render = new Render(project);
var render = new Render(project, _binaryMaskFactory);
if (_renders.TryAdd(render.Id, render))
{
_ =render.Run(_taskChannel);
await render.Run(_taskChannel);
}
_ = ProcessQueue();
return Task.FromResult(render.Id);
return render.Id;
}
private async Task ProcessQueue(CancellationToken cancellationToken = default)

View File

@ -1,5 +1,7 @@
using Domain.Interfaces;
using SkiaSharp;
using Make3.CommonTypes.Interfaces;
using Make3.CommonTypes.Interfaces.Matrices;
//using Make3.CommonTypes.BinaryMask;
namespace Domain.RenderPart;
@ -7,8 +9,9 @@ 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)
public BigFrameRender(IMatrixAbstractFactory matrixAbstractFactory, IEnumerable<ILayer> layers,
uint row, uint col, uint bigFrameWidth, uint bigFrameHeight, Guid renderId) :
base(matrixAbstractFactory, layers, row, col, renderId)
{
_bigFrameWidth = bigFrameWidth;
_bigFrameHeight = bigFrameHeight;
@ -56,12 +59,20 @@ public class BigFrameRender : RenderPartBase
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 automask = previousLayerResult?.Automask ??
((IBinaryMaskFactory)_matrixAbstractFactory.GetFactory<bool>())
.Create((int)bigFrameWidth, (int)bigFrameHeight, previousLayerResult?.Automask.GetBlackCellsPercentage() ?? 0);
var result = new BigFrameLayerRenderResult()
{
Frame = new SKBitmap(Convert.ToInt32(bigFrameWidth), Convert.ToInt32(bigFrameHeight)),
// Frame = new MagickImage(Convert.ToInt32(bigFrameWidth), Convert.ToInt32(bigFrameHeight)),
Automask = automask,
};
result.Frame = await layer.Render(x, y, bigFrameWidth, bigFrameHeight, automask);
var renderResult = await layer.Render(x, y, bigFrameWidth, bigFrameHeight, automask);
result.Automask = renderResult.Automask;
// result.Table1 = renderResult.Table1;
// result.Table2 = renderResult.Table2;
// result.Table3 = renderResult.Table3;
// result.Table4 = renderResult.Table4;
return result;
}

View File

@ -1,4 +1,6 @@
using Domain.Interfaces;
//using Make3.CommonTypes.BinaryMask;
using Make3.CommonTypes.Interfaces.Matrices;
namespace Domain.RenderPart;
@ -8,11 +10,13 @@ public abstract class RenderPartBase : IFrameRender
protected uint _row;
protected uint _col;
protected IMatrixAbstractFactory _matrixAbstractFactory;
public Guid RenderId { get; private set; }
protected RenderPartBase(IEnumerable<ILayer> layers, uint row, uint col, Guid renderId)
protected RenderPartBase(IMatrixAbstractFactory matrixAbstractFactory, IEnumerable<ILayer> layers, uint row, uint col, Guid renderId)
{
_matrixAbstractFactory = matrixAbstractFactory;
_layers = layers;
_row = row;
_col = col;

View File

@ -1,3 +1,5 @@
using Domain.Entities;
namespace Domain;
public class RenderResult

View File

@ -0,0 +1,117 @@
using Google.Protobuf;
using LayerClients;
namespace Make3.RenderServer.Grpc;
public static class GrpcConverters
{
private const int StreamChunkSize = 4096; // Размер чанка (4 КБ)
public static double[,] DecodeMatrix(List<LayerClients.MatrixRow> grpcMatrix)
{
if (grpcMatrix == null || grpcMatrix.Count == 0)
{
throw new ArgumentException("The input grpcMatrix is null or empty.");
}
// Определяем размерность массива
int rows = grpcMatrix.Count;
int cols = grpcMatrix[0].Values.Count;
// Создаём двумерный массив
double[,] matrix = new double[rows, cols];
// Заполняем массив данными из grpcMatrix
for (int i = 0; i < rows; i++)
{
if (grpcMatrix[i].Values.Count != cols)
{
throw new InvalidOperationException("All rows in grpcMatrix must have the same number of columns.");
}
for (int j = 0; j < cols; j++)
{
matrix[i, j] = grpcMatrix[i].Values[j];
}
}
return matrix;
}
public static Stream AppendToStream(Stream stream, IEnumerable<MatrixRow> matrix)
{
using var writer = new BinaryWriter(stream, System.Text.Encoding.Default, true);
foreach (var row in matrix)
{
foreach (var value in row.Values)
{
writer.Write(value);
}
}
stream.Position = 0;
return stream;
}
public static double[,] ConvertStreamToMatrix(Stream stream, uint rows, uint columns)
{
var matrix = new double[rows, columns];
using var reader = new BinaryReader(stream);
for (uint y = 0; y < rows; y++)
{
for (uint x = 0; x < columns; x++)
{
if (reader.BaseStream.Position < reader.BaseStream.Length)
{
matrix[y, x] = reader.ReadDouble(); // Читаем `double` из потока
}
else
{
throw new EndOfStreamException("Not enough data to read from stream.");
// matrix[y, x] = 0; // Заполняем нулями, если данных недостаточно
}
}
}
return matrix;
}
public static async Task SendStream(Stream stream, Func<ByteString, Task> sendChunk)
{
var buffer = new byte[StreamChunkSize];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
await sendChunk(ByteString.CopyFrom(buffer, 0, bytesRead));
}
}
public static void ReceiveStream(string outputPath, Func<ByteString?> getChunk)
{
using var fileStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write);
ByteString chunk;
while ((chunk = getChunk()) != null)
{
fileStream.Write(chunk.ToByteArray());
}
}
public static DecimalValue ConvertDecimalValue(decimal value)
{
var nanoFactor = 1_000_000_000;
var units = decimal.ToInt64(value);
var nanos = decimal.ToInt32((value - units) * nanoFactor);
return new DecimalValue
{
Units = units,
Nanos = nanos,
};
}
public static decimal ConvertDecimalValue(DecimalValue value)
{
var nanoFactor = 1_000_000_000;
return value.Units + value.Nanos / nanoFactor;
}
}

View File

@ -3,24 +3,81 @@ import "google/protobuf/wrappers.proto";
option csharp_namespace = "LayerClients";
service TestLayer {
rpc Prerender (PrerenderRequest) returns (PrerenderResponse);
rpc StreamPrerenderData (stream PrerenderRequest) returns (stream PrerenderResponse);
rpc Render (RenderRequest) returns (RenderResponse);
}
message PrerenderRequest {
string optical_schema_data = 1;
bytes mask = 2;
bytes image = 3;
bool invert_mask = 4;
ProjectData project_data = 1;
HardwareData hardware_data = 2;
string optical_schema_data = 3;
bytes image = 4;
google.protobuf.BytesValue mask = 5;
google.protobuf.BoolValue invert_mask = 6;
double difraction_angle = 7;
bool posterize_result = 8;
bool invert_profile = 9;
bool invert_horizontal_angle = 10;
double direct_angle = 11;
double angle_of_view = 12;
double object_angle = 13;
double horizontal_roughness = 14;
double vertical_roughness = 15;
}
message ProjectData {
double hologram_width = 1;
double hologram_Height = 2;
}
message HardwareData {
double ppu = 1;
double unit_size = 2;
IlluminationLevels illumination_levels = 3;
Resolution matrix_resolution = 4;
Resolution frame_resolution = 5;
Size frame_size = 6;
}
message IlluminationLevels {
int32 zero = 1;
int32 linear_low = 2;
int32 linear_high = 3;
}
message Resolution {
uint32 x = 1;
uint32 y = 2;
}
message Size {
DecimalValue width = 1;
DecimalValue height = 2;
SizeUnit unit = 3;
}
message DecimalValue {
// Whole units part of the amount
int64 units = 1;
// Nano units of the amount (10^-9)
// Must be same sign as units
sfixed32 nanos = 2;
}
enum SizeUnit {
um = 0;
mm = 1;
}
message PrerenderResponse {
string status = 1;
repeated MatrixRow test_matrix = 2; // Представляем матрицу через строки
repeated MatrixRow grating_period = 1;
repeated MatrixRow angles_horizontal = 2;
repeated MatrixRow phases = 3;
repeated MatrixRow saturation = 4;
}
message MatrixRow {
repeated double values = 1; // Значения одной строки матрицы
repeated double values = 1;
}
message RenderRequest {

View File

@ -1,62 +1,184 @@
using Domain;
using Domain.Entities;
using Domain.Interfaces;
using Domain.Project;
using Google.Protobuf;
using Grpc.Core;
using ImageMagick;
using LayerClients;
using SkiaSharp;
using Make3.CommonTypes.Interfaces;
using Make3.CommonTypes.Interfaces.Matrices;
using Make3.RenderServer.Grpc;
using IlluminationLevels = LayerClients.IlluminationLevels;
using Resolution = LayerClients.Resolution;
using Size = LayerClients.Size;
using SizeUnit = LayerClients.SizeUnit;
namespace Make3.RenderServer.Layers;
public class TestLayer(LayerClients.TestLayer.TestLayerClient grpcClient) : ILayer
public class TestLayer(LayerClients.TestLayer.TestLayerClient grpcClient, IMatrixAbstractFactory matrixAbstractFactory) : ILayer
{
public uint Order { get; init; }
public OpticalSchema OpticalSchema { get; init; }
public SKBitmap? Mask { get; init; }
public required SKBitmap Image { get; init; }
public IBinaryMask? Mask { get; init; }
public required MagickImage Image { get; init; }
public bool InvertMask { get; init; }
public HardwareSettings HardwareSettings { get; init; }
public double HologramWidth { get; init; }
public double HologramHeight { get; init; }
public double DifractionAngle { get; set; }
public bool PosterizeResult { get; set; }
public bool InvertProfile { get; set; }
public bool InvertHorizontalAngle { get; set; }
//Освещение голограммы
public double DirectAngle { get; set; }
public double AngleOfView { get; set; }
/// <summary>
/// компенсация для кристалла
/// </summary>
public double ObjectAngle { get; set; }
public double HorizontalRoughness { get; set; }
public double VerticalRoughness { get; set; }
private readonly LayerClients.TestLayer.TestLayerClient _grpcClient = grpcClient;
private readonly IMatrixAbstractFactory _matrixAbstractFactory = matrixAbstractFactory;
public async Task Prerender()
{
using var imageData = Image.Encode(SKEncodedImageFormat.Png, 100);
using var maskData = Mask?.Encode(SKEncodedImageFormat.Png, 100);
var request = new PrerenderRequest
var imageData = Image.ToByteArray(MagickFormat.Png);
using var call = _grpcClient.StreamPrerenderData();
await GrpcConverters.SendStream(new MemoryStream(imageData), async (imageChunk) =>
{
OpticalSchemaData = OpticalSchema.ToString(),
Image = ByteString.CopyFrom(imageData.Span),
};
if (maskData != null)
var request = MakePrerenderRequest();
request.Image = imageChunk;
await call.RequestStream.WriteAsync(request);
});
if (Mask != null)
{
request.Mask = ByteString.CopyFrom(maskData.Span);
request.InvertMask = InvertMask;
await GrpcConverters.SendStream(Mask.GetStream(), async (maskChunk) =>
{
var request = MakePrerenderRequest();
request.Mask = maskChunk;
request.InvertMask = InvertMask;
await call.RequestStream.WriteAsync(request);
});
// request.Mask = ByteString.CopyFrom(maskData);
// request.InvertMask = InvertMask;
}
var response = await _grpcClient.PrerenderAsync(request);
await call.RequestStream.CompleteAsync();
Stream gratingStream = new MemoryStream();
Stream anglesStream = new MemoryStream();
Stream phasesStream = new MemoryStream();
Stream saturationStream = new MemoryStream();
Stream table1Stream = new MemoryStream(); // Тестовая таблица
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
GrpcConverters.AppendToStream(gratingStream, response.GratingPeriod);
GrpcConverters.AppendToStream(anglesStream, response.AnglesHorizontal);
GrpcConverters.AppendToStream(phasesStream, response.Phases);
GrpcConverters.AppendToStream(saturationStream, response.Saturation);
// GrpcConverters.DecodeMatrix(table1Stream, response.Table1); // Чтение тестовой таблицы
}
// var response = await _grpcClient.PrerenderAsync(request);
var m1 = GrpcConverters.ConvertStreamToMatrix(gratingStream, Image.Width, Image.Height);
}
public async Task<SKBitmap> Render(uint x, uint y, uint frameWidth, uint frameHeight, SKBitmap? automask)
private PrerenderRequest MakePrerenderRequest()
{
return new PrerenderRequest
{
ProjectData = new ProjectData
{
HologramWidth = HologramWidth,
HologramHeight = HologramHeight,
},
HardwareData = new HardwareData()
{
Ppu = HardwareSettings.Ppu,
UnitSize = HardwareSettings.UnitSize,
IlluminationLevels = new IlluminationLevels
{
Zero = HardwareSettings.IlluminationLevels.Zero,
LinearLow = HardwareSettings.IlluminationLevels.LinearLow,
LinearHigh = HardwareSettings.IlluminationLevels.LinearHigh,
},
MatrixResolution = new Resolution
{
X = HardwareSettings.MatrixResolution.X,
Y = HardwareSettings.MatrixResolution.Y,
},
FrameResolution = new Resolution
{
X = HardwareSettings.FrameResolution.X,
Y = HardwareSettings.FrameResolution.Y,
},
FrameSize = new Size
{
Width = GrpcConverters.ConvertDecimalValue(HardwareSettings.FrameSize.Width),
Height = GrpcConverters.ConvertDecimalValue(HardwareSettings.FrameSize.Height),
Unit = HardwareSettings.FrameSize.Unit switch
{
Domain.Project.SizeUnit.um => SizeUnit.Um,
Domain.Project.SizeUnit.mm => SizeUnit.Mm,
_ => throw new NotImplementedException()
},
}
},
OpticalSchemaData = OpticalSchema.ToString(),
// Image = ByteString.CopyFrom(imageData),
DifractionAngle = DifractionAngle,
PosterizeResult = PosterizeResult,
InvertProfile = InvertProfile,
InvertHorizontalAngle = InvertHorizontalAngle,
VerticalRoughness = VerticalRoughness,
HorizontalRoughness = HorizontalRoughness,
DirectAngle = DirectAngle,
AngleOfView = AngleOfView,
ObjectAngle = ObjectAngle,
};
}
public async Task<IntermediateRenderResult> Render(uint x, uint y, uint frameWidth, uint frameHeight, IBinaryMask? automask)
{
//здесь надо кусок изображения взять
using var imageData = Image.Encode(SKEncodedImageFormat.Png, 100);
using var maskData = Mask?.Encode(SKEncodedImageFormat.Png, 100);
using var automaskData = automask?.Encode(SKEncodedImageFormat.Png, 100);
var imageData = Image.ToByteArray(MagickFormat.Png);
// var maskData = Mask?.ToByteArray(MagickFormat.Png);
IBinaryMask? maskData = null;
// using var automaskData = automask?.Encode(SKEncodedImageFormat.Png, 100);
byte[]? automaskData = null;
var request = new RenderRequest
{
X = x,
Y = y,
FrameWidth = frameWidth,
FrameHeight = frameHeight,
Image = ByteString.CopyFrom(imageData.Span),
Image = ByteString.CopyFrom(imageData),
// Automask = ByteString.CopyFrom(imageData.Span),
};
if (maskData != null)
{
request.Mask = ByteString.CopyFrom(maskData.Span);
request.InvertMask = InvertMask;
// request.Mask = ByteString.CopyFrom(maskData);
// request.InvertMask = InvertMask;
}
request.Automask = automaskData == null ? null : ByteString.CopyFrom(automaskData.Span);
request.Automask = automaskData == null ? null : ByteString.CopyFrom(automaskData);
var response = await _grpcClient.RenderAsync(request);
var byteArray = response.RenderedImage.ToByteArray();
return SKBitmap.Decode(byteArray);
return new IntermediateRenderResult
{
Automask = ((IBinaryMaskFactory)matrixAbstractFactory.GetFactory<bool>())
.Create(10, 20, 0),
};
}
}

View File

@ -1,5 +1,7 @@
using Domain;
using Domain.Interfaces;
using Make3.CommonTypes.Interfaces.Matrices;
using Make3.CommonTypes.Matrices;
using Make3.RenderServer;
var builder = WebApplication.CreateBuilder(args);
@ -8,6 +10,7 @@ var builder = WebApplication.CreateBuilder(args);
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddScoped<IMatrixAbstractFactory, MatrixAbstractFactory>();
builder.Services.AddScoped<IRenderManager, RenderManager>();
// builder.Services.AddGrpc();

View File

@ -1,7 +1,10 @@
using Domain;
using Domain.Interfaces;
using Domain.Project;
using ImageMagick;
using Make3.CommonTypes.Interfaces;
using Make3.CommonTypes.Interfaces.Matrices;
using Make3.RenderServer.Layers;
using SkiaSharp;
namespace Make3.RenderServer;
@ -18,44 +21,101 @@ public class TestProjectBackgroundService : BackgroundService
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var dir = @"C:\Users\Ko12A\OneDrive\Изображения";
var image1 = OpenImage(Path.Combine(dir, "01_gettyimages_488111026_resized.jpg"));
var image2 = OpenImage(Path.Combine(dir, "kisspng-bmp-file-for.bmp"));
var image3 = OpenImage(Path.Combine(dir, "Zrzut ekranu 2021-07-20 164131.png"));
var dir = @"C:\DOTProjects\ImagesForNewM3";
var image1 = new MagickImage(Path.Combine(dir, "CrystalTest1_2083x2083_16bit.png"));//"Sphere16b-0.png"));
var image2 = new MagickImage(Path.Combine(dir, "Crystal_Mask_2083x2083.png"));
var image3 = new MagickImage(Path.Combine(dir, "AMask.png"));
using var scope = _serviceProvider.CreateScope();
var matrixAbstractFactory = scope.ServiceProvider.GetRequiredService<IMatrixAbstractFactory>();
var project = new Project
{
Id = Guid.NewGuid(),
HardwareSettings = new HardwareSettings
{
Ppu = 76.8d,
UnitSize = 12,
IlluminationLevels = new IlluminationLevels(14, 110, 222),
MatrixResolution = new Resolution(1920, 1080),
FrameResolution = new Resolution(1536, 1024),
FrameSize = new Size(240, 160, SizeUnit.um),
},
Height = Convert.ToUInt32(image1.Width),
Width = Convert.ToUInt32(image2.Width),
Layers = [
new TestLayer(_testLaterGrpcClient)
{
Order = 0,
Image = image1,
OpticalSchema = OpticalSchema.Sp11,
},
new TestLayer(_testLaterGrpcClient)
{
Order = 1,
Image = image2,
Mask = image3,
InvertMask = false,
OpticalSchema = OpticalSchema.Sp11,
},
],
Width = Convert.ToUInt32(image1.Height),
};
using var scope = _serviceProvider.CreateScope();
project.Layers =
[
new TestLayer(_testLaterGrpcClient, matrixAbstractFactory)
{
Order = 0,
Image = image1,
Mask = ConvertImageToMask(matrixAbstractFactory, image2),
HologramWidth = 25.0,
HologramHeight = 25.0,
HardwareSettings = project.HardwareSettings,
OpticalSchema = OpticalSchema.Sp11,
InvertMask = false,
DifractionAngle = 33.0,
PosterizeResult = false,
InvertProfile = false,
InvertHorizontalAngle = false,
DirectAngle = 90.0,
AngleOfView = 180.0,
ObjectAngle = 80.0,//90.0 + 10,//35,
HorizontalRoughness = 0.0,
VerticalRoughness = 0.0,
},
new TestLayer(_testLaterGrpcClient, matrixAbstractFactory)
{
Order = 1,
Image = image2,
Mask = ConvertImageToMask(matrixAbstractFactory, image3),
InvertMask = false,
OpticalSchema = OpticalSchema.Sp11,
},
];
var renderManager = scope.ServiceProvider.GetRequiredService<IRenderManager>();
var renderId = await renderManager.StartRender(project);
}
private SKBitmap OpenImage(string filename)
{
using SKBitmap bitmap = SKBitmap.Decode(filename);
return bitmap.Copy();
}
private IBinaryMask ConvertImageToMask(IMatrixAbstractFactory matrixAbstractFactory, MagickImage image)
{
var binaryMaskFactory = (IBinaryMaskFactory)matrixAbstractFactory.GetFactory<bool>();
var result = binaryMaskFactory.Create((int)image.Width, (int)image.Height, 0);
using var pixels = image.GetPixels();
// for (uint y = 0; y < image.Height; y++)
// {
// for (uint x = 0; x < image.Width; x++)
// {
// var pixel = image.GetPixels().GetPixel((int)x, (int)y);
// var red = pixel.ToColor()?.R ?? 0;
// // var blue = pixel.ToColor()?.B ?? 0;
// // var green = pixel.ToColor()?.G ?? 0;
// var intensity = red;// + blue + green;
// if (intensity == 0)
// {
// result.MakeOpaque(x, y);
// }
// }
// } /// 13 sec - 3 Ch 10sec - 1 ch
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x < image.Width; x++)
{
var intensity = pixels.GetPixel(x, y).ToColor().R;
//+ pixels.GetPixel(x, y).ToColor().G + pixels.GetPixel(x, y).ToColor().B;
if (intensity == 0)
{
result.MakeOpaque(x, y);
}
}
} /// 13sec - 3ch, 5 sec - 1 ch
var p = result.GetBlackCellsPercentage();
return result;
}
}