habulaj's picture
Update routers/cover.py
9617a9b verified
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)}")