File size: 3,658 Bytes
8ba64a4
9645c29
 
 
 
8ba64a4
 
 
 
 
 
 
 
 
 
 
 
9645c29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import base64
import io
from PIL import Image

import requests


def get_image_data(image_path):
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode("utf-8")
    return image_data


def get_data_format(image_path):
    image_format = image_path.split(".")[-1]
    if image_format == "jpg":
        image_format = "jpeg"
    return


def get_image_base64_and_type(image_url: str, max_dimension: int = 2048) -> tuple[str | None, str | None]:
    try:
        # --- 1. Download the image ---
        response = requests.get(image_url, stream=True, timeout=20) # Added timeout
        response.raise_for_status()  # Raise an exception for bad status codes (4xx or 5xx)
    
        # Check content type
        content_type = response.headers.get('content-type')
        allowed_types = ['image/png', 'image/jpeg', 'image/webp', 'image/gif']
        if not content_type or content_type not in allowed_types:
            raise ValueError(f"Unsupported image type: {content_type}. Expected one of {allowed_types}.")

        # --- 2. Open the image using Pillow ---
        image_data = response.content
        img = Image.open(io.BytesIO(image_data))

        # Check if the image is animated (GIF)
        if img.format == 'GIF' and getattr(img, 'is_animated', False):
            raise ValueError("Animated GIFs are not supported.")

        # --- 3. Check dimensions and resize if necessary ---
        width, height = img.size
        longest_dim = max(width, height)

        if longest_dim > max_dimension:
            # print(f"Image dimensions ({width}x{height}) exceed max dimension ({max_dimension}). Resizing...")
            if width > height:
                # Width is the longest dimension
                new_width = max_dimension
                new_height = int(height * (max_dimension / width))
            else:
                # Height is the longest or they are equal
                new_height = max_dimension
                new_width = int(width * (max_dimension / height))

            # Resize the image - Use Resampling.LANCZOS for high-quality downscaling
            img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
            # print(f"Image resized to: {img.size}"

        width, height = img.size
        shortest_dim = min(width, height)

        if shortest_dim > 768:
            if width < height:
                new_width = 768
                new_height = int(height * (768 / width))
            else:
                new_height = 768
                new_width = int(width * (768 / height))
            img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
        

        # --- 4. Save the image to a byte buffer ---
        # We need to save the potentially modified image back to bytes
        buffer = io.BytesIO()
        # Save with the JPG format. Handle potential format issues.
        try:
            img_format = 'JPEG'
            img.save(buffer, format=img_format, quality=100) 
        except Exception as save_err:
            try:
                # Fallback to PNG if original format saving fails
                img_format = 'PNG'
                img.save(buffer, format=img_format)
            except Exception as png_save_err:
                raise Exception(f"Failed to save image in PNG format. Error: {png_save_err}")

        image_bytes = buffer.getvalue()

        # --- 5. Encode the image bytes to base64 ---
        base64_encoded_image = base64.b64encode(image_bytes).decode('utf-8')

        return base64_encoded_image, img_format

    except Exception as e:
        raise ValueError(f"Invalid image URL: {e}")