habulaj commited on
Commit
0d25a50
verified
1 Parent(s): c611783

Delete routers/memoriam.py

Browse files
Files changed (1) hide show
  1. routers/memoriam.py +0 -203
routers/memoriam.py DELETED
@@ -1,203 +0,0 @@
1
- from fastapi import APIRouter, Query, HTTPException
2
- from fastapi.responses import StreamingResponse
3
- from PIL import Image, ImageDraw, ImageEnhance, ImageFont
4
- from io import BytesIO
5
- import requests
6
- from typing import Optional
7
- import logging
8
-
9
- # Configurar logging
10
- logging.basicConfig(level=logging.INFO)
11
- log = logging.getLogger("memoriam-api")
12
-
13
- router = APIRouter()
14
-
15
- def download_image_from_url(url: str) -> Image.Image:
16
- headers = {
17
- "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"
18
- }
19
- response = requests.get(url, headers=headers)
20
- if response.status_code != 200:
21
- raise HTTPException(status_code=400, detail=f"Imagem n茫o p么de ser baixada. C贸digo {response.status_code}")
22
- try:
23
- return Image.open(BytesIO(response.content)).convert("RGB")
24
- except Exception as e:
25
- raise HTTPException(status_code=400, detail=f"Erro ao abrir imagem: {str(e)}")
26
-
27
- def resize_and_crop_to_fill(img: Image.Image, target_width: int, target_height: int) -> Image.Image:
28
- img_ratio = img.width / img.height
29
- target_ratio = target_width / target_height
30
-
31
- if img_ratio > target_ratio:
32
- scale_height = target_height
33
- scale_width = int(scale_height * img_ratio)
34
- else:
35
- scale_width = target_width
36
- scale_height = int(scale_width / img_ratio)
37
-
38
- img_resized = img.resize((scale_width, scale_height), Image.LANCZOS)
39
-
40
- left = (scale_width - target_width) // 2
41
- top = (scale_height - target_height) // 2
42
- right = left + target_width
43
- bottom = top + target_height
44
-
45
- return img_resized.crop((left, top, right, bottom))
46
-
47
- def create_bottom_black_gradient(width: int, height: int) -> Image.Image:
48
- """Cria um gradiente preto suave que vai do topo transparente at茅 a metade da imagem preto"""
49
- gradient = Image.new("RGBA", (width, height), color=(0, 0, 0, 0))
50
- draw = ImageDraw.Draw(gradient)
51
-
52
- for y in range(height):
53
- # Gradiente mais suave que come莽a transparente e vai at茅 metade da imagem
54
- ratio = y / height
55
- if ratio <= 0.6:
56
- # Primeira parte: totalmente transparente
57
- alpha = 0
58
- elif ratio <= 0.75:
59
- # Transi莽茫o muito suave (60% a 75% da altura)
60
- alpha = int(80 * (ratio - 0.6) / 0.15)
61
- else:
62
- # Final suave (75% a 100% da altura)
63
- alpha = int(80 + 50 * (ratio - 0.75) / 0.25)
64
-
65
- # Usar preto puro (0, 0, 0) com alpha mais baixo
66
- draw.line([(0, y), (width, y)], fill=(0, 0, 0, alpha))
67
-
68
- return gradient
69
-
70
- def create_top_black_gradient(width: int, height: int) -> Image.Image:
71
- """Cria um gradiente preto suave que vai do fundo transparente at茅 a metade da imagem preto"""
72
- gradient = Image.new("RGBA", (width, height), color=(0, 0, 0, 0))
73
- draw = ImageDraw.Draw(gradient)
74
-
75
- for y in range(height):
76
- # Gradiente mais suave que come莽a preto e vai at茅 metade da imagem
77
- ratio = y / height
78
- if ratio <= 0.25:
79
- # Primeira parte suave (0% a 25% da altura)
80
- alpha = int(80 + 50 * (0.25 - ratio) / 0.25)
81
- elif ratio <= 0.4:
82
- # Transi莽茫o muito suave (25% a 40% da altura)
83
- alpha = int(80 * (0.4 - ratio) / 0.15)
84
- else:
85
- # Segunda parte: totalmente transparente
86
- alpha = 0
87
-
88
- # Usar preto puro (0, 0, 0) com alpha mais baixo
89
- draw.line([(0, y), (width, y)], fill=(0, 0, 0, alpha))
90
-
91
- return gradient
92
-
93
- def draw_text_left_aligned(draw: ImageDraw.Draw, text: str, x: int, y: int, font_path: str, font_size: int):
94
- """Desenha texto alinhado 脿 esquerda com especifica莽玫es exatas"""
95
- try:
96
- font = ImageFont.truetype(font_path, font_size)
97
- except Exception:
98
- font = ImageFont.load_default()
99
-
100
- # Espa莽amento entre letras 0% e cor branca
101
- draw.text((x, y), text, font=font, fill=(255, 255, 255), spacing=0)
102
-
103
-
104
-
105
- def create_canvas(image_url: Optional[str], name: Optional[str], birth: Optional[str], death: Optional[str], text_position: str = "bottom") -> BytesIO:
106
- # Dimens玫es fixas para Instagram
107
- width = 1080
108
- height = 1350
109
-
110
- canvas = Image.new("RGBA", (width, height), (0, 0, 0, 0)) # Fundo transparente
111
-
112
- # Carregar e processar imagem de fundo se fornecida
113
- if image_url:
114
- try:
115
- img = download_image_from_url(image_url)
116
- img_bw = ImageEnhance.Color(img).enhance(0.0).convert("RGBA")
117
- filled_img = resize_and_crop_to_fill(img_bw, width, height)
118
- canvas.paste(filled_img, (0, 0))
119
- except Exception as e:
120
- log.warning(f"Erro ao carregar imagem: {e}")
121
-
122
- # Aplicar gradiente baseado na posi莽茫o do texto
123
- if text_position.lower() == "top":
124
- gradient_overlay = create_top_black_gradient(width, height)
125
- else: # bottom
126
- gradient_overlay = create_bottom_black_gradient(width, height)
127
-
128
- canvas = Image.alpha_composite(canvas, gradient_overlay)
129
-
130
- # Adicionar logo no canto inferior direito com opacidade
131
- try:
132
- logo = Image.open("recurve.png").convert("RGBA")
133
- logo_resized = logo.resize((120, 22))
134
- # Aplicar opacidade 脿 logo
135
- logo_with_opacity = Image.new("RGBA", logo_resized.size)
136
- logo_with_opacity.paste(logo_resized, (0, 0))
137
- # Reduzir opacidade
138
- logo_alpha = logo_with_opacity.split()[-1].point(lambda x: int(x * 0.42)) # 42% de opacidade
139
- logo_with_opacity.putalpha(logo_alpha)
140
-
141
- logo_padding = 40
142
- logo_x = width - 120 - logo_padding
143
- logo_y = height - 22 - logo_padding
144
- canvas.paste(logo_with_opacity, (logo_x, logo_y), logo_with_opacity)
145
- except Exception as e:
146
- log.warning(f"Erro ao carregar a logo: {e}")
147
-
148
- draw = ImageDraw.Draw(canvas)
149
-
150
- # Configurar posi莽玫es baseadas no text_position
151
- text_x = 80 # Alinhamento 脿 esquerda com margem
152
-
153
- if text_position.lower() == "top":
154
- dates_y = 100
155
- name_y = dates_y + 36 + 6 # Ano + espa莽amento de 6px + nome
156
- else: # bottom
157
- dates_y = height - 250
158
- name_y = dates_y + 36 + 6 # Ano + espa莽amento de 6px + nome
159
-
160
- # Desenhar datas primeiro (se fornecidas)
161
- if birth or death:
162
- font_path_regular = "fonts/AGaramondPro-Regular.ttf"
163
-
164
- # Construir texto das datas
165
- dates_text = ""
166
- if birth and death:
167
- dates_text = f"{birth} - {death}"
168
- elif birth:
169
- dates_text = f"{birth}"
170
- elif death:
171
- dates_text = f"- {death}"
172
-
173
- if dates_text:
174
- draw_text_left_aligned(draw, dates_text, text_x, dates_y, font_path_regular, 36)
175
-
176
- # Desenhar nome abaixo das datas
177
- if name:
178
- font_path = "fonts/AGaramondPro-BoldItalic.ttf"
179
- draw_text_left_aligned(draw, name, text_x, name_y, font_path, 87)
180
-
181
- buffer = BytesIO()
182
- canvas.save(buffer, format="PNG")
183
- buffer.seek(0)
184
- return buffer
185
-
186
- @router.get("/cover/memoriam")
187
- def get_memoriam_image(
188
- image_url: Optional[str] = Query(None, description="URL da imagem de fundo"),
189
- name: Optional[str] = Query(None, description="Nome (ser谩 exibido em mai煤sculas)"),
190
- birth: Optional[str] = Query(None, description="Ano de nascimento (ex: 1943)"),
191
- death: Optional[str] = Query(None, description="Ano de falecimento (ex: 2023)"),
192
- text_position: str = Query("bottom", description="Posi莽茫o do texto: 'top' ou 'bottom'")
193
- ):
194
- """
195
- Gera imagem de memoriam no formato 1080x1350 (Instagram).
196
- Todos os par芒metros s茫o opcionais, mas recomenda-se fornecer pelo menos o nome.
197
- O gradiente ser谩 aplicado baseado na posi莽茫o do texto (top ou bottom).
198
- """
199
- try:
200
- buffer = create_canvas(image_url, name, birth, death, text_position)
201
- return StreamingResponse(buffer, media_type="image/png")
202
- except Exception as e:
203
- raise HTTPException(status_code=500, detail=f"Erro ao gerar imagem: {str(e)}")