from typing import List


def rgb_to_cielab(rgb: List[int]) -> List[int]:
    """
    Convert from RGB to CIELab color space.

    Arguments:
        rgb: Iterable of length 3 with integer values between 0 and 255

    Returns:
        A list with 3 integer scaled values of CIELab.

    References:
        - https://github.com/QIICR/dcmqi/blob/0c101b702f12a86cc142cb000a074fbd341f8784/libsrc/Helper.cpp#L173
        - https://github.com/QIICR/dcmqi/blob/0c101b702f12a86cc142cb000a074fbd341f8784/libsrc/Helper.cpp#L256
        - https://github.com/QIICR/dcmqi/blob/0c101b702f12a86cc142cb000a074fbd341f8784/libsrc/Helper.cpp#L336
    """
    assert len(rgb) == 3

    # RGB -> CIEXYZ (Ref 1)
    tmp = tuple(min(max(x / 255.0, 0.0), 1.0) for x in rgb)
    tmp = tuple(((x + 0.055) / 1.055) ** 2.4 if x > 0.04045 else x / 12.92 for x in tmp)
    tmp = tuple(x * 100 for x in tmp)
    tmp = (
        0.4124564 * tmp[0] + 0.3575761 * tmp[1] + 0.1804375 * tmp[2],
        0.2126729 * tmp[0] + 0.7151522 * tmp[1] + 0.0721750 * tmp[2],
        0.0193339 * tmp[0] + 0.1191920 * tmp[1] + 0.9503041 * tmp[2],
    )

    # CIEXYZ -> CIELab (Ref 2)
    tmp = tuple(x / y for x, y in zip(tmp, (95.047, 100, 108.883)))
    tmp = tuple(x ** (1 / 3) if x > 0.008856 else (7.787 * x) + (16 / 116) for x in tmp)
    tmp = ((116 * tmp[1]) - 16, 500 * (tmp[0] - tmp[1]), 200 * (tmp[1] - tmp[2]))

    # CIELab -> ScaledCIELab (Ref 3)
    return [
        int(tmp[0] * 65535 / 100 + 0.5),
        int((tmp[1] + 128) * 65535 / 255 + 0.5),
        int((tmp[2] + 128) * 65535 / 255 + 0.5),
    ]