code: def rotate(
      clip,
      angle,
      unit="deg",
      resample="bicubic",
      expand=True,
      center=None,
      translate=None,
      bg_color=None,
  ):
      """
      Rotates the specified clip by ``angle`` degrees (or radians) anticlockwise
      If the angle is not a multiple of 90 (degrees) or ``center``, ``translate``,
      and ``bg_color`` are not ``None``, the package ``pillow`` must be installed,
      and there will be black borders. You can make them transparent with:
  
      >>> new_clip = clip.add_mask().rotate(72)
  
      Parameters
      ----------
  
      clip : VideoClip
        A video clip.
  
      angle : float
        Either a value or a function angle(t) representing the angle of rotation.
  
      unit : str, optional
        Unit of parameter `angle` (either "deg" for degrees or "rad" for radians).
  
      resample : str, optional
        An optional resampling filter. One of "nearest", "bilinear", or "bicubic".
  
      expand : bool, optional
        If true, expands the output image to make it large enough to hold the
        entire rotated image. If false or omitted, make the output image the same
        size as the input image.
  
      translate : tuple, optional
        An optional post-rotate translation (a 2-tuple).
  
      center : tuple, optional
        Optional center of rotation (a 2-tuple). Origin is the upper left corner.
  
      bg_color : tuple, optional
        An optional color for area outside the rotated image. Only has effect if
        ``expand`` is true.
      """
      if Image:
          try:
              resample = {
                  "bilinear": Image.BILINEAR,
                  "nearest": Image.NEAREST,
                  "bicubic": Image.BICUBIC,
              }[resample]
          except KeyError:
              raise ValueError(
                  "'resample' argument must be either 'bilinear', 'nearest' or 'bicubic'"
              )
  
      if hasattr(angle, "__call__"):
          get_angle = angle
      else:
          get_angle = lambda t: angle
  
      def filter(get_frame, t):
          angle = get_angle(t)
          im = get_frame(t)
  
          if unit == "rad":
              angle = math.degrees(angle)
  
          angle %= 360
          if not center and not translate and not bg_color:
              if (angle == 0) and expand:
                  return im
              if (angle == 90) and expand:
                  transpose = (
                      [1, 0] if len(im.shape) == 2 else [1, 0, 2]
                  )
                  return np.transpose(im, axes=transpose)[::-1]
              elif (angle == 270) and expand:
                  transpose = (
                      [1, 0] if len(im.shape) == 2 else [1, 0, 2]
                  )
                  return np.transpose(im, axes=transpose)[:, ::-1]
              elif (angle == 180) and expand:
                  return im[::-1, ::-1]
  
          if not Image:
              raise ValueError(
                  'Without "Pillow" installed, only angles that are a multiple of 90'
                  " without centering, translation and background color transformations"
                  ' are supported, please install "Pillow" with `pip install pillow`'
              )
  
          # build PIL.rotate kwargs
          kwargs, _locals = ({}, locals())
          for PIL_rotate_kw_name, (
              kw_name,
              supported,
              min_version,
          ) in PIL_rotate_kwargs_supported.items():
              # get the value passed to rotate FX from `locals()` dictionary
              kw_value = _locals[kw_name]
  
              if supported:  # if argument supported by PIL version
                  kwargs[PIL_rotate_kw_name] = kw_value
              else:
                  if kw_value is not None:  # if not default value
                      warnings.warn(
                          f"rotate '{kw_name}' argument is not supported"
                          " by your Pillow version and is being ignored. Minimum"
                          " Pillow version required:"
                          f" v{'.'.join(str(n) for n in min_version)}",
                          UserWarning,
                      )
  
          # PIL expects uint8 type data. However a mask image has values in the
          # range [0, 1] and is of float type.  To handle this we scale it up by
          # a factor 'a' for use with PIL and then back again by 'a' afterwards.
          if im.dtype == "float64":
              # this is a mask image
              a = 255.0
          else:
              a = 1
  
          # call PIL.rotate
          return (
              np.array(
                  Image.fromarray(
                      np.array(a * im).astype(np.uint8)
                  ).rotate(
                      angle, expand=expand, resample=resample, **kwargs
                  )
              )
              / a
          )
  
      return clip.transform(filter, apply_to=["mask"])
  
imports: import math
  import warnings
  import numpy
label_desc: Use image node_id 1 for calling a global function with example usage: rotate(clip, angle, unit, resample, expand, center, translate, bg_color) and returns: clip, unknown, im, np, np, im