def scalar_multiplication(first_image: ImageWrapper, scalar: float):
    w, h = first_image.dimensions()

    result = ImageWrapper.from_dimensions(w, h, mode=first_image.get_mode())

    for x in range(w):
        for y in range(h):
            val = [
                int(first_image.get_pixel(x, y)[i] * scalar) % 255
                for i in range(len(first_image.get_pixel(x, y)))
            ]
            result.set_pixel(x, y, tuple(val))

    return result
def pixel_to_pixel_operation(first_image: ImageWrapper,
                             second_image: ImageWrapper, operation):
    assert first_image.dimensions() == second_image.dimensions()

    w, h = first_image.dimensions()
    matrix = []

    for x in range(w):
        row = []
        for y in range(h):
            val = [
                operation(
                    first_image.get_pixel(x, y)[i],
                    second_image.get_pixel(x, y)[i])
                for i in range(len(first_image.get_pixel(x, y)))
            ]
            row.append(tuple(val))
        matrix.append(row)

    return matrix_to_image(normalized_matrix(matrix),
                           mode=first_image.get_mode())
def pixel_transformation(image: ImageWrapper, transformation_function):
    w, h = image.dimensions()

    matrix = []

    for x in range(w):
        row = []
        for y in range(h):
            val = transformation_function(x, y, image.get_pixel(x, y))

            row.append(tuple(val))
        matrix.append(row)

    return matrix_to_image(normalized_matrix(matrix), mode=image.get_mode())