GIMPのプラグインをc言語で作ってみる2。ピクセル単位で描画【GEGL】

fill greenコンピュータ
範囲選択(矩形)を緑色で塗りつぶすプラグインです。
#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);

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-green-fill",
    "Green Fill",
    "Green Fill",
    "MayWorks",
    "Copyright MayWorks",
    "2022",
    "_Green Fill...",
    "RGBA",
    GIMP_PLUGIN,
    G_N_ELEMENTS (args), 0,
    args, NULL);

  gimp_plugin_menu_register ("plug-in-green-fill",
                             "<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;
  GeglBuffer *gegl_buf;
  gint         x1, y1, x2, y2;
  gint image_id, drawable_id, channels;
  GeglRectangle roi;
  gboolean non_empty;

  /* Setting mandatory output values */
  *nreturn_vals = 1;
  *return_vals  = values;

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

  /* Getting run_mode - we won't display a dialog if 
   * we are in NONINTERACTIVE mode */
  run_mode = param[0].data.d_int32;

  if (run_mode != GIMP_RUN_NONINTERACTIVE)
    g_message("Green Fill\n");
  
  gegl_init (NULL, NULL);
  drawable_id = param[2].data.d_drawable;
  gegl_buf = gimp_drawable_get_buffer(drawable_id);
  image_id = gimp_item_get_image (drawable_id);
  channels = gimp_drawable_bpp (drawable_id);
  if (channels != 4){
      g_message("not RGBA");
      return;
  }
  gimp_selection_bounds(image_id, &non_empty, &x1, &y1, &x2, &y2);
  if (non_empty == FALSE)
    return;
  
  gegl_rectangle_set(&roi, x1, y1, x2-x1, y2-y1);
  gfloat *buf  = g_new0 (gfloat, roi.height * roi.width * channels);
  gint x,y;
  gint offset=0;

  gegl_buffer_get (gegl_buf,  &roi, 1.0, babl_format ("RGBA float"), buf,
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

  for (y=0;y<roi.height;y++)
  {
    for (x=0;x<roi.width;x++)
    {
        //g_message("%d", gimp_selection_value(image_id, x, y));
        offset = (y * roi.width * channels) + x * channels;
        buf[offset + 0] = 0.0f;
        buf[offset + 1] = 255.0f;
        buf[offset + 2] = 0.0f;
        buf[offset + 3] = 1.0f;
    }
  }

  gegl_buffer_set (gegl_buf, &roi, 0, babl_format ("RGBA float"), buf, GEGL_AUTO_ROWSTRIDE);  
  g_free (buf);
  gegl_buffer_flush(gegl_buf);

  gimp_drawable_update (drawable_id,
                        x1, y1,
                        roi.width, roi.height);
  gimp_displays_flush();
  gegl_exit();
}
各種形状の選択範囲を緑色で塗りつぶすつもりで作成しましたが、矩形以外の範囲選択には対応できていません。
対応形式はRGBAのみです。アルファチャンネルが無い場合追加してください。
GEGLについてネットで調べてみましたが日本語で書かれた情報が少ないので、GEGLが何をするものか今一つ理解できていない状態です。

参考にしたサイト
GEGL API

C++ (Cpp) gegl_buffer_get Example - itcodet
The c++ (cpp) gegl_buffer_get example is extracted from the most popular open source projects, you can refer to the following example for usage.

コメント