import argparse import cairo import imageio import math import numpy as np import random import sys ## Set up commandline args help_text = "Usage: python image_to_svg --image_file [file]" parser = argparse.ArgumentParser( description = help_text, ) parser.add_argument("-f", "--image_file", help="input .jpg image file") parser.add_argument("-b", "--bin_size", help="number of pixels per bin") parser.add_argument("-t", "--type", help="tone_circle, halftone_circle") parser.add_argument("-g", "--grid", help="square, hex") parser.add_argument("-p", "--padding", help="padding fracion, like 0.1") parser.add_argument("-o", "--svg_out", help="name of svg output file") args = parser.parse_args() print(args.image_file) source_image = imageio.imread(uri=args.image_file, pilmode="L") width = source_image.shape[1] height = source_image.shape[0] #surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) surface = cairo.SVGSurface(args.svg_out, width, height) ctx = cairo.Context(surface) ctx.set_source_rgb(0, 0, 0) ctx.rectangle(0, 0, width, height) ctx.fill() def tone_circle(x, y, size, intensity): print(x, y, size, intensity) num_tones = 10 tone = math.floor(num_tones * intensity) / (num_tones - 1) ctx.set_source_rgb(tone, tone, tone) ctx.arc(x + size / 2, y + size / 2, (1.0 - float(args.padding)) * size / 2.0, 0, 2.0 * math.pi) ctx.fill() def halftone_circle(x, y, size, intensity): # ctx.set_source_rgb(255, 223, 0) ctx.set_source_rgb(255, 225, 255) radius_scale = (1.0 - float(args.padding)) * 0.5 * math.sqrt(1.0 - intensity) ctx.arc(x + size / 2, y + size / 2, size * radius_scale, 0, 2.0 * math.pi) ctx.fill() bin = int(args.bin_size) vertical_step = bin if (args.grid == "hex"): vertical_step = math.sqrt(3) * bin / 2 offset = 0 for y_step in range(0, int(math.ceil(height / vertical_step)) - 1): for x_step in range(0, int(math.ceil((width - offset) / bin))): x_start = int(math.floor(x_step * bin + offset)) y_start = int(math.floor(y_step * vertical_step)) value = np.mean(source_image[y_start : y_start + bin, x_start : x_start + bin]) intensity = 1 - (value / 255.0) if (args.type == "tone_circle"): tone_circle(x_start, y_start, bin, intensity) if (args.type == "halftone_circle"): halftone_circle(x_start, y_start, bin, intensity) if (offset == 0 and args.grid == "hex"): offset = bin / 2 else: offset = 0 ctx.save()