Пример #1
0
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
Пример #2
0
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
Пример #3
0
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
Пример #4
0
    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)
Пример #5
0
    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)
Пример #6
0
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")
Пример #7
0
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)
Пример #8
0
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)
Пример #9
0
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