perf: optimize PNG compression only on final operations

- Add is_final parameter to trim_whitespace and convert_to_monochrome
- Only optimize PNGs on the final operation of each level
- Remove optimization from extract command
- Level 1: optimize in trim_whitespace
- Level 2: optimize in convert_to_monochrome
- Level 3: defer to optipng
This commit is contained in:
Esa Kataja
2024-12-03 22:23:54 +02:00
parent 75dc1c3e2c
commit a979712c8c
+15 -8
View File
@@ -81,13 +81,14 @@ def extract(input_pdf):
print(f"Extracted {len(pages)} pages to {temp_dir}/") print(f"Extracted {len(pages)} pages to {temp_dir}/")
def trim_whitespace(image_path: str) -> bool: def trim_whitespace(image_path: str, is_final: bool = False) -> bool:
"""Remove white space from around the image. """Remove white space from around the image.
Handles both RGB and RGBA images, treating transparent pixels as white. Handles both RGB and RGBA images, treating transparent pixels as white.
Args: Args:
image_path: Path to the image file image_path: Path to the image file
is_final: Whether this is the final operation on the image
Returns: Returns:
bool: True if successful, False otherwise bool: True if successful, False otherwise
@@ -124,8 +125,8 @@ def trim_whitespace(image_path: str) -> bool:
# Crop the original image (preserving transparency) # Crop the original image (preserving transparency)
cropped = image.crop((x1, y1, x2, y2)) cropped = image.crop((x1, y1, x2, y2))
# Save the cropped image # Save the cropped image, optimizing only if this is the final operation
cropped.save(image_path, "PNG", optimize=False) cropped.save(image_path, "PNG", optimize=is_final)
return True return True
except Exception as e: except Exception as e:
@@ -206,11 +207,15 @@ def deskew():
else: else:
print(" No line segments detected") print(" No line segments detected")
def convert_to_monochrome(image_path: str) -> bool: def convert_to_monochrome(image_path: str, is_final: bool = False) -> bool:
"""Convert image to 1-bit monochrome. """Convert image to 1-bit monochrome.
Handles RGBA images by converting transparent pixels to white before thresholding. Handles RGBA images by converting transparent pixels to white before thresholding.
Args:
image_path: Path to the image file
is_final: Whether this is the final operation on the image
Returns: Returns:
bool: True if successful, False otherwise bool: True if successful, False otherwise
""" """
@@ -243,8 +248,8 @@ def convert_to_monochrome(image_path: str) -> bool:
# Convert to 1-bit using threshold # Convert to 1-bit using threshold
image = image.point(lambda x: 255 if x > settings.MONOCHROME_THRESHOLD else 0, '1') image = image.point(lambda x: 255 if x > settings.MONOCHROME_THRESHOLD else 0, '1')
# Save the monochrome image # Save the monochrome image, optimizing only if this is the final operation
image.save(image_path, "PNG", optimize=False) image.save(image_path, "PNG", optimize=is_final)
return True return True
except Exception as e: except Exception as e:
@@ -312,7 +317,8 @@ def optimize(level):
print("\nTrimming whitespace from images...") print("\nTrimming whitespace from images...")
for i, file_path in enumerate(temp_files, 1): for i, file_path in enumerate(temp_files, 1):
print(f"[{i}/{total_files}] Processing {os.path.basename(file_path)}...", end='', flush=True) print(f"[{i}/{total_files}] Processing {os.path.basename(file_path)}...", end='', flush=True)
if trim_whitespace(file_path): # Only optimize if this is the final step (level 1)
if trim_whitespace(file_path, is_final=(opt_level == OptimizationLevel.TRIM)):
successful['trim'] += 1 successful['trim'] += 1
print(" ") print(" ")
else: else:
@@ -323,7 +329,8 @@ def optimize(level):
print("\nConverting to monochrome...") print("\nConverting to monochrome...")
for i, file_path in enumerate(temp_files, 1): for i, file_path in enumerate(temp_files, 1):
print(f"[{i}/{total_files}] Converting {os.path.basename(file_path)}...", end='', flush=True) print(f"[{i}/{total_files}] Converting {os.path.basename(file_path)}...", end='', flush=True)
if convert_to_monochrome(file_path): # Only optimize if this is the final step (level 2)
if convert_to_monochrome(file_path, is_final=(opt_level == OptimizationLevel.MONOCHROME)):
successful['monochrome'] += 1 successful['monochrome'] += 1
print(" ") print(" ")
else: else: