sue@blog ~ /posts/ai-image-specify-font
$ cd ../
$ cat post.metadata

画像生成AIで“狙ったフォント”を画像に入れる — 名前指定は効かない、style語は系統だけ、確実なのは合成

date: 2026-06-16 生成AI フォント 実験
「このフォントで描いて」がなぜ効かないのか。gpt-imageで実際に試して、効くフォント指定・効かない指定・確実な方法を切り分けた。結論から言うと、狙ったフォントそのものが要るなら合成一択だ。
漢字崩れシリーズの実践編
本編は ① 症状と対処② なぜ崩れる③ 実装対策④ 崩れやすい字リスト
周辺トラブル編に 異体字・旧字体和欧混植 ほか。この記事はそこで何度も出てくる「フォント合成」を、実際に手を動かして検証する回。

先に結論

この記事の実験環境
生成は gpt-image-2 / 不透明 / quality=low(書体の検証なので、崩れにくい強経路に固定)と、対比用の gpt-image-1.5 / 透過 / low。合成は Python + Pillow に実フォント(Noto Sans JP / ヒラギノ明朝・丸ゴ・角ゴ)。題材はクライアント非連想の汎用名「森のパン工房」。

1. 「このフォントで」はなぜ効かないのか

画像生成モデルはフォントエンジンを持っていない。文字は「意味のある記号」ではなく“絵”として一緒に描かれる(→ 本編②「なぜ崩れるのか」)。だから「このフォントファイルで組版する」という概念がそもそも無い。加えて、API のリクエストにフォントを指定する場所が無い(model・prompt・size・quality・background…で、font は無い)。指定しようがないのだ。

実際にやってみる。プロンプトに「フォントは必ず Noto Sans JP を使うこと」と名指ししても、出てくるのは素のゴシックで、ただ「ゴシック体で」と書いたときと見分けがつかない。3回試して毎回同じで、名指しによる差は出なかった(そもそも API にフォントを渡す引数が無い以上、効きようがない)。

「Noto Sans JPを使え」と名指ししても素のゴシックが出ている
gpt-image-2 / 不透明 / low。「フォントは Noto Sans JP を使うこと」と名指ししても、出るのは素のゴシック。3回とも同じで、名指しの効果は無かった。

つまり「フォント名を書く」という発想自体が、画像生成では空振りする。効くのは“見た目の系統”を表す言葉だけだ。


2. style語は“系統”までは効く(ただし特定フォントではない)

一方で、書体の系統を表す言葉はちゃんと届く。同じ「森のパン工房」を、ゴシック体/明朝体/丸ゴシック体/筆文字で頼み分けると、gpt-image-2 は見てわかるレベルで描き分けた。

ゴシック・明朝・丸ゴ・筆を頼み分けて描き分けられている4枚
gpt-image-2 / 不透明 / low。style語=系統はおおむね効く:明朝は細くコントラスト、丸ゴは角丸、筆は毛筆。ただし“その系統っぽい何か”で、特定フォントではない。

明朝は横画が細く縦画が太いコントラストのある字面に、丸ゴは角が丸く、筆文字は毛筆になった。系統としてはおおむね機能している。ただし限界がはっきりある。

弱経路で『森のパン工房』の先頭の森が崩れ、頼んでいない装飾が湧いている
gpt-image-1.5 / 透過 / low に同じ名指しを投げた例。書体どころか先頭の「森」が上に余計な画の増えた別字に化け、無地指定なのに装飾(落ち葉・虫など)まで湧いた。弱経路では系統以前に文字が壊れる。

使いどころは「雰囲気だけ出ればよく、文字の正確さに責任を負わない装飾」まで。ブランドフォントや、文字が正確である必要のある場面では style語では足りない


3. 確実なのは「文字なし背景 + フォント合成」

狙ったフォントをそのまま入れたいなら、モデルに文字を描かせないのが答えだ。本編③「実装で打てる対策」の M7 として挙げた手で、要は① 文字を置く場所を空けた“文字なし背景”を生成 → ② コードで実フォントを重畳する。

モデルに頼んだ“明朝”と、合成した本物の明朝を並べてみる。左はモデルの「明朝体で」(明朝寄りで、これはこれで悪くない。ただしウロコや太さは run ごとにブレる)、右はヒラギノ明朝を合成したもの(毎回このウロコちょうど)。差は“品質”というより“狙って固定できるかどうか”にある。

モデルに『明朝体で』と頼んだ結果。明朝寄りだが細部はブレる
モデルの「明朝体で」。明朝寄りにはなるが、ウロコや太さは安定しない。
ヒラギノ明朝を合成した結果。ウロコまで正確
ヒラギノ明朝を合成。狙った明朝そのもの。ウロコまで正確で run間のブレも無い。

同じ背景に書体だけ差し替えれば、選んだフォントちょうどが手に入る。ゴシック(Noto Sans JP)・明朝・丸ゴ・極太、どれでも思いどおりだ。

同じ背景に4つの実フォントを合成した4枚。選んだ書体ちょうどが出ている
同じ文字なし背景に、実フォントを4種合成(Noto Sans JP/ヒラギノ明朝/丸ゴ/角ゴW8)。選んだ書体ちょうど。同じ合成は毎回バイト一致(md5一致)の決定論。

しかもこの経路は決定論的だ。同じ背景・同じ文字列・同じフォントで合成すれば、出力は毎回バイト単位で同一(md5 一致を確認)。崩れる余地が原理的に無い。背景生成は安い low のままでよく、コストも上がらない。

最小コード(Pillow)
from PIL import Image, ImageDraw, ImageFont

bg = Image.open("bg_textless.png").convert("RGBA")   # 文字なし背景(gpt-imageで生成)
W, H = bg.size
d = ImageDraw.Draw(bg)
font = ImageFont.truetype("NotoSansJP-Bold.otf", 200) # ← ここで“狙ったフォント”を固定
box = d.textbbox((0, 0), "森のパン工房", font=font)
x = (W - (box[2]-box[0]))/2 - box[0]
y = (H - (box[3]-box[1]))/2 - box[1]
d.text((x, y), "森のパン工房", font=font,
       fill=(38,28,18), stroke_width=10, stroke_fill=(255,255,255))  # 白フチで可読性
bg.convert("RGB").save("out.png")

Web 系なら HTML+Canvas / SVG → PNG でも同じこと。要は「描画はコード、生成は背景だけ」に分ければ、フォントは完全にこちらの管理下に入る。


4. 合成の唯一の落とし穴:グリフ被覆

合成は確実だが、出せるのはそのフォントが持っているグリフだけ。フォントに字が無ければ豆腐(□)になる。人名・社名のレア漢字でこれを踏む。

試しに 髙﨑德𠮷鷗邊 を4フォントで描くと、補助平面(4バイト)の 𠮷(つちよし・U+20BB7)ヒラギノ角ゴシック W8 では豆腐になった。Noto Sans JP・ヒラギノ明朝・丸ゴには入っている。「システムフォントだから安心」とは限らない。

Noto Sans JPで髙﨑德𠮷鷗邊がすべて正しく出ている
Noto Sans JP。𠮷(補助平面)まで含めて全グリフが出る。被覆が広い。
ヒラギノ角ゴシックW8で𠮷だけ豆腐□になっている
ヒラギノ角ゴシック W8。𠮷(U+20BB7)だけ豆腐(□)。システムフォントでもレア漢字は欠けることがある。

対策はシンプル。被覆の広い和文フォント(Noto Sans JP/源ノ角ゴシック)を使う、そしてレアな人名漢字は描画して目視確認する。異体字(髙・﨑・𠮷 など)が正式表記の固有名詞は誤字が致命的なので、ここは必ず一度レンダリングして確かめる(→ 周辺編 異体字・旧字体)。IVS(異体字セレクタ)が要るケースは、対応フォント+セレクタ付き文字列で固定する。


5. 「フォントを見せれば寄る?」参考画像での転写(1試行 → 30枚で再検証)

「サンプル画像を渡して“この書体で”と言えば?」もよく聞く。最初は1枚だけ試して「prompt-onlyより寄るっぽい」と書いたが、1試行で言い切るのは怖い。そこで明朝・丸ゴ・筆の3系統 ×「言葉だけ(prompt-only)」と「参考画像を渡す」の2条件 × 各5回=30枚を生成し、どっちの条件で作ったかを伏せたまま、独立な判定者2名で書体を分類して固め直した(明朝・丸ゴの参考画像は実フォント、筆だけは和文の筆フォントが手元に無いのでAIで描いた見本を使った)。

渡した3つの参考画像:明朝・丸ゴ(実フォント)と筆(AI生成)
渡した参考画像。別の文言「書体の見本」を、明朝・丸ゴは実フォントで、筆はAIで描いて edit API に渡した。

結果は、事前の「参考画像のほうが寄る」という見立てを裏切った。系統ごとにバラバラで、しかも丸ゴでは逆効果だった。

丸ゴは逆効果。 言葉だけ(「丸ゴシック体で」)は5回とも丸ゴになったのに、丸ゴの参考画像を渡すと出力はむしろ角ゴ化し、丸ゴと判定されたのは5回中1回だけ(残りは角ゴ)。「見せれば寄る」どころか、言葉だけより悪化した。

丸ゴ:言葉だけは5/5丸ゴ、参考画像を渡すと1/5に下がり角ゴ化
丸ゴを狙う。上=言葉だけ(5回とも丸ゴ)、下=参考画像(角の丸みが消えて角ゴ寄り、丸ゴ判定は1/5)。参考画像が逆効果になった例。

明朝は差が出なかった。 言葉だけも参考画像も、明朝と判定されたのはどちらも5回中4回(各1回だけ角ゴに振れた)。参考画像を渡しても上積みは無い。最初の1試行で「寄った」と思えたのは、たまたま当たりを引いただけだった。

明朝:言葉だけも参考画像も4/5で差がない
明朝を狙う。上=言葉だけ、下=参考画像。どちらも4/5で差なし

筆は両方とも完璧。 言葉だけ・参考画像とも5回すべて筆。元から特徴が強くて崩れにくい系統では、どちらでも問題ない。

筆:言葉だけも参考画像も5/5
筆を狙う。上=言葉だけ、下=参考画像。どちらも5/5。

なお文字の正確さ(「森のパン工房」の6字)は30枚すべてで保たれた(独立判定60件すべて「崩れなし」)。少なくともこの強経路では、参考画像を渡しても文字は崩れない——崩れないが、書体は寄らない、という話だ。

丸ゴが崩れたのは「参考画像」のせい?「edit経路」のせい? — 切り分けた

丸ゴだけ逆効果だったが、参考画像の条件は edit API+絵のある背景、言葉だけは generations+無地で作っていた。これだと「参考画像 vs 言葉」に「edit/背景の有無」が混ざる。そこで丸ゴで (言葉だけ / 参考画像) ×(無地の背景 / 絵のある背景) の4条件を各5回ずつ、同じく条件を伏せて判定し、切り分けた。

丸ゴの2×2:参考画像×絵の背景のときだけ角ゴ化する
丸ゴを狙う4条件。角ゴ化するのは「参考画像 + 絵のある背景」のセルだけ。無地なら参考画像でも丸ゴ、絵があっても言葉だけなら丸ゴ(それぞれ5/5)。

はっきりした。逆効果は「参考画像」と「絵のある背景」が揃ったときだけ起きる相互作用だった。どちらか片方を外すと崩れない——無地+参考画像も、絵の背景+言葉だけも、各5/5で丸ゴ。念のため「参考画像+絵の背景」だけ独立にもう一度5枚回しても、やはり角ゴ化が再現した(2回の実行を合わせて10枚中8枚が角ゴ)。だから単なる当たり外れではない。推測だが、背景の絵と参考画像の両方を同時に辻褄合わせしようとすると、モデルは丸みを捨てて無難な角ゴに寄る——そんな挙動に見える。

しかもこれは実用上タチが悪い。画像を生成する時点でふつう背景には絵がある。つまり「絵のある背景に、参考画像で書体を寄せたい」といういちばんやりたい使い方でこそ逆効果が出る。無地でなら参考画像が効くとはいえ、無地ならそもそも合成すれば済む話だ。

まとめると、「参考画像を見せれば狙った書体に寄る」は当てにならない。元から寄る系統(筆)では言葉だけでも足り、明朝は言葉だけと差がなく、丸ゴは(実用的な絵の背景では)むしろ逆効果になりうる。正確な書体が要るなら、ここでも結論は合成に戻る。なお、この丸ゴの逆効果や文字崩れが別モデルでどう変わるかgpt-image-2 vs gpt-image-1.5 のモデル比較編 で検証した(逆効果は gpt-image-2 に強く出る癖で、gpt-image-1.5 では弱い)。


6. 実装の指針

  1. 正確なフォントが要る(ブランドフォント/明朝指定/等幅/人名の異体字)→ フォント合成。決定論で確実、いちばん安い。
  2. 雰囲気だけでいい(文字の正確さに責任が無い装飾)→ style語で系統を指定。ただし特定フォントは諦める+文字の正確さは別途担保。
  3. 既に崩れた画像がある → edit API で文字だけ修正(→ ③ 実装対策)。ただしフォントは選べない。
  4. 系統を寄せたい → まず style語で足りることが多い。参考画像は当てにならない(丸ゴではむしろ逆効果だった)。正確さが要るなら合成。
  5. やらない:フォントを名指しする(効かない)/弱経路で文字を描かせて納品する。

まとめ

画像生成AIに「特定のフォントで」と頼むのは、構造的に空振りする——モデルはフォントを持たず、API にも指定する場所が無い。効くのは系統を表す style語までで、それも“っぽい何か”止まり。狙ったフォントそのものが要るなら、文字なし背景を生成してコードで実フォントを合成するのが唯一の確実な道だ。決定論で毎回同じ、コストも上がらない。唯一気をつけるのはグリフ被覆——被覆の広いフォントを選び、レア漢字は描画確認する。これは 異体字実装対策 で繰り返し出てきた「確定テキストは合成」の、具体的なやり方そのものだ。

関連記事
本編: ① 症状と対処② なぜ崩れる③ 実装対策④ 崩れやすい字リスト
周辺: 異体字・旧字体(髙→高)和欧混植(第2回 Vol.3)縦書き
モデル比較: gpt-image-2 vs gpt-image-1.5 — フォント挙動はモデルで変わる?
sue@blog ~ $ _