# sumaexcel/image.py from typing import Optional, Tuple, Union from pathlib import Path import os from PIL import Image from openpyxl.drawing.image import Image as XLImage from openpyxl.worksheet.worksheet import Worksheet class ImageManager: """Handle image operations in Excel""" def __init__(self, worksheet: Worksheet): self.worksheet = worksheet self.temp_dir = Path("/tmp/sumaexcel_images") self.temp_dir.mkdir(parents=True, exist_ok=True) def add_image( self, image_path: Union[str, Path], cell_coordinates: Tuple[int, int], size: Optional[Tuple[int, int]] = None, keep_aspect_ratio: bool = True, anchor_type: str = 'absolute' ) -> None: """Add image to worksheet at specified position""" # Convert path to Path object image_path = Path(image_path) # Open and process image with Image.open(image_path) as img: # Get original size orig_width, orig_height = img.size # Calculate new size if specified if size: target_width, target_height = size if keep_aspect_ratio: ratio = min(target_width/orig_width, target_height/orig_height) target_width = int(orig_width * ratio) target_height = int(orig_height * ratio) # Resize image img = img.resize((target_width, target_height), Image.LANCZOS) # Save temporary resized image temp_path = self.temp_dir / f"temp_{image_path.name}" img.save(temp_path) image_path = temp_path # Create Excel image object excel_image = XLImage(str(image_path)) # Add to worksheet self.worksheet.add_image(excel_image, anchor=f'{cell_coordinates[0]}{cell_coordinates[1]}') def add_image_absolute( self, image_path: Union[str, Path], position: Tuple[int, int], size: Optional[Tuple[int, int]] = None ) -> None: """Add image with absolute positioning""" excel_image = XLImage(str(image_path)) if size: excel_image.width, excel_image.height = size excel_image.anchor = 'absolute' excel_image.top, excel_image.left = position self.worksheet.add_image(excel_image) def cleanup(self) -> None: """Clean up temporary files""" for file in self.temp_dir.glob("temp_*"): file.unlink() def __del__(self): """Cleanup on object destruction""" self.cleanup()