File size: 2,927 Bytes
4834935
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""
Utility functions for the Qwen Image Editor application.
"""

import io
import base64
import numpy as np
from PIL import Image
from typing import Optional, Tuple


def image_to_bytes(img: Image.Image, format: str = "PNG") -> bytes:
    """
    Convert PIL Image to bytes.
    
    Args:
        img: PIL Image object
        format: Output format (PNG, JPEG, etc.)
    
    Returns:
        Image as bytes
    """
    buffer = io.BytesIO()
    img.save(buffer, format=format)
    buffer.seek(0)
    return buffer.getvalue()


def bytes_to_image(data: bytes) -> Image.Image:
    """
    Convert bytes to PIL Image.
    
    Args:
        data: Image data as bytes
    
    Returns:
        PIL Image object
    """
    return Image.open(io.BytesIO(data))


def image_to_base64(img: Image.Image) -> str:
    """
    Convert PIL Image to base64 string.
    
    Args:
        img: PIL Image object
    
    Returns:
        Base64 encoded string
    """
    buffer = io.BytesIO()
    img.save(buffer, format="PNG")
    return base64.b64encode(buffer.getvalue()).decode()


def base64_to_image(b64: str) -> Image.Image:
    """
    Convert base64 string to PIL Image.
    
    Args:
        b64: Base64 encoded string
    
    Returns:
        PIL Image object
    """
    return Image.open(io.BytesIO(base64.b64decode(b64)))


def get_image_info(img: Image.Image) -> dict:
    """
    Get information about an image.
    
    Args:
        img: PIL Image object
    
    Returns:
        Dictionary with image information
    """
    return {
        "width": img.width,
        "height": img.height,
        "mode": img.mode,
        "format": img.format,
        "size_bytes": len(image_to_bytes(img))
    }


def create_thumbnail(img: Image.Image, max_size: int = 256) -> Image.Image:
    """
    Create a thumbnail of the image.
    
    Args:
        img: PIL Image object
        max_size: Maximum dimension size
    
    Returns:
        Thumbnail PIL Image
    """
    img_copy = img.copy()
    img_copy.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
    return img_copy


def validate_image(img: Optional[Image.Image]) -> bool:
    """
    Validate that the image is valid.
    
    Args:
        img: PIL Image object to validate
    
    Returns:
        True if valid, False otherwise
    """
    if img is None:
        return False
    try:
        return img.width > 0 and img.height > 0
    except:
        return False


def np_to_pil(arr: np.ndarray) -> Image.Image:
    """
    Convert numpy array to PIL Image.
    
    Args:
        arr: Numpy array
    
    Returns:
        PIL Image
    """
    if arr.dtype != np.uint8:
        arr = arr.astype(np.uint8)
    return Image.fromarray(arr)


def pil_to_np(img: Image.Image) -> np.ndarray:
    """
    Convert PIL Image to numpy array.
    
    Args:
        img: PIL Image
    
    Returns:
        Numpy array
    """
    return np.array(img)