GIMPのプラグインをc言語で作ってみる。

GIMP コンピュータ
GIMP
GIMP developersのC言語のプラグインのソースを読んでみて、さらにシンプルに選択範囲を青色に塗りつぶすだけのサンプルプログラムを作成してみました。
推奨されない古い関数を使っているので多量に警告が出るのですが、とりあえずUbuntu20.04上のGIMP2.10で動くことは確認出来ました。
#include <libgimp/gimp.h>

static void query (void);
static void run   (const gchar      *name,
                   gint              nparams,
                   const GimpParam  *param,
                   gint             *nreturn_vals,
                   GimpParam       **return_vals);
static void my_bluefill  (GimpDrawable *drawable);

GimpPlugInInfo PLUG_IN_INFO =
{
  NULL,
  NULL,
  query,
  run
};

MAIN()

static void
query (void)
{
  static GimpParamDef args[] =
  {
    {
      GIMP_PDB_INT32,
      "run-mode",
      "Run mode"
    },
    {
      GIMP_PDB_IMAGE,
      "image",
      "Input image"
    },
    {
      GIMP_PDB_DRAWABLE,
      "drawable",
      "Input drawable"
    }
  };

  gimp_install_procedure (
    "plug-in-my-bluefill",
    "My Blue Fill",
    "MyBlueFill",
    "May Work",
    "Copyright MayWork",
    "2022",
    "MyBlueFill...",
    "RGB*, GRAY*",
    GIMP_PLUGIN,
    G_N_ELEMENTS (args), 0,
    args, NULL);

  gimp_plugin_menu_register ("plug-in-my-bluefill",
                             "<Image>/Filters/Misc");
}

static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam  values[1];
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  GimpRunMode       run_mode;
  GimpDrawable *drawable;

  *nreturn_vals = 1;
  *return_vals  = values;

  values[0].type = GIMP_PDB_STATUS;
  values[0].data.d_status = status;

  run_mode = param[0].data.d_int32;

  gimp_progress_init ("Blue Fill Runing...");

  drawable = gimp_drawable_get (param[2].data.d_drawable);
  my_bluefill (drawable);

  gimp_displays_flush ();
  gimp_drawable_detach (drawable);

  return;
}

static void
my_bluefill (GimpDrawable *drawable)
{
  gint         i, channels, image_id, drawable_id;
  gint         x1, y1, x2, y2;
  GimpPixelRgn rgn_out;
  guchar      *outrow;
  GeglRectangle roi;
  gboolean non_empty;
  
  drawable_id = drawable->drawable_id;
  image_id = gimp_item_get_image (drawable_id);
  gimp_selection_bounds(image_id, &non_empty, &x1, &y1, &x2, &y2);
  if (non_empty == FALSE)
    return;

  channels = gimp_drawable_bpp (drawable->drawable_id);

  gimp_pixel_rgn_init (&rgn_out,
                       drawable,
                       x1, y1,
                       x2 - x1, y2 - y1,
                       TRUE, TRUE);

  outrow = g_new (guchar, channels * (x2 - x1));
  
  for(i = 0; i < (channels * (x2 - x1)); i += channels)
  {
      outrow[i] = 0;
      outrow[i+1] = 0;
      outrow[i+2] = 255;
  }

  for (i = y1; i < y2; i++)
  {
    gimp_pixel_rgn_set_row (&rgn_out, outrow, x1, i, x2 - x1);

    if (i % 10 == 0)
        gimp_progress_update ((gdouble) (i - y1) / (gdouble) (y2 - y1));
    }

  g_free (outrow);

  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id,
                        x1, y1,
                        x2 - x1, y2 - y1);

}
ビルド方法は過去の記事を見てください。
GIMP developersのhello.cをビルドする。【Ubuntu20.04】
Ubuntu20.04でgimpをインストールしたところPython-Fuのプラグインを実行することが出来ないようです。Python-FuからScript-Fuで作り直すかとも思いましたが、調べてみたところc言語の単一ソースファイルから比較...

選択範囲の座標情報をもとに画像のピクセルを配列として取得し、そちらを書き換えています。
gimp_pixel_rgn_set_row ()関数で1行単位で一気に書き換えますので、1ピクセル事に書き換える方法と比べてだいぶ高速に動作してくれます。

ちなみに今回警告が出ている部分をgeglライブラリを使って警告が出ない方法も試しています。1ピクセル単位に書き換える方法は見つけましたが、残念ながら今回のサンプルと比べるとだいぶ動作が遅いです。
C言語でバイナリを作成すれば1ピクセル単位の書き換えも高速で動作することを期待しましたが、力わざで解決できる問題ではないようです。

コメント