from PIL import Image

def mass(image, from_x=0, from_y=0, to_x=None, to_y=None):
    width, height = image.size
    pixels = image.load()
    total_mass = 0

    if to_x is None:
        to_x = width
    if to_y is None:
        to_y = height

    for x in range(from_x, to_x):
        for y in range(from_y, to_y):
            total_mass += pixels[x, y]

    return total_mass

def center_of_mass(image):
    width, height = image.size
    pixels = image.load()
    total_mass = mass(image)
    if total_mass == 0:
        return width / 2, height / 2

    center_x = 0
    center_y = 0

    for x in range(width):
        for y in range(height):
            center_x += x * pixels[x, y]
            center_y += y * pixels[x, y]

    center_x /= total_mass
    center_y /= total_mass

    return center_x + 0.5, center_y + 0.5

def remove_black_borders(image):
    width, height = image.size
    for x in range(width):
        if mass(image, from_x=x, to_x=x+1) > 0:
            break
    image = image.crop((x, 0, width, height))

    width, height = image.size
    for x in range(width - 1, -1, -1):
        if mass(image, from_x=x, to_x=x+1) > 0:
            break
    image = image.crop((0, 0, x + 1, height))

    width, height = image.size
    for y in range(height):
        if mass(image, from_y=y, to_y=y+1) > 0:
            break
    image = image.crop((0, y, width, height))

    width, height = image.size
    for y in range(height - 1, -1, -1):
        if mass(image, from_y=y, to_y=y+1) > 0:
            break
    image = image.crop((0, 0, width, y + 1))

    return image

def preprocess(image):
    image = image.convert('L')
    image = image.point(lambda x: 255 if x > 128 else 0)
    image = remove_black_borders(image)

    ratio = image.width / image.height

    if ratio > 1:
        new_width = 20
        new_height = int(20 / ratio)
    else:
        new_width = int(20 * ratio)
        new_height = 20

    image = image.resize((new_width, new_height))

    center_x, center_y = center_of_mass(image)
    offset_x = int(28 / 2 - center_x)
    offset_y = int(28 / 2 - center_y)

    background = Image.new('L', (28, 28), 'black')
    background.paste(image, (offset_x, offset_y))

    return background
