commit 70c8fc94e538e1069f6872902933ea5132010fd8 Author: Dark-Storm Date: Sat Aug 18 19:34:41 2018 +0200 First commit, enjoy! diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bbbb27c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__/** +*.png +*.jpg +*.bmp diff --git a/process.py b/process.py new file mode 100755 index 0000000..3b3a102 --- /dev/null +++ b/process.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 + +from argparse import ArgumentParser +from bresenham import bresenham +from PIL import Image, ImageDraw +from random import randint +import sys + + +rand = lambda: randint(0,255) + + +def print_stats(img): + pixels = img.getdata() + count = sum([1 for i in pixels if i == 0]) + print("{} black pixels over {} ({:.1%})".format(count, len(pixels), count/len(pixels))) + + +def get_lines(img): + lines = [] + pixels = [(x, y) for x in range(img.width) for y in range(img.height) if img.getpixel((x, y)) == 0] + + i, n = 0, len(pixels) * len(pixels) + + print("Get lines:", end = "") + for a in pixels: + for b in pixels: + line = list(bresenham(b[0], b[1], a[0], a[1])) + r = len([0 for p in line if p not in pixels]) + if not r: + lines.append(line) + i += 1 + print("\rGet lines: {:.0%}".format(i / n), end = "") + print("\rGet lines: complete") + + print("{} lines found".format(len(lines))) + return lines + + +def removing_doubles(lines): + results = [] + i, n = 0, len(lines) + + print("Remove duplicated lines:", end = "") + for l in lines: + s = sorted(l) + same = False + for o in results: + if sorted(o) == s: + same = True + break + if same == False: + results.append(l) + i += 1 + print("\rRemove double lines: {:.0%}".format(i / n), end = "") + print("\rRemove double lines: complete") + + print("{} lines kept".format(len(results))) + return results + + +def removing_useless(lines): + results = [] + i, n = 0, len(lines) + + print("Remove useless lines:", end = "") + for l in lines: + inclusions = 0 + others = (x for x in lines if x != l) + for k in others: + if len(list(set(l).intersection(set(k)))) == len(l): + inclusions += 1 + break + if inclusions == 0 or len(l) == 1: + results.append((len(l), l)) + i += 1 + print("\rRemove useless lines: {:.0%}".format(i / n), end = "") + print("\rRemove useless lines: complete") + + print("{} lines kept".format(len(results))) + return results + + +def get_best_solution(img, lines): + px_left = [(x, y) for x in range(img.width) for y in range(img.height) if img.getpixel((x, y)) == 0] + results = [] + n = len(px_left) + + print("Draw:", end = "") + while len(px_left): + lines = [(sum([1 for p in l if p in px_left]), l) for n, l in lines] + lines = sorted(lines) + (p, line) = lines.pop() + px_left = [p for p in px_left if p not in line] + results.append((line[0], line[-1])) + print("\rDraw: {:.0%}".format(1 - len(px_left)/n), end="") + print("\rDraw: complete") + + print("Solution found in {} lines".format(len(results))) + return results + + + +if __name__ == "__main__": + parser = ArgumentParser(description='Generate the Multi DrawStat code for an image.') + parser.add_argument('path', type=str, help='path of the image to process') + parser.add_argument('-d', '--draw', type=bool, default=False, help='draw the result into a new file and display it') + + args = parser.parse_args() + + try: + image = Image.open(args.path) + except: + sys.exit("Error! Unable to open file.") + + try: + image = image.convert('1') + except: + sys.exit("Error! Unable to convert to 1bit") + + print_stats(image) + lines = get_lines(image) + lines = removing_doubles(lines) + lines = removing_useless(lines) + r = get_best_solution(image, lines) + + if draw: + export = Image.new('RGB', image.size, 'white') + drawer = ImageDraw.Draw(export) + for ((a, b), (c, d)) in reversed(r): + drawer.line((a, b, c, d), fill=(rand(), rand(), rand())) + export = export.resize((export.width * 8, export.height * 8)) + export.save(args.path[:-4] + "_gen.png") + export.show() + + print("\n\n=================================================\n\n") + + for l in r: + print(l[0], l[1]) + + print("\n\n=================================================\n\nDone!")