mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-05-05 00:13:42 +03:00
Merge pull request #1458 from wiredfool/pr1431
Use correctly sized pointers for windows handle types.
This commit is contained in:
commit
fdfbe8f3ee
111
Tests/test_imagewin_pointers.py
Normal file
111
Tests/test_imagewin_pointers.py
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
from helper import unittest, PillowTestCase, hopper
|
||||||
|
from PIL import Image, ImageWin
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import ctypes
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
# see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652
|
||||||
|
|
||||||
|
if sys.platform.startswith('win32'):
|
||||||
|
import ctypes.wintypes
|
||||||
|
|
||||||
|
class BITMAPFILEHEADER(ctypes.Structure):
|
||||||
|
_pack_ = 2
|
||||||
|
_fields_ = [
|
||||||
|
('bfType', ctypes.wintypes.WORD),
|
||||||
|
('bfSize', ctypes.wintypes.DWORD),
|
||||||
|
('bfReserved1', ctypes.wintypes.WORD),
|
||||||
|
('bfReserved2', ctypes.wintypes.WORD),
|
||||||
|
('bfOffBits', ctypes.wintypes.DWORD),
|
||||||
|
]
|
||||||
|
|
||||||
|
class BITMAPINFOHEADER(ctypes.Structure):
|
||||||
|
_pack_ = 2
|
||||||
|
_fields_ = [
|
||||||
|
('biSize', ctypes.wintypes.DWORD),
|
||||||
|
('biWidth', ctypes.wintypes.LONG),
|
||||||
|
('biHeight', ctypes.wintypes.LONG),
|
||||||
|
('biPlanes', ctypes.wintypes.WORD),
|
||||||
|
('biBitCount', ctypes.wintypes.WORD),
|
||||||
|
('biCompression', ctypes.wintypes.DWORD),
|
||||||
|
('biSizeImage', ctypes.wintypes.DWORD),
|
||||||
|
('biXPelsPerMeter', ctypes.wintypes.LONG),
|
||||||
|
('biYPelsPerMeter', ctypes.wintypes.LONG),
|
||||||
|
('biClrUsed', ctypes.wintypes.DWORD),
|
||||||
|
('biClrImportant', ctypes.wintypes.DWORD),
|
||||||
|
]
|
||||||
|
|
||||||
|
BI_RGB = 0
|
||||||
|
DIB_RGB_COLORS = 0
|
||||||
|
|
||||||
|
memcpy = ctypes.cdll.msvcrt.memcpy
|
||||||
|
memcpy.argtypes = [ ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t ]
|
||||||
|
|
||||||
|
CreateCompatibleDC = ctypes.windll.gdi32.CreateCompatibleDC
|
||||||
|
CreateCompatibleDC.argtypes = [ ctypes.wintypes.HDC ]
|
||||||
|
CreateCompatibleDC.restype = ctypes.wintypes.HDC
|
||||||
|
|
||||||
|
DeleteDC = ctypes.windll.gdi32.DeleteDC
|
||||||
|
DeleteDC.argtypes = [ ctypes.wintypes.HDC ]
|
||||||
|
|
||||||
|
SelectObject = ctypes.windll.gdi32.SelectObject
|
||||||
|
SelectObject.argtypes = [ ctypes.wintypes.HDC, ctypes.wintypes.HGDIOBJ ]
|
||||||
|
SelectObject.restype = ctypes.wintypes.HGDIOBJ
|
||||||
|
|
||||||
|
DeleteObject = ctypes.windll.gdi32.DeleteObject
|
||||||
|
DeleteObject.argtypes = [ ctypes.wintypes.HGDIOBJ ]
|
||||||
|
|
||||||
|
CreateDIBSection = ctypes.windll.gdi32.CreateDIBSection
|
||||||
|
CreateDIBSection.argtypes = [ ctypes.wintypes.HDC, ctypes.c_void_p, ctypes.c_uint, ctypes.POINTER(ctypes.c_void_p), ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD ]
|
||||||
|
CreateDIBSection.restype = ctypes.wintypes.HBITMAP
|
||||||
|
|
||||||
|
|
||||||
|
def serialize_dib(bi, pixels):
|
||||||
|
bf = BITMAPFILEHEADER()
|
||||||
|
bf.bfType = 0x4d42
|
||||||
|
bf.bfOffBits = ctypes.sizeof(bf) + bi.biSize
|
||||||
|
bf.bfSize = bf.bfOffBits + bi.biSizeImage
|
||||||
|
bf.bfReserved1 = bf.bfReserved2 = 0
|
||||||
|
|
||||||
|
buf = (ctypes.c_byte * bf.bfSize)()
|
||||||
|
bp = ctypes.addressof(buf)
|
||||||
|
memcpy(bp, ctypes.byref(bf), ctypes.sizeof(bf))
|
||||||
|
memcpy(bp + ctypes.sizeof(bf), ctypes.byref(bi), bi.biSize)
|
||||||
|
memcpy(bp + bf.bfOffBits, pixels, bi.biSizeImage)
|
||||||
|
return bytearray(buf)
|
||||||
|
|
||||||
|
class TestImageWinPointers(PillowTestCase):
|
||||||
|
def test_pointer(self):
|
||||||
|
im = hopper()
|
||||||
|
(width, height) =im.size
|
||||||
|
opath = self.tempfile('temp.png')
|
||||||
|
imdib = ImageWin.Dib(im)
|
||||||
|
|
||||||
|
hdr = BITMAPINFOHEADER()
|
||||||
|
hdr.biSize = ctypes.sizeof(hdr)
|
||||||
|
hdr.biWidth = width
|
||||||
|
hdr.biHeight = height
|
||||||
|
hdr.biPlanes = 1
|
||||||
|
hdr.biBitCount = 32
|
||||||
|
hdr.biCompression = BI_RGB
|
||||||
|
hdr.biSizeImage = width * height * 4
|
||||||
|
hdr.biClrUsed = 0
|
||||||
|
hdr.biClrImportant = 0
|
||||||
|
|
||||||
|
hdc = CreateCompatibleDC(None)
|
||||||
|
#print('hdc:',hex(hdc))
|
||||||
|
pixels = ctypes.c_void_p()
|
||||||
|
dib = CreateDIBSection(hdc, ctypes.byref(hdr), DIB_RGB_COLORS, ctypes.byref(pixels), None, 0)
|
||||||
|
SelectObject(hdc, dib)
|
||||||
|
|
||||||
|
imdib.expose(hdc)
|
||||||
|
bitmap = serialize_dib(hdr, pixels)
|
||||||
|
DeleteObject(dib)
|
||||||
|
DeleteDC(hdc)
|
||||||
|
|
||||||
|
reloaded = Image.open(BytesIO(bitmap)).save(opath)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
47
display.c
47
display.c
|
@ -35,6 +35,12 @@
|
||||||
|
|
||||||
#include "ImDib.h"
|
#include "ImDib.h"
|
||||||
|
|
||||||
|
#if SIZEOF_VOID_P == 8
|
||||||
|
#define F_HANDLE "K"
|
||||||
|
#else
|
||||||
|
#define F_HANDLE "k"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
ImagingDIB dib;
|
ImagingDIB dib;
|
||||||
|
@ -74,8 +80,8 @@ _delete(ImagingDisplayObject* display)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_expose(ImagingDisplayObject* display, PyObject* args)
|
_expose(ImagingDisplayObject* display, PyObject* args)
|
||||||
{
|
{
|
||||||
int hdc;
|
HDC hdc;
|
||||||
if (!PyArg_ParseTuple(args, "i", &hdc))
|
if (!PyArg_ParseTuple(args, F_HANDLE, &hdc))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ImagingExposeDIB(display->dib, hdc);
|
ImagingExposeDIB(display->dib, hdc);
|
||||||
|
@ -87,10 +93,10 @@ _expose(ImagingDisplayObject* display, PyObject* args)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_draw(ImagingDisplayObject* display, PyObject* args)
|
_draw(ImagingDisplayObject* display, PyObject* args)
|
||||||
{
|
{
|
||||||
int hdc;
|
HDC hdc;
|
||||||
int dst[4];
|
int dst[4];
|
||||||
int src[4];
|
int src[4];
|
||||||
if (!PyArg_ParseTuple(args, "i(iiii)(iiii)", &hdc,
|
if (!PyArg_ParseTuple(args, F_HANDLE "(iiii)(iiii)", &hdc,
|
||||||
dst+0, dst+1, dst+2, dst+3,
|
dst+0, dst+1, dst+2, dst+3,
|
||||||
src+0, src+1, src+2, src+3))
|
src+0, src+1, src+2, src+3))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -131,10 +137,10 @@ _paste(ImagingDisplayObject* display, PyObject* args)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_query_palette(ImagingDisplayObject* display, PyObject* args)
|
_query_palette(ImagingDisplayObject* display, PyObject* args)
|
||||||
{
|
{
|
||||||
int hdc;
|
HDC hdc;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "i", &hdc))
|
if (!PyArg_ParseTuple(args, F_HANDLE, &hdc))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
status = ImagingQueryPaletteDIB(display->dib, hdc);
|
status = ImagingQueryPaletteDIB(display->dib, hdc);
|
||||||
|
@ -145,30 +151,31 @@ _query_palette(ImagingDisplayObject* display, PyObject* args)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_getdc(ImagingDisplayObject* display, PyObject* args)
|
_getdc(ImagingDisplayObject* display, PyObject* args)
|
||||||
{
|
{
|
||||||
int window;
|
HWND window;
|
||||||
HDC dc;
|
HDC dc;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "i", &window))
|
if (!PyArg_ParseTuple(args, F_HANDLE, &window))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dc = GetDC((HWND) window);
|
dc = GetDC(window);
|
||||||
if (!dc) {
|
if (!dc) {
|
||||||
PyErr_SetString(PyExc_IOError, "cannot create dc");
|
PyErr_SetString(PyExc_IOError, "cannot create dc");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Py_BuildValue("i", (int) dc);
|
return Py_BuildValue(F_HANDLE, dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_releasedc(ImagingDisplayObject* display, PyObject* args)
|
_releasedc(ImagingDisplayObject* display, PyObject* args)
|
||||||
{
|
{
|
||||||
int window, dc;
|
HWND window;
|
||||||
|
HDC dc;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "ii", &window, &dc))
|
if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &window, &dc))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ReleaseDC((HWND) window, (HDC) dc);
|
ReleaseDC(window, dc);
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
|
@ -386,7 +393,7 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
|
||||||
if (title_size > 0) {
|
if (title_size > 0) {
|
||||||
title = PyUnicode_FromStringAndSize(NULL, title_size);
|
title = PyUnicode_FromStringAndSize(NULL, title_size);
|
||||||
if (title)
|
if (title)
|
||||||
GetWindowText(hwnd, PyUnicode_AS_UNICODE(title), title_size+1);
|
GetWindowTextW(hwnd, PyUnicode_AS_UNICODE(title), title_size+1);
|
||||||
} else
|
} else
|
||||||
title = PyUnicode_FromString("");
|
title = PyUnicode_FromString("");
|
||||||
if (!title)
|
if (!title)
|
||||||
|
@ -397,7 +404,7 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
|
||||||
GetWindowRect(hwnd, &outer);
|
GetWindowRect(hwnd, &outer);
|
||||||
|
|
||||||
item = Py_BuildValue(
|
item = Py_BuildValue(
|
||||||
"nN(iiii)(iiii)", (Py_ssize_t) hwnd, title,
|
F_HANDLE "N(iiii)(iiii)", hwnd, title,
|
||||||
inner.left, inner.top, inner.right, inner.bottom,
|
inner.left, inner.top, inner.right, inner.bottom,
|
||||||
outer.left, outer.top, outer.right, outer.bottom
|
outer.left, outer.top, outer.right, outer.bottom
|
||||||
);
|
);
|
||||||
|
@ -600,10 +607,10 @@ windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
/* fall through... */
|
/* fall through... */
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
callback = (PyObject*) GetWindowLong(wnd, 0);
|
callback = (PyObject*) GetWindowLongPtr(wnd, 0);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
threadstate = (PyThreadState*)
|
threadstate = (PyThreadState*)
|
||||||
GetWindowLong(wnd, sizeof(PyObject*));
|
GetWindowLongPtr(wnd, sizeof(PyObject*));
|
||||||
current_threadstate = PyThreadState_Swap(NULL);
|
current_threadstate = PyThreadState_Swap(NULL);
|
||||||
PyEval_RestoreThread(threadstate);
|
PyEval_RestoreThread(threadstate);
|
||||||
} else
|
} else
|
||||||
|
@ -631,7 +638,7 @@ windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
callback_error("window damage callback");
|
callback_error("window damage callback");
|
||||||
|
|
||||||
result = PyObject_CallFunction(
|
result = PyObject_CallFunction(
|
||||||
callback, "siiiii", "clear", (int) dc,
|
callback, "s" F_HANDLE "iiii", "clear", dc,
|
||||||
0, 0, rect.right-rect.left, rect.bottom-rect.top
|
0, 0, rect.right-rect.left, rect.bottom-rect.top
|
||||||
);
|
);
|
||||||
if (result)
|
if (result)
|
||||||
|
@ -640,7 +647,7 @@ windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
callback_error("window clear callback");
|
callback_error("window clear callback");
|
||||||
|
|
||||||
result = PyObject_CallFunction(
|
result = PyObject_CallFunction(
|
||||||
callback, "siiiii", "repair", (int) dc,
|
callback, "s" F_HANDLE "iiii", "repair", dc,
|
||||||
0, 0, rect.right-rect.left, rect.bottom-rect.top
|
0, 0, rect.right-rect.left, rect.bottom-rect.top
|
||||||
);
|
);
|
||||||
if (result)
|
if (result)
|
||||||
|
@ -741,7 +748,7 @@ PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
|
||||||
SetForegroundWindow(wnd); /* to make sure it's visible */
|
SetForegroundWindow(wnd); /* to make sure it's visible */
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
return Py_BuildValue("n", (Py_ssize_t) wnd);
|
return Py_BuildValue(F_HANDLE, wnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
|
|
|
@ -228,7 +228,7 @@ ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4])
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImagingExposeDIB(ImagingDIB dib, int dc)
|
ImagingExposeDIB(ImagingDIB dib, void *dc)
|
||||||
{
|
{
|
||||||
/* Copy bitmap to display */
|
/* Copy bitmap to display */
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ ImagingExposeDIB(ImagingDIB dib, int dc)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImagingDrawDIB(ImagingDIB dib, int dc, int dst[4], int src[4])
|
ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4])
|
||||||
{
|
{
|
||||||
/* Copy bitmap to printer/display */
|
/* Copy bitmap to printer/display */
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ ImagingDrawDIB(ImagingDIB dib, int dc, int dst[4], int src[4])
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ImagingQueryPaletteDIB(ImagingDIB dib, int dc)
|
ImagingQueryPaletteDIB(ImagingDIB dib, void *dc)
|
||||||
{
|
{
|
||||||
/* Install bitmap palette */
|
/* Install bitmap palette */
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,10 @@ extern ImagingDIB ImagingNewDIB(const char *mode, int xsize, int ysize);
|
||||||
|
|
||||||
extern void ImagingDeleteDIB(ImagingDIB im);
|
extern void ImagingDeleteDIB(ImagingDIB im);
|
||||||
|
|
||||||
extern void ImagingDrawDIB(ImagingDIB dib, int dc, int dst[4], int src[4]);
|
extern void ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4]);
|
||||||
extern void ImagingExposeDIB(ImagingDIB dib, int dc);
|
extern void ImagingExposeDIB(ImagingDIB dib, void *dc);
|
||||||
|
|
||||||
extern int ImagingQueryPaletteDIB(ImagingDIB dib, int dc);
|
extern int ImagingQueryPaletteDIB(ImagingDIB dib, void *dc);
|
||||||
|
|
||||||
extern void ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]);
|
extern void ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user