Не знаю
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;
|
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; } = [];
|
||||||
}
|
}
|
||||||
@ -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>
|
||||||
|
|||||||
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;
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
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;
|
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; }
|
||||||
}
|
}
|
||||||
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 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
namespace Domain;
|
namespace Domain;
|
||||||
|
|
||||||
public class RenderResult
|
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";
|
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 {
|
||||||
|
|||||||
@ -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),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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();
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user