mirror of
https://github.com/DarthAffe/ScreenCapture.NET.git
synced 2025-12-12 13:28:35 +00:00
Update README.md
This commit is contained in:
parent
9cc6cfb653
commit
7c768e08ae
105
README.md
105
README.md
@ -4,6 +4,14 @@
|
|||||||
[](https://github.com/DarthAffe/ScreenCapture.NET/blob/master/LICENSE)
|
[](https://github.com/DarthAffe/ScreenCapture.NET/blob/master/LICENSE)
|
||||||
[](https://github.com/DarthAffe/ScreenCapture.NET/stargazers)
|
[](https://github.com/DarthAffe/ScreenCapture.NET/stargazers)
|
||||||
|
|
||||||
|
## NuGet-Packages:
|
||||||
|
| Package | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| [ScreenCapture.NET](https://www.nuget.org/packages/ScreenCapture.NET)| The core-package required to use ScreenCapture.NET captures or write your own. |
|
||||||
|
| [ScreenCapture.NET.DX11](https://www.nuget.org/packages/ScreenCapture.NET.DX11) | DirectX 11 based capturing. Fast and supports the whole set of features. **This should always be used if possible!** |
|
||||||
|
| [ScreenCapture.NET.DX9](https://www.nuget.org/packages/ScreenCapture.NET.DX9) | DirectX 9 based capturing. Slower then DX 11 and does not support rotated screens and GPU-accelerated downscaling. Only useful if the DX11 package can't be used for some reason. |
|
||||||
|
| [ScreenCapture.NET.X11](https://www.nuget.org/packages/ScreenCapture.NET.X11) | libX11 based capturing for the X-Window-System. Currently the only way to use ScreenCapture.NET on linux. Quite slow and can easily break depending on the X-Server config. Works on my machine, but it's not really a high proprity to support at the moment. Does not support rotated screens and GPU-accelerated downscaling. |
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
```csharp
|
```csharp
|
||||||
// Create a screen-capture service
|
// Create a screen-capture service
|
||||||
@ -18,50 +26,81 @@ IEnumerable<Display> displays = screenCaptureService.GetDisplays(graphicsCards.F
|
|||||||
// Create a screen-capture for all screens you want to capture
|
// Create a screen-capture for all screens you want to capture
|
||||||
IScreenCapture screenCapture = screenCaptureService.GetScreenCapture(displays.First());
|
IScreenCapture screenCapture = screenCaptureService.GetScreenCapture(displays.First());
|
||||||
|
|
||||||
// Register the regions you want to capture on the screen
|
// Register the regions you want to capture om the screen
|
||||||
// Capture the whole screen
|
// Capture the whole screen
|
||||||
CaptureZone fullscreen = screenCapture.RegisterCaptureZone(0, 0, screenCapture.Display.Width, screenCapture.Display.Height);
|
ICaptureZone fullscreen = screenCapture.RegisterCaptureZone(0, 0, screenCapture.Display.Width, screenCapture.Display.Height);
|
||||||
// Capture a 100x100 region at the top left and scale it down to 50x50
|
// Capture a 100x100 region at the top left and scale it down to 50x50
|
||||||
CaptureZone topLeft = screenCapture.RegisterCaptureZone(0, 0, 100, 100, downscaleLevel: 1);
|
ICaptureZone topLeft = screenCapture.RegisterCaptureZone(0, 0, 100, 100, downscaleLevel: 1);
|
||||||
|
|
||||||
// Capture the screen
|
// Capture the screen
|
||||||
// This should be done in a loop on a seperate thread as CaptureScreen blocks if the screen is not updated (still image).
|
// This should be done in a loop on a seperate thread as CaptureScreen blocks if the screen is not updated (still image).
|
||||||
screenCapture.CaptureScreen();
|
screenCapture.CaptureScreen();
|
||||||
|
|
||||||
// Do something with the captured image - e.g. access all pixels (same could be done with topLeft)
|
// Do something with the captured image - e.g. access all pixels (same could be done with topLeft)
|
||||||
// Locking is not neccessary in that case as we're capturing in the same thread,
|
|
||||||
// but when using a threaded-approach (which is recommended) it prevents potential tearing of the data in the buffer.
|
//Lock the zone to access the data. Remember to dispose the returned disposable to unlock again.
|
||||||
lock (fullscreen.Buffer)
|
using (fullscreen.Lock())
|
||||||
{
|
{
|
||||||
// Stride is the width in bytes of a row in the buffer (width in pixel * bytes per pixel)
|
// You have multiple options now:
|
||||||
int stride = fullscreen.Stride;
|
// 1. Access the raw byte-data
|
||||||
|
ReadOnlySpan<byte> rawData = fullscreen.RawBuffer;
|
||||||
|
|
||||||
Span<byte> data = new(fullscreen.Buffer);
|
// 2. Use the provided abstraction to access pixels without having to care about low-level byte handling
|
||||||
|
// Get the image captured for the zone
|
||||||
|
IImage image = fullscreen.Image;
|
||||||
|
|
||||||
// Iterate all rows of the image
|
// Iterate all pixels of the image
|
||||||
for (int y = 0; y < fullscreen.Height; y++)
|
foreach (IColor color in image)
|
||||||
{
|
Console.WriteLine($"A: {color.A}, R: {color.R}, G: {color.G}, B: {color.B}");
|
||||||
// Select the actual data of the row
|
|
||||||
Span<byte> row = data.Slice(y * stride, stride);
|
|
||||||
|
|
||||||
// Iterate all pixels
|
// Get the pixel at location (x = 10, y = 20)
|
||||||
for (int x = 0; x < row.Length; x += fullscreen.BytesPerPixel)
|
IColor imageColorExample = image[10, 20];
|
||||||
{
|
|
||||||
// Data is in BGRA format for the DX11ScreenCapture
|
// Get the first row
|
||||||
byte b = row[x];
|
IImage.IImageRow row = image.Rows[0];
|
||||||
byte g = row[x + 1];
|
// Get the 10th pixel of the row
|
||||||
byte r = row[x + 2];
|
IColor rowColorExample = row[10];
|
||||||
byte a = row[x + 3];
|
|
||||||
}
|
// Get the first column
|
||||||
}
|
IImage.IImageColumn column = image.Columns[0];
|
||||||
|
// Get the 10th pixel of the column
|
||||||
|
IColor columnColorExample = column[10];
|
||||||
|
|
||||||
|
// Cuts a rectangle out of the original image (x = 100, y = 150, width = 400, height = 300)
|
||||||
|
IImage subImage = image[100, 150, 400, 300];
|
||||||
|
|
||||||
|
// All of the things above (rows, columns, sub-images) do NOT allocate new memory so they are fast and memory efficient, but for that reason don't provide raw byte access.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
IF you know which Capture-provider you're using it performs a bit better to not use the abstraction but a more low-level approach instead.
|
||||||
|
This is the same example as above but without using the interfaces:
|
||||||
|
```csharp
|
||||||
|
DX11ScreenCaptureService screenCaptureService = new DX11ScreenCaptureService();
|
||||||
|
IEnumerable<GraphicsCard> graphicsCards = screenCaptureService.GetGraphicsCards();
|
||||||
|
IEnumerable<Display> displays = screenCaptureService.GetDisplays(graphicsCards.First());
|
||||||
|
DX11ScreenCapture screenCapture = screenCaptureService.GetScreenCapture(displays.First());
|
||||||
|
|
||||||
|
CaptureZone<ColorBGRA> fullscreen = screenCapture.RegisterCaptureZone(0, 0, screenCapture.Display.Width, screenCapture.Display.Height);
|
||||||
|
CaptureZone<ColorBGRA> topLeft = screenCapture.RegisterCaptureZone(0, 0, 100, 100, downscaleLevel: 1);
|
||||||
|
|
||||||
|
screenCapture.CaptureScreen();
|
||||||
|
|
||||||
|
using (fullscreen.Lock())
|
||||||
|
{
|
||||||
|
RefImage<ColorBGRA> image = fullscreen.Image;
|
||||||
|
|
||||||
|
foreach (ColorBGRA color in image)
|
||||||
|
Console.WriteLine($"A: {color.A}, R: {color.R}, G: {color.G}, B: {color.B}");
|
||||||
|
|
||||||
|
ColorBGRA imageColorExample = image[10, 20];
|
||||||
|
|
||||||
|
ReadOnlyRefEnumerable<ColorBGRA> row = image.Rows[0];
|
||||||
|
ColorBGRA rowColorExample = row[10];
|
||||||
|
|
||||||
|
ReadOnlyRefEnumerable<ColorBGRA> column = image.Columns[0];
|
||||||
|
ColorBGRA columnColorExample = column[10];
|
||||||
|
|
||||||
|
RefImage<ColorBGRA> subImage = image[100, 150, 400, 300];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the top left zone more towards the center
|
|
||||||
// Using the Update-method allows to move the zone without having to allocate
|
|
||||||
// new buffers and textures which yields a good performance gain if done at high framerates.
|
|
||||||
screenCapture.UpdateCaptureZone(topLeft, x: 100, y: 200);
|
|
||||||
|
|
||||||
// Note that resizing the zone is also possible but currently reinitializes the zone
|
|
||||||
// -> no performance gain compared to removing and readding the zone.
|
|
||||||
screenCapture.UpdateCaptureZone(topLeft, width: 20, height: 20);
|
|
||||||
```
|
```
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user