import numpy as np
from numpy.typing import NDArray as NDArray
from typing import Any

def numpy_to_gif(path: str, array: NDArray[np.integer | np.floating | np.bool_], duration: int = 100, loop: int = 0, mkdir: bool = True, **kwargs: Any) -> None:
    ''' Generate a \'.gif\' file from a numpy array for 3D/4D visualization.

\tArgs:
\t\tpath     (str):     Path to the output .gif file.
\t\tarray    (NDArray): Numpy array to be dumped (must be 3D or 4D).
\t\t\t3D: (depth, height, width) - e.g. (64, 1024, 1024)
\t\t\t4D: (depth, height, width, channels) - e.g. (50, 64, 1024, 3)
\t\tduration (int):     Duration between frames in milliseconds.
\t\tloop     (int):     Number of loops (0 = infinite).
\t\tmkdir    (bool):    Create the directory if it does not exist.
\t\t**kwargs (Any):     Additional keyword arguments for PIL.Image.save().

\tExamples:

\t\t.. code-block:: python

\t\t\t> # 3D array example
\t\t\t> array = np.random.randint(0, 256, (10, 100, 100), dtype=np.uint8)
\t\t\t> numpy_to_gif("output_10_frames_100x100.gif", array, duration=200, loop=0)

\t\t\t> # 4D array example (batch of 3D images)
\t\t\t> array_4d = np.random.randint(0, 256, (5, 10, 100, 3), dtype=np.uint8)
\t\t\t> numpy_to_gif("output_50_frames_100x100.gif", array_4d, duration=200)

\t\t\t> total_duration = 1000  # 1 second
\t\t\t> numpy_to_gif("output_1s.gif", array, duration=total_duration // len(array))
\t'''
