Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- from datetime import datetime, timedelta
- import time
- import subprocess
- from PIL import Image, ImageDraw, ImageFont
- import numpy as np
- from math import radians, floor, ceil
- from easing_functions import CubicEaseInOut
- from moviepy.editor import ImageSequenceClip, VideoClip
- def pol2cart(r, phi):
- x = r * np.cos(phi)
- y = r * np.sin(phi)
- return(x, y)
- def maprange(a, b, s):
- (a1, a2), (b1, b2) = a, b
- return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
- def calc_ellipse_coords(r, a, width):
- width = width - 2
- x1, y1 = pol2cart(r - 2, radians(a - 90)) # r - 2
- x2, y2 = pol2cart(r - width, radians(a - 90))
- ax, ay = (r + x2 + (x1 - x2) / 2), (r + y2 + (y1 - y2) / 2)
- left_corner = (ax - width / 2, ay - width / 2)
- right_corner = (ax + width / 2, ay + width / 2)
- return left_corner, right_corner
- def draw_fade_in_frames(background, starting_from, n_frames):
- # 0.5 second of fade in animation -----------------------
- for f in range(starting_from, n_frames):
- img = background.copy()
- draw = ImageDraw.Draw(img, mode='RGBA')
- # draw numbers
- draw.text((x, y), f"{00:02}:{00:02}", fill=red, font=font)
- # draw dot
- color = (255, 0, 0, ceil(maprange([0, n_frames], [0, 255], f)))
- draw.ellipse((dims[0]/2 - width / 2 + 1, 0, dims[0]/2 + width / 2 - 1, width - 1),
- fill=color, outline=None, width=0)
- if antialiasing:
- img = img.resize(
- (dims[0] // multiplier, dims[1] // multiplier),
- antialiasing
- )
- img.save(f'img/{f}.jpg')
- def draw_in_anim_frames(background, starting_from, n_frames):
- # 3 seconds of `in` animation -----------------------
- in_frames = n_frames
- # ease numbers animation
- m = CubicEaseInOut(0, mins, in_frames)
- h = CubicEaseInOut(0, hours, in_frames)
- total_m = CubicEaseInOut(0, hours % 12 * 60 + mins, in_frames)
- for f in range(in_frames):
- img = background.copy()
- draw = ImageDraw.Draw(img)
- # draw numbers
- text = f"{round(h.ease(f)):02}:{round(m.ease(f)):02}"
- draw.text((x, y), text, fill=red, font=font)
- # draw curves
- # === hour curve
- h_offset = maprange([0, 1440/2], [0, 360], total_m.ease(f))
- h_curve_box = (0, 0, dims[0], dims[1])
- draw.arc(h_curve_box, start=-90, end=-90 +
- h_offset, fill=red, width=width)
- # === === dot stuff
- r = (h_curve_box[3] - h_curve_box[0]) / 2
- left_corner, right_corner = calc_ellipse_coords(r, h_offset, width)
- draw.ellipse((*left_corner, *right_corner),
- fill=red, outline=None, width=0)
- draw.ellipse((dims[0]/2 - width / 2 + 1, 0, dims[0]/2 + width / 2 - 1, width - 1),
- fill=red, outline=None, width=0)
- # === minute curve
- m_offset = maprange([0, 60], [0, 360], m.ease(f))
- m_curve_box = (width + spacing, width + spacing,
- dims[0] - width - spacing, dims[1] - width - spacing)
- draw.arc(m_curve_box, start=-90, end=-90 +
- m_offset, fill=red, width=int(width/2))
- if antialiasing:
- img = img.resize(
- (dims[0] // multiplier, dims[1] // multiplier),
- antialiasing
- )
- img.save(f'img/{starting_from + f}.jpg')
- def draw_still_frames(background, starting_from, n_frames):
- # 2 seconds of still image --------------------------
- still_frames = n_frames
- img = background.copy()
- draw = ImageDraw.Draw(img)
- # draw numbers
- draw.text((x, y), f"{hours:02}:{mins:02}", fill=red, font=font)
- # draw curves
- # === hour curve
- h_offset = maprange([0, 1440/2], [0, 360], hours % 12*60+mins)
- h_curve_box = (0, 0, dims[0], dims[1])
- draw.arc(h_curve_box, start=-90, end=-90 +
- h_offset, fill=red, width=width)
- # === === dot stuff
- r = (h_curve_box[3] - h_curve_box[0])/2
- left_corner, right_corner = calc_ellipse_coords(r, h_offset, width)
- draw.ellipse((*left_corner, *right_corner),
- fill=red, outline=None, width=0)
- draw.ellipse((dims[0]/2 - width / 2 + 1, 0, dims[0]/2 + width / 2 - 1, width - 1),
- fill=red, outline=None, width=0)
- # === minute curve
- m_offset = maprange([0, 60], [0, 360], mins)
- m_curve_box = (width + spacing, width + spacing,
- dims[0] - width - spacing, dims[1] - width - spacing)
- draw.arc(m_curve_box, start=-90, end=-90 +
- m_offset, fill=red, width=int(width/2))
- # save n_frames copies (this part of animation is a stop frame, not actually an animation)
- for i in range(still_frames):
- if antialiasing:
- img = img.resize(
- (dims[0] // multiplier, dims[1] // multiplier),
- antialiasing
- )
- img.save(f'img/{starting_from + i}.jpg')
- def draw_out_anim_frames(background, starting_from, n_frames):
- # 1 second of `out` animation -----------------------
- out_frames = n_frames
- m = CubicEaseInOut(mins, 60, out_frames)
- h = CubicEaseInOut(hours, 24, out_frames)
- total_m = CubicEaseInOut(hours % 12 * 60 + mins, 12*60, out_frames)
- for f in range(out_frames):
- img = background.copy()
- draw = ImageDraw.Draw(img)
- # draw numbers
- a = round(h.ease(f))
- b = round(m.ease(f))
- text = f"{a if a!=24 else 00:02}:{b if b!=60 else 00:02}"
- draw.text((x, y), text, fill=red, font=font)
- # draw curves
- # hour curve
- h_offset = maprange([0, 1440/2], [0, 360], total_m.ease(f))
- h_curve_box = (0, 0, dims[0], dims[1])
- draw.arc(h_curve_box, start=-90, end=-90 +
- h_offset, fill=red, width=width)
- # dot stuff
- r = (h_curve_box[3] - h_curve_box[0])/2
- left_corner, right_corner = calc_ellipse_coords(r, h_offset, width)
- draw.ellipse((*left_corner, *right_corner),
- fill=red, outline=None, width=0)
- draw.ellipse((dims[0]/2 - width / 2 + 1, 0, dims[0]/2 + width / 2 - 1, width - 1),
- fill=red, outline=None, width=0)
- # minute curve
- m_offset = maprange([0, 60], [0, 360], m.ease(f))
- m_curve_box = (width + spacing, width + spacing,
- dims[0] - width - spacing, dims[1] - width - spacing)
- draw.arc(m_curve_box, start=-90, end=-90 +
- m_offset, fill=red, width=int(width / 2))
- if antialiasing:
- img = img.resize(
- (dims[0] // multiplier, dims[1] // multiplier),
- antialiasing
- )
- img.save(f'img/{starting_from + f}.jpg')
- def draw_fade_out_frames(background, starting_from, n_frames):
- # 0.5 second of fade out animation -----------------------
- fade_out_frames = n_frames
- for f in range(fade_out_frames):
- img = background.copy()
- draw = ImageDraw.Draw(img, mode='RGBA')
- # draw numbers
- draw.text((x, y), f"{00:02}:{00:02}", fill=red, font=font)
- # draw curves
- # hour curve
- color = (255, 0, 0, round(
- maprange([0, fade_out_frames], [255, 0], f)))
- draw.ellipse((0, 0, dims[0], dims[1]),
- fill=None, outline=color, width=width)
- # minute curve
- draw.ellipse((width+spacing, width+spacing, dims[0] - (width+spacing), dims[1] - (width+spacing)),
- fill=None, outline=color, width=width//2)
- if antialiasing:
- img = img.resize(
- (dims[0] // multiplier, dims[1] // multiplier),
- antialiasing
- )
- img.save(f'img/{starting_from + f}.jpg')
- def make_overlay(dt_obj, antialiasing=True):
- # img settings
- # if antialiasing option is True, scale image by multiplier size with ANTIALIAS flag,
- # draw stuff, then scale image down by multiplier with the same ANTIALIAS flag
- if antialiasing:
- multiplier = 2
- else:
- multiplier = 1
- # background image dimentions shoud be equal e.g. square image
- dims = (800 * multiplier, 800 * multiplier)
- red = (255, 0, 0, 255)
- hours = dt_obj.hour
- mins = dt_obj.minute
- # duration settings
- # duration = 7 seconds
- d0, d1, d2, d3, d4 = 0.5, 2, 2, 2, 0.5
- fps = 30
- fade_in_frames = round(fps * d0)
- in_frames = fps * d1
- still_frames = fps * d2
- out_frames = fps * d3
- fade_out_frames = round(fps * d4)
- # text settings
- font = ImageFont.truetype('dig_mono.ttf', size=170 * multiplier)
- x, y = 210 * multiplier, 240 * multiplier
- # curve settings
- width = 16 * multiplier
- spacing = 6 * multiplier
- with (Image.open('t1000.jpg')).resize(dims, antialiasing) as background:
- draw_fade_in_frames(background, 0, fade_in_frames)
- draw_in_anim_frames(background, fade_in_frames, in_frames)
- frame_offset = fade_in_frames
- draw_still_frames(background, frame_offset + in_frames, still_frames)
- frame_offset = fade_in_frames + in_frames
- draw_out_anim_frames(background, frame_offset +
- still_frames, out_frames)
- frame_offset = fade_in_frames + in_frames + still_frames
- draw_fade_out_frames(background, frame_offset +
- out_frames, fade_out_frames)
- def create_video(dt):
- # Duration: 0.5s + 2s + 2s + 2s + 0.5
- filename = f"vid/{dt.hour:02}_{dt.minute:02}.mp4"
- if os.path.isfile(filename):
- return filename
- make_overlay(dt, True)
- ffmpeg = "/home/pi/FFmpeg/ffmpeg"
- cmd = [ffmpeg, '-framerate', '30', '-i', 'img/%d.jpg', '-c:v',
- 'libx264', '-pix_fmt', 'yuv420p', '-threads', '4', '-b:v', '5120k', f'{filename}']
- subprocess.call(cmd)
- os.system('rm img/*')
- return filename
- def render_all_videos():
- for h in range(24):
- for m in range(60):
- dt = datetime(2020, 1, 1, h, m, 1)
- create_video(dt)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement