# Python 2.7.7 Code, utilizing PIL
# Written by Jonathan Frech, 13th, 14th of August 2017

# import Python built-in libraries
import random, sys, os, time

# main function
def main():
	# start timer
	t0 = time.time()
	
	# try to import PIL
	try: from PIL import Image, ImageDraw
	except: return "Could not import PIL (Python Imaging Library). Is it installed?\nsudo apt-get install python-pil"
	
	# image file has to be specified
	if len(sys.argv) < 2: return "Please specify an input image file name.\nUsage: python mosaify.py <image file name> [n] [k]"
	
	# parameters
	n, k = 5., 1.
	if len(sys.argv) >= 3:
		try: n = float(sys.argv[2]); 1/(n>0)
		except: return "Invalid parameter n ('%s')." % sys.argv[2]
	if len(sys.argv) >= 4:
		try: n = float(sys.argv[3]); 1/(n>0)
		except: return "Invalid parameter k ('%s')." % sys.argv[3]
	
	# open file
	print "Reading file..."
	F = sys.argv[1]
	try: Img = Image.open(F)
	except: return "Could not open file '%s'." % F
	
	# image size, new image, pixel arrays, draw
	s = w, h = Img.size
	img = Image.new("RGB", s)
	drw = ImageDraw.Draw(img)
	Pix, pix = Img.load(), img.load()
	
	# paramters
	N, K = int(max(w, h)/n), int(max(w, h)/k)

	# foreground, background (not actually shown; used internally)	
	c0, c1 = (1, 0, 0), (0, 0, 1)
	
	# fill new image
	img.paste(c0, (0, 0, w, h))
	
	# all points in image, all points in 3x3 grid, function name
	R = [(x, y) for x in range(w) for y in range(h)]
	S = [(x, y) for x in range(-1, 2) for y in range(-1, 2)]
	r = random.randint
	
	# return random point not in image
	def P():
		x, y = 0, 0
		while 0<=x<w and 0<=y<h: x, y = r(-K, w+K-1), r(-K, h+K-1)
		return x, y
	
	# draw lines
	print "Drawing lines..."
	for _ in range(N): drw.line(P()+P(), fill = c1)
	
	# flood polygons (defined by line intersections)
	print "Flooding polygons..."
	for x, y in R:
		if pix[x, y] == c0: ImageDraw.floodfill(img, (x, y), Pix[x, y])
	
	# fix lines (fill with surrounding colors)
	print "Fixing lines..."
	for x, y in R:
		if pix[x, y] == c1:
			f = []
			for X, Y in S:
				if 0<=X+x<w and 0<=Y+y<h and pix[X+x, Y+y] != c1: f.append((X+x, Y+y))
			if len(f) > 0: pix[x, y] = pix[random.choice(f)]
	
	# determine file name, attempt to save
	v = F.split("."); f = "%s_mosaified.%s" % (".".join(v[:-1]), v[-1]); n = 2
	while os.path.exists(f): f = "%s_mosaified_%d.%s" % (".".join(v[:-1]), n, v[-1]); n += 1
	try: img.save(f); print "Successfully saved image as '%s'." % f
	except: return "Failed to save image as '%s'." % f
	
	# stop timer
	t1 = time.time(); t = t1-t0
	print "Took %.2f seconds." % t

# run if called as main
if __name__ == "__main__":
	try: m = main(); print "\033[31;91mError\033[0m: %s" % m if m else ""
	except KeyboardInterrupt: print "arelessly interrupted."