Making Pixel art using Python (Minecraft Edition)
As random as this might seem, it was strangely satisfying and fun to do. Yes, I sat and just created Numpy arrays with specific RGB values to make 720x720 px images of Minecraft mobs.
Let’s first import the required libraries:
numpy for creating and manipulating arrays,
matplotlib for displaying and saving the data as an image file, and the
random module (this was only used to randomly pick from shades of green for the creeper face).
import numpy as np
import matplotlib.pyplot as plt
Initializing the Numpy array
creeper = np.full((720,720,3), 255, dtype="uint8")
Here I’m using Numpy to initialize an array (720 pixels in width and height, and the third dimension to store color) with the value 255 and
dtype as uint8 i.e. 8-bit unsigned integer (0–255). Displaying the array as an image using
pyplot.imshow() would give a completely white image since it’s filled with the value 255.
Setting the Colors
I made a list of the shades of green that I wanted on the creeper face. All these colors are represented as RGB (Red Green Blue) values, each storing some integer in the range 0-255 (this is why we’re using
greens = [[204, 255, 204], #lighter to darker shades of green
[153, 255, 153],
[102, 255, 102],
[51, 255, 51],
[0, 255, 0],
[0, 204, 0],
[0, 153, 0],
[0, 102, 0]]
Filling the Colors
Since the image is 720x720 px, I decided to section the plane into 90px squares that would divide the entire image as an 8x8 grid. This was done by running two for loops with range 0–720 and stride set to 90.
For each iteration of the inner loop, I fetched a random shade of green from the list
greens using the function
random.choices(). Then I used numpy array slicing to set a 90x90 unit box of the image with the randomly chosen color.
for i in range(0,720,90):
for j in range(0,720,90):
color = random.choices(greens, k=1)
creeper[i:i+90, j:j+90] = color
The resulting image would look something like this,
Next, to fill the features of the face, I simply got the positions of each feature by multiplying the box number I wanted to color with the value 90. For eg. in the above image, to color the second last box in the top row ( or position (0,6)), the start index row-wise would be 0 * 90 = 0, and column-wise value would be 6 * 90 = 540. The end index would depend on how many blocks (rows and columns) we wish to color.
creeper[90:270, 90:270] = [0, 0, 0] # right-eye
creeper[90:270, 450:630] = [0, 0, 0] # left-eye
creeper[270:360, 270:450] = [0, 0, 0] # nose
creeper[360:540, 180:540] = [0, 0, 0] # mouth
creeper[540:630, 180:270] = [0, 0, 0] # mouth bottom right trail
creeper[540:630, 450:540] = [0, 0, 0] # mouth bottom left trail
That’s pretty much it. The array when displayed as an image, would now look like this,
Pretty simple right ? I also made an enderman face by simply initializing the array with black (0, 0, 0) instead of white (255, 255, 255).
enderman = np.full((720,720,3), 0, dtype="uint8")
Since the only features on the face were the eyes, I just made a list containing shades of purple for the eyes.
purples = [[236, 116, 255], [204, 0, 204], [237, 140, 255]]
Then I just filled the required boxes in the grid with colors I wanted.
enderman[360:450, 0:90] = enderman[360:450,630:720] = purples
enderman[360:450, 90:180] = enderman[360:450,540:630] = purples
enderman[360:450, 180:270] = enderman[360:450,450:540] = purples
The end result would look like this,
You can easily merge these images either vertically or horizontally by making use of
collage = np.hstack((creeper, enderman))
You can also save the image locally using
That’s all there is to it. Hope you found this interesting. I certainly enjoyed doing this and will probably end up making all the mob faces in the same way teehee.