Use PyCapsule in _imagingtk

This commit is contained in:
Aleksandr Karpinskii 2024-09-02 04:29:34 +04:00
parent c69ad03af0
commit 920c4ac447
2 changed files with 31 additions and 15 deletions

View File

@ -48,18 +48,18 @@ def _get_image_from_kw(kw: dict[str, Any]) -> ImageFile.ImageFile | None:
def _pyimagingtkcall( def _pyimagingtkcall(
command: str, photo: PhotoImage | tkinter.PhotoImage, id: int command: str, photo: PhotoImage | tkinter.PhotoImage, ptr: object
) -> None: ) -> None:
tk = photo.tk tk = photo.tk
try: try:
tk.call(command, photo, id) tk.call(command, photo, repr(ptr))
except tkinter.TclError: except tkinter.TclError:
# activate Tkinter hook # activate Tkinter hook
# may raise an error if it cannot attach to Tkinter # may raise an error if it cannot attach to Tkinter
from . import _imagingtk from . import _imagingtk
_imagingtk.tkinit(tk.interpaddr()) _imagingtk.tkinit(tk.interpaddr())
tk.call(command, photo, id) tk.call(command, photo, repr(ptr))
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -181,7 +181,7 @@ class PhotoImage:
block = image.new_block(self.__mode, im.size) block = image.new_block(self.__mode, im.size)
image.convert2(block, image) # convert directly between buffers image.convert2(block, image) # convert directly between buffers
_pyimagingtkcall("PyImagingPhoto", self.__photo, block.id) _pyimagingtkcall("PyImagingPhoto", self.__photo, block.ptr)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -255,9 +255,8 @@ class BitmapImage:
def getimage(photo: PhotoImage) -> Image.Image: def getimage(photo: PhotoImage) -> Image.Image:
"""Copies the contents of a PhotoImage to a PIL image memory.""" """Copies the contents of a PhotoImage to a PIL image memory."""
im = Image.new("RGBA", (photo.width(), photo.height())) im = Image.new("RGBA", (photo.width(), photo.height()))
block = im.im
_pyimagingtkcall("PyImagingPhotoGet", photo, block.id) _pyimagingtkcall("PyImagingPhotoGet", photo, im.im.ptr)
return im return im

View File

@ -56,19 +56,36 @@ static Tk_PhotoPutBlock_t TK_PHOTO_PUT_BLOCK;
static Imaging static Imaging
ImagingFind(const char *name) { ImagingFind(const char *name) {
Py_ssize_t id; PyObject *capsule;
int direct_pointer = 0;
const char *expected = "capsule object \"" IMAGING_MAGIC "\" at 0x";
/* FIXME: use CObject instead? */ if (name[0] == '<') {
#if defined(_WIN64) name++;
id = _atoi64(name); } else {
#else // Special case for PyPy, where the string representation of a Capsule
id = atol(name); // refers directly to the pointer itself, not to the PyCapsule object.
#endif direct_pointer = 1;
if (!id) { }
if (strncmp(name, expected, strlen(expected))) {
return NULL; return NULL;
} }
return (Imaging)id; capsule = (PyObject *)strtoull(name + strlen(expected), NULL, 16);
if (direct_pointer) {
return (Imaging)capsule;
}
if (!PyCapsule_IsValid(capsule, IMAGING_MAGIC)) {
PyErr_Format(
PyExc_TypeError, "Expected PyCapsule with '%s' name.", IMAGING_MAGIC
);
return NULL;
}
return (Imaging)PyCapsule_GetPointer(capsule, IMAGING_MAGIC);
} }
static int static int