mirror of
https://github.com/DarthAffe/ScreenCapture.NET.git
synced 2025-12-12 13:28:35 +00:00
WIP (not working!) First draft for generic color format handling
This commit is contained in:
parent
af401448e7
commit
2cc8a9b6ac
@ -185,11 +185,11 @@ public sealed class DX11ScreenCapture : IScreenCapture
|
|||||||
|
|
||||||
MappedSubresource mapSource = _context.Map(stagingTexture, 0, MapMode.Read, MapFlags.None);
|
MappedSubresource mapSource = _context.Map(stagingTexture, 0, MapMode.Read, MapFlags.None);
|
||||||
IntPtr sourcePtr = mapSource.DataPointer;
|
IntPtr sourcePtr = mapSource.DataPointer;
|
||||||
lock (captureZone.Buffer)
|
lock (captureZone.PixelBuffer)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < captureZone.Height; y++)
|
for (int y = 0; y < captureZone.Height; y++)
|
||||||
{
|
{
|
||||||
Marshal.Copy(sourcePtr, captureZone.Buffer, y * captureZone.Stride, captureZone.Stride);
|
Marshal.Copy(sourcePtr, captureZone.PixelBuffer.Raw, y * captureZone.Stride, captureZone.Stride);
|
||||||
sourcePtr += mapSource.RowPitch;
|
sourcePtr += mapSource.RowPitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,8 +209,7 @@ public sealed class DX11ScreenCapture : IScreenCapture
|
|||||||
int unscaledHeight = height;
|
int unscaledHeight = height;
|
||||||
(width, height) = CalculateScaledSize(unscaledWidth, unscaledHeight, downscaleLevel);
|
(width, height) = CalculateScaledSize(unscaledWidth, unscaledHeight, downscaleLevel);
|
||||||
|
|
||||||
byte[] buffer = new byte[width * height * BPP];
|
PixelBuffer buffer = new PixelBuffer<ColorBGRA8>(width, height);
|
||||||
|
|
||||||
CaptureZone captureZone = new(_indexCounter++, x, y, width, height, BPP, downscaleLevel, unscaledWidth, unscaledHeight, buffer);
|
CaptureZone captureZone = new(_indexCounter++, x, y, width, height, BPP, downscaleLevel, unscaledWidth, unscaledHeight, buffer);
|
||||||
lock (_captureZones)
|
lock (_captureZones)
|
||||||
InitializeCaptureZone(captureZone);
|
InitializeCaptureZone(captureZone);
|
||||||
@ -268,7 +267,7 @@ public sealed class DX11ScreenCapture : IScreenCapture
|
|||||||
captureZone.Width = newWidth;
|
captureZone.Width = newWidth;
|
||||||
captureZone.Height = newHeight;
|
captureZone.Height = newHeight;
|
||||||
captureZone.DownscaleLevel = newDownscaleLevel;
|
captureZone.DownscaleLevel = newDownscaleLevel;
|
||||||
captureZone.Buffer = new byte[newWidth * newHeight * BPP];
|
captureZone.PixelBuffer = new PixelBuffer<ColorBGRA8>(newWidth, newHeight);
|
||||||
|
|
||||||
InitializeCaptureZone(captureZone);
|
InitializeCaptureZone(captureZone);
|
||||||
}
|
}
|
||||||
@ -305,18 +304,18 @@ public sealed class DX11ScreenCapture : IScreenCapture
|
|||||||
private void InitializeCaptureZone(in CaptureZone captureZone)
|
private void InitializeCaptureZone(in CaptureZone captureZone)
|
||||||
{
|
{
|
||||||
Texture2DDescription stagingTextureDesc = new()
|
Texture2DDescription stagingTextureDesc = new()
|
||||||
{
|
{
|
||||||
CpuAccessFlags = CpuAccessFlags.Read,
|
CpuAccessFlags = CpuAccessFlags.Read,
|
||||||
BindFlags = BindFlags.None,
|
BindFlags = BindFlags.None,
|
||||||
Format = Format.B8G8R8A8_UNorm,
|
Format = Format.B8G8R8A8_UNorm,
|
||||||
Width = captureZone.Width,
|
Width = captureZone.Width,
|
||||||
Height = captureZone.Height,
|
Height = captureZone.Height,
|
||||||
OptionFlags = ResourceOptionFlags.None,
|
OptionFlags = ResourceOptionFlags.None,
|
||||||
MipLevels = 1,
|
MipLevels = 1,
|
||||||
ArraySize = 1,
|
ArraySize = 1,
|
||||||
SampleDescription = { Count = 1, Quality = 0 },
|
SampleDescription = { Count = 1, Quality = 0 },
|
||||||
Usage = ResourceUsage.Staging
|
Usage = ResourceUsage.Staging
|
||||||
};
|
};
|
||||||
ID3D11Texture2D stagingTexture = _device!.CreateTexture2D(stagingTextureDesc);
|
ID3D11Texture2D stagingTexture = _device!.CreateTexture2D(stagingTextureDesc);
|
||||||
|
|
||||||
ID3D11Texture2D? scalingTexture = null;
|
ID3D11Texture2D? scalingTexture = null;
|
||||||
@ -324,18 +323,18 @@ public sealed class DX11ScreenCapture : IScreenCapture
|
|||||||
if (captureZone.DownscaleLevel > 0)
|
if (captureZone.DownscaleLevel > 0)
|
||||||
{
|
{
|
||||||
Texture2DDescription scalingTextureDesc = new()
|
Texture2DDescription scalingTextureDesc = new()
|
||||||
{
|
{
|
||||||
CpuAccessFlags = CpuAccessFlags.None,
|
CpuAccessFlags = CpuAccessFlags.None,
|
||||||
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
|
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
|
||||||
Format = Format.B8G8R8A8_UNorm,
|
Format = Format.B8G8R8A8_UNorm,
|
||||||
Width = captureZone.UnscaledWidth,
|
Width = captureZone.UnscaledWidth,
|
||||||
Height = captureZone.UnscaledHeight,
|
Height = captureZone.UnscaledHeight,
|
||||||
OptionFlags = ResourceOptionFlags.GenerateMips,
|
OptionFlags = ResourceOptionFlags.GenerateMips,
|
||||||
MipLevels = captureZone.DownscaleLevel + 1,
|
MipLevels = captureZone.DownscaleLevel + 1,
|
||||||
ArraySize = 1,
|
ArraySize = 1,
|
||||||
SampleDescription = { Count = 1, Quality = 0 },
|
SampleDescription = { Count = 1, Quality = 0 },
|
||||||
Usage = ResourceUsage.Default
|
Usage = ResourceUsage.Default
|
||||||
};
|
};
|
||||||
scalingTexture = _device!.CreateTexture2D(scalingTextureDesc);
|
scalingTexture = _device!.CreateTexture2D(scalingTextureDesc);
|
||||||
scalingTextureView = _device.CreateShaderResourceView(scalingTexture);
|
scalingTextureView = _device.CreateShaderResourceView(scalingTexture);
|
||||||
}
|
}
|
||||||
@ -362,18 +361,18 @@ public sealed class DX11ScreenCapture : IScreenCapture
|
|||||||
using IDXGIOutput5 output = _output.QueryInterface<IDXGIOutput5>();
|
using IDXGIOutput5 output = _output.QueryInterface<IDXGIOutput5>();
|
||||||
|
|
||||||
Texture2DDescription captureTextureDesc = new()
|
Texture2DDescription captureTextureDesc = new()
|
||||||
{
|
{
|
||||||
CpuAccessFlags = CpuAccessFlags.None,
|
CpuAccessFlags = CpuAccessFlags.None,
|
||||||
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
|
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
|
||||||
Format = Format.B8G8R8A8_UNorm,
|
Format = Format.B8G8R8A8_UNorm,
|
||||||
Width = Display.Width,
|
Width = Display.Width,
|
||||||
Height = Display.Height,
|
Height = Display.Height,
|
||||||
OptionFlags = ResourceOptionFlags.None,
|
OptionFlags = ResourceOptionFlags.None,
|
||||||
MipLevels = 1,
|
MipLevels = 1,
|
||||||
ArraySize = 1,
|
ArraySize = 1,
|
||||||
SampleDescription = { Count = 1, Quality = 0 },
|
SampleDescription = { Count = 1, Quality = 0 },
|
||||||
Usage = ResourceUsage.Default
|
Usage = ResourceUsage.Default
|
||||||
};
|
};
|
||||||
_captureTexture = _device.CreateTexture2D(captureTextureDesc);
|
_captureTexture = _device.CreateTexture2D(captureTextureDesc);
|
||||||
|
|
||||||
lock (_captureZones)
|
lock (_captureZones)
|
||||||
@ -383,7 +382,7 @@ public sealed class DX11ScreenCapture : IScreenCapture
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_useNewDuplicationAdapter)
|
if (_useNewDuplicationAdapter)
|
||||||
_duplicatedOutput = output.DuplicateOutput1(_device, Format.B8G8R8A8_UNorm); // DarthAffe 27.02.2021: This prepares for the use of 10bit color depth
|
_duplicatedOutput = output.DuplicateOutput1(_device, new[] { Format.B8G8R8A8_UNorm }); // DarthAffe 27.02.2021: This prepares for the use of 10bit color depth
|
||||||
else
|
else
|
||||||
_duplicatedOutput = output.DuplicateOutput(_device);
|
_duplicatedOutput = output.DuplicateOutput(_device);
|
||||||
}
|
}
|
||||||
|
|||||||
39
ScreenCapture.NET/Helper/MathHelper.cs
Normal file
39
ScreenCapture.NET/Helper/MathHelper.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace ScreenCapture.NET;
|
||||||
|
|
||||||
|
public static class MathHelper
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float Clamp(this float value, float min, float max)
|
||||||
|
{
|
||||||
|
// ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10%
|
||||||
|
if (value < min) return min;
|
||||||
|
if (value > max) return max;
|
||||||
|
return value;
|
||||||
|
// ReSharper restore ConvertIfStatementToReturnStatement
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a normalized float value in the range [0..1] to a byte [0..255].
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="percentage">The normalized float value to convert.</param>
|
||||||
|
/// <returns>The byte value.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static byte GetByteValueFromPercentage(this float percentage)
|
||||||
|
{
|
||||||
|
if (float.IsNaN(percentage)) return 0;
|
||||||
|
|
||||||
|
percentage = percentage.Clamp(0, 1.0f);
|
||||||
|
return (byte)(percentage >= 1.0f ? 255 : percentage * 256.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a byte value [0..255] to a normalized float value in the range [0..1].
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The byte value to convert.</param>
|
||||||
|
/// <returns>The normalized float value.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float GetPercentageFromByteValue(this byte value)
|
||||||
|
=> value == 255 ? 1.0f : (value / 256.0f);
|
||||||
|
}
|
||||||
@ -81,7 +81,7 @@ public sealed class BlackBarDetection
|
|||||||
int stride = _captureZone.Stride;
|
int stride = _captureZone.Stride;
|
||||||
for (int row = 0; row < _captureZone.Height; row++)
|
for (int row = 0; row < _captureZone.Height; row++)
|
||||||
{
|
{
|
||||||
Span<byte> data = new(_captureZone.Buffer, row * stride, stride);
|
Span<byte> data = new(_captureZone.PixelBuffer.Raw, row * stride, stride);
|
||||||
for (int i = 0; i < data.Length; i += 4)
|
for (int i = 0; i < data.Length; i += 4)
|
||||||
if ((data[i] > threshold) || (data[i + 1] > threshold) || (data[i + 2] > threshold))
|
if ((data[i] > threshold) || (data[i + 1] > threshold) || (data[i + 2] > threshold))
|
||||||
return row;
|
return row;
|
||||||
@ -96,7 +96,7 @@ public sealed class BlackBarDetection
|
|||||||
int stride = _captureZone.Stride;
|
int stride = _captureZone.Stride;
|
||||||
for (int row = _captureZone.Height - 1; row >= 0; row--)
|
for (int row = _captureZone.Height - 1; row >= 0; row--)
|
||||||
{
|
{
|
||||||
Span<byte> data = new(_captureZone.Buffer, row * stride, stride);
|
Span<byte> data = new(_captureZone.PixelBuffer.Raw, row * stride, stride);
|
||||||
for (int i = 0; i < data.Length; i += 4)
|
for (int i = 0; i < data.Length; i += 4)
|
||||||
if ((data[i] > threshold) || (data[i + 1] > threshold) || (data[i + 2] > threshold))
|
if ((data[i] > threshold) || (data[i + 1] > threshold) || (data[i + 2] > threshold))
|
||||||
return (_captureZone.Height - 1) - row;
|
return (_captureZone.Height - 1) - row;
|
||||||
@ -109,7 +109,7 @@ public sealed class BlackBarDetection
|
|||||||
{
|
{
|
||||||
int threshold = Threshold;
|
int threshold = Threshold;
|
||||||
int stride = _captureZone.Stride;
|
int stride = _captureZone.Stride;
|
||||||
byte[] buffer = _captureZone.Buffer;
|
byte[] buffer = _captureZone.PixelBuffer.Raw;
|
||||||
for (int column = 0; column < _captureZone.Width; column++)
|
for (int column = 0; column < _captureZone.Width; column++)
|
||||||
for (int row = 0; row < _captureZone.Height; row++)
|
for (int row = 0; row < _captureZone.Height; row++)
|
||||||
{
|
{
|
||||||
@ -125,7 +125,7 @@ public sealed class BlackBarDetection
|
|||||||
{
|
{
|
||||||
int threshold = Threshold;
|
int threshold = Threshold;
|
||||||
int stride = _captureZone.Stride;
|
int stride = _captureZone.Stride;
|
||||||
byte[] buffer = _captureZone.Buffer;
|
byte[] buffer = _captureZone.PixelBuffer.Raw;
|
||||||
for (int column = _captureZone.Width - 1; column >= 0; column--)
|
for (int column = _captureZone.Width - 1; column >= 0; column--)
|
||||||
for (int row = 0; row < _captureZone.Height; row++)
|
for (int row = 0; row < _captureZone.Height; row++)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -19,37 +19,58 @@ public sealed class CaptureZone
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the x-location of the region on the screen.
|
/// Gets the x-location of the region on the screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int X { get; internal set; }
|
/// <remarks>
|
||||||
|
/// Should only be set inside of ScreenCaptures!
|
||||||
|
/// </remarks>
|
||||||
|
public int X { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the y-location of the region on the screen.
|
/// Gets the y-location of the region on the screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Y { get; internal set; }
|
/// <remarks>
|
||||||
|
/// Should only be set inside of ScreenCaptures!
|
||||||
|
/// </remarks>
|
||||||
|
public int Y { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the width of the captured region.
|
/// Gets the width of the captured region.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Width { get; internal set; }
|
/// <remarks>
|
||||||
|
/// Should only be set inside of ScreenCaptures!
|
||||||
|
/// </remarks>
|
||||||
|
public int Width { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the height of the captured region.
|
/// Gets the height of the captured region.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Height { get; internal set; }
|
/// <remarks>
|
||||||
|
/// Should only be set inside of ScreenCaptures!
|
||||||
|
/// </remarks>
|
||||||
|
public int Height { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the level of downscaling applied to the image of this region before copying to local memory. The calculation is (width and height)/2^downscaleLevel.
|
/// Gets the level of downscaling applied to the image of this region before copying to local memory. The calculation is (width and height)/2^downscaleLevel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int DownscaleLevel { get; internal set; }
|
/// <remarks>
|
||||||
|
/// Should only be set inside of ScreenCaptures!
|
||||||
|
/// </remarks>
|
||||||
|
public int DownscaleLevel { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the original width of the region (this equals <see cref="Width"/> if <see cref="DownscaleLevel"/> is 0).
|
/// Gets the original width of the region (this equals <see cref="Width"/> if <see cref="DownscaleLevel"/> is 0).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int UnscaledWidth { get; internal set; }
|
/// <remarks>
|
||||||
|
/// Should only be set inside of ScreenCaptures!
|
||||||
|
/// </remarks>
|
||||||
|
public int UnscaledWidth { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the original height of the region (this equals <see cref="Height"/> if <see cref="DownscaleLevel"/> is 0).
|
/// Gets the original height of the region (this equals <see cref="Height"/> if <see cref="DownscaleLevel"/> is 0).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int UnscaledHeight { get; internal set; }
|
/// <remarks>
|
||||||
|
/// Should only be set inside of ScreenCaptures!
|
||||||
|
/// </remarks>
|
||||||
|
public int UnscaledHeight { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the amount of bytes per pixel in the image (most likely 3 [RGB] or 4 [ARGB]).
|
/// Gets the amount of bytes per pixel in the image (most likely 3 [RGB] or 4 [ARGB]).
|
||||||
@ -64,7 +85,10 @@ public sealed class CaptureZone
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the buffer containing the image data. Format depends on the specific capture but is most likely BGRA32.
|
/// Gets the buffer containing the image data. Format depends on the specific capture but is most likely BGRA32.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] Buffer { get; internal set; }
|
/// <remarks>
|
||||||
|
/// Should only be set inside of ScreenCaptures!
|
||||||
|
/// </remarks>
|
||||||
|
public PixelBuffer PixelBuffer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the config for black-bar detection.
|
/// Gets the config for black-bar detection.
|
||||||
@ -107,7 +131,7 @@ public sealed class CaptureZone
|
|||||||
/// <param name="unscaledWidth">The original width of the region.</param>
|
/// <param name="unscaledWidth">The original width of the region.</param>
|
||||||
/// <param name="unscaledHeight">The original height of the region</param>
|
/// <param name="unscaledHeight">The original height of the region</param>
|
||||||
/// <param name="buffer">The buffer containing the image data.</param>
|
/// <param name="buffer">The buffer containing the image data.</param>
|
||||||
internal CaptureZone(int id, int x, int y, int width, int height, int bytesPerPixel, int downscaleLevel, int unscaledWidth, int unscaledHeight, byte[] buffer)
|
public CaptureZone(int id, int x, int y, int width, int height, int bytesPerPixel, int downscaleLevel, int unscaledWidth, int unscaledHeight, PixelBuffer buffer)
|
||||||
{
|
{
|
||||||
this.Id = id;
|
this.Id = id;
|
||||||
this.X = x;
|
this.X = x;
|
||||||
@ -118,7 +142,7 @@ public sealed class CaptureZone
|
|||||||
this.UnscaledWidth = unscaledWidth;
|
this.UnscaledWidth = unscaledWidth;
|
||||||
this.UnscaledHeight = unscaledHeight;
|
this.UnscaledHeight = unscaledHeight;
|
||||||
this.DownscaleLevel = downscaleLevel;
|
this.DownscaleLevel = downscaleLevel;
|
||||||
this.Buffer = buffer;
|
this.PixelBuffer = buffer;
|
||||||
|
|
||||||
BlackBars = new BlackBarDetection(this);
|
BlackBars = new BlackBarDetection(this);
|
||||||
}
|
}
|
||||||
|
|||||||
41
ScreenCapture.NET/Model/Colors/ColorBGRA8.cs
Normal file
41
ScreenCapture.NET/Model/Colors/ColorBGRA8.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace ScreenCapture.NET;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public readonly struct ColorBGRA8 : IColor
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private readonly byte _r;
|
||||||
|
private readonly byte _g;
|
||||||
|
private readonly byte _b;
|
||||||
|
private readonly byte _a;
|
||||||
|
|
||||||
|
public byte A => _a;
|
||||||
|
public byte R => _r;
|
||||||
|
public byte G => _g;
|
||||||
|
public byte B => _b;
|
||||||
|
|
||||||
|
public float sA => _a.GetPercentageFromByteValue();
|
||||||
|
public float sR => _r.GetPercentageFromByteValue();
|
||||||
|
public float sG => _g.GetPercentageFromByteValue();
|
||||||
|
public float sB => _b.GetPercentageFromByteValue();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public ColorBGRA8()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public ColorBGRA8(byte r, byte g, byte b, byte a)
|
||||||
|
{
|
||||||
|
this._r = r;
|
||||||
|
this._g = g;
|
||||||
|
this._b = b;
|
||||||
|
this._a = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
14
ScreenCapture.NET/Model/Colors/IColor.cs
Normal file
14
ScreenCapture.NET/Model/Colors/IColor.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace ScreenCapture.NET;
|
||||||
|
|
||||||
|
public interface IColor
|
||||||
|
{
|
||||||
|
byte A { get; }
|
||||||
|
byte R { get; }
|
||||||
|
byte G { get; }
|
||||||
|
byte B { get; }
|
||||||
|
|
||||||
|
float sA { get; }
|
||||||
|
float sR { get; }
|
||||||
|
float sG { get; }
|
||||||
|
float sB { get; }
|
||||||
|
}
|
||||||
56
ScreenCapture.NET/Model/PixelBuffer.cs
Normal file
56
ScreenCapture.NET/Model/PixelBuffer.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using CommunityToolkit.HighPerformance;
|
||||||
|
|
||||||
|
namespace ScreenCapture.NET;
|
||||||
|
|
||||||
|
public abstract class PixelBuffer
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
public byte[] Raw { get; }
|
||||||
|
|
||||||
|
public abstract ReadOnlySpan2D<IColor> Pixels { get; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
protected PixelBuffer(byte[] buffer)
|
||||||
|
{
|
||||||
|
this.Raw = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class PixelBuffer<TColor> : PixelBuffer
|
||||||
|
where TColor : unmanaged, IColor
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private readonly int _width;
|
||||||
|
private readonly int _height;
|
||||||
|
|
||||||
|
public override unsafe ReadOnlySpan2D<IColor> Pixels
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
TColor @ref = MemoryMarshal.AsRef<TColor>(Raw);
|
||||||
|
return new ReadOnlySpan2D<IColor>(Unsafe.AsPointer(ref @ref), _height, _width, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public PixelBuffer(int width, int height)
|
||||||
|
: base(new byte[width * height * Marshal.SizeOf<TColor>()])
|
||||||
|
{
|
||||||
|
this._width = width;
|
||||||
|
this._height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0;net5.0</TargetFrameworks>
|
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
@ -31,9 +31,9 @@
|
|||||||
- Fixed ambiguous equals in Display
|
- Fixed ambiguous equals in Display
|
||||||
</PackageReleaseNotes>
|
</PackageReleaseNotes>
|
||||||
|
|
||||||
<Version>1.2.0</Version>
|
<Version>2.0.0</Version>
|
||||||
<AssemblyVersion>1.2.0</AssemblyVersion>
|
<AssemblyVersion>2.0.0</AssemblyVersion>
|
||||||
<FileVersion>1.2.0</FileVersion>
|
<FileVersion>2.0.0</FileVersion>
|
||||||
|
|
||||||
<OutputPath>..\bin\</OutputPath>
|
<OutputPath>..\bin\</OutputPath>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
@ -64,6 +64,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.1.0" />
|
||||||
<PackageReference Include="Vortice.Direct3D11" Version="1.9.143" />
|
<PackageReference Include="Vortice.Direct3D11" Version="1.9.143" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@ -2,4 +2,5 @@
|
|||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=directx/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=directx/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helper/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helper/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=model/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=model/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=model_005Ccolors/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
Loading…
x
Reference in New Issue
Block a user