141}141}
142```142```
143 143
144```ruby
145require "base64"
146require "openai"
147
148client = OpenAI::Client.new
149result = client.images.generate(
150 model: "gpt-image-2",
151 prompt: "A watercolor robot reading in a library"
152)
153generated_image = result.data&.first or raise "No image returned"
154File.binwrite(
155 "generated-image.png",
156 Base64.strict_decode64(generated_image.b64_json)
157)
158```
159
144```bash160```bash
145curl -X POST "https://api.openai.com/v1/images/generations" \161curl -X POST "https://api.openai.com/v1/images/generations" \
146 -H "Authorization: Bearer $OPENAI_API_KEY" \162 -H "Authorization: Bearer $OPENAI_API_KEY" \
261}277}
262```278```
263 279
280```ruby
281require "base64"
282require "openai"
283
284client = OpenAI::Client.new
285response = client.responses.create(
286 model: "gpt-5.6",
287 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",
288 tools: [{type: :image_generation}]
289)
290
291image_call = response.output.find do |item|
292 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
293end
294unless image_call.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
295 raise "No image generation call returned"
296end
297
298encoded_image = image_call.result or raise "No image returned"
299File.binwrite("otter.png", Base64.strict_decode64(encoded_image))
300```
301
264 302
265 303
266### Multi-turn image generation304### Multi-turn image generation
361}399}
362```400```
363 401
402```ruby
403require "base64"
404require "openai"
405
406client = OpenAI::Client.new
407response = client.responses.create(
408 model: "gpt-5.6",
409 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",
410 tools: [{type: :image_generation, action: :generate}]
411)
412
413image_call = response.output.find do |item|
414 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
415end
416unless image_call.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
417 raise "No image generation call returned"
418end
419
420encoded_image = image_call.result or raise "No image returned"
421output_path = ENV.fetch("OPENAI_EXAMPLE_OUTPUT_PATH", "otter.png")
422File.binwrite(output_path, Base64.decode64(encoded_image))
423puts(output_path)
424```
425
364 426
365If you force `edit` without providing an image in context, the call will return an error. Leave `action` at `auto` to have the model decide when to generate or edit.427If you force `edit` without providing an image in context, the call will return an error. Leave `action` at `auto` to have the model decide when to generate or edit.
366 428
518}580}
519```581```
520 582
583```ruby
584require "base64"
585require "openai"
586
587client = OpenAI::Client.new
588first = client.responses.create(
589 model: "gpt-5.6",
590 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",
591 tools: [{type: :image_generation}]
592)
593
594first_image = first.output.find do |item|
595 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
596end
597unless first_image.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
598 raise "No image generation call returned"
599end
600
601encoded_image = first_image.result or raise "No image returned"
602File.binwrite("cat_and_otter.png", Base64.strict_decode64(encoded_image))
603
604follow_up = client.responses.create(
605 model: "gpt-5.6",
606 input: "Now make it look realistic.",
607 previous_response_id: first.id,
608 tools: [{type: :image_generation}]
609)
610
611follow_up_image = follow_up.output.find do |item|
612 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
613end
614unless follow_up_image.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
615 raise "No follow-up image generation call returned"
616end
617
618encoded_image = follow_up_image.result or raise "No follow-up image returned"
619File.binwrite("cat_and_otter_realistic.png", Base64.strict_decode64(encoded_image))
620```
621
521 622
522 623
523 624
709}810}
710```811```
711 812
813```ruby
814require "base64"
815require "openai"
816
817client = OpenAI::Client.new
818first = client.responses.create(
819 model: "gpt-5.6",
820 input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",
821 tools: [{type: :image_generation}]
822)
823
824first_image = first.output.find do |item|
825 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
826end
827unless first_image.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
828 raise "No image generation call returned"
829end
830
831encoded_image = first_image.result or raise "No image returned"
832File.binwrite("cat_and_otter.png", Base64.strict_decode64(encoded_image))
833
834follow_up = client.responses.create(
835 model: "gpt-5.6",
836 input: [
837 {
838 role: :user,
839 content: [{type: :input_text, text: "Now make it look realistic."}]
840 },
841 {type: :image_generation_call, id: first_image.id}
842 ],
843 tools: [{type: :image_generation}]
844)
845
846follow_up_image = follow_up.output.find do |item|
847 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
848end
849unless follow_up_image.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
850 raise "No follow-up image generation call returned"
851end
852
853encoded_image = follow_up_image.result or raise "No follow-up image returned"
854File.binwrite("cat_and_otter_realistic.png", Base64.strict_decode64(encoded_image))
855```
856
712 857
713 858
714#### Result859#### Result
887}1032}
888```1033```
889 1034
1035```ruby
1036require "base64"
1037require "openai"
1038
1039client = OpenAI::Client.new
1040stream = client.responses.stream(
1041 model: "gpt-5.6",
1042 input: "Generate an image of a river made of white owl feathers.",
1043 tools: [{type: :image_generation, partial_images: 2}]
1044)
1045
1046stream.each do |event|
1047 case event
1048 when OpenAI::Models::Responses::ResponseImageGenCallPartialImageEvent
1049 image = Base64.strict_decode64(event.partial_image_b64)
1050 File.binwrite("river-partial-#{event.partial_image_index}.png", image)
1051 when OpenAI::Models::Responses::ResponseCompletedEvent
1052 image_call = event.response.output.find do |item|
1053 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
1054 end
1055 next unless image_call.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
1056
1057 File.binwrite(
1058 "river-final.png",
1059 Base64.strict_decode64(image_call.result)
1060 )
1061 end
1062end
1063```
1064
890 1065
891 1066
892 1067
986}1161}
987```1162```
988 1163
1164```ruby
1165require "base64"
1166require "openai"
1167
1168client = OpenAI::Client.new
1169stream = client.images.generate_stream_raw(
1170 model: "gpt-image-2",
1171 prompt: "A river made of white owl feathers in a winter landscape",
1172 partial_images: 2
1173)
1174
1175stream.each do |event|
1176 next unless event.is_a?(OpenAI::Models::ImageGenPartialImageEvent)
1177
1178 image = Base64.strict_decode64(event.b64_json)
1179 File.binwrite("river#{event.partial_image_index}.png", image)
1180end
1181```
1182
989 1183
990 1184
991#### Result1185#### Result
1115}1309}
1116```1310```
1117 1311
1312```ruby
1313require "openai"
1314require "pathname"
1315
1316client = OpenAI::Client.new
1317file = client.files.create(
1318 file: Pathname("image.png"),
1319 purpose: OpenAI::Models::FilePurpose::VISION
1320)
1321puts(file.id)
1322```
1323
1118 1324
1119#### Create a base64 encoded image1325#### Create a base64 encoded image
1120 1326
1157}1363}
1158```1364```
1159 1365
1366```ruby
1367require "base64"
1368
1369image = File.binread("image.png")
1370puts(Base64.strict_encode64(image))
1371```
1372
1160 1373
1161Edit an image1374Edit an image
1162 1375
1380}1593}
1381```1594```
1382 1595
1596```ruby
1597require "base64"
1598require "openai"
1599require "pathname"
1600
1601client = OpenAI::Client.new
1602base64_images = ["body-lotion.png", "soap.png"].map do |path|
1603 Base64.strict_encode64(File.binread(path))
1604end
1605file_ids = [
1606 client.files.create(file: Pathname("bath-bomb.png"), purpose: :vision).id,
1607 client.files.create(file: Pathname("incense-kit.png"), purpose: :vision).id
1608]
1609prompt = <<~PROMPT
1610 Generate a photorealistic image of a gift basket on a white background
1611 labeled 'Relax & Unwind' with a ribbon and handwriting-like font,
1612 containing all the items in the reference pictures.
1613PROMPT
1614response = client.responses.create(
1615 model: "gpt-5.6",
1616 input: [{
1617 role: :user,
1618 content: [
1619 {type: :input_text, text: prompt},
1620 *base64_images.map do |image|
1621 {type: :input_image, image_url: "data:image/png;base64,#{image}"}
1622 end,
1623 *file_ids.map do |file_id|
1624 {type: :input_image, file_id: file_id}
1625 end
1626 ]
1627 }],
1628 tools: [{type: :image_generation}]
1629)
1630
1631image_call = response.output.find do |item|
1632 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
1633end
1634unless image_call.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
1635 raise "No image generation call returned"
1636end
1637
1638File.binwrite("gift-basket.png", Base64.strict_decode64(image_call.result))
1639```
1640
1383 1641
1384 1642
1385 1643
1529}1787}
1530```1788```
1531 1789
1790```ruby
1791require "base64"
1792require "openai"
1793require "pathname"
1794
1795client = OpenAI::Client.new
1796images = %w[body-lotion.png bath-bomb.png incense-kit.png soap.png].map do |path|
1797 Pathname(path)
1798end
1799result = client.images.edit(
1800 image: images,
1801 model: "gpt-image-2",
1802 prompt: <<~PROMPT
1803 Generate a photorealistic image of a gift basket on a white background
1804 labeled 'Relax & Unwind' with a ribbon and handwriting-like font,
1805 containing all the items in the reference pictures.
1806 PROMPT
1807)
1808generated_image = result.data&.first or raise "No image returned"
1809File.binwrite("gift-basket.png", Base64.strict_decode64(generated_image.b64_json))
1810```
1811
1532```bash1812```bash
1533curl -s -D >(grep -i x-request-id >&2) \1813curl -s -D >(grep -i x-request-id >&2) \
1534 -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) \1814 -o >(jq -r '.data[0].b64_json' | base64 --decode > gift-basket.png) \
1754}2034}
1755```2035```
1756 2036
2037```ruby
2038require "base64"
2039require "openai"
2040require "pathname"
2041
2042client = OpenAI::Client.new
2043image = client.files.create(file: Pathname("sunlit_lounge.png"), purpose: :vision)
2044mask = client.files.create(file: Pathname("mask.png"), purpose: :vision)
2045response = client.responses.create(
2046 model: "gpt-5.6",
2047 input: [{
2048 role: :user,
2049 content: [
2050 {type: :input_text, text: "Add a flamingo to the pool."},
2051 {type: :input_image, file_id: image.id}
2052 ]
2053 }],
2054 tools: [{
2055 type: :image_generation,
2056 input_image_mask: {file_id: mask.id}
2057 }]
2058)
2059
2060image_call = response.output.find do |item|
2061 item.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
2062end
2063unless image_call.is_a?(OpenAI::Models::Responses::ResponseOutputItem::ImageGenerationCall)
2064 raise "No image generation call returned"
2065end
2066
2067File.binwrite("lounge.png", Base64.strict_decode64(image_call.result))
2068```
2069
1757 2070
1758 2071
1759 2072
1850}2163}
1851```2164```
1852 2165
2166```ruby
2167require "openai"
2168require "pathname"
2169require "base64"
2170
2171client = OpenAI::Client.new
2172image = Pathname("sunlit_lounge.png")
2173mask = Pathname("mask.png")
2174result = client.images.edit(
2175 image: image,
2176 mask: mask,
2177 model: "gpt-image-2",
2178 prompt: "A sunlit indoor lounge area with a pool containing a flamingo"
2179)
2180generated_image = result.data&.first or raise "No image returned"
2181File.binwrite("lounge.png", Base64.strict_decode64(generated_image.b64_json))
2182```
2183
1853```bash2184```bash
1854curl -s -D >(grep -i x-request-id >&2) \2185curl -s -D >(grep -i x-request-id >&2) \
1855 -o >(jq -r '.data[0].b64_json' | base64 --decode > lounge.png) \2186 -o >(jq -r '.data[0].b64_json' | base64 --decode > lounge.png) \
2283}2614}
2284```2615```
2285 2616
2617```ruby
2618require "openai"
2619
2620client = OpenAI::Client.new
2621begin
2622 client.images.generate(
2623 model: "gpt-image-2",
2624 prompt: "Create a poster humiliating my coworker with insulting captions"
2625 )
2626rescue OpenAI::Errors::BadRequestError => error
2627 raise unless error.code == "moderation_blocked"
2628
2629 body = Hash.try_convert(error.body) || {}
2630 moderation_details = body[:moderation_details] || body["moderation_details"] || {}
2631 categories = moderation_details[:categories] || moderation_details["categories"] || []
2632 stage = moderation_details[:moderation_stage] || moderation_details["moderation_stage"]
2633
2634 hint = "This request did not meet safety requirements."
2635 if categories.include?("harassment")
2636 hint = "Remove abusive or targeting language and focus on neutral visual details."
2637 elsif stage == "input"
2638 hint = "Revise the prompt or input images, then submit the request again."
2639 elsif stage == "output"
2640 hint = "Change the prompt and generate again; the generated result was blocked."
2641 end
2642
2643 warn("Image generation blocked (#{error.code}): #{hint}")
2644end
2645```
2646
2286 2647
2287### Supported models2648### Supported models
2288 2649