New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple screenshots using ScreenDC issue #259
Comments
Has been asked (with possible working answer) on Stackoverflow. |
I do not think this issue is solved: |
I see this also with Classic (but built against GTK 3), so I think this is probably rather something to do with the GTK 3 implementation of wxScreenDC and nothing wxPython specific. Probably needs a C++ reproducer and ticket opened on trac.wxwidgets.org. |
Yep, there are also similar problems with OSX. My understanding is that due to the additional layers between the applications and the display for automatic buffering and compositing, that we don't have the same level of access to the display's image buffer that we had before with the older systems, and so we simply can not fetch what is displayed on the screen via the wx.ScreenDC API in order to Blit it into a bitmap. I think I saw somebody say that you can think of wx.ScreenDC being a write-only interface now. That said, on OSX you can use wx.ScreenDC.GetAsBitmap to get an image of the screen. It's not implemented for GTK3 unfortunately. |
On Mon, Aug 12, 2019 at 06:29:06PM -0700, Robin Dunn wrote:
Yep, there are also similar problems with OSX.
My understanding is that due to the additional layers
between the applications and the display for automatic
buffering and compositing, that we don't have the same level
of access to the display's image buffer that we had before
with the older systems, and so we simply can not fetch what
is displayed on the screen via the wx.ScreenDC API in order
to Blit it into a bitmap.
I feared as much. Put another way: there's _no_ way to
_fully_ (including window decorations) screenshot an
application from within wxPhoenix ?
Karsten
--
GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B
|
If you are willing to try other packages, then pyscreenshot might be a way:
https://github.com/ponty/pyscreenshot
Since apparently they have done it, I don’t see why it shouldn’t be
possible in wx. Also, doesn’t wxWidgets have its own screenshot tool for
the documentation:
https://github.com/wxWidgets/wxWidgets/blob/cc931612eec2e3ea49200ebff45042135f3c3f9c/utils/screenshotgen/src/autocapture.cpp
Andrea.
…On Tue, 13 Aug 2019 at 08.27, ncqgm ***@***.***> wrote:
On Mon, Aug 12, 2019 at 06:29:06PM -0700, Robin Dunn wrote:
> Yep, there are also similar problems with OSX.
>
> My understanding is that due to the additional layers
> between the applications and the display for automatic
> buffering and compositing, that we don't have the same level
> of access to the display's image buffer that we had before
> with the older systems, and so we simply can not fetch what
> is displayed on the screen via the wx.ScreenDC API in order
> to Blit it into a bitmap.
I feared as much. Put another way: there's _no_ way to
_fully_ (including window decorations) screenshot an
application from within wxPhoenix ?
Karsten
--
GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#259?email_source=notifications&email_token=ACESNIN7I46O2RZ6VLAJSI3QEJH63A5CNFSM4DFBOMDKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4EVSCA#issuecomment-520706312>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACESNILULMFGA7W467NKPKTQEJH63ANCNFSM4DFBOMDA>
.
|
On Tue, Aug 13, 2019 at 06:43:02AM +0000, Andrea Gavana wrote:
Also, doesn’t wxWidgets have its own screenshot tool for
the documentation:
https://github.com/wxWidgets/wxWidgets/blob/cc931612eec2e3ea49200ebff45042135f3c3f9c/utils/screenshotgen/src/autocapture.cpp
I saw that before but looked again:
AFAICS they do exactly what I do, except for a
memory_DC.Clear()
after setting the bitmap object on the memory_DC:
bmp = wx.Bitmap()
memory_DC.SelectObj(bmp)
memory_DC.Clear() # <==
memory_DC.Blit(..., screen_DC, ...)
memory_DC.SelectObj(wx.NullBitmap)
bmp.SaveFile()
I can't see how this should make a difference but I'll give
it a try. That sequence (w/o the .Clear()) certainly does not
work for me.
Karsten
--
GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B
|
On Tue, Aug 13, 2019 at 06:43:02AM +0000, Andrea Gavana wrote:
If you are willing to try other packages, then pyscreenshot might be a way:
https://github.com/ponty/pyscreenshot
They are doing it the brutal way: Creating a new wx.App for each screenshot.
Karsten
--
GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B
|
On Mon, Aug 12, 2019 at 06:29:06PM -0700, Robin Dunn wrote:
My understanding is that due to the additional layers
between the applications and the display for automatic
buffering and compositing, that we don't have the same level
of access to the display's image buffer that we had before
with the older systems, and so we simply can not fetch what
is displayed on the screen via the wx.ScreenDC API in order
to Blit it into a bitmap. I think I saw somebody say that you
can think of wx.ScreenDC being a write-only interface now.
I am not so sure anymore that I understand that line of
thought:
Upon the *first* instantiation of wx.ScreenDC() it works just
right - the ScreenDC contains a copy of the desktop at that
time.
Subsequent, *new*, instantiations of the same class will not.
Why would one have access to the desktop content the first
time around but not later on ?
We are not talking live interaction with the desktop here.
Why should it be technically possible to read once but not
more than once ?
Surely that sounds like the first instantiation is cached
somewhere and merely returned later on ?
Best,
Karsten
--
GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B
|
Faced the same problem on Ubuntu 19.10, wxPython 4.0.6 gtk3 (phoenix) wxWidgets 3.0.4, python 3.7.5. Just insert import wx
from datetime import datetime
from time import sleep
def take_screenshot():
screen = wx.ScreenDC()
size = screen.GetSize()
width = size[0]
height = size[1]
bmp = wx.Bitmap(width, height)
mem = wx.MemoryDC(bmp)
mem.Blit(0, 0, width, height, screen, 0, 0)
screen.Blit(0, 0, width, height, screen, 0, 0) # <-- this line makes multiple screenshots work
bmp.SaveFile(str(datetime.now()) + '.png', wx.BITMAP_TYPE_PNG)
if __name__ == '__main__':
app = wx.App()
take_screenshot()
sleep(3)
take_screenshot()
sleep(3)
take_screenshot()
sleep(3)
take_screenshot() upd: It is better to use |
Am Thu, Mar 18, 2021 at 02:56:51AM -0700 schrieb The-o:
Faced the same problem on Ubuntu 19.10, wxPython 4.0.6 gtk3 (phoenix) wxWidgets 3.0.4, python 3.7.5.
And it seems I found workaround:
Just insert `screen.Blit(0, 0, width, height, screen, 0, 0)` after `mem.Blit(0, 0, width, height, screen, 0, 0)`.
I can confirm this works for me. It perhaps "updates" a
globally cached (?) Screen DC from layers further down,
closer to the hardware ?
Karsten
|
I don't really know how and why it works. I believe it is something to do with wxWidgets and not with wxPython itself. But the confusing fact is that there is no such an if-branch in wxWidgets v3.0.4 I have (https://github.com/wxWidgets/wxWidgets/blob/v3.0.4/src/gtk/dc.cpp#L138). And I'm not good at cairo, so the mystery of why the workaround works still remains for me. |
The-o found a workaround for the problem that taking consecutive screenshots of a ScreenDC always returned the same (initial) image. wxWidgets/Phoenix#259 (comment) (cherry picked from commit 513cd90)
The-o found a workaround for the problem that taking consecutive screenshots of a ScreenDC always returned the same (initial) image. wxWidgets/Phoenix#259 (comment)
If you take a screenshot with
wx.ScreenDC()
for few times, then every time you will get the same image: the screenshot at the moment whenwx.ScreenDC()
was called for the first time. The only solution found is to run it every time in separate Process with its ownwx.App()
inside.However, if you do this on wxPython Classic, it works just fine.
Sample code down here:
The text was updated successfully, but these errors were encountered: