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_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 writeAsPNG(root, filename): from cairo import ImageSurface, Context, FORMAT_ARGB32 from rsvg import Handle img = ImageSurface(FORMAT_ARGB32, float(root.attrib["width"]),float(root.attrib["height"])) #test ctx = Context(img) handle = Handle(None, tostring(root)) handle.render_cairo(ctx) img.write_to_png(filename) return filename
class Canvas: def __init__(self, width, height): self.xform = lambda x, y: (x, y) self.img = ImageSurface(FORMAT_RGB24, width, height) self.ctx = Context(self.img) self.ctx.move_to(0, 0) self.ctx.line_to(width, 0) self.ctx.line_to(width, height) self.ctx.line_to(0, height) self.ctx.line_to(0, 0) self.ctx.set_source_rgb(1, 1, 1) self.ctx.fill() self.width = width self.height = height def fit(self, left, top, right, bottom): xoff = left yoff = top xscale = self.width / float(right - left) yscale = self.height / float(bottom - top) if abs(xscale) > abs(yscale): xscale *= abs(yscale) / abs(xscale) elif abs(xscale) < abs(yscale): yscale *= abs(xscale) / abs(yscale) self.xform = lambda x, y: ((x - xoff) * xscale, (y - yoff) * yscale) def dot(self, x, y, size=4, fill=(.5, .5, .5)): x, y = self.xform(x, y) self.ctx.arc(x, y, size/2., 0, 2*pi) self.ctx.set_source_rgb(*fill) self.ctx.fill() def line(self, points, stroke=(.5, .5, .5), width=1): self.ctx.move_to(*self.xform(*points[0])) for (x, y) in points[1:]: self.ctx.line_to(*self.xform(x, y)) self.ctx.set_source_rgb(*stroke) self.ctx.set_line_cap(LINE_CAP_ROUND) self.ctx.set_line_width(width) self.ctx.stroke() def save(self, filename): self.img.write_to_png(filename)
class Canvas: def __init__(self, width, height): self.xform = lambda x, y: (x, y) self.img = ImageSurface(FORMAT_RGB24, width, height) self.ctx = Context(self.img) self.ctx.move_to(0, 0) self.ctx.line_to(width, 0) self.ctx.line_to(width, height) self.ctx.line_to(0, height) self.ctx.line_to(0, 0) self.ctx.set_source_rgb(1, 1, 1) self.ctx.fill() self.width = width self.height = height def fit(self, left, top, right, bottom): xoff = left yoff = top xscale = self.width / float(right - left) yscale = self.height / float(bottom - top) if abs(xscale) > abs(yscale): xscale *= abs(yscale) / abs(xscale) elif abs(xscale) < abs(yscale): yscale *= abs(xscale) / abs(yscale) self.xform = lambda x, y: ((x - xoff) * xscale, (y - yoff) * yscale) def dot(self, x, y, size=4, fill=(.5, .5, .5)): x, y = self.xform(x, y) self.ctx.arc(x, y, size / 2., 0, 2 * pi) self.ctx.set_source_rgb(*fill) self.ctx.fill() def line(self, points, stroke=(.5, .5, .5), width=1): self.ctx.move_to(*self.xform(*points[0])) for (x, y) in points[1:]: self.ctx.line_to(*self.xform(x, y)) self.ctx.set_source_rgb(*stroke) self.ctx.set_line_cap(LINE_CAP_ROUND) self.ctx.set_line_width(width) self.ctx.stroke() def save(self, filename): self.img.write_to_png(filename)
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 plugmap(w, s, e, n): west = open_df.long.min() south = open_df.lat.min() east = open_df.long.max() north = open_df.lat.max() zoom = 5 # tiles = list(mercantile.tiles(west, south, east, north, zoom)) print(tiles) tile_size = (256, 256) # создаем пустое изображение в которое как мозайку будем вставлять тайлы # для начала просто попробуем отобразить все четыре тайла в строчку map_image = ImageSurface(FORMAT_ARGB32, tile_size[0] * len(tiles), tile_size[1]) # создаем контекст для рисования ctx = Context(map_image) for idx, t in enumerate(tiles): server = random.choice(['a', 'b', 'c' ]) # у OSM три сервера, распределяем нагрузку url = 'http://{server}.tile.openstreetmap.org/{zoom}/{x}/{y}.png'.format( server=server, zoom=t.z, x=t.x, y=t.y) # запрашиваем изображение response = urllib.request.urlopen(url) # создаем cairo изображние img = ImageSurface.create_from_png(io.BytesIO(response.read())) # рисуем изображение, с правильным сдвигом по оси x ctx.set_source_surface(img, idx * tile_size[0], 0) ctx.paint() # сохраняем собраное изображение в файл with open("map.png", "wb") as f: map_image.write_to_png(f)
[tags.pop() for x in range(len(segment) - 1)] VERTS.extend(verts) CODES.extend(codes) start = end+1 ctx.new_path() ctx.set_source_rgba(1,1,0, 0.5) i = 0 while (i < len(CODES)): if (CODES[i] == MOVETO): ctx.move_to(VERTS[i][0],VERTS[i][1]) i += 1 elif (CODES[i] == LINETO): ctx.line_to(VERTS[i][0],VERTS[i][1]) i += 1 elif (CODES[i] == CURVE3): ctx.curve_to(VERTS[i][0],VERTS[i][1], VERTS[i+1][0],VERTS[i+1][1], # undocumented VERTS[i+1][0],VERTS[i+1][1]) i += 2 elif (CODES[i] == CURVE4): ctx.curve_to(VERTS[i][0],VERTS[i][1], VERTS[i+1][0],VERTS[i+1][1], VERTS[i+2][0],VERTS[i+2][1]) i += 3 ctx.fill() surface.flush() surface.write_to_png("glyph-vector-cairo.png") Image.open("glyph-vector-cairo.png").show()
face = Face('./Vera.ttf') face.set_char_size( 4*48*64 ) flags = FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP face.load_char('S', flags ) slot = face.glyph glyph = slot.get_glyph() stroker = Stroker( ) stroker.set(64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 ) glyph.stroke( stroker , True ) blyph = glyph.to_bitmap(FT_RENDER_MODE_NORMAL, Vector(0,0), True ) bitmap = blyph.bitmap width, rows, pitch = bitmap.width, bitmap.rows, bitmap.pitch surface = ImageSurface(FORMAT_ARGB32, 600, 800) ctx = Context(surface) Z = make_image_surface(bitmap) ctx.set_source_surface(Z, 0, 0) scale = 640.0 / rows patternZ = ctx.get_source() SurfacePattern.set_filter(patternZ, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(300.0 - width *scale /2.0 ), -80) patternZ.set_matrix(scalematrix) ctx.set_source_rgb (0 , 0, 1) ctx.mask(patternZ) ctx.fill() surface.flush() surface.write_to_png("glyph-outline-cairo.png") Image.open("glyph-outline-cairo.png").show()
class Canvas: def __init__(self, width: int, height: Optional[int] = None, *, normalise: bool = True): if height is None: height = width self._width = width self._height = height self._surface = ImageSurface(FORMAT_ARGB32, width, height) self._context = Context(self._surface) self._normalise = normalise if self._normalise: self.scale(self._width, self._height) @property def width(self) -> int: return self._width if not self._normalise else 1 @property def height(self) -> int: return self._height if not self._normalise else 1 # TODO depreciate @property def context(self) -> Context: # pragma: no cover return self._context def save(self) -> None: self._context.save() def restore(self) -> None: self._context.restore() # Transformation def rotate(self, angle: float) -> None: self._context.rotate(angle) def translate(self, x: float, y: float) -> None: self._context.translate(x, y) def scale(self, width: int, height: int) -> None: self._context.scale(width, height) def set_line_width(self, width: float) -> None: self._context.set_line_width(width) # Colour functionality def set_colour(self, colour: Colour) -> None: self._context.set_source_rgba(colour.red, colour.blue, colour.green, colour.alpha) def set_grey(self, colour_value: float, alpha: float = 1) -> None: colour = Colour(*(colour_value, ) * 3, alpha) self.set_colour(colour) def set_black(self) -> None: self.set_colour(BLACK) def set_white(self) -> None: self.set_colour(WHITE) def set_background(self, colour: Colour) -> None: self._context.rectangle(0, 0, self.width, self.height) self.set_colour(colour) self._context.fill() def set_line_cap(self, line_cap: LineCap) -> None: self._context.set_line_cap(line_cap.value) def set_line_join(self, line_join: LineJoin) -> None: self._context.set_line_join(line_join.value) def set_fill_rule(self, file_rule: FillRule) -> None: self._context.set_fill_rule(file_rule.value) # Render methods def fill(self, preserve: bool = False) -> None: if not preserve: self._context.fill() else: self._context.fill_preserve() def stroke(self, preserve: bool = False) -> None: if not preserve: self._context.stroke() else: self._context.stroke_preserve() def clip(self) -> None: self._context.clip() def _draw_path(self, path: Iterable[Point], close_path: bool) -> None: self._context.new_sub_path() for p in path: self._context.line_to(*p) if close_path: self._context.close_path() def draw_path(self, path: Iterable[PointType], close_path: bool = False) -> None: points = (p if isinstance(p, Point) else Point(*p) for p in path) self._draw_path(points, close_path) def draw_polygon(self, polygon: Polygon) -> None: self._draw_path(polygon.points, close_path=True) def draw_circle(self, circle: Circle, fill: bool = False, stroke: bool = True) -> None: self._context.new_sub_path() self._context.arc(*circle.centre, circle.radius, 0, 2 * pi) def write_to_png(self, file_name: str) -> None: self._surface.write_to_png(file_name)
offset=pitch, strides=[pitch * 3, 1]) ndB = ndarray(shape=(rows, width), buffer=copybuffer, dtype=ubyte, order='C', offset=2 * pitch, strides=[pitch * 3, 1]) ndI = ndarray(shape=(rows, width), buffer=I.get_data(), dtype=uint32, order='C', strides=[I.get_stride(), 4]) # 255 * 2**24 = opaque ndI[:, :] = 255 * 2**24 + ndR[:, :] * 2**16 + ndG[:, :] * 2**8 + ndB[:, :] I.mark_dirty() ctx.set_source_surface(I, 0, 0) pattern = ctx.get_source() SurfacePattern.set_filter(pattern, FILTER_BEST) # Re-use the sane scale (LVD_V taller than LCD), # but adjust vertical position to line up mid-height of glyphs adjust = (rows - rows_old) * 240.0 / rows scalematrix.translate(-400, adjust) pattern.set_matrix(scalematrix) ctx.paint() # surface.flush() surface.write_to_png("glyph-lcd-cairo.png") Image.open("glyph-lcd-cairo.png").show()
offset=0, strides=[pitch*3, 1]) ndG = ndarray(shape=(rows,width), buffer=copybuffer, dtype=ubyte, order='C', offset=pitch, strides=[pitch*3, 1]) ndB = ndarray(shape=(rows,width), buffer=copybuffer, dtype=ubyte, order='C', offset=2*pitch, strides=[pitch*3, 1]) ndI = ndarray(shape=(rows,width), buffer=I.get_data(), dtype=uint32, order='C', strides=[I.get_stride(), 4]) # 255 * 2**24 = opaque ndI[:,:] = 255 * 2**24 + ndR[:,:] * 2**16 + ndG[:,:] * 2**8 + ndB[:,:] I.mark_dirty() ctx.set_source_surface(I, 0, 0) pattern = ctx.get_source() SurfacePattern.set_filter(pattern, FILTER_BEST) # Re-use the sane scale (LVD_V taller than LCD), # but adjust vertical position to line up mid-height of glyphs adjust = (rows - rows_old) * 240.0 /rows scalematrix.translate(-400, adjust) pattern.set_matrix(scalematrix) ctx.paint() # surface.flush() surface.write_to_png("glyph-lcd-cairo.png") Image.open("glyph-lcd-cairo.png").show()
I = ImageSurface(FORMAT_ARGB32, width, rows) try: ndI = np.ndarray(shape=(rows,width), buffer=I.get_data(), dtype=np.uint32, order='C', strides=[I.get_stride(), 4]) except NotImplementedError: raise SystemExit("For python 3.x, you need pycairo >= 1.11+ (from https://github.com/pygobject/pycairo)") # Although both are 32-bit, cairo is host-order while # freetype is small endian. ndI[:,:] = bitmap[:,:,3] * 2**24 + bitmap[:,:,2] * 2**16 + bitmap[:,:,1] * 2**8 + bitmap[:,:,0] # ndI[...] = (bitmap*(1,2**8,2**16,2**24)).sum(axis=-1) I.mark_dirty() surface = ImageSurface(FORMAT_ARGB32, 2*width, rows) ctx = Context(surface) ctx.set_source_surface(I, 0, 0) ctx.paint() ctx.set_source_surface(I, width/2, 0) ctx.paint() ctx.set_source_surface(I, width , 0) ctx.paint() surface.write_to_png("emoji-color-cairo.png") Image.open("emoji-color-cairo.png").show()
FT_LOAD_TARGET_MONO ) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch glyph_surface = make_image_surface(face.glyph.bitmap) surface = ImageSurface(FORMAT_ARGB32, 800, 600) ctx = Context(surface) ctx.rectangle(0,0,800,600) ctx.set_line_width(0) ctx.set_source_rgb (0.5 , 0.5, 0.5) ctx.fill() # scale = 480.0 / rows ctx.set_source_surface(glyph_surface, 0, 0) pattern = ctx.get_source() SurfacePattern.set_filter(pattern, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(400.0 - width *scale /2.0 ), -60) pattern.set_matrix(scalematrix) ctx.set_source_rgb (0 , 0, 1) ctx.mask(pattern) ctx.fill() surface.flush() surface.write_to_png("glyph-mono+alpha-cairo.png") Image.open("glyph-mono+alpha-cairo.png").show()
raise RuntimeError('pitch != width * 4 for color bitmap: Please report this.') bitmap = np.array(bitmap.buffer, dtype=np.uint8).reshape((bitmap.rows,bitmap.width,4)) I = ImageSurface(FORMAT_ARGB32, width, rows) try: ndI = np.ndarray(shape=(rows,width), buffer=I.get_data(), dtype=np.uint32, order='C', strides=[I.get_stride(), 4]) except NotImplementedError: raise SystemExit("For python 3.x, you need pycairo >= 1.11+ (from https://github.com/pygobject/pycairo)") # Although both are 32-bit, cairo is host-order while # freetype is small endian. ndI[:,:] = bitmap[:,:,3] * 2**24 + bitmap[:,:,2] * 2**16 + bitmap[:,:,1] * 2**8 + bitmap[:,:,0] I.mark_dirty() surface = ImageSurface(FORMAT_ARGB32, 2*width, rows) ctx = Context(surface) ctx.set_source_surface(I, 0, 0) ctx.paint() ctx.set_source_surface(I, width/2, 0) ctx.paint() ctx.set_source_surface(I, width , 0) ctx.paint() surface.write_to_png("emoji-color-cairo.png") Image.open("emoji-color-cairo.png").show()
face.load_char('S', FT_LOAD_RENDER | FT_LOAD_TARGET_MONO) bitmap = face.glyph.bitmap width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows pitch = face.glyph.bitmap.pitch glyph_surface = make_image_surface(face.glyph.bitmap) surface = ImageSurface(FORMAT_ARGB32, 800, 600) ctx = Context(surface) ctx.rectangle(0, 0, 800, 600) ctx.set_line_width(0) ctx.set_source_rgb(0.5, 0.5, 0.5) ctx.fill() # scale = 480.0 / rows ctx.set_source_surface(glyph_surface, 0, 0) pattern = ctx.get_source() SurfacePattern.set_filter(pattern, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0 / scale, 1.0 / scale) scalematrix.translate(-(400.0 - width * scale / 2.0), -60) pattern.set_matrix(scalematrix) ctx.set_source_rgb(0, 0, 1) ctx.mask(pattern) ctx.fill() surface.flush() surface.write_to_png("glyph-mono+alpha-cairo.png") Image.open("glyph-mono+alpha-cairo.png").show()
ctx.set_source_rgb(1, 1, 0) ctx.mask(patternF) ctx.fill() scalematrix.translate(+400, 0) patternF.set_matrix(scalematrix) ctx.mask(patternF) ctx.fill() # stroke on top ctx.set_source_surface(Z, 0, 0) patternZ = ctx.get_source() SurfacePattern.set_filter(patternZ, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0 / scale, 1.0 / scale) scalematrix.translate(-(600.0 - widthZ * scale / 2.0), -50) patternZ.set_matrix(scalematrix) ctx.set_source_rgb(1, 0, 0) ctx.mask(patternZ) ctx.fill() scalematrix.translate(-400, 0) patternZ.set_matrix(scalematrix) ctx.mask(patternZ) ctx.fill() surface.flush() surface.write_to_png("glyph-color-cairo.png") Image.open("glyph-color-cairo.png").show()
Z = ImageSurface(FORMAT_A8, int(round(height+0.5)), int(round(width+0.5))) ctx = Context(Z) if (wantRotate): ctx.set_matrix(Matrix(xx=0.0,xy=-1.0,yx=1.0,yy=0.0,x0=height)) # Second pass for actual rendering x, y = -sc(glyph_extents[0].x_bearing + positions[0].x_offset), height + sc(min_iy) if (emulate_default): x = 16 y = sc(font_extents.asscender) + 16 if (wantTTB): x = sc(max_ix) y = sc(max_iy) for info,pos,extent in zip(infos, positions, glyph_extents): face.load_glyph(info.codepoint) x += sc(extent.x_bearing + pos.x_offset) y -= sc(extent.y_bearing + pos.y_offset) # cairo does not like zero-width bitmap from the space character! if (face.glyph.bitmap.width > 0): glyph_surface = make_image_surface(face.glyph.bitmap) ctx.set_source_surface(glyph_surface, x, y) ctx.paint() x += sc(pos.x_advance - extent.x_bearing - pos.x_offset) y -= sc(pos.y_advance - extent.y_bearing - pos.y_offset) Z.flush() Z.write_to_png("hb-view.png") Image.open("hb-view.png").show() ### Derived from freetype-py:examples/hello-world-cairo.py ends. #####################################################################
baseline = max(baseline, max(0,-(slot.bitmap_top-bitmap.rows))) kerning = face.get_kerning(previous, c) width += (slot.advance.x >> 6) + (kerning.x >> 6) previous = c Z = ImageSurface(FORMAT_A8, width, height) ctx = Context(Z) # Second pass for actual rendering x, y = 0, 0 previous = 0 for c in text: face.load_char(c) bitmap = slot.bitmap top = slot.bitmap_top left = slot.bitmap_left w,h = bitmap.width, bitmap.rows y = height-baseline-top kerning = face.get_kerning(previous, c) x += (kerning.x >> 6) # cairo does not like zero-width bitmap from the space character! if (bitmap.width > 0): glyph_surface = make_image_surface(face.glyph.bitmap) ctx.set_source_surface(glyph_surface, x, y) ctx.paint() x += (slot.advance.x >> 6) previous = c Z.flush() Z.write_to_png("hello-world-cairo.png") Image.open("hello-world-cairo.png").show()
y0 = H//2 + (random.uniform()-.1)*50 for dx,dy in spiral(): c = .25+.75*random.random() x = int(x0+dx) y = int(y0+dy) checked = False I.flush() if not (x <= w//2 or y <= h//2 or x >= (W-w//2) or y >= (H-h//2)): ndI = ndarray(shape=(h,w), buffer=I.get_data(), dtype=ubyte, order='C', offset=(x-w//2) + I.get_stride() * (y-h//2), strides=[I.get_stride(), 1]) ndL = ndarray(shape=(h,w), buffer=L.get_data(), dtype=ubyte, order='C', strides=[L.get_stride(), 1]) if ((ndI * ndL).sum() == 0): checked = True new_region = RectangleInt(x-w//2, y-h//2, w, h) if (checked or ( drawn_regions.contains_rectangle(new_region) == REGION_OVERLAP_OUT )): ctxI.set_source_surface(L, 0, 0) pattern = ctxI.get_source() scalematrix = Matrix() scalematrix.scale(1.0,1.0) scalematrix.translate(w//2 - x, h//2 - y) pattern.set_matrix(scalematrix) ctxI.set_source_rgba(c,c,c,c) ctxI.mask(pattern) drawn_regions.union(new_region) break I.flush() I.write_to_png("wordle-cairo.png") Image.open("wordle-cairo.png").show()
ctx.set_source_rgb (1 , 1, 0) ctx.mask(patternF) ctx.fill() scalematrix.translate(+400,0) patternF.set_matrix(scalematrix) ctx.mask(patternF) ctx.fill() # stroke on top ctx.set_source_surface(Z, 0, 0) patternZ = ctx.get_source() SurfacePattern.set_filter(patternZ, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(600.0 - widthZ *scale /2.0 ), -50) patternZ.set_matrix(scalematrix) ctx.set_source_rgb (1 , 0, 0) ctx.mask(patternZ) ctx.fill() scalematrix.translate(-400,0) patternZ.set_matrix(scalematrix) ctx.mask(patternZ) ctx.fill() surface.flush() surface.write_to_png("glyph-color-cairo.png") Image.open("glyph-color-cairo.png").show()
def _to_png(self, font, font_position=None, dst=None, limit=800, size=1500, tab_width=1500, padding_characters=""): """Use HB, FreeType and Cairo to produce a png for a table. Parameters ---------- font: DFont font_position: str Label indicating which font has been used. dst: str Path to output image. If no path is given, return in-memory """ # TODO (M Foley) better packaging for pycairo, freetype-py # and uharfbuzz. # Users should be able to pip install these bindings without needing # to install the correct libs. # A special mention to the individuals who maintain these packages. Using # these dependencies has sped up the process of creating diff images # significantly. It's an incredible age we live in. y_tab = int(1500 / 25) x_tab = int(tab_width / 64) width, height = 1024, 200 cells_per_row = int((width - x_tab) / x_tab) # Compute height of image x, y, baseline = x_tab, 0, 0 for idx, row in enumerate(self._data[:limit]): x += x_tab if idx % cells_per_row == 0: y += y_tab x = x_tab height += y height += 100 # draw image Z = ImageSurface(FORMAT_ARGB32, width, height) ctx = Context(Z) ctx.rectangle(0, 0, width, height) ctx.set_source_rgb(1, 1, 1) ctx.fill() # label image ctx.set_font_size(30) ctx.set_source_rgb(0.5, 0.5, 0.5) ctx.move_to(x_tab, 50) ctx.show_text("{}: {}".format(self.table_name, len(self._data))) ctx.move_to(x_tab, 100) if font_position: ctx.show_text("Font Set: {}".format(font_position)) if len(self._data) > limit: ctx.set_font_size(20) ctx.move_to(x_tab, 150) ctx.show_text( "Warning: {} different items. Only showing most serious {}". format(len(self._data), limit)) hb.ot_font_set_funcs(font.hbfont) # Draw glyphs x, y, baseline = x_tab, 200, 0 x_pos = x_tab y_pos = 200 for idx, row in enumerate(self._data[:limit]): string = "{}{}{}".format(padding_characters, row['string'], padding_characters) buf = self._shape_string(font, string, row['features']) char_info = buf.glyph_infos char_pos = buf.glyph_positions for info, pos in zip(char_info, char_pos): gid = info.codepoint font.ftfont.load_glyph(gid, flags=6) bitmap = font.ftslot.bitmap if bitmap.width > 0: ctx.set_source_rgb(0, 0, 0) glyph_surface = _make_image_surface( font.ftfont.glyph.bitmap, copy=False) ctx.set_source_surface( glyph_surface, x_pos + font.ftslot.bitmap_left + (pos.x_offset / 64.), y_pos - font.ftslot.bitmap_top - (pos.y_offset / 64.)) glyph_surface.flush() ctx.paint() x_pos += (pos.x_advance) / 64. y_pos += (pos.y_advance) / 64. x_pos += x_tab - (x_pos % x_tab) if idx % cells_per_row == 0: # add label if font_position: ctx.set_source_rgb(0.5, 0.5, 0.5) ctx.set_font_size(10) ctx.move_to(width - 20, y_pos) ctx.rotate(1.5708) ctx.show_text(font_position) ctx.set_source_rgb(0, 0, 0) ctx.rotate(-1.5708) # Start a new row y_pos += y_tab x_pos = x_tab Z.flush() if dst: Z.write_to_png(dst) else: img = StringIO() Z.write_to_png(img) return Image.open(img)
def _paint_panel(self, key, width, height, panel_h): self.db.IUD("update web_stat_panels set HEIGHT = %s where ID = %s" % (panel_h, key)) self.db.commit() color_x_line = (0.7, 0.7, 0.7) color_x_line_2 = (0.9, 0.9, 0.9) color_y_line = (0.9, 0.9, 0.9) color_y_line_date = (0.7, 0.7, 0.7) color_border = (0.5, 0.5, 0.5) left = 40 right = 10 bottom = 15 var_ids = "0" series = [0, 0, 0, 0] typ = 0 for row in self.db.select( "select SERIES_1, SERIES_2, SERIES_3, SERIES_4, TYP " " from web_stat_panels " " where ID = " + str(key) ): series = row var_ids = "%s, %s, %s, %s" % row[0:4] typ = row[4] width, height = int(width), int(height) if width <= 0: width = 300 if height <= 0: height = 150 interval = self.param("range") delta_x = 1 if interval == "-6 hour": delta_x = 6 * 3600 elif interval == "-12 hour": delta_x = 12 * 3600 elif interval == "-1 day": delta_x = 24 * 3600 elif interval == "-3 day": delta_x = 3 * 24 * 3600 elif interval == "-7 day": delta_x = 7 * 24 * 3600 elif interval == "-14 day": delta_x = 14 * 24 * 3600 elif interval == "-30 day": delta_x = 30 * 24 * 3600 elif interval == "-90 day": delta_x = 3 * 30 * 24 * 3600 elif interval == "-180 day": delta_x = 6 * 30 * 24 * 3600 elif interval == "-360 day": delta_x = 12 * 30 * 24 * 3600 min_x = int(self.param("start")) - delta_x // 2 max_x = min_x + delta_x min_x_q = min_x - delta_x # // 100 max_x_q = max_x + delta_x # // 100 max_y = -9999 min_y = 9999 # Делаем полную выборку данных. Выкидываем подозрительные точки и # собираем статистику. prev_vals = [-9999] * 4 chart_data = [[], [], [], []] zoom_step = delta_x / (width * 5) if zoom_step < 1 or typ != 0: zoom_step = 1 x_min_max_values = [] mi_x = max_x_q ma_x = min_x_q tt = -100 for row in self.db.select( "select UNIX_TIMESTAMP(CHANGE_DATE) D, MIN(VALUE) + (MAX(VALUE) - MIN(VALUE)) VALUE, VARIABLE_ID " " from core_variable_changes " " where VARIABLE_ID in (%s) " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " " group by 3, ROUND(UNIX_TIMESTAMP(CHANGE_DATE) / %s)" " order by 3, 1 " % (var_ids, min_x_q, max_x_q, zoom_step) ): ind = series.index(row[2]) chart_data[ind] += [row] if row[0] > min_x and row[0] < max_x: max_y = max(max_y, row[1]) min_y = min(min_y, row[1]) if tt == -100: tt = row[2] if tt != row[2]: v = [tt, mi_x, ma_x] x_min_max_values += [v] mi_x = max_x_q ma_x = min_x_q tt = row[2] if row[0] < mi_x: mi_x = row[0] if row[0] > ma_x: ma_x = row[0] if tt != -1: v = [tt, mi_x, ma_x] x_min_max_values += [v] # print(x_min_max_values) # print(series) """ for row in self.db.select("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "order by CHANGE_DATE " % (min_x_q, max_x_q)): """ """ try: self.db.IUD("set @rn := 0") sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "order by CHANGE_DATE " % (min_x_q, max_x_q)) for c in self.db.select("select count(*) c " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " % (min_x_q, max_x_q)): cou = c[0] ccc = 1000 * 4 if cou > ccc: sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, @rn := @rn + 1 rownum " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "having mod(rownum, %s) = 0 " "order by VARIABLE_ID, CHANGE_DATE " % (min_x_q, max_x_q, math.ceil(cou / ccc))) for row in self.db.select(sql): ind = series.index(row[2]) prev_vals[ind] = row[1] if abs(prev_vals[ind] - row[1]) < 10: chart_data[ind] += [row] if row[0] > min_x and row[0] < max_x: max_y = max(max_y, row[1]) min_y = min(min_y, row[1]) prev_vals[ind] = row[1] except: pass """ if min_y is None or max_y is None or min_y == 9999 or max_y == -9999 or min_y == max_y: max_y = 1 min_y = 0 min_y = math.floor(min_y) max_y = math.ceil(max_y) if typ == 2: if min_y < 0 and max_y < 0: max_y = 0 elif min_y > 0 and max_y > 0: min_y = 0 # Определяем цвета colors = [[1, 0, 0], [0, 0.65, 0.31], [0, 0, 1], [1, 0, 1]] off_y = (max_y - min_y) / 10 min_y -= off_y max_y += off_y try: kx = (max_x - min_x) / (width - left - right) ky = (max_y - min_y) / (height - bottom) if ky == 0: ky = 1 except: kx, ky = 1, 1 img = ImageSurface(FORMAT_ARGB32, width, height) ctx = Context(img) width -= right ctx.set_line_width(1) # Рисуем сетку ctx.set_font_size(12) try: b_w, b_h = ctx.text_extents("00-00-0000")[2:4] # Метки на оси Y count = math.ceil(max_y) - math.ceil(min_y) space_count = math.ceil(count / ((height - bottom) / (b_h * 1.5))) sc = 0 for i in range(math.ceil(min_y), math.ceil(max_y)): if sc == 0: y = height - bottom + (min_y - i) / ky ctx.set_source_rgb(*(color_x_line)) ctx.move_to(left, y) ctx.line_to(width, y) ctx.stroke() ctx.set_source_rgb(0, 0, 0) num = str(i) tw, th = ctx.text_extents(num)[2:4] ctx.move_to(left - 5 - tw, y + th // 2) ctx.show_text(num) sc = space_count sc -= 1 # Метки на оси Х x_step = 3600 if interval == "-6 hour" or interval == "-12 hour" or interval == "-1 day": # Дополнительно метки часов x_step = 3600 for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step)): x = (i * x_step - min_x) / kx + left ctx.set_source_rgb(*(color_x_line_2)) ctx.move_to(x, 0) ctx.line_to(x, height - bottom) ctx.stroke() num = datetime.datetime.fromtimestamp(i * x_step).strftime("%H") tw, th = ctx.text_extents(num)[2:4] ctx.move_to(x + 2, height - bottom - 3) ctx.set_source_rgb(*(color_x_line)) ctx.show_text(num) x_step = 3600 * 24 space_count = 1 count = math.ceil(max_x / x_step) - math.ceil(min_x / x_step) try: if (width / count) < b_w: space_count = 2 except: pass sc = 0 tz = 3600 * 2 tx_prev = -100 for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step) + 1): if sc == 0: d_i = datetime.datetime.fromtimestamp(i * x_step) x = (i * x_step - min_x - tz) / kx + left ctx.set_source_rgb(0, 0, 0) num = d_i.strftime("%d-%m-%Y %H") x -= (int(d_i.strftime("%H")) * 3600 - tz) / kx tw, th = ctx.text_extents(num)[2:4] tx = x - tw // 2 ctx.move_to(tx, height - bottom + th + 5) if tx - tx_prev > tw: ctx.show_text(num) tx_prev = tx ctx.set_source_rgb(*(color_y_line_date)) else: ctx.set_source_rgb(*(color_y_line)) if x >= left and x < width: ctx.move_to(x, 0) ctx.line_to(x, height - bottom) ctx.stroke() sc = space_count sc -= 1 except Exception as e: pass # Рисуем верхний и правый бордер ctx.set_source_rgb(*color_border) ctx.move_to(left, 0) ctx.line_to(width, 0) ctx.line_to(width, height - bottom) ctx.stroke() # Рисуем сами графики ctx.rectangle(left, 0, width - left, height) ctx.clip() is_first = True currVarID = -1 prevX = -1 if typ == 0: # Линейная for ind in range(4): """ if len(chart_data[ind]) > 0: for i in range(len(chart_data[ind]) - 1): chart_data[ind][i] = list(chart_data[ind][i]) r1 = chart_data[ind][i] r2 = chart_data[ind][i + 1] chart_data[ind][i][0] += (r2[0] - r1[0]) / 2 chart_data[ind][i][1] += (r2[1] - r1[1]) / 2 """ ctx.set_source_rgb(*colors[ind]) is_first = True for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky if is_first: ctx.move_to(x, y) else: if row[0] - prevX > 10000: ctx.move_to(x, y) else: ctx.line_to(x, y) prevX = row[0] is_first = False ctx.stroke() elif typ == 1: # Точечная for ind in range(4): if chart_data[ind]: ctx.set_source_rgb(*colors[ind]) for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky ctx.rectangle(x - 3, y - 3, 6, 6) ctx.fill() elif typ == 2: # Столбчатая cy = height - bottom - (-min_y) / ky for ind in range(4): for row in chart_data[ind]: if currVarID != row[2]: ctx.fill() for i in range(4): if series[i] == row[2]: ctx.set_source_rgb(*colors[i]) x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky ctx.rectangle(x - 5, y, 10, cy - y) currVarID = row[2] ctx.fill() else: # Линейчастая # one_vals = self._get_one_val(series, min_x_q, max_x_q) one_vals = self._get_one_val(series, x_min_max_values, min_x_q, max_x_q) for ind in range(4): if series[ind]: is_now = True for r in one_vals[ind]: if r[4] == 1: chart_data[ind].insert(0, r) else: chart_data[ind] += [r] is_now = False if is_now: if len(chart_data[ind]) > 0: r = list(chart_data[ind][len(chart_data[ind]) - 1]) r[0] = datetime.datetime.now().timestamp() chart_data[ind] += [r] color = colors[ind] color_fill = color.copy() color_fill += [0.3] is_first = True y0 = height - bottom + min_y / ky for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky if is_first: is_first = False else: ctx.set_source_rgb(*color) ctx.move_to(prevX, prevY) ctx.line_to(x, prevY) ctx.line_to(x, y) ctx.stroke() ctx.set_source_rgba(*color_fill) rx, ry, rw, rh = prevX, y0, x - prevX, prevY - y0 ctx.rectangle(rx, ry, rw, rh) ctx.fill() prevX, prevY = x, y # Рисуем оси ctx.set_source_rgb(0, 0, 0) ctx.move_to(left, 0) ctx.line_to(left, height - bottom) ctx.line_to(width, height - bottom) ctx.stroke() # --------------------------- del ctx byt = BytesIO() img.write_to_png(byt) byt.seek(0) return byt.read()