Windows 10 screen capture raises UnparsableClipboardFormatException
Opened this issue · 4 comments
Hi there!
I think this is a really great tool and I am excited to use it for engineering practice where it's common to copy-paste screen grabs of analysis models.
I install pyclip
and immediately tried to use it with a screen capture only to be greeted with the following:
---------------------------------------------------------------------------
UnparsableClipboardFormatException Traceback (most recent call last)
Input In [15], in <cell line: 1>()
----> 1 nb.paste.paste_image()
File ~\Notebooks\package_development\nbengineer\nbengineer\paste.py:31, in paste_image()
29 immediately in the current Jupyter notebook.
30 """
---> 31 clipboard_data = pyclip.paste()
32 first_eight_bytes = clipboard_data[:8]
33 image_type = _identify_image_type(first_eight_bytes)
File ~\Anaconda3\lib\site-packages\pyclip\__init__.py:42, in paste(*args, **kwargs)
40 if DEFAULT_CLIPBOARD is None:
41 raise ClipboardSetupException("Could not setup clipboard").with_traceback(_CLIPBOARD_EXCEPTION_TB)
---> 42 return DEFAULT_CLIPBOARD.paste(*args, **kwargs)
File ~\Anaconda3\lib\site-packages\pyclip\win_clip.py:218, in WindowsClipboard.paste(self, encoding, text, errors)
216 acceptable_formats = [f for f in all_formats if f in self._implemented_formats]
217 if not acceptable_formats:
--> 218 raise UnparsableClipboardFormatException("Clipboard contents have no standard formats available. "
219 "The contents can only be understood by a private program")
220 if (text or encoding or errors) and format not in self._string_formats:
221 raise ClipboardNotTextFormatException("Clipboard has no text formats available, but text options "
222 "were specified.")
UnparsableClipboardFormatException: Clipboard contents have no standard formats available. The contents can only be understood by a private program
I was hoping that with all of the additional clipboard formats available on Windows that it would be quite flexible. Is this something that is just a small fix or is there something funny going on with Windows and their proprietary formats?
Thanks for any time you can spend on this!
Thanks for raising this issue. Right now, pyclip
supports a narrow set of clipboard formats. Essentially, just text formats and hdrop (file copy/paste).
It seems you have copied and subsequently tried to paste through the pyclip
program a format that is not supported.
I guess I would wonder: (1) what format(s) is stored when screen grabs are used to populate the clipboard and (2) what should the behavior of .paste
do when dealing with these format(s).
Hi @spyoungtech,
After reading your source, and some of the Windows clipboard documentation, it seems that when one calls .GetClipboardData()
, a person has various options available to them on what format they would like their data in. After reviewing the various formats available, I used a print()
call to see what format a screen capture comes out with: 49161
.
It seems that this clipboard format code is something of a generic code to refer to a DataObject
. For screenshots, it seems that format codes 8: 'CF_DIB'
and/or 17: 'CF_DIBV5'
are the codes that return the byte arrays for the bitmap image.
I added an argument to .paste()
called format_override
which allows for the user to specify a custom Windows format code to get the data in the format required. The new .paste()
code would look like this:
def paste(self, encoding: str = None, text: bool = None, errors: str = None, format_override: int = None) -> Union[str, bytes]:
"""
Returns clipboard contents
:param encoding: same meaning as in ``bytes.encode``. Implies ``text=True``
:param text: if True, bytes object will be en
:param errors: same meaning as in ``bytes.encode``. Implies ``text=True``.
:param format_override: an attempt is made to find the format of the clipboard data internally but sometimes,
on Windows, this format is incorrect. Allows user to specify a format to return the data in.
See: https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
Use format code 8 for bitmap screen captures.
:return: clipboard contents. Return value is bytes by default
or str if any of ``encoding``, ``text``, or ``errors`` is provided.
"""
with self._clipboard as clip:
if format_override:
format = format_override
else:
format = clip.EnumClipboardFormats()
if format == 0:
if text or encoding or errors:
return ''
else:
return b''
...
This byte data can be passed through a BytesIO
into PIL.Image
to then manipulate the image:
So, it seems that it is possible to get screen capture data using pyclip
but, unfortunately, the clipboard format enum that is used by default, 49161
is ambiguous and requires the user to then specify what format they would like the bitmap data in.
In my local copy, I created this format_override
which would allow me to get the functionality I need but then I would be vendoring pyclip
into my own little utility package which is not ideal.
Let me know your thoughts on this. If you are interested in being able to work with Windows screen captures, then perhaps you might have some other ideas on how to manage this. My approach seems kinda hacky and it may break the API (because you would have different kwargs for different platforms).