Firefly Generative Expand & Fill
既存画像を変更するための、関連はあるが異なる2つのAPIについて説明します。Expand はキャンバスを拡大し、新しい領域に新しいコンテンツを生成します。Fill はマスクでガイドされた、既存のキャンバス内の領域を変更または置換します。適切な方を選ぶことが作業の半分であり、残りはマスクの品質です。
このスキルを使用するタイミング
以下の場合にこのスキルを使用します:
- ユーザーが画像のキャンバスを任意の方向に拡張したい場合
- ユーザーが画像の領域(背景、オブジェクト、テキスト領域)を置換または変更したい場合
- キャンペーンで単一のソースアセットから複数のアスペクト比が必要な場合
- クリエイティブチームが画像から不要なオブジェクトを削除したい場合
- ユーザーがインペインティング、アウトペインティング、拡張、または塗りつぶしについて言及した場合
以下の場合にはこのスキルを使用しないでください:
- ユーザーが完全に新しい画像を希望する場合 —
firefly-generate-image-v3-asyncを使用 - ユーザーが既存画像のスタイルバリエーションを希望する場合 —
firefly-generate-similarを使用 - 変換が純粋なラスター編集(シャープネス、色補正)である場合 — Lightroom API を使用
Expand と Fill の比較 — 判断表
| ニーズ | エンドポイント |
|---|---|
| キャンバスを拡大し、新しい領域にコンテンツを生成 | Expand |
| 画像のアスペクト比を変更 (1:1 → 16:9) | Expand |
| オブジェクトを削除し、その領域をパッチ | Fill |
| 被写体を維持したまま背景を置換 | 背景をカバーするマスクで Fill |
| 特定の領域(空、地面、人のシャツ)を置換 | Fill |
| 損傷した領域や不要な領域をインペイント | Fill |
| アウトペイント(古典的なAIアート「フレームの外を生成」) | Expand |
要約すると:キャンバスが大きくなる = Expand。キャンバスはそのまま = Fill。
Generative Expand
ステップ1 — Expand ジョブの送信
curl --silent -X POST 'https://firefly-api.adobe.io/v3/images/expand' \
-H "Authorization: Bearer $FIREFLY_SERVICES_ACCESS_TOKEN" \
-H "X-Api-Key: $FIREFLY_SERVICES_CLIENT_ID" \
-H 'Content-Type: application/json' \
-d '{
"image": {"source": {"uploadId": "$SOURCE_UPLOAD_ID"}},
"size": {"width": 2304, "height": 1280},
"prompt": "a sweeping desert landscape continuing into the distance",
"placement": {
"alignment": {"horizontal": "center", "vertical": "center"}
},
"numVariations": 2
}'
非同期ジョブパターン(jobId、statusUrl、cancelUrl)を返します — firefly-generate-image-v3-async と同じ方法でポーリングします。
placement フィールド
placement は、元の画像が 新しい(より大きな)キャンバス内のどこに配置されるかを制御します:
"placement": {
"alignment": {"horizontal": "center", "vertical": "center"},
"inset": {"left": 0, "top": 0, "right": 0, "bottom": 0}
}
| 配置 | 効果 |
|---|---|
center, center | 元の画像が中央に、すべての辺に均等に拡張 |
left, center | 元の画像が左に、右側に拡張 |
right, top | 元の画像が右上に、下と左に拡張 |
細かいピクセル制御には inset を使用します。典型的なパターン:元の画像を中央に、均等に拡張します。ソーシャルメディアのバリエーション(ランドスケープ→ポートレート)の場合は、被写体がセーフエリアに収まるように元の画像を中央からオフセットして配置します。
Expand の prompt フィールド
プロンプトは、新しい(拡張された)領域に何を含めるべきかを説明します。元の画像はそのままです。例:
| 元の画像 | プロンプト | 結果 |
|---|---|---|
| 人物のポートレート | "the rest of their body in a business suit" | 元の頭部 + 新しい体 |
| 白い背景の製品 | "a kitchen counter with morning light" | シーン内の製品 |
| 風景のクローズアップ | "a vast sky with scattered clouds above" | シーンが上に続く |
prompt を空のままにすると、Firefly が既存のコンテンツをスタイル的に拡張します(クロップ/リクロップワークフローで一般的)。
アスペクト比レシピ
一般的なプロダクションユースケース:
| 元のサイズ | 変換後 | size | placement.alignment |
|---|---|---|---|
| 1024×1024 (1:1) | 1408×768 (16:9 ランドスケープ) | width 1408, height 768 | center, center |
| 1024×1024 (1:1) | 768×1408 (9:16 ポートレート) | width 768, height 1408 | center, top (顔の下部) |
| 1408×768 (キーアート) | 2304×1280 (シネマティック) | width 2304, height 1280 | center, center |
| 1024×1024 (スクエア) | 1024×1792 (ストーリー ポートレート) | width 1024, height 1792 | center, top |
Generative Fill
ステップ1 — マスクの準備
Fill には、Firefly にどの領域を変更するかを指示するマスクが必要です。白ピクセル = この領域を塗りつぶす。黒ピクセル = そのまま保持。グレースケール = ソフトブレンド。
マスクはソース画像と同じ寸法でなければなりません。マスクはクライアント側(画像エディター、Photoshop API、または sharp / pillow を使用したプログラム)で生成し、ストレージ参照としてアップロードします。
# マスクのアップロード
MASK_UPLOAD_ID=$(curl --silent -X POST 'https://firefly-api.adobe.io/v2/storage/image' \
-H "Authorization: Bearer $FIREFLY_SERVICES_ACCESS_TOKEN" \
-H "X-API-Key: $FIREFLY_SERVICES_CLIENT_ID" \
-H "Content-Type: image/png" \
--data-binary "@./mask.png" \
| jq -r '.images[0].id')
ステップ2 — Fill ジョブの送信
curl --silent -X POST 'https://firefly-api.adobe.io/v3/images/fill' \
-H "Authorization: Bearer $FIREFLY_SERVICES_ACCESS_TOKEN" \
-H "X-Api-Key: $FIREFLY_SERVICES_CLIENT_ID" \
-H 'Content-Type: application/json' \
-d '{
"image": {
"source": {"uploadId": "$SOURCE_UPLOAD_ID"},
"mask": {"source": {"uploadId": "$MASK_UPLOAD_ID"}}
},
"prompt": "a modern minimalist living room background",
"numVariations": 2
}'
非同期ジョブパターンを返します — 完了するまでポーリングします。
Fill の prompt フィールド
プロンプトは、マスクされた領域に何を表示するかを説明します。マスクされていない領域はそのままです。
| マスクの対象 | プロンプト | 結果 |
|---|---|---|
| 製品ショットの背景 | "marble kitchen counter" | 製品はそのまま、新しい背景 |
| 不要な人物 | "empty park bench" | 人物が削除され、ベンチが領域を埋める |
| ラベル領域 | "minimal white space" | ラベルがなくなり、領域がクリーンに |
| 車両の色領域 | "matte red paint" | 車両が赤に |
マスク生成戦略
| 戦略 | ツール | いつ使用するか |
|---|---|---|
| 手動マスク | Photoshop、画像エディター | 単発のクリエイティブ作業 |
| プログラムによるマスク | sharp、pillow | 幾何学的な領域(上半分、左3分の1) |
| 被写体検出 | Photoshop API select_subject またはカスタムセグメンテーション | 背景の置換、被写体の分離 |
| カラーキーマスク | sharp しきい値処理 | 特定の色の領域の置換 |
| AI セグメンテーション | SAM (Segment Anything)、Mediapipe | プロダクションセグメンテーションパイプライン |
高スループットワークフロー(毎日数百のキーアートアセットの背景拡張)の場合、マスクは被写体検出からプログラム的に生成されます — 手動では決してありません。
パイプラインでの Expand と Fill の組み合わせ
一般的なプロダクションパイプライン:
ソースキーアート (1408×768)
↓ Expand (2304×1280 へ、シーンを拡張するプロンプト)
拡張された画像
↓ Fill (マスクはテキスト領域をカバー、プロンプト: "clean background")
クリーンなシネマティックバージョン
↓ Photoshop API アクションの適用 (テキストオーバーレイ、レイヤーコンポジション)
最終アセット
これは、凝縮された標準的なキーアート生成パターンです。各ステージは非同期ジョブです。パイプラインはキューで管理されます(firefly-services-rate-limits を参照)。
プロダクションパターン
パターン: 単一ソースからのマルチアスペクト生成
1つのスクエアキーアートから、ランドスケープ + ポートレート + ストーリーフォーマットを生成します:
const aspects = [
{ name: 'landscape-16-9', size: { width: 1408, height: 768 }, alignment: { horizontal: 'center', vertical: 'center' } },
{ name: 'portrait-9-16', size: { width: 768, height: 1408 }, alignment: { horizontal: 'center', vertical: 'top' } },
{ name: 'story-9-16', size: { width: 1024, height: 1792 }, alignment: { horizontal: 'center', vertical: 'top' } },
];
const jobs = await Promise.all(
aspects.map(a => submitExpand({
sourceUploadId: SOURCE_ID,
size: a.size,
placement: { alignment: a.alignment },
prompt: 'continue the scene naturally',
numVariations: 2,
})),
);
3つの送信で、並行して約6つの出力が得られます。それぞれをアスペクトタグとともに永続化し、下流のクリエイティブチームに渡します。
パターン: スケールでの背景置換
ブランドキャンペーンクリエイター向けの背景スワップの場合:
ソース画像
↓ Photoshop API: select_subject → マスク (被写体 白, 背景 黒)
↓ マスクを反転 (被写体 黒, 背景 白) — Sharp/Pillow
反転したマスクで Fill リクエスト
↓ プロンプト: "<brand-aligned background>"
出力: 被写体はそのまま、新しい背景
反転ステップは重要です — Photoshop の select_subject は被写体マスクを提供しますが、背景置換にはその逆が必要です。
検証
Expand/Fill パイプラインは、以下の場合にプロダクション対応となります:
- Expand と Fill の判断がユースケースごとに文書化されている
- マスク生成が自動化されており、手動ではない(50を超えるボリュームの場合)
- マスクが送信前に正しい寸法と適切な極性であることが検証されている
- 出力が成功とマークされる前に、ソースと視覚的に検査されている
- マルチアスペクトパイプラインが逐次ではなく並行で送信されている
placementの決定がブランドのセーフエリアガイドラインに沿っている
トラブルシューティングとエッジケース
- Expand 出力で元のコンテンツと新しいコンテンツの間に継ぎ目が見える: 元の画像に異常な色や粒状感がある可能性があります。シードを変更して再生成するか、ソースの品質を説明するプロンプトで Expand を試してみてください。
- Fill プロンプトが無視される: マスクが反転している可能性が高いです(白=保持、黒=塗りつぶし のはずが逆になっている)。マスクの極性を再確認してください。
- Fill 出力がマスクの外側ににじむ: マスクのエッジが柔らかすぎます(ガウシアンブラーが強すぎる)。マスクのエッジをシャープにするか、バイナリマスクを使用してください。
- Expand で被写体の配置が予期せず変更される:
placement.alignmentを明示的に設定してください。デフォルトでは被写体が移動する可能性があります。 - マスクが大きすぎる (>8MB): マスクを圧縮してください。限定パレットのシングルチャンネルグレースケール PNG は通常、適切に圧縮されます。
- 極端なアスペクト比への Expand が不自然に見える: Expand を2ステップで行ってください:元の → 中間 → 最終。各ステップでの変化を小さくします。
- Fill で被写体が完全に削除される: マスクが被写体に重なっています。マスクを背景のみに絞ってください。
他のスキルとの連携
firefly-services-storage-refs— マスク + ソースのアップロードfirefly-generate-image-v3-async— 同じ非同期パターンphotoshop-api-actions— 自動マスク生成用 (select_subject)firefly-services-rate-limits— バッチパイプライン用