From b6cf0743627251202a479d27974ac62649cea8f6 Mon Sep 17 00:00:00 2001 From: ABelliqueux Date: Mon, 26 Feb 2024 18:32:18 +0100 Subject: [PATCH] Picamera2 support --- config.toml | 1 + main_c.py | 93 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/config.toml b/config.toml index b0214e9..0d0d90b 100644 --- a/config.toml +++ b/config.toml @@ -1,4 +1,5 @@ [DEFAULT] +camera_type = 0 file_extension = 'JPG' trigger_mode = 'key' projects_folder = '' diff --git a/main_c.py b/main_c.py index 98946f3..8910291 100644 --- a/main_c.py +++ b/main_c.py @@ -30,7 +30,7 @@ from io import BytesIO from itertools import count import locale import os -from PIL import Image, ImageTk, ImageFilter, ImageDraw, ImageFont +from PIL import Image, ImageTk, ImageFilter, ImageDraw, ImageOps, ImageFont import sys import threading import time @@ -73,6 +73,8 @@ _ = gettext.translation('template', localedir='locales', languages=[LOCALE]).get # Config # defaults project_settings_defaults = { + # DSLR = 0, picam = 1, webcam = 2 + 'camera_type': 0, 'file_extension':'JPG', 'trigger_mode': 'key', 'projects_folder': '', @@ -103,7 +105,7 @@ for location in config_locations: with open(os.path.expanduser(location + 'config.toml'), 'rb') as config_file: project_settings = tomllib.load(config_file) if 'CHECK' in project_settings: - camera_settings = project_settings['CHECK'] + camera_status = project_settings['CHECK'] if 'CAMERA' in project_settings: camera_settings = project_settings['CAMERA'] if 'DEFAULT' in project_settings: @@ -115,6 +117,8 @@ class KISStopmo(tk.Tk): def __init__(self, *args, **kargs): self.check_config() + if project_settings['camera_type']: + from picamera2 import Picamera2 # Default config # Set script settings according to config file self.onion_skin = project_settings['onion_skin_onstartup'] @@ -157,16 +161,36 @@ class KISStopmo(tk.Tk): self.img_index = self.check_range(len(self.img_list)-1, False) self.splash_text = _("No images yet! Start shooting...") # Camera setup - self.camera = gp.check_result(gp.gp_camera_new()) - try: - gp.check_result(gp.gp_camera_init(self.camera)) - # get configuration tree - self.current_camera_config = gp.check_result(gp.gp_camera_get_config(self.camera)) - self.apply_camera_settings(self.camera, self.current_camera_config) - if self.check_status(self.camera, self.current_camera_config) is False: - print(_("Warning: Some settings are not set to the recommended value!")) - except: - self.splash_text += _("\nCamera not found or busy.") + if project_settings['camera_type'] != 0: + try: + self.camera = Picamera2() + self.picam_conf_full = self.camera.create_still_configuration(main={"size":(1920,1080)}, lores={"size":(800,600)}) + self.camera.configure(self.picam_conf_full) + # Autofocus, get lens position and switch to manual mode + # Set Af mode to Manual (1). Default is Continuous (2), Auto is 1 + # TODO: lock exposure, wb + self.camera.set_controls({'AfMode':1}) + self.camera.start(show_preview=False) + self.camera.autofocus_cycle() + self.camera_lenspos = self.camera.capture_metadata()['LensPosition'] + self.camera.set_controls({'AfMode':0, 'AwbEnable': False, 'AeEnable': False}) + self.camera.stop() + except: + self.camera = False + self.splash_text += _("\nCamera not found or busy.") + else: + self.camera = gp.check_result(gp.gp_camera_new()) + try: + gp.check_result(gp.gp_camera_init(self.camera)) + # get configuration tree + self.current_camera_config = gp.check_result(gp.gp_camera_get_config(self.camera)) + self.apply_camera_settings(self.camera, self.current_camera_config) + if self.check_status(self.camera, self.current_camera_config) is False: + print(_("Warning: Some settings are not set to the recommended value!")) + except: + self.camera = False + + self.splash_text += _("\nCamera not found or busy.") self.timeout = 3000 # milliseconds @@ -200,8 +224,8 @@ class KISStopmo(tk.Tk): if project_settings['trigger_mode'] != 'event': root.bind("", self.capture_image) - - + + def check_config(self): global project_settings for setting in project_settings_defaults: @@ -414,7 +438,8 @@ class KISStopmo(tk.Tk): # ~ image = Image.open(filepath) # ~ print( filetuple[0] + "is not in cache") image = Image.open(os.path.join(self.savepath, filetuple[0])) - image = image.resize((w, h)) + # ~ image = image.resize((w, h),reducing_gap=1.5) + image = ImageOps.fit(image, (w, h)) if vflip: image = image.transpose(Image.Transpose.FLIP_TOP_BOTTOM) if hflip: @@ -465,6 +490,7 @@ class KISStopmo(tk.Tk): def update_image(self, event=None, index=None): + # TODO : check event mode stille works if event is not None: self.img_index = self.check_range(self.img_index+1) if index is None: @@ -639,20 +665,25 @@ class KISStopmo(tk.Tk): next_filename = self.return_next_frame_number(self.get_last_frame(self.savepath)) # build full path to file target_path = os.path.join(self.savepath, next_filename) - # ~ print(target_path) - # Get file from camera - if event_data is None: - # ~ print("j pressed") - new_frame_path = self.camera.capture(gp.GP_CAPTURE_IMAGE) - # ~ self.camera.trigger_capture() - new_frame = self.camera.file_get( - new_frame_path.folder, new_frame_path.name, gp.GP_FILE_TYPE_NORMAL) - print(_("Saving {}{}").format(new_frame_path.folder, new_frame_path.name)) + if project_settings['camera_type']: + self.camera.start(show_preview=False) + self.camera.set_controls({"LensPosition": self.camera_lenspos}) + self.camera.capture_file(target_path, 'main', format='jpeg') + self.camera.stop() else: - print(_("Getting file {}").format(event_data.name)) - new_frame = self.camera.file_get( - event_data.folder, event_data.name, gp.GP_FILE_TYPE_NORMAL) - new_frame.save(target_path) + # Get file from DSLR camera + if event_data is None: + # ~ print("j pressed") + new_frame_path = self.camera.capture(gp.GP_CAPTURE_IMAGE) + # ~ self.camera.trigger_capture() + new_frame = self.camera.file_get( + new_frame_path.folder, new_frame_path.name, gp.GP_FILE_TYPE_NORMAL) + print(_("Saving {}{}").format(new_frame_path.folder, new_frame_path.name)) + else: + print(_("Getting file {}").format(event_data.name)) + new_frame = self.camera.file_get( + event_data.folder, event_data.name, gp.GP_FILE_TYPE_NORMAL) + new_frame.save(target_path) # ~ next_filename = prefix+next(filename)+ext # ~ print(self.img_list) if '{letter}.-001.JPG'.format(letter=self.project_letter) in self.img_list: @@ -698,7 +729,11 @@ class KISStopmo(tk.Tk): # check with self.export_task.done() == True ? https://stackoverflow.com/questions/69350645/proper-way-to-retrieve-the-result-of-tasks-in-asyncio def end_bg_loop(KISStopmo): - KISStopmo.camera.exit() + if KISStopmo.camera is not False: + if project_settings['camera_type']: + KISStopmo.camera.stop() + else: + KISStopmo.camera.exit() KISStopmo.end_thread = True root = tk.Tk()