def convert_svg2png(infile, outfile, w, h): """ Converts svg files to png using Cairosvg or Inkscape @file_path : String; the svg file absolute path @dest_path : String; the png file absolute path """ if use_inkscape: cmd = Popen(["inkscape", "-z", "-f", infile, "-e", outfile, "-w", str(w), "-h", str(h)], stdout=PIPE, stderr=PIPE) cmd.communicate() else: handle = Rsvg.Handle() svg = handle.new_from_file(infile) dim = svg.get_dimensions() img = ImageSurface(FORMAT_ARGB32, w, h) ctx = Context(img) ctx.scale(w / dim.width, h / dim.height) svg.render_cairo(ctx) png_io = BytesIO() img.write_to_png(png_io) with open(outfile, 'wb') as fout: fout.write(png_io.getvalue()) svg.close() png_io.close() img.finish()
def convert_to_png(input_file, output_file, width=None, height=None): """Convert svg to png.""" if width and height: handle = Rsvg.Handle() svg = handle.new_from_file(input_file) dim = svg.get_dimensions() img = ImageSurface( FORMAT_ARGB32, width, height) ctx = Context(img) ctx.scale(width / dim.width, height / dim.height) svg.render_cairo(ctx) png_io = BytesIO() img.write_to_png(png_io) with open(output_file, 'wb') as fout: fout.write(png_io.getvalue()) fout.close() svg.close() png_io.close() img.finish() else: with open(input_file, "r") as content_file: svg = content_file.read() content_file.close() fout = open(output_file, "wb") svg2png(bytestring=bytes(svg, "UTF-8"), write_to=fout) fout.close()
def convert_svg2png(infile, outfile, w, h): """ Converts svg files to png using Cairosvg or Inkscape @file_path : String; the svg file absolute path @dest_path : String; the png file absolute path """ if use_inkscape: p = Popen(["inkscape", "-z", "-f", infile, "-e", outfile, "-w", str(w), "-h", str(h)], stdout=PIPE, stderr=PIPE) output, err = p.communicate() else: handle = Rsvg.Handle() svg = handle.new_from_file(infile) dim = svg.get_dimensions() img = ImageSurface(FORMAT_ARGB32, w, h) ctx = Context(img) ctx.scale(w / dim.width, h / dim.height) svg.render_cairo(ctx) png_io = BytesIO() img.write_to_png(png_io) with open(outfile, 'wb') as fout: fout.write(png_io.getvalue()) svg.close() png_io.close() img.finish()
def convert_to_png(input_file, output_file, width=None, height=None): """Convert svg to png.""" if width and height: handle = Rsvg.Handle() svg = handle.new_from_file(input_file) dim = svg.get_dimensions() img = ImageSurface(FORMAT_ARGB32, width, height) ctx = Context(img) ctx.scale(width / dim.width, height / dim.height) svg.render_cairo(ctx) png_io = BytesIO() img.write_to_png(png_io) with open(output_file, 'wb') as fout: fout.write(png_io.getvalue()) fout.close() svg.close() png_io.close() img.finish() else: with open(input_file, "r") as content_file: svg = content_file.read() content_file.close() fout = open(output_file, "wb") svg2png(bytestring=bytes(svg, "UTF-8"), write_to=fout) fout.close()
def svg_to_png(filename, icondata, w=128, h=128): if not SVG_TO_PNG: return None Rsvg = load_Rsvg() log("svg_to_png%s Rsvg=%s", (filename, "%i bytes" % len(icondata), w, h), Rsvg) if not Rsvg: return None try: from cairo import ImageSurface, Context, FORMAT_ARGB32 #pylint: disable=no-name-in-module, import-outside-toplevel #'\sinkscape:[a-zA-Z]*=["a-zA-Z0-9]*' img = ImageSurface(FORMAT_ARGB32, w, h) ctx = Context(img) handle = Rsvg.Handle.new_from_data(icondata) dim = handle.get_dimensions() ctx.scale(w / dim.width, h / dim.height) handle.render_cairo(ctx) del handle img.flush() buf = BytesIO() img.write_to_png(buf) icondata = buf.getvalue() buf.close() img.finish() return icondata except Exception: log("svg_to_png%s", (icondata, w, h), exc_info=True) if re.findall(INKSCAPE_RE, icondata): #try again after stripping the bogus inkscape attributes #as some rsvg versions can't handle that (ie: Debian Bullseye) icondata = re.sub(INKSCAPE_RE, b"", icondata) return svg_to_png(filename, icondata, w, h) if icondata.find(INKSCAPE_BROKEN_SODIPODI_DTD) > 0: icondata = icondata.replace(INKSCAPE_BROKEN_SODIPODI_DTD, INKSCAPE_SODIPODI_DTD) return svg_to_png(filename, icondata, w, h) log.error("Error: failed to convert svg icon") if filename: log.error(" '%s':", filename) log.error(" %i bytes, %s", len(icondata), ellipsizer(icondata)) return None
def _scale_down(self, handle, ratio): xsize, ysize = self.size if ratio >= 1.0: # Convert surface = ImageSurface(FORMAT_ARGB32, xsize, ysize) ctx = Context(surface) else: # Scale xsize, ysize = int(xsize * ratio), int(ysize * ratio) surface = ImageSurface(FORMAT_ARGB32, xsize, ysize) ctx = Context(surface) ctx.scale(ratio, ratio) # Render handle.render_cairo(ctx) # Transform to a PIL image for further manipulation size = (xsize, ysize) im = frombuffer('RGBA', size, surface.get_data(), 'raw', 'BGRA', 0, 1) surface.finish() return im, xsize, ysize
class CairoBackingBase(WindowBackingBase): HAS_ALPHA = envbool("XPRA_ALPHA", True) def __init__(self, wid, window_alpha, _pixel_depth=0): super().__init__(wid, window_alpha and self.HAS_ALPHA) self.idle_add = GLib.idle_add self.size = 0, 0 self.render_size = 0, 0 def init(self, ww: int, wh: int, bw: int, bh: int): mod = self.size != (bw, bh) or self.render_size != (ww, wh) self.size = bw, bh self.render_size = ww, wh if mod: self.create_surface() def get_info(self): info = super().get_info() info.update({ "type": "Cairo", "rgb-formats": self.RGB_MODES, }) return info def create_surface(self): bw, bh = self.size old_backing = self._backing #should we honour self.depth here? self._backing = None if bw == 0 or bh == 0: #this can happen during cleanup return None self._backing = ImageSurface(FORMAT_ARGB32, bw, bh) cr = Context(self._backing) cr.set_operator(OPERATOR_CLEAR) cr.set_source_rgba(1, 1, 1, 1) cr.rectangle(0, 0, bw, bh) cr.fill() if old_backing is not None: oldw, oldh = old_backing.get_width(), old_backing.get_height() sx, sy, dx, dy, w, h = self.gravity_copy_coords(oldw, oldh, bw, bh) cr.translate(dx - sx, dy - sy) cr.rectangle(sx, sy, w, h) cr.fill() cr.set_operator(OPERATOR_SOURCE) cr.set_source_surface(old_backing, 0, 0) cr.paint() self._backing.flush() return cr def close(self): if self._backing: self._backing.finish() WindowBackingBase.close(self) def cairo_paint_pixbuf(self, pixbuf, x: int, y: int, options): """ must be called from UI thread """ log("source pixbuf: %s", pixbuf) w, h = pixbuf.get_width(), pixbuf.get_height() self.cairo_paint_from_source(Gdk.cairo_set_source_pixbuf, pixbuf, x, y, w, h, w, h, options) def cairo_paint_surface(self, img_surface, x: int, y: int, width: int, height: int, options): iw, ih = img_surface.get_width(), img_surface.get_height() log("source image surface: %s", ( img_surface.get_format(), iw, ih, img_surface.get_stride(), img_surface.get_content(), )) def set_source_surface(gc, surface, sx, sy): gc.set_source_surface(surface, sx, sy) self.cairo_paint_from_source(set_source_surface, img_surface, x, y, iw, ih, width, height, options) def cairo_paint_from_source(self, set_source_fn, source, x: int, y: int, iw: int, ih: int, width: int, height: int, options): """ must be called from UI thread """ log("cairo_paint_surface%s backing=%s, paint box line width=%i", (set_source_fn, source, x, y, iw, ih, width, height, options), self._backing, self.paint_box_line_width) gc = Context(self._backing) if self.paint_box_line_width: gc.save() gc.rectangle(x, y, width, height) gc.clip() gc.set_operator(OPERATOR_CLEAR) gc.rectangle(x, y, width, height) gc.fill() gc.set_operator(OPERATOR_SOURCE) gc.translate(x, y) if iw != width or ih != height: gc.scale(width / iw, height / ih) gc.rectangle(0, 0, width, height) set_source_fn(gc, source, 0, 0) gc.paint() if self.paint_box_line_width: gc.restore() encoding = options.get("encoding") self.cairo_paint_box(gc, encoding, x, y, width, height) def cairo_paint_box(self, gc, encoding, x, y, w, h): color = get_paint_box_color(encoding) gc.set_line_width(self.paint_box_line_width) gc.set_source_rgba(*color) gc.rectangle(x, y, w, h) gc.stroke() def _do_paint_rgb16(self, img_data, x, y, width, height, render_width, render_height, rowstride, options): return self._do_paint_rgb(FORMAT_RGB16_565, False, img_data, x, y, width, height, render_width, render_height, rowstride, options) def _do_paint_rgb24(self, img_data, x: int, y: int, width: int, height: int, render_width: int, render_height: int, rowstride: int, options): return self._do_paint_rgb(FORMAT_RGB24, False, img_data, x, y, width, height, render_width, render_height, rowstride, options) def _do_paint_rgb30(self, img_data, x, y, width, height, render_width, render_height, rowstride, options): return self._do_paint_rgb(FORMAT_RGB30, True, img_data, x, y, width, height, render_width, render_height, rowstride, options) def _do_paint_rgb32(self, img_data, x: int, y: int, width: int, height: int, render_width: int, render_height: int, rowstride: int, options): if self._alpha_enabled: cformat = FORMAT_ARGB32 else: cformat = FORMAT_RGB24 return self._do_paint_rgb(cformat, True, img_data, x, y, width, height, render_width, render_height, rowstride, options) def _do_paint_rgb(self, *args): raise NotImplementedError() def get_encoding_properties(self): props = WindowBackingBase.get_encoding_properties(self) if SCROLL_ENCODING: props["encoding.scrolling"] = True return props def paint_scroll(self, img_data, options, callbacks): self.idle_add(self.do_paint_scroll, img_data, callbacks) def do_paint_scroll(self, scrolls, callbacks): old_backing = self._backing gc = self.create_surface() if not gc: fire_paint_callbacks(callbacks, False, message="no context") return gc.set_operator(OPERATOR_SOURCE) for sx, sy, sw, sh, xdelta, ydelta in scrolls: gc.set_source_surface(old_backing, xdelta, ydelta) x = sx + xdelta y = sy + ydelta gc.rectangle(x, y, sw, sh) gc.fill() if self.paint_box_line_width > 0: self.cairo_paint_box(gc, "scroll", x, y, sw, sh) del gc self._backing.flush() fire_paint_callbacks(callbacks) def nasty_rgb_via_png_paint(self, cairo_format, has_alpha: bool, img_data, x: int, y: int, width: int, height: int, rowstride: int, rgb_format): log.warn("nasty_rgb_via_png_paint%s", (cairo_format, has_alpha, len(img_data), x, y, width, height, rowstride, rgb_format)) #PIL fallback from PIL import Image if has_alpha: oformat = "RGBA" else: oformat = "RGB" #use frombytes rather than frombuffer to be compatible with python3 new-style buffers #this is slower, but since this codepath is already dreadfully slow, we don't care bdata = memoryview_to_bytes(img_data) src_format = rgb_format.replace("X", "A") try: img = Image.frombytes(oformat, (width, height), bdata, "raw", src_format, rowstride, 1) except ValueError as e: log("PIL Image frombytes:", exc_info=True) raise Exception("failed to parse raw %s data as %s to %s: %s" % (rgb_format, src_format, oformat, e)) from None #This is insane, the code below should work, but it doesn't: # img_data = bytearray(img.tostring('raw', oformat, 0, 1)) # pixbuf = new_from_data(img_data, COLORSPACE_RGB, True, 8, width, height, rowstride) # success = self.cairo_paint_pixbuf(pixbuf, x, y) #So we still rountrip via PNG: from io import BytesIO png = BytesIO() img.save(png, format="PNG") reader = BytesIO(png.getvalue()) png.close() img = ImageSurface.create_from_png(reader) self.cairo_paint_surface(img, x, y, width, height, {}) return True def cairo_draw(self, context): log( "cairo_draw: size=%s, render-size=%s, offsets=%s, pointer_overlay=%s", self.size, self.render_size, self.offsets, self.pointer_overlay) if self._backing is None: return #try: # log("clip rectangles=%s", context.copy_clip_rectangle_list()) #except: # log.error("clip:", exc_info=True) ww, wh = self.render_size w, h = self.size if ww == 0 or w == 0 or wh == 0 or h == 0: return if w != ww or h != wh: context.scale(ww / w, wh / h) x, y = self.offsets[:2] if x != 0 or y != 0: context.translate(x, y) context.set_operator(OPERATOR_SOURCE) context.set_source_surface(self._backing, 0, 0) context.paint() if self.pointer_overlay and self.cursor_data: px, py, _size, start_time = self.pointer_overlay[2:] spx = round(w * px / ww) spy = round(h * py / wh) cairo_paint_pointer_overlay(context, self.cursor_data, x + spx, y + spy, start_time)