def pad_nd_image(image,
                 new_shape=None,
                 mode="constant",
                 kwargs=None,
                 return_slicer=False,
                 shape_must_be_divisible_by=None):
    """
    image: Input image.
    new_shape: New shape of image, if None, the image shape will be determined by shape_must_be_divisible_by. Default: None.
    mode: The padding mode for image. Reference to np.pad for more information.
    kwargs: The padding kwargs for image. Reference to np.pad for more information.
    return_slicer: if True then this function will also return what coords you will need to use when cropping back to original shape. Default: False.
    shape_must_be_divisible_by: After applying new_shape, make sure the new shape is divisibly by that number (can also be a list with an entry for each axis). Whatever is missing to match that will
    be padded (so the result may be larger than new_shape if shape_must_be_divisible_by is not None). Default: None.
    """
    if kwargs is None:
        kwargs = {'constant_values': 0}

    if new_shape is not None:
        old_shape = np.array(image.shape[-len(new_shape):])
    else:
        assert shape_must_be_divisible_by is not None, "shape_must_be_divisible_by must not be None when shape_must_be_divisible_by is None."
        assert isinstance(
            shape_must_be_divisible_by, (list, tuple, np.ndarray)
        ), "shape_must_be_divisible_by can be 'list', 'tuple', 'np.ndarray', but got {}.".format(
            shape_must_be_divisible_by)
        new_shape = image.shape[-len(shape_must_be_divisible_by):]
        old_shape = new_shape

    num_axes_nopad = len(image.shape) - len(new_shape)
    new_shape = [max(new_shape[i], old_shape[i]) for i in range(len(new_shape))]

    if not isinstance(new_shape, np.ndarray):
        new_shape = np.array(new_shape)

    if shape_must_be_divisible_by is not None:
        if not isinstance(shape_must_be_divisible_by,
                          (list, tuple, np.ndarray)):
            shape_must_be_divisible_by = [shape_must_be_divisible_by] * len(
                new_shape)
        else:
            assert len(shape_must_be_divisible_by) == len(new_shape)

        for i in range(len(new_shape)):
            if new_shape[i] % shape_must_be_divisible_by[i] == 0:
                new_shape[i] -= shape_must_be_divisible_by[i]

        new_shape = np.array([
            new_shape[i] + shape_must_be_divisible_by[i] - new_shape[i] %
            shape_must_be_divisible_by[i] for i in range(len(new_shape))
        ])

    difference = new_shape - old_shape
    pad_below = difference // 2
    pad_above = difference // 2 + difference % 2
    pad_list = [[0, 0]] * num_axes_nopad + list(
        [list(i) for i in zip(pad_below, pad_above)])

    if not ((all([i == 0 for i in pad_below])) and
            (all([i == 0 for i in pad_above]))):
        res = np.pad(image, pad_list, mode, **kwargs)
    else:
        res = image

    if not return_slicer:
        return res

    pad_list = np.array(pad_list)
    pad_list[:, 1] = np.array(res.shape) - pad_list[:, 1]
    slicer = list(slice(*i) for i in pad_list)
    return res, slicer

    image: Input image.
    new_shape: New shape of image, if None, the image shape will be determined by shape_must_be_divisible_by. Default: None.
    mode: The padding mode for image. Reference to np.pad for more information.
    kwargs: The padding kwargs for image. Reference to np.pad for more information.
    return_slicer: if True then this function will also return what coords you will need to use when cropping back to original shape. Default: False.
    shape_must_be_divisible_by: After applying new_shape, make sure the new shape is divisibly by that number (can also be a list with an entry for each axis). Whatever is missing to match that will
    be padded (so the result may be larger than new_shape if shape_must_be_divisible_by is not None). Default: None.
    
contrib/MedicalSeg/nnunet/utils/utils.py