diff --git a/pdf_cleaner.py b/pdf_cleaner.py index d115c2d..95d9d1a 100755 --- a/pdf_cleaner.py +++ b/pdf_cleaner.py @@ -96,12 +96,18 @@ def trim_whitespace(image_path: str) -> bool: # Open image with PIL image = Image.open(image_path) - # Convert to grayscale if not already - if image.mode != 'L': - image = image.convert('L') + # Create flattened version with white background for finding bounds + flattened = Image.new('RGB', image.size, 'white') + if image.mode == 'RGBA': + flattened.paste(image, mask=image.split()[3]) + else: + flattened.paste(image) + + # Convert to grayscale for finding bounds + flattened = flattened.convert('L') # Get the bounding box of non-white pixels - bbox = image.getbbox() + bbox = flattened.getbbox() if not bbox: print(f"Warning: No content found in {image_path}") return False @@ -115,11 +121,11 @@ def trim_whitespace(image_path: str) -> bool: x2 = min(width, x2 + padding) y2 = min(height, y2 + padding) - # Crop the image - image = image.crop((x1, y1, x2, y2)) + # Crop the original image (preserving transparency) + cropped = image.crop((x1, y1, x2, y2)) - # Save the image - image.save(image_path, "PNG", optimize=False) + # Save the cropped image + cropped.save(image_path, "PNG", optimize=False) return True except Exception as e: @@ -203,25 +209,44 @@ def deskew(): def convert_to_monochrome(image_path: str) -> bool: """Convert image to 1-bit monochrome. + Handles RGBA images by converting transparent pixels to white before thresholding. + Returns: bool: True if successful, False otherwise """ try: - # Read the image - img = cv2.imread(image_path) - if img is None: - print(f"Warning: Could not read image {image_path}") - return False + # Open image with PIL + image = Image.open(image_path) + + # Convert to RGBA if not already + if image.mode != 'RGBA': + image = image.convert('RGBA') + + # Get the image data as a list of pixels + data = image.getdata() + + # Create new image data, replacing transparent pixels with white + new_data = [] + for item in data: + # If pixel is transparent (alpha < 128), make it white + if item[3] < 128: + new_data.append((255, 255, 255, 255)) + else: + new_data.append(item) + + # Create new image with modified data + image.putdata(new_data) # Convert to grayscale - gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + image = image.convert('L') - # Apply threshold - _, mono = cv2.threshold(gray, settings.MONOCHROME_THRESHOLD, 255, cv2.THRESH_BINARY) + # Convert to 1-bit using threshold + image = image.point(lambda x: 255 if x > settings.MONOCHROME_THRESHOLD else 0, '1') # Save the monochrome image - cv2.imwrite(image_path, mono) + image.save(image_path, "PNG", optimize=False) return True + except Exception as e: print(f"Error converting to monochrome {image_path}: {str(e)}") return False