Release candidate

This commit is contained in:
Mr Finchum 2025-01-27 18:56:11 +01:00
parent 8f539d4097
commit 2b35cbc48b
4 changed files with 175 additions and 82 deletions

View file

@ -26,7 +26,7 @@ build:
- job: gitversion - job: gitversion
artifacts: true artifacts: true
script: script:
- sed -i "s/0.0.1/${GitVersion_MajorMinorPatch}/" src/optima35/__init__.py - sed -i "s/1.0.0/${GitVersion_MajorMinorPatch}/" src/optima35/__init__.py
- cat src/optima35/__init__.py - cat src/optima35/__init__.py
- python3 -m pip install build - python3 -m pip install build
- python3 -m build - python3 -m build

View file

@ -1,5 +1,10 @@
# Changelog # Changelog
## 1.0.0-rc:
### Refactoring
- Added function descriptions for better clarity and maintainability.
- Introduced guidelines for each function, defining objectives and expected behavior.
## 0.12.x ## 0.12.x
### 0.12.2: Bug fixes ### 0.12.2: Bug fixes
- Fixed missing lens in meta data - Fixed missing lens in meta data

View file

@ -1 +1 @@
__version__ = "0.0.1" __version__ = "1.0.0"

View file

@ -22,83 +22,124 @@ class OptimaManager:
data_for_exif["date_time_original"] = new_time.strftime("%Y:%m:%d %H:%M:%S") data_for_exif["date_time_original"] = new_time.strftime("%Y:%m:%d %H:%M:%S")
return data_for_exif return data_for_exif
def process_image(self, # TODO: split into two classes, one for modification for one saving.. def _process_image(
image_input_file, self,
image_output_file, image_input_file: str,
file_type = "jpg", resize: int = None,
quality = 90, watermark: str = None,
compressing = 6, font_size: int = 2,
optimize = False, grayscale: bool = False,
resize = None, brightness: float = None,
watermark = None, contrast: float = None
font_size = 2, ):
grayscale = False, # Restructured by ChatGPT, but had to fix bugs
brightness = None, img = self.image_processor.open_image(image_input_file)
contrast = None, # Apply transformations
dict_for_exif = None,
gps = None,
copy_exif = False,
save = True):
# Partly optimized by ChatGPT
# Open the image file
with self.image_processor.open_image(image_input_file) as img:
processed_img = img
image_name = os.path.basename(image_output_file) # for date adjustment
# Resize
if resize is not None: if resize is not None:
processed_img = self.image_processor.resize_image( print("Resize")
image=processed_img, percent = resize img = self.image_processor.resize_image(img, percent=resize)
)
# Watermark
if watermark is not None: if watermark is not None:
processed_img = self.image_processor.add_watermark( print("Watermark")
processed_img, watermark, int(font_size) img = self.image_processor.add_watermark(img, watermark, font_size)
)
# Grayscale
if grayscale: if grayscale:
processed_img = self.image_processor.grayscale(processed_img) print("Grayscale")
img = self.image_processor.grayscale(img)
# Brightness
if brightness is not None: if brightness is not None:
processed_img = self.image_processor.change_brightness( print("Brightness")
processed_img, brightness img = self.image_processor.change_brightness(img, brightness)
)
# Contrast
if contrast is not None: if contrast is not None:
processed_img = self.image_processor.change_contrast( print("Contrast")
processed_img, contrast img = self.image_processor.change_contrast(img, contrast)
) return img
# EXIF data handling def _handle_exif(
exif_piexif_format = None self,
if dict_for_exif: # todo: maybe move to ui and only accept complete exif dicts.. image,
selected_exif = dict_for_exif file_name,
dict_for_exif: dict = None,
gps: tuple[float, float] = None,
copy_exif: bool = False
):
# Restructured by ChatGPT, but had to fix bugs
# Build or copy EXIF data
if dict_for_exif:
if "date_time_original" in dict_for_exif: if "date_time_original" in dict_for_exif:
selected_exif = self.modify_timestamp_in_exif(selected_exif, image_name) dict_for_exif = self.modify_timestamp_in_exif(dict_for_exif, file_name)
exif_piexif_format = self.exif_handler.build_exif_bytes( exif_data = self.exif_handler.build_exif_bytes(
selected_exif, self.image_processor.get_image_size(processed_img) dict_for_exif, self.image_processor.get_image_size(image)
)
if gps:
exif_data = self.exif_handler.add_geolocation_to_exif(
exif_data, gps[0], gps[1]
)
elif copy_exif:
exif_data = self.exif_handler.get_exif_info(image)
else:
exif_data = None
return exif_data
def process_and_save_image(
self,
image_input_file: str,
image_output_file: str,
file_type: str = "jpg",
quality: int = 90,
compressing: int = 6,
optimize: bool = False,
resize: int = None,
watermark: str = None,
font_size: int = 2,
grayscale: bool = False,
brightness: float = None,
contrast: float = None,
dict_for_exif: dict = None,
gps: tuple[float, float] = None,
copy_exif: bool = False
) -> None:
"""
Processes an image with the given parameters and saves the output to a file.
Args:
image_input_file (str): Path to the input image file.
image_output_file (str): Path to save the processed image.
file_type (str): Output image format ('jpg', 'png'). Defaults to 'jpg'.
quality (int): JPEG quality (1-100). Defaults to 90.
compressing (int): PNG compression level (0-9). Defaults to 6.
optimize (bool): Optimize image for smaller file size. Defaults to False.
resize (int, optional): Resize percentage. Defaults to None.
watermark (str, optional): Watermark text to add. Defaults to None.
font_size (int): Font size for the watermark. Defaults to 2.
grayscale (bool): Convert image to grayscale. Defaults to False.
brightness (float, optional): Adjust brightness (e.g., 1.2 for 20% brighter). Defaults to None.
contrast (float, optional): Adjust contrast (e.g., 1.5 for 50% higher contrast). Defaults to None.
dict_for_exif (dict, optional): EXIF metadata to insert. Defaults to None.
gps (tuple[float, float], optional): GPS coordinates (latitude, longitude). Defaults to None.
copy_exif (bool): Copy EXIF metadata from the input image. Defaults to False.
Returns:
None
"""
# Restructured by ChatGPT
processed_img = self._process_image(
image_input_file,
resize,
watermark,
font_size,
grayscale,
brightness,
contrast,
) )
# GPS data # Handle EXIF metadata
if gps is not None: exif_piexif_format = self._handle_exif(
latitude = float(gps[0]) image = processed_img,
longitude = float(gps[1]) file_name = image_output_file,
exif_piexif_format = self.exif_handler.add_geolocation_to_exif(exif_piexif_format, latitude, longitude) dict_for_exif = dict_for_exif,
gps = gps,
copy_exif = copy_exif
)
# Copy EXIF data if selected, and ensure size is correct in exif data # Save the image
elif copy_exif:
try:
og_exif = self.exif_handler.get_exif_info(img)
og_exif["Exif"][40962], og_exif["Exif"][40963] = self.image_processor.get_image_size(processed_img)
exif_piexif_format = og_exif
except Exception:
print("Copying EXIF data selected, but no EXIF data is available in the original image file.")
if save:
# Save the processed image
self.image_processor.save_image( self.image_processor.save_image(
image = processed_img, image = processed_img,
path = image_output_file, path = image_output_file,
@ -106,12 +147,59 @@ class OptimaManager:
file_type = file_type, file_type = file_type,
jpg_quality = quality, jpg_quality = quality,
png_compressing = compressing, png_compressing = compressing,
optimize = optimize optimize = optimize,
)
def process_image_object(
self,
image_input_file: str,
resize: int = None,
watermark: str = None,
font_size: int = 2,
grayscale: bool = False,
brightness: float = None,
contrast: float = None
):
"""
Processes an image with the given parameters and returns the modified image object.
Args:
image_input_file (str): Path to the input image file.
resize (int, optional): Resize percentage. Defaults to None.
watermark (str, optional): Watermark text to add. Defaults to None.
font_size (int): Font size for the watermark. Defaults to 2.
grayscale (bool): Convert image to grayscale. Defaults to False.
brightness (float, optional): Adjust brightness. Defaults to None.
contrast (float, optional): Adjust contrast. Defaults to None.
Returns:
Image: The processed image object.
"""
# Restructured by ChatGPT
processed_img = self._process_image(
image_input_file,
resize,
watermark,
font_size,
grayscale,
brightness,
contrast,
) )
else:
return self.image_processor.convert_pil_to_qtimage(processed_img) return self.image_processor.convert_pil_to_qtimage(processed_img)
def insert_dict_to_image(self, exif_dict, image_path, gps = None): def insert_exif_to_image(self, exif_dict: dict, image_path: str, gps: tuple[float, float] = None) -> None:
"""
Inserts EXIF metadata into an image.
Args:
exif_data (dict): A dictionary containing EXIF metadata as key-value pairs (e.g., strings, integers).
image_path (str): Absolute path to the target image file.
gps (tuple[float, float], optional): GPS coordinates as a tuple (latitude, longitude). Defaults to None.
Returns:
None: The function modifies the image file in place.
"""
# Restructured by ChatGPT
image_name, ending = os.path.splitext(os.path.basename(image_path)) image_name, ending = os.path.splitext(os.path.basename(image_path))
img = self.image_processor.open_image(image_path) img = self.image_processor.open_image(image_path)
selected_exif = exif_dict selected_exif = exif_dict