def render(out_file, contours, size): s = "" for contour in contours: for i, curve in enumerate(contour): for j, pair in enumerate(curve): pair = pair * size * 0.8 pair = pair.astype(np.int32) if (i == 0) and (j == 0): s += "M{:d},{:d} ".format(pair[0], pair[1]) elif j == 1: s += "Q{:d},{:d}".format(pair[0], pair[1]) elif j == 2: s += ",{:d},{:d} ".format(pair[0], pair[1]) img = Image.new("RGB", (size, size)) draw = aggdraw.Draw(img) outline = aggdraw.Pen("white", 1) fill = aggdraw.Brush("white") symbol = aggdraw.Symbol(s) pos = int(.1 * size) xy = (pos, pos) draw.symbol(xy, symbol, outline, fill) draw.flush() img = img.transpose(Image.FLIP_TOP_BOTTOM) img.save(out_file)
def create_noise_curve(image, number): w, h = image.size while number: x1 = random.randint(0, int(w / 5)) x2 = random.randint(int(w / 5), int(4 * w / 5)) x3 = random.randint(int(4 * w / 5), w) y1 = random.randint(0, int(2 * h / 5)) y2 = random.randint(int(2 * h / 5), h) y3 = random.randint(0, int(2 * h / 5)) points = [x1, y1, x2, y2, x3, y3] draw = aggdraw.Draw(image) # 2 is the outlinewidth in pixels color = random_color(10, 200, random.randint(220, 225)) outline = aggdraw.Pen(color, 2) # the pathstring: c for bezier curves (all lowercase letters for relative path) pathstring = "c" coord_len = len(points) for coord in points: if points.index(coord) == (coord_len - 1): pathstring += str(coord) else: pathstring += str(coord) + " " # xy position to place symbol xy = (x1, y1) symbol = aggdraw.Symbol(pathstring) draw.symbol(xy, symbol, outline) draw.flush() number -= 1 return image
def draw_symbol(self, polys): # draw global svg svg = "" for poly in polys: exterior = poly[0] if len(poly) > 1: holes = poly[1:] else: holes = [] def traverse_ring(coords): global svg # begin coords = (point for point in coords) startx,starty = next(coords) svg += " M%s,%s"%(startx, starty) # connect to each successive point for nextx,nexty in coords: svg += " L%s,%s"%(nextx, nexty) # first exterior traverse_ring(exterior) # then holes for hole in holes: # !!! need to test for ring direction !!! hole = (point for point in hole) traverse_ring(hole) self.drawer.symbol((0,0), aggdraw.Symbol(svg.strip()), self.pen, self.brush)
def traverse_curvelines(coords): pathstring = "" # begin coords = pairwise(grouper(coords, 2)) (startx, starty), (endx, endy) = next(coords) pathstring += " M%s,%s" % (startx, starty) # draw straight line to first line midpoint midx, midy = (endx + startx) / 2.0, (endy + starty) / 2.0 pathstring += " L%s,%s" % (midx, midy) oldmidx, oldmidy = midx, midy # for each line for line in coords: # curve from midpoint of first to midpoint of second (startx, starty), (endx, endy) = line midx, midy = (endx + startx) / 2.0, (endy + starty) / 2.0 pathstring += " Q%s,%s,%s,%s" % (startx, starty, midx, midy) oldmidx, oldmidy = midx, midy # draw straight line to endpoint of last line pathstring += " L%s,%s" % (endx, endy) # make into symbol object symbol = aggdraw.Symbol(pathstring) return symbol
def draw(anchor, commands, coords, canvas, pen, brush=None): aggdraw_path_string = get_aggdraw_path_string(commands, coords) symbol = aggdraw.Symbol(aggdraw_path_string) if brush == None: canvas.symbol(anchor, symbol, pen) else: canvas.symbol(anchor, symbol, pen, brush)
def display_vectorized(self, vmobject, canvas): if vmobject.is_subpath: #Subpath vectorized mobjects are taken care #of by their parent return pen, fill = self.get_pen_and_fill(vmobject) pathstring = self.get_pathstring(vmobject) symbol = aggdraw.Symbol(pathstring) canvas.symbol((0, 0), symbol, pen, fill)
def bezier(self, ctx, p0, p1, p2, p3): ax, ay = p0 bx, by = p1 cx, cy = p2 dx, dy = p3 pathstring = " m{:f},{:f} c{:f},{:f},{:f},{:f},{:f},{:f}".format( ax, ay, bx, by, cx, cy, dx, dy) symbol = aggdraw.Symbol(pathstring) ctx.symbol((0, 0), symbol, aggdraw.Pen((255, 0, 0)))
def _draw_subpath(subpath, width, height): from PIL import Image import aggdraw mask = Image.new('L', (width, height), 0) path = ' '.join(map(str, _generate_symbol(subpath, width, height))) draw = aggdraw.Draw(mask) brush = aggdraw.Brush(255) symbol = aggdraw.Symbol(path) draw.symbol((0, 0), symbol, None, brush) draw.flush() del draw return mask
def showImage(_list_xy): im = Image.open(path).convert("RGBA") drawT = ImageDraw.Draw(im) draw = aggdraw.Draw(im) print(_list_xy) pen = aggdraw.Pen((0, 0, 0)) brush = aggdraw.Brush((0, 0, 0)) outline = aggdraw.Pen((0, 0, 0), 5) flag = 0 for xy_order in range(0, int((len(_list_xy) - 1) / 3)): #ezier = "m 0,0 t" for coordintes in range(0, 3): if (flag == 0): flag = 1 p0x = _list_xy[xy_order * 3]["x"] p0y = _list_xy[xy_order * 3]["y"] p0_x = _list_xy[xy_order * 3]["x"] p0_y = _list_xy[xy_order * 3]["y"] p1_x = _list_xy[xy_order * 3 + 1]["x"] p1_y = _list_xy[xy_order * 3 + 1]["y"] p2_x = _list_xy[xy_order * 3 + 2]["x"] p2_y = _list_xy[xy_order * 3 + 2]["y"] p3_x = _list_xy[xy_order * 3 + 3]["x"] p3_y = _list_xy[xy_order * 3 + 3]["y"] draw.ellipse((p0_x - 10, p0_y - 10, p0_x + 10, p0_y + 10), brush) p0 = str(p0_x) + "," + str(p0_y) p1 = str(_list_xy[xy_order * 3 + 1]["x"] - p0_x) + "," + str(_list_xy[xy_order * 3 + 1]["y"] - p0_y) + "," p2 = str(_list_xy[xy_order * 3 + 2]["x"] - p0_x) + "," + str(_list_xy[xy_order * 3 + 2]["y"] - p0_y) + "," p3 = str(_list_xy[xy_order * 3 + 3]["x"] - p0_x) + "," + str(_list_xy[xy_order * 3 + 3]["y"] - p0_y) draw.ellipse((p0_x - 3, p0_y - 3, p0_x + 3, p0_y + 3), pen) draw.ellipse((p3_x - 10, p3_y - 10, p3_x + 10, p3_y + 10), brush) draw.ellipse((p3_x - 3, p3_y - 3, p3_x + 3, p3_y + 3), pen) bezier = "m " + p0 + "c " + p1 + p2 + p3 print(bezier) symbol = aggdraw.Symbol(bezier) draw.symbol((0, 0), symbol, outline) spen = aggdraw.Pen((120, 120, 120)) sbrush = aggdraw.Brush((120, 120, 120)) draw.ellipse((p0x - 10, p0y - 10, p0x + 10, p0y + 10), sbrush) draw.ellipse((p0x - 3, p0y - 3, p0x + 3, p0y + 3), spen) draw.flush() #drawTime(_list_xy) im.save('draw\\result\\out.png')
def draw_stroke(backdrop, layer, vector_mask=None): from PIL import Image, ImageChops import aggdraw from psd_tools.composer.blend import blend width = layer._psd.width height = layer._psd.height setting = layer.stroke._data # Draw mask. stroke_width = float(setting.get('strokeStyleLineWidth', 1.)) mask = Image.new('L', (width, height)) draw = aggdraw.Draw(mask) for subpath in layer.vector_mask.paths: path = ' '.join(map(str, _generate_symbol(subpath, width, height))) symbol = aggdraw.Symbol(path) pen = aggdraw.Pen(255, int(2 * stroke_width)) draw.symbol((0, 0), symbol, pen, None) draw.flush() del draw # For now, path operations are not implemented. if vector_mask: vector_mask_ = Image.new('L', (width, height)) vector_mask_.paste(vector_mask, vector_mask.info['offset']) mask = ImageChops.darker(mask, vector_mask_) offset = backdrop.info.get('offset', layer.offset) bbox = offset + (offset[0] + backdrop.width, offset[1] + backdrop.height) mask = mask.crop(bbox) # Paint the mask. painter = setting.get('strokeStyleContent') mode = setting.get('strokeStyleBlendMode').enum if not painter: logger.warning('Empty stroke style content.') return backdrop if painter.classID == b'solidColorLayer': image = draw_solid_color_fill(mask.size, painter) elif painter.classID == b'gradientLayer': image = draw_gradient_fill(mask.size, painter) elif painter.classID == b'patternLayer': image = draw_pattern_fill(mask.size, layer._psd, painter) else: logger.warning('Unknown painter: %s' % painter) return backdrop image.putalpha(mask) return blend(backdrop, image, (0, 0), mode)
def _draw_subpath(subpath, width, height): from PIL import Image import aggdraw mask = Image.new('L', (width, height), 0) if len(subpath) <= 1: logger.warning('not enough knots: %d' % len(subpath)) return mask path = ' '.join(map(str, _generate_symbol(subpath, width, height))) draw = aggdraw.Draw(mask) brush = aggdraw.Brush(255) symbol = aggdraw.Symbol(path) draw.symbol((0, 0), symbol, None, brush) draw.flush() del draw return mask
def traverse_linestring(coords): pathstring = "" # begin coords = grouper(coords, 2) startx, starty = next(coords) pathstring += " M%s,%s" % (startx, starty) # connect to each successive point for nextx, nexty in coords: pathstring += " L%s,%s" % (nextx, nexty) # make into symbol object symbol = aggdraw.Symbol(pathstring) return symbol
def segments_to_symbol(segments): """Renders a list of curve and line segments into an aggdraw Path object for drawing. """ path = "M{0},{1} ".format(segments[0][1][0][0], segments[0][1][0][1]) # start at first point for curve, points in segments: if curve: start, end, ctrl = points path += "Q{0},{1},{2},{3} ".format(ctrl[0], ctrl[1], end[0], end[1]) else: start, end = points path += "L{0},{1} ".format(end[0], end[1]) return aggdraw.Symbol(path)
def _draw_subpath(subpath_list, width, height, brush, pen): """ Rasterize Bezier curves. TODO: Replace aggdraw implementation with skimage.draw. """ from PIL import Image import aggdraw mask = Image.new('L', (width, height), 0) draw = aggdraw.Draw(mask) pen = aggdraw.Pen(**pen) if pen else None brush = aggdraw.Brush(**brush) if brush else None for subpath in subpath_list: if len(subpath) <= 1: logger.warning('not enough knots: %d' % len(subpath)) continue path = ' '.join(map(str, _generate_symbol(subpath, width, height))) symbol = aggdraw.Symbol(path) draw.symbol((0, 0), symbol, pen, brush) draw.flush() del draw return np.expand_dims(np.array(mask).astype(np.float32) / 255., 2)
def take_screenshot(bundle_path, html_dir, cache_dir, size): os.makedirs(cache_dir, exist_ok=True) lv2_init() pb = get_pedalboard_info(bundle_path) if size: w, h = size.split('x') width, height = int(w), int(h) else: width, height = pb['width'], pb['height'] if (width, height) == (0, 0): width, height = 3840, 2160 img_dir = os.path.join(html_dir, 'img') # preload images audio_input_img = Image.open(os.path.join(img_dir, 'audio-input.png')) audio_output_img = Image.open(os.path.join(img_dir, 'audio-output.png')) audio_input_connected = Image.open( os.path.join(img_dir, 'audio-input-connected.png')) audio_output_connected = Image.open( os.path.join(img_dir, 'audio-output-connected.png')) midi_input_img = Image.open(os.path.join(img_dir, 'midi-input.png')) midi_output_img = Image.open(os.path.join(img_dir, 'midi-output.png')) midi_input_connected = Image.open( os.path.join(img_dir, 'midi-input-connected.png')) midi_output_connected = Image.open( os.path.join(img_dir, 'midi-output-connected.png')) cv_input_img = Image.open(os.path.join(img_dir, 'cv-input.png')) cv_output_img = Image.open(os.path.join(img_dir, 'cv-output.png')) cv_input_connected = Image.open( os.path.join(img_dir, 'cv-input-connected.png')) cv_output_connected = Image.open( os.path.join(img_dir, 'cv-output-connected.png')) default_screenshot = Image.open( os.path.join(html_dir, 'resources', 'pedals', 'default.png')) right_padding = audio_input_connected.size[0] * 2 bottom_padding = right_padding # create capture/playback connectors device_capture = [] for ix in range(0, pb['hardware']['audio_ins']): device_capture.append({ 'symbol': 'capture_{0}'.format(ix + 1), 'img': audio_output_img, 'connected_img': audio_output_connected, 'type': 'audio', }) if not pb.get('midi_separated_mode', False): device_capture.append({ 'symbol': 'midi_merger_out', 'img': midi_output_img, 'connected_img': midi_output_connected, 'type': 'midi', }) elif pb['hardware'].get('serial_midi_in', False): device_capture.append({ 'symbol': 'serial_midi_in', 'img': midi_output_img, 'connected_img': midi_output_connected, 'type': 'midi', }) for midi_in in pb['hardware']['midi_ins']: device_capture.append({ 'symbol': midi_in['symbol'], 'img': midi_output_img, 'connected_img': midi_output_connected, 'type': 'midi', }) for ix in range(0, pb['hardware']['cv_ins']): device_capture.append({ 'symbol': 'cv_capture_{0}'.format(ix + 1), 'img': cv_output_img, 'connected_img': cv_output_connected, 'type': 'cv', }) device_playback = [] for ix in range(0, pb['hardware']['audio_outs']): device_playback.append({ 'symbol': 'playback_{0}'.format(ix + 1), 'img': audio_input_img, 'connected_img': audio_input_connected, 'type': 'audio', }) if not pb.get('midi_separated_mode', False): device_playback.append({ 'symbol': 'midi_broadcaster_in', 'img': midi_input_img, 'connected_img': midi_input_connected, 'type': 'midi', }) elif pb['hardware'].get('serial_midi_out', False): device_playback.append({ 'symbol': 'serial_midi_out', 'img': midi_input_img, 'connected_img': midi_input_connected, 'type': 'midi', }) for midi_out in pb['hardware']['midi_outs']: device_playback.append({ 'symbol': midi_out['symbol'], 'img': midi_input_img, 'connected_img': midi_input_connected, 'type': 'midi', }) for ix in range(0, pb['hardware']['cv_outs']): device_playback.append({ 'symbol': 'cv_playback_{0}'.format(ix + 1), 'img': cv_input_img, 'connected_img': cv_input_connected, 'type': 'cv', }) # create plugins plugins = pb['plugins'] plugin_map = {} for p in plugins: # read plugin data data = get_plugin_info(p['uri']) p['data'] = data # read plugin image gui = get_plugin_gui(p['uri']) screenshot_path = gui.get('screenshot', None) pimg = Image.open(screenshot_path).convert( 'RGBA') if screenshot_path else default_screenshot p['img'] = pimg if screenshot_path: # detect ports and save/read version = '{0}.{1}'.format(data['version'], data.get('release', 0)).replace('.', '_') encoded_uri = base64.b64encode(p['uri'].encode()).decode() filename = os.path.join( cache_dir, '{0}_{1}_{2}'.format(__version__.replace('.', '_'), encoded_uri, version)) if os.path.isfile(filename): with open(filename, 'r') as fh: columns = json.loads(fh.read()) else: columns = { 'in_ports': tuple( tuple(c) for c in detect_first_column(pimg, pimg.size[0])), 'out_ports': tuple( tuple(c) for c in detect_first_column( pimg, pimg.size[0], rtol=True)), } with open(filename, 'w') as fh: fh.write(json.dumps(columns)) else: # tuna can, we have to guess the position of the connectors columns = { 'in_ports': ((-9, 121), (-9, 146), (-9, 190), (-9, 215), (-9, 259), (-9, -284), (-9, 328), (-9, 353)), 'out_ports': ((259, 121), (259, 146), (259, 190), (259, 215), (259, 259), (259, 284), (259, 328), (259, 353)) } # detect connectors in_ports = data['ports']['audio']['input'] + data['ports']['midi'][ 'input'] + data['ports']['cv']['input'] if len(in_ports) > 0: audio_in_ix = len(data['ports']['audio']['input']) cv_in_ix = len(data['ports']['cv']['input']) + audio_in_ix for ix, conn in enumerate(chunks(columns['in_ports'], 2)): if ix < len(in_ports): in_ports[ix]['connector'] = conn if ix < audio_in_ix: in_ports[ix]['connected_img'] = audio_input_connected in_ports[ix]['offset'] = (79, 15) in_ports[ix]['type'] = 'audio' elif ix < cv_in_ix: in_ports[ix]['connected_img'] = cv_input_connected in_ports[ix]['offset'] = (67, 15) in_ports[ix]['type'] = 'cv' else: in_ports[ix]['connected_img'] = midi_input_connected in_ports[ix]['offset'] = (67, 9) in_ports[ix]['type'] = 'midi' if not all('connector' in p for p in in_ports): raise Exception( 'Connector detection for input ports of plugin {0} failed'. format(p['uri'])) out_ports = data['ports']['audio']['output'] + data['ports']['midi'][ 'output'] + data['ports']['cv']['output'] if len(out_ports) > 0: audio_out_ix = len(data['ports']['audio']['output']) cv_out_ix = len(data['ports']['cv']['output']) + audio_out_ix for ix, conn in enumerate(chunks(columns['out_ports'], 2)): if ix < len(out_ports): out_ports[ix]['connector'] = conn if ix < audio_out_ix: out_ports[ix]['connected_img'] = audio_output_connected out_ports[ix]['offset'] = (8, 15) out_ports[ix]['type'] = 'audio' elif ix < cv_out_ix: out_ports[ix]['connected_img'] = cv_output_connected out_ports[ix]['offset'] = (11, 22) out_ports[ix]['type'] = 'cv' else: out_ports[ix]['connected_img'] = midi_output_connected out_ports[ix]['offset'] = (8, 9) out_ports[ix]['type'] = 'midi' if not all('connector' in p for p in out_ports): raise Exception( 'Connector detection for output ports of plugin {0} failed' .format(p['uri'])) plugin_map[p['instance']] = p # calculate image size height = 0 for p in plugins: if p['x'] + p['img'].size[0] + right_padding > width: width = p['x'] + p['img'].size[0] + right_padding if p['y'] + p['img'].size[1] + bottom_padding > height: height = p['y'] + p['img'].size[1] + bottom_padding width = rint(width) height = rint(height) or rint(1112) # calculate device connectors positions used_symbols = tuple(c['source'] for c in pb['connections']) + tuple( c['target'] for c in pb['connections']) used_types = ('audio', 'cv') device_capture = tuple( d for d in device_capture if d['type'] in used_types or d['symbol'] in ('serial_midi_in', 'midi_merger_out') or d['symbol'] in used_symbols) device_playback = tuple( d for d in device_playback if d['type'] in used_types or d['symbol'] in ( 'serial_midi_out', 'midi_broadcaster_in') or d['symbol'] in used_symbols) step = rint(height / (len(device_capture) + 1)) h = step for d in device_capture: d.update({'x': 0, 'y': h}) h = h + step h = step for d in device_playback: d.update({'x': width, 'y': h}) h = h + step # draw plugin cables and calculate connectors connectors = [] paths = [] for ix, c in enumerate(pb['connections']): # source source = next( (s for s in device_capture if s['symbol'] == c['source']), None) if source: source_connected_img = source['connected_img'] source_pos = anchor(source_connected_img.size, source['x'], source['y'], Anchor.LEFT_CENTER) source_x = source['x'] + source_connected_img.size[0] source_y = source['y'] source_type = source['type'] else: if '/' not in c['source']: continue source_i, source_s = c['source'].split('/') source = plugin_map[source_i] all_ports = source['data']['ports']['audio']['output'] + source[ 'data']['ports']['midi']['output'] + source['data']['ports'][ 'cv']['output'] port = next(p for p in all_ports if p['symbol'] == source_s) conn = port['connector'] source_connected_img = port['connected_img'] source_pos = (source['x'] + conn[0][0] - port['offset'][0], source['y'] + conn[0][1] - port['offset'][1]) source_x = source_pos[0] + source_connected_img.size[0] source_y = source_pos[1] + source_connected_img.size[1] / 2 source_type = port['type'] # target target = next( (t for t in device_playback if t['symbol'] == c['target']), None) if target: target_connected_img = target['connected_img'] target_pos = anchor(target_connected_img.size, target['x'], target['y'], Anchor.RIGHT_CENTER) target_x = target['x'] - target_connected_img.size[0] target_y = target['y'] target_type = target['type'] else: if '/' not in c['target']: continue target_i, target_s = c['target'].split('/') target = plugin_map[target_i] all_ports = target['data']['ports']['audio']['input'] + target[ 'data']['ports']['midi']['input'] + target['data']['ports'][ 'cv']['input'] port = next(p for p in all_ports if p['symbol'] == target_s) conn = port['connector'] target_connected_img = port['connected_img'] target_pos = (target['x'] + conn[0][0] - port['offset'][0], target['y'] + conn[0][1] - port['offset'][1]) target_x = target_pos[0] target_y = target_pos[1] + target_connected_img.size[1] / 2 target_type = port['type'] delta_x = target_x - source_x - 50 if delta_x < 0: delta_x = 8.5 * (delta_x / 6) else: delta_x /= 1.5 path = 'm{0},{1} c{2},{3},{4},{5},{6},{7}'.format( rint(source_x), rint(source_y), rint(target_x - delta_x - source_x), 0, rint(delta_x), rint(target_y - source_y), rint(target_x - source_x), rint(target_y - source_y)) paths.append((path, source_type, target_type)) connectors.append( (source_connected_img, (rint(source_pos[0]), rint(source_pos[1])), source_connected_img)) connectors.append( (target_connected_img, (rint(target_pos[0]), rint(target_pos[1])), target_connected_img)) # create image img = Image.new('RGBA', (width, height), (0, 0, 0, 0)) # draw device connectors for d in device_capture: img.paste(d['img'], anchor(d['img'].size, d['x'], d['y'], Anchor.LEFT_CENTER)) for d in device_playback: img.paste(d['img'], anchor(d['img'].size, d['x'], d['y'], Anchor.RIGHT_CENTER)) # draw all paths try: import aggdraw draw = aggdraw.Draw(img) audio_pen = aggdraw.Pen('#81009A', 7) midi_pen = aggdraw.Pen('#00546C', 7) cv_pen = aggdraw.Pen('#BB6736', 7) for path, source_type, target_type in paths: symbol = aggdraw.Symbol(path) pen = audio_pen if source_type == 'midi' or target_type == 'midi': pen = midi_pen elif source_type == 'cv' or target_type == 'cv': pen = cv_pen draw.symbol((0, 0), symbol, pen) draw.flush() except: print('Aggdraw failed') # draw all connectors for c in connectors: img.paste(*c) # draw plugins for p in plugins: img.paste(p['img'], (rint(p['x']), rint(p['y'])), p['img']) img.save(os.path.join(bundle_path, 'screenshot.png'), compress_level=3) resize_image(img) img.save(os.path.join(bundle_path, 'thumbnail.png')) img.close()
polyline0.add_decoration({'type': 'tick', 'position': 'tip'}) polyline0.add_decoration({'type': 'arrow', 'position': 'foot'}) # #sketch.add_graphics(rect0, polyline0) #sketch.refresh() # img = Image.new('RGBA', (W, H), DEFAULT_BACKGROUND_COLOR) canvas = aggdraw.Draw(img) # This draws on the canvas directly, without creating an object pen = aggdraw.Pen((255, 0, 255), DEFAULT_PEN_WIDTH) aggdrawstring = 'M600,200 L400,600' symbol = aggdraw.Symbol(aggdrawstring) canvas.symbol((0, 0), symbol, pen) # Draw the objects created earlier via their method polyline0.draw(canvas) rect0.draw(canvas) canvas.flush() img.save('alinesegment.png') os.system(' '.join(['open -a preview alinesegment.png'])) # ============== END OF SCRIPT ================================ print("=" * 80) print("END OF SCRIPT.")