Image Generation
AI Gateway supports image generation and editing capabilities. You can generate new images from text prompts, edit existing images, and create variations with natural language instructions.
You can view all available models that support image generation by using the Image filter at the AI Gateway Models page.
Google's Gemini 2.5 Flash Image model offers state-of-the-art image generation and editing capabilities. This model supports specifying response modalities to enable image outputs alongside text responses.
You can find details on this model in the Model Library.
Generate images from text prompts using the generateText
function with appropriate provider options:
import 'dotenv/config';
import { generateText } from 'ai';
import fs from 'node:fs';
import path from 'node:path';
async function main() {
const result = await generateText({
model: 'google/gemini-2.5-flash-image-preview',
providerOptions: {
google: { responseModalities: ['TEXT', 'IMAGE'] },
},
prompt:
'Render two versions of a pond tortoise sleeping on a log in a lake at sunset.',
});
if (result.text) {
console.log(result.text);
}
// Save generated images to local filesystem
const imageFiles = result.files.filter((f) =>
f.mediaType?.startsWith('image/'),
);
if (imageFiles.length > 0) {
// Create output directory if it doesn't exist
const outputDir = 'output';
fs.mkdirSync(outputDir, { recursive: true });
const timestamp = Date.now();
for (const [index, file] of imageFiles.entries()) {
const extension = file.mediaType?.split('/')[1] || 'png';
const filename = `image-${timestamp}-${index}.${extension}`;
const filepath = path.join(outputDir, filename);
await fs.promises.writeFile(filepath, file.uint8Array);
console.log(`Saved image to ${filepath}`);
}
}
console.log();
console.log('Usage: ', JSON.stringify(result.usage, null, 2));
console.log(
'Provider metadata: ',
JSON.stringify(result.providerMetadata, null, 2),
);
}
main().catch(console.error);
import 'dotenv/config';
import { streamText } from 'ai';
import fs from 'node:fs';
import path from 'node:path';
async function main() {
const result = streamText({
model: 'google/gemini-2.5-flash-image-preview',
providerOptions: {
google: { responseModalities: ['TEXT', 'IMAGE'] },
},
prompt: 'Render a pond tortoise sleeping on a log in a lake at sunset.',
});
// Create output directory if it doesn't exist
const outputDir = 'output';
fs.mkdirSync(outputDir, { recursive: true });
const timestamp = Date.now();
let imageIndex = 0;
for await (const delta of result.fullStream) {
switch (delta.type) {
case 'text-delta': {
process.stdout.write(delta.text);
break;
}
case 'file': {
if (delta.file.mediaType.startsWith('image/')) {
console.log();
const extension = delta.file.mediaType?.split('/')[1] || 'png';
const filename = `image-${timestamp}-${imageIndex}.${extension}`;
const filepath = path.join(outputDir, filename);
await fs.promises.writeFile(filepath, delta.file.uint8Array);
console.log(`Saved image to ${filepath}`);
imageIndex++;
}
break;
}
}
}
process.stdout.write('\n\n');
console.log();
console.log('Finish reason: ', result.finishReason);
console.log('Usage: ', JSON.stringify(await result.usage, null, 2));
console.log(
'Provider metadata: ',
JSON.stringify(await result.providerMetadata, null, 2),
);
}
main().catch(console.error);
import { type ModelMessage, streamText } from 'ai';
import 'dotenv/config';
import * as readline from 'node:readline/promises';
import fs from 'node:fs';
import path from 'node:path';
const terminal = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const messages: ModelMessage[] = [];
async function main() {
// Create output directory if it doesn't exist
const outputDir = 'output';
fs.mkdirSync(outputDir, { recursive: true });
while (true) {
messages.push({ role: 'user', content: await terminal.question('You: ') });
const result = streamText({
model: 'google/gemini-2.5-flash-image-preview',
providerOptions: {
google: { responseModalities: ['TEXT', 'IMAGE'] },
},
messages,
});
process.stdout.write('\nAssistant: ');
const timestamp = Date.now();
let imageIndex = 0;
for await (const delta of result.fullStream) {
switch (delta.type) {
case 'text-delta': {
process.stdout.write(delta.text);
break;
}
case 'file': {
if (delta.file.mediaType.startsWith('image/')) {
console.log();
const extension = delta.file.mediaType?.split('/')[1] || 'png';
const filename = `chat-image-${timestamp}-${imageIndex}.${extension}`;
const filepath = path.join(outputDir, filename);
await fs.promises.writeFile(filepath, delta.file.uint8Array);
console.log(`💾 Saved image to ${filepath}`);
imageIndex++;
}
break;
}
}
}
process.stdout.write('\n\n');
console.log('Usage: ', JSON.stringify(await result.usage, null, 2));
console.log(
'Provider metadata: ',
JSON.stringify(await result.providerMetadata, null, 2),
);
messages.push(...(await result.response).messages);
}
}
main().catch(console.error);
Check the AI SDK provider documentation for more on provider/model-specific image generation configuration.
Generated images are returned as GeneratedFile
objects in the result.files
array. Each contains:
base64
: The file as a base 64 data stringuint8Array
: The file as aUint8Array
mediaType
: The MIME type (e.g.,image/png
,image/jpeg
)
When using streamText
, images are delivered through fullStream
as file
events:
for await (const delta of result.fullStream) {
switch (delta.type) {
case 'text-delta':
// Handle text chunks
process.stdout.write(delta.text);
break;
case 'file':
// Handle generated files (images)
if (delta.file.mediaType.startsWith('image/')) {
await saveImage(delta.file);
}
break;
}
}
Was this helpful?