Open1

Node-REDからgpt-image-1は?

n0bisuken0bisuke

ライブラリ依存なしでがんばる

import fs from "fs/promises";
// Node.js 18+ の場合 global.fetch が使えます。
// それ以前は: import fetch from "node-fetch";

const API_KEY = "キー";

async function ghibliStyleEdit(inputPath, outputPath) {
  // 1) 画像を読み込んで Buffer 化
  const imageBuffer = await fs.readFile(inputPath);

  // 2) ランダム boundary と定数
  const boundary = "----NodeRedBoundary" + Math.random().toString(36).slice(2);
  const CRLF = "\r\n";
  const parts = [];

  // 3) ヘルパー関数
  function appendField(name, value) {
    parts.push(Buffer.from(
      `--${boundary}${CRLF}` +
      `Content-Disposition: form-data; name="${name}"${CRLF}${CRLF}` +
      `${value}${CRLF}`
    ));
  }
  function appendFile(name, buffer, filename, contentType) {
    parts.push(Buffer.from(
      `--${boundary}${CRLF}` +
      `Content-Disposition: form-data; name="${name}"; filename="${filename}"${CRLF}` +
      `Content-Type: ${contentType}${CRLF}${CRLF}`
    ));
    parts.push(buffer);
    parts.push(Buffer.from(CRLF));
  }

  // 4) 各パーツを組み立て
  appendField("model", "gpt-image-1");
  appendField("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`);
  appendField("quality", "medium");
  appendFile("image", imageBuffer, "input.png", "image/png");

  // 終端 boundary
  parts.push(Buffer.from(`--${boundary}--${CRLF}`));

  // 5) ボディ全体の Buffer を作成
  const bodyBuffer = Buffer.concat(parts);

  // 6) リクエスト
  const res = await fetch("https://api.openai.com/v1/images/edits", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": `multipart/form-data; boundary=${boundary}`,
      "Content-Length": bodyBuffer.length.toString(),
    },
    body: bodyBuffer,
  });

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

  // 7) レスポンス処理
  const { data } = await res.json();
  const outBuffer = Buffer.from(data[0].b64_json, "base64");
  await fs.writeFile(outputPath, outBuffer);
  console.log(`Saved edited image to ${outputPath}`);
}

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