def test_text_annotation_get_window_extent(): figure = Figure(dpi=100) renderer = RendererAgg(200, 200, 100) # Only text annotation annotation = Annotation('test', xy=(0, 0)) annotation.set_figure(figure) text = Text(text='test', x=0, y=0) text.set_figure(figure) bbox = annotation.get_window_extent(renderer=renderer) text_bbox = text.get_window_extent(renderer=renderer) eq_(bbox.width, text_bbox.width) eq_(bbox.height, text_bbox.height) _, _, d = renderer.get_text_width_height_descent( 'text', annotation._fontproperties, ismath=False) _, _, lp_d = renderer.get_text_width_height_descent( 'lp', annotation._fontproperties, ismath=False) below_line = max(d, lp_d) # These numbers are specific to the current implementation of Text points = bbox.get_points() eq_(points[0, 0], 0.0) eq_(points[1, 0], text_bbox.width) eq_(points[0, 1], -below_line) eq_(points[1, 1], text_bbox.height - below_line)
def chunk_limit_setup(): N = 100_000 dpi = 500 w = 5 * dpi h = 6 * dpi # just fit in the width x = np.linspace(0, w, N) # and go top-to-bottom y = np.ones(N) * h y[::2] = 0 idt = IdentityTransform() # make a renderer ra = RendererAgg(w, h, dpi) # setup the minimal gc to draw a line gc = ra.new_gc() gc.set_linewidth(1) gc.set_foreground('r') # make a Path p = Path(np.vstack((x, y)).T) # effectively disable path simplification (but leaving it "on") p.simplify_threshold = 0 return ra, gc, p, idt
def draw_quadmesh(data, obj): """Returns the PGFPlots code for an graphics environment holding a rendering of the object. """ content = [] # Generate file name for current object filename, rel_filepath = files.new_filename(data, "img", ".png") # Get the dpi for rendering and store the original dpi of the figure dpi = data["dpi"] fig_dpi = obj.figure.get_dpi() obj.figure.set_dpi(dpi) # Render the object and save as png file from matplotlib.backends.backend_agg import RendererAgg cbox = obj.get_clip_box() width = int(round(cbox.extents[2])) height = int(round(cbox.extents[3])) ren = RendererAgg(width, height, dpi) obj.draw(ren) # Generate a image from the render buffer image = Image.frombuffer( "RGBA", ren.get_canvas_width_height(), ren.buffer_rgba(), "raw", "RGBA", 0, 1 ) # Crop the image to the actual content (removing the the regions otherwise # used for axes, etc.) # 'image.crop' expects the crop box to specify the left, upper, right, and # lower pixel. 'cbox.extents' gives the left, lower, right, and upper # pixel. box = ( int(round(cbox.extents[0])), 0, int(round(cbox.extents[2])), int(round(cbox.extents[3] - cbox.extents[1])), ) cropped = image.crop(box) cropped.save(filename) # Restore the original dpi of the figure obj.figure.set_dpi(fig_dpi) # write the corresponding information to the TikZ file extent = obj.axes.get_xlim() + obj.axes.get_ylim() # Explicitly use \pgfimage as includegrapics command, as the default # \includegraphics fails unexpectedly in some cases ff = data["float format"] content.append( ( "\\addplot graphics [includegraphics cmd=\\pgfimage," "xmin=" + ff + ", xmax=" + ff + ", " "ymin=" + ff + ", ymax=" + ff + "] {{{}}};\n" ).format(*(extent + (rel_filepath,))) ) return data, content
def draw_quadmesh(data, obj): '''Returns the PGFPlots code for an graphics environment holding a rendering of the object. ''' content = [] # Generate file name for current object if 'img number' not in data.keys(): data['img number'] = 0 filename = os.path.join( data['output dir'], '%s_img%03d.png' % (data['base name'], data['img number'])) data['img number'] = data['img number'] + 1 # Get the dpi for rendering and store the original dpi of the figure dpi = data['dpi'] fig_dpi = obj.figure.get_dpi() obj.figure.set_dpi(dpi) # Render the object and save as png file from matplotlib.backends.backend_agg import RendererAgg cbox = obj.get_clip_box() width = int(round(cbox.extents[2])) height = int(round(cbox.extents[3])) ren = RendererAgg(width, height, dpi) obj.draw(ren) # Generate a image from the render buffer image = Image.frombuffer('RGBA', ren.get_canvas_width_height(), ren.buffer_rgba(), 'raw', 'RGBA', 0, 1) # Crop the image to the actual content (removing the the regions otherwise # used for axes, etc.) # 'image.crop' expects the crop box to specify the left, upper, right, and # lower pixel. 'cbox.extents' gives the left, lower, right, and upper # pixel. box = (int(round(cbox.extents[0])), 0, int(round(cbox.extents[2])), int(round(cbox.extents[3] - cbox.extents[1]))) cropped = image.crop(box) cropped.save(filename) # Restore the original dpi of the figure obj.figure.set_dpi(fig_dpi) # write the corresponding information to the TikZ file extent = obj.axes.get_xlim() + obj.axes.get_ylim() rel_filepath = os.path.basename(filename) if data['rel data path']: rel_filepath = os.path.join(data['rel data path'], rel_filepath) # Explicitly use \pgfimage as includegrapics command, as the default # \includegraphics fails unexpectedly in some cases content.append('\\addplot graphics [includegraphics cmd=\\pgfimage,' 'xmin=%.15g, xmax=%.15g, ' 'ymin=%.15g, ymax=%.15g] {%s};\n' % (extent + (rel_filepath, ))) return data, content
def draw_quadmesh(data, obj): """Returns the PGFPlots code for an graphics environment holding a rendering of the object. """ content = [] # Generate file name for current object filename, rel_filepath = _files.new_filename(data, "img", ".png") # Get the dpi for rendering and store the original dpi of the figure dpi = data["dpi"] fig_dpi = obj.figure.get_dpi() obj.figure.set_dpi(dpi) # Render the object and save as png file from matplotlib.backends.backend_agg import RendererAgg cbox = obj.get_clip_box() width = int(round(cbox.extents[2])) height = int(round(cbox.extents[3])) ren = RendererAgg(width, height, dpi) obj.draw(ren) # Generate a image from the render buffer image = Image.frombuffer( "RGBA", ren.get_canvas_width_height(), ren.buffer_rgba(), "raw", "RGBA", 0, 1 ) # Crop the image to the actual content (removing the the regions otherwise # used for axes, etc.) # 'image.crop' expects the crop box to specify the left, upper, right, and # lower pixel. 'cbox.extents' gives the left, lower, right, and upper # pixel. box = ( int(round(cbox.extents[0])), 0, int(round(cbox.extents[2])), int(round(cbox.extents[3] - cbox.extents[1])), ) cropped = image.crop(box) cropped.save(filename) # Restore the original dpi of the figure obj.figure.set_dpi(fig_dpi) # write the corresponding information to the TikZ file extent = obj.axes.get_xlim() + obj.axes.get_ylim() # Explicitly use \pgfimage as includegrapics command, as the default # \includegraphics fails unexpectedly in some cases ff = data["float format"] content.append( "\\addplot graphics [includegraphics cmd=\\pgfimage," f"xmin={extent[0]:{ff}}, xmax={extent[1]:{ff}}, " f"ymin={extent[2]:{ff}}, ymax={extent[3]:{ff}}] {{{rel_filepath}}};\n" ) return data, content
def render(self): w, h = self.shape r = RendererAgg(w, h, 72) arr = np.frombuffer(r.buffer_rgba(), np.uint8) arr.shape = r.height, r.width, -1 for stroke in self.strokes: stroke.render(r) image_raw = np.float32(arr, dtype=np.float32) / 255 return rgba_to_rgb(image_raw)
def create_mask(self, img=None, mask_shape=None): if mask_shape is None: self.height, self.width = img.shape[:2] else: self.height, self.width = mask_shape self.renderer = RendererAgg(self.width, self.height, 90) buf = self.renderer.buffer_rgba() arr = np.frombuffer(buf, np.uint8) self.array = arr.reshape(self.height, self.width, 4) self.mask_img.set_data(self.array) self.bbox.set_points(np.array([[0, 0], [self.width, self.height]]))
def render_figure_as_image(self, wFig, hFig, dpi): """ Renders a matplotlib figure using the Agg backend and stores the result in a C{wx.Image}. The arguments C{wFig} and {hFig} are the width and height of the figure, and C{dpi} is the dots-per-inch to render at. """ figure = self.figure if mat_ver < zoom_ver: old_dpi = figure.dpi.get() figure.dpi.set(dpi) old_width = figure.figwidth.get() figure.figwidth.set(wFig) old_height = figure.figheight.get() figure.figheight.set(hFig) wFig_Px = int(figure.bbox.width()) hFig_Px = int(figure.bbox.height()) agg = RendererAgg(wFig_Px, hFig_Px, Value(dpi)) else: old_dpi = figure.get_dpi() figure.set_dpi(dpi) old_width = figure.get_figwidth() figure.set_figwidth(wFig) old_height = figure.get_figheight() figure.set_figheight(hFig) old_frameon = figure.frameon figure.frameon = False wFig_Px = int(figure.bbox.width) hFig_Px = int(figure.bbox.height) agg = RendererAgg(wFig_Px, hFig_Px, dpi) figure.draw(agg) if mat_ver < zoom_ver: figure.dpi.set(old_dpi) figure.figwidth.set(old_width) figure.figheight.set(old_height) else: figure.set_dpi(old_dpi) figure.set_figwidth(old_width) figure.set_figheight(old_height) figure.frameon = old_frameon image = wx.EmptyImage(wFig_Px, hFig_Px) image.SetData(agg.tostring_rgb()) return image
def get_renderer(self, cleared=False): l, b, w, h = self.figure.bbox.bounds key = w, h, self.figure.dpi try: self._lastKey, self.renderer except AttributeError: need_new_renderer = True else: need_new_renderer = (self._lastKey != key) if need_new_renderer: self.renderer = RendererAgg(w, h, self.figure.dpi) mixin_gl_renderer(self.renderer) self._lastKey = key elif cleared: self.renderer.clear() return self.renderer
def render(self): """ Renders the image from the set of strokes and returns an RGB image with dimensions self.shape. """ w, h = self.shape r = RendererAgg(w, h, 72) arr = np.frombuffer(r.buffer_rgba(), np.uint8) arr.shape = r.height, r.width, -1 for stroke in self.strokes: stroke.render(r) image_raw = np.float32(arr, dtype=np.float32) / 255 return rgba_to_rgb(image_raw)
def test_arrow_annotation_get_window_extent(): figure = Figure(dpi=100) figure.set_figwidth(2.0) figure.set_figheight(2.0) renderer = RendererAgg(200, 200, 100) # Text annotation with arrow annotation = Annotation('', xy=(0.0, 50.0), xytext=(50.0, 50.0), xycoords='figure pixels', arrowprops={ 'facecolor': 'black', 'width': 8, 'headwidth': 10, 'shrink': 0.0 }) annotation.set_figure(figure) annotation.draw(renderer) bbox = annotation.get_window_extent() points = bbox.get_points() eq_(bbox.width, 50.0) assert_almost_equal(bbox.height, 10.0 / 0.72) eq_(points[0, 0], 0.0) eq_(points[0, 1], 50.0 - 5 / 0.72)
def run(self, html): self.fontsize = self.original_fontsize self.text_fig = Figure(dpi=self.dpi) self.renderer = RendererAgg(self.figwidth, self.figheight, self.dpi) self.rows, self.num_header_rows = self.parse_html(html) self.col_widths = self.calculate_col_widths() self.row_heights = self.get_row_heights() self.fig = self.create_figure() return self.print_table()
def renderLineSampleImage(line, width, dpi = 100): import Debug # Debug.printCall(None, (line, width)) from matplotlib.backends.backend_agg import RendererAgg as Renderer from matplotlib.lines import Line2D useValue = True try: from matplotlib.transforms import Value except ImportError: useValue = False from PyQt4 import QtGui attributes = ["antialiased", "color", "dash_capstyle", "dash_joinstyle", "linestyle", "linewidth", "marker", "markeredgecolor", "markeredgewidth", "markerfacecolor", "markersize", "solid_capstyle", "solid_joinstyle"] lineAttributes = dict() for attribute in attributes: lineAttributes[attribute] = getattr(line, "get_" + attribute)() height = max(lineAttributes["linewidth"], lineAttributes["markersize"] * 1.4 + 2 + 2*lineAttributes["markeredgewidth"]) pixmapWidth = int(width + lineAttributes["markersize"] * 1.4 + 2 + 2*lineAttributes["markeredgewidth"]) + 1 markerSize = lineAttributes["markersize"] if(useValue): renderer = Renderer(pixmapWidth, height, Value(dpi)) else: renderer = Renderer(pixmapWidth, height, dpi) linePos = int(height / 2 + 1) sampleLine = Line2D([markerSize, pixmapWidth - markerSize], [linePos, linePos], **lineAttributes) sampleLine.draw(renderer) lineImageStr = renderer.tostring_argb() lineARGB = [map(ord, lineImageStr[i:i+4]) for i in xrange(0, len(lineImageStr), 4)] image = QtGui.QImage(pixmapWidth, height, QtGui.QImage.Format_ARGB32) for x in xrange(pixmapWidth): for y in xrange(int(height)): argb = lineARGB[x + y * pixmapWidth] image.setPixel(x, y, QtGui.qRgba(argb[1], argb[2], argb[3], argb[0])) return image
def write_header(self): from matplotlib.backends.backend_agg import RendererAgg try: from matplotlib.transforms import Value except ImportError: dpi = 72 else: dpi = Value(72) self.renderer = RendererAgg(self.w, self.h, dpi)
def __init__(self, html): self.original_fontsize = 22 self.fontsize = self.original_fontsize self.figwidth = 20 self.dpi = 100 self.text_fig = Figure(dpi=self.dpi) self.renderer = RendererAgg(20, 4, self.dpi) self.rows, self.num_header_rows = self.parse_html(html) self.col_widths = self.calculate_col_widths() self.row_heights = self.get_row_heights() self.fig = self.create_figure()
def render_figure_as_image(self, wFig, hFig, dpi): """ Renders a Matplotlib figure using the Agg backend and stores the result in a class:`wx.Image`. The arguments *wFig* and *hFig* are the width and the height of the figure, and *dpi* is the dots-per-inch to render at. """ figure = self.figure # Set new DPI, width, and height in inches old_dpi = figure.get_dpi() figure.set_dpi(dpi) old_width = figure.get_figwidth() figure.set_figwidth(wFig) old_height = figure.get_figheight() figure.set_figheight(hFig) old_frameon = figure.get_frameon() figure.set_frameon(False) # Width and height in pixels wFig_Px = int(figure.bbox.width) hFig_Px = int(figure.bbox.height) # Get renderer and use it to draw the figure # agg = RendererAgg(wFig_Px, hFig_Px, Value(dpi)) agg = RendererAgg(wFig_Px, hFig_Px, dpi) figure.draw(agg) # reset back to old DPI, width and height in inches figure.set_dpi(old_dpi) figure.set_figwidth(old_width) figure.set_figheight(old_height) figure.set_frameon(old_frameon) # Create an empty image and set it to rendered image image = wx.EmptyImage(wFig_Px, hFig_Px) image.SetData(agg.tostring_rgb()) return image
def write_header(self, resolution=72): from matplotlib.backends.backend_agg import RendererAgg, Figure from matplotlib.backend_bases import GraphicsContextBase try: from matplotlib.transforms import Value except ImportError: dpi = resolution else: dpi = Value(resolution) self.renderer = RendererAgg(self.w, self.h, dpi) self.figure = Figure() self.gc = GraphicsContextBase() self.gc.set_linewidth(.2)
class PNG(EPS): def write_header(self): from matplotlib.backends.backend_agg import RendererAgg dpi = 72 self.renderer = RendererAgg(self.w, self.h, dpi) def write_trailer(self): # The array conversion magic is necessary to make things work with # matplotlib 2.0.0, 3.2.x, and 3.3.0 at the same time. import matplotlib.image buf = self.renderer.buffer_rgba() # Buf is of type bytes (matplotlib < 3.3.0) or memoryview. # That might be an implementation detail. array = np.frombuffer(buf, dtype=np.uint8).reshape( int(self.h), int(self.w), 4) matplotlib.image.imsave( self.filename, array, format="png")
def test_empty_annotation_get_window_extent(): figure = Figure(dpi=100) figure.set_figwidth(2.0) figure.set_figheight(2.0) renderer = RendererAgg(200, 200, 100) # Text annotation with arrow annotation = Annotation( '', xy=(0.0, 50.0), xytext=(0.0, 50.0), xycoords='figure pixels') annotation.set_figure(figure) annotation.draw(renderer) bbox = annotation.get_window_extent() points = bbox.get_points() eq_(points[0, 0], 0.0) eq_(points[1, 0], 0.0) eq_(points[1, 1], 50.0) eq_(points[0, 1], 50.0)
def __init__(self, arr, reverse=True): from matplotlib.transforms import Affine2D, IdentityTransform from matplotlib.backends.backend_agg import RendererAgg self.arr = arr self.height, self.width, _ = self.arr.shape renderer = RendererAgg(self.width, self.height, 90) img = mpl.image.BboxImage(renderer.bbox) img.set_data(arr) img.draw(renderer) self.renderer = renderer if not reverse: self.trans_offset = self.trans = IdentityTransform() else: self.trans_offset = Affine2D().scale(1, -1) self.trans = Affine2D().scale(1, -1).translate(0, self.height) self.parameters = {}
# working directly with renderer and graphics contexts primitives from matplotlib.font_manager import FontProperties from matplotlib.backends.backend_agg import RendererAgg from matplotlib.transforms import Value # a 400x400 canvas at 72dpi canvas dpi = Value(72.0) o = RendererAgg(400,400, dpi) # the graphics context gc = o.new_gc() # draw the background white gc.set_foreground('w') face = (1,1,1) # white o.draw_rectangle(gc, face, 0, 0, 400, 400) # the gc's know about color strings, and can handle any matplotlib # color arguments (hex strings, rgb, format strings, etc) gc.set_foreground('g') gc.set_linewidth(4) face = (1,0,0) # must be rgb o.draw_rectangle(gc, face, 10, 50, 100, 200) # draw a translucent ellipse rgb = (0,0,1) gc.set_alpha(0.5) o.draw_arc(gc, rgb, 100, 100, 100, 100, 360, 360, 0) # draw a dashed line gc.set_dashes(0, [5, 10])
def draw_quadmesh(data, obj): '''Returns the PGFPlots code for an graphics environment holding a rendering of the object. ''' content = [] # Generate file name for current object if 'img number' not in data.keys(): data['img number'] = 0 filename = os.path.join(data['output dir'], '%s_img%03d.png' % (data['base name'], data['img number']) ) data['img number'] = data['img number'] + 1 # Get the dpi for rendering and store the original dpi of the figure dpi = data['dpi'] fig_dpi = obj.figure.get_dpi() obj.figure.set_dpi(dpi) # Render the object and save as png file from matplotlib.backends.backend_agg import RendererAgg cbox = obj.get_clip_box() width = int(round(cbox.extents[2])) height = int(round(cbox.extents[3])) ren = RendererAgg(width, height, dpi) obj.draw(ren) # Generate a image from the render buffer image = Image.frombuffer('RGBA', ren.get_canvas_width_height(), ren.buffer_rgba(), 'raw', 'RGBA', 0, 1) # Crop the image to the actual content (removing the the regions otherwise # used for axes, etc.) # 'image.crop' expects the crop box to specify the left, upper, right, and # lower pixel. 'cbox.extents' gives the left, lower, right, and upper # pixel. box = (int(round(cbox.extents[0])), 0, int(round(cbox.extents[2])), int(round(cbox.extents[3] - cbox.extents[1]))) cropped = image.crop(box) cropped.save(filename) # Restore the original dpi of the figure obj.figure.set_dpi(fig_dpi) # write the corresponding information to the TikZ file extent = obj.axes.get_xlim() + obj.axes.get_ylim() if data['rel data path']: rel_filepath = os.path.join(data['rel data path'], os.path.basename(filename) ) else: rel_filepath = os.path.basename(filename) # Explicitly use \pgfimage as includegrapics command, as the default # \includegraphics fails unexpectedly in some cases content.append('\\addplot graphics [includegraphics cmd=\pgfimage,' 'xmin=%.15g, xmax=%.15g, ' 'ymin=%.15g, ymax=%.15g] {%s};\n' % (extent + (rel_filepath,)) ) return data, content
class ImageMaskDrawer(HasTraits): mask_updated = Event drawed = Event is_dirty = Bool(False) def __init__(self, ax, img=None, mask_shape=None, canmove=True, size=None): self.canmove = canmove self.ax = ax if size is None: size = 10 self.bbox = mtrans.Bbox(np.array([[0, 0], [10, 10]])) bbox = mtrans.TransformedBbox(self.bbox, ax.transData) self.mask_img = mimage.BboxImage(bbox, animated=True, alpha=0.6, zorder=1000) self.ax.add_artist(self.mask_img) self.create_mask(img, mask_shape) self.canvas = ax.figure.canvas self.event_ids = [ self.canvas.mpl_connect('motion_notify_event', self.on_move), self.canvas.mpl_connect('draw_event', self.on_draw), self.canvas.mpl_connect('button_press_event', self.on_press), self.canvas.mpl_connect('button_release_event', self.on_release), self.canvas.mpl_connect('scroll_event', self.on_scroll), ] self.circle = mpatches.Circle((0, 0), size, facecolor="red", alpha=0.5, animated=True) self.ax.add_patch(self.circle) self.mask_circle = mpatches.Circle((0, 0), 10, facecolor="white", lw=0) self.mask_line = plt.Line2D((0, 0), (0, 0), lw=18, solid_capstyle="round", color="white") self.background = None self.last_pos = None self.timer = Timer(40, self.check_dirty) def remove(self): self.mask_img.remove() self.circle.remove() for event_id in self.event_ids: self.canvas.mpl_disconnect(event_id) def check_dirty(self): if self.is_dirty: self._update() self.is_dirty = False def create_mask(self, img=None, mask_shape=None): if mask_shape is None: self.height, self.width = img.shape[:2] else: self.height, self.width = mask_shape self.renderer = RendererAgg(self.width, self.height, 90) buf = self.renderer.buffer_rgba() arr = np.frombuffer(buf, np.uint8) self.array = arr.reshape(self.height, self.width, 4) self.mask_img.set_data(self.array) self.bbox.set_points(np.array([[0, 0], [self.width, self.height]])) def clear_mask(self): self.array[:, :, :-1] = 255 self.array[:, :, -1] = 0 def get_mask_array(self): return self.array[:, :, -1].copy() def get_mask_offset(self): box = self.mask_img.bbox._bbox return box.x0, box.y0 def on_scroll(self, event): radius = self.circle.get_radius() radius += event.step radius = max(3, min(30, radius)) self.circle.set_radius(radius) self.mask_circle.set_radius(radius) self.mask_line.set_linewidth(radius * 2 - 2) self._update() def transform_pos(self, x, y): box = self.mask_img.bbox._bbox return x - box.x0, y - box.y0 def on_press(self, event): buttons = (1, 3) if self.canmove else (1, ) if event.button in buttons and event.inaxes is self.ax: self.mask_img.set_visible(True) self.img_pos = self.mask_img.bbox._bbox.get_points() self.last_pos = self.transform_pos(event.xdata, event.ydata) self.last_pos2 = event.xdata, event.ydata self.mask_circle.center = self.last_pos if event.button == 1: self.mask_circle.draw(self.renderer) self.mask_updated = True self.mask_img.set_array(self.array) self.is_dirty = True def on_release(self, event): self.last_pos = None if event.button == 1 and event.inaxes is self.ax: self.drawed = True def on_draw(self, event): self.background = self.canvas.copy_from_bbox(self.ax.bbox) self.mask_img.set_array(self.array) self.ax.draw_artist(self.mask_img) if self.circle.get_visible(): self.ax.draw_artist(self.circle) self.canvas.blit(self.ax.bbox) def on_move(self, event): self.is_dirty = True if event.inaxes != self.ax: self.circle.set_visible(False) return self.circle.set_visible(True) self.circle.center = event.xdata, event.ydata if event.button == 1 and self.last_pos is not None: pos = self.transform_pos(event.xdata, event.ydata) self.mask_line.set_data((self.last_pos[0], pos[0]), (self.last_pos[1], pos[1])) self.mask_line.draw(self.renderer) self.last_pos = pos self.mask_updated = True if self.canmove and event.button == 3 and self.last_pos is not None: xdata, ydata = event.xdata, event.ydata dx = self.last_pos2[0] - xdata dy = self.last_pos2[1] - ydata new_pos = self.img_pos - [dx, dy] self.mask_img.bbox._bbox.set_points(new_pos) self.mask_img.bbox.invalidate() def _update(self): if self.background is not None: self.canvas.restore_region(self.background) self.mask_img.set_array(self.array) self.ax.draw_artist(self.mask_img) if self.circle.get_visible(): self.ax.draw_artist(self.circle) self.canvas.blit(self.ax.bbox) def update(self): # self.mask_img.set_array(self.array) self._update() def hide_mask(self): self.mask_img.set_visible(False) def show_mask(self): self.mask_img.set_visible(True)
# working directly with renderer and graphics contexts primitives from matplotlib.font_manager import FontProperties from matplotlib.backends.backend_agg import RendererAgg from matplotlib.transforms import Value # a 400x400 canvas at 72dpi canvas dpi = Value(72.0) o = RendererAgg(400, 400, dpi) # the graphics context gc = o.new_gc() # draw the background white gc.set_foreground('w') face = (1, 1, 1) # white o.draw_rectangle(gc, face, 0, 0, 400, 400) # the gc's know about color strings, and can handle any matplotlib # color arguments (hex strings, rgb, format strings, etc) gc.set_foreground('g') gc.set_linewidth(4) face = (1, 0, 0) # must be rgb o.draw_rectangle(gc, face, 10, 50, 100, 200) # draw a translucent ellipse rgb = (0, 0, 1) gc.set_alpha(0.5) o.draw_arc(gc, rgb, 100, 100, 100, 100, 360, 360, 0) # draw a dashed line gc.set_dashes(0, [5, 10])
def _renderer(self, fd): from matplotlib.backends.backend_agg import RendererAgg dpi = 72 return RendererAgg(self.w, self.h, dpi)
class FigureCanvasWxAggModGL(FigureCanvasWxAggMod): glcanvas = None def __init__(self, *args, **kwargs): FigureCanvasWxAggMod.__init__(self, *args, **kwargs) if FigureCanvasWxAggModGL.glcanvas is None: win = wx.GetApp().TopWindow glcanvas = MyGLCanvas(win) FigureCanvasWxAggModGL.glcanvas = glcanvas glcanvas.SetMinSize((2, 2)) glcanvas.SetMaxSize((2, 2)) # self.SetSizer(wx.BoxSizer(wx.HORIZONTAL)) win.GetSizer().Add(glcanvas) win.Layout() glcanvas.Refresh() def get_renderer(self, cleared=False): l, b, w, h = self.figure.bbox.bounds key = w, h, self.figure.dpi try: self._lastKey, self.renderer except AttributeError: need_new_renderer = True else: need_new_renderer = (self._lastKey != key) if need_new_renderer: self.renderer = RendererAgg(w, h, self.figure.dpi) mixin_gl_renderer(self.renderer) self._lastKey = key elif cleared: self.renderer.clear() return self.renderer def draw(self, *args, **kargs): self._update_hl_color() return FigureCanvasWxAggMod.draw(self, *args, **kargs) def draw_artist(self, drawDC=None, alist=None): if alist is None: alist = [] gl_obj = [a for a in alist if hasattr(a, 'is_gl')] for o in gl_obj: o.is_last = False if len(gl_obj) > 0: gl_obj[-1].is_last = True self.renderer._k_globj = 0 self.renderer._num_globj = len(gl_obj) self.renderer.no_update_id() # self.renderer.no_lighting = no_lighting self._update_hl_color() FigureCanvasWxAggModGL.glcanvas._artist_mask = alist v = FigureCanvasWxAggMod.draw_artist(self, drawDC=drawDC, alist=alist) # self.renderer.no_lighting = False return v def _update_hl_color(self): value = self.hl_color vv = list([float(x) for x in value]) + [1.0] vv[3] = 0.65 FigureCanvasWxAggModGL.glcanvas._hl_color = tuple(vv[:4]) def _onPaint(self, evt): # self.glcanvas.OnPaint(evt) # evt.Skip() FigureCanvasWxAggMod._onPaint(self, evt) def _onSize(self, evt=None, nocheck=False): FigureCanvasWxAggMod._onSize(self, evt=evt, nocheck=nocheck) # self.glcanvas.SetSize(self.bitmap.GetSize()) def disable_alpha_blend(self): FigureCanvasWxAggModGL.glcanvas._alpha_blend = False def enable_alpha_blend(self): FigureCanvasWxAggModGL.glcanvas._alpha_blend = True
def test_renderer(): from matplotlib.backends.backend_agg import RendererAgg renderer = RendererAgg(10, 20, 30) pickle.dump(renderer, BytesIO())
class FigureCanvasWxAggModGL(FigureCanvasWxAggMod): glcanvas = None def __init__(self, *args, **kwargs): FigureCanvasWxAggMod.__init__(self, *args, **kwargs) if FigureCanvasWxAggModGL.glcanvas is None: win = wx.GetApp().TopWindow glcanvas = load_glcanvas()(win) FigureCanvasWxAggModGL.glcanvas = glcanvas glcanvas.SetMinSize((2,2)) glcanvas.SetMaxSize((2,2)) #self.SetSizer(wx.BoxSizer(wx.HORIZONTAL)) win.GetSizer().Add(glcanvas) win.Layout() glcanvas.Refresh() def get_renderer(self, cleared=False): l, b, w, h = self.figure.bbox.bounds key = w, h, self.figure.dpi try: self._lastKey, self.renderer except AttributeError: need_new_renderer = True else: need_new_renderer = (self._lastKey != key) if need_new_renderer: self.renderer = RendererAgg(w, h, self.figure.dpi) mixin_gl_renderer(self.renderer) self._lastKey = key elif cleared: self.renderer.clear() return self.renderer def draw(self, *args, **kargs): self._update_hl_color() return FigureCanvasWxAggMod.draw(self, *args, **kargs) def draw_artist(self, drawDC=None, alist=None): if alist is None: alist = [] gl_obj = [a for a in alist if hasattr(a, 'is_gl')] for o in gl_obj: o.is_last = False if len(gl_obj) > 0: gl_obj[-1].is_last = True self.renderer._k_globj = 0 self.renderer._num_globj = len(gl_obj) self.renderer.no_update_id() # self.renderer.no_lighting = no_lighting self._update_hl_color() FigureCanvasWxAggModGL.glcanvas._artist_mask = alist v = FigureCanvasWxAggMod.draw_artist(self, drawDC=drawDC, alist=alist) # self.renderer.no_lighting = False return v def _update_hl_color(self): value = self.hl_color vv = list([float(x) for x in value]) + [1.0] vv[3] = 0.65 FigureCanvasWxAggModGL.glcanvas._hl_color = tuple(vv[:4]) def _onPaint(self, evt): # self.glcanvas.OnPaint(evt) # evt.Skip() FigureCanvasWxAggMod._onPaint(self, evt) def _onSize(self, evt=None, nocheck=False): FigureCanvasWxAggMod._onSize(self, evt = evt, nocheck = nocheck) #self.glcanvas.SetSize(self.bitmap.GetSize()) def disable_alpha_blend(self): FigureCanvasWxAggModGL.glcanvas._alpha_blend = False def enable_alpha_blend(self): FigureCanvasWxAggModGL.glcanvas._alpha_blend = True
def write_header(self): from matplotlib.backends.backend_agg import RendererAgg dpi = 72 self.renderer = RendererAgg(self.w, self.h, dpi)
class ImageMaskDrawer(HasTraits): mask_updated = Event drawed = Event def __init__(self, ax, img=None, mask_shape=None, canmove=True, size=None): self.canmove = canmove self.ax = ax if size is None: size = 10 self.bbox = mtrans.Bbox(np.array([[0, 0], [10, 10]])) bbox = mtrans.TransformedBbox(self.bbox, ax.transData) self.mask_img = mimage.BboxImage(bbox, animated=True, alpha=0.6, zorder=1000) self.ax.add_artist(self.mask_img) self.create_mask(img, mask_shape) self.canvas = ax.figure.canvas self.canvas.mpl_connect('motion_notify_event', self.on_move) self.canvas.mpl_connect('draw_event', self.on_draw) self.canvas.mpl_connect('button_press_event', self.on_press) self.canvas.mpl_connect('button_release_event', self.on_release) self.canvas.mpl_connect('scroll_event', self.on_scroll) self.circle = mpatches.Circle((0, 0), size, facecolor="red", alpha=0.5, animated=True) self.ax.add_patch(self.circle) self.mask_circle = mpatches.Circle((0, 0), 10, facecolor="white", lw=0) self.mask_line = plt.Line2D((0, 0), (0, 0), lw=18, solid_capstyle="round", color="white") self.background = None self.last_pos = None def create_mask(self, img=None, mask_shape=None): if mask_shape is None: self.height, self.width = img.shape[:2] else: self.height, self.width = mask_shape self.renderer = RendererAgg(self.width, self.height, 90) buf = self.renderer.buffer_rgba() arr = np.frombuffer(buf, np.uint8) self.array = arr.reshape(self.height, self.width, 4) self.mask_img.set_data(self.array) self.bbox.set_points(np.array([[0, 0], [self.width, self.height]])) def clear_mask(self): self.array[:, :, :-1] = 255 self.array[:, :, -1] = 0 def get_mask_array(self): return self.array[:, :, -1].copy() def get_mask_offset(self): box = self.mask_img.bbox._bbox return box.x0, box.y0 def on_scroll(self, event): radius = self.circle.get_radius() radius += event.step radius = max(3, min(30, radius)) self.circle.set_radius(radius) self.mask_circle.set_radius(radius) self.mask_line.set_linewidth(radius*2 - 2) self._update() def transform_pos(self, x, y): box = self.mask_img.bbox._bbox return x - box.x0, y - box.y0 def on_press(self, event): buttons = (1, 3) if self.canmove else (1, ) if event.button in buttons and event.inaxes is self.ax: self.mask_img.set_visible(True) self.mask_img.set_animated(True) self.canvas.draw() self.img_pos = self.mask_img.bbox._bbox.get_points() self.last_pos = self.transform_pos(event.xdata, event.ydata) self.last_pos2 = event.xdata, event.ydata self.mask_circle.center = self.last_pos if event.button == 1: self.mask_circle.draw(self.renderer) self.mask_updated = True self.mask_img.set_array(self.array) self._update() def on_release(self, event): self.mask_img.set_animated(False) self.last_pos = None self.canvas.draw() if event.button == 1 and event.inaxes is self.ax: self.drawed = True def on_draw(self, event): self.background = self.canvas.copy_from_bbox(self.ax.bbox) def on_move(self, event): if event.inaxes != self.ax: self.circle.set_visible(False) return self.circle.set_visible(True) self.circle.center = event.xdata, event.ydata if event.button == 1 and self.last_pos is not None: pos = self.transform_pos(event.xdata, event.ydata) self.mask_line.set_data((self.last_pos[0], pos[0]), (self.last_pos[1], pos[1])) self.mask_line.draw(self.renderer) self.last_pos = pos self.mask_img.set_array(self.array) self.mask_updated = True if self.canmove and event.button == 3 and self.last_pos is not None: xdata, ydata = event.xdata, event.ydata dx = self.last_pos2[0] - xdata dy = self.last_pos2[1] - ydata new_pos = self.img_pos - [dx, dy] self.mask_img.bbox._bbox.set_points(new_pos) self.mask_img.bbox.invalidate() self._update() def _update(self): if self.background is not None: self.canvas.restore_region(self.background) if self.mask_img.get_animated(): self.ax.draw_artist(self.mask_img) self.ax.draw_artist(self.circle) self.canvas.blit(self.ax.bbox) def update(self): self.mask_img.set_array(self.array) self._update() def hide_mask(self): self.mask_img.set_visible(False) def show_mask(self): self.mask_img.set_visible(True)