Files
codex/codex-rs/codex-api/src/images.rs
T
Gan Tu f9e7b19df8 Add optional animated GIF output to image generation (#59073)
## What changed

- Gate GIF output behind `features.image_generation_animation`, disabled by default.
- Accept `gif` options for generation and editing, with optional `frame_count` and `frame_duration_ms` controls. Use `gif: {}` for API defaults.
- Preserve animated output with `.gif` filenames and `image/gif` data URLs while providing a still preview to the model.
- Add guidance for simple animations and spritesheet-based GIF edits.

## Testing

Add integration coverage for GIF generation and editing, explicit frame controls and API defaults, saved animation bytes, and still-preview replay across follow-up turns.

GitOrigin-RevId: 08afa0316ae3675921652157836191a649f563cf
2026-11-03 06:24:24 +00:00

94 lines
2.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use codex_protocol::models::ImageReference;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct ImageGenerationRequest {
pub prompt: String,
#[serde(flatten)]
pub output: Option<ImageOutput>,
#[serde(skip_serializing_if = "Option::is_none")]
pub background: Option<ImageBackground>,
pub model: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub n: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quality: Option<ImageQuality>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<String>,
}
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct ImageEditRequest {
pub images: Vec<ImageReference>,
pub prompt: String,
#[serde(flatten)]
pub output: Option<ImageOutput>,
#[serde(skip_serializing_if = "Option::is_none")]
pub background: Option<ImageBackground>,
pub model: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub n: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quality: Option<ImageQuality>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<String>,
}
/// Optional GIF controls accepted by the Images generation and edit endpoints.
#[derive(Debug, Clone, Copy, Deserialize, Serialize, JsonSchema, PartialEq)]
pub struct GifOptions {
/// Number of frames (2–16). Defaults to 9.
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 2, max = 16))]
pub frame_count: Option<u32>,
/// Duration of each frame in milliseconds (20–2000). Defaults to 200.
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(range(min = 20, max = 2000))]
pub frame_duration_ms: Option<u32>,
}
/// The Images API expects the format and its controls as sibling fields.
#[derive(Debug, Clone, Copy, Serialize, PartialEq)]
#[serde(tag = "output_format", rename_all = "lowercase")]
pub enum ImageOutput {
Gif(GifOptions),
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ImageBackground {
Transparent,
Opaque,
Auto,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ImageQuality {
Low,
Medium,
High,
Auto,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
pub struct ImageResponse {
pub created: u64,
pub data: Vec<ImageData>,
#[serde(default)]
pub background: Option<ImageBackground>,
#[serde(default)]
pub quality: Option<ImageQuality>,
#[serde(default)]
pub size: Option<String>,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
pub struct ImageData {
pub b64_json: String,
#[serde(default)]
pub generation_id: Option<String>,
}