from django.core.files.base import ContentFile from django.utils.text import slugify from ..models.images import ImageLibrary import os try: import requests except ImportError: requests = None from PIL import Image as PILImage def create_image_from_file( file_path, name, description="", alt_text="", category="other", tags="" ): """ Create an ImageLibrary entry from a local file. Args: file_path: Path to the image file name: Name for the image description: Optional description alt_text: Alternative text for accessibility category: Image category tags: Comma-separated tags Returns: ImageLibrary instance or None if failed """ try: if not os.path.exists(file_path): print(f"File not found: {file_path}") return None # Generate slug slug = slugify(name) # Check if image already exists if ImageLibrary.objects.filter(slug=slug).exists(): print(f"Image with slug '{slug}' already exists") return ImageLibrary.objects.get(slug=slug) # Create image library entry image_lib = ImageLibrary( name=name, slug=slug, description=description, alt_text=alt_text or name, category=category, tags=tags, ) # Read and save the image file with open(file_path, "rb") as f: image_lib.image.save( os.path.basename(file_path), ContentFile(f.read()), save=True ) print(f"Created image library entry: {name}") return image_lib except Exception as e: print(f"Error creating image library entry: {e}") return None def create_image_from_url( url, name, description="", alt_text="", category="other", tags="" ): """ Create an ImageLibrary entry from a URL. Args: url: URL to the image name: Name for the image description: Optional description alt_text: Alternative text for accessibility category: Image category tags: Comma-separated tags Returns: ImageLibrary instance or None if failed """ if requests is None: print("requests library is not installed. Cannot download from URL.") return None try: # Generate slug slug = slugify(name) # Check if image already exists if ImageLibrary.objects.filter(slug=slug).exists(): print(f"Image with slug '{slug}' already exists") return ImageLibrary.objects.get(slug=slug) # Download the image response = requests.get(url) response.raise_for_status() # Create image library entry image_lib = ImageLibrary( name=name, slug=slug, description=description, alt_text=alt_text or name, category=category, tags=tags, ) # Save the image filename = url.split("/")[-1] if "?" in filename: filename = filename.split("?")[0] image_lib.image.save(filename, ContentFile(response.content), save=True) print(f"Created image library entry from URL: {name}") return image_lib except Exception as e: print(f"Error creating image library entry from URL: {e}") return None def get_image_by_slug(slug): """ Get an image from the library by slug. Args: slug: Slug of the image Returns: ImageLibrary instance or None if not found """ try: return ImageLibrary.objects.get(slug=slug) except ImageLibrary.DoesNotExist: return None def get_images_by_category(category): """ Get all images from a specific category. Args: category: Category name Returns: QuerySet of ImageLibrary instances """ return ImageLibrary.objects.filter(category=category) def get_images_by_tags(tags): """ Get images that contain any of the specified tags. Args: tags: List of tags or comma-separated string Returns: QuerySet of ImageLibrary instances """ if isinstance(tags, str): tags = [tag.strip() for tag in tags.split(",")] from django.db.models import Q query = Q() for tag in tags: query |= Q(tags__icontains=tag) return ImageLibrary.objects.filter(query).distinct() def cleanup_unused_images(): """ Find and optionally clean up unused images from the library. Returns: List of ImageLibrary instances with usage_count = 0 """ unused_images = ImageLibrary.objects.filter(usage_count=0) print(f"Found {unused_images.count()} unused images:") for image in unused_images: print(f" - {image.name} ({image.slug})") return unused_images def optimize_image(image_library_instance, max_width=1920, max_height=1080, quality=85): """ Optimize an image in the library by resizing and compressing. Args: image_library_instance: ImageLibrary instance max_width: Maximum width in pixels max_height: Maximum height in pixels quality: JPEG quality (1-100) Returns: bool: True if optimization was successful """ try: if not image_library_instance.image: return False # Open the image with PILImage.open(image_library_instance.image.path) as img: # Calculate new dimensions while maintaining aspect ratio ratio = min(max_width / img.width, max_height / img.height) if ratio < 1: # Only resize if image is larger than max dimensions new_width = int(img.width * ratio) new_height = int(img.height * ratio) # Resize the image img_resized = img.resize( (new_width, new_height), PILImage.Resampling.LANCZOS ) # Save the optimized image img_resized.save( image_library_instance.image.path, format="JPEG", quality=quality, optimize=True, ) # Update the image properties image_library_instance._update_image_properties() print(f"Optimized image: {image_library_instance.name}") return True else: print(f"Image already optimal: {image_library_instance.name}") return True except Exception as e: print(f"Error optimizing image {image_library_instance.name}: {e}") return False