File size: 4,386 Bytes
d3325ee
 
9617a9b
d3325ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9617a9b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d3325ee
 
 
 
 
 
9617a9b
d3325ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9617a9b
 
 
d3325ee
9617a9b
d3325ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from fastapi import APIRouter, Query, HTTPException
from fastapi.responses import StreamingResponse
from PIL import Image, ImageDraw
from io import BytesIO
import requests

router = APIRouter()

def download_image_from_url(url: str) -> Image.Image:
    headers = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/115.0.0.0 Safari/537.36"
        )
    }
    try:
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        return Image.open(BytesIO(response.content)).convert("RGBA")
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Erro ao baixar imagem: {url} ({str(e)})")

def resize_and_crop_to_fill(img: Image.Image, target_width: int, target_height: int) -> Image.Image:
    """
    Redimensiona e corta a imagem para preencher exatamente o espaço alvo (sempre centralizado).
    
    Args:
        img: Imagem PIL
        target_width: Largura alvo
        target_height: Altura alvo
    """
    img_ratio = img.width / img.height
    target_ratio = target_width / target_height
    
    if img_ratio > target_ratio:
        # Imagem é mais larga proporcionalmente - redimensionar baseado na altura
        scale_height = target_height
        scale_width = int(scale_height * img_ratio)
    else:
        # Imagem é mais alta proporcionalmente - redimensionar baseado na largura
        scale_width = target_width
        scale_height = int(scale_width / img_ratio)
    
    img_resized = img.resize((scale_width, scale_height), Image.LANCZOS)
    
    # Centralizar o crop
    left = (scale_width - target_width) // 2
    top = (scale_height - target_height) // 2
    right = left + target_width
    bottom = top + target_height
    
    return img_resized.crop((left, top, right, bottom))

def add_rounded_corners(img: Image.Image, radius: int) -> Image.Image:
    """
    Adiciona cantos arredondados à imagem.
    
    Args:
        img: Imagem PIL
        radius: Raio do arredondamento em pixels
    
    Returns:
        Imagem com cantos arredondados
    """
    # Criar máscara para os cantos arredondados
    mask = Image.new("L", img.size, 0)
    draw = ImageDraw.Draw(mask)
    
    # Desenhar retângulo com cantos arredondados
    draw.rounded_rectangle(
        [(0, 0), (img.width, img.height)],
        radius=radius,
        fill=255
    )
    
    # Aplicar máscara à imagem
    output = Image.new("RGBA", img.size, (0, 0, 0, 0))
    output.paste(img, (0, 0))
    output.putalpha(mask)
    
    return output

def create_cover_image(image_url: str) -> BytesIO:
    """
    Cria uma capa para reels do Instagram.
    - Fundo preto
    - Largura: 1080, Altura: 1920
    - Imagem renderizada em Largura: 1080, Altura: 1440, X: 0, Y: 240
    - Cantos arredondados com raio de 145px
    """
    # Dimensões do canvas
    canvas_width = 1080
    canvas_height = 1920
    
    # Criar canvas com fundo preto
    canvas = Image.new("RGBA", (canvas_width, canvas_height), color=(0, 0, 0, 255))
    
    # Baixar e processar imagem
    img = download_image_from_url(image_url)
    
    # Redimensionar e cortar imagem para as dimensões especificadas
    # Largura: 1080, Altura: 1440
    img_width = 1080
    img_height = 1440
    filled_img = resize_and_crop_to_fill(img, img_width, img_height)
    
    # Aplicar arredondamento de 145px nos cantos
    rounded_img = add_rounded_corners(filled_img, 145)
    
    # Colar imagem na posição X: 0, Y: 240
    canvas.paste(rounded_img, (0, 240), rounded_img)
    
    # Converter para bytes
    buffer = BytesIO()
    canvas.convert("RGB").save(buffer, format="PNG")
    buffer.seek(0)
    return buffer

@router.get("/cover/reel")
def get_reel_cover(
    image_url: str = Query(..., description="URL da imagem a ser renderizada")
):
    """
    Endpoint para gerar capa para reels do Instagram.
    
    Args:
        image_url: URL da imagem a ser renderizada (obrigatório)
    
    Returns:
        Imagem PNG com fundo preto e imagem renderizada nas posições especificadas
    """
    try:
        buffer = create_cover_image(image_url)
        return StreamingResponse(buffer, media_type="image/png")
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Erro ao gerar imagem: {str(e)}")