Moving file
This commit is contained in:
parent
5c61ff0587
commit
41a9c5190e
4 changed files with 0 additions and 250 deletions
|
@ -1,28 +0,0 @@
|
||||||
make:
|
|
||||||
- Nikon
|
|
||||||
model:
|
|
||||||
- FG
|
|
||||||
- F50
|
|
||||||
lens:
|
|
||||||
- Nikon LENS SERIES E 50mm
|
|
||||||
- AF NIKKOR 35-70mm
|
|
||||||
iso: # Numeric values cause errors with simple_term_menu and must be quoted. This issue will be resolved with the future UI switch.
|
|
||||||
- "100"
|
|
||||||
- "200"
|
|
||||||
- "400"
|
|
||||||
- "800"
|
|
||||||
- "1000"
|
|
||||||
- "1600"
|
|
||||||
- "3200"
|
|
||||||
image_description:
|
|
||||||
- ILFORD DELTA 3200
|
|
||||||
- ILFORD ILFOCOLOR
|
|
||||||
- LomoChrome Turquoise
|
|
||||||
user_comment:
|
|
||||||
- Scanner.NORITSU-KOKI
|
|
||||||
- Scanner.NA
|
|
||||||
artist:
|
|
||||||
- Mr. Finchum
|
|
||||||
copyright_info:
|
|
||||||
- All Rights Reserved
|
|
||||||
- No Copyright
|
|
115
image_handler.py
115
image_handler.py
|
@ -1,115 +0,0 @@
|
||||||
from PIL import Image, ImageDraw, ImageFont, ImageEnhance
|
|
||||||
import piexif
|
|
||||||
import time
|
|
||||||
|
|
||||||
class ImageProcessor:
|
|
||||||
"""Functions using pillow are in here."""
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def open_image(self, path):
|
|
||||||
"""Open an image from path, returns image object."""
|
|
||||||
return Image.open(path)
|
|
||||||
|
|
||||||
def get_image_size(self, image):
|
|
||||||
"""Simply get image size."""
|
|
||||||
return image.size
|
|
||||||
|
|
||||||
def grayscale(self, image):
|
|
||||||
"""Change to grayscale"""
|
|
||||||
return image.convert("L")
|
|
||||||
|
|
||||||
def change_contrast(self, image, change):
|
|
||||||
enhancer = ImageEnhance.Contrast(image)
|
|
||||||
new_img = enhancer.enhance(1 + (change/100))
|
|
||||||
return new_img
|
|
||||||
|
|
||||||
def change_brightness(self, image, change):
|
|
||||||
enhancer = ImageEnhance.Brightness(image)
|
|
||||||
new_img = enhancer.enhance(1 + (change/100))
|
|
||||||
return new_img
|
|
||||||
|
|
||||||
def resize_image(self, image, percent, resample = True):
|
|
||||||
"""Resize an image by giving a percent."""
|
|
||||||
new_size = tuple(int(x * (percent / 100)) for x in image.size)
|
|
||||||
if resample:
|
|
||||||
resized_image = image.resize(new_size)
|
|
||||||
else:
|
|
||||||
resized_image = image.resize((new_size),resample=Image.Resampling.NEAREST)
|
|
||||||
return resized_image
|
|
||||||
|
|
||||||
def add_watermark(self, image, text, font_size_scale = 70):
|
|
||||||
drawer = ImageDraw.Draw(image)
|
|
||||||
imagewidth, imageheight = image.size
|
|
||||||
margin = (imageheight / 100 ) * 2 # margin dynamic, 2% of image size
|
|
||||||
font_size = imagewidth / font_size_scale # Scaling the font size
|
|
||||||
try: # Try loading front, if notaviable return unmodified image
|
|
||||||
font = ImageFont.truetype("OpenDyslexic3-Regular.ttf", font_size)
|
|
||||||
except:
|
|
||||||
print("Error loading font for watermark, please ensure font is installed...\n")
|
|
||||||
time.sleep(0.3)
|
|
||||||
return image
|
|
||||||
|
|
||||||
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
|
|
||||||
y = imageheight - textheight - margin
|
|
||||||
drawer.text((x, y), text, font = font)
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
def save_image(self, image, path, file_type, jpg_quality, png_compressing, optimize, exif_data = None):
|
|
||||||
# partly optimized by chatGPT
|
|
||||||
"""
|
|
||||||
Save an image to the specified path with optional EXIF data and optimization.
|
|
||||||
"""
|
|
||||||
file_type = file_type.lower()
|
|
||||||
save_params = {"optimize": optimize}
|
|
||||||
# Add file-specific parameters
|
|
||||||
if file_type == "jpg":
|
|
||||||
save_params["quality"] = jpg_quality
|
|
||||||
elif file_type == "png":
|
|
||||||
save_params["compress_level"] = png_compressing
|
|
||||||
elif file_type not in ["webp", "jpg", "png"]:
|
|
||||||
input(f"Type: {file_type} is not supported. Press Enter to continue...")
|
|
||||||
return
|
|
||||||
# Add EXIF data if available
|
|
||||||
if exif_data is not None:
|
|
||||||
save_params["exif"] = piexif.dump(exif_data)
|
|
||||||
if file_type == "webp":
|
|
||||||
print("File format webp does not support all exif features, some information might get lost...\n")
|
|
||||||
time.sleep(0.1)
|
|
||||||
try:
|
|
||||||
image.save(f"{path}.{file_type}", **save_params)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Failed to save image: {e}")
|
|
||||||
|
|
||||||
class ExifHandler:
|
|
||||||
"""Function using piexif are here."""
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_exif_info(self, image):
|
|
||||||
return(piexif.load(image.info['exif']))
|
|
||||||
|
|
||||||
def build_exif_dict(self, user_data, imagesize):
|
|
||||||
"""Build a piexif-compatible EXIF dictionary from user data."""
|
|
||||||
# Mostly made by ChatGPT, some adjustment
|
|
||||||
zeroth_ifd = {
|
|
||||||
piexif.ImageIFD.Make: user_data["make"],
|
|
||||||
piexif.ImageIFD.Model: user_data["model"],
|
|
||||||
piexif.ImageIFD.Software: user_data["software"],
|
|
||||||
piexif.ImageIFD.Copyright: user_data["copyright_info"],
|
|
||||||
piexif.ImageIFD.Artist: user_data["artist"],
|
|
||||||
piexif.ImageIFD.ImageDescription: user_data["image_description"],
|
|
||||||
piexif.ImageIFD.XResolution: (72, 1),
|
|
||||||
piexif.ImageIFD.YResolution: (72, 1),
|
|
||||||
}
|
|
||||||
exif_ifd = {
|
|
||||||
piexif.ExifIFD.UserComment: user_data["user_comment"],
|
|
||||||
piexif.ExifIFD.ISOSpeedRatings: int(user_data["iso"]),
|
|
||||||
piexif.ExifIFD.PixelXDimension: imagesize[0],
|
|
||||||
piexif.ExifIFD.PixelYDimension: imagesize[1],
|
|
||||||
}
|
|
||||||
if "date_time_original" in user_data:
|
|
||||||
exif_ifd[piexif.ExifIFD.DateTimeOriginal] = user_data["date_time_original"].encode("utf-8")
|
|
||||||
return {"0th": zeroth_ifd, "Exif": exif_ifd}
|
|
60
tui.py
60
tui.py
|
@ -1,60 +0,0 @@
|
||||||
from simple_term_menu import TerminalMenu
|
|
||||||
|
|
||||||
class SimpleTUI:
|
|
||||||
"""TUI parts using library simple_term_menu"""
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def choose_menu(self, menu_title, choices):
|
|
||||||
""" Dynamic function to display content of a list and returnes which was selected."""
|
|
||||||
menu_options = choices
|
|
||||||
menu = TerminalMenu(
|
|
||||||
menu_entries = menu_options,
|
|
||||||
title = menu_title,
|
|
||||||
menu_cursor = "> ",
|
|
||||||
menu_cursor_style = ("fg_gray", "bold"),
|
|
||||||
menu_highlight_style = ("bg_gray", "fg_black"),
|
|
||||||
cycle_cursor = True,
|
|
||||||
clear_screen = False
|
|
||||||
)
|
|
||||||
menu.show()
|
|
||||||
return menu.chosen_menu_entry
|
|
||||||
|
|
||||||
def multi_select_menu(self, menu_title, choices):
|
|
||||||
""" Dynamic function to display content of a list and returnes which was selected."""
|
|
||||||
menu_options = choices
|
|
||||||
menu = TerminalMenu(
|
|
||||||
menu_entries = menu_options,
|
|
||||||
title = menu_title,
|
|
||||||
multi_select=True,
|
|
||||||
show_multi_select_hint=True,
|
|
||||||
menu_cursor_style = ("fg_gray", "bold"),
|
|
||||||
menu_highlight_style = ("bg_gray", "fg_black"),
|
|
||||||
cycle_cursor = True,
|
|
||||||
clear_screen = False
|
|
||||||
)
|
|
||||||
menu.show()
|
|
||||||
choisen_values = menu.chosen_menu_entries
|
|
||||||
|
|
||||||
if choisen_values == None:
|
|
||||||
print("Exiting...")
|
|
||||||
exit()
|
|
||||||
else:
|
|
||||||
return menu.chosen_menu_entries
|
|
||||||
|
|
||||||
def yes_no_menu(self, message): # oh
|
|
||||||
menu_options = ["[y] yes", "[n] no"]
|
|
||||||
menu = TerminalMenu(
|
|
||||||
menu_entries = menu_options,
|
|
||||||
title = f"{message}",
|
|
||||||
menu_cursor = "> ",
|
|
||||||
menu_cursor_style = ("fg_red", "bold"),
|
|
||||||
menu_highlight_style = ("bg_gray", "fg_black"),
|
|
||||||
cycle_cursor = True,
|
|
||||||
clear_screen = False
|
|
||||||
)
|
|
||||||
menu_entry_index = menu.show()
|
|
||||||
if menu_entry_index == 0:
|
|
||||||
return True
|
|
||||||
elif menu_entry_index == 1:
|
|
||||||
return False
|
|
47
utility.py
47
utility.py
|
@ -1,47 +0,0 @@
|
||||||
import yaml
|
|
||||||
|
|
||||||
class Utilities:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def read_yaml(self, yaml_file):
|
|
||||||
try:
|
|
||||||
with open(yaml_file, "r") as file:
|
|
||||||
data = yaml.safe_load(file)
|
|
||||||
return data
|
|
||||||
except (FileNotFoundError, PermissionError) as e:
|
|
||||||
print(f"Error loading settings file: {e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
def write_yaml(self, yaml_file, data):
|
|
||||||
try:
|
|
||||||
with open(yaml_file, "w") as file:
|
|
||||||
yaml.dump(data, file)
|
|
||||||
except PermissionError as e:
|
|
||||||
print(f"Error saving setings: {e}")
|
|
||||||
|
|
||||||
def yes_no(self, str):
|
|
||||||
"""Ask user y/n question"""
|
|
||||||
while True:
|
|
||||||
choice = input(f"{str} (y/n): ")
|
|
||||||
if choice == "y":
|
|
||||||
return True
|
|
||||||
elif choice == "n":
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
print("Not a valid option, try again.")
|
|
||||||
|
|
||||||
def progress_bar(self, current, total, barsize = 50):
|
|
||||||
if current > total:
|
|
||||||
print("\033[91mThis bar has exceeded its limits!\033[0m Maybe the current value needs some restraint?")
|
|
||||||
print(f"{(current - total) * '\033[92mHonk, Honk!\033[0m '}")
|
|
||||||
return
|
|
||||||
progress = int((barsize / total) * current)
|
|
||||||
rest = barsize - progress
|
|
||||||
if rest <= 2: rest = 0
|
|
||||||
# Determine the number of digits in total
|
|
||||||
total_digits = len(str(total))
|
|
||||||
# Format current with leading zeros
|
|
||||||
current_formatted = f"{current:0{total_digits}}"
|
|
||||||
print(f"{current_formatted}|{progress * '-'}>{rest * ' '}|{total}", end="\r")
|
|
||||||
if current == total: print("")
|
|
Loading…
Add table
Add a link
Reference in a new issue