Coder Social home page Coder Social logo

darthaffe / screencapture.net Goto Github PK

View Code? Open in Web Editor NEW
49.0 3.0 9.0 204 KB

Fast and easy to use screen-capturing

License: GNU Lesser General Public License v2.1

C# 100.00%
screen-capture desktop-duplication capture directx display screen display-capture image

screencapture.net's Introduction

ScreenCapture.NET

GitHub release (latest by date) Nuget GitHub GitHub Repo stars

NuGet-Packages:

Package Description
ScreenCapture.NET The core-package required to use ScreenCapture.NET captures or write your own.
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 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 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

// Create a screen-capture service
IScreenCaptureService screenCaptureService = new DX11ScreenCaptureService();

// Get all available graphics cards
IEnumerable<GraphicsCard> graphicsCards = screenCaptureService.GetGraphicsCards();

// Get the displays from the graphics card(s) you are interested in
IEnumerable<Display> displays = screenCaptureService.GetDisplays(graphicsCards.First());

// Create a screen-capture for all screens you want to capture
IScreenCapture screenCapture = screenCaptureService.GetScreenCapture(displays.First());

// Register the regions you want to capture om the screen
// Capture the whole screen
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
ICaptureZone topLeft = screenCapture.RegisterCaptureZone(0, 0, 100, 100, downscaleLevel: 1);

// 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).
screenCapture.CaptureScreen();

// Do something with the captured image - e.g. access all pixels (same could be done with topLeft)

//Lock the zone to access the data. Remember to dispose the returned disposable to unlock again.
using (fullscreen.Lock())
{
    // You have multiple options now:
    // 1. Access the raw byte-data
    ReadOnlySpan<byte> rawData = fullscreen.RawBuffer;

    // 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 pixels of the image
    foreach (IColor color in image)
        Console.WriteLine($"A: {color.A}, R: {color.R}, G: {color.G}, B: {color.B}");

    // Get the pixel at location (x = 10, y = 20)
    IColor imageColorExample = image[10, 20];

    // Get the first row
    IImage.IImageRow row = image.Rows[0];
    // Get the 10th pixel of the row
    IColor rowColorExample = row[10];

    // 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:

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];
}

screencapture.net's People

Contributors

darthaffe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

screencapture.net's Issues

Unable to install DX9 and DX11 on Windows 10

When attempting to install on Windows 10, I get the error:

Error	NU1202	Package ScreenCapture.NET.DX11 2.0.0 is not compatible with net7.0 (.NETCoreApp,Version=v7.0). Package ScreenCapture.NET.DX11 2.0.0 supports:
  - net6.0-windows7.0 (.NETCoreApp,Version=v6.0)
  - net7.0-windows7.0 (.NETCoreApp,Version=v7.0)

I'm guessing that because of the added -windows7.0 to the end of the version, NuGet doesn't want to install the package. Nevermind, it seems that NuGet is fine with installing a different package that uses net6.0-windows7.0

Edit: yeah, turns out for some reason this package gets errors when attempting to install without a target platform, but others don't??? Either way, setting the Target platform in the project settings to Windows 7.0 worked

Featurerequest IImage.Convert();

It would be nice if IImage was convertable either to Image or to Bitmap.

Like:

ICaptureZone zone = screen.RegisterCaptureZone(1080, 896, 57, 35, downscaleLevel: 1);
screen.CaptureScreen();
using (zone.Lock())
{
IImage img = GEAR.Image;
Bitmap bmp = img.convert();
}

Crashes if I set the application to use a specific GPU

Hi,

Thank you for your work, it has been quite useful. However I have one small issue with it. For some reason if I set my application to use a specific GPU in the Windows 11 settings (Graphics settings > Browse > Add application to the list then set it to use a non-primary GPU) it will crash. This is the error I get:

Exception thrown: 'SharpGen.Runtime.SharpGenException' in SharpGen.Runtime
Exception thrown: 'System.NullReferenceException' in SharpGen.Runtime
Object reference not set to an instance of an object.

Extracted embedded document "/_/src/Vortice.Direct3D11/obj/SharpGen-dlpP0O1fxIg71ru7toZjEspM3SEWycxI33HTG2U0-wg/SharpGen.Bindings.g.cs" to "C:\Users\redacted\AppData\Local\Temp\.vsdbgsrc\b59c979149b9e423f798cdf58884ed5deffddeab2a0edf36fe51751a9333ed2c\SharpGen.Bindings.g.cs"

I am using a 4090 as the primary GPU and 3060 as the secondary, so both should be fully compatible with this. I am able to set 99% of applications I work with to any GPU without any issues so I assume this is just a bug of some kind. I have a feeling that when I set the application to use the second GPU, it still tries to access the first one causing it to crash or something. Honestly not sure. But to my understanding I cant specify which GPU to use within the API itself. I hope this all makes sense anyway, thank you once again for your work.

screenshoting

hi there, i was wondering if there is any implementation of this that takes in the window handle and screenshot the provided window?

Display collection not refreshing on display settings change

If display mode is changed, public IEnumerable GetDisplays(GraphicsCard graphicsCard) won't return updated list.

https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgifactory1-enumadapters1

When you create a factory, the factory enumerates the set of adapters that are available in the system. Therefore, if you change the adapters in a system, you must destroy and recreate the IDXGIFactory1 object. The number of adapters in a system changes when you add or remove a display card, or dock or undock a laptop.

Not sure if this issue should be here or in the artemis ambilight plugin git.

Convert CaptureZone Buffer to Jpeg Image Buffer

Hello. I truly appreciate the library. Just have a general question. Is there a suggested approach to turning the CaptureZone Buffer into an image buffer of a recognizable format? The following is what I am doing right now, but Bitmap (System.Drawing.Common) isn't a cross-platform solution and I believe losing support even for Windows in .NET 7.

        private static Task<byte[]> GetScreenshotImage(IScreenCapture screenCapture, CaptureZone captureZone)
        {
            return Task.Run(() =>
            {
                screenCapture.CaptureScreen();

                lock (captureZone.Buffer)
                {
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    {
                        GCHandle pinnedArray = GCHandle.Alloc(captureZone.Buffer, GCHandleType.Pinned);
                        IntPtr pointer = pinnedArray.AddrOfPinnedObject();

                        Bitmap bitmap = new Bitmap(captureZone.Width, captureZone.Height, captureZone.Stride, PixelFormat.Format32bppArgb, pointer);

                        pinnedArray.Free();

                        using MemoryStream jpgStream = new MemoryStream();
                        bitmap.Save(jpgStream, ImageFormat.Jpeg);

                        return jpgStream.ToArray();
                    }

                    return captureZone.Buffer;
                }
            });
        }

HDR Support

I would like to request HDR support, as taking a screenshot on a HDR monitor makes the colors look like the contrast really high.

Vertical monitor partial capture

Hi Darth,

Stumbled upon this while testing ---

Scenario:
Second monitor is a vertical monitor.
It seems it is treated as a non-rotated screen.

Result from 'Usage' example, only modification is that I selected the second monitor as a source:
screenshot1

Windows snipping tool:
image

Object reference not set to an instance of an object when i execute the code in a loop or when i call a get response twice

Message=Object reference not set to an instance of an object. Source=SharpGen.Runtime Arborescence des appels de procédure : à SharpGen.Runtime.CppObject.get_Item(Int32 index) à Vortice.Direct3D11.ID3D11Device.CreateTexture2D(Texture2DDescription desc, Void* initialData) à Vortice.Direct3D11.ID3D11Device.CreateTexture2D(Texture2DDescription description, SubresourceData[] initialData) à ScreenCapture.NET.DX11ScreenCapture.InitializeCaptureZone(CaptureZone& captureZone) à ScreenCapture.NET.DX11ScreenCapture.RegisterCaptureZone(Int32 x, Int32 y, Int32 width, Int32 height, Int32 downscaleLevel)
CaptureZone fullscreen = screenCapture.RegisterCaptureZone(0, 0, screenCapture.Display.Width, screenCapture.Display.Height);

Multiple screen

When I use multiple screens to take screenshots, all of them except the first one show up as black screens.

IScreenCaptureService screenCaptureService = new DX11ScreenCaptureService();
IEnumerable<GraphicsCard> graphicsCards = screenCaptureService.GetGraphicsCards();
foreach (GraphicsCard graphicsCard in graphicsCards)
{
    IEnumerable<Display> displays = screenCaptureService.GetDisplays(graphicsCard);
    foreach (Display display in displays)
    {
        IScreenCapture screenCapture = screenCaptureService.GetScreenCapture(display);
        CaptureZone fullscreen = screenCapture.RegisterCaptureZone(0, 0, screenCapture.Display.Width, screenCapture.Display.Height);
        screenCapture.CaptureScreen();
        var image = Image.LoadPixelData<Bgra32>(fullscreen.Buffer, screenCapture.Display.Width, screenCapture.Display.Height);
        image.SaveAsJpeg("C:\\temp\\" + display.DeviceName + ".jpg");
    }
}

Bug ScreenCapture.NET.DX11

When I try and instantiate a screencapture service

IScreenCaptureService screenCaptureService = new DX11ScreenCaptureService();

I get the following error.

Method 'get_ColorFormat' in type 'ScreenCapture.NET.IColor' from assembly 'ScreenCapture.NET, Version=2.0.1.0, Culture=neutral, PublicKeyToken=null' cannot be a static and a virtual.

Using .Net 6.0. The issue occurs on both ScreenCapture.NET v2.0.0 and v2.0.1

System.NullReferenceException: 'Object reference not set to an instance of an object.'

Using the example code, crashing on
| StackTrace | " at SharpGen.Runtime.CppObject.get_Item(Int32 index)\r\n at Vortice.Direct3D11.ID3D11Device.CreateTexture2D(Texture2DDescription descRef, SubresourceData[] initialDataRef)\r\n at ScreenCapture.NET.DX11ScreenCapture.InitializeCaptureZone(CaptureZone& captureZone)\r\n at ScreenCapture.NET.DX11ScreenCapture.RegisterCaptureZone(Int32 x, Int32 y, Int32 width, Int32 height, Int32 downscaleLevel)\r\n

`
DPIAwareness.Initalize();

        IScreenCaptureService screenCaptureService = new DX11ScreenCaptureService();

        // Get all available graphics cards
        IEnumerable<GraphicsCard> graphicsCards = screenCaptureService.GetGraphicsCards();

        // Get the displays from the graphics card(s) you are interested in
        IEnumerable<Display> displays = screenCaptureService.GetDisplays(graphicsCards.First());

        // Create a screen-capture for all screens you want to capture
        IScreenCapture screenCapture = screenCaptureService.GetScreenCapture(displays.First());

        // Register the regions you want to capture om the screen
        // Capture the whole screen
        CaptureZone fullscreen = screenCapture.RegisterCaptureZone(0, 0, screenCapture.Display.Width, screenCapture.Display.Height);`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.