habulaj commited on
Commit
047a98b
·
verified ·
1 Parent(s): 5255166

Update routers/image.py

Browse files
Files changed (1) hide show
  1. routers/image.py +57 -56
routers/image.py CHANGED
@@ -664,7 +664,7 @@ def get_logo_path(slide_color: int) -> str:
664
  else:
665
  return "recurveblack.png" # Logo preta
666
 
667
- def create_slide_canvas(image_url: str, slide: int, text: Optional[str] = None, color: int = 1) -> BytesIO:
668
  """
669
  Cria um canvas para slides com imagem cortada baseada no parâmetro slide.
670
 
@@ -755,14 +755,17 @@ def create_slide_canvas(image_url: str, slide: int, text: Optional[str] = None,
755
  # Colar imagem no canvas
756
  canvas.paste(img_with_mask, (x_pos, y_pos), img_with_mask)
757
 
758
- # Obter cor do texto baseada na cor do slide
759
- text_color = get_text_color(color)
 
 
 
760
 
761
  # Adicionar texto se slide for 1 e text for fornecido
762
  if slide == 1 and text and text.strip():
763
  draw = ImageDraw.Draw(canvas)
764
  # Renderizar texto com as especificações: X: 200, Y: 155, L: 815, MAX 5 linhas
765
- render_slide_text(draw, text, x=200, y=155, max_width=815, max_lines=5, text_color=text_color)
766
 
767
  # Adicionar texto se slide for 2 e text for fornecido
768
  if slide == 2 and text and text.strip():
@@ -770,7 +773,7 @@ def create_slide_canvas(image_url: str, slide: int, text: Optional[str] = None,
770
  # Renderizar texto com as especificações: X: 445, Y: 370, L: 585, MAX 19 linhas
771
  # A imagem do slide 2 agora vai de Y: 370 a Y: 1150 (altura 780px)
772
  # Para centralizar o texto na área da imagem, o centro é Y: 370 + (780/2) = 760
773
- render_slide_text(draw, text, x=445, y=760, max_width=585, max_lines=19, center_vertical=True, text_color=text_color)
774
 
775
  # Adicionar logo no canto inferior direito
776
  try:
@@ -798,7 +801,7 @@ def create_slide_canvas(image_url: str, slide: int, text: Optional[str] = None,
798
  buffer.seek(0)
799
  return buffer
800
 
801
- def create_quote_canvas(quote_text: str, role: Optional[str] = None, name: Optional[str] = None, color: int = 1, quote_background: bool = False, image_url: Optional[str] = None) -> BytesIO:
802
  """
803
  Cria um canvas para quotes com fundo colorido, imagem quote.png e texto centralizado.
804
 
@@ -896,28 +899,26 @@ def create_quote_canvas(quote_text: str, role: Optional[str] = None, name: Optio
896
  text_x = 180
897
  text_y = canvas_height // 2 # Centralizar verticalmente
898
 
899
- # Obter cor do texto baseada no quote_background
900
- if quote_background:
901
- # Quando quote_background=True, sempre usar branco
902
- text_color = (255, 255, 255, 255)
903
- else:
904
- # Quando quote_background=False, usar cor baseada na cor do fundo
905
- text_color = get_text_color(color)
906
 
907
  # Adicionar imagem quote.png ou quoteblank.png acima do texto
908
  try:
909
- # Escolher imagem baseada no quote_background e cor
910
  if quote_background:
911
  # Quando quote_background=True, sempre usar quotered.png
912
  quote_image_name = "quotered.png"
913
  else:
914
- # Quando quote_background=False, escolher baseado na cor
915
- if color == 6:
916
- # Cor 6 sempre usa quoteblank.png
917
- quote_image_name = "quoteblank.png"
918
  else:
919
- # Outras cores: quotered.png se texto branco, quote.png se texto preto
920
- quote_image_name = "quotered.png" if text_color == (255, 255, 255, 255) else "quote.png"
921
  quote_img = Image.open(quote_image_name).convert("RGBA")
922
  quote_width, quote_height = 87, 67.46
923
 
@@ -1043,11 +1044,11 @@ def create_quote_canvas(quote_text: str, role: Optional[str] = None, name: Optio
1043
  quote_text_with_symbol = quote_text + '”'
1044
 
1045
  # Renderizar texto com as especificações solicitadas
1046
- render_quote_text(draw, quote_text_with_symbol, text_x, text_y, text_width, text_color, quote_background)
1047
 
1048
  # Renderizar cargo e nome se fornecidos
1049
  if role or name:
1050
- render_author_info(draw, canvas, role, name, text_x, text_y, text_width, quote_text_with_symbol, text_color, quote_background)
1051
 
1052
  buffer = BytesIO()
1053
  canvas.convert("RGB").save(buffer, format="PNG")
@@ -1284,23 +1285,17 @@ def render_author_info(draw: ImageDraw.Draw, canvas: Image.Image, role: Optional
1284
  except (OSError, IOError):
1285
  font = ImageFont.load_default()
1286
 
1287
- # Determinar cores baseadas no quote_background
1288
- if quote_background:
1289
- # Quando quote_background=True, sempre usar branco
1290
  cargo_color = (255, 255, 255, 255)
 
1291
  nome_color = (255, 255, 255, int(255 * 0.65))
1292
- else:
1293
- # Quando quote_background=False, usar cores baseadas na cor do texto principal
1294
- if text_color == (255, 255, 255, 255): # Se texto principal for branco
1295
- # Cor do cargo: branco
1296
- cargo_color = (255, 255, 255, 255)
1297
- # Cor do nome: branco com 65% de opacidade
1298
- nome_color = (255, 255, 255, int(255 * 0.65))
1299
- else: # Se texto principal for preto
1300
- # Cor do cargo: 140F09 (RGB: 20, 15, 9)
1301
- cargo_color = (20, 15, 9, 255)
1302
- # Cor do nome: 140F09 com 65% de opacidade
1303
- nome_color = (20, 15, 9, int(255 * 0.65))
1304
 
1305
  # Calcular altura do texto principal para posicionar o autor
1306
  # Usar a mesma lógica do render_quote_text para calcular a altura
@@ -1513,7 +1508,7 @@ def render_author_info(draw: ImageDraw.Draw, canvas: Image.Image, role: Optional
1513
  current_y += name_height + 5
1514
 
1515
  def create_canvas(image_url: str, text: Optional[str] = None,
1516
- text_position: str = "bottom", background: bool = False, color: int = 1, background_position: str = "bottom") -> BytesIO:
1517
  # Dimensões fixas do Instagram
1518
  width, height = 1080, 1350
1519
 
@@ -1598,19 +1593,21 @@ def create_canvas(image_url: str, text: Optional[str] = None,
1598
  background_rect = Image.new("RGBA", (width, background_height), color=bg_color)
1599
  canvas.paste(background_rect, (0, background_start_y))
1600
  else:
1601
- # Adicionar gradiente apenas se background=False
1602
  # Lógica inteligente para posicionamento do gradiente
1603
 
1604
- # Se text_position=bottom, sempre gradiente embaixo (obrigatório)
1605
- if text_position == "bottom":
1606
- gradient_overlay = create_gradient_overlay(width, height, "bottom")
1607
- canvas = Image.alpha_composite(canvas, gradient_overlay)
1608
-
1609
- # Se text_position=top
1610
- elif text_position == "top":
1611
- # Sempre gradiente em cima quando texto está no topo
1612
- gradient_overlay = create_gradient_overlay(width, height, "top")
1613
- canvas = Image.alpha_composite(canvas, gradient_overlay)
 
 
1614
 
1615
  # Adicionar logo na posição (X: 880, Y: 1260)
1616
  try:
@@ -1662,14 +1659,17 @@ def create_canvas(image_url: str, text: Optional[str] = None,
1662
  else:
1663
  text_y = None
1664
 
1665
- # Obter cor do texto baseada na cor do fundo
1666
- text_color = get_text_color(color)
 
 
 
1667
 
1668
  # Renderizar texto se fornecido
1669
  if text and text.strip() and text_y is not None:
1670
  # Alinhar pela base quando no bottom; pelo topo quando no top
1671
  align_text_top = (text_position == "top")
1672
- render_text(draw, text, x=78, y=text_y, max_width=924, max_lines=5, align_top=align_text_top, text_color=text_color)
1673
 
1674
  buffer = BytesIO()
1675
  canvas.convert("RGB").save(buffer, format="PNG")
@@ -1688,18 +1688,19 @@ def get_image(
1688
  quote: Optional[str] = Query(None, description="Texto da quote para gerar poster com fundo colorido"),
1689
  role: Optional[str] = Query(None, description="Position/role of the person who said the quote"),
1690
  name: Optional[str] = Query(None, description="Name of the person who said the quote"),
1691
- quote_background: bool = Query(False, description="Se True, centraliza texto, role/name e símbolo da quote")
 
1692
  ):
1693
  try:
1694
  # Se o parâmetro quote for fornecido, usar a funcionalidade de quote
1695
  if quote is not None and quote.strip():
1696
- buffer = create_quote_canvas(quote, role, name, color, quote_background, image_url)
1697
  # Se o parâmetro slide for fornecido, usar a funcionalidade de slides
1698
  elif slide is not None:
1699
- buffer = create_slide_canvas(image_url, slide, text, color)
1700
  else:
1701
  # Usar funcionalidade normal de criação de imagem
1702
- buffer = create_canvas(image_url, text, text_position, background, color, background_position)
1703
  return StreamingResponse(buffer, media_type="image/png")
1704
  except Exception as e:
1705
  raise HTTPException(status_code=500, detail=f"Erro ao gerar imagem: {str(e)}")
 
664
  else:
665
  return "recurveblack.png" # Logo preta
666
 
667
+ def create_slide_canvas(image_url: str, slide: int, text: Optional[str] = None, color: int = 1, text_color: str = "white") -> BytesIO:
668
  """
669
  Cria um canvas para slides com imagem cortada baseada no parâmetro slide.
670
 
 
755
  # Colar imagem no canvas
756
  canvas.paste(img_with_mask, (x_pos, y_pos), img_with_mask)
757
 
758
+ # Obter cor do texto baseada no parâmetro text_color
759
+ if text_color.lower() == "black":
760
+ text_color_tuple = (0, 0, 0, 255) # #000000
761
+ else: # white (padrão)
762
+ text_color_tuple = (255, 255, 255, 255) # branco
763
 
764
  # Adicionar texto se slide for 1 e text for fornecido
765
  if slide == 1 and text and text.strip():
766
  draw = ImageDraw.Draw(canvas)
767
  # Renderizar texto com as especificações: X: 200, Y: 155, L: 815, MAX 5 linhas
768
+ render_slide_text(draw, text, x=200, y=155, max_width=815, max_lines=5, text_color=text_color_tuple)
769
 
770
  # Adicionar texto se slide for 2 e text for fornecido
771
  if slide == 2 and text and text.strip():
 
773
  # Renderizar texto com as especificações: X: 445, Y: 370, L: 585, MAX 19 linhas
774
  # A imagem do slide 2 agora vai de Y: 370 a Y: 1150 (altura 780px)
775
  # Para centralizar o texto na área da imagem, o centro é Y: 370 + (780/2) = 760
776
+ render_slide_text(draw, text, x=445, y=760, max_width=585, max_lines=19, center_vertical=True, text_color=text_color_tuple)
777
 
778
  # Adicionar logo no canto inferior direito
779
  try:
 
801
  buffer.seek(0)
802
  return buffer
803
 
804
+ def create_quote_canvas(quote_text: str, role: Optional[str] = None, name: Optional[str] = None, color: int = 1, quote_background: bool = False, image_url: Optional[str] = None, text_color: str = "white") -> BytesIO:
805
  """
806
  Cria um canvas para quotes com fundo colorido, imagem quote.png e texto centralizado.
807
 
 
899
  text_x = 180
900
  text_y = canvas_height // 2 # Centralizar verticalmente
901
 
902
+ # Obter cor do texto baseada no parâmetro text_color
903
+ if text_color.lower() == "black":
904
+ text_color_tuple = (0, 0, 0, 255) # #000000
905
+ else: # white (padrão)
906
+ text_color_tuple = (255, 255, 255, 255) # branco
 
 
907
 
908
  # Adicionar imagem quote.png ou quoteblank.png acima do texto
909
  try:
910
+ # Escolher imagem baseada no quote_background e text_color
911
  if quote_background:
912
  # Quando quote_background=True, sempre usar quotered.png
913
  quote_image_name = "quotered.png"
914
  else:
915
+ # Quando quote_background=False, escolher baseado no text_color
916
+ if text_color.lower() == "black":
917
+ # Se text_color=black, usar quote.png (preta)
918
+ quote_image_name = "quote.png"
919
  else:
920
+ # Se text_color=white, usar quotered.png (vermelha)
921
+ quote_image_name = "quotered.png"
922
  quote_img = Image.open(quote_image_name).convert("RGBA")
923
  quote_width, quote_height = 87, 67.46
924
 
 
1044
  quote_text_with_symbol = quote_text + '”'
1045
 
1046
  # Renderizar texto com as especificações solicitadas
1047
+ render_quote_text(draw, quote_text_with_symbol, text_x, text_y, text_width, text_color_tuple, quote_background)
1048
 
1049
  # Renderizar cargo e nome se fornecidos
1050
  if role or name:
1051
+ render_author_info(draw, canvas, role, name, text_x, text_y, text_width, quote_text_with_symbol, text_color_tuple, quote_background)
1052
 
1053
  buffer = BytesIO()
1054
  canvas.convert("RGB").save(buffer, format="PNG")
 
1285
  except (OSError, IOError):
1286
  font = ImageFont.load_default()
1287
 
1288
+ # Determinar cores baseadas no text_color
1289
+ if text_color == (255, 255, 255, 255): # Se texto principal for branco
1290
+ # Cor do cargo: branco
1291
  cargo_color = (255, 255, 255, 255)
1292
+ # Cor do nome: branco com 65% de opacidade
1293
  nome_color = (255, 255, 255, int(255 * 0.65))
1294
+ else: # Se texto principal for preto
1295
+ # Cor do cargo: 140F09 (RGB: 20, 15, 9)
1296
+ cargo_color = (20, 15, 9, 255)
1297
+ # Cor do nome: 140F09 com 65% de opacidade
1298
+ nome_color = (20, 15, 9, int(255 * 0.65))
 
 
 
 
 
 
 
1299
 
1300
  # Calcular altura do texto principal para posicionar o autor
1301
  # Usar a mesma lógica do render_quote_text para calcular a altura
 
1508
  current_y += name_height + 5
1509
 
1510
  def create_canvas(image_url: str, text: Optional[str] = None,
1511
+ text_position: str = "bottom", background: bool = False, color: int = 1, background_position: str = "bottom", text_color: str = "white") -> BytesIO:
1512
  # Dimensões fixas do Instagram
1513
  width, height = 1080, 1350
1514
 
 
1593
  background_rect = Image.new("RGBA", (width, background_height), color=bg_color)
1594
  canvas.paste(background_rect, (0, background_start_y))
1595
  else:
1596
+ # Adicionar gradiente apenas se background=False e text_color não for black
1597
  # Lógica inteligente para posicionamento do gradiente
1598
 
1599
+ # Se text_color=black, não adicionar gradientes pretos
1600
+ if text_color.lower() != "black":
1601
+ # Se text_position=bottom, sempre gradiente embaixo (obrigatório)
1602
+ if text_position == "bottom":
1603
+ gradient_overlay = create_gradient_overlay(width, height, "bottom")
1604
+ canvas = Image.alpha_composite(canvas, gradient_overlay)
1605
+
1606
+ # Se text_position=top
1607
+ elif text_position == "top":
1608
+ # Sempre gradiente em cima quando texto está no topo
1609
+ gradient_overlay = create_gradient_overlay(width, height, "top")
1610
+ canvas = Image.alpha_composite(canvas, gradient_overlay)
1611
 
1612
  # Adicionar logo na posição (X: 880, Y: 1260)
1613
  try:
 
1659
  else:
1660
  text_y = None
1661
 
1662
+ # Obter cor do texto baseada no parâmetro text_color
1663
+ if text_color.lower() == "black":
1664
+ text_color_tuple = (0, 0, 0, 255) # #000000
1665
+ else: # white (padrão)
1666
+ text_color_tuple = (255, 255, 255, 255) # branco
1667
 
1668
  # Renderizar texto se fornecido
1669
  if text and text.strip() and text_y is not None:
1670
  # Alinhar pela base quando no bottom; pelo topo quando no top
1671
  align_text_top = (text_position == "top")
1672
+ render_text(draw, text, x=78, y=text_y, max_width=924, max_lines=5, align_top=align_text_top, text_color=text_color_tuple)
1673
 
1674
  buffer = BytesIO()
1675
  canvas.convert("RGB").save(buffer, format="PNG")
 
1688
  quote: Optional[str] = Query(None, description="Texto da quote para gerar poster com fundo colorido"),
1689
  role: Optional[str] = Query(None, description="Position/role of the person who said the quote"),
1690
  name: Optional[str] = Query(None, description="Name of the person who said the quote"),
1691
+ quote_background: bool = Query(False, description="Se True, centraliza texto, role/name e símbolo da quote"),
1692
+ text_color: str = Query("white", description="Cor do texto: 'white' ou 'black'")
1693
  ):
1694
  try:
1695
  # Se o parâmetro quote for fornecido, usar a funcionalidade de quote
1696
  if quote is not None and quote.strip():
1697
+ buffer = create_quote_canvas(quote, role, name, color, quote_background, image_url, text_color)
1698
  # Se o parâmetro slide for fornecido, usar a funcionalidade de slides
1699
  elif slide is not None:
1700
+ buffer = create_slide_canvas(image_url, slide, text, color, text_color)
1701
  else:
1702
  # Usar funcionalidade normal de criação de imagem
1703
+ buffer = create_canvas(image_url, text, text_position, background, color, background_position, text_color)
1704
  return StreamingResponse(buffer, media_type="image/png")
1705
  except Exception as e:
1706
  raise HTTPException(status_code=500, detail=f"Erro ao gerar imagem: {str(e)}")