使用PIL制作简单动画,哎

代码

from moviepy.editor import *
import os
import math
import numpy as np
from enum import Enum
from PIL import Image, ImageDraw, ImageFont, ImageColor


class BackgroundGradient(Enum):
    skyline = ['#1488CC', '#2B32B2']
    cool_brown = ['#603813', '#b29f94']
    rose_water = ['#E55D87', '#5FC3E4']
    crystal_clear = ['#159957', '#155799']
    midnight_city = ['#232526', '#414345']
    deep_space = ['#000000', '#434343']


joint = None


def _display_gradient_bg(base_img: Image, bg_gradient: BackgroundGradient, type=0):
    img_w, img_h = base_img.size
    draw = ImageDraw.Draw(base_img)
    start_color, end_color = bg_gradient.value
    if '#' in start_color:
        start_color = ImageColor.getrgb(start_color)
    if '#' in end_color:
        end_color = ImageColor.getrgb(end_color)

    len = None
    if type == 0:  # 水平方向渐变,渐变步长
        len = img_w
    elif type == 1:  # v
        len = img_h

    # 水平方向渐变,渐变步长
    step_r = (end_color[0] - start_color[0]) / len
    step_g = (end_color[1] - start_color[1]) / len
    step_b = (end_color[2] - start_color[2]) / len

    for i in range(0, len):
        bg_r = round(start_color[0] + step_r * i)
        bg_g = round(start_color[1] + step_g * i)
        bg_b = round(start_color[2] + step_b * i)
        if type == 0:
            draw.line([(i, 0), (i, img_h)], fill=(bg_r, bg_g, bg_b))
        elif type == 1:
            draw.line([(0, i), (img_w, i)], fill=(bg_r, bg_g, bg_b))

    start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[1])
    shape_color_1 = (start_color[0], start_color[1], start_color[2], 20)
    fnt = ImageFont.truetype("/Users/admin/PycharmProjects/video_process/videos/ttf/明兰.ttf", 50)
    draw.multiline_text((int(img_w * 0.05), int(img_h * 0.05)), "三角 ▶", font=fnt, fill=shape_color_1)


def draw_one_circle(the_draw: ImageDraw, bounding_circle, shape_color, width):
    the_draw.ellipse(bounding_circle, outline=shape_color, width=width)


def draw_one_arc(the_draw: ImageDraw, xy, start, end, fill, width):
    the_draw.arc(xy, start, end, fill, width)


def draw_one_regular_pro(the_draw: ImageDraw, bounding_circle, n_sides, rotation=0, fill=None, outline=None, width=1):
    the_draw.regular_polygon(bounding_circle, n_sides, rotation=rotation, fill=fill, outline=outline, width=width)


def draw_one_line(the_draw: ImageDraw, xy, fill=None, width=1, joint=None):
    the_draw.line(xy, fill=fill, width=width, joint=joint)


def _add_rotate(base_img: Image, t, duration):
    img_w, img_h = base_img.size
    draw = ImageDraw.Draw(base_img)
    min_w_h = min(img_w, img_h)
    radis = int(min_w_h * 0.3)
    center = (img_w // 2, img_h // 2)
    bounding_circle = (center, radis)
    start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[0])
    shape_color_1 = (start_color[0], start_color[1], start_color[2], 120)

    start_color = ImageColor.getrgb(BackgroundGradient.cool_brown.value[0])
    fill = (start_color[0], start_color[1], start_color[2], 120)
    end_arge = 120
    rotation = int(end_arge / duration * t) if t < duration else end_arge
    draw_one_regular_pro(draw, bounding_circle, n_sides=3, rotation=rotation, fill=fill, outline=shape_color_1, width=5)


def _add_regular_polygon(base_img: Image, t, duration):
    img_w, img_h = base_img.size
    draw = ImageDraw.Draw(base_img)
    min_w_h = min(img_w, img_h)
    radis = int(min_w_h * 0.3)
    center = (img_w // 2, img_h // 2)
    bounding_circle = (center, radis)
    start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[0])
    shape_color_1 = (start_color[0], start_color[1], start_color[2], 120)

    start_color = ImageColor.getrgb(BackgroundGradient.cool_brown.value[0])
    cur = int(120 / duration * t)
    fill = (start_color[0], start_color[1], start_color[2], cur)
    draw_one_regular_pro(draw, bounding_circle, n_sides=3, rotation=0, fill=fill, outline=shape_color_1, width=5)


def _add_line(base_img: Image, t, duration):
    img_w, img_h = base_img.size
    draw = ImageDraw.Draw(base_img)
    center = (img_w // 2, img_h // 2)
    start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[0])
    shape_color_1 = (start_color[0], start_color[1], start_color[2], 120)
    min_w_h = min(img_w, img_h)
    radis = int(min_w_h * 0.3)
    theta = 30 * math.pi / 180
    sin_theta = math.sin(theta)
    cos_theta = math.cos(theta)
    point_1 = (center[0], center[1] - radis)
    point_2 = (center[0] - int(cos_theta * radis), center[1] + int(sin_theta * radis))
    point_3 = (center[0] + int(cos_theta * radis), center[1] + int(sin_theta * radis))
    w = point_1[0] - point_2[0]
    h = - (point_1[1] - point_2[1])
    tan_theta = math.tan(60 * math.pi / 180)
    dw = (w / duration)
    cur_dw = int(dw * t)
    cur_w = point_1[0] - cur_dw
    dh = int(cur_dw * tan_theta)
    cur_h = point_1[1] + dh
    draw_one_line(draw, [point_1, (cur_w, cur_h)], shape_color_1, 5, joint)

    draw_one_line(draw, [point_3, (point_3[0] - cur_dw, point_3[1] - dh)], shape_color_1, 5, joint)

    w = point_3[0] - point_2[0]
    dw = w / duration
    cur_dw = dw * t
    cur_w = point_2[0] + int(cur_dw)
    draw_one_line(draw, [point_2, (cur_w, point_3[1])], shape_color_1, 5, joint)


def _add_circle2(base_img: Image, t, duration):
    img_w, img_h = base_img.size
    draw = ImageDraw.Draw(base_img)
    dt = 20 / duration
    cur = int(dt * t)
    start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[1])
    shape_color_1 = (start_color[0], start_color[1], start_color[2], cur)
    min_w_h = min(img_w, img_h)
    first = int(min_w_h * 0.1)
    offset = 100
    first = int(1.5 * first)
    center_three = (0 + offset + first, img_h - offset - first)
    coords_three = [(center_three[0] - first, center_three[1] - first),
                    (center_three[0] + first, center_three[1] + first)]

    draw_one_circle(draw, coords_three, shape_color_1, 5)


def _add_circle(base_img: Image, t, duration):
    img_w, img_h = base_img.size
    draw = ImageDraw.Draw(base_img)
    dt = 20 / duration
    cur = int(dt * t)
    start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[0])
    shape_color_1 = (start_color[0], start_color[1], start_color[2], cur)
    min_w_h = min(img_w, img_h)
    first = int(min_w_h * 0.1)
    offset = 40
    center_first = (0 + offset + first, img_h - offset - first)
    coords_first = [(center_first[0] - first, center_first[1] - first),
                    (center_first[0] + first, center_first[1] + first)]
    draw_one_circle(draw, coords_first, shape_color_1, 5)


def _add_upper(base_img: Image, t):
    img_w, img_h = base_img.size
    draw = ImageDraw.Draw(base_img)
    dt = 20 / 0.5
    cur = int(dt * t)
    start_color = ImageColor.getrgb(BackgroundGradient.skyline.value[0])
    shape_color_1 = (start_color[0], start_color[1], start_color[2], cur)
    min_w_h = min(img_w, img_h)
    center_second = (img_w, 0)
    radius_second = int(min_w_h * 0.3)
    coords_second = [(center_second[0] - radius_second, center_second[1] - radius_second),
                     (center_second[0] + radius_second, center_second[1] + radius_second)]
    draw_one_arc(draw, coords_second, 90, 180, shape_color_1, 5)


def _add_cover(base_img: Image):
    img_w, img_h = base_img.size
    draw = ImageDraw.Draw(base_img)
    shape_color_1 = (255, 255, 255, 120)
    shape_color_2 = (255, 255, 255, 60)
    shape_color_3 = (255, 255, 255, 40)

    min_w_h = min(img_w, img_h)

    first = int(min_w_h * 0.05)
    offset = 30
    center_first = (0 + offset + first, img_h - offset - first)
    coords_first = [(center_first[0] - first, center_first[1] - first),
                    (center_first[0] + first, center_first[1] + first)]

    center_second = (img_w, 0)
    radius_second = int(min_w_h * 0.3)
    coords_second = [(center_second[0] - radius_second, center_second[1] - radius_second),
                     (center_second[0] + radius_second, center_second[1] + radius_second)]

    offset = 50
    first = int(1.5 * first)
    center_three = (0 + offset + first, img_h - offset - first)
    coords_three = [(center_three[0] - first, center_three[1] - first),
                    (center_three[0] + first, center_three[1] + first)]

    draw_one_circle(draw, coords_first, shape_color_2, 3)
    draw_one_arc(draw, coords_second, 90, 180, shape_color_3, 5)
    draw_one_circle(draw, coords_three, shape_color_1, 4)

    radis = int(min_w_h * 0.3)
    center = (img_w // 2, img_h // 2)
    bounding_circle = (center, radis)
    draw_one_regular_pro(draw, bounding_circle, n_sides=3, rotation=0, fill=shape_color_3, outline=None, width=5)

    theta = 30 * math.pi / 180
    sin_theta = math.sin(theta)
    cos_theta = math.cos(theta)
    point_1 = (center[0], center[1] - radis)
    point_2 = (center[0] - int(cos_theta * radis), center[1] + int(sin_theta * radis))
    point_3 = (center[0] + int(cos_theta * radis), center[1] + int(sin_theta * radis))
    draw_one_line(draw, [point_1, point_2, point_3, point_1], shape_color_2, 5, "curve")


all_duration = 6.0


class My_Basic():
    def __init__(self):
        gb_w = 1080
        gb_h = 1440
        img_bg = Image.new("RGBA", (gb_w, gb_h))
        _display_gradient_bg(img_bg, BackgroundGradient.deep_space, type=1)
        self.img_bg = img_bg

    def get_frame(self, img=None):
        if img is not None:
            temp = Image.alpha_composite(self.img_bg, img).convert("RGB")
            return np.array(temp)
        temp = self.img_bg.convert("RGB")
        return np.array(temp)

    def copy_bg(self):
        return self.img_bg.copy()

    def update(self, img):
        self.img_bg = Image.alpha_composite(self.img_bg, img)


my_basic = My_Basic()


def make_frame(t):
    if t == 0:
        return my_basic.get_frame()
    if t <= 0.5:
        img_copy = my_basic.copy_bg()
        _add_upper(img_copy, t)
        my_basic.update(img_copy)
        return my_basic.get_frame()
    if t <= 1:
        img_copy = my_basic.copy_bg()
        _add_circle(img_copy, t - 0.5, 0.5)
        my_basic.update(img_copy)
        return my_basic.get_frame()
    if t <= 1.5:
        img_copy = my_basic.copy_bg()
        _add_circle2(img_copy, t - 1.0, 1.0)
        my_basic.update(img_copy)
        return my_basic.get_frame()

    if t <= 2.5:
        img_copy = my_basic.copy_bg()
        _add_line(img_copy, t - 1.5, 1)
        return my_basic.get_frame(img_copy)
    if t <= 3.5:
        img_copy = my_basic.copy_bg()
        _add_regular_polygon(img_copy, t - 2.5, 1)
        return my_basic.get_frame(img_copy)
    if t <= all_duration:
        img_copy = my_basic.copy_bg()
        _add_rotate(img_copy, t - 3.5, 1)
        return my_basic.get_frame(img_copy)
    return my_basic.get_frame()


vc = VideoClip(make_frame=make_frame, duration=all_duration)
source = '/Users/admin/刘德华-忘情水.mp3'
audio = AudioFileClip(source)
audio = audio.subclip(8 - vc.duration, 8)
audio =audio.fx(afx.audio_fadeout, 0.4)
vc = vc.set_audio(audio)
res_file = "{}.mp4".format(os.path.basename(__file__))
vc.write_videofile(res_file, audio_codec="aac", codec="libx264", threads=1, fps=30, verbose=False,
                   logger=None)

结果

movie.py

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值