spacepaste

#!/usr/bin/python
import random
import Image, ImageDraw, ImageChops
import copy
import json
import traceback
import os


im = Image.open("Mona_Lisa.png")
width = im.size[0]
height = im.size[1]

aafactor = 1

listlen = 1
modperitem = 100
currentbest = 0

itemspergen = listlen*(modperitem+1)

mu = 0.1

class triangle(object):
  def __init__(self,initobj=[]):
    try :
      self.R = initobj[0]
      self.G = initobj[1]
      self.B = initobj[2]
      self.A = initobj[3]
      self.X1 = initobj[4]
      self.Y1 = initobj[5]
      self.X2 = initobj[6]
      self.Y2 = initobj[7]
      self.X3 = initobj[8]
      self.Y3 = initobj[9]
    except :
      self.R = random.randint(0,255)
      self.G = random.randint(0,255)
      self.B = random.randint(0,255)
      self.A = random.randint(0,255)
      self.X1 = random.random()
      self.Y1 = random.random()
      self.X2 = random.random()
      self.Y2 = random.random()
      self.X3 = random.random()
      self.Y3 = random.random()

  def modify(self):
    case = random.randint(1,4)
    if case == 1:
      self.R = int(random.gauss(self.R,mu*255))
      if self.R < 0:
        self.R = 0
      elif self.R > 255:
        self.R = 255
      self.G = int(random.gauss(self.G,mu*255))
      if self.G < 0:
        self.G = 0
      elif self.G > 255:
        self.G = 255
      self.B = int(random.gauss(self.B,mu*255))
      if self.B < 0:
        self.B = 0
      elif self.B > 255:
        self.B = 255
      self.A = int(random.gauss(self.A,mu*255))
      if self.A < 0:
        self.A = 0
      elif self.A > 255:
        self.A = 255
    elif case == 2:
      self.X1 = random.gauss(self.X1,mu)
      self.Y1 = random.gauss(self.Y1,mu)
    elif case == 3:
      self.X2 = random.gauss(self.X2,mu)
      self.Y2 = random.gauss(self.Y2,mu)
    elif case == 4:
      self.X3 = random.gauss(self.X3,mu)
      self.Y3 = random.gauss(self.Y3,mu)

  def diagnostics(self):
    print "R:%i" %self.R
    print "G:%i" %self.G
    print "B:%i" %self.B
    print "A:%i" %self.A
    print "X1:%i" %self.X1
    print "Y1:%i" %self.Y1
    print "X2:%i" %self.X2
    print "Y2:%i" %self.Y2
    print "X3:%i" %self.X3
    print "Y3:%i" %self.Y3

  def contents(self):
    return [self.R, self.G, self.B, self.A, self.X1, self.Y1, self.X2, self.Y2, self.X3, self.Y3]

class triimage(object):
  def __init__(self,initobj=[]):
    self.triangles = []
    for i in initobj:
      self.triangles.append(triangle(i))

  def modify(self):
    case1 = random.randint(1,12)
    if len(self.triangles) == 0 or case1 == 1:
      self.triangles.append(triangle())
    elif case1 == 2:
      case2 = random.randint(0,len(self.triangles)-1)
      del self.triangles[case2]
    else :
      case2 = random.randint(0,len(self.triangles)-1)
      self.triangles[case2].modify()

  def diagnostics(self):
    for i in xrange(len(self.triangles)):
      self.triangles[i].diagnostics()
      print "-----"

  def contents(self):
    returnlist = []
    for i in xrange(len(self.triangles)):
      returnlist.append(self.triangles[i].contents())
    return returnlist

  def getimage(self):
    back = Image.new('RGBA',(width*aafactor,height*aafactor))
    for i in xrange(len(self.triangles)):
      poly = Image.new('RGBA',(width*aafactor,height*aafactor))
      pdraw = ImageDraw.Draw(poly)
      pdraw.polygon([(self.triangles[i].X1*width*aafactor,self.triangles[i].Y1*height*aafactor),(self.triangles[i].X2*width*aafactor,self.triangles[i].Y2*height*aafactor),(self.triangles[i].X3*width*aafactor,self.triangles[i].Y3*height*aafactor)],fill=(self.triangles[i].R,self.triangles[i].G,self.triangles[i].B,self.triangles[i].A))
      back.paste(poly,mask=poly)

    back.thumbnail((width,height),Image.ANTIALIAS)
    return back.convert('RGB')

def load():
  global newgoodtriangles
  global generation
  try :
    fin = open('dump')
    loadlist = json.load(fin)
    loadtriimages = loadlist[0]
    generation = loadlist[1]
    readstate = loadlist[2]
    random.setstate(settable(readstate))
    fin.close()
    newgoodtriangles = []
    for i in loadtriimages:
      newgoodtriangles.append(triimage(i))
  except :
    print "Couldn't load dump!"
    traceback.print_exc()
    print "Initializing with default values"
    newgoodtriangles = []
    for i in xrange(listlen):
      newgoodtriangles.append(triimage())
    generation = 0
    random.seed(0)

def save():
  newgoodtriangles[0].getimage().save('images/' + str(generation) + '.png')

  try :
    savelist = []
    savetrilist = []
    for i in newgoodtriangles:
      savetrilist.append(i.contents())
    savelist.append(savetrilist)
    savelist.append(generation)
    savelist.append(random.getstate())
    fout = open('dump','w')
    fout2 = open('backups/' + str(generation) + '.dat','w')
    json.dump(savelist,fout)
    json.dump(savelist,fout2)
    fout.close()
    fout2.close()
  except :
    print "Couldn't dump the data!"
    traceback.print_exc()

  try :
    totalitemsran = generation * itemspergen
    fout = open('timedata.csv','a')
    fout.write(str(totalitemsran) + ',' + str(currentbest) + '\n')
    fout.close()
  except :
    print "Couldn't write time data!"
    traceback.print_exc()

def main():
  global newgoodtriangles
  global generation
  load()

  for i in xrange(5):
    generation = generation + 1
    triimagelist = []
    diff = []
    for j in xrange(len(newgoodtriangles)):
      for k in xrange(modperitem):
        triimagelist.append(copy.deepcopy(newgoodtriangles[j]))
        triimagelist[-1].modify()
        diff.append(difference(im,triimagelist[-1].getimage()))
      triimagelist.append(copy.deepcopy(newgoodtriangles[j]))
      diff.append(difference(im,triimagelist[-1].getimage()))

    list3 = zip(diff,triimagelist)
    list3.sort()

    for j in xrange(len(newgoodtriangles)):
      newgoodtriangles[j] = list3[j][1]

    print str(generation) + ": " + str(list3[0][0])

    global currentbest
    currentbest = list3[0][0]
    save()

def settable(read):
  thatlist = []
  for i in read[1]:
     thatlist.append(long(i))
  nowoneisatuple = tuple(thatlist)
  return (read[0],nowoneisatuple,read[2])


def difference(im1,im2):
  if im1.size != im2.size:
    raise Exception('Image sizes don\'t match.')
  diff = 0
  im1list = list(im1.getdata())
  im2list = list(im2.getdata())

  for i in xrange(len(im1list)):
    rgb1 = im1list[i]
    rgb2 = im2list[i]

    diffr = rgb1[0]-rgb2[0]
    diffg = rgb1[1]-rgb2[1]
    diffb = rgb1[2]-rgb2[2]

    diff = diff + diffr*diffr+diffg*diffg+diffb*diffb

  return diff

if __name__ == '__main__':
  main()