SerpentAI / D3DShot

Extremely fast and robust screen capture on Windows with the Desktop Duplication API
MIT License
328 stars 74 forks source link

Getting garbled image on screenshot #19

Closed Maheidem closed 4 years ago

Maheidem commented 4 years ago

Hi,

I´ve been trying to use D3DShot but it´s been returning a garbled image, like this:

I´m thinking this has something to do with drivers, any thoughts?

venusjoel commented 4 years ago

I am experiencing the same issue, did you come up with a solution?

Maheidem commented 4 years ago

So far nothing. I haven't actually tried any more. Easier to just find some other solution

Disablez commented 4 years ago

On an nvidia 2080 Ti it happens at 3440x1440 resolution; lowering it fixes the problem, but obviously it's just a temporary workaround. Tried all capture methods... pil, numpy, torch_gpu ... etc, same result.

nbrochu commented 4 years ago

Apologies for the late reply.

For everyone getting the garbled images, can you share a snippet of what you do with the output you get from D3DShot? Do you pass it to scikit-image, OpenCV, Pillow, Other?

Information about OS, Python, Resolution, GPUs is also useful.

I'd love to get this fixed but will need some examples to find a first clue.

nbrochu commented 4 years ago

Possible hint in #11

For maximum performance, the buffer at the pointer returned by the Desktop Duplication API is left as is. NumPy is able to perform view manipulations to access the buffer differently without altering it. It's possible that whatever you pass your D3DShot output to tries to access the raw buffer of the array instead of its view. That would cause garbled images because the shape and stride information would be lost.

That wouldn't explain why @Ricky54326 only sees a garbled image at very high resolutions and it works otherwise though. Maybe the array is getting copied at some point? That forces an ordering of the new buffer to conform to the view.

gbrlfaria commented 4 years ago

Here's my attempt to reproduce the issue. I have tested d3dshot with two code snippets.

The first one uses the "numpy" output format and displays the image using OpenCV.

import cv2
import d3dshot

d = d3dshot.create(capture_output='numpy')
img = d.screenshot()

cv2.imshow('screenshot', img)
cv2.waitKey()

The second one uses the default capture output format (PIL) and just saves the screenshot to disk.

import d3dshot

d = d3dshot.create()
img = d.screenshot_to_disk()

In both cases, the output image is garbled and looks like this (it should be a Visual Studio Code window). Although I didn't test other output formats like @Disablez did, I am positive that the same problem happens.

Now some information about the environment in which I performed the tests above.

Operating System: Windows 10 Home Edition, version 1909 (build 18363.836)
Python Version: Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Resolution: 1366x768
GPU (integrated): Intel(R) HD Graphics 620 (python.exe was run with this graphics card)
GPU (discrete): NVIDIA GeForce 920MX

And this is the output for d.displays.

[<Display name=Generic PnP Monitor adapter=Intel(R) HD Graphics 620 resolution=1366x768 rotation=0 scale_factor=1.0 primary=True>]

Edit: I have just tested the same code with the same environment, except that I lowered the desktop resolution to 1360x768 and it works just fine. Actually, it works for any value lower than 1366x768. Maybe the issue happens only when the desktop is set to the maximum resolution?

j4hangir commented 4 years ago

I made a duplicate of this issue here https://github.com/SerpentAI/D3DShot/issues/26, seems there hasn't be a solution yet...

nbrochu commented 4 years ago

Doing a D3DShot day tomorrow. I'm going to be trying to reproduce this. Seems like it's pretty widespread too.

nbrochu commented 4 years ago

It would appear the issue is only present with certain resolutions. I finally managed to get garbled output by forcing resolutions in the Nvidia Control Panel.

Here are my results:

Now to figure out what's happening at those resolutions...

nbrochu commented 4 years ago

I believe I have found the source of the problem. At the garbled resolutions, the pitch of the DXGI_MAPPED_RECT doesn't match width * 4.

Example:

If I don't respect the pitch given by the IDXGISurface, I start filling in the next row of pixels while still in the potential padding from the previous row. This causes the row offset or garbled effect in the screenshot you all shared.

Windows seems to pad the IDXGISurface so the width will be divisible by 32. This is probably to enable all the neat tricks you can do with strides. If you check carefully in my resolution tests above, all the ones that are garbled don't have widths that are divisible by 32.

Fix on the way!

nbrochu commented 4 years ago

Happy to report that the issue is now fixed. Be sure to grab D3DShot 0.1.5 and let me know how it goes.

Arcitec commented 4 years ago

Very cool. Great bug hunting and conclusion, @nbrochu ! :-)