Не знаю
This commit is contained in:
parent
2f721d6514
commit
4f4b80255d
@ -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; } = [];
|
||||
}
|
||||
@ -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>
|
||||
|
||||
28
Domain/Entities/BinaryMask2.cs
Normal file
28
Domain/Entities/BinaryMask2.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
12
Domain/Entities/IntermediateRenderResult.cs
Normal file
12
Domain/Entities/IntermediateRenderResult.cs
Normal 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; }
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
11
Domain/Project/HardwareSettings.cs
Normal file
11
Domain/Project/HardwareSettings.cs
Normal 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; }
|
||||
}
|
||||
3
Domain/Project/IlluminationLevels.cs
Normal file
3
Domain/Project/IlluminationLevels.cs
Normal file
@ -0,0 +1,3 @@
|
||||
namespace Domain.Project;
|
||||
|
||||
public record IlluminationLevels(byte Zero, byte LinearLow, byte LinearHigh);
|
||||
@ -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; }
|
||||
}
|
||||
3
Domain/Project/Resolution.cs
Normal file
3
Domain/Project/Resolution.cs
Normal file
@ -0,0 +1,3 @@
|
||||
namespace Domain.Project;
|
||||
|
||||
public record Resolution(uint X, uint Y);
|
||||
9
Domain/Project/Size.cs
Normal file
9
Domain/Project/Size.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Domain.Project;
|
||||
|
||||
public record Size(decimal Width, decimal Height, SizeUnit Unit);
|
||||
|
||||
public enum SizeUnit
|
||||
{
|
||||
um,
|
||||
mm
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Domain;
|
||||
|
||||
public class RenderResult
|
||||
|
||||
117
Make3.RenderServer/Grpc/GrpcConverters.cs
Normal file
117
Make3.RenderServer/Grpc/GrpcConverters.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
@ -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),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user