RedXIII | April 13, 2021, 11:03 a.m.
Unlock your artistic talent with Pillow
As technology takes center stage in our lives, we turn to media to express ourselves. Knowing a programming language like Python can open many doors, including those that swing inward.
Coding is an opportunity to open the creative process. Projects like Google’s DevArt and Processing.org are making it easier for artists and engineers to innovate new, engaging experiences.
With Python, it’s possible to make exciting digital art using the power of pixels. With the Pillow library, Python can read and write image data, making it possible to create endless new works of art.
I’ll show you how to use Python to create a popular glitch art technique known as pixel sorting.
Pixel sorting is about rearranging the pixels in an image, usually by sorting rows or columns of image data. Remember, an image on the computer is made of thousands of pixels. Each pixel has three values, one for each of the three colors used to draw images on your monitor: red, green, and blue.
This ‘RGB’ data is combined to render the final color of every pixel you see.
The Pillow library gives us access to tools we can use to manipulate images. It offers a variety of image processing capabilities including, but not limited to, color enhancement and other image filters.
Before you can use Pillow, you’ll need to install it on your computer. It’s easiest to install the library using pip.
pip install Pillow
Once Pillow is installed, we can access the PIL image library with the following:
from PIL import Image
We’ll need a reference picture before we can start sorting. Keep in mind that the bigger the image, the longer the program will take to finish the sorting process. My image is around 700 pixels wide by 400 pixels tall.
Save the image in the same folder as the Python file you’re working with. I named mine pixel_sort.py.
Accessing the individual pixels of an image is fairly easy, as is storing the dimensions of the image.
img = Image.open(“red_rock.jpg”)width, height = img.sizepixels = img.load()
This is all we need to start the sorting process. Image.load() returns a dictionary, or key/value pair, where each key points to an RBG value.
For instance, pixels[0,0] might be equal to (255, 0, 0) if that pixel’s value were bright red.
Using a nested for loop, we’ll traverse the rows of the image and then sort each row. There are many ways to sort pixels. Hue, luminosity, contrast, etc. These can all be used as criteria for conducting the sort.
For the sake of simplicity, we’ll focus on the overall value of each pixel. Since each pixel is made up of three colors (RGB), we can add them all up and get a single value.
For each row in the image, we’ll find the pixel with the highest overall value. This will serve as a breaking point for the sort, meaning we’ll only sort the array up to that pixel.
Doing this will yield some interesting artistic effects, but this is only one method of pixel sorting. It was inspired by Ken Asendorf, the inventor of the technique.
We’ll wrap the sorting code in it’s own function. This will get called for every row in the image, returning a sorted row.
def sort_row(row):
min = 255*3
min_index = 0
#find the darkest pixel in the row
for i in range(len(row)):
# each pixel has an RPG value, for instance (255, 255, 255)
temp = row[i][0] + row[i][1] + row[i][2]
if temp < min:
min = temp
min_index = i# sort the row up the brightest pixel
sorted_row = row[:min_index]
sorted_row.sort()return sorted_row + row[min_index:]
The Pillow library allows us to create images from scratch using the new() method. We’ll need to specify the image mode (RGB) and provide the desired width and height.
new_img = Image.new(‘RGB’,(width, height))
Once the new image is created, we can add pixel data to it using the putdata() method. This method requires a Python list, so we’ll need to convert our pixel data into a list before it will work.
# to make a new image, we'll need to conver the data to a list
sorted_pixels = []for y in range(height):
for x in range(width):
sorted_pixels.append(pixels[x,y])new_img.putdata(sorted_pixels)
Display images using the show() method.
new_img.show()
Lastly, we can save the new image by using the save() method.
new_img.save(“sorted_red_rock.jpg”)
For example, Asendorf’s original code incorporated both horizontal and vertical sorting, and choosing other sorting methods can yield interesting results.
Feel free to modify this code, expanding on it’s potential and adding your own methods. Who knows, you might just make something beautiful.
Here’s the full code:
from PIL import Image“””
To pixel sort, we first need to load all the pixels in an image file.
We’ll then loop through each row of the image data, record the color value of
each pixel in the row, then sort the row based on those values.
“””
def sort_row(row):
min = 255*3
min_index = 0
#find the darkest pixel in the row
for i in range(len(row)):
# each pixel has an RPG value, for instance (255, 255, 255)
temp = row[i][0] + row[i][1] + row[i][2]
if temp < min:
min = temp
min_index = i# sort the row up the brightest pixel
sorted_row = row[:min_index]
sorted_row.sort()return sorted_row + row[min_index:]def pixel_sort():
print(“loading the image…”)
# load the image data
img = Image.open(“motorboat.jpg”)# load the pixel data from the file.
pixels = img.load()width, height = img.sizeprint(“sorting the image…”)
# loop through each row and sort the pixels in that row
for y in range(height):
# get a row
row = []
for x in range(width):
row.append(pixels[x,y])# sort the row
row = sort_row(row)# record the sorted data
for x in range(width):
pixels[x,y] = row[x]# to make a new image, we’ll need to conver the data to a list
sorted_pixels = []for y in range(height):
for x in range(width):
sorted_pixels.append(pixels[x,y])new_img = Image.new(‘RGB’,(width, height))
new_img.putdata(sorted_pixels)print(“image preview…”)
# preview the sorted image.
new_img.show()
print(“saving image…”)
# save the file with a new name.
new_img.save(“motorboat_sorted.jpg”)pixel_sort()