I'm trying to create an image with every possible color. It would start with a seed pixel and then place randomly-generated RGB pixels around it. Future placements would be based on whichever open spot had the average of the pixels surrounding it closest to the new color to be placed.
from PIL import Image
import numpy as np
from random import randint
import sys
import random
import itertools
sys.setcheckinterval(10000)
def moddistance3(x1,y1,z1,x2,y2,z2): #get relative distance between two 3D points
x = abs(x1 - x2)
y = abs(y1 - y2)
z = abs(z1 - z2)
return (x + y + z)
def genColor(unused): #generate random color (not used anymore)
test = 0
while test == 0:
red = randint(0,255)
green = randint(0,255)
blue = randint(0,255)
if unused[red,green,blue] == 1:
test = 1
return (red,green,blue)
def surroundAvg(points,unfilled):
surrounding = {}
count = len(points)
for inc in xrange(count):
neighbors = filledNeighbors(points[inc][0],points[inc][1],unfilled)
nearcount = len(neighbors)
pixred = 0
pixgreen = 0
pixblue = 0
for num in xrange(nearcount):
(temp_red,temp_green,temp_blue) = pixels[neighbors[num][0],neighbors[num][1]]
pixred = pixred + temp_red
pixgreen = pixgreen + temp_green
pixblue = pixblue + temp_blue
pixred = pixred / nearcount
pixgreen = pixgreen / nearcount
pixblue = pixblue / nearcount
surrounding[(points[inc][0],points[inc][1])] = (pixred,pixgreen,pixblue)
return surrounding
def genPoint(perim,unfilled,averages,red,green,blue):
num_test = len(perim)
test = 0
least_diff = 9999
nearby = []
for point in xrange(num_test):
i = perim[point][0]
j = perim[point][1]
pixred = averages[(i,j)][0]
pixgreen = averages[(i,j)][1]
pixblue = averages[(i,j)][2]
diff = abs(red - pixred) + abs(green - pixgreen) + abs(blue - pixblue)
if diff < least_diff or test == 0:
least_diff = diff
newx = i
newy = j
test = 1
return newx,newy
def cubegen(): #create the cube of colors with each color having its own number
cube = np.zeros(16777216,dtype=np.object)
num = 0
for red in xrange(0,256):
for green in xrange(0,256):
for blue in xrange(0,256):
cube[num] = [red,green,blue]
num += 1
return cube
def getNeighbors(x,y,unfilled):
Prod = itertools.product
toremove = []
neighbors = list(Prod(range(x-1,x+2),range(y-1,y+2)))
for num in xrange(len(neighbors)):
i,j = neighbors[num]
if j > 4095 or i > 4095 or unfilled[(i,j)] == 0 or j < 0 or i < 0:
toremove.append((i,j))
map(neighbors.remove,toremove)
return neighbors
def filledNeighbors(x,y,unfilled):
Prod = itertools.product
toremove = []
neighbors = list(Prod(range(x-1,x+2),range(y-1,y+2)))
#neighbors = filter(lambda i,j: j < 4096 and i < 4096 and unfilled[i,j] == 0 and j > -1 and i > -1,allneighbors)
for num in xrange(len(neighbors)):
i,j = neighbors[num]
if j > 4095 or i > 4095 or unfilled[(i,j)] == 1 or j < 0 or i < 0:
toremove.append((i,j))
map(neighbors.remove,toremove)
return neighbors
img = Image.new('RGB', (4096,4096)) # create a new black image
pixels = img.load() # create the pixel map
colorList = range(16777216)
colorCube = cubegen()
print("Color cube created successfully")
unfilled = {}
for x in xrange(4096):
for y in xrange(4096):
unfilled[(x,y)] = 1
startx = 2048
starty = 2048
random.shuffle(colorList)
print("Color list shuffled successfully")
color = colorList[0]
(red,green,blue) = colorCube[color]
pixels[startx,starty] = (red,green,blue)
unfilled[(startx,starty)] = 0
perim_empty = getNeighbors(startx,starty,unfilled)
edge = []
#edge.append((startx,starty))
avg = surroundAvg(perim_empty,unfilled)
print("First point placed successfully.")
#appendEdge = edge.append
#removeEdge = edge.remove
appendPerim = perim_empty.append
removePerim = perim_empty.remove
updateAvg = avg.update
for iteration in xrange(1,16777216):
temp = {}
color = colorList[iteration]
(red,green,blue) = colorCube[color]
(i,j) = genPoint(perim_empty,unfilled,avg,red,green,blue)
unfilled[(i,j)] = 0
pixels[i,j] = (red,green,blue)
new_neighbors = getNeighbors(i,j,unfilled)
map(appendPerim,new_neighbors)
temp = surroundAvg(new_neighbors,unfilled)
updateAvg(temp)
removePerim((i,j))
#appendEdge((i,j))
#if iteration % 20 == 0:
# toremove = []
# appendToRemove = toremove.append
# for num in xrange(len(edge)):
# nearby = getNeighbors(edge[num][0],edge[num][1],unfilled)
# if len(nearby) == 0:
# appendToRemove(edge[num])
#for num in xrange(len(toremove)):
# edge.remove(toremove[num])
# map(removeEdge,toremove)
if iteration % 500 == 0:
print("Iteration %d complete" %iteration)
if iteration == 100000 or iteration == 500000 or iteration ==1000000 or iteration == 5000000 or iteration == 10000000 or iteration == 15000000:
img.save("Perimeter Averaging -- %d iterations.bmp" %iteration)
img.save("Perimeter Averaging Final.bmp")
img.show()
The problem is that when I try to run this, it takes days to even go through 1,000,000 of the colors, and slows down considerably as it goes. I can't figure out how to make it take less time, and I know there must be a way to do this that doesn't take months. I'm new to code and am teaching myself, so please forgive any obvious fixes I've totally overlooked.