Reputation: 615
I'm trying to write a glitch art program that lets me make pictures kinda fall like sand, and I have it working for greyscale (L). I'm trying to convert it into color, but I can't get this code to work. Here's what I have for color
#! /usr/bin/python
from PIL import Image
from random import randint
# Sorts img kinda randomly
source = Image.open("test.jpg")
threshold = 150
img = source.load()
blackandwhite = source.convert("L").load()
canvas = Image.new("RGB", source.size)
newimg = canvas.load()
count = source.size[0]
print (source.format)
print (source.size)
print (source.mode)
print ("Threshold: ", threshold)
print ("============================================")
counter = 0 #counter
# do the loop twice because we want to make em fall!
counter = 0
for i in range(0, source.size[0]-1): # loop through every x value
vert_list = [] #list of this column
for pix in range(0, source.size[1]-1): #make a list of the column from the b&w img
color = blackandwhite[i, pix] #for being in color ^^
vert_list.append( color )
counter += 1
if counter % 10 == 0:
print(counter, "/", count)
#now remove all pixels brighter than the threshold
color_vert_list = []
for x in range(0, len(vert_list)-1):
if vert_list[x] < threshold:
color_vert_list.append(img[i, pix]) #add colors darker than something to the color list
top_spacing = source.size[1] - len(color_vert_list) #height
for pixel in range(0, len(color_vert_list)):
newimg[i,pixel + top_spacing] = color_vert_list[pixel] #add em
canvas.save("fall.png") #save
and here's the same code working in black and white
#! /usr/bin/python
from PIL import Image
from random import randint
# Sorts img kinda randomly
source = Image.open("test.jpg")
threshold = 150
img = source.load()
blackandwhite = source.convert("L").load()
canvas = Image.new("L", source.size)
newimg = canvas.load()
count = source.size[0]
print (source.format)
print (source.size)
print (source.mode)
print ("Threshold: ", threshold)
print ("============================================")
counter = 0 #counter
# do the loop twice because we want to make em fall!
counter = 0
for i in range(0, source.size[0]-1): # loop through every x value
vert_list = [] #list of this column
for pix in range(0, source.size[1]-1): #make a list of the column from the b&w img
color = blackandwhite[i, pix] #for being in color ^^
vert_list.append( color )
counter += 1
if counter % 10 == 0:
print(counter, "/", count)
#now remove all pixels brighter than the threshold
vert_list[:] = (x for x in vert_list if threshold > x)
top_spacing = source.size[1] - len(vert_list) #height
for pixel in range(0, len(vert_list)):
newimg[i,pixel + top_spacing] = vert_list[pixel]
canvas.save("fall.png")
Upvotes: 0
Views: 1023
Reputation: 365637
It looks like your problem is that you're trying to get back the color value (which you've discarded) from the greyscale value's index, but that isn't going to work when you've already discarded previous greyscale values and the indices no longer match up.
So let's start over. Instead of keeping a list of greyscale vertices and a list of color vertices and trying to match them up, let's just keep a list of (greyscale, color) pairs. Like this:
for pix in range(0, source.size[1]-1): #make a list of the column from the b&w img
grey = blackandwhite[i, pix]
color = img[i, pix]
vert_list.append((grey, color))
Now, you just need to change the filter to use the grey value in the pair:
vert_list[:] = (x for x in vert_list if threshold > x[0])
… and change the newimg
assignment to use the color value in the pair:
newimg[i,pixel + top_spacing] = vert_list[pixel][1]
And (other than changing the mode of the canvas
, which you already got right), that's all you need to do.
I've posted a complete implementation here (with comments on the three changed lines).
Upvotes: 1