gpt-image-1のAPIでジブリ風加工のImage to Imageを試す

gpt-image-1楽しいですね。

ChatGPTの4oで画像をジブリ風にして！などが流行ってましたがその機能が使えるAPIって感じです。

画像をインプットして画像を出力するのでImage to Imageです。


> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/aad56243-d626-43ab-aac5-39450aa286fa.png)

## 準備

APIキーは認証が必要なのでやっておきましょう。

```
$ npm i openai
```

ちなみにNode.jsはv24にしてます。

### プロンプト

プロンプトはこちらです。「この画像をジブリ風にしてください」をプロンプトにすると？をo4-miniに考えてもらいまいました。

```
“<IMAGE> → Transform the input image into a hand-painted Studio Ghibli-style illustration.  
• Use a soft pastel color palette and watercolor-like textures  
• Warm, natural lighting with gentle atmospheric haze  
• Painterly brush strokes, delicate gradients, and subtle film grain  
• Whimsical details: floating petals, glowing fireflies, drifting dust motes  
• Lush, detailed backgrounds (rolling hills, ancient trees, quaint villages, or misty forests)  
• Characters (if present): large expressive eyes, gentle facial expressions, flowing hair/clothes  
• Preserve original composition and silhouette  
• Render at high resolution (e.g. 4K), no text or logos  
”
```

## シンプルなコード

本当にサンプルを触ったくらいですが

```js
import fs from "fs";
import OpenAI, { toFile } from "openai";

const client = new OpenAI({apiKey: `APIキー`});

const imageFiles = [
    "kanda-matsuri.png"
];

const images = await Promise.all(
    imageFiles.map(async (file) =>
        await toFile(fs.createReadStream(file), null, {
            type: "image/png",
        })
    ),
);

const rsp = await client.images.edit({
    model: "gpt-image-1",
    image: images,
    prompt: `
<IMAGE> → Transform the input image into a hand-painted Studio Ghibli-style illustration.  
• Use a soft pastel color palette and watercolor-like textures  
• Warm, natural lighting with gentle atmospheric haze  
• Painterly brush strokes, delicate gradients, and subtle film grain  
• Whimsical details: floating petals, glowing fireflies, drifting dust motes  
• Lush, detailed backgrounds (rolling hills, ancient trees, quaint villages, or misty forests)  
• Characters (if present): large expressive eyes, gentle facial expressions, flowing hair/clothes  
• Preserve original composition and silhouette  
• Render at high resolution (e.g. 4K), no text or logos 
    `,
});

// Save the image to a file
const image_base64 = rsp.data[0].b64_json;
const image_bytes = Buffer.from(image_base64, "base64");
fs.writeFileSync("kanda-matsuri-new-1.png", image_bytes);
```

### 出力結果

こんな感じです。2つ出してみた

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/7ba5aff1-c6e1-40cb-b25d-49efcc1dcf12.png)
>
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/aad56243-d626-43ab-aac5-39450aa286fa.png)
 
### 参考: 元画像

https://x.com/n0bisuke/status/1921481084769878287

## SDK無し版

OpenAIのSDK使わない場合はformDataに情報を入れてリクエストしたらできました

```js
import fs from "fs/promises";
import { Blob } from "buffer"; 

const API_KEY = process.env.OPENAI_API_KEY;

async function ghibliStyleEdit(inputPath, outputPath) {
  // 画像を Buffer として読み込む
  const imageBytes = await fs.readFile(inputPath);

  // Web 標準の FormData
  const form = new FormData();
  form.append("model", "gpt-image-1");
  form.append(
    "prompt",
    `<IMAGE> → Transform the input image into a hand-painted Studio Ghibli-style illustration.
• Use a soft pastel color palette and watercolor-like textures
• Warm, natural lighting with gentle atmospheric haze
• Painterly brush strokes, delicate gradients, and subtle film grain
…（省略）…`
  );
  // buffer を Blob に包んでファイルフィールドに
  form.append(
    "image",
    new Blob([imageBytes], { type: "image/png" }),
    "input.png"
  );
  // マスクが必要なら同様に mask フィールドを追加

  const res = await fetch("https://api.openai.com/v1/images/edits", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      // Content-Type は自動でセットされるので不要
    },
    body: form,
  });

  if (!res.ok) {
    const err = await res.text();
    throw new Error(`OpenAI API error: ${res.status} ${err}`);
  }

  const { data } = await res.json();
  const buf = Buffer.from(data[0].b64_json, "base64");
  await fs.writeFile(outputPath, buf);
  console.log(`Saved to ${outputPath}`);
}

// 実行
ghibliStyleEdit("kanda-matsuri.png", "kanda-matsuri-ghibli.png").catch(console.error);
```

## クオリティコントロール

APIの利用料金を節約したい場合はクオリティを下げると良いっぽいです。

- low: 最も安価（約$0.02/画像）
- medium: 中程度のコスト（約$0.07/画像）
- high: 最高品質だが最も高価（約$0.19/画像）


> ローは昔の生成AIっぽい...
> 
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/c44363cd-a3ed-4fd3-bca6-5620dda56491.png)


https://x.com/n0bisuke/status/1922295102090674564

https://x.com/n0bisuke/status/1922294977192698196

https://x.com/n0bisuke/status/1922296636044161445