Не знаю

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; namespace Domain;
@ -10,6 +12,10 @@ public class BigFrameLayerRenderResult
public uint FrameSizeY { get; set; } 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; } = []; public List<ExpIniFileGenerator.FrameExpInfo> FrameInfos { get; set; } = [];
} }

View File

@ -8,7 +8,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <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> </ItemGroup>
</Project> </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; namespace Domain.Interfaces;
public interface ILayer public interface ILayer
{ {
public uint Order { get; } public uint Order { get; }
public OpticalSchema OpticalSchema { get; } public OpticalSchema OpticalSchema { get; }
public SKBitmap Image { get; } public MagickImage Image { get; }
public SKBitmap? Mask { get; } public IBinaryMask? Mask { get; }
public bool InvertMask { get; } public bool InvertMask { get; }
public Task Prerender(); 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 interface IRenderManager
{ {
public Task<Guid> StartRender(Project project); public Task<Guid> StartRender(Project.Project project);
public Task StopRender(Guid renderId); public Task StopRender(Guid renderId);
IEnumerable<Guid> GetActiveRenders(); 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; using Domain.Interfaces;
namespace Domain; namespace Domain.Project;
public class Project public class Project
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
public IEnumerable<ILayer> Layers { get; set; } = []; public IEnumerable<ILayer> Layers { get; set; } = [];
public uint Width { get; set; } public uint Width { get; set; }
public uint Height { 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 System.Threading.Channels;
using Domain.Interfaces; using Domain.Interfaces;
using Domain.RenderPart; using Domain.RenderPart;
using Make3.CommonTypes.Interfaces.Matrices;
//using Make3.CommonTypes.BinaryMask;
namespace Domain; namespace Domain;
@ -15,9 +18,13 @@ public class Render
private readonly bool _useBigFrames = true; private readonly bool _useBigFrames = true;
private readonly CancellationTokenSource _cancellationTokenSource = new(); 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(); Id = Guid.NewGuid();
ProjectId = project.Id; ProjectId = project.Id;
_width = project.Width; _width = project.Width;
@ -56,7 +63,7 @@ public class Render
for (uint x = 0; x < _width; x += bigFrameWidth) for (uint x = 0; x < _width; x += bigFrameWidth)
{ {
uint currentBigFrameWidth = Math.Min(bigFrameWidth, _width - x); 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); await channel.Writer.WriteAsync(bigFrameRender);
} }
} }

View File

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

View File

@ -1,5 +1,7 @@
using Domain.Interfaces; using Domain.Interfaces;
using SkiaSharp; using Make3.CommonTypes.Interfaces;
using Make3.CommonTypes.Interfaces.Matrices;
//using Make3.CommonTypes.BinaryMask;
namespace Domain.RenderPart; namespace Domain.RenderPart;
@ -7,8 +9,9 @@ public class BigFrameRender : RenderPartBase
{ {
private readonly uint _bigFrameWidth; private readonly uint _bigFrameWidth;
private readonly uint _bigFrameHeight; private readonly uint _bigFrameHeight;
public BigFrameRender(IEnumerable<ILayer> layers, uint row, uint col, uint bigFrameWidth, uint bigFrameHeight, Guid renderId) : public BigFrameRender(IMatrixAbstractFactory matrixAbstractFactory, IEnumerable<ILayer> layers,
base(layers, row, col, renderId) uint row, uint col, uint bigFrameWidth, uint bigFrameHeight, Guid renderId) :
base(matrixAbstractFactory, layers, row, col, renderId)
{ {
_bigFrameWidth = bigFrameWidth; _bigFrameWidth = bigFrameWidth;
_bigFrameHeight = bigFrameHeight; _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) 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() 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; return result;
} }

View File

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

View File

@ -1,3 +1,5 @@
using Domain.Entities;
namespace Domain; namespace Domain;
public class RenderResult 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"; option csharp_namespace = "LayerClients";
service TestLayer { service TestLayer {
rpc Prerender (PrerenderRequest) returns (PrerenderResponse); rpc StreamPrerenderData (stream PrerenderRequest) returns (stream PrerenderResponse);
rpc Render (RenderRequest) returns (RenderResponse); rpc Render (RenderRequest) returns (RenderResponse);
} }
message PrerenderRequest { message PrerenderRequest {
string optical_schema_data = 1; ProjectData project_data = 1;
bytes mask = 2; HardwareData hardware_data = 2;
bytes image = 3; string optical_schema_data = 3;
bool invert_mask = 4; 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 { message PrerenderResponse {
string status = 1; repeated MatrixRow grating_period = 1;
repeated MatrixRow test_matrix = 2; // Представляем матрицу через строки repeated MatrixRow angles_horizontal = 2;
repeated MatrixRow phases = 3;
repeated MatrixRow saturation = 4;
} }
message MatrixRow { message MatrixRow {
repeated double values = 1; // Значения одной строки матрицы repeated double values = 1;
} }
message RenderRequest { message RenderRequest {

View File

@ -1,62 +1,184 @@
using Domain; using Domain;
using Domain.Entities;
using Domain.Interfaces; using Domain.Interfaces;
using Domain.Project;
using Google.Protobuf; using Google.Protobuf;
using Grpc.Core;
using ImageMagick;
using LayerClients; 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; 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 uint Order { get; init; }
public OpticalSchema OpticalSchema { get; init; } public OpticalSchema OpticalSchema { get; init; }
public SKBitmap? Mask { get; init; } public IBinaryMask? Mask { get; init; }
public required SKBitmap Image { get; init; } public required MagickImage Image { get; init; }
public bool InvertMask { 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 LayerClients.TestLayer.TestLayerClient _grpcClient = grpcClient;
private readonly IMatrixAbstractFactory _matrixAbstractFactory = matrixAbstractFactory;
public async Task Prerender() public async Task Prerender()
{ {
using var imageData = Image.Encode(SKEncodedImageFormat.Png, 100); var imageData = Image.ToByteArray(MagickFormat.Png);
using var maskData = Mask?.Encode(SKEncodedImageFormat.Png, 100); using var call = _grpcClient.StreamPrerenderData();
var request = new PrerenderRequest await GrpcConverters.SendStream(new MemoryStream(imageData), async (imageChunk) =>
{ {
OpticalSchemaData = OpticalSchema.ToString(), var request = MakePrerenderRequest();
Image = ByteString.CopyFrom(imageData.Span), request.Image = imageChunk;
}; await call.RequestStream.WriteAsync(request);
if (maskData != null) });
if (Mask != null)
{ {
request.Mask = ByteString.CopyFrom(maskData.Span); await GrpcConverters.SendStream(Mask.GetStream(), async (maskChunk) =>
request.InvertMask = InvertMask; {
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); var imageData = Image.ToByteArray(MagickFormat.Png);
using var maskData = Mask?.Encode(SKEncodedImageFormat.Png, 100); // var maskData = Mask?.ToByteArray(MagickFormat.Png);
using var automaskData = automask?.Encode(SKEncodedImageFormat.Png, 100); IBinaryMask? maskData = null;
// using var automaskData = automask?.Encode(SKEncodedImageFormat.Png, 100);
byte[]? automaskData = null;
var request = new RenderRequest var request = new RenderRequest
{ {
X = x, X = x,
Y = y, Y = y,
FrameWidth = frameWidth, FrameWidth = frameWidth,
FrameHeight = frameHeight, FrameHeight = frameHeight,
Image = ByteString.CopyFrom(imageData.Span), Image = ByteString.CopyFrom(imageData),
// Automask = ByteString.CopyFrom(imageData.Span), // Automask = ByteString.CopyFrom(imageData.Span),
}; };
if (maskData != null) if (maskData != null)
{ {
request.Mask = ByteString.CopyFrom(maskData.Span); // request.Mask = ByteString.CopyFrom(maskData);
request.InvertMask = InvertMask; // 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 response = await _grpcClient.RenderAsync(request);
var byteArray = response.RenderedImage.ToByteArray(); 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;
using Domain.Interfaces; using Domain.Interfaces;
using Make3.CommonTypes.Interfaces.Matrices;
using Make3.CommonTypes.Matrices;
using Make3.RenderServer; using Make3.RenderServer;
var builder = WebApplication.CreateBuilder(args); 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 // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi(); builder.Services.AddOpenApi();
builder.Services.AddScoped<IMatrixAbstractFactory, MatrixAbstractFactory>();
builder.Services.AddScoped<IRenderManager, RenderManager>(); builder.Services.AddScoped<IRenderManager, RenderManager>();
// builder.Services.AddGrpc(); // builder.Services.AddGrpc();

View File

@ -1,7 +1,10 @@
using Domain; using Domain;
using Domain.Interfaces; using Domain.Interfaces;
using Domain.Project;
using ImageMagick;
using Make3.CommonTypes.Interfaces;
using Make3.CommonTypes.Interfaces.Matrices;
using Make3.RenderServer.Layers; using Make3.RenderServer.Layers;
using SkiaSharp;
namespace Make3.RenderServer; namespace Make3.RenderServer;
@ -18,44 +21,101 @@ public class TestProjectBackgroundService : BackgroundService
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
var dir = @"C:\Users\Ko12A\OneDrive\Изображения"; var dir = @"C:\DOTProjects\ImagesForNewM3";
var image1 = OpenImage(Path.Combine(dir, "01_gettyimages_488111026_resized.jpg")); var image1 = new MagickImage(Path.Combine(dir, "CrystalTest1_2083x2083_16bit.png"));//"Sphere16b-0.png"));
var image2 = OpenImage(Path.Combine(dir, "kisspng-bmp-file-for.bmp")); var image2 = new MagickImage(Path.Combine(dir, "Crystal_Mask_2083x2083.png"));
var image3 = OpenImage(Path.Combine(dir, "Zrzut ekranu 2021-07-20 164131.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 var project = new Project
{ {
Id = Guid.NewGuid(), 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), Height = Convert.ToUInt32(image1.Width),
Width = Convert.ToUInt32(image2.Width), Width = Convert.ToUInt32(image1.Height),
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,
},
],
}; };
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 renderManager = scope.ServiceProvider.GetRequiredService<IRenderManager>();
var renderId = await renderManager.StartRender(project); 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;
}
} }