ComfyUIの色管理と書き出し|PNGに色プロファイルが入らない理由と対処【2026年版】

当ページのリンクには広告が含まれています。
comfyui color management export 2026

生成した画像を Photoshop で開いたら色が違う。Web に上げたらくすんだ。犯人はプロンプトでもサンプラーでもなく書き出しの側にいることがある。ComfyUI の SaveImage の実装を読むと、色に関する情報が1バイトも書かれていないことが分かる。

検証環境と方法:ComfyUI 0.3.76nodes.py / comfy_extras/nodes_images.py を直接読み、保存処理と同じ式・同じ引数をローカルで再実行して出力バイトを検査した(Python 3.12.3 / numpy 2.4.4 / Pillow 12.2.0)。チャンク一覧と数値は実測値。測っていない範囲=モデルを読み込む実際の生成、GPU 経路、他バージョンでの再現、ビューア側の表示差。

結論(ComfyUI 0.3.76 実測)

  • SaveImage の PNG に ICC プロファイルも sRGB チャンクも入らない。入るのは tEXt(prompt / workflow)だけ
  • 出力は 8bit トゥルーカラー固定。16bit で出す経路はコアに無い
  • float→8bit の変換は四捨五入ではなく切り捨て(0.5 → 127)。ただしこの偏りは往復しても増えない=実測で 0/256 階調
  • 範囲外の値はクリップされる(縮小されない)。1.2 も 5.0 も等しく 255
  • コアの静止画保存ノードは SaveImage(PNG)だけ。JPEG / 静止 WebP は無い
目次

なぜ「色が違う」と感じるのか?

結論から言うと、ComfyUI が出す PNG は無タグだからだ。実際に SaveImage と同じ呼び出しで PNG を書き、チャンクを並べるとこうなる。

チャンク 役割 ComfyUI の出力
IHDR 幅・高さ・ビット深度 あり(8bit / カラータイプ2)
tEXt テキスト情報 あり(prompt / workflow)
iCCP ICC プロファイル埋め込み 無し
sRGB sRGB であるという宣言 無し
gAMA / cHRM ガンマ・色度点 無し

色の手がかりが無いので、開いた側が勝手に決める。ブラウザと多くのビューアは「タグが無ければ sRGB」と解釈するので結果的に一致することが多い。ずれるのは作業スペースが sRGB でないアプリで開いたときだ。Adobe RGB で作業していれば、同じ数値が別の色として表示される。画像が変わったのではなく解釈が変わっている

対処は「変換」ではなく「宣言」=受け取り側で sRGB を指定する(Photoshop の「プロファイルの指定」)。「プロファイル変換」を選ぶと無タグの画素値を別空間へ作り替えてしまうので、かえってずれる。⚠ 実測したのはファイルに何が書かれているかまでで、表示差そのものは測っていない。これで直るのは原因が無タグ解釈だった場合に限る。

0.5 が 127 になるのはなぜ?

ComfyUI の画像テンソルは 0.0〜1.0 の float だ。保存時にこう変換される。

i = 255. * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))

astype(np.uint8)ゼロ方向へ切り捨てる。四捨五入しない。同じ式を実行するとこうなる。

テンソル値 255倍 実際の出力 四捨五入なら
0.500000 127.500 127 128
0.998000 254.490 254 254
1.000000 255.000 255 255

差は最大でも1階調(1/255)にとどまる(知覚できるかは測っていない。階調によっては見える場合がある)。そしてこの偏りは繰り返しても増えない。保存と読み直しの往復を全256階調で6世代まわすと変化した階調は0/256だった。8bit に落ちた時点で 255×(v÷255)v に戻るので、そこから先は動かない。

つまり切り捨てが効くのは最初の1回だけだ。ただし劣化しないわけではない。往復のたびに 8bit へ量子化されるので、その間の加工が生んだ 1/255 未満の差は毎回そこで捨てられる。積もるのは誤差ではなく捨てた情報のほう。だから世代を重ねるワークフローは中間をテンソルのまま繋ぐほうが素直になる。

VRAM が足りず解像度やバッチを落としている場合、色より先にそこが効く。GPU 環境をすぐ試すなら、ComfyUI が入ったクラウドが手早い。

環境構築なしでComfyUIを試す|ConoHa AI Canvas※ ComfyUI・AUTOMATIC1111・Kohya SS が環境構築なしで使えるGPUクラウド

範囲外の値はどうなる?

np.clip(i, 0, 255) なのでクリップされる。1.2 も 5.0 も等しく 255 になり、-0.3 は 0 になる。全体を縮めて収める処理は入っていない

白飛びに直結する。ハイライトが 1.0 を超えていれば超過分は保存の瞬間に捨てられ、後から戻せない。CFG を下げるか、書き出し前に明度・コントラストを調整するノードを挟むか——いずれにせよ保存前に抑えるしかない。

コアで選べる書き出しは何がある?

0.3.76 のコアにある保存系ノードは5つで、静止画は SaveImage の PNG だけだ。

ノード 形式 備考
SaveImage PNG(8bit) compress_level=4 固定。UI から変更不可
PreviewImage PNG temp ディレクトリ行き・compress_level=1
SaveAnimatedPNG APNG メタデータは独自 comf チャンク
SaveAnimatedWEBP アニメ WebP lossless の既定は True
SaveSVGNode SVG ベクター出力用

PreviewImage を成果物にしない。 継承元は SaveImage だが、保存先は出力フォルダではなく temp ディレクトリで、ファイル名にランダムな接尾辞が付く。プレビューだけ繋いで「保存できている」と思い込むと、消えたときに取り返せない。

JPEG・16bit・ICC 埋め込みはすべてカスタムノードの領分だ(カスタムノードの選び方と導入手順)。

実務ではどう運用する?

  • 受け取り側で sRGB を「指定」する。変換ではなく指定。無タグ解釈が原因のずれはこれで解消する
  • 中間結果を PNG で往復させない。誤差は積もらないが、往復のたびに 8bit へ量子化され1/255 未満の差が毎回捨てられる
  • 白飛びは保存前に潰す。クリップされた後では情報が無い
  • 納品物は SaveImage から出すPreviewImage は temp 行き
  • 配布時は tEXt を意識する。プロンプトとワークフローがそのまま埋まっているので、見られたくないなら --disable-metadata で起動する

なお 3DCG 側のカラースペース(ACES 等)は別の話だ。テクスチャの色管理はMaya × Substance Painter のカラースペース設定を参照してほしい。ComfyUI 側はそもそもタグを持たないので論点が違う。

ワークフローの整理は管理・整理術、基本操作はComfyUI の使い方完全入門を参照。

書き出しの前段でバッチ生成まで自動化したい場合は、GPU を専有できる環境のほうが結局は速い。

ConoHa AI Canvas の構成を見る※ ブラウザから使えるGPUクラウド。停止中は課金されない

よくある質問

ComfyUI の PNG は sRGB ですか?

ファイルにはそう書かれていません。0.3.76 の SaveImageiCCPsRGB チャンクも書かないため、開く側の解釈に委ねられます。多くのビューアは無タグを sRGB とみなすため実運用では sRGB として扱われますが、これは各アプリの既定の挙動であって、ファイルが宣言しているわけではありません

Photoshop で色が変わります。どう直しますか?

「プロファイルの指定」で sRGB を割り当ててください。「プロファイル変換」を選ぶと、無タグの画素値を別の色空間へ作り替えてしまい、かえってずれます。元画像は変わっていないので、解釈を合わせるだけで済みます。

16bit PNG で書き出せますか?

0.3.76 のコアではできません。SaveImageastype(np.uint8) で 8bit に固定しており、ビット深度の入力もありません。16bit や EXR が必要ならカスタムノードを導入することになります。

生成画像にプロンプトが埋め込まれていると聞きました。消せますか?

消せます。SaveImagetEXt チャンクに promptworkflow を JSON で書き込みます。ComfyUI を --disable-metadata を付けて起動すると、この書き込み自体が行われません。既存ファイルから消す場合は、画像編集ソフトで再保存するか、メタデータ削除ツールを使ってください。

PNG の圧縮率は変えられますか?

SaveImage では変えられません。compress_level が 4 でコードに直書きされており、ノードの入力として公開されていないためです。ちなみに SaveAnimatedPNG は 0〜9 で指定でき、既定は同じく 4 です。

まとめ

ComfyUI の「色が違う」は、色を変換されているのではなく、色が宣言されていないことから来る。0.3.76 の SaveImage が書くのは 8bit の画素と tEXt だけで、ICC も sRGB チャンクも付かない。受け取り側で sRGB を指定すれば、この原因のずれは解消する。

float から 8bit への変換は切り捨てで、範囲外はクリップされる。ただし切り捨ての偏りは往復しても増えない(実測 0/256 階調)。失われるのは誤差ではなく 8bit 未満の情報のほうだ。中間はテンソルのまま繋ぎ、白飛びは保存前に抑える。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ITインフラエンジニア歴12年。クラウド(AWSがメイン、一部Azure)の実務は3年目。並行して社会人向けの3DCGスクールに在学中。Windows 11 + RTX 4070 Ti SUPER の自宅環境で実際に手を動かしながら、インフラ・クラウド・AI・3DCGの技術記事を書いています。

コメント

コメントする

CAPTCHA


目次