X Tutup
/* -*- mode: c++; c-basic-offset: 4 -*- */ /* * The Python Imaging Library. * $Id$ * */ /* This is needed for (at least) Tk 8.4.1, otherwise the signature of ** Tk_PhotoPutBlock changes. */ #define USE_COMPOSITELESS_PHOTO_PUT_BLOCK #include #include #include #include #include "py_converters.h" extern "C" { #ifdef __APPLE__ # ifdef TK_FRAMEWORK # include # include # else # include # endif #else # include #endif } #if defined(_MSC_VER) # define SIZE_T_FORMAT "%Iu" #else # define SIZE_T_FORMAT "%zu" #endif typedef struct { PyObject_HEAD; Tcl_Interp *interp; } TkappObject; static int PyAggImagePhoto(ClientData clientdata, Tcl_Interp *interp, int argc, char **argv) { Tk_PhotoHandle photo; Tk_PhotoImageBlock block; PyObject *bufferobj; // vars for blitting PyObject *bboxo; size_t aggl, bboxl; bool has_bbox; uint8_t *destbuffer; int destx, desty, destwidth, destheight, deststride; //unsigned long tmp_ptr; long mode; long nval; if (Tk_MainWindow(interp) == NULL) { // Will throw a _tkinter.TclError with "this isn't a Tk application" return TCL_ERROR; } if (argc != 5) { Tcl_AppendResult(interp, "usage: ", argv[0], " destPhoto srcImage", (char *)NULL); return TCL_ERROR; } /* get Tcl PhotoImage handle */ photo = Tk_FindPhoto(interp, argv[1]); if (photo == NULL) { Tcl_AppendResult(interp, "destination photo must exist", (char *)NULL); return TCL_ERROR; } /* get array (or object that can be converted to array) pointer */ if (sscanf(argv[2], SIZE_T_FORMAT, &aggl) != 1) { Tcl_AppendResult(interp, "error casting pointer", (char *)NULL); return TCL_ERROR; } bufferobj = (PyObject *)aggl; numpy::array_view buffer; try { buffer = numpy::array_view(bufferobj); } catch (...) { Tcl_AppendResult(interp, "buffer is of wrong type", (char *)NULL); PyErr_Clear(); return TCL_ERROR; } int srcheight = buffer.dim(0); /* XXX insert aggRenderer type check */ /* get array mode (0=mono, 1=rgb, 2=rgba) */ mode = atol(argv[3]); if ((mode != 0) && (mode != 1) && (mode != 2)) { Tcl_AppendResult(interp, "illegal image mode", (char *)NULL); return TCL_ERROR; } /* check for bbox/blitting */ if (sscanf(argv[4], SIZE_T_FORMAT, &bboxl) != 1) { Tcl_AppendResult(interp, "error casting pointer", (char *)NULL); return TCL_ERROR; } bboxo = (PyObject *)bboxl; if (bboxo != NULL && bboxo != Py_None) { agg::rect_d rect; if (!convert_rect(bboxo, &rect)) { return TCL_ERROR; } has_bbox = true; destx = (int)rect.x1; desty = srcheight - (int)rect.y2; destwidth = (int)(rect.x2 - rect.x1); destheight = (int)(rect.y2 - rect.y1); deststride = 4 * destwidth; destbuffer = new agg::int8u[deststride * destheight]; if (destbuffer == NULL) { Tcl_AppendResult(interp, "could not allocate memory", (char *)NULL); return TCL_ERROR; } for (int i = 0; i < destheight; ++i) { memcpy(destbuffer + (deststride * i), &buffer(i + desty, destx, 0), deststride); } } else { has_bbox = false; destbuffer = NULL; destx = desty = destwidth = destheight = deststride = 0; } /* setup tkblock */ block.pixelSize = 1; if (mode == 0) { block.offset[0] = block.offset[1] = block.offset[2] = 0; nval = 1; } else { block.offset[0] = 0; block.offset[1] = 1; block.offset[2] = 2; if (mode == 1) { block.offset[3] = 0; block.pixelSize = 3; nval = 3; } else { block.offset[3] = 3; block.pixelSize = 4; nval = 4; } } if (has_bbox) { block.width = destwidth; block.height = destheight; block.pitch = deststride; block.pixelPtr = destbuffer; Tk_PhotoPutBlock(photo, &block, destx, desty, destwidth, destheight); delete[] destbuffer; } else { block.width = buffer.dim(1); block.height = buffer.dim(0); block.pitch = (int)block.width * nval; block.pixelPtr = buffer.data(); /* Clear current contents */ Tk_PhotoBlank(photo); /* Copy opaque block to photo image, and leave the rest to TK */ Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height); } return TCL_OK; } static PyObject *_pyobj_addr(PyObject *self, PyObject *args) { PyObject *pyobj; if (!PyArg_ParseTuple(args, "O", &pyobj)) { return NULL; } return Py_BuildValue("n", (Py_ssize_t)pyobj); } static PyObject *_tkinit(PyObject *self, PyObject *args) { Tcl_Interp *interp; TkappObject *app; Py_ssize_t arg; int is_interp; if (!PyArg_ParseTuple(args, "ni", &arg, &is_interp)) { return NULL; } if (is_interp) { interp = (Tcl_Interp *)arg; } else { /* Do it the hard way. This will break if the TkappObject layout changes */ app = (TkappObject *)arg; interp = app->interp; } /* This will bomb if interp is invalid... */ Tcl_CreateCommand(interp, "PyAggImagePhoto", (Tcl_CmdProc *)PyAggImagePhoto, (ClientData)0, (Tcl_CmdDeleteProc *)NULL); Py_INCREF(Py_None); return Py_None; } static PyMethodDef functions[] = { /* Tkinter interface stuff */ { "_pyobj_addr", (PyCFunction)_pyobj_addr, 1 }, { "tkinit", (PyCFunction)_tkinit, 1 }, { NULL, NULL } /* sentinel */ }; #if PY3K static PyModuleDef _tkagg_module = { PyModuleDef_HEAD_INIT, "_tkagg", "", -1, functions, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit__tkagg(void) { PyObject *m; m = PyModule_Create(&_tkagg_module); import_array(); return m; } #else PyMODINIT_FUNC init_tkagg(void) { import_array(); Py_InitModule("_tkagg", functions); } #endif
X Tutup