From 8282c49454f4b13d8b6616a92a8fd6afbb1ffdcb Mon Sep 17 00:00:00 2001 From: paulscalise1 <93959622+paulscalise1@users.noreply.github.com> Date: Mon, 17 Feb 2025 18:07:53 -0600 Subject: [PATCH] deleted utility --- keychain-utility.py | 478 -------------------------------------------- 1 file changed, 478 deletions(-) delete mode 100644 keychain-utility.py diff --git a/keychain-utility.py b/keychain-utility.py deleted file mode 100644 index e94fec5..0000000 --- a/keychain-utility.py +++ /dev/null @@ -1,478 +0,0 @@ -import tkinter as tk -from tkinter import ttk, filedialog, scrolledtext, messagebox -from PIL import Image, ImageTk, ImageEnhance, ImageOps -import subprocess -import os - -class UNLKeychainProgrammerApp: - def __init__(self, root): - self.root = root - self.root.title("UNL Keychain Utility") - self.root.geometry("850x650") - - # Create a notebook (tabbed interface) - self.notebook = ttk.Notebook(root) - self.notebook.pack(fill=tk.BOTH, expand=True) - - # Page 1: UNL Keychain Programmer - self.page1 = ttk.Frame(self.notebook) - self.notebook.add(self.page1, text="Keychain Programmer") - - # Terminal output window - self.terminal_output = scrolledtext.ScrolledText(self.page1, wrap=tk.WORD, width=80, height=20) - self.terminal_output.pack(padx=10, pady=10) - - # Add initial text to the terminal output window - self.terminal_output.insert(tk.END, "> Welcome to the UNL Keychain Utility application v1.0.\n") - self.terminal_output.insert(tk.END, "> To begin programming your keychain, select the '.bin' file from the 'build' folder.\n") - self.terminal_output.insert(tk.END, "> Create custom images using the Bitmap Playground tab.\n\n") - - # Select File button - self.select_file_button = ttk.Button(self.page1, text="Select File", command=self.select_file) - self.select_file_button.pack(pady=5) - - # Flash Firmware button - self.flash_firmware_button = ttk.Button(self.page1, text="Flash Firmware", command=self.flash_firmware) - self.flash_firmware_button.pack(pady=5) - - # Button to toggle options visibility - self.toggle_options_button = ttk.Button(self.page1, text="Options", command=self.toggle_options) - self.toggle_options_button.pack(pady=5) - - # Frame to hold checkboxes (initially hidden) - self.options_frame = ttk.Frame(self.page1) - self.options_visible = False - - # Checkboxes for options - self.options_vars = {} - for option in ["-u", "-l", "-e", "-o", "-G", "-R"]: - var = tk.BooleanVar() - self.options_vars[option] = var - checkbox = ttk.Checkbutton(self.options_frame, text=option, variable=var) - checkbox.pack(anchor=tk.W) - - # Page 2: Image to Bitmap Converter - self.page2 = ttk.Frame(self.notebook) - self.notebook.add(self.page2, text="Bitmap Playground") - - # Upload Image button - self.upload_image_button = ttk.Button(self.page2, text="Upload Image", command=self.upload_image) - self.upload_image_button.pack(pady=10) - - # Brightness label - self.brightness_label = ttk.Label(self.page2, text="Brightness:") - self.brightness_label.pack(pady=5) - - # Brightness slider with labels - self.brightness_frame = ttk.Frame(self.page2) - self.brightness_frame.pack(pady=5) - - self.brightness_label_left = ttk.Label(self.brightness_frame, text="0%") - self.brightness_label_left.pack(side=tk.LEFT, padx=5) - - self.brightness_slider = ttk.Scale(self.brightness_frame, from_=0, to=1, value=1, orient=tk.HORIZONTAL) - self.brightness_slider.pack(side=tk.LEFT, fill=tk.X, expand=True) - - self.brightness_label_right = ttk.Label(self.brightness_frame, text="100%") - self.brightness_label_right.pack(side=tk.LEFT, padx=5) - - # Mono Mode button - self.mono_mode_var = tk.BooleanVar() - self.mono_mode_button = ttk.Checkbutton(self.page2, text="Mono Mode", variable=self.mono_mode_var, command=self.toggle_mono_mode) - self.mono_mode_button.pack(pady=5) - - # Generate Image button - self.generate_image_button = ttk.Button(self.page2, text="Generate Bitmap", command=self.generate_image) - self.generate_image_button.pack(pady=10) - - # Image preview window - self.image_preview_label = ttk.Label(self.page2) - self.image_preview_label.pack(pady=10) - - # C Array output text box - self.c_array_text = scrolledtext.ScrolledText(self.page2, wrap=tk.WORD, width=100, height=13) - self.c_array_text.pack(padx=10, pady=10) - - # Add a "Copy to Clipboard" button - self.copy_button = ttk.Button(self.page2, text="Copy Code to Clipboard", command=self.copy_to_clipboard) - self.copy_button.pack(pady=10) - - # Page 3: GIF to Bitmap Converter - self.page3 = ttk.Frame(self.notebook) - self.notebook.add(self.page3, text="GIF Playground") - - # Upload GIF button - self.upload_gif_button = ttk.Button(self.page3, text="Upload GIF", command=self.upload_gif) - self.upload_gif_button.pack(pady=10) - - # Create a frame to hold the labels - self.frame_info_container = ttk.Frame(self.page3) - self.frame_info_container.pack(pady=5) - - self.frame_count_label = ttk.Label(self.frame_info_container, text="Original number of frames: 0") - self.frame_count_label.pack(side=tk.LEFT, padx=10) - - self.frame_duration_value_label = ttk.Label(self.frame_info_container, text="Average Frame Duration: 0 ms") - self.frame_duration_value_label.pack(side=tk.LEFT, padx=10) - - # Label to display the slider value (frames to output) - self.frame_slider_value_label = ttk.Label(self.page3, text="Frames to output: 0 (also output size in KB)") - self.frame_slider_value_label.pack(pady=5) - - # Slider for number of frames - self.frame_slider_label = ttk.Label(self.page3) - #self.frame_slider_label.pack(pady=5) - - self.frame_slider = ttk.Scale(self.page3, from_=1, to=100, orient=tk.HORIZONTAL) - self.frame_slider.pack(pady=5) - - # Bind the slider to update the label - self.frame_slider.config(command=self.update_slider_value_label) - - # Checkbox for retaining aspect ratio - self.aspect_ratio_var = tk.BooleanVar(value=True) - self.aspect_ratio_checkbox = ttk.Checkbutton(self.page3, text="Retain Aspect Ratio", variable=self.aspect_ratio_var) - self.aspect_ratio_checkbox.pack(pady=5) - - # Save GIF button - self.save_gif_button = ttk.Button(self.page3, text="Generate GIF Frame Code", command=self.save_gif) - self.save_gif_button.pack(pady=10) - - # GIF preview window - self.gif_preview_label = ttk.Label(self.page3) - self.gif_preview_label.pack(pady=10) - - # C Array output text box - self.gif_array_text = scrolledtext.ScrolledText(self.page3, wrap=tk.WORD, width=100, height=13) - self.gif_array_text.pack(padx=10, pady=10) - - # Add a "Copy to Clipboard" button - self.copy_gif_text = ttk.Button(self.page3, text="Copy Code to Clipboard", command=self.copy_gif_text_clipboard) - self.copy_gif_text.pack(pady=10) - - # Variable to track the preview loop - self.after_id = None - self.uploaded_gif_path = None - - def toggle_options(self): - """Toggle the visibility of the options frame.""" - if self.options_visible: - self.options_frame.pack_forget() - else: - self.options_frame.pack(pady=5, fill=tk.X) - self.options_visible = not self.options_visible - - def select_file(self): - file_path = filedialog.askopenfilename(filetypes=[("Binary files", "*.bin")]) - if file_path: - self.terminal_output.insert(tk.END, f"Selected file: {file_path}\n") - self.selected_file = file_path - else: - self.terminal_output.insert(tk.END, "No file selected.\n") - - def flash_firmware(self): - if hasattr(self, 'selected_file'): - selected_options = [option for option, var in self.options_vars.items() if var.get()] - command = f"puyaisp {' '.join(selected_options)} -f {self.selected_file}" - - # Display the command being executed - self.terminal_output.insert(tk.END, f"Executing command: {command}\n") - - try: - result = subprocess.run(command, shell=True, capture_output=True, text=True) - self.terminal_output.insert(tk.END, result.stdout) - self.terminal_output.insert(tk.END, result.stderr) - except Exception as e: - self.terminal_output.insert(tk.END, f"Error: {e}\n") - else: - self.terminal_output.insert(tk.END, "No file selected. Please select a file first.\n") - - def upload_image(self): - file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg *.png *.bmp")]) - if file_path: - self.image_path = file_path - self.show_image_preview(file_path) - else: - self.image_preview_label.config(text="No image selected.") - - def toggle_mono_mode(self): - """Enable or disable the brightness slider based on mono mode.""" - if self.mono_mode_var.get(): - self.brightness_slider.config(state=tk.DISABLED) # Disable the slider - else: - self.brightness_slider.config(state=tk.NORMAL) # Enable the slider - - def generate_image(self): - if hasattr(self, 'image_path'): - brightness = self.brightness_slider.get() if not self.mono_mode_var.get() else None - use_second_method = self.mono_mode_var.get() - - if use_second_method: - pixels = self.process_image_mono(self.image_path) - else: - pixels = self.process_image_regular(self.image_path, brightness) - - c_arr = self.generate_c_array(pixels, "const uint8_t custom_frame[1024] = {") - self.c_array_text.delete(1.0, tk.END) - self.c_array_text.insert(tk.END, c_arr) - - # Show the processed image preview - base_filename = os.path.basename(self.image_path) - processed_image_path = f'monochrome_{base_filename}' - self.show_image_preview(processed_image_path) - else: - self.c_array_text.delete(1.0, tk.END) - self.c_array_text.insert(tk.END, "No image selected. Please upload an image first.") - - def copy_to_clipboard(self): - """Copy the content of the ScrolledText widget to the clipboard.""" - text = self.c_array_text.get("1.0", tk.END).strip() - self.root.clipboard_clear() - self.root.clipboard_append(text) - self.root.update() - - def copy_gif_text_clipboard(self): - """Copy the content of the ScrolledText widget to the clipboard.""" - text = self.gif_array_text.get("1.0", tk.END).strip() - self.root.clipboard_clear() - self.root.clipboard_append(text) - self.root.update() - - def process_image_regular(self, filename, brightness=1.0): - img = Image.open(filename).convert('L') - enhancer = ImageEnhance.Brightness(img) - img = enhancer.enhance(brightness) - img = img.resize((128, 64)) - img.save('greyscale3.png') - - mono = img.convert('1') - mono = mono.resize((128, 64)) - - pixels = list(mono.getdata()) - white = pixels.count(255) - black = pixels.count(0) - - if white > black: - pixels = [not elem for elem in pixels] - - mono = Image.new(mono.mode, mono.size) - mono.putdata(pixels) - - base_filename = os.path.basename(filename) - output_filename = f'monochrome_{base_filename}' - mono.save(output_filename) - - return pixels - - def process_image_mono(self, filename): - img = Image.open(filename).convert('L') - img = img.resize((128, 64)) - - threshold = 128 - mono = img.point(lambda p: 255 if p > threshold else 0, '1') - - pixels = list(mono.getdata()) - white = pixels.count(255) - black = pixels.count(0) - - if white > black: - pixels = [0 if elem == 255 else 255 for elem in pixels] - - mono = Image.new('1', (128, 64)) - mono.putdata(pixels) - - base_filename = os.path.basename(filename) - output_filename = f'monochrome_{base_filename}' - mono.save(output_filename) - - return pixels - - def generate_c_array(self, pixels, c_arr_str): - c_arr = c_arr_str - q = 0 - for i in range(len(pixels)): - j = i % 8 - if j == 0 and i != 0: - c_arr += f"0x{q:02x}," - q = 0 - if pixels[i] == 255: - q += 1 << (7 - j) - c_arr += f"0x{q:02x}" - c_arr += '};' - - start_index = c_arr.find("{") + 1 - end_index = c_arr.find("}") - hex_values_str = c_arr[start_index:end_index] - hex_values_list = hex_values_str.split(",") - reg_bitmap = [int(x.strip(), 16) for x in hex_values_list] - - paged_bitmap = [] - for page in range(8): - for segment in range(16): - buff = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] - for col in range(8): - b = reg_bitmap[1023 - (page * 128 + segment + col * 16)] - for e in range(8): - buff[e] = buff[e] | ((b & 0x01) << col) - b = b >> 1 - paged_bitmap.extend(buff) - - hex_strings = [f"0x{byte:02x}" for byte in paged_bitmap] - chunks = [hex_strings[i:i + 16] for i in range(0, len(hex_strings), 16)] - rows = [", ".join(chunk) for chunk in chunks] - return c_arr_str + "\n " + ",\n ".join(rows) + "};" - - def show_image_preview(self, image_path): - image = Image.open(image_path) - image = image.resize((128, 64)) - photo = ImageTk.PhotoImage(image) - self.image_preview_label.config(image=photo) - self.image_preview_label.image = photo - - def upload_gif(self): - file_path = filedialog.askopenfilename(filetypes=[("GIF files", "*.gif")]) - if file_path: - self.gif_path = file_path - self.show_gif_preview(file_path) - self.update_frame_duration_vlaue_label(file_path) - else: - self.gif_preview_label.config(text="No GIF selected.") - - def show_gif_preview(self, gif_path): - if self.after_id: - self.root.after_cancel(self.after_id) # Stop the previous loop - gif = Image.open(gif_path) - self.gif_frames = [] - self.frame_durations = [] - for frame in range(gif.n_frames): - gif.seek(frame) - self.gif_frames.append(gif.copy()) - self.frame_durations.append(gif.info['duration']) - self.current_frame = 0 - self.frame_count_label.config(text=f"Number of frames: {len(self.gif_frames)}") # Update frame count - self.frame_slider.config(to=len(self.gif_frames)) # Update slider max value - self.frame_slider.set(int((len(self.gif_frames) - 1) * 0.50)) # Set default to 50% of total frames - self.update_slider_value_label(self.frame_slider.get()) # Update the slider value label - self.update_gif_preview() - - def update_slider_value_label(self, value): - """Update the label to show the current slider value.""" - self.frame_slider_value_label.config(text=f"Frames to output: {int(float(value))} (also output size in KB)") - - def update_frame_duration_vlaue_label(self, gif_path): - gif = Image.open(gif_path) - total_frames = gif.n_frames - # Calculate total duration of original GIF - gif_duration = 0 - for i in range(total_frames): - gif.seek(i) - gif_duration += gif.info['duration'] - - # Calculate new duration per frame to maintain total duration - duration_per_frame = int(gif_duration / (total_frames)) - self.frame_duration_value_label.config(text=f"Average Frame Duration: {int(duration_per_frame)} ms") - - def update_gif_preview(self): - if self.gif_frames: - frame_image = ImageTk.PhotoImage(self.gif_frames[self.current_frame]) - self.gif_preview_label.config(image=frame_image) - self.gif_preview_label.image = frame_image - self.current_frame = (self.current_frame + 1) % len(self.gif_frames) - self.after_id = self.root.after(self.frame_durations[self.current_frame], self.update_gif_preview) - - def save_gif(self): - if hasattr(self, 'gif_path'): - num_frames = int(self.frame_slider.get()) # Get the slider value - retain_aspect_ratio = self.aspect_ratio_var.get() - output_path = os.path.join(os.getcwd(), "output.gif") - self.convert_gif_to_bw_gif(self.gif_path, output_path, num_frames, retain_aspect_ratio) - self.show_gif_preview(output_path) - else: - messagebox.showerror("Error", "No valid GIF file uploaded.") - - def convert_gif_to_bw_gif(self, gif_path, output_path, num_frames, retain_aspect_ratio): - try: - gif = Image.open(gif_path) - frames = [] - durations = [] - total_frames = gif.n_frames - step = total_frames / num_frames - - # Calculate total duration of original GIF - original_duration = 0 - for i in range(total_frames): - gif.seek(i) - original_duration += gif.info['duration'] - - # Calculate new duration per frame to maintain total duration - new_duration_per_frame = int(original_duration / (num_frames - 1)) # -1 because we skip first frame - - - for i in range(1, num_frames): - frame_index = int(i * step) - gif.seek(frame_index) - - if retain_aspect_ratio: - resized_frame = self.resize_with_aspect_ratio(gif, (128, 64)) - else: - resized_frame = gif.resize((128, 64)) - - bw_frame = resized_frame.convert("1") - frames.append(bw_frame) - durations.append(new_duration_per_frame) - - frames[0].save( - output_path, - save_all=True, - append_images=frames[1:], - loop=0, - duration=durations, - disposal=2 - ) - - self.gif_array_text.delete(1.0, tk.END) - for idx, frame in enumerate(frames): - pixels = list(frame.getdata()) - c_arr = self.generate_c_array(pixels, f"const uint8_t gif{idx}[1024] = {{") - self.gif_array_text.insert(tk.END, c_arr + "\n\n") - - self.gif_array_text.insert(tk.END, f"const uint8_t * gif[{len(frames)}] = {{") - - for idx, frame in enumerate(frames): - if (idx != 0 and idx % 10 == 0): - self.gif_array_text.insert(tk.END, f" \\ \n\t\t") - if (idx == len(frames) - 1): - self.gif_array_text.insert(tk.END, f"gif{idx}}};\n\n") - else: - self.gif_array_text.insert(tk.END, f"gif{idx}, ") - - - return output_path - except Exception as e: - messagebox.showerror("Error", f"An error occurred: {e}") - return None - - def resize_with_aspect_ratio(self, frame, target_size): - original_width, original_height = frame.size - target_width, target_height = target_size - aspect_ratio = original_width / original_height - - if aspect_ratio > (target_width / target_height): - new_width = target_width - new_height = int(target_width / aspect_ratio) - else: - new_height = target_height - new_width = int(target_height * aspect_ratio) - - resized_frame = frame.resize((new_width, new_height)) - padded_frame = Image.new("1", target_size, 0) - padded_frame.paste(resized_frame, ( - (target_width - new_width) // 2, - (target_height - new_height) // 2 - )) - return padded_frame - -if __name__ == "__main__": - root = tk.Tk() - app = UNLKeychainProgrammerApp(root) - root.mainloop() \ No newline at end of file -- GitLab