def test_margin(ClipClass, margin_size, margins, color, expected_result): if ClipClass is BitmapClip: clip = BitmapClip([["RRR", "RRR"], ["RRR", "RRR"]], fps=1) else: clip = ColorClip(color=(255, 0, 0), size=(3, 2), duration=2).with_fps(1) # if None, set default argument values if color is None: color = (0, 0, 0) if margins is None: margins = [0, 0, 0, 0] left, right, top, bottom = margins new_clip = margin( clip, margin_size=margin_size, left=left, right=right, top=top, bottom=bottom, color=color, ) assert new_clip == BitmapClip(expected_result, fps=1)
def test_colorx(): color_dict = {"H": (0, 0, 200), "L": (0, 0, 50), "B": (0, 0, 255), "O": (0, 0, 0)} clip = BitmapClip([["LLO", "BLO"]], color_dict=color_dict, fps=1) clipfx = colorx(clip, 4) target = BitmapClip([["HHO", "BHO"]], color_dict=color_dict, fps=1) assert target == clipfx
def test_freeze_region(): clip = BitmapClip([["AAB", "CCC"], ["BBR", "DDD"], ["CCC", "ABC"]], fps=1) # Test region clip1 = freeze_region(clip, t=1, region=(2, 0, 3, 1)) target1 = BitmapClip([["AAR", "CCC"], ["BBR", "DDD"], ["CCR", "ABC"]], fps=1) assert clip1 == target1 # Test outside_region clip2 = freeze_region(clip, t=1, outside_region=(2, 0, 3, 1)) target2 = BitmapClip([["BBB", "DDD"], ["BBR", "DDD"], ["BBC", "DDD"]], fps=1) assert clip2 == target2
def test_invert_colors(): clip = BitmapClip( [["AB", "BC"]], color_dict={"A": (0, 0, 0), "B": (50, 100, 150), "C": (255, 255, 255)}, fps=1, ) clip1 = invert_colors(clip) target1 = BitmapClip( [["CD", "DA"]], color_dict={"A": (0, 0, 0), "D": (205, 155, 105), "C": (255, 255, 255)}, fps=1, ) assert clip1 == target1
def test_time_mirror(): clip = BitmapClip([["AA", "AA"], ["BB", "BB"], ["CC", "CC"]], fps=1) clip1 = time_mirror(clip) target1 = BitmapClip([["CC", "CC"], ["BB", "BB"], ["AA", "AA"]], fps=1) assert clip1 == target1 clip2 = BitmapClip( [["AA", "AA"], ["BB", "BB"], ["CC", "CC"], ["DD", "DD"]], fps=1) clip3 = time_mirror(clip2) target3 = BitmapClip( [["DD", "DD"], ["CC", "CC"], ["BB", "BB"], ["AA", "AA"]], fps=1) assert clip3 == target3
def test_time_symmetrize(): clip = BitmapClip([["AA", "AA"], ["BB", "BB"], ["CC", "CC"]], fps=1) clip1 = time_symmetrize(clip) target1 = BitmapClip( [ ["AA", "AA"], ["BB", "BB"], ["CC", "CC"], ["CC", "CC"], ["BB", "BB"], ["AA", "AA"], ], fps=1, ) assert clip1 == target1
def test_fadein(): color_dict = { "I": (0, 0, 0), "R": (255, 0, 0), "G": (0, 255, 0), "B": (0, 0, 255), "W": (255, 255, 255), } clip = BitmapClip([["R"], ["G"], ["B"]], color_dict=color_dict, fps=1) clip1 = fadein(clip, 1) # default initial color target1 = BitmapClip([["I"], ["G"], ["B"]], color_dict=color_dict, fps=1) assert clip1 == target1 clip2 = fadein(clip, 1, initial_color=(255, 255, 255)) # different initial color target2 = BitmapClip([["W"], ["G"], ["B"]], color_dict=color_dict, fps=1) assert clip2 == target2
def test_crop(): # x: 0 -> 4, y: 0 -> 3 inclusive clip = BitmapClip([["ABCDE", "EDCBA", "CDEAB", "BAEDC"]], fps=1) clip1 = crop(clip) target1 = BitmapClip([["ABCDE", "EDCBA", "CDEAB", "BAEDC"]], fps=1) assert clip1 == target1 clip2 = crop(clip, x1=1, y1=1, x2=3, y2=3) target2 = BitmapClip([["DC", "DE"]], fps=1) assert clip2 == target2 clip3 = crop(clip, y1=2) target3 = BitmapClip([["CDEAB", "BAEDC"]], fps=1) assert clip3 == target3 clip4 = crop(clip, x1=2, width=2) target4 = BitmapClip([["CD", "CB", "EA", "ED"]], fps=1) assert clip4 == target4 # TODO x_center=1 does not perform correctly clip5 = crop(clip, x_center=2, y_center=2, width=3, height=3) target5 = BitmapClip([["ABC", "EDC", "CDE"]], fps=1) assert clip5 == target5 clip6 = crop(clip, x_center=2, width=2, y1=1, y2=2) target6 = BitmapClip([["DC"]], fps=1) assert clip6 == target6
def test_loop(util, video): clip = BitmapClip([["R"], ["G"], ["B"]], fps=1) clip1 = loop(clip, n=2) # loop 2 times target1 = BitmapClip([["R"], ["G"], ["B"], ["R"], ["G"], ["B"]], fps=1) assert clip1 == target1 clip2 = loop(clip, duration=8) # loop 8 seconds target2 = BitmapClip( [["R"], ["G"], ["B"], ["R"], ["G"], ["B"], ["R"], ["G"]], fps=1) assert clip2 == target2 clip3 = loop(clip).with_duration(5) # infinite loop target3 = BitmapClip([["R"], ["G"], ["B"], ["R"], ["G"]], fps=1) assert clip3 == target3 clip = video(start_time=0.2, end_time=0.3) # 0.1 seconds long clip1 = loop(clip).with_duration(0.5) # infinite looping clip1.write_videofile(os.path.join(util.TMP_DIR, "loop1.webm")) clip2 = loop(clip, duration=0.5) # loop for 1 second clip2.write_videofile(os.path.join(util.TMP_DIR, "loop2.webm")) clip3 = loop(clip, n=3) # loop 3 times clip3.write_videofile(os.path.join(util.TMP_DIR, "loop3.webm")) # Test audio looping clip = AudioClip(lambda t: np.sin(440 * 2 * np.pi * t) * (t % 1) + 0.5, duration=2.5, fps=44100) clip1 = clip.loop(2)
def test_loop(): clip = BitmapClip([["R"], ["G"], ["B"]], fps=1) clip1 = loop(clip, n=2) # loop 2 times target1 = BitmapClip([["R"], ["G"], ["B"], ["R"], ["G"], ["B"]], fps=1) assert clip1 == target1 clip2 = loop(clip, duration=8) # loop 8 seconds target2 = BitmapClip( [["R"], ["G"], ["B"], ["R"], ["G"], ["B"], ["R"], ["G"]], fps=1) assert clip2 == target2 clip3 = loop(clip).with_duration(5) # infinite loop target3 = BitmapClip([["R"], ["G"], ["B"], ["R"], ["G"]], fps=1) assert clip3 == target3 clip = get_test_video().subclip(0.2, 0.3) # 0.1 seconds long clip1 = loop(clip).with_duration(0.5) # infinite looping clip1.write_videofile(os.path.join(TMP_DIR, "loop1.webm")) clip2 = loop(clip, duration=0.5) # loop for 1 second clip2.write_videofile(os.path.join(TMP_DIR, "loop2.webm")) clip3 = loop(clip, n=3) # loop 3 times clip3.write_videofile(os.path.join(TMP_DIR, "loop3.webm")) # Test audio looping clip = AudioClip(lambda t: np.sin(440 * 2 * np.pi * t) * (t % 1) + 0.5, duration=2.5, fps=44100) clip1 = clip.loop(2) # TODO fix AudioClip.__eq__() # assert concatenate_audioclips([clip, clip]) == clip1 close_all_clips(objects=locals())
def test_freeze(): clip = BitmapClip([["R"], ["G"], ["B"]], fps=1) # 3 separate frames clip1 = freeze(clip, t=1, freeze_duration=1) target1 = BitmapClip([["R"], ["G"], ["G"], ["B"]], fps=1) assert clip1 == target1 clip2 = freeze(clip, t="end", freeze_duration=1) target2 = BitmapClip([["R"], ["G"], ["B"], ["B"]], fps=1) assert clip2 == target2 clip3 = freeze(clip, t=1, total_duration=4) target3 = BitmapClip([["R"], ["G"], ["G"], ["B"]], fps=1) assert clip3 == target3 clip4 = freeze(clip, t="end", total_duration=4, padding_end=1) target4 = BitmapClip([["R"], ["G"], ["G"], ["B"]], fps=1) assert clip4 == target4
def test_margin(): clip = BitmapClip([["RRR", "RRR"], ["RRB", "RRB"]], fps=1) # Make sure that the default values leave clip unchanged clip1 = margin(clip) assert clip == clip1 # 1 pixel black margin clip2 = margin(clip, margin_size=1) target = BitmapClip( [["OOOOO", "ORRRO", "ORRRO", "OOOOO"], ["OOOOO", "ORRBO", "ORRBO", "OOOOO"]], fps=1, ) assert target == clip2 # 1 pixel green margin clip3 = margin(clip, margin_size=1, color=(0, 255, 0)) target = BitmapClip( [["GGGGG", "GRRRG", "GRRRG", "GGGGG"], ["GGGGG", "GRRBG", "GRRBG", "GGGGG"]], fps=1, ) assert target == clip3
def test_rotate_supported_PIL_kwargs( unsupported_kwargs, monkeypatch, ): """Test supported 'rotate' FX arguments by PIL version.""" rotate_module = importlib.import_module("moviepy.video.fx.rotate") # patch supported kwargs data by PIL version new_PIL_rotate_kwargs_supported, min_version_by_kwarg_name = ({}, {}) for kwarg, ( kw_name, supported, min_version, ) in rotate_module.PIL_rotate_kwargs_supported.items(): supported = kw_name not in unsupported_kwargs new_PIL_rotate_kwargs_supported[kwarg] = [ kw_name, supported, min_version ] min_version_by_kwarg_name[kw_name] = ".".join( str(n) for n in min_version) monkeypatch.setattr( rotate_module, "PIL_rotate_kwargs_supported", new_PIL_rotate_kwargs_supported, ) with pytest.warns(UserWarning) as record: BitmapClip([["R", "G", "B"]], fps=1).fx( rotate_module.rotate, 45, bg_color=(10, 10, 10), center=(1, 1), translate=(1, 0), ) # assert number of warnings assert len(record.list) == len(unsupported_kwargs) # assert messages contents messages = [] for warning in record.list: messages.append(warning.message.args[0]) for unsupported_kwarg in unsupported_kwargs: expected_message = ( f"rotate '{unsupported_kwarg}' argument is not supported by your" " Pillow version and is being ignored. Minimum Pillow version" f" required: v{min_version_by_kwarg_name[unsupported_kwarg]}") assert expected_message in messages
def test_rotate(angle_offset): # Run several times to ensure that adding 360 to rotation angles has no effect clip = BitmapClip([["AAAA", "BBBB", "CCCC"], ["ABCD", "BCDE", "CDEA"]], fps=1) clip1 = rotate(clip, 0 + angle_offset) target1 = BitmapClip([["AAAA", "BBBB", "CCCC"], ["ABCD", "BCDE", "CDEA"]], fps=1) assert clip1 == target1 clip2 = rotate(clip, 90 + angle_offset) target2 = BitmapClip( [["ABC", "ABC", "ABC", "ABC"], ["DEA", "CDE", "BCD", "ABC"]], fps=1 ) assert clip2 == target2, clip2.to_bitmap() clip3 = rotate(clip, 180 + angle_offset) target3 = BitmapClip([["CCCC", "BBBB", "AAAA"], ["AEDC", "EDCB", "DCBA"]], fps=1) assert clip3 == target3 clip4 = rotate(clip, 270 + angle_offset) target4 = BitmapClip( [["CBA", "CBA", "CBA", "CBA"], ["CBA", "DCB", "EDC", "AED"]], fps=1 ) assert clip4 == target4
def test_speedx(): clip = BitmapClip([["A"], ["B"], ["C"], ["D"]], fps=1) clip1 = speedx(clip, 0.5) # 1/2x speed target1 = BitmapClip( [["A"], ["A"], ["B"], ["B"], ["C"], ["C"], ["D"], ["D"]], fps=1 ) assert clip1 == target1 clip2 = speedx(clip, final_duration=8) # 1/2x speed target2 = BitmapClip( [["A"], ["A"], ["B"], ["B"], ["C"], ["C"], ["D"], ["D"]], fps=1 ) assert clip2 == target2 clip3 = speedx(clip, final_duration=12) # 1/2x speed target3 = BitmapClip( [ ["A"], ["A"], ["A"], ["B"], ["B"], ["B"], ["C"], ["C"], ["C"], ["D"], ["D"], ["D"], ], fps=1, ) assert clip3 == target3 clip4 = speedx(clip, 2) # 2x speed target4 = BitmapClip([["A"], ["C"]], fps=1) assert clip4 == target4 clip5 = speedx(clip, final_duration=2) # 2x speed target5 = BitmapClip([["A"], ["C"]], fps=1) assert clip5 == target5 clip6 = speedx(clip, 4) # 4x speed target6 = BitmapClip([["A"]], fps=1) assert ( clip6 == target6 ), f"{clip6.duration} {target6.duration} {clip6.fps} {target6.fps}"
def test_rotate( angle_offset, angle, unit, resample, translate, center, bg_color, expected_frames, ): """Check ``rotate`` FX behaviour against possible combinations of arguments.""" original_frames = [["AAAA", "BBBB", "CCCC"], ["ABCD", "BCDE", "CDEA"]] # angles are defined in degrees, so convert to radians testing ``unit="rad"`` if unit == "rad": if hasattr(angle, "__call__"): _angle = lambda t: math.radians(angle(0)) else: _angle = math.radians(angle) else: _angle = angle clip = BitmapClip(original_frames, fps=1) kwargs = { "unit": unit, "resample": resample, "translate": translate, "center": center, "bg_color": bg_color, } if resample not in ["bilinear", "nearest", "bicubic"]: with pytest.raises(ValueError) as exc: clip.rotate(_angle, **kwargs) assert ( "'resample' argument must be either 'bilinear', 'nearest' or 'bicubic'" ) == str(exc.value) return else: rotated_clip = clip.rotate(_angle, **kwargs) expected_clip = BitmapClip(expected_frames, fps=1) assert rotated_clip.to_bitmap() == expected_clip.to_bitmap()
def test_freeze(t, freeze_duration, total_duration, padding_end, output_frames): input_frames = ["R", "G", "B"] clip_duration = len(input_frames) # create BitmapClip with predefined set of colors, during 1 second each one clip = BitmapClip([list(color) for color in input_frames], fps=1).with_duration( clip_duration ) # build kwargs passed to `freeze` possible_kwargs = { "t": t, "freeze_duration": freeze_duration, "total_duration": total_duration, "padding_end": padding_end, } kwargs = { kw_name: kw_value for kw_name, kw_value in possible_kwargs.items() if kw_value is not None } # freeze clip if hasattr(output_frames, "__traceback__"): with pytest.raises(output_frames): freeze(clip, **kwargs) return else: freezed_clip = freeze(clip, **kwargs) # assert new duration expected_freeze_duration = ( freeze_duration if freeze_duration is not None else total_duration - clip_duration ) assert freezed_clip.duration == clip_duration + expected_freeze_duration # assert colors are the expected for i, color in enumerate(freezed_clip.iter_frames()): expected_color = list(BitmapClip.DEFAULT_COLOR_DICT[output_frames[i]]) assert list(color[0][0]) == expected_color
def test_even_size(): clip1 = BitmapClip([["ABC", "BCD"]], fps=1) # Width odd clip1even = even_size(clip1) target1 = BitmapClip([["AB", "BC"]], fps=1) assert clip1even == target1 clip2 = BitmapClip([["AB", "BC", "CD"]], fps=1) # Height odd clip2even = even_size(clip2) target2 = BitmapClip([["AB", "BC"]], fps=1) assert clip2even == target2 clip3 = BitmapClip([["ABC", "BCD", "CDE"]], fps=1) # Width and height odd clip3even = even_size(clip3) target3 = BitmapClip([["AB", "BC"]], fps=1) assert clip3even == target3
def test_rotate( PIL_installed, angle_offset, angle, unit, resample, translate, center, bg_color, expected_frames, monkeypatch, ): """Check ``rotate`` FX behaviour against possible combinations of arguments.""" original_frames = [["AAAA", "BBBB", "CCCC"], ["ABCD", "BCDE", "CDEA"]] # angles are defined in degrees, so convert to radians testing ``unit="rad"`` if unit == "rad": if hasattr(angle, "__call__"): _angle = lambda t: math.radians(angle(0)) else: _angle = math.radians(angle) else: _angle = angle clip = BitmapClip(original_frames, fps=1) kwargs = { "unit": unit, "resample": resample, "translate": translate, "center": center, "bg_color": bg_color, } if resample not in ["bilinear", "nearest", "bicubic"]: with pytest.raises(ValueError) as exc: clip.rotate(_angle, **kwargs) assert ( "'resample' argument must be either 'bilinear', 'nearest' or 'bicubic'" ) == str(exc.value) return # if the scenario implies that PIL is not installed, monkeypatch the # module in which 'rotate' function resides if not PIL_installed: rotate_module = importlib.import_module("moviepy.video.fx.rotate") monkeypatch.setattr(rotate_module, "Image", None) rotate_func = rotate_module.rotate else: rotate_func = rotate # resolve the angle, because if it is a multiple of 90, the rotation # can be computed event without an available PIL installation if hasattr(_angle, "__call__"): _resolved_angle = _angle(0) else: _resolved_angle = _angle if unit == "rad": _resolved_angle = math.degrees(_resolved_angle) if not PIL_installed and ((_resolved_angle % 90 != 0) or center or translate or bg_color): with pytest.raises(ValueError) as exc: rotated_clip = clip.fx(rotate_func, _angle, **kwargs) assert ( 'Without "Pillow" installed, only angles that are a multiple of 90' ) in str(exc.value) else: rotated_clip = clip.fx(rotate_func, _angle, **kwargs) expected_clip = BitmapClip(expected_frames, fps=1) assert rotated_clip.to_bitmap() == expected_clip.to_bitmap()
def test_mirror_y(): clip = BitmapClip([["AB", "CD"]], fps=1) clip1 = mirror_y(clip) target = BitmapClip([["CD", "AB"]], fps=1) assert clip1 == target
def test_mirror_x(): clip = BitmapClip([["AB", "CD"]], fps=1) clip1 = mirror_x(clip) target = BitmapClip([["BA", "DC"]], fps=1) assert clip1 == target
def test_blackwhite(): # Create black/white spectrum ``bw_color_dict`` to compare against it. # Colors after ``blackwhite`` FX must be inside this dictionary # Note: black/white spectrum is made of colors with same numbers # [(0, 0, 0), (1, 1, 1), (2, 2, 2)...] bw_color_dict = {} for num in range(0, 256): bw_color_dict[chr(num + 255)] = (num, num, num) color_dict = bw_color_dict.copy() # update dictionary with default BitmapClip color_dict values color_dict.update(BitmapClip.DEFAULT_COLOR_DICT) # add row with random colors in b/w spectrum random_row = "" for num in range(512, 515): # use unique unicode representation for each color char = chr(num) random_row += char # random colors in the b/w spectrum color_dict[char] = tuple(random.randint(0, 255) for i in range(3)) # clip converted below to black/white clip = BitmapClip([["RGB", random_row]], color_dict=color_dict, fps=1) # for each possible ``preserve_luminosity`` boolean argument value for preserve_luminosity in [True, False]: # default argument (``RGB=None``) clip_bw = blackwhite(clip, preserve_luminosity=preserve_luminosity) bitmap = clip_bw.to_bitmap() assert bitmap for i, row in enumerate(bitmap[0]): for char in row: # all characters returned by ``to_bitmap`` are in the b/w spectrum assert char in bw_color_dict if i == 0: # pure "RGB" colors are converted to [85, 85, 85] assert char == row[0] # so are equal # custom random ``RGB`` argument clip_bw_custom_rgb = blackwhite( clip, RGB=(random.randint(0, 255), 0, 0), preserve_luminosity=preserve_luminosity, ) bitmap = clip_bw_custom_rgb.to_bitmap() for i, row in enumerate(bitmap[0]): for i2, char in enumerate(row): # all characters returned by ``to_bitmap`` are in the b/w spectrum assert char in bw_color_dict # for clip "RGB" row, two latest converted colors are equal if i == 0 and i2 > 0: assert char == row[1] and char == row[2] # ``RGB="CRT_phosphor"`` argument clip_bw_crt_phosphor = blackwhite( clip, RGB="CRT_phosphor", preserve_luminosity=preserve_luminosity) bitmap = clip_bw_crt_phosphor.to_bitmap() assert bitmap for row in bitmap[0]: for char in row: # all characters returned by ``to_bitmap`` are in the b/w spectrum assert char in bw_color_dict