Skip to content

Commit 8ace770

Browse files
PederHPclaude
andcommitted
feat: add gpt-image-2 and gpt-image-1-mini; --resolution support for gpt-image-2
- Default OpenAI model is now gpt-image-2 - gpt-image-1-mini added to help output - --resolution now accepted for gpt-image-2 as WxH (e.g. 2048x1152) or aspect ratio (e.g. 3:2) - Client-side validation: multiples of 16, max edge 3840px, long:short ratio <= 3:1, total pixels 655,360-8,294,400 - Older OpenAI models continue to reject --resolution - Bump version to 1.1.0 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e369def commit 8ace770

5 files changed

Lines changed: 110 additions & 16 deletions

File tree

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Multi-provider image generation CLI using .NET 10 and System.CommandLine.
2626
**Provider Pattern:**
2727
- `IImageGenerationClient` - common interface for all providers
2828
- `GeminiImageClient` - Google Gemini API (gemini-2.5-flash-image, gemini-3-pro-image-preview)
29-
- `OpenAIImageClient` - OpenAI API (gpt-image-1.5, gpt-image-1)
29+
- `OpenAIImageClient` - OpenAI API (gpt-image-2, gpt-image-1.5, gpt-image-1, gpt-image-1-mini)
3030
- `BflImageClient` - Black Forest Labs FLUX API (flux-2-pro, flux-2-flex, flux-2-max)
3131
- `PoeImageClient` - Poe.com API (unified access to many models)
3232

@@ -47,7 +47,7 @@ Parameters validated at runtime - using unsupported options with a provider caus
4747
|-----------|--------|--------|-----|-----|
4848
| `--system-prompt` | Supported | Error | Error | Error |
4949
| `--temperature` | Supported (0.0-2.0) | Error | Error | Error |
50-
| `--resolution` | Pro models only | Error | Supported | Model-dependent |
50+
| `--resolution` | Pro models only | gpt-image-2 only | Supported | Model-dependent |
5151
| `--quality` | Error | Supported | Error | Supported |
5252
| `--samples` max | 4 | 10 | 10 | 10 |
5353
| `--images` max | N/A | N/A | 8 | N/A |

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ image-gen --list-models -p poe
119119

120120
| Feature | Gemini | OpenAI | BFL | Poe |
121121
|---------|--------|--------|-----|-----|
122-
| Default model | gemini-2.5-flash-image | gpt-image-1.5 | flux-2-pro | GPT-Image-1 |
122+
| Default model | gemini-2.5-flash-image | gpt-image-2 | flux-2-pro | GPT-Image-1 |
123123
| System prompts | Yes | No | No | No |
124124
| Temperature control | Yes | No | No | No |
125-
| Resolution control | Pro models | No | Yes | Model-dependent |
125+
| Resolution control | Pro models | gpt-image-2 only | Yes | Model-dependent |
126126
| Quality control | No | Yes | No | Yes |
127127
| Max images per request | 4 | 10 | 10 | 10 |
128128
| Max reference images | N/A | N/A | 8 | N/A |

src/ImageGenCli.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<PackAsTool>true</PackAsTool>
1212
<ToolCommandName>image-gen</ToolCommandName>
1313
<PackageId>ImageGenCli</PackageId>
14-
<Version>1.0.0</Version>
14+
<Version>1.1.0</Version>
1515
<Description>Multi-provider image generation CLI supporting Gemini, OpenAI, BFL FLUX, and Poe</Description>
1616
<Authors>image-gen-cli contributors</Authors>
1717
<PackageReadmeFile>README.md</PackageReadmeFile>

src/OpenAIImageClient.cs

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace ImageGenCli;
77

88
/// <summary>
99
/// Image generation client for OpenAI API.
10-
/// Supports gpt-image-1.5 and gpt-image-1 models.
10+
/// Supports gpt-image-2, gpt-image-1.5, gpt-image-1, and gpt-image-1-mini models.
1111
/// </summary>
1212
public class OpenAIImageClient : IImageGenerationClient
1313
{
@@ -20,8 +20,8 @@ public class OpenAIImageClient : IImageGenerationClient
2020
/// Creates a new OpenAI image client.
2121
/// </summary>
2222
/// <param name="apiKey">The OpenAI API key.</param>
23-
/// <param name="model">The model to use (default: gpt-image-1.5).</param>
24-
public OpenAIImageClient(string apiKey, string model = "gpt-image-1.5")
23+
/// <param name="model">The model to use (default: gpt-image-2).</param>
24+
public OpenAIImageClient(string apiKey, string model = "gpt-image-2")
2525
{
2626
_apiKey = apiKey;
2727
_model = model;
@@ -54,7 +54,7 @@ private async Task<string> GenerateTextOnlyAsync(GenerationRequest request, Canc
5454
["model"] = _model,
5555
["prompt"] = request.Prompt,
5656
["n"] = request.NumberOfImages,
57-
["size"] = MapSize(request.AspectRatio)
57+
["size"] = ResolveSize(request)
5858
};
5959

6060
if (!string.IsNullOrEmpty(request.Quality))
@@ -85,7 +85,7 @@ private async Task<string> GenerateWithImagesAsync(GenerationRequest request, Ca
8585
form.Add(new StringContent(_model), "model");
8686
form.Add(new StringContent(request.Prompt), "prompt");
8787
form.Add(new StringContent(request.NumberOfImages.ToString()), "n");
88-
form.Add(new StringContent(MapSize(request.AspectRatio)), "size");
88+
form.Add(new StringContent(ResolveSize(request)), "size");
8989

9090
if (!string.IsNullOrEmpty(request.Quality))
9191
{
@@ -141,6 +141,18 @@ private static GenerationResult ParseResponse(string content)
141141
return result;
142142
}
143143

144+
private string ResolveSize(GenerationRequest request)
145+
{
146+
if (_model == "gpt-image-2" && !string.IsNullOrEmpty(request.Resolution) && request.Resolution != "1K")
147+
{
148+
if (TryResolveSize(request.Resolution, out var size, out _))
149+
{
150+
return size;
151+
}
152+
}
153+
return MapSize(request.AspectRatio);
154+
}
155+
144156
private static string MapSize(string aspectRatio)
145157
{
146158
// OpenAI uses pixel dimensions, map from aspect ratio
@@ -154,4 +166,71 @@ private static string MapSize(string aspectRatio)
154166
_ => "1024x1024"
155167
};
156168
}
169+
170+
/// <summary>
171+
/// Resolves a --resolution value for gpt-image-2, accepting either WxH (e.g. "2048x1152")
172+
/// or an aspect ratio (e.g. "3:2"). Validates gpt-image-2 constraints client-side:
173+
/// each edge a multiple of 16, max edge ≤ 3840, long:short ratio ≤ 3:1,
174+
/// total pixels in [655,360, 8,294,400].
175+
/// </summary>
176+
public static bool TryResolveSize(string input, out string size, out string error)
177+
{
178+
size = "";
179+
error = "";
180+
181+
// Aspect-ratio form → pick a sensible preset.
182+
if (input.Contains(':') && !input.Contains('x', StringComparison.OrdinalIgnoreCase))
183+
{
184+
size = input switch
185+
{
186+
"1:1" => "2048x2048",
187+
"3:2" or "16:9" => "2048x1152",
188+
"2:3" or "9:16" => "1152x2048",
189+
"4:3" => "2048x1536",
190+
"3:4" => "1536x2048",
191+
_ => ""
192+
};
193+
if (size == "")
194+
{
195+
error = $"Unsupported aspect ratio '{input}' for gpt-image-2 --resolution. Try WxH (e.g. 2048x1152) or 1:1, 3:2, 2:3, 16:9, 9:16, 4:3, 3:4.";
196+
return false;
197+
}
198+
return true;
199+
}
200+
201+
// WxH form.
202+
var parts = input.ToLowerInvariant().Split('x');
203+
if (parts.Length != 2 || !int.TryParse(parts[0], out var w) || !int.TryParse(parts[1], out var h))
204+
{
205+
error = $"Invalid --resolution '{input}'. Expected WxH (e.g. 2048x1152) or aspect ratio (e.g. 3:2).";
206+
return false;
207+
}
208+
209+
if (w % 16 != 0 || h % 16 != 0)
210+
{
211+
error = $"gpt-image-2 requires both dimensions be multiples of 16 (got {w}x{h}).";
212+
return false;
213+
}
214+
if (w > 3840 || h > 3840)
215+
{
216+
error = $"gpt-image-2 max edge length is 3840px (got {w}x{h}).";
217+
return false;
218+
}
219+
var longEdge = Math.Max(w, h);
220+
var shortEdge = Math.Min(w, h);
221+
if (longEdge > shortEdge * 3)
222+
{
223+
error = $"gpt-image-2 long:short edge ratio must not exceed 3:1 (got {w}x{h}).";
224+
return false;
225+
}
226+
long pixels = (long)w * h;
227+
if (pixels < 655_360 || pixels > 8_294_400)
228+
{
229+
error = $"gpt-image-2 total pixels must be between 655,360 and 8,294,400 (got {pixels:N0} from {w}x{h}).";
230+
return false;
231+
}
232+
233+
size = $"{w}x{h}";
234+
return true;
235+
}
157236
}

src/Program.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
var resolutionOption = new Option<string>("--resolution", "-r")
3434
{
35-
Description = "Output resolution: 1K, 2K, 4K (Gemini Pro, BFL, some Poe models)",
35+
Description = "Output resolution: 1K, 2K, 4K (Gemini Pro, BFL, some Poe models); WxH or aspect ratio for OpenAI gpt-image-2",
3636
DefaultValueFactory = _ => "1K"
3737
};
3838

@@ -147,7 +147,7 @@
147147
// Determine model based on provider
148148
var model = modelOverride ?? provider switch
149149
{
150-
"openai" => "gpt-image-1.5",
150+
"openai" => "gpt-image-2",
151151
"bfl" => "flux-2-pro",
152152
"poe" => "GPT-Image-1",
153153
_ => "gemini-2.5-flash-image"
@@ -205,11 +205,19 @@
205205

206206
if (provider == "openai")
207207
{
208-
if (resolution != "1K")
208+
if (resolution != "1K" && model != "gpt-image-2")
209209
{
210-
Console.Error.WriteLine("Error: --resolution is not supported by OpenAI. Use --quality instead.");
210+
Console.Error.WriteLine($"Error: --resolution is only supported on gpt-image-2 (got model '{model}'). Use --quality instead.");
211211
return 1;
212212
}
213+
if (model == "gpt-image-2" && resolution != "1K")
214+
{
215+
if (!OpenAIImageClient.TryResolveSize(resolution, out _, out var sizeError))
216+
{
217+
Console.Error.WriteLine($"Error: {sizeError}");
218+
return 1;
219+
}
220+
}
213221
if (!string.IsNullOrEmpty(systemPrompt))
214222
{
215223
Console.Error.WriteLine("Error: --system-prompt is not supported by OpenAI.");
@@ -379,8 +387,15 @@ static void PrintModelsForProvider(string provider)
379387
break;
380388

381389
case "openai":
382-
Console.WriteLine(" gpt-image-1.5 (default) Latest model, exceptional quality");
383-
Console.WriteLine(" gpt-image-1 Previous generation model");
390+
Console.WriteLine(" gpt-image-2 (default) Latest model, supports --resolution (WxH or aspect ratio)");
391+
Console.WriteLine(" gpt-image-1.5 Previous generation model");
392+
Console.WriteLine(" gpt-image-1 Earlier generation model");
393+
Console.WriteLine(" gpt-image-1-mini Lightweight model for basic generation");
394+
Console.WriteLine();
395+
Console.WriteLine("gpt-image-2 --resolution constraints:");
396+
Console.WriteLine(" WxH form (e.g. 2048x1152): each edge multiple of 16, max edge 3840px,");
397+
Console.WriteLine(" long:short ratio ≤ 3:1, total pixels between 655,360 and 8,294,400.");
398+
Console.WriteLine(" Aspect ratio form (e.g. 3:2) maps to a preset near 2K.");
384399
break;
385400

386401
case "bfl":

0 commit comments

Comments
 (0)