Merge branch 'merge/from_forked' into 'main'

Merge image_handler from TUI fork

See merge request python_projects3802849/optima-35!4
This commit is contained in:
Mr Finchum 2024-12-28 10:51:18 +00:00
commit c36ab9b733
5 changed files with 26 additions and 16 deletions

View file

@ -1,6 +1,9 @@
# Changelog # Changelog
## 0.2.x ## 0.2.x
### 0.2.1: Merge from TUI fork
- Ensure watermark is white with black borders.
### 0.2.0 ### 0.2.0
- **Cleaner folder structure** - **Cleaner folder structure**
- Moving files with classes to different folder to keep project cleaner. - Moving files with classes to different folder to keep project cleaner.

View file

@ -6,8 +6,6 @@
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. **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**
@ -15,25 +13,24 @@ The primary focus is on building a terminal-based user interface (TUI). Initiall
- 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**
![my-gif](https://gitlab.com/python_projects3802849/optima-35/-/raw/main/media/v0.1.0-demo.gif?ref_type=heads) ![my-gif](https://gitlab.com/python_projects3802849/optima-35/-/raw/main/media/v0.1.0-demo.gif?ref_type=heads)
## Dependencies ## Dependencies
To run **OPTIMA-35**, 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.

View file

@ -1,3 +1,4 @@
# Example file. You can add and remove entries here.
make: make:
- Nikon - Nikon
model: model:

View file

@ -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"
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?")

View 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