Jabir
Jabir

Reputation: 81

How do I create a checker board pattern?

I am trying to write a code that can generate an checker board pattern. The final image size should be 100 x 100, the checker board size 5 x 5, such that each box has dimensions h/5 and w/5. The code I have is wrong:

from PIL import Image, ImageDraw

h = 500
w = 500
img = Image.new("RGB", (h,w), (255, 0, 0))   # create a new 15x15 image
pixels = img.load()                          # create the pixel map
print("1")

for i in range (h):
    for j in range(w):
        if ((i + j)%2) != 0:
            im = Image.new('RGB', (h//5, w//5), 'black')
        else:
            draw = ImageDraw.Draw(img, "RGBA")
            draw.rectangle(((h//5, w//5), (i+.5, j+.5)), fill="blue")
    
print ("done")
img.show()

Upvotes: 2

Views: 3603

Answers (3)

HansHirse
HansHirse

Reputation: 18925

I had the feeling, that accessing single pixels in Pillow using all those nested loops isn't the best idea performance-wise.

So, my idea would be to set up a small (m, n) checker using (nested) lists, build a Pillow Image object from that using putdata, and simply resize it to the desired size using the Image.NEAREST resampling filter. I added some flexibility for choosing colors and image modes.

from itertools import chain
from math import ceil
from PIL import Image

m, n = (5, 5)                                   # Checker dimension (x, y)
w, h = (100, 100)                               # Final image width and height

c1 = 0      # (224, 64, 64)                     # First color
c2 = 255    # (128, 128, 128)                   # Second color
mode = 'L' if isinstance(c1, int) else 'RGB'    # Mode from first color

# Generate pixel-wise checker, even x dimension
if m % 2 == 0:
    pixels = [[c1, c2] for i in range(int(m/2))] + \
             [[c2, c1] for i in range(int(m/2))]
    pixels = [list(chain(*pixels)) for i in range(ceil(n/2))]

# Generate pixel-wise checker, odd x dimension
else:
    pixels = [[c1, c2] for i in range(ceil(m*n/2))]

# Generate final Pillow-compatible pixel values
pixels = list(chain(*pixels))[:(m*n)]

# Generate Pillow image from pixel values, resize to final image size, and save
checker = Image.new(mode, (m, n))
checker.putdata(pixels)
checker = checker.resize((w, h), Image.NEAREST)
checker.save('checker.png')

For the shown configuration, the output would be:

Checker #1

Switching to RGB, and altering m, w, and h, we might get something like this:

Checker #2

As already pointed out in the other answers, if w or h are not whole integer factors of m or n, then you'll get somehow distorted output (m = n = 5, w = h = 102):

Checker #3

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
Pillow:        8.1.2
----------------------------------------

Upvotes: 2

Mainly Karma
Mainly Karma

Reputation: 477

I know it's already been answered, here's a way to loop over it differently

from PIL import Image

h = 500
w = 500

# You can also easily set the number of squares per row
number_of_square_across = 10

# You can also easily set the colors
color_one = (0, 0, 0)
color_two = (0, 0, 255)

length_of_square = h/number_of_square_across
length_of_two_squares = h/number_of_square_across*2

img = Image.new("RGB", (h, w), (255, 0, 0))  # create a new 15x15 image
pixels = img.load()  # create the pixel map

for i in range(h):
    # for every 100 pixels out of the total 500 
    # if its the first 50 pixels
    if (i % length_of_two_squares) >= length_of_square:
        for j in range(w):
            if (j % length_of_two_squares) < length_of_square:
                pixels[i,j] = color_one
            else:
                pixels[i,j] = color_two

    # else its the second 50 pixels         
    else:
        for j in range(w):
            if (j % length_of_two_squares) >= length_of_square:
                pixels[i,j] = color_one
            else:
                pixels[i,j] = color_two

print("done")
img.show()

Upvotes: 2

LPR
LPR

Reputation: 390

For anyone who reads this in the future and is looking for a general solution to make a checker board see here:

M, N = 10, 10
arr = [[0 for _ in range(N)] for _ in range(M)] # an M by N  array
for i in range(M):
    for j in range(N):
        if (i&1)^(j&1): # if (i is odd and j is even) or (j is odd and i is even)
            arr[i][j] = 1 # change the pixel from white to black

Solution tailored specifically to the OP's inquiry see here:

from PIL import Image, ImageDraw


h = 500
w = 500
img = Image.new("RGB", (h,w), (255, 0, 0)) # create a new 15x15 image
pixels = img.load() # create the pixel map
print ("1")


for i in range (h):
    for j in range(w):
        if (i&1)^(j&1):
            pixels[i,j] = (0, 0, 0)
        else:
            pixels[i,j] = (0, 0, 255)

    
print ("done")
img.show()

# BIGGER BOX SIZE
from PIL import Image, ImageDraw


h = 500
w = 500
img = Image.new("RGB", (h,w), (255, 0, 0)) # create a new 15x15 image
pixels = img.load() # create the pixel map
print ("1")

box_size = 25
for i in range (0, h, box_size):
    for j in range(0, w, box_size):
        y, x = i // box_size, j // box_size
        if (y&1)^(x&1):
            for di in range(box_size):
                for dj in range(box_size):
                    pixels[i+di,j+dj] = (0, 0, 0)
        else:
            for di in range(box_size):
                for dj in range(box_size):
                    pixels[i+di,j+dj] = (0, 0, 255)
    
print ("done")
img.show()

This will get you the checker pattern for an array.

Upvotes: 1

Related Questions