from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import os, shutil, sys , fnmatch
import subprocess
import re
root = Tk()
root.geometry("800x450")
root.title('Tk Mirror images and make VP9 webm video from sequence')
def cancella(a):
global imgdir
global prgdir
global workdir
if a == "all":
MsgBox = messagebox.askquestion ('WARNING','Are you sure you want to clear all images files (render too)?',icon = 'warning')
# cancella tutta la images/*.jpg
if MsgBox == 'yes':
os.chdir(imgdir)
exe = "del " + imgpre.get() + "*.jpg"
p = subprocess.run (exe, shell=True)
print(p)
exe = "del " + imgpre.get() + "*.png"
p = subprocess.run (exe, shell=True)
print(p)
os.chdir(workdir)
p = subprocess.run ("del _tmp*", shell=True)
print(p)
os.chdir(prgdir)
if a == "tmp":
os.chdir(workdir)
p = subprocess.run ("del _tmp*", shell=True)
print(p)
os.chdir(prgdir)
def natural_sort(l):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
return sorted(l, key = alphanum_key)
def esegui():
global imgdir
global prgdir
global out_put
po = fps_out.get()
pc = crf.get()
pf = method.get()
mir = mirror.get()
ints = startf.get()
pref= imgpre.get()
pts_val = ptsval.get()
dnz_set = dnz.get()
suff = suffix.get()
out_put = video_o.get()
#repeat
repeat_= imrepeat.get()
repfirst_ = repfirst.get()
replast_ = replast.get()
#convert speed in setpts
pts_val = float(pts_val)
pts_val = (1 / pts_val)
pts_val = str(pts_val)[0:6]
if suff == "0":
tipo = ".jpg"
if suff == "1":
tipo = ".png"
img_or = []
print (prgdir)
#check out
ok = True
if os.path.isfile(out_put +".webm"):
ok = sovrascrivi(ok)
if ok == False:
print ("---------------------")
print ("aborted")
print ("---------------------")
return
# pulisci prima le _tmp*.
cancella("tmp")
os.chdir(imgdir)
a = os.getcwd()
print (a)
# for root, dirs, files in os.walk("."):
# for filename in files:
# print(filename)
# img_or.append(filename)
# nuovo con pattern e ordine naturale
img_raw = []
pattern = pref + "*" + tipo
listOfFiles = os.listdir('.')
for entry in listOfFiles:
if fnmatch.fnmatch(entry, pattern):
img_raw.append (entry)
img_or = natural_sort(img_raw)
print ("lista orig:");
print (img_or)
quanti = len(img_or)
aggiunti = 0
print ()
print (quanti)
print ()
work = dir_work.get()
#giro normali
if mir != "2":
#global copia
copia = 0
for i in range (0,(quanti)):
#print ("a" , copia, i)
#print(img_or[i])
newname = work + "/_tmp{:03d}".format(copia) + tipo
print (newname)
shutil.copy2(img_or[i], newname)
copia = copia +1
#print (copia)
if repeat_ == "1" and i == 0:
c = int(repfirst_)
print ("repeat first:", c)
for i2 in range (1,(c+1)):
newname = work + "/_tmp{:03d}".format(copia) + tipo
print (newname)
shutil.copy2(img_or[i], newname)
copia = copia+1
aggiunti = quanti + c
print ("add", aggiunti)
if repeat_ == "1" and i == (quanti-1):
c = int(replast_)
print ("repeat last:", c)
for i2 in range (1,(c+1)):
newname = work + "/_tmp{:03d}".format(copia) + tipo
print (newname)
shutil.copy2(img_or[i], newname)
copia = copia+1
#print ("-", copia)
aggiunti = aggiunti + c
print ("add", aggiunti)
#print(img_or[i] + " -> " + newname);
#print()
print ("Default")
print()
if mir == "1":
# reverse
if aggiunti == 0:
nn = quanti
else:
nn = aggiunti
for i in range ((quanti -2),0,-1):
#print(img_or[i])
newname = work + "/_tmp" + "{:03d}".format(nn) + tipo
#print (newname)
shutil.copy2(img_or[i], newname)
print(img_or[i] + " -> " + newname);
nn += 1
print ("Mirrorer")
if mir == "2":
# reverse
nn = 0
for i in range ((quanti-1),-1,-1):
newname = work + "/_tmp" + "{:03d}".format(nn) + tipo
shutil.copy2(img_or[i], newname)
print(img_or[i] + " -> " + newname);
nn += 1
print ("Reversed only")
print()
#>>> "The sum of 1 + 2 is {:03d}".format(1+2)
#'The sum of 1 + 2 is 003'
# image
os.chdir(prgdir)
a = os.getcwd()
print (a)
print()
outpuf = "\"" + out_put + ".webm" + "\""
inputf = "\"" + dir_work.get() + "/_tmp%03d" + tipo + "\""
exe = "ffmpeg.exe -hide_banner -y -i " + inputf + " -c:v libvpx-vp9 -crf "
exe = exe + pc + " "
exe = exe + "-vf "
if dnz_set == "1":
exe = exe + "hqdn3d,"
exepts = "setpts=" + pts_val + "*PTS,"
if pf == "1":
exe2 = exepts + "framerate=fps=" + po + ":scene=30:interp_start=" + ints + " "
else:
exe2 = exepts + "fps=fps=" + po + " "
exe = exe + exe2 + "-quality good -rc_lookahead 16 -speed 3 "
exe = exe + "-vprofile 0 -qmax 51 -qmin 4 -slices 4 -tile-columns 6 -frame-parallel 1 "
exe = exe + "-auto-alt-ref 1 -lag-in-frames 25 -row-mt 1 -g 120 -bf 2 -pix_fmt yuv420p "
exe = exe + "-r " + po + " " + outpuf
p = subprocess.run (exe, shell=True)
print()
print(p)
print()
exe = "ffplay -hide_banner " + outpuf + " -loop 0"
p = subprocess.run (exe, shell=True)
print ("Done")
print("-------------------------------------------")
def sovrascrivi(x):
global out_put
MsgBox = messagebox.askquestion ('WARNING', 'file ' + out_put + '.webm exist, overwrite?',icon = 'warning')
if MsgBox == 'yes':
return (x)
if MsgBox == 'no':
x = False
return (x)
def chg_img_dir():
global imgdir
folder_selected = filedialog.askdirectory()
imgdir = folder_selected
dir_img.set(folder_selected)
def opendir():
global prgdir
os.startfile(prgdir)
fps_out = StringVar(root, value='25')
crf = StringVar(root, value='21')
method = StringVar(root, value='1')
startf = StringVar(root, value='180')
mirror = StringVar(root, value='1')
imgpre = StringVar(root, value="z")
ptsval = StringVar(root, value="1.00")
dnz = StringVar(root, value="0")
suffix =StringVar(root, value="0" )
video_o = StringVar(root, value="out" )
imrepeat = StringVar(root, value="0" )
repfirst = StringVar(root, value="1" )
replast = StringVar(root, value="1" )
prgdir = os.getcwd()
# cartelle basiche
if not os.path.isdir('images'):
os.mkdir('images')
os.chdir('images')
imgdir = os.getcwd()
os.chdir(prgdir)
if not os.path.isdir('images/work'):
os.mkdir('images/work')
os.chdir('images/work')
workdir = os.getcwd()
os.chdir(prgdir)
dir_img = StringVar(root, value = imgdir)
dir_work = StringVar(root, value = workdir)
frametop = Frame(root)
l8 = Button ( frametop , text= "Images dir: ", command = chg_img_dir, padx= 2 )
l8.grid(row = 0, column = 1 , sticky = W, pady = 2, rowspan = 1, columnspan=1 )
l8b = Label( frametop, textvariable = dir_img, padx = 2 , fg = "#873926")
l8b.grid(row = 0, column = 3 , sticky = W, pady = 2, rowspan = 1, columnspan=4 )
l9 = Label( frametop, text= 'Images base prefix:', padx = 2)
l9.grid(row = 1, column = 1 , sticky = W, pady = 2, rowspan = 1 )
e9 = Entry(frametop, textvariable = imgpre, width=8)
e9.grid(row = 1, column = 4 , sticky = W, pady = 2)
r9a = Radiobutton(frametop, text = "JPG", variable = suffix, value = "0")
r9a.grid(row = 1, column = 5 , sticky = W, pady = 2, rowspan = 1 )
r9b = Radiobutton(frametop, text = "PNG", variable = suffix, value = "1")
r9b.grid(row = 1, column = 6 , sticky = W, pady = 2, rowspan = 1 )
l10 = Label( frametop, text= 'Speed X: ', padx = 2)
l10.grid(row = 2, column = 1 , sticky = W, pady = 2, rowspan = 1 )
e10 = Entry(frametop, textvariable = ptsval, width=8)
e10.grid(row = 2, column = 4 , sticky = W, pady = 2)
l10c = Label( frametop, text= '(with setpts)', padx = 2)
l10c.grid(row = 2, column = 5 , sticky = W, pady = 2, columnspan = 2)
l4 = Label( frametop, text= 'Frame vf mode:', padx = 2)
l4.grid(row = 3, column = 1 , sticky = W, pady = 2, rowspan = 1 )
r4 = Radiobutton(frametop, text = "fps", variable = method, value = "0")
r4.grid(row = 3, column = 4 , sticky = W, pady = 2, rowspan = 1 )
r5 = Radiobutton(frametop, text = "framerate", variable = method, value = "1")
r5.grid(row = 3, column = 5 , sticky = W, pady = 2, rowspan = 1 )
l5 = Label( frametop, text= 'Framerate interp start (0-255):', padx = 2)
l5.grid(row = 4, column = 1 , sticky = W, pady = 2, rowspan = 1 )
e5 = Entry(frametop, textvariable = startf, width=5)
e5.grid(row = 4, column = 4 , sticky = W, pady = 2 )
l2 = Label( frametop, text= 'FPS out:', padx = 2)
l2.grid(row = 5, column = 1 , sticky = W, pady = 2, rowspan = 1 )
e2 = Entry(frametop, textvariable=fps_out, width=5)
e2.grid(row = 5, column = 4 , sticky = W, pady = 2 )
l6 = Label( frametop, text= 'Mirror images:', padx = 2)
l6.grid(row = 6, column = 1 , sticky = W, pady = 2, rowspan = 1, columnspan=1 )
r6 = Radiobutton(frametop, text = "ON", variable = mirror, value = "1")
r6.grid(row = 6, column = 4 , sticky = W, pady = 2, rowspan = 1 )
r7 = Radiobutton(frametop, text = "OFF", variable = mirror, value = "0")
r7.grid(row = 6, column = 5 , sticky = W, pady = 2, rowspan = 1 )
r8 = Radiobutton(frametop, text = "Reverse only", variable = mirror, value = "2")
r8.grid(row = 6, column = 6 , sticky = W, pady = 2, rowspan = 1 )
lr1 = Label( frametop, text= 'Repeat first-last images:', padx = 2)
lr1.grid(row = 7, column = 1 , sticky = W, pady = 2, rowspan = 1, columnspan=1 )
rr7 = Checkbutton( frametop, text = "", variable = imrepeat, \
onvalue = 1, offvalue = 0, \
width = 1)
rr7.grid(row = 7, column = 3 , sticky = W, pady = 2, rowspan = 1 )
rfe = Entry(frametop, textvariable=repfirst, width=5)
rfe.grid(row = 7, column = 4 , sticky = W, pady = 2, rowspan = 1 )
rfl = Entry(frametop, textvariable=replast, width=5)
rfl.grid(row = 7, column = 5 , sticky = W, pady = 2, rowspan = 1 )
l3 = Label( frametop, text= 'CRF: (4-45)', padx = 2)
l3.grid(row = 8, column = 1 , sticky = W, pady = 2, rowspan = 1 )
e3 = Entry(frametop, textvariable=crf, width=5)
e3.grid(row = 8, column = 4 , sticky = W, pady = 2 )
l11 = Label( frametop, text= 'Filters:', padx = 2)
l11.grid(row = 9, column = 1 , sticky = W, pady = 2, rowspan = 1 , columnspan =3)
cb11 = Checkbutton( frametop, text = "HQDN3D", variable = dnz, \
onvalue = 1, offvalue = 0, \
width = 6)
cb11.grid(row = 9, column = 4 , sticky = W, pady = 2, rowspan = 1 )
l12 = Label( frametop, text= 'Out: ' + prgdir, padx = 2)
l12.grid(row = 10, column = 1 , sticky = W, pady = 2, rowspan = 1 )
e12 = Entry(frametop, textvariable=video_o, width=19) #w=10
e12.grid(row = 10, column = 5 , sticky = W, pady = 2 )
l12b = Label( frametop, text= '.webm', padx = 2)
l12b.grid(row = 10, column = 6 , sticky = W, pady = 2, rowspan = 1 )
b12b = Button ( frametop , text= "explore", command = opendir, bg = "#f7f5bc" )
b12b.grid(row = 10, column = 7 , sticky = W, pady = 0, rowspan = 1)
frametop.grid_rowconfigure(9, minsize=20)
#frametop.place(relx=0.5, rely=0.5, anchor= CENTER )
frametop.pack(pady=20)
# sotto -----------------------------------------------------
framebot = Frame(root)
framebot.grid_columnconfigure(3, minsize=20)
framebot.grid_columnconfigure(5, minsize=20)
framebot.grid_rowconfigure(3, minsize=20)
b1 = Button ( framebot , text= "START", command = esegui , padx= 50, pady=15, bg = 'black' , fg = 'white' )
b1.grid(row = 0, column = 0 ,rowspan = 2
, columnspan= 2)
b2 = Button ( framebot , text= "DELETE ALL IMG", command = lambda: cancella("all") , padx= 10, pady=10, bg = "#a81826" , fg = 'yellow' )
b2.grid(row = 0, column = 4 ,rowspan = 1)
b3 = Button ( framebot , text= "DELETE TMP IMG", command = lambda: cancella("tmp") , padx= 0, pady=10)
b3.grid(row = 0, column = 6 ,rowspan = 1)
framebot.pack(side = BOTTOM)
root.mainloop()