gimp について
GIMP 内蔵の Script-Fu サーバーを介して GIMP 3 を操作するスキルです。画像の作成、確認、書き出しを自動化するユーザー向けで、GUI 上で Python スクリプトを実行し、API リファレンスとレシピも提供します。
主な機能
- 01Script-Fu 経由で Python スクリプトを送信
- 02画像、レイヤー、選択範囲、テキストを操作
- 03編集可能な GEGL フィルターを適用
- 04PDB プロシージャの呼び出しと書き出し
- 05サムネイルで合成結果を確認
活用シーン
- 01ポスターを作成して XCF と PNG で書き出し
- 02GIMP で開いている画像を編集
- 03フォルダーの一括処理やレイヤー別書き出し
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jablonkai/ skills --skill gimpインストール後、Claude Code で/gimpを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api-reference.mdrecipes.mdscripts/example-poster.pygimp_client.pygimp-send.shgimp-start.sh詳細
GIMP コントロール
GIMP(/Applications/GIMP.app)には Python 3 が組み込まれており、GObject Introspection(gi.repository.Gimp)経由の libgimp を通じて、ドキュメントモデル全体を公開しています。ピクセルとフィルターには GEGL を使用します。GIMP 独自の Script-Fu サーバー(GIMP に標準搭載されている TCP エンドポイントで、インストールは不要です)経由で操作すると、各スクリプトが GIMP の python-fu-eval に渡されます。スクリプトは 実行中の GIMP を対象に動作します。キャンバスが更新され、レイヤーの積み重ねはユーザーが見ているものと同じで、ヘッドレスでは何も実行されません。このスキル内のすべての呼び出しは GIMP 3.2.6 で実行しました。
- scripts/gimp-send.sh —
.pyファイル(または-c 'inline code')を送信し、キャプチャした出力を表示します。接続の確認には--ping、生の Script-Fu の評価には--schemeを使います。 - scripts/gimp-start.sh — Script-Fu サーバーを待ち受け状態にして GIMP の GUI を起動し、応答があるまで待機します。
- scripts/gimp_client.py — 両方で使用するワイヤープロトコルです。
- scripts/example-poster.py — コピーして参考にできる、構築 → 検証 → エクスポートまでを行う完全なスクリプトです。
- references/api-reference.md — バージョン検証済みの libgimp API(画像、レイヤー、選択範囲、描画、テキスト、GEGL フィルター、PDB 呼び出し、ピクセルの読み戻し、エクスポート)。以下のチートシートを超えるものを書く前に読んでください。
- references/recipes.md — ユーザー自身の画像での作業、フォルダーの一括処理、レイヤーごとのエクスポート、マスク、アニメーション、API でできないことについて説明します。
制御ループ
-
接続を確認する:
bash scripts/gimp-send.sh --ping→{"ok": true, "bridge": "gimp", "port": 10008, "reply": "3.2.6 | open images: 2"}。応答がない場合、状況は 2 通りあり、それぞれ対処法が異なります。
- GIMP が起動していない →
bash scripts/gimp-start.shでサーバーを有効にして GUI を起動し、準備ができるまで待ちます。ユーザーの画面にウィンドウが開くため、その旨を伝えてください。 - GIMP は起動しているが、サーバーが有効になっていない → リモートから有効にすることはできません。また、それを回避するために 2 つ目のインスタンスを起動してはいけません。2 つの GIMP は同じ設定ディレクトリを共有しており、未保存の作業はすでに開いている方にあるためです。次の 1 回のクリックをユーザーに依頼してください:Filters ▸ Development ▸ Script-Fu ▸ Start Server…。待ち受け先は
127.0.0.1、ポートは10008です。(ローカライズされた GIMP でも Development は英語のままです。ハンガリー語版では、メニューのパスは Szűrők ▸ Development ▸ Script-Fu ▸ Kiszolgáló indítása… となります。)
- GIMP が起動していない →
-
スクラッチパッドに構築スクリプトを書くと、それを送信します:
OUT=/path/to/outdir bash scripts/gimp-send.sh /path/build.py。OUTはグローバル変数とos.environ["OUT"]の両方として渡されます。GIMP に渡される変数はこれだけです。SRC=... bash gimp-send.shとすると、スクリプトは GIMP のプロセス内で実行されるため、KeyErrorが発生します。入力パスは絶対パスのリテラルとしてスクリプトに記述してください。GIMP_SEND_TIMEOUT=600(秒)を設定すると、一括処理や大きなエクスポートにも対応できます。 -
フィードバックを確認する。送信側は、スクリプトがキャプチャした stdout/stderr と、失敗時には Python のトレースバックを返し、ゼロ以外で終了します。そのため、戻り値の受け取りには
print(...)を使ってください。それ以外の情報は報告されません。GIMP 独自のエラーコンソールはアプリ内に表示されたままです。 -
結果を確認する。
image.get_thumbnail(w, h, Gimp.PixbufTransparency.SMALL_CHECKS)は、合成画像をそのまま PNG にレンダリングし、Read で読み込めるようにします。すべての構築スクリプトの最後にこれを実行してください。1 行で済み、アサーションでは見つけられない問題も検出できます。 -
反復し、納品する。スクリプトを修正して再送信します。スクリプトは再実行可能にしてください。すでに開いている画像を変更するのではなく、バージョンごとに新しい画像を作成します。これにより、再送信しても前回の試行にレイヤーが積み重なりません。
送信するたびに、新しい python-fu-eval プロセスが起動します。送信間で保持されるのは、GIMP 内(開いている画像)またはディスク上にあるものだけです。往復はおよそ 1 秒なので、API を推測するより、使い捨ての送信で試す方が手軽です。
スクリプティング早見表
import gi
gi.require_version("Babl", "0.1"); gi.require_version("Gegl", "0.4")
gi.require_version("Gimp", "3.0")
from gi.repository import Babl, Gegl, Gimp, Gio
Gegl.init(None)
画像とレイヤースタック
image = Gimp.Image.new(1000, 1400, Gimp.ImageBaseType.RGB)
layer = Gimp.Layer.new(image, "background", 1000, 1400,
Gimp.ImageType.RGBA_IMAGE, 100.0, Gimp.LayerMode.NORMAL)
image.insert_layer(layer, None, 0) # parent=None -> top level; 0 = topmost
layer.set_opacity(70.0) # 0–100 float, not 0–255
layer.set_mode(Gimp.LayerMode.SCREEN)
Gimp.Display.new(image) # show it — the user watches the build happen
Gimp.displays_flush() # nothing repaints without this
ユーザーがすでに開いているものを操作するには、Gimp.get_images()[0] を使います。最も最近アクティブになった画像が先頭です。破壊的な処理を行う前に複製してください。詳しくは
recipes.mdを参照してください。
色:入力も出力も sRGB
Gegl.Color は リニア RGB を保存するため、コンストラクターとセッターは同じものではありません。この違いにより、画像が目に見えて色あせたようになります。
Gegl.Color.new("#1a73e8") # parses sRGB — use this
colour.set_rgba(0.10, 0.45, 0.85, 1.0) # LINEAR components — rarely what you meant
list(colour.get_bytes(Babl.format("R'G'B'A u8")).get_data()) # [26,115,232,255]
Gimp.context_set_foreground(Gegl.Color.new("#ffb703"))
選択範囲、塗りつぶし、描画
image.select_rectangle(Gimp.ChannelOps.REPLACE, x, y, w, h) # also ellipse, polygon,
layer.edit_fill(Gimp.FillType.FOREGROUND) # round_rectangle, color
Gimp.Selection.none(image) # every later edit respects the selection
layer.fill(Gimp.FillType.FOREGROUND) # whole layer, ignores the selection
Gimp.context_set_gradient_fg_bg_rgb()
layer.edit_gradient_fill(Gimp.GradientType.LINEAR, 0.0, False, 1.0, 0.0, True,
x1, y1, x2, y2)
Gimp.context_set_brush(Gimp.Brush.get_by_name("2. Hardness 100"))
Gimp.context_set_brush_size(20.0)
Gimp.paintbrush_default(layer, [40.0, 40.0, 200.0, 200.0]) # ONE drawable, flat x/y list
テキスト
font = Gimp.context_get_font() # safer than naming one: get_by_name
text = Gimp.TextLayer.new(image, "GIMP", font, 150.0, Gimp.Unit.pixel())
image.insert_layer(text, None, 0)
text.set_color(Gegl.Color.new("#f8f9fa"))
text.set_justification(Gimp.TextJustification.CENTER)
text.set_offsets((image.get_width() - text.get_width()) // 2, 300) # measure AFTER
フィルター — 非破壊を優先
GIMP 3 のフィルターは適用後も有効で編集可能なままなので、他の人の作品に対するデフォルトの方法として適切です。
blur = Gimp.DrawableFilter.new(layer, "gegl:gaussian-blur", "glow blur")
config = blur.get_config()
config.set_property("std-dev-x", 90.0); config.set_property("std-dev-y", 90.0)
blur.update() # push config into the filter
layer.append_filter(blur) # or layer.merge_filter(blur) to bake it in
推測するのではなく、Gegl.list_operations() と Gegl.Operation.list_properties("gegl:gaussian-blur") を使ってオペレーションとプロパティ名を調べてください。従来の plug-in-gauss 系は GIMP 3 では廃止されています。
バインディングがないもの:PDB
proc = Gimp.get_pdb().lookup_procedure("script-fu-drop-shadow") # None if absent
config = proc.create_config()
config.set_property("run-mode", Gimp.RunMode.NONINTERACTIVE)
config.set_property("image", image)
config.set_core_object_array("drawables", [layer]) # NOT set_property
result = proc.run(config)
エクスポート
Gimp.file_save(Gimp.RunMode.NONINTERACTIVE, image,
Gio.File.new_for_path(OUT + "/poster.xcf"), None) # .png/.jpg/... too
flat = image.duplicate(); flat.flatten() # flatten a copy, not the original
Gimp.file_save(Gimp.RunMode.NONINTERACTIVE, flat,
Gio.File.new_for_path(OUT + "/poster.png"), None)
flat.delete()
.xcf ではすべてのレイヤー、マスク、ライブフィルターをユーザーが編集可能な状態に保てます。ユーザーから別の指示がない限り、フラット化したエクスポートとあわせて .xcf も渡してください。JPEG の品質や GIF のタイミングなどの形式オプションは、PDB 経由でエクスポートプラグインを呼び出して設定します。詳しくは
api-reference.mdを参照してください。
検証
- 返された標準出力が即時の確認手段です。
print(...)の出力はそのまま返され、失敗した場合はゼロ以外の終了コードとともにトレースバックが返されます。 - サムネイル PNGは視覚的な確認に使えます。
image.get_thumbnail(500, 700, Gimp.PixbufTransparency.SMALL_CHECKS)を$OUTに保存して Read します。これは合成後の画像なので、レイヤーごとの説明では分からないブレンドモードやフィルターの状態も正確に確認できます。 - 数値:
Babl.format("R'G'B'A u8")を使ってimage.pick_color([...], x, y, True, False, 0.0)でサンプリングすると、色が正確に適用されたことを確認できます。layer.histogram(...)では 0~255 のスケールで平均値と中央値を取得できます。サイズ、レイヤー名、オフセット、モード、適用済みフィルターをmetrics.jsonに書き出し、スタックを目視する代わりに Read してください。 - 受け渡し:エクスポートした PNG/JPEG はどこでも開けます。
.xcfでは作業内容を編集可能な状態に保てます。
注意点
Gegl.Color.set_rgbaはリニア値で、Gegl.Color.new("#hex")は sRGB です。 取り違えると、すべての色が気付かないうちに明るくなります。値の読み戻しにはget_rgba()ではなく、get_bytes(Babl.format("R'G'B'A u8"))を使ってください。- GIMP オブジェクトの配列には
set_core_object_arrayを使います。config.set_property( "drawables", [layer])はcould not convert [...] to type 'GimpCoreObjectArray'を発生させます。また、値を読み戻すにはresult.get_core_object_array(i)が必要です。result.index(i)は反復処理できないGBoxedを返します。 - 描画呼び出しが受け取るのはドローアブル 1 つで、リストではありません(
Gimp.paintbrush_default(layer, pts))。一方、pick_colorが受け取るのはドローアブルの リスト です。この非対称性は仕様です。 - フォントが見つからない場合、
Gimp.Font.get_by_nameはNoneを返します。 エラーはTextLayer.new内でArgument 2 does not allow None as a valueとして初めて表面化します。ユーザーがフォントを指定していない場合はGimp.context_get_font()を使い、戻り値を確認してください。 - テキストレイヤーは自動的にサイズ変更されます — テキスト、サイズ、間隔を設定したあとで中央揃えと位置決めを行ってください。そうしないと、前のレイアウトを測定することになります。
- 編集後は
Gimp.displays_flush()を呼び出してください。 そうしないと、ユーザーには古いキャンバスが表示され、スクリプトが何もしていないと双方が思ってしまいます。 get_offsets、pick_color、histogram、selection.boundsでは成功フラグが先頭にあります。 タプルをアンパックしてください。むやみにインデックスでアクセスしないでください。- リソース名はローカライズされています — ハンガリー語版 GIMP では、グラデーション名は
FG to BG (RGB)ではなくElőtérből háttérbe (RGB)です。英語名をハードコードするのではなく、実行時に一覧を取得してください(Gimp.gradients_get_list("")など)。 image.delete()は確認なしで未保存の変更を破棄します。 自分のスクリプトが作成した画像にのみ呼び出してください。ユーザーの画像には決して呼び出さないでください。image.undo_group_start()/undo_group_end()で編集をまとめてください。 そうすれば、Ctrl+Z を 1 回押すだけで、400 回の個別操作ではなく、ビルド全体を元に戻せます。- 送信するたびに状態は引き継がれません — 毎回、新しい
python-fu-evalプロセスが起動し、OUTだけを含む新しい名前空間でスクリプトが実行されます。os、json、giリポジトリは自分でインポートしてください。画像にバージョンを付けて("poster_v2")、再実行時に前回の試行と競合しないようにしてください。 - 送信が失敗すると、作成途中の画像が開いたままになります。 画像の作成直後に
image.set_file(Gio.File.new_for_path(OUT + "/poster_v2.xcf"))を呼び出してください。そうすれば次回の送信時に、get_file()とdelete()を使ってGimp.get_images()から自分の残骸を見つけられ、ユーザーが開いたものには触れずに削除できます。 flatten()はコンテキストの背景色で透明部分を塗りつぶします。この色は、それ以前の塗りつぶしで設定された値です。平坦化する前に背景色を設定する(Gimp.context_set_background)か、アルファを維持するためにmerge_visible_layers(Gimp.MergeType.CLIP_TO_IMAGE)を使ってください。- GIMP 3 では
--batchに--batch-interpreterが必要です。指定しないと、GIMP はインタープリターの一覧を表示して終了します。gimp-start.shではすでに指定されています。 - GIMP が異常終了すると、ポートがバインドされたままになることがあります。
script-fu-serverプラグインは独立したプロセスなので、GIMP の終了後もしばらく動作し続けます。そのため、ポートを確認しただけでは、接続先がなくても「稼働中」と表示されます。--pingを使えば確認できます(応答の途中で接続が閉じられ、孤立したプロセスはその後終了します)。そのように報告された場合は、GIMP を再起動してください。 - GIMP 2.10 のチュートリアルは移植できません。
gimpfu、pdb.gimp_*、RGB タプル、plug-in-gaussフィルターはすべて廃止されており、残っている呼び出しも形式が変わっています —edit_bucket_fill(fill_type, x, y)は、しきい値をGimp.context_set_sample_thresholdから取得するようになりました。どこかで見たプロシージャ名を信頼する前に、lookup_procedureがNoneを返さないことを確認してください。 - ツールはスクリプトから操作できません — 変形ウィジェット、自由選択、メニューアクションの実行はできません。使える操作は塗りつぶし、描画呼び出し、選択範囲、GEGL フィルターだけです。recipes.md を参照してください。
セキュリティ
ここにインストールするものはありませんが、Script-Fu サーバーを起動すると、GIMP はコード実行サーバーになります。起動を依頼する前に、そのことを伝えてください。
- サーバーは
127.0.0.1:10008で待ち受け、受信した内容をそのままpython-fu-evalに渡します。ユーザーの権限で、ユーザーが開いている画像を対象に、任意の Python コードを実行できます。認証機能はありません。ローカルのすべてのプロセスと、共有マシン上の他のすべてのユーザーが、このサーバー経由で GIMP を操作できます。 - 必ず 127.0.0.1 を指定してください。 サーバーの起動ダイアログでは任意の待ち受けアドレスを指定できます。
0.0.0.0または LAN アドレスにバインドすると、ネットワーク全体に対するリモートコード実行が可能になります。gimp-start.shはループバックに固定しています。ユーザーが手動で起動する場合は、アドレスを伝えてください。 - HTTP ではありません。プロトコルは長さプレフィックスと
Gマジックバイトを使用するため、ブラウザーからのリクエストは最初のバイトで拒否されます。これはワイヤ形式の副作用であり、オリジンの確認ではありません。 - 停止するには、GIMP を終了してください。 GIMP の終了後もプラグインプロセスが終了するまで、ポートが一時的にバインドされたままになることがあります。そのため、ポートの確認だけでは稼働中であることの証明にはなりません。
--pingを使用してください(gimp-send.sh --ping)。