Course EN
← back to chapter

Texto a imagen

Entra un prompt, sale una imagen cuadrada, renderizada inline. Todo el oficio está

Showcase — Texto a imagen

Entra un prompt, sale una imagen cuadrada, renderizada inline. Todo el oficio está en la especificidad del prompt — sujeto, estilo, iluminación, composición. El backend regresa la imagen como un data URI; la página la renderiza.

Córrelo

bash bootstrap-secrets.sh              # reads ../../../../.env, writes secrets/
docker compose up --build              # default: PROVIDER=openai

Abre http://localhost:3000. Gemini: PROVIDER=gemini docker compose up --build.

Qué hay aquí

  • backend/ai_openai.pyimages.generate, regresa un data URI de PNG en base64.
  • backend/ai_gemini.py — el modelo de imagen de Gemini vía generate_content, bytes codificados en base64.
  • frontend/app/page.tsx — caja de prompt; renderiza el data URI devuelto como imagen.

Detenlo

docker compose down

Ejecútalo en tu máquina

Descarga el proyecto como ZIP y córrelo con Docker. Levanta un backend FastAPI y un frontend Next.js en localhost:3000.

Descargar text-to-image.zip

unzip text-to-image.zip
cd text-to-image
bash bootstrap-secrets.sh   # one-time: pulls API keys into ./secrets
docker compose up --build   # default provider: openai
# or:  PROVIDER=gemini docker compose up --build

Escribe algo, elige un proveedor y ejecuta el mismo código de Código contra la API real. Requiere iniciar sesión.


  

Los mismos módulos que ejecuta el botón Run. El proyecto completo (frontend, Dockerfile, compose) está en el ZIP, pestaña README.

backend/ai_openai.py

"""Showcase 1 (OpenAI): text to image.

A prompt in, a square image out, returned as a data URI the page renders inline.
The whole craft is in how specific the prompt is — subject, style, lighting,
composition.
"""
from openai import OpenAI

_client = OpenAI()

_MODEL = "gpt-image-1"


def run(prompt: str) -> str:
    p = prompt.strip()
    if not p:
        return "Enter a prompt describing the image you want."
    response = _client.images.generate(model=_MODEL, prompt=p, size="1024x1024")
    return f"data:image/png;base64,{response.data[0].b64_json}"

backend/ai_gemini.py

"""Showcase 1 (Gemini): text to image.

Gemini's image model via generate_content (the standalone Imagen endpoint is
deprecated). The image comes back as an inline data part; we base64 it into a
data URI for the page.
"""
import base64
import os

from google import genai
from google.genai import types

_client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

_MODEL = "gemini-2.5-flash-image"


def _generate(prompt: str) -> str:
    response = _client.models.generate_content(
        model=_MODEL, contents=prompt,
        config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
    )
    for part in response.candidates[0].content.parts:
        if getattr(part, "inline_data", None) and part.inline_data.data:
            b64 = base64.b64encode(part.inline_data.data).decode()
            return f"data:image/png;base64,{b64}"
    return "No image was generated — try rephrasing the prompt."


def run(prompt: str) -> str:
    p = prompt.strip()
    if not p:
        return "Enter a prompt describing the image you want."
    return _generate(p)

Archivos del proyecto

  • .gitignore
  • README.es.md
  • README.md
  • backend/Dockerfile
  • backend/ai_gemini.py
  • backend/ai_openai.py
  • backend/main.py
  • backend/requirements.txt
  • bootstrap-secrets.sh
  • docker-compose.yml
  • frontend/Dockerfile
  • frontend/app/layout.tsx
  • frontend/app/page.tsx
  • frontend/next.config.ts
  • frontend/package.json
  • frontend/tsconfig.json