← back to Resize It

scripts/analyze_proportions.py

116 lines

#!/usr/bin/env python3
"""
AI-powered image proportion analysis
Analyzes images to detect distortion or incorrect proportions
"""

import sys
import json
import base64
import argparse
from pathlib import Path


def encode_image_to_base64(image_path):
    """Encode image to base64 for API transmission"""
    with open(image_path, 'rb') as img_file:
        return base64.b64encode(img_file.read()).decode('utf-8')


def get_image_mime_type(image_path):
    """Determine MIME type from file extension"""
    suffix = Path(image_path).suffix.lower()
    mime_types = {
        '.jpg': 'image/jpeg',
        '.jpeg': 'image/jpeg',
        '.png': 'image/png',
        '.gif': 'image/gif',
        '.webp': 'image/webp',
        '.bmp': 'image/bmp'
    }
    return mime_types.get(suffix, 'image/jpeg')


def analyze_image_proportions_prompt(original_path=None, resized_path=None):
    """
    Generate analysis prompt for Claude/Gemini to analyze image proportions

    Returns:
        dict with prompt and image data for API call
    """

    analysis_request = {
        "task": "image_proportion_analysis",
        "instruction": """Analyze the provided image(s) for proportion and distortion issues.

Please examine:
1. **Aspect Ratio**: Are objects in the image proportioned correctly? Do circles look like circles, squares like squares?
2. **Distortion**: Is there any stretching, squashing, or warping visible?
3. **Expected Proportions**: Do people, objects, or text appear at natural proportions?
4. **Comparison** (if two images provided): How does the resized image compare to the original? Is there any introduced distortion?

Provide your analysis in JSON format with these fields:
{
  "has_distortion": boolean,
  "distortion_type": "horizontal_stretch" | "vertical_stretch" | "horizontal_squash" | "vertical_squash" | "none" | "unknown",
  "severity": "none" | "minor" | "moderate" | "severe",
  "confidence": float (0-1),
  "observations": [list of specific observations],
  "recommendation": "string with recommended action"
}

Be thorough but objective in your analysis."""
    }

    images = []

    if original_path:
        images.append({
            "label": "original",
            "path": original_path,
            "base64": encode_image_to_base64(original_path),
            "mime_type": get_image_mime_type(original_path)
        })

    if resized_path:
        images.append({
            "label": "resized",
            "path": resized_path,
            "base64": encode_image_to_base64(resized_path),
            "mime_type": get_image_mime_type(resized_path)
        })

    analysis_request["images"] = images

    return analysis_request


def main():
    parser = argparse.ArgumentParser(
        description='Prepare image proportion analysis for AI (Claude/Gemini)'
    )
    parser.add_argument('--original', help='Original image path')
    parser.add_argument('--resized', help='Resized image path')
    parser.add_argument('--output-format', choices=['json', 'prompt'], default='json',
                        help='Output format: json (full data) or prompt (text prompt only)')

    args = parser.parse_args()

    if not args.original and not args.resized:
        print("Error: Must provide at least one image (--original or --resized)")
        sys.exit(1)

    # Generate analysis request
    analysis_data = analyze_image_proportions_prompt(args.original, args.resized)

    if args.output_format == 'json':
        # Output full JSON (includes base64 encoded images)
        print(json.dumps(analysis_data, indent=2))
    else:
        # Output just the prompt text
        print(analysis_data["instruction"])


if __name__ == '__main__':
    main()