mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-04 21:50:54 +03:00
add support for CF_DIBV5, CF_HDROP, and 'PNG' in ImageGrab.grabclipboard() on win32
This commit is contained in:
parent
d23df7227c
commit
5728662c7f
|
@ -4,7 +4,7 @@ import sys
|
||||||
import pytest
|
import pytest
|
||||||
from PIL import Image, ImageGrab
|
from PIL import Image, ImageGrab
|
||||||
|
|
||||||
from .helper import assert_image
|
from .helper import assert_image, assert_image_equal_tofile
|
||||||
|
|
||||||
|
|
||||||
class TestImageGrab:
|
class TestImageGrab:
|
||||||
|
@ -71,3 +71,26 @@ $bmp = New-Object Drawing.Bitmap 200, 200
|
||||||
|
|
||||||
im = ImageGrab.grabclipboard()
|
im = ImageGrab.grabclipboard()
|
||||||
assert_image(im, im.mode, im.size)
|
assert_image(im, im.mode, im.size)
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
|
||||||
|
def test_grabclipboard_file(self):
|
||||||
|
p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
|
||||||
|
p.stdin.write(rb'Set-Clipboard -Path "Tests\images\hopper.gif"')
|
||||||
|
p.communicate()
|
||||||
|
|
||||||
|
im = ImageGrab.grabclipboard()
|
||||||
|
assert_image_equal_tofile(im, "Tests/images/hopper.gif")
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
|
||||||
|
def test_grabclipboard_png(self):
|
||||||
|
p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
|
||||||
|
p.stdin.write(
|
||||||
|
rb"""$bytes = [System.IO.File]::ReadAllBytes("Tests\images\hopper.png")
|
||||||
|
$ms = new-object System.IO.MemoryStream(, $bytes)
|
||||||
|
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
|
||||||
|
[Windows.Forms.Clipboard]::SetData("PNG", $ms)"""
|
||||||
|
)
|
||||||
|
p.communicate()
|
||||||
|
|
||||||
|
im = ImageGrab.grabclipboard()
|
||||||
|
assert_image_equal_tofile(im, "Tests/images/hopper.png")
|
||||||
|
|
|
@ -93,12 +93,24 @@ def grabclipboard():
|
||||||
os.unlink(filepath)
|
os.unlink(filepath)
|
||||||
return im
|
return im
|
||||||
elif sys.platform == "win32":
|
elif sys.platform == "win32":
|
||||||
data = Image.core.grabclipboard_win32()
|
|
||||||
if isinstance(data, bytes):
|
|
||||||
from . import BmpImagePlugin
|
|
||||||
import io
|
import io
|
||||||
|
|
||||||
return BmpImagePlugin.DibImageFile(io.BytesIO(data))
|
fmt, data = Image.core.grabclipboard_win32()
|
||||||
return data
|
if isinstance(data, str):
|
||||||
|
if fmt == "file":
|
||||||
|
with open(data, "rb") as f:
|
||||||
|
im = Image.open(io.BytesIO(f.read()))
|
||||||
|
return im
|
||||||
|
if isinstance(data, bytes):
|
||||||
|
data = io.BytesIO(data)
|
||||||
|
if fmt == "png":
|
||||||
|
from . import PngImagePlugin
|
||||||
|
|
||||||
|
return PngImagePlugin.PngImageFile(data)
|
||||||
|
elif fmt == "DIB":
|
||||||
|
from . import BmpImagePlugin
|
||||||
|
|
||||||
|
return BmpImagePlugin.DibImageFile(data)
|
||||||
|
return None
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("ImageGrab.grabclipboard() is macOS and Windows only")
|
raise NotImplementedError("ImageGrab.grabclipboard() is macOS and Windows only")
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#include <Shlobj.h>
|
||||||
#include "ImDib.h"
|
#include "ImDib.h"
|
||||||
|
|
||||||
#if SIZEOF_VOID_P == 8
|
#if SIZEOF_VOID_P == 8
|
||||||
|
@ -473,33 +474,66 @@ PyObject*
|
||||||
PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args)
|
PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
int clip;
|
int clip;
|
||||||
HANDLE handle;
|
HANDLE handle = NULL;
|
||||||
int size;
|
int size;
|
||||||
void* data;
|
void* data;
|
||||||
PyObject* result;
|
PyObject* result;
|
||||||
|
UINT format;
|
||||||
|
UINT formats[] = { CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0 };
|
||||||
|
LPCSTR format_names[] = { "DIB", "DIB", "file", "png", NULL };
|
||||||
|
|
||||||
clip = OpenClipboard(NULL);
|
if (!OpenClipboard(NULL)) {
|
||||||
/* FIXME: check error status */
|
PyErr_SetString(PyExc_OSError, "failed to open clipboard");
|
||||||
|
return NULL;
|
||||||
handle = GetClipboardData(CF_DIB);
|
|
||||||
if (!handle) {
|
|
||||||
/* FIXME: add CF_HDROP support to allow cut-and-paste from
|
|
||||||
the explorer */
|
|
||||||
CloseClipboard();
|
|
||||||
Py_INCREF(Py_None);
|
|
||||||
return Py_None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find best format as set by clipboard owner
|
||||||
|
format = 0;
|
||||||
|
while (!handle && (format = EnumClipboardFormats(format))) {
|
||||||
|
for (UINT i = 0; formats[i] != 0; i++) {
|
||||||
|
if (format == formats[i]) {
|
||||||
|
handle = GetClipboardData(format);
|
||||||
|
format = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handle) {
|
||||||
|
CloseClipboard();
|
||||||
|
return Py_BuildValue("zO", NULL, Py_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formats[format] == CF_HDROP) {
|
||||||
|
LPDROPFILES files = (LPDROPFILES)GlobalLock(handle);
|
||||||
size = GlobalSize(handle);
|
size = GlobalSize(handle);
|
||||||
|
|
||||||
|
if (files->fWide) {
|
||||||
|
LPCWSTR filename = (LPCWSTR)(((char*)files) + files->pFiles);
|
||||||
|
size = wcsnlen(filename, (size - files->pFiles) / 2);
|
||||||
|
result = Py_BuildValue("zu#", "file", filename, size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LPCSTR filename = (LPCSTR)(((char*)files) + files->pFiles);
|
||||||
|
size = strnlen(filename, size - files->pFiles);
|
||||||
|
result = Py_BuildValue("zs#", "file", filename, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalUnlock(handle);
|
||||||
|
CloseClipboard();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
data = GlobalLock(handle);
|
data = GlobalLock(handle);
|
||||||
|
size = GlobalSize(handle);
|
||||||
|
|
||||||
result = PyBytes_FromStringAndSize(data, size);
|
result = PyBytes_FromStringAndSize(data, size);
|
||||||
|
|
||||||
GlobalUnlock(handle);
|
GlobalUnlock(handle);
|
||||||
|
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
|
|
||||||
return result;
|
return Py_BuildValue("zN", format_names[format], result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user