Genuary 14

Day 14 of #Genuary!

Pure black and white. No gray.

For today's prompt, I'm demonstrating one of my favorite dithering techniques: Magic Square Dithering!

Every row and column of a magic square has the same sum, which makes it a great thresholding pattern for dithering by avoiding horizontal and vertical banding.

The Code

Setup

from PIL import Image
import numpy as np
from IPython.display import display
              

Python

Input Image

target_image = Image.open("assets/charcuterie.jpg").convert('L').rotate(-90)
display(target_image)
              

Python

Canvas Image

canvas_image = Image.new("L", target_image.size, "black")
display(canvas_image)
              

Python

Algorithm and Results!

magic_square = [[2, 7, 6], [9, 5, 1], [4, 3, 8]]

for i in range(6, 10):
    width = 2**i
    target_image_data = np.array(target_image.resize((width, width)))
    canvas_image_data = np.array(canvas_image.resize((width, width)))

    for i in range(0, 3):
        for j in range(0, 3):
            canvas_image_data[i::3, j::3] = np.where(
                target_image_data[i::3, j::3] > 255*magic_square[i][j]/9, 
                255, 
                0
            )


    canvas_image = Image.fromarray(canvas_image_data).resize(
        (1024, 1024), 
        Image.NEAREST
    )
    display(canvas_image)
              

Python