Merge branch 'feature/forked' into 'main'
Finishing op the TUI version See merge request python_projects3802849/optima-35-tui!1
This commit is contained in:
commit
a0b4e1d771
4 changed files with 34 additions and 38 deletions
54
README.md
54
README.md
|
@ -1,65 +1,50 @@
|
||||||
# OPTIMA-35
|
# OPTIMA-35 TUI *version*
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
Fork from **OPTIMA-35** (**Organizing, Processing, Tweaking Images and Modifying scanned Analogs from 35mm Film**) which will preserve the TUI
|
||||||
**OPTIMA-35** (**Organizing, Processing, Tweaking Images and Modifying scanned Analogs from 35mm Film**) is a Python-based project designed to provide a streamlined way to manage and edit metadata and images from analog photography. But can be used for any images.
|
|
||||||
|
|
||||||
This project is a *port* of my earlier work, an collection of [bash script](https://gitlab.com/sf-bashscripts/analogphotography), transitioning functionality to a more modular and maintainable design.
|
This project is a *port* of my earlier work, an collection of [bash script](https://gitlab.com/sf-bashscripts/analogphotography), transitioning functionality to a more modular and maintainable design.
|
||||||
|
|
||||||
The primary focus is on building a terminal-based user interface (TUI). Initially, the interface will utilize `simple_term_menu`, with plans to expand to `textual` for a more dynamic TUI experience in the future.
|
|
||||||
|
|
||||||
**Please check** if a new branch is available and read the **changelog** to see the progress and current features of the program. The README might sometimes lag behind.
|
|
||||||
|
|
||||||
## **Current Status**
|
## **Current Status**
|
||||||
- While the program works and core features are available, there are currently no safety checks in place. For example, the program will write / save an image without verifying if a file with the same name already exists.
|
- While the program works and core features are available, there are currently some safety checks missing. For example, the program will write / save an image without verifying if a file with the same name already exists.
|
||||||
- Additionally, while EXIF data/metadata should be implemented correctly, there is a possibility of overlooked issues. In the worst case, a program might throw an error when handling EXIF data, though this has not occurred so far.
|
- Additionally, while EXIF data/metadata should be implemented correctly, there is a possibility of overlooked issues. In the worst case, a program might throw an error when handling EXIF data, though this has not occurred so far.
|
||||||
|
|
||||||
### Available Features:
|
### Available Features:
|
||||||
- Initial basic TUI functionality using `simple_term_menu` (planned to switch to a different interface later).
|
- Initial basic TUI functionality using `simple_term_menu`
|
||||||
- Core features, including image resizing, metadata management, and YAML configuration.
|
- Core features:
|
||||||
|
- resizing
|
||||||
## Key Features
|
- renaming
|
||||||
|
- grayscale
|
||||||
- Intuitive TUI for organizing and editing metadata and image properties.
|
- Change brightness
|
||||||
- Improved modularity with classes split into separate files for flexibility and maintainability.
|
- Change contrast
|
||||||
- Supports essential tasks like reading, editing, and saving EXIF data, as well as resizing and processing images.
|
- Exif management
|
||||||
|
- Add watermark
|
||||||
|
|
||||||
**Gif of program in action**
|
**Gif of program in action**
|
||||||
|
|
||||||
|

|
||||||

|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
To run **OPTIMA-35 TUI**, the following Python libraries are required:
|
||||||
|
|
||||||
To run **OPTIMA-35**, the following Python libraries are required:
|
|
||||||
|
|
||||||
- **textual**: For building TUI (planned future updates).
|
|
||||||
- **pyyaml**: To handle YAML files for configuration and settings.
|
- **pyyaml**: To handle YAML files for configuration and settings.
|
||||||
- **piexif**: To read, modify, and write EXIF metadata.
|
- **piexif**: To read, modify, and write EXIF metadata.
|
||||||
- **Pillow**: For image processing.
|
- **pillow**: For image processing.
|
||||||
- **simple\_term\_menu**: For building the initial TUI interface.
|
- **simple\_term\_menu**: For building the initial TUI interface.
|
||||||
|
|
||||||
### Installing Dependencies
|
### Installing Dependencies
|
||||||
|
|
||||||
You can install the dependencies using `pip`:
|
You can install the dependencies using `pip`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install textual pyyaml piexif pillow simple-term-menu
|
pip install pyyaml piexif pillow simple-term-menu
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can use `conda` or its alternatives (`anaconda`, `mamba`, `micromamba`):
|
Alternatively, you can use `conda` or its alternatives (`anaconda`, `mamba`, `micromamba`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
conda install -c conda-forge textual pyyaml piexif pillow simple-term-menu
|
conda install -c conda-forge pyyaml piexif pillow simple-term-menu
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development Approach
|
|
||||||
Compared to my previous project, [FTL Save Manager](https://gitlab.com/python_projects3802849/ftl-save-manager), this project emphasizes:
|
|
||||||
|
|
||||||
- **Enhanced Modularity**: Classes and components are organized into separate files, making the codebase more maintainable and scalable.
|
|
||||||
- **Improved Design Principles**: Focus on creating reusable and flexible code for future expansion.
|
|
||||||
- **Slower Code Pushes**: Updates and code releases will be less frequent but of higher quality, ensuring stability and adherence to best practices.
|
|
||||||
|
|
||||||
# Use of LLMs
|
# Use of LLMs
|
||||||
In the interest of transparency, I disclose that Generative AI (GAI) large language models (LLMs), including OpenAI’s ChatGPT and Ollama models (e.g., OpenCoder and Qwen2.5-coder), have been used to assist in this project.
|
In the interest of transparency, I disclose that Generative AI (GAI) large language models (LLMs), including OpenAI’s ChatGPT and Ollama models (e.g., OpenCoder and Qwen2.5-coder), have been used to assist in this project.
|
||||||
|
|
||||||
|
@ -71,8 +56,9 @@ In the interest of transparency, I disclose that Generative AI (GAI) large langu
|
||||||
|
|
||||||
In cases where LLMs contribute directly to code or provide substantial optimizations, such contributions will be disclosed and documented in the relevant sections of the codebase.
|
In cases where LLMs contribute directly to code or provide substantial optimizations, such contributions will be disclosed and documented in the relevant sections of the codebase.
|
||||||
|
|
||||||
mradermacher gguf Q4K-M Instruct version of infly/OpenCoder-1.5B
|
**ollama**
|
||||||
unsloth gguf Q4K_M Instruct version of both Qwen/QWEN2 1.5B and 3B
|
- mradermacher gguf Q4K-M Instruct version of infly/OpenCoder-1.5B
|
||||||
|
- unsloth gguf Q4K_M Instruct version of both Qwen/QWEN2 1.5B and 3B
|
||||||
|
|
||||||
### References
|
### References
|
||||||
1. **Huang, Siming, et al.**
|
1. **Huang, Siming, et al.**
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# Example file. You can add and remove entries here.
|
||||||
make:
|
make:
|
||||||
- Nikon
|
- Nikon
|
||||||
model:
|
model:
|
||||||
|
|
6
main.py
6
main.py
|
@ -8,7 +8,8 @@ from ui.tui import SimpleTUI
|
||||||
class Optima35:
|
class Optima35:
|
||||||
# The layout of class Optima35 was originally made by ChatGPT, but major adjustments have been made. To remain transparent, I disclose this.
|
# The layout of class Optima35 was originally made by ChatGPT, but major adjustments have been made. To remain transparent, I disclose this.
|
||||||
def __init__(self, settings_file, exif_options_file):
|
def __init__(self, settings_file, exif_options_file):
|
||||||
self.version = "0.2.0"
|
self.name = "OPTIMA-35 TUI"
|
||||||
|
self.version = "0.2.1"
|
||||||
self.utilities = Utilities()
|
self.utilities = Utilities()
|
||||||
self.image_processor = ImageProcessor()
|
self.image_processor = ImageProcessor()
|
||||||
self.exif_handler = ExifHandler()
|
self.exif_handler = ExifHandler()
|
||||||
|
@ -132,7 +133,8 @@ class Optima35:
|
||||||
self.settings["output_folder"] = input("Enter path of output folder: ").strip()
|
self.settings["output_folder"] = input("Enter path of output folder: ").strip()
|
||||||
self.settings["file_format"] = self.take_input_and_validate(question = "Enter export file format (jpg, png, webp): ", accepted_input = ["jpg", "png", "webp"], accepted_type = str)
|
self.settings["file_format"] = self.take_input_and_validate(question = "Enter export file format (jpg, png, webp): ", accepted_input = ["jpg", "png", "webp"], accepted_type = str)
|
||||||
self.settings["modifications"] = self.tui.multi_select_menu(
|
self.settings["modifications"] = self.tui.multi_select_menu(
|
||||||
"Select what you want to do", menu_options
|
f"\n{self.name} v.{self.version} \nSelect what you want to do (esc or q to exit)",
|
||||||
|
menu_options
|
||||||
)
|
)
|
||||||
if "Change EXIF" not in self.settings["modifications"]:
|
if "Change EXIF" not in self.settings["modifications"]:
|
||||||
self.settings["copy_exif"] = self.tui.yes_no_menu("Do you want to copy exif info from original file?")
|
self.settings["copy_exif"] = self.tui.yes_no_menu("Do you want to copy exif info from original file?")
|
||||||
|
|
|
@ -47,13 +47,20 @@ class ImageProcessor:
|
||||||
font = ImageFont.truetype("OpenDyslexic3-Regular.ttf", font_size)
|
font = ImageFont.truetype("OpenDyslexic3-Regular.ttf", font_size)
|
||||||
except:
|
except:
|
||||||
print("Error loading font for watermark, please ensure font is installed...\n")
|
print("Error loading font for watermark, please ensure font is installed...\n")
|
||||||
time.sleep(0.3)
|
time.sleep(0.1)
|
||||||
return image
|
return image
|
||||||
|
|
||||||
c, w, textwidth, textheight, = drawer.textbbox(xy = (0, 0), text = text, font = font) # Getting text size, only need the last two values
|
c, w, textwidth, textheight, = drawer.textbbox(xy = (0, 0), text = text, font = font) # Getting text size, only need the last two values
|
||||||
x = imagewidth - textwidth - margin
|
x = imagewidth - textwidth - margin
|
||||||
y = imageheight - textheight - margin
|
y = imageheight - textheight - margin
|
||||||
drawer.text((x, y), text, font = font)
|
|
||||||
|
# thin border
|
||||||
|
drawer.text((x-1, y), text, font=font, fill=(64, 64, 64))
|
||||||
|
drawer.text((x+1, y), text, font=font, fill=(64, 64, 64))
|
||||||
|
drawer.text((x, y-1), text, font=font, fill=(64, 64, 64))
|
||||||
|
drawer.text((x, y+1), text, font=font, fill=(64, 64, 64))
|
||||||
|
# Adding text in the desired color
|
||||||
|
drawer.text((x, y), text, font = font, fill=(255, 255, 255))
|
||||||
|
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue