Generate NTF images with Python
Imagine buying a digital artwork on the internet at a reasonable price and getting a unique digital token known as an NFT, which proves your authority over the artwork you bought. Wouldn't it be great?
NFTs are currently taking the digital art and collectables world by storm. When everyone worldwide believed Bitcoin as the digital answer to currency, NFTs are now pitched as the digital answer to collectibles. Digital artists see their lives changing thanks to massive sales to a new crypto-audience.
What is NFT?
NFT stands for a non-fungible token, which means it can neither be replaced nor interchanged because it has unique properties. NFT is a digital asset that represents internet collectibles like art, music, and games with an authentic certificate created by blockchain technology that underlies Cryptocurrency. It cannot be forged or otherwise manipulated. NFT exchanges take place in cryptocurrencies such as Bitcoin on specialist sites.
Let's start.
Before start we need to install a library called pillow.
So what is pillow?
Basically pillow is a library that will help us create and save our images. If you want to know more about it click here.
In this project we are going to generate some lines and save the images as a png file.
NFT_Generator.py
First thing to do is to import our modules or libraries that we are going to use.
from PIL import Image, ImageDraw, ImageChop
import random
import colorsyss
Let me explain why we are exporting these modules.
Image, ImageDraw and ImageChop - These functions from the pillow library are going to help us handle we the image drawing and overlays that we are going to do.
Random - It will be used to generate random colors.
colorsys - This one is will make possible to use HSV colors instead the usual RGB, and it will help us convert the HSV to RGB.
So let's start by generating our colors.
# Generate random color
def random_color():
h = random.random()
s = 1
v = 1
float_rgb = colorsys.hsv_to_rgb(h, s, v)
rgb = [int(x * 255) for x in float_rgb]
return tuple(rgb)
The random_color() function, as the name sujests, it will generate our colors. Hue will have a value between 0 and 1 and the saturation and value will have a fix value of 1. Then we are going to convert the HSV value to RGB and we are going to rung the RGB variable and store the RGB values in the rgb variable and return it to be used later when we call the function.
NOTE: Let me explain what HSV stands for:
Hue - Hue is the color portion of the model, expressed as a number from 0 to 360 degrees:
Saturation - Saturation describes the amount of gray in a particular color, from 0 to 100 percent. Reducing this component toward zero introduces more gray and produces a faded effect. Sometimes, saturation appears as a range from 0 to 1, where 0 is gray, and 1 is a primary color.
Value -Value works in conjunction with saturation and describes the brightness or intensity of the color, from 0 to 100 percent, where 0 is completely black, and 100 is the brightest and reveals the most color.
After creating our function to create our colors it is time to generate our NFT's.
So firts we are going to create our generate nft function we then block by block adding code to it while I explain it.
def generate_nft(path: str):
Our function will receive a path, that path is where we are going to store the image or images.
# Image Size
target_size_px = 256
# Scale factor for our image
scale_factor = 2
So as you can see we create two variables, one will store the size of our image and the other will store the scale factor that is going to be used to scale up our image, for later to resize the image and to make our images more soft.
# Draw Basic Image
image_size_px = target_size_px * scale_factor
image_bg_color = (0, 0, 0)
padding_px = 16 * scale_factor
start_color = random_color()
end_color = random_color()
image = Image.new(
"RGB",
size=(image_size_px, image_size_px),
color=image_bg_color
)
Now it is time to draw our images. In the code above we are adding size and background to the image. Besides that we are adding some padding to the image to center the image itself. Then we are going to use 2 colors later but we can declared now. These colors will be used to create a gradiend effect on the drawing. After declaring our variables it is time to create our image. for that we are going to use Image with the function new. This will receive the type of colors that we are using, the size of the image and the color value.
Now that we create our image it is time to draw it, for that we do the following
draw = ImageDraw.Draw(image)
In our image we are going to draw some lines and those lines will be linked, so for that we need to create an array of points and generate them and happend it to the array:
points = []
# Generate the points
for _ in range(10):
random_point = (
random.randint(padding_px, image_size_px-padding_px),
random.randint(padding_px, image_size_px-padding_px)
)
points.append(random_point)
Once we create our points, we need to create a bouncing box to make sure that our lines will be centered for that we need to get the max and min XY of our points:
# Draw bouncing box
min_x = min([p[0] for p in points])
max_x = max([p[0] for p in points])
min_y = min([p[1] for p in points])
max_y = max([p[1] for p in points])
Now it is time to center our image:
# Center Image
delta_x = min_x - (image_size_px - max_x)
delta_y = min_y - (image_size_px - max_y)
for i, point in enumerate(points):
points[i] = (point[0] - delta_x // 2, point[1] - delta_y // 2)
Let me explain what is happening in the code above.
The variables delta_x and delta_y will receive the differente between the biggest side and the smallest size of the image. in other words, if we dont have our image centered one of the sizes will be bigger than the other and what we need to get is the difference between them.
After that we are going to loop our points and give them the correct position. That makes sure that our image is centered.
Now what we need to do is to draw our points in our image:
# Draw the points
thickness = 0
n_points = len(points)
for i, point in enumerate(points):
# Overlay Canvas
overlay = Image.new(
"RGB",
size=(image_size_px, image_size_px),
color=image_bg_color
)
overlay_draw = ImageDraw.Draw(overlay)
p1 = point
if i == n_points - 1:
p2 = points[0]
else:
p2 = points[i+1]
line_xy = (p1, p2)
color_factor = i / n_points
line_color = interpolate(start_color, end_color, color_factor)
thickness += scale_factor
overlay_draw.line(line_xy, fill=line_color, width=thickness)
image = ImageChops.add(image, overlay)
To draw our lines, first we are going to give them some thickness, so we declared a variable for that. We create a variable to store the size of the points array that is going to be used later in our color factor. but for now we are going to loop throgh all our points.
Inside our loop we are going to create an overlay canvas just to make our image a little better. This overlay will be created the same way we create our image.
So our lines will be linked, for that we are going to store the two points of that line.
p1 represents the first point of the line and p2 the last point. However the p2 needs to be conditioned. because we need to check if we are in the last point of our array or not. After the validation we can create our line by storing the two values in a variable.
The color factor it will be used to check if we are at the end of our points or not. Now it is time to use the interpolated function by giving the start color, end color and the color factor.
while we do that we add the scale factor to the thickness of the line and we draw the lines and add the lines and overlay to the image.
After all that process we are going to resize our image to make it cleaner.
# Resize image
image = image.resize(
(target_size_px, target_size_px),
resample=image.ANTIALIAS
)
Finally it is time to save our image. To save our image we need to give the path were we want to save the file.
# Save Imag
image.save(path)e
The following code it is just a bonus if you want to generate 5 NFTs at once:
if __name__ == "__main__":
for i in range(5):
generate_nft(f"teste_image_{i}.png")
This is an image generated by our application.
Conclusion
This small project open a door for you to create your own NFTs. You can use whatever library you want to create beautifull drawings. There are a great number of generated NFTs being sold for millions of dollars.