- テキストから画像の生成
- 画像から画像への編集
- 複数画像の合成
- 生成した画像の保存
- Base URL:
https://api.cometapi.com - SDK のインストール:
pip install google-genai(Python)またはnpm install @google/genai(Node.js)
セットアップ
CometAPI のベース URL を指定してクライアントを初期化します。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,
)
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" },
});
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...
}
テキストから画像の生成
テキストプロンプト(Prompt)から画像を生成し、ファイルに保存します。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")
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");
}
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"]
}
}'
candidates[0].content.parts にあり、ここにはテキストパートや画像パートが含まれる場合があります。Gemini の画像モデルは、特にテキストと画像の両方をリクエストした場合や、thinking 出力を明示的に有効にした場合、最終画像の前に中間的な thought パートを返すこともあります。最初の inlineData をそのまま保存してはいけません。thought が true のパートをスキップし、その後に残る最後の画像パートを保存してください。
最終画像のみを含む典型的なレスポンス:
{
"candidates": [{
"content": {
"parts": [
{ "text": "Here is your image..." },
{
"inlineData": {
"mimeType": "image/png",
"data": "<base64-encoded-image>"
}
}
]
}
}]
}
{
"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"
}]
}
const imageParts = response.candidates[0].content.parts.filter(
(part) => part.inlineData && part.thought !== true,
);
const finalImagePart = imageParts.at(-1);
画像から画像への生成
入力画像をアップロードし、テキストプロンプトで変換します。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")
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"));
}
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"] }
}'
- Python SDK は
PIL.Imageオブジェクトを直接受け付けるため、手動での Base64 エンコードは不要です。 - 生の Base64 文字列を渡す際は、
data:image/jpeg;base64,プレフィックスを含めないでください。
複数画像の合成
複数の入力画像から新しい画像を生成します。CometAPI は2つのアプローチをサポートしています。方法 1: 1枚のコラージュ画像
複数の元画像を1つのコラージュにまとめ、その後で希望する出力を説明します。

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")
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"] }
}'
方法 2: 複数の個別画像(最大14枚)
複数の画像を直接渡します。Gemini 3 モデルは最大14枚の参照画像(オブジェクト + キャラクター)をサポートします。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")
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"] }
}'

4K画像生成
高解像度の出力には、aspect_ratio と image_size を含む image_config を指定します。
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")
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"));
}
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"}
}
}'
高解像度リクエストでは、最終的な非thoughtの画像パートを基準に出力を判断してください。統合側で最初の
inlineData パートを保存すると、要求した imageSize よりも低解像度の中間thought画像を保存してしまう場合があります。マルチターン画像編集(チャット)
SDK のチャット機能を使って、画像を反復的にブラッシュアップできます。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")
2 回目のターン: 改良
response = chat.send_message(“このインフォグラフィックをスペイン語にしてください。他の要素は一切変更しないでください。”)
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"));
}
ヒント
プロンプトの最適化
プロンプトの最適化
スタイルのキーワード(例: “cyberpunk, film grain, low contrast”)、アスペクト比、被写体、背景、照明、ディテールのレベルを指定してください。
Base64 形式
Base64 形式
raw HTTP を使用する場合は、
data:image/png;base64, のプレフィックスを含めず、raw Base64 文字列のみを使用してください。Python SDK では、PIL.Image オブジェクトを使うことでこれが自動的に処理されます。画像出力を強制する
画像出力を強制する
テキストなしで画像出力を確実に行うには、
"responseModalities" を ["IMAGE"] のみに設定してください。画像がぼやけている、または解像度が低いのはなぜですか?
画像がぼやけている、または解像度が低いのはなぜですか?
コードが中間の thought image を保存していないか確認してください。Gemini の画像レスポンスには、
thought が true の image part が含まれる場合があります。これらは最終出力ではありません。thought: true の part はスキップし、inlineData が存在し、かつ thought が true ではない最後の image part を保存してください。テキスト出力が不要な場合は、混在したテキスト/画像レスポンスの処理を減らすために "responseModalities": ["IMAGE"] をリクエストしてください。