Remove tk dep, use date for session option

This commit is contained in:
ABelliqueux 2024-09-09 14:19:06 +02:00
parent 2582da088b
commit 0e49b446c6
6 changed files with 147 additions and 42 deletions

BIN
Tuffy_Bold.ttf Normal file

Binary file not shown.

View File

@ -1,5 +1,6 @@
[DEFAULT]
#camera_type = 2
use_date_for_folder = false
file_extension = 'png'
projects_folder = 'testcv/'
onion_skin_onstartup = true

View File

@ -2,6 +2,8 @@ import cv2
import gettext
from itertools import count
import os
# Needed for utf-8 text
from PIL import ImageFont, ImageDraw, Image
from send2trash import send2trash
import signal
import sys
@ -9,14 +11,14 @@ import subprocess
import time
import tomllib
# TODO : remove tkinter dep
import tkinter as tk
from tkinter import filedialog, messagebox
# ~ import tkinter as tk
# ~ from tkinter import messagebox
import numpy as np
running_from_folder = os.path.realpath(__file__)
alphabet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
next_letter = 'A'
# l10n
LOCALE = os.getenv('LANG', 'en_EN')
@ -30,7 +32,7 @@ project_settings_defaults = {
'file_extension':'JPG',
'trigger_mode': 'key',
'projects_folder': '',
# ~ 'project_letter': 'A'
'use_date_for_folder': False,
'onion_skin_onstartup' : False,
'onionskin_alpha_default' : 0.4,
'onionskin_fx' : False,
@ -61,20 +63,85 @@ for location in config_locations:
config_found_msg = _("Found configuration file in {}").format(os.path.expanduser(location))
print(config_found_msg)
# Create blank image with 0s
blank_image = np.zeros((project_settings['screen_h'], project_settings['screen_w'],3), np.uint8)
# Set all pixels to light grey
blank_image[:,0:] = 200
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(blank_image,_("Pas d'image"),(int(project_settings['screen_w']/3),int(project_settings['screen_h']/2)), font, 4, (100, 100, 100), 8, cv2.LINE_AA)
def generate_text_image(text:str, screen_w, screen_h, bullets=False):
text_image = Image.new('RGB',
(screen_w, screen_h),
(0,0,0)
)
# ~ text_image = np.zeros((screen_h,screen_w,3),np.uint8)
# ~ text_image_pil = Image.fromarray(text_image)
text_image_draw = ImageDraw.Draw(text_image)
if text is not None:
font = ImageFont.truetype("Tuffy_Bold.ttf", (screen_w/32))
font_len = font.getlength(text.split('\n')[0])
text_image_draw.multiline_text((screen_w/2 - font_len/2, screen_h/2 ),
text,
fill=(255, 255, 255),
font=font,
align='center',
spacing=20
)
if bullets:
dot_radius = screen_w/24
x_unit = (screen_w/32)
y_unit = (screen_h/32)
green_dot = (x_unit*14, y_unit*24)
red_dot = (green_dot[0]+x_unit*4, green_dot[1])
# Green dot
text_image_draw.circle(green_dot,
dot_radius,
fill=(0,255,0),
outline=None,
width=1
)
text_image_draw.text(green_dot,
_("Yes"),
fill=(0, 0, 0),
font=font,
anchor="mm",
spacing=20
)
# Red dot
text_image_draw.circle(red_dot,
dot_radius,
fill=(0,0,255),
outline=None,
width=1
)
text_image_draw.text(red_dot,
_("No"),
fill=(0, 0, 0),
font=font,
anchor="mm",
spacing=20
)
text_image = np.array(text_image)
return text_image
def find_letter_after(letter:str):
if letter in alphabet and alphabet.index(letter) < len(alphabet) - 1:
return alphabet[alphabet.index(letter) + 1]
def askyesno(text:str):
blank = generate_text_image(text, project_settings['screen_w'], project_settings['screen_h'], bullets=True)
cv2.imshow("StopiCV", blank)
# Wait for input to continue
answer = cv2.waitKey(0)
# Space pressed == yes
if answer%256 == 32 or answer%256 == 48 :
return True
# Any other key == no
else:
return False
def find_letter_after(letter:str, date=False):
if letter in alphabet and alphabet.index(letter) < len(alphabet) - 1 and not date:
letter = alphabet[alphabet.index(letter) + 1]
else:
# Create folder with date
year,mon,day,hour,minute,sec,wd,yd,dst = time.localtime()
letter = '{}-{}-{}_{}-{}-{}'.format(year,mon,day,hour,minute,sec)
return letter
def get_projects_folder():
if len(projects_folder):
project_folder = projects_folder
@ -99,28 +166,34 @@ def get_projects_folder():
def get_session_folder():
global next_letter
project_folder = get_projects_folder()
if project_folder:
sessions_list = []
dir_list = os.listdir(project_folder)
# Filter folders with name only one char long
for dir in dir_list:
if len(dir) == 1 and dir in alphabet:
sessions_list.append(dir)
for folder in dir_list:
if len(folder) == 1 and folder in alphabet:
sessions_list.append(folder)
# If folders exist, find last folder in alphabetical order
if len(sessions_list):
sessions_list.sort()
last_letter = sessions_list[-1]
# By default, find next letter for a new session
next_letter = find_letter_after(last_letter)
next_letter = find_letter_after(last_letter, project_settings['use_date_for_folder'])
if next_letter is False:
return False
# A previous session folder was found; ask the user if they wish to resume session
resume_session = tk.messagebox.askyesno(_("Resume session?"), _("A previous session was found in {}, resume shooting ?").format(os.path.join(project_folder, last_letter)))
if resume_session:
next_letter = last_letter
if not project_settings['use_date_for_folder']:
resume_session = askyesno(_("A previous session was found in {},\n resume shooting ?").format(os.path.join(project_folder, last_letter)))
# ~ resume_session = tk.messagebox.askyesno(_("Resume session?"), _("A previous session was found in {}, resume shooting ?").format(os.path.join(project_folder, last_letter)))
if resume_session:
next_letter = last_letter
else:
next_letter = 'A'
if not project_settings['use_date_for_folder']:
next_letter = 'A'
else:
next_letter = find_letter_after('A', project_settings['use_date_for_folder'])
if os.path.exists(os.path.join(project_folder, next_letter)) is False:
os.mkdir(os.path.join(project_folder, next_letter))
print(_("Using {} as session folder.").format(os.path.join(project_folder, next_letter)))
@ -346,10 +419,10 @@ def main(args):
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cv2.namedWindow("StopiCV", cv2.WINDOW_GUI_NORMAL)
cv2.setWindowProperty("StopiCV", cv2.WND_PROP_OPENGL, cv2.WINDOW_OPENGL)
cv2.setWindowProperty("StopiCV", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.setWindowProperty("StopiCV", cv2.WND_PROP_ASPECT_RATIO, cv2.WINDOW_KEEPRATIO)
# ~ cv2.namedWindow("StopiCV", cv2.WINDOW_GUI_NORMAL)
# ~ cv2.setWindowProperty("StopiCV", cv2.WND_PROP_OPENGL, cv2.WINDOW_OPENGL)
# ~ cv2.setWindowProperty("StopiCV", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
# ~ cv2.setWindowProperty("StopiCV", cv2.WND_PROP_ASPECT_RATIO, cv2.WINDOW_KEEPRATIO)
frame = get_onionskin_frame(savepath, index)
while True:
@ -403,20 +476,16 @@ def main(args):
# Key left
elif (k%256 == 81) or (k%256 == 52):
# Displau previous frame
print("Left")
if len(img_list):
if playback:
playback = False
index, frame = previous_frame(index)
print("L: {}".format(index))
elif (k%256 == 83) or (k%256 == 54):
# Displau next frame
print("Right")
if len(img_list):
if playback:
playback = False
index, frame = next_frame(index)
print("R: {}".format(index))
# Key e / keypad *
elif (k%256 == 101) or (k%256 == 42):
print("Export")
@ -444,8 +513,8 @@ def main(args):
print(_("Window was closed, exiting..."))
break
# Take pic
# SPACE or numpad 0 pressed
elif (k%256 == 32) or (k%256 == 48):
# SPACE pressed
img_name = return_next_frame_number(get_last_frame(savepath))
img_path = os.path.join(savepath, img_name)
cv2.imwrite(img_path, og_frame)
@ -455,31 +524,43 @@ def main(args):
else:
index += 1
frame = get_onionskin_frame(savepath, index)
# TODO : go back to last frame ?
# REMOVE : Debug print keycode
elif k==-1: # normally -1 returned,so don't print it
continue
else:
print(k) # else print its value
if 'ffmpeg_process' in locals():
if ffmpeg_process.poll() is None:
print("Ffmpeg is still running. Waiting for task to complete.")
if ffmpeg_process.poll() is None:
print(_("Ffmpeg is still running.\n Waiting for task to complete."))
msg = generate_text_image(_("Ffmpeg is still running.\n Waiting for task to complete."),
project_settings['screen_w'], project_settings['screen_h']
)
cv2.imshow("StopiCV", msg)
# Force window refresh
cv2.pollKey()
try:
ffmpeg_process.wait(timeout=1)
ffmpeg_process.wait(timeout=20)
except:
print("Terminating running process...")
print(_("Terminating running process..."))
ffmpeg_process.terminate()
cam.release()
cv2.destroyAllWindows()
cv2.namedWindow("StopiCV", cv2.WINDOW_GUI_NORMAL)
cv2.setWindowProperty("StopiCV", cv2.WND_PROP_OPENGL, cv2.WINDOW_OPENGL)
cv2.setWindowProperty("StopiCV", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.setWindowProperty("StopiCV", cv2.WND_PROP_ASPECT_RATIO, cv2.WINDOW_KEEPRATIO)
ctrlc_pressed = False
projects_folder = project_settings['projects_folder']
next_letter = 'Z'
img_list = []
savepath = get_session_folder()
onionskin = project_settings['onion_skin_onstartup']
playback = False
playhead = 0
loop_playback = True
blank_image = generate_text_image(_("No images yet! Start shooting..."), project_settings['screen_w'], project_settings['screen_h'])
if len(savepath):
project_letter = savepath.split(os.sep)[-1]

Binary file not shown.

View File

@ -6,14 +6,20 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2024-02-18 11:30+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"PO-Revision-Date: 2024-09-09 12:28+0200\n"
"Last-Translator: arthus <arthus@ateliers>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
msgid "Yes"
msgstr "Oui"
msgid "No"
msgstr "Non"
#: ../main_c.py:96
msgid "No configuration file found, using defaults."
msgstr "Aucun fichier de configuration trouvé, utilisation des valeurs par défaut."
@ -37,8 +43,8 @@ msgid ""
msgstr "\nCaméra introuvable ou occupée."
#: ../main_c.py:256
msgid "A previous session was found in {}, resume shooting ?"
msgstr "Une session précédente à été trouvée dans {}, reprendre la session ?"
msgid "A previous session was found in {},\n resume shooting ?"
msgstr "Une session précédente à été trouvée dans {},\n reprendre la session ?"
#: ../main_c.py:256
msgid "Resume session?"
@ -86,3 +92,9 @@ msgstr "Exportation dans {}"
msgid "Mp4 files"
msgstr "Fichier Mp4"
msgid "Ffmpeg is still running.\n Waiting for task to complete."
msgstr "Ffmpeg est toujours en cours d'éxécution.\n Attente de la fin du processus.'"
msgid "Terminating running process..."
msgstr "Terminaison des processus en cours..."

View File

@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2024-02-19 18:47+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"PO-Revision-Date: 2024-09-09 12:28+0200\n"
"Last-Translator: arthus <arthus@ateliers>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -15,6 +15,12 @@ msgstr ""
"Generated-By: pygettext.py 1.5\n"
msgid "Yes"
msgstr ""
msgid "No"
msgstr ""
#: ../main_c.py:96
msgid "No configuration file found, using defaults."
msgstr ""
@ -38,7 +44,7 @@ msgid ""
msgstr ""
#: ../main_c.py:281
msgid "A previous session was found in {}, resume shooting ?"
msgid "A previous session was found in {},\n resume shooting ?"
msgstr ""
#: ../main_c.py:281
@ -85,3 +91,8 @@ msgstr ""
msgid "Exporting to {}"
msgstr ""
msgid "Ffmpeg is still running.\n Waiting for task to complete."
msgstr ""
msgid "Terminating running process..."
msgstr ""