> ## Documentation Index
> Fetch the complete documentation index at: https://apidoc.cometapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Usar modelos de imagen Gemini

> Llama a modelos de imagen Gemini (Nano Banana 2 / Pro) en CometAPI usando el Google Gen AI SDK para generación de texto a imagen, imagen a imagen y composición de múltiples imágenes.

Esta guía muestra cómo usar modelos de imagen Gemini a través de CometAPI usando el **Google Gen AI SDK**. Cubre:

* Generación de texto a imagen
* Edición de imagen a imagen
* Composición de múltiples imágenes
* Guardado de imágenes generadas

<Info>
  - **URL base:** `https://api.cometapi.com`
  - Instala el SDK: `pip install google-genai` (Python) o `npm install @google/genai` (Node.js)
</Info>

***

## Configuración

Inicializa el cliente con la URL base de CometAPI:

<CodeGroup>
  ```python Python theme={null}
  from google import genai
  from google.genai import types
  import os

  COMETAPI_KEY = os.environ["COMETAPI_KEY"]

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
      api_key=COMETAPI_KEY,
  )
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";

  const COMETAPI_KEY = process.env.COMETAPI_KEY;

  const ai = new GoogleGenAI({
    apiKey: COMETAPI_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.cometapi.com" },
  });
  ```

  ```go Go theme={null}
  package main

  import (
  	"context"
  	"os"
  	"google.golang.org/genai"
  )

  func main() {
  	ctx := context.Background()
  	apiKey := os.Getenv("COMETAPI_KEY")

  	client, _ := genai.NewClient(ctx, &genai.ClientConfig{
  		APIKey:  apiKey,
  		Backend: genai.BackendGeminiAPI,
  		HTTPOptions: genai.HTTPOptions{
  			BaseURL: "https://api.cometapi.com",
  		},
  	})
  	// use client below...
  }
  ```
</CodeGroup>

***

## Generación de texto a imagen

Genera una imagen a partir de un prompt de texto y guárdala en un archivo.

<CodeGroup>
  ```python Python theme={null}
  from google import genai
  from google.genai import types
  from PIL import Image
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
      api_key=os.environ.get("COMETAPI_KEY"),
  )

  response = client.models.generate_content(
      model="gemini-3.1-flash-image-preview",
      contents="Create a picture of a nano banana dish in a fancy restaurant with a Gemini theme",
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif part.inline_data is not None:
          final_image = part.as_image()

  if final_image:
      final_image.save("generated_image.png")
      print("Image saved to generated_image.png")
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";
  import * as fs from "fs";

  const ai = new GoogleGenAI({
    apiKey: process.env.COMETAPI_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.cometapi.com" },
  });

  const response = await ai.models.generateContent({
    model: "gemini-3.1-flash-image-preview",
    contents: "Create a picture of a nano banana dish in a fancy restaurant with a Gemini theme",
    config: { responseModalities: ["TEXT", "IMAGE"] },
  });

  let finalImagePart;
  for (const part of response.candidates[0].content.parts) {
    if (part.thought === true) {
      continue;
    }
    if (part.text) {
      console.log(part.text);
    }
    if (part.inlineData) {
      finalImagePart = part;
    }
  }

  if (finalImagePart) {
    const buffer = Buffer.from(finalImagePart.inlineData.data, "base64");
    fs.writeFileSync("generated_image.png", buffer);
    console.log("Image saved to generated_image.png");
  }
  ```

  ```bash Shell theme={null}
  curl -s -X POST \
    "https://api.cometapi.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent" \
    -H "Authorization: Bearer $COMETAPI_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "contents": [{
        "parts": [{"text": "Create a picture of a nano banana dish in a fancy restaurant with a Gemini theme"}]
      }],
      "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"]
      }
    }'
  ```
</CodeGroup>

**Guarda la parte de la imagen final:**

Los datos de la imagen están en `candidates[0].content.parts`, que puede contener partes de texto y/o de imagen. Los modelos de imagen de Gemini también pueden devolver partes de pensamiento intermedias antes de la imagen final, especialmente cuando solicitas tanto texto como imágenes o habilitas explícitamente la salida de pensamiento. No guardes a ciegas el primer `inlineData`; omite las partes donde `thought` sea `true` y luego guarda la última parte de imagen restante.

Respuesta típica solo con la imagen final:

```json theme={null}
{
  "candidates": [{
    "content": {
      "parts": [
        { "text": "Here is your image..." },
        {
          "inlineData": {
            "mimeType": "image/png",
            "data": "<base64-encoded-image>"
          }
        }
      ]
    }
  }]
}
```

Respuesta con una parte de texto, una imagen de pensamiento intermedia y la imagen final:

```json theme={null}
{
  "candidates": [{
    "content": {
      "role": "model",
      "parts": [
        { "text": "Here is your image..." },
        {
          "inlineData": {
            "mimeType": "image/jpeg",
            "data": "<base64-encoded-intermediate-image>"
          },
          "thought": true
        },
        {
          "inlineData": {
            "mimeType": "image/jpeg",
            "data": "<base64-encoded-final-image>"
          },
          "thought": false,
          "thoughtSignature": "<signature>"
        }
      ]
    },
    "finishReason": "STOP"
  }]
}
```

Usa esta regla de análisis para cada respuesta de imagen de Gemini:

```javascript theme={null}
const imageParts = response.candidates[0].content.parts.filter(
  (part) => part.inlineData && part.thought !== true,
);
const finalImagePart = imageParts.at(-1);
```

***

## Generación de imagen a imagen

Sube una imagen de entrada y transfórmala con un prompt de texto.

<CodeGroup>
  ```python Python theme={null}
  from google import genai
  from google.genai import types
  from PIL import Image
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
      api_key=os.environ.get("COMETAPI_KEY"),
  )

  # Load the source image
  source_image = Image.open("source.jpg")

  response = client.models.generate_content(
      model="gemini-3.1-flash-image-preview",
      contents=["Transform this into a watercolor painting", source_image],
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif part.inline_data is not None:
          final_image = part.as_image()

  if final_image:
      final_image.save("watercolor_output.png")
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";
  import * as fs from "fs";

  const ai = new GoogleGenAI({
    apiKey: process.env.COMETAPI_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.cometapi.com" },
  });

  const imageData = fs.readFileSync("source.jpg").toString("base64");

  const response = await ai.models.generateContent({
    model: "gemini-3.1-flash-image-preview",
    contents: [
      { text: "Transform this into a watercolor painting" },
      { inlineData: { mimeType: "image/jpeg", data: imageData } },
    ],
    config: { responseModalities: ["TEXT", "IMAGE"] },
  });

  const imageParts = response.candidates[0].content.parts.filter(
    (part) => part.inlineData && part.thought !== true,
  );
  const finalImagePart = imageParts.at(-1);

  if (finalImagePart) {
    fs.writeFileSync("watercolor_output.png", Buffer.from(finalImagePart.inlineData.data, "base64"));
  }
  ```

  ```bash Shell theme={null}
  curl -s -X POST \
    "https://api.cometapi.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent" \
    -H "Authorization: Bearer $COMETAPI_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "contents": [{
        "role": "user",
        "parts": [
          { "text": "Transform this into a watercolor painting" },
          { "inline_data": { "mime_type": "image/jpeg", "data": "<base64-encoded-source-image>" } }
        ]
      }],
      "generationConfig": { "responseModalities": ["TEXT", "IMAGE"] }
    }'
  ```
</CodeGroup>

<Note>
  * El SDK de Python acepta objetos `PIL.Image` directamente; no se necesita codificación manual en Base64.
  * **No** incluyas el prefijo `data:image/jpeg;base64,` al pasar cadenas Base64 sin procesar.
</Note>

***

## Composición de múltiples imágenes

Genera una nueva imagen a partir de varias imágenes de entrada. CometAPI admite dos enfoques:

### Método 1: Una sola imagen de collage

Combina varias imágenes de origen en un solo collage y luego describe la salida deseada.

<Frame>
  <img src="https://mintcdn.com/cometapi/OukMcVwzR05umRJn/images/image/gemini/6100640_569419.png?fit=max&auto=format&n=OukMcVwzR05umRJn&q=85&s=02d820e809bd8e21e3b7b0c58592c6ab" alt="Ejemplo de collage de entrada" width="1200" height="754" data-path="images/image/gemini/6100640_569419.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/cometapi/OukMcVwzR05umRJn/images/image/gemini/6100640_569420.png?fit=max&auto=format&n=OukMcVwzR05umRJn&q=85&s=b8f128a921f62619b575926da824fd43" alt="Salida generada" width="1200" height="733" data-path="images/image/gemini/6100640_569420.png" />
</Frame>

<CodeGroup>
  ```python Python theme={null}
  from google import genai
  from google.genai import types
  from PIL import Image
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
      api_key=os.environ.get("COMETAPI_KEY"),
  )

  collage = Image.open("collage.jpg")

  response = client.models.generate_content(
      model="gemini-3.1-flash-image-preview",
      contents=[
          "A model is posing and leaning against a pink BMW with a green alien keychain attached to a pink handbag, a pink parrot on her shoulder, and a pug wearing a pink collar and gold headphones",
          collage,
      ],
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.inline_data is not None:
          final_image = part.as_image()

  if final_image:
      final_image.save("composition_output.png")
  ```

  ```bash Shell theme={null}
  curl -s -X POST \
    "https://api.cometapi.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent" \
    -H "Authorization: Bearer $COMETAPI_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "contents": [{
        "role": "user",
        "parts": [
          { "text": "A model is posing and leaning against a pink BMW with a green alien keychain attached to a pink handbag, a pink parrot on her shoulder, and a pug wearing a pink collar and gold headphones" },
          { "inline_data": { "mime_type": "image/jpeg", "data": "<base64-encoded-collage-image>" } }
        ]
      }],
      "generationConfig": { "responseModalities": ["TEXT", "IMAGE"] }
    }'
  ```
</CodeGroup>

### Método 2: Varias imágenes separadas (hasta 14)

Pasa varias imágenes directamente. Los modelos Gemini 3 admiten hasta 14 imágenes de referencia (objetos + personajes):

<CodeGroup>
  ```python Python theme={null}
  from google import genai
  from google.genai import types
  from PIL import Image
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
      api_key=os.environ.get("COMETAPI_KEY"),
  )

  image1 = Image.open("image1.jpg")
  image2 = Image.open("image2.jpg")
  image3 = Image.open("image3.jpg")

  response = client.models.generate_content(
      model="gemini-3.1-flash-image-preview",
      contents=["Merge the three images", image1, image2, image3],
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.inline_data is not None:
          final_image = part.as_image()

  if final_image:
      final_image.save("merged_output.png")
  ```

  ```bash Shell theme={null}
  curl -s -X POST \
    "https://api.cometapi.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent" \
    -H "Authorization: Bearer $COMETAPI_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "contents": [{
        "role": "user",
        "parts": [
          { "text": "Merge the three images" },
          { "inline_data": { "mime_type": "image/jpeg", "data": "<base64-image-1>" } },
          { "inline_data": { "mime_type": "image/jpeg", "data": "<base64-image-2>" } },
          { "inline_data": { "mime_type": "image/jpeg", "data": "<base64-image-3>" } }
        ]
      }],
      "generationConfig": { "responseModalities": ["TEXT", "IMAGE"] }
    }'
  ```
</CodeGroup>

<Frame>
  <img src="https://mintcdn.com/cometapi/OukMcVwzR05umRJn/images/image/gemini/6100640_569429.png?fit=max&auto=format&n=OukMcVwzR05umRJn&q=85&s=2a1ea93ce3477491d8014283896c31e2" alt="Resultado de la generación con múltiples imágenes" width="1248" height="832" data-path="images/image/gemini/6100640_569429.png" />
</Frame>

***

## Generación de imágenes 4K

Especifica `image_config` con `aspect_ratio` e `image_size` para una salida de alta resolución:

<CodeGroup>
  ```python Python theme={null}
  from google import genai
  from google.genai import types
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
      api_key=os.environ.get("COMETAPI_KEY"),
  )

  response = client.models.generate_content(
      model="gemini-3.1-flash-image-preview",
      contents="Da Vinci style anatomical sketch of a Monarch butterfly on textured parchment",
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
          image_config=types.ImageConfig(
              aspect_ratio="1:1",
              image_size="4K",
          ),
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif image := part.as_image():
          final_image = image

  if final_image:
      final_image.save("butterfly_4k.png")
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";
  import * as fs from "fs";

  const ai = new GoogleGenAI({
    apiKey: process.env.COMETAPI_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.cometapi.com" },
  });

  const response = await ai.models.generateContent({
    model: "gemini-3.1-flash-image-preview",
    contents: "Da Vinci style anatomical sketch of a Monarch butterfly on textured parchment",
    config: {
      responseModalities: ["TEXT", "IMAGE"],
      imageConfig: { aspectRatio: "1:1", imageSize: "4K" },
    },
  });

  const imageParts = response.candidates[0].content.parts.filter(
    (part) => part.inlineData && part.thought !== true,
  );
  const finalImagePart = imageParts.at(-1);

  if (finalImagePart) {
    fs.writeFileSync("butterfly_4k.png", Buffer.from(finalImagePart.inlineData.data, "base64"));
  }
  ```

  ```bash Shell theme={null}
  curl -s -X POST \
    "https://api.cometapi.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent" \
    -H "Authorization: Bearer $COMETAPI_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "contents": [{"parts": [{"text": "Da Vinci style anatomical sketch of a Monarch butterfly on textured parchment"}]}],
      "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {"aspectRatio": "1:1", "imageSize": "4K"}
      }
    }'
  ```
</CodeGroup>

<Note>
  Para las solicitudes de alta resolución, evalúa el resultado según la parte final de imagen que no sea de pensamiento. Si tu integración guarda la primera parte `inlineData`, puede que guarde una imagen de pensamiento intermedia con una resolución inferior a la `imageSize` solicitada.
</Note>

***

## Edición de imágenes en varios turnos (chat)

Usa la función de chat del SDK para refinar imágenes de forma iterativa:

<CodeGroup>
  ```python Python theme={null}
  from google import genai
  from google.genai import types
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
      api_key=os.environ.get("COMETAPI_KEY"),
  )

  chat = client.chats.create(
      model="gemini-3.1-flash-image-preview",
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  ## First turn: Generate
  response = chat.send_message(
      "Create a vibrant infographic explaining photosynthesis as a recipe, styled like a colorful kids cookbook"
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif image := part.as_image():
          final_image = image

  if final_image:
      final_image.save("photosynthesis.png")
  ```

  ## Segundo turno: refinar

  response = chat.send\_message("Update this infographic to be in Spanish. Do not change any other elements.")

  final\_image = None
  for part in response.parts:
  if getattr(part, "thought", False):
  continue
  if part.text is not None:
  print(part.text)
  elif image := part.as\_image():
  final\_image = image

  if final\_image:
  final\_image.save("photosynthesis\_spanish.png")

  ````

  ```javascript Node.js
  import { GoogleGenAI } from "@google/genai";
  import * as fs from "fs";

  const ai = new GoogleGenAI({
    apiKey: process.env.COMETAPI_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.cometapi.com" },
  });

  const chat = ai.chats.create({
    model: "gemini-3.1-flash-image-preview",
    config: { responseModalities: ["TEXT", "IMAGE"] },
  });

  // First turn: generate
  const response1 = await chat.sendMessage(
    "Create a vibrant infographic explaining photosynthesis as a recipe, styled like a colorful kids cookbook"
  );
  const imageParts1 = response1.candidates[0].content.parts.filter(
    (part) => part.inlineData && part.thought !== true,
  );
  const finalImagePart1 = imageParts1.at(-1);
  if (finalImagePart1) {
    fs.writeFileSync("photosynthesis.png", Buffer.from(finalImagePart1.inlineData.data, "base64"));
  }

  // Second turn: refine
  const response2 = await chat.sendMessage(
    "Update this infographic to be in Spanish. Do not change any other elements."
  );
  const imageParts2 = response2.candidates[0].content.parts.filter(
    (part) => part.inlineData && part.thought !== true,
  );
  const finalImagePart2 = imageParts2.at(-1);
  if (finalImagePart2) {
    fs.writeFileSync("photosynthesis_spanish.png", Buffer.from(finalImagePart2.inlineData.data, "base64"));
  }
  ````
</CodeGroup>

***

## Consejos

<AccordionGroup>
  <Accordion title="Optimización del Prompt">
    Especifica palabras clave de estilo (p. ej., "cyberpunk, film grain, low contrast"), relación de aspecto, sujeto, fondo, iluminación y nivel de detalle.
  </Accordion>

  <Accordion title="Formato Base64">
    Al usar HTTP sin procesar, no incluyas el prefijo `data:image/png;base64,` — usa solo la cadena Base64 sin procesar. El SDK de Python maneja esto automáticamente con objetos `PIL.Image`.
  </Accordion>

  <Accordion title="Forzar salida de imagen">
    Establece `"responseModalities"` en `["IMAGE"]` únicamente para garantizar una salida de imagen sin texto.
  </Accordion>

  <Accordion title="¿Por qué mi imagen está borrosa o tiene menor resolución?">
    Comprueba si tu código guardó una imagen de pensamiento intermedia. Las respuestas de imágenes de Gemini pueden incluir partes de imagen donde `thought` es `true`; estas no son la salida final. Omite las partes con `thought: true` y guarda la última parte de imagen donde exista `inlineData` y `thought` no sea `true`. Si no necesitas salida de texto, solicita `"responseModalities": ["IMAGE"]` para reducir el manejo de respuestas mixtas de texto/imagen.
  </Accordion>
</AccordionGroup>

Para más detalles, consulta la [Referencia de la API](/api/image/gemini/gemini-generates-image).

**Documentación oficial:** [Generación de imágenes de Nano Banana](https://ai.google.dev/gemini-api/docs/image-generation)

* [Comprensión de imágenes de Gemini](https://ai.google.dev/gemini-api/docs/image-understanding)
