Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b828756

Browse files
authored
Merge pull request #10680 from anntzer/newtk
Rewrite the tk C blitting code
2 parents adc0b93 + 691c7e6 commit b828756

File tree

5 files changed

+87
-19
lines changed

5 files changed

+87
-19
lines changed

lib/matplotlib/backends/_backend_tk.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
from __future__ import (absolute_import, division, print_function,
2-
unicode_literals)
3-
41
import six
52
from six.moves import tkinter as Tk
63

4+
import math
75
import logging
86
import os.path
97
import sys
108

11-
# Paint image to Tk photo blitter extension
12-
import matplotlib.backends.tkagg as tkagg
9+
import numpy as np
1310

11+
from . import _tkagg
1412
from matplotlib.backends.backend_agg import FigureCanvasAgg
1513
import matplotlib.backends.windowing as windowing
1614

@@ -48,11 +46,37 @@ def raise_msg_to_str(msg):
4846
msg = '\n'.join(map(str, msg))
4947
return msg
5048

49+
5150
def error_msg_tkpaint(msg, parent=None):
5251
from six.moves import tkinter_messagebox as tkMessageBox
5352
tkMessageBox.showerror("matplotlib", msg)
5453

5554

55+
def blit(photoimage, aggimage, offsets, bbox=None):
56+
"""
57+
Blit *aggimage* to *photoimage*.
58+
59+
*offsets* is a tuple describing how to fill the ``offset`` field of the
60+
``Tk_PhotoImageBlock`` struct: it should be (0, 1, 2, 3) for RGBA8888 data,
61+
(2, 1, 0, 3) for little-endian ARBG32 (i.e. GBRA8888) data and (1, 2, 3, 0)
62+
for big-endian ARGB32 (i.e. ARGB8888) data.
63+
64+
If *bbox* is passed, it defines the region that gets blitted.
65+
"""
66+
data = np.asarray(aggimage)
67+
height, width = data.shape[:2]
68+
dataptr = (height, width, data.ctypes.data)
69+
if bbox is not None:
70+
(x1, y1), (x2, y2) = bbox.__array__()
71+
bboxptr = (math.floor(x1), math.ceil(x2),
72+
math.floor(y1), math.ceil(y2))
73+
else:
74+
photoimage.blank()
75+
bboxptr = (0, width, 0, height)
76+
_tkagg.blit(
77+
photoimage.tk.interpaddr(), str(photoimage), dataptr, offsets, bboxptr)
78+
79+
5680
class TimerTk(TimerBase):
5781
'''
5882
Subclass of :class:`backend_bases.TimerBase` that uses Tk's timer events.

lib/matplotlib/backends/backend_tkagg.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from . import tkagg # Paint image to Tk photo blitter extension.
1+
from . import _backend_tk
22
from .backend_agg import FigureCanvasAgg
33
from ._backend_tk import (
44
_BackendTk, FigureCanvasTk, FigureManagerTk, NavigationToolbar2Tk)
@@ -7,12 +7,12 @@
77
class FigureCanvasTkAgg(FigureCanvasAgg, FigureCanvasTk):
88
def draw(self):
99
super(FigureCanvasTkAgg, self).draw()
10-
tkagg.blit(self._tkphoto, self.renderer._renderer, colormode=2)
10+
_backend_tk.blit(self._tkphoto, self.renderer._renderer, (0, 1, 2, 3))
1111
self._master.update_idletasks()
1212

1313
def blit(self, bbox=None):
14-
tkagg.blit(
15-
self._tkphoto, self.renderer._renderer, bbox=bbox, colormode=2)
14+
_backend_tk.blit(
15+
self._tkphoto, self.renderer._renderer, (0, 1, 2, 3), bbox=bbox)
1616
self._master.update_idletasks()
1717

1818

lib/matplotlib/backends/backend_tkcairo.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import numpy as np
44

5-
from . import tkagg # Paint image to Tk photo blitter extension.
5+
from . import _backend_tk
66
from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo
77
from ._backend_tk import _BackendTk, FigureCanvasTk
88

@@ -20,13 +20,9 @@ def draw(self):
2020
self._renderer.set_width_height(width, height)
2121
self.figure.draw(self._renderer)
2222
buf = np.reshape(surface.get_data(), (height, width, 4))
23-
# Convert from ARGB32 to RGBA8888. Using .take() instead of directly
24-
# indexing ensures C-contiguity of the result, which is needed by
25-
# tkagg.
26-
buf = buf.take(
27-
[2, 1, 0, 3] if sys.byteorder == "little" else [1, 2, 3, 0],
28-
axis=2)
29-
tkagg.blit(self._tkphoto, buf, colormode=2)
23+
_backend_tk.blit(
24+
self._tkphoto, buf,
25+
(2, 1, 0, 3) if sys.byteorder == "little" else (1, 2, 3, 0))
3026
self._master.update_idletasks()
3127

3228

lib/matplotlib/backends/tkagg.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22

33
import numpy as np
44

5+
from matplotlib import cbook
56
from matplotlib.backends import _tkagg
67

8+
9+
cbook.warn_deprecated(
10+
"3.0", "The matplotlib.backends.tkagg module is deprecated.")
11+
12+
713
def blit(photoimage, aggimage, bbox=None, colormode=1):
814
tk = photoimage.tk
915

src/_tkagg.cpp

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,50 @@ static PyObject *_tkinit(PyObject *self, PyObject *args)
203203
return Py_None;
204204
}
205205

206+
static PyObject *mpl_tk_blit(PyObject *self, PyObject *args)
207+
{
208+
Tcl_Interp *interp;
209+
char const *photo_name;
210+
int height, width;
211+
unsigned char *data_ptr;
212+
int o0, o1, o2, o3;
213+
int x1, x2, y1, y2;
214+
Tk_PhotoHandle photo;
215+
Tk_PhotoImageBlock block;
216+
if (!PyArg_ParseTuple(args, "ns(iin)(iiii)(iiii):blit",
217+
&interp, &photo_name,
218+
&height, &width, &data_ptr,
219+
&o0, &o1, &o2, &o3,
220+
&x1, &x2, &y1, &y2)) {
221+
goto exit;
222+
}
223+
if (!(photo = TK_FIND_PHOTO(interp, photo_name))) {
224+
PyErr_SetString(PyExc_ValueError, "Failed to extract Tk_PhotoHandle");
225+
goto exit;
226+
}
227+
block.pixelPtr = data_ptr + 4 * ((height - y2) * width + x1);
228+
block.width = x2 - x1;
229+
block.height = y2 - y1;
230+
block.pitch = 4 * width;
231+
block.pixelSize = 4;
232+
block.offset[0] = o0;
233+
block.offset[1] = o1;
234+
block.offset[2] = o2;
235+
block.offset[3] = o3;
236+
TK_PHOTO_PUT_BLOCK_NO_COMPOSITE(
237+
photo, &block, x1, height - y2, x2 - x1, y2 - y1);
238+
exit:
239+
if (PyErr_Occurred()) {
240+
return NULL;
241+
} else {
242+
Py_RETURN_NONE;
243+
}
244+
}
245+
206246
static PyMethodDef functions[] = {
207247
/* Tkinter interface stuff */
208248
{ "tkinit", (PyCFunction)_tkinit, 1 },
249+
{ "blit", (PyCFunction)mpl_tk_blit, 1 },
209250
{ NULL, NULL } /* sentinel */
210251
};
211252

@@ -444,8 +485,9 @@ int load_tkinter_funcs(void)
444485
}
445486
#endif // end not Windows
446487

447-
static PyModuleDef _tkagg_module = { PyModuleDef_HEAD_INIT, "_tkagg", "", -1, functions,
448-
NULL, NULL, NULL, NULL };
488+
static PyModuleDef _tkagg_module = {
489+
PyModuleDef_HEAD_INIT, "_tkagg", "", -1, functions, NULL, NULL, NULL, NULL
490+
};
449491

450492
PyMODINIT_FUNC PyInit__tkagg(void)
451493
{

0 commit comments

Comments
 (0)