moviepy.video.fx.resize — MoviePy 1.0.1 documentation

# Source code for moviepy.video.fx.resize

    resize_possible = True

    try:
        # TRY USING OpenCV AS RESIZER
        #raise ImportError #debugging
        import cv2
        import numpy as np
        def resizer (pic, newsize):
            lx, ly = int(newsize[0]), int(newsize[1])
            if lx > pic.shape[1] or ly > pic.shape[0]:
                # For upsizing use linear for good quality & decent speed
                interpolation = cv2.INTER_LINEAR
            else:
                # For dowsizing use area to prevent aliasing
                interpolation = cv2.INTER_AREA
            return cv2.resize(+pic.astype('uint8'), (lx, ly),
                              interpolation=interpolation)

        resizer.origin = "cv2"

    except ImportError:

        try:
            # TRY USING PIL/PILLOW AS RESIZER
            from PIL import Image
            import numpy as np
            def resizer(pic, newsize):
                newsize = list(map(int, newsize))[::-1]
                shape = pic.shape
                if len(shape)==3:
                    newshape = (newsize[0],newsize[1], shape[2] )
                else:
                    newshape = (newsize[0],newsize[1])

                pilim = Image.fromarray(pic)
                resized_pil = pilim.resize(newsize[::-1], Image.ANTIALIAS)
                #arr = np.fromstring(resized_pil.tostring(), dtype='uint8')
                #arr.reshape(newshape)
                return np.array(resized_pil)

            resizer.origin = "PIL"

        except ImportError:
            # TRY USING SCIPY AS RESIZER
            try:
                from scipy.misc import imresize
                resizer = lambda pic, newsize : imresize(pic,
                                                map(int, newsize[::-1]))
                resizer.origin = "Scipy"

            except ImportError:
                resize_possible = False

    from moviepy.decorators import apply_to_mask

    def resize(clip, newsize=None, height=None, width=None, apply_to_mask=True):
        """
        Returns a video clip that is a resized version of the clip.

        Parameters
        ------------

        newsize:
          Can be either
            - ``(width,height)`` in pixels or a float representing
            - A scaling factor, like 0.5
            - A function of time returning one of these.

        width:
          width of the new clip in pixel. The height is then computed so
          that the width/height ratio is conserved.

        height:
          height of the new clip in pixel. The width is then computed so
          that the width/height ratio is conserved.

        Examples
        ----------

        >>> myClip.resize( (460,720) ) # New resolution: (460,720)
        >>> myClip.resize(0.6) # width and heigth multiplied by 0.6
        >>> myClip.resize(width=800) # height computed automatically.
        >>> myClip.resize(lambda t : 1+0.02*t) # slow swelling of the clip

        """

        w, h = clip.size

        if newsize is not None:

            def trans_newsize(ns):

                if isinstance(ns, (int, float)):
                    return [ns * w, ns * h]
                else:
                    return ns

            if hasattr(newsize, "__call__"):

                newsize2 = lambda t : trans_newsize(newsize(t))

                if clip.ismask:

                    fun = lambda gf,t: (1.0*resizer((255 * gf(t)).astype('uint8'),
                                                     newsize2(t))/255)
                else:

                    fun = lambda gf,t: resizer(gf(t).astype('uint8'),
                                              newsize2(t))

                return clip.fl(fun, keep_duration=True,
                               apply_to= (["mask"] if apply_to_mask else []))

            else:

                newsize = trans_newsize(newsize)

        elif height is not None:

            if hasattr(height, "__call__"):
                fun = lambda t : 1.0*int(height(t))/h
                return resize(clip, fun)

            else:

                newsize = [w * height / h, height]

        elif width is not None:

            if hasattr(width, "__call__"):
                fun = lambda t : 1.0*width(t)/w
                return resize(clip, fun)

            newsize = [width, h * width / w]

        # From here, the resizing is constant (not a function of time), size=newsize

        if clip.ismask:
            fl = lambda pic: 1.0*resizer((255 * pic).astype('uint8'), newsize)/255.0

        else:
            fl = lambda pic: resizer(pic.astype('uint8'), newsize)

        newclip = clip.fl_image(fl)

        if apply_to_mask and clip.mask is not None:
            newclip.mask = resize(clip.mask, newsize, apply_to_mask=False)

        return newclip

    if not resize_possible:

        doc = resize.__doc__
        def resize(clip, newsize=None, height=None, width=None):
            raise ImportError("fx resize needs OpenCV or Scipy or PIL")
        resize.__doc__ = doc