Software

NFT Pixel Art Generated with Python

Ignoring whether NFTs or Non-Fungible Tokens are useful or valuable it is an emerging market that combines art and code so why not try making your own with python.

The process of creating an NFT will not be done in python only the image generation.

I decided to create some pixel art NFTs mostly because at some point you need to actually create art assets. I am not the most talented artist but can muddle my way through if I have some references to go off of.

There has been a slew of generative pixel art-based images being sold as NFTs such as CryptoPunks or Weird Whales so I decided to pick a subject that I could make lots of iterations on. What came to mind to me was microorganisms. This is because my partner is in Med School and has been learning about the different kinds of microbes in the environment.

I named them Cryptobes!

Art Assets

Art assets are the base components that you will use to generate random combinations and permutations. So how do you create them? well there are many ways but basically, YOU HAVE TO DESIGN THEM! For pixel art generation I like to use a simple IOS app called 8bit Painter

This allows me to quickly make different pixel art designs on the go.

I then researched different kinds of microbes and what they looked like. This was a bit out of my depth as a computer engineer but I am definitely qualified to google image search! I found this really cool chart that lists a bunch of different kinds of organisms by their scientific name.

Etsy: Dr. Warhols Periodic Table of Microbes

From there I used a microorganism wiki to learn more about the different kinds and shapes to inform my pixel art creations.

MicrobeWiki Shapes of Microbes Bacillus Spirillum

This was a pretty lengthy process and took a few days to iterate on. But ultimately I ended up with 12 different base designs that I could further manipulate with code. The full collection that I generated is up on OpenSea.

Generative Cryptobes

Python Generation

Now comes the real fun part! For the majority, we will only use two python libraries, the Random number generator library and the PIL image manipulation library. I like to use Jupyter Lab to experiment with Python in easy-to-manage Jupyter Notebooks, you can learn more about it below.

The first step is to get your created asset into python. Thankfully the PIL library handles this usually more complicated step all we need to do is provide it with the desired image path. We can import lots of different kinds of image types but I will primarily use the PNG format as it is easy to use and generate.

from PIL import Image
test_image = Image.open("test.png")

The next step is to change the background color this is also done by either selecting a color using a three integer tuple such as (25, 128, 75) during the instantiation of our base image that we will be building off of.

test_size = test_image.size
base_size = (test_size[0]+100,test_size[1]+100)
base_image = Image.new(mode="RGB", size=base_size, color=(25,128,75))

Now we need to paste the art asset into the base image. This is very easy if we have made the base image the same size as our art asset but we would need to shift the art asset if the canvas is bigger.

base_image.paste(test_image, (50,50))

Now, what if we want to change the colors in the art asset to some other color? For this, we have a handy method in the PIL library that pulls out all the unique colors in an image. From there we can do a simple substitution in a loop over all the pixels.

unique_colors = test_image.getcolors()
from random import randint
pixels = base_image.load()

for color in unique_colors:
    if color[1][3] > 0:
        color_c = (color[1][0],color[1][1],color[1][2])
        rand_color=(randint(0,255),randint(0,255),randint(0,255))
        for i in range(base_image.size[0]):
            for j in range(base_image.size[1]):
                if pixels[i,j] == color_c:
                    pixels[i,j] = rand_color
base_mask = Image.new(mode="RGB", size=base_size, color=(0,0,0,0))
base_mask.putalpha(0)
base_mask.paste(microbe_image, (50,50), mask=microbe_image)
full_image = Image.new(mode="RGB", size=base_size, color=(25,128,75))
full_image.paste(base_image, (50,50), mask=base_mask)

So what is this mask parameter that we are using, we did not need it in the original image paste? This is because the original image used transparent pixels in the background but when we transformed the colors we lost that information so we need to use the original that had the transparent pixel information to mask out all the areas we do not want this is because they would overlap underlying pixels.

So now let’s put this into a function that selects a microbe image asset, changes its colors to random variations, and returns it and its mask. To do this we need some python OS tools along with the random and PIL libraries.

from PIL import Image
from random import randint
import random
import os
def full_random_image():
image_name = random.choice(os.listdir("images"))
asset_image = Image.open("images/"+image_name)
asset_size = asset_image.size
base_size = (asset_size[0]+100,asset_size[1]+100)
base_image = Image.new(mode="RGB", size=base_size, color=(0,0,0,0))
base_image.paste(asset_image, (50,50), mask=asset_image)
u_colors = asset_image.getcolors()
pixels = base_image.load() # create the pixel map
no_change = []
for color in u_colors:
if color[1][3] > 0:
color_c = (color[1][0],color[1][1],color[1][2])
if color_c not in no_change:
rand_color = (randint(0,255),randint(0,255),randint(0,255))
for i in range(base_image.size[0]): # for every pixel:
for j in range(base_image.size[1]):
if pixels[i,j] == color_c:
pixels[i,j] = rand_color
base_mask = Image.new(mode="RGB", size=base_size, color=(0,0,0,0))
base_mask.putalpha(0)
base_mask.paste(asset_image, (50,50), mask=asset_image)
return((base_image,base_mask))
def random_color_image(image_name):
asset_image = Image.open("images/"+image_name)
asset_size = asset_image.size
base_size = (asset_size[0]+100,asset_size[1]+100)
base_image = Image.new(mode="RGB", size=base_size, color=(0,0,0,0))
base_image.paste(asset_image, (50,50), mask=asset_image)
u_colors = asset_image.getcolors()
pixels = base_image.load() # create the pixel map
no_change = []
for color in u_colors:
if color[1][3] > 0:
color_c = (color[1][0],color[1][1],color[1][2])
if color_c not in no_change:
rand_color = (randint(0,255),randint(0,255),randint(0,255))
for i in range(base_image.size[0]): # for every pixel:
for j in range(base_image.size[1]):
if pixels[i,j] == color_c:
pixels[i,j] = rand_color
base_mask = Image.new(mode="RGB", size=base_size, color=(0,0,0,0))
base_mask.putalpha(0)
base_mask.paste(asset_image, (50,50), mask=asset_image)
return((base_image,base_mask))

From this, we can make an iterator that creates individual cryptobes or forms them into various combinations and saves them into images that we can upload as NFTs. Here is a simple example that creates N amounts of each asset and randomly changes their color pallet along with selecting a pastel background color.

Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Now you can create higher-level images of your art assets such as a random selection of evenly spaced assets. But I will leave this up to the reader as it’s a simple fun exercise now that you have all the tools. So start creating with your own pixel art assets!

Example Cryptobe Wall

You can find the code on my Github project although I did not include my art assets. You can take one of the example ones in the app to test with if needed.

Github: Python Pixel Art Randomizer

Upload to OpenSea

I won’t cover this too much since there is already a large selection of guides on how to create NFTs on OpenSea. But the long and the short of it is that you need a MetaMask account to create an OpenSea account. Once you have that you can make a collection. If you want to avoid the Ethereium gas fees make sure to select the polygon network as the collections payment method.

You will also need to come up with a sufficiently unique name for your collection and give it a decent description.

From here you can select the create option and upload your PNG name it and select the polygon payment network. Give it a unique name and upload! After this, you can select to sell it through various methods such as auction or fixed price. Hopefully, your NFT will be the next big thing and you’ll make bank, if that happens be sure to send me a kickback if my post helped you get there.

Conclusion

NFTs are hardly a proven thing and based on some of the past purchases they are most definitely overvalued. But the way I see it is art is always evolving why not have fun creating something, it’s free, just don’t take it too seriously.

If you are curious you can take a look at my NFT collections that I created for fun.

OpenSea: Tea Time