/* PIKA - Photo and Image Kooker Application
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 *
 * Original copyright, applying to most contents (license remains unchanged): 
 * Copyright (C) 1995-2003 Spencer Kimball and Peter Mattis
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

/* NOTE: This file is auto-generated by pdbgen.pl. */

#include "config.h"

#include "stamp-pdbgen.h"

#include <cairo.h>

#include <gegl.h>

#include <gdk-pixbuf/gdk-pixbuf.h>

#include "libpikabase/pikabase.h"
#include "libpikacolor/pikacolor.h"
#include "libpikamath/pikamath.h"

#include "libpikabase/pikabase.h"

#include "pdb-types.h"

#include "core/pika.h"
#include "core/pikachannel.h"
#include "core/pikacontainer.h"
#include "core/pikadrawable.h"
#include "core/pikagrouplayer.h"
#include "core/pikaimage-color-profile.h"
#include "core/pikaimage-colormap.h"
#include "core/pikaimage-duplicate.h"
#include "core/pikaimage-merge.h"
#include "core/pikaimage-metadata.h"
#include "core/pikaimage-pick-color.h"
#include "core/pikaimage-pick-item.h"
#include "core/pikaimage-rotate.h"
#include "core/pikaimage.h"
#include "core/pikaitem.h"
#include "core/pikalayer.h"
#include "core/pikapalette.h"
#include "core/pikaparamspecs.h"
#include "core/pikapickable.h"
#include "core/pikaprogress.h"
#include "core/pikaselection.h"
#include "core/pikatempbuf.h"
#include "file/file-utils.h"
#include "gegl/pika-babl.h"
#include "plug-in/pikaplugin-cleanup.h"
#include "plug-in/pikaplugin.h"
#include "plug-in/pikapluginmanager.h"
#include "vectors/pikavectors.h"

#include "pikapdb.h"
#include "pikapdberror.h"
#include "pikapdb-utils.h"
#include "pikapdbcontext.h"
#include "pikaprocedure.h"
#include "internal-procs.h"

#include "pika-intl.h"


static PikaValueArray *
image_id_is_valid_invoker (PikaProcedure         *procedure,
                           Pika                  *pika,
                           PikaContext           *context,
                           PikaProgress          *progress,
                           const PikaValueArray  *args,
                           GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  gint image_id;
  gboolean valid = FALSE;

  image_id = g_value_get_int (pika_value_array_index (args, 0));

  if (success)
    {
      valid = (pika_image_get_by_id (pika, image_id) != NULL);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_boolean (pika_value_array_index (return_vals, 1), valid);

  return return_vals;
}

static PikaValueArray *
get_images_invoker (PikaProcedure         *procedure,
                    Pika                  *pika,
                    PikaContext           *context,
                    PikaProgress          *progress,
                    const PikaValueArray  *args,
                    GError               **error)
{
  PikaValueArray *return_vals;
  gint num_images = 0;
  PikaImage **images = NULL;

  GList *list = pika_get_image_iter (pika);

  num_images = g_list_length (list);

  if (num_images)
    {
      gint i;

      images = g_new (PikaImage *, num_images);

      for (i = 0; i < num_images; i++, list = g_list_next (list))
        images[i] = g_object_ref (list->data);
    }

  return_vals = pika_procedure_get_return_values (procedure, TRUE, NULL);

  g_value_set_int (pika_value_array_index (return_vals, 1), num_images);
  pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_IMAGE, (GObject **) images, num_images);

  return return_vals;
}

static PikaValueArray *
image_new_invoker (PikaProcedure         *procedure,
                   Pika                  *pika,
                   PikaContext           *context,
                   PikaProgress          *progress,
                   const PikaValueArray  *args,
                   GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  gint width;
  gint height;
  gint type;
  PikaImage *image = NULL;

  width = g_value_get_int (pika_value_array_index (args, 0));
  height = g_value_get_int (pika_value_array_index (args, 1));
  type = g_value_get_enum (pika_value_array_index (args, 2));

  if (success)
    {
      image = pika_create_image (pika, width, height, type,
                                 PIKA_PRECISION_U8_NON_LINEAR, FALSE);

      if (! image)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), image);

  return return_vals;
}

static PikaValueArray *
image_new_with_precision_invoker (PikaProcedure         *procedure,
                                  Pika                  *pika,
                                  PikaContext           *context,
                                  PikaProgress          *progress,
                                  const PikaValueArray  *args,
                                  GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  gint width;
  gint height;
  gint type;
  gint precision;
  PikaImage *image = NULL;

  width = g_value_get_int (pika_value_array_index (args, 0));
  height = g_value_get_int (pika_value_array_index (args, 1));
  type = g_value_get_enum (pika_value_array_index (args, 2));
  precision = g_value_get_enum (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_babl_is_valid (type, precision))
        {
          image = pika_create_image (pika, width, height, type,
                                     precision, FALSE);
          if (! image)
            success = FALSE;
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), image);

  return return_vals;
}

static PikaValueArray *
image_duplicate_invoker (PikaProcedure         *procedure,
                         Pika                  *pika,
                         PikaContext           *context,
                         PikaProgress          *progress,
                         const PikaValueArray  *args,
                         GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaImage *new_image = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      new_image = pika_image_duplicate (image);

      if (! new_image)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), new_image);

  return return_vals;
}

static PikaValueArray *
image_delete_invoker (PikaProcedure         *procedure,
                      Pika                  *pika,
                      PikaContext           *context,
                      PikaProgress          *progress,
                      const PikaValueArray  *args,
                      GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      if (pika_image_get_display_count (image) == 0)
        g_object_unref (image);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_base_type_invoker (PikaProcedure         *procedure,
                             Pika                  *pika,
                             PikaContext           *context,
                             PikaProgress          *progress,
                             const PikaValueArray  *args,
                             GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint base_type = 0;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      base_type = pika_image_get_base_type (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_enum (pika_value_array_index (return_vals, 1), base_type);

  return return_vals;
}

static PikaValueArray *
image_get_precision_invoker (PikaProcedure         *procedure,
                             Pika                  *pika,
                             PikaContext           *context,
                             PikaProgress          *progress,
                             const PikaValueArray  *args,
                             GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint precision = 0;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      precision = pika_image_get_precision (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_enum (pika_value_array_index (return_vals, 1), precision);

  return return_vals;
}

static PikaValueArray *
image_get_default_new_layer_mode_invoker (PikaProcedure         *procedure,
                                          Pika                  *pika,
                                          PikaContext           *context,
                                          PikaProgress          *progress,
                                          const PikaValueArray  *args,
                                          GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint mode = 0;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      mode = pika_image_get_default_new_layer_mode (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_enum (pika_value_array_index (return_vals, 1), mode);

  return return_vals;
}

static PikaValueArray *
image_get_width_invoker (PikaProcedure         *procedure,
                         Pika                  *pika,
                         PikaContext           *context,
                         PikaProgress          *progress,
                         const PikaValueArray  *args,
                         GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint width = 0;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      width = pika_image_get_width (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_int (pika_value_array_index (return_vals, 1), width);

  return return_vals;
}

static PikaValueArray *
image_get_height_invoker (PikaProcedure         *procedure,
                          Pika                  *pika,
                          PikaContext           *context,
                          PikaProgress          *progress,
                          const PikaValueArray  *args,
                          GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint height = 0;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      height = pika_image_get_height (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_int (pika_value_array_index (return_vals, 1), height);

  return return_vals;
}

static PikaValueArray *
image_get_layers_invoker (PikaProcedure         *procedure,
                          Pika                  *pika,
                          PikaContext           *context,
                          PikaProgress          *progress,
                          const PikaValueArray  *args,
                          GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint num_layers = 0;
  PikaLayer **layers = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      GList *list = pika_image_get_layer_iter (image);

      num_layers = g_list_length (list);

      if (num_layers)
        {
          gint i;

          layers = g_new (PikaLayer *, num_layers);

          for (i = 0; i < num_layers; i++, list = g_list_next (list))
            layers[i] = g_object_ref (list->data);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_layers);
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_LAYER, (GObject **) layers, num_layers);
    }

  return return_vals;
}

static PikaValueArray *
image_get_channels_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint num_channels = 0;
  PikaChannel **channels = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      GList *list = pika_image_get_channel_iter (image);

      num_channels = g_list_length (list);

      if (num_channels)
        {
          gint i;

          channels = g_new (PikaChannel *, num_channels);

          for (i = 0; i < num_channels; i++, list = g_list_next (list))
            channels[i] = g_object_ref (list->data);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_channels);
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_CHANNEL, (GObject **) channels, num_channels);
    }

  return return_vals;
}

static PikaValueArray *
image_get_vectors_invoker (PikaProcedure         *procedure,
                           Pika                  *pika,
                           PikaContext           *context,
                           PikaProgress          *progress,
                           const PikaValueArray  *args,
                           GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint num_vectors = 0;
  PikaVectors **vectors = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      GList *list = pika_image_get_vectors_iter (image);

      num_vectors = g_list_length (list);

      if (num_vectors)
        {
          gint i;

          vectors = g_new (PikaVectors *, num_vectors);

          for (i = 0; i < num_vectors; i++, list = g_list_next (list))
            vectors[i] = g_object_ref (list->data);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_vectors);
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_VECTORS, (GObject **) vectors, num_vectors);
    }

  return return_vals;
}

static PikaValueArray *
image_unset_active_channel_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      pika_image_unset_selected_channels (image);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_floating_sel_invoker (PikaProcedure         *procedure,
                                Pika                  *pika,
                                PikaContext           *context,
                                PikaProgress          *progress,
                                const PikaValueArray  *args,
                                GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaLayer *floating_sel = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      floating_sel = pika_image_get_floating_selection (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), floating_sel);

  return return_vals;
}

static PikaValueArray *
image_floating_sel_attached_to_invoker (PikaProcedure         *procedure,
                                        Pika                  *pika,
                                        PikaContext           *context,
                                        PikaProgress          *progress,
                                        const PikaValueArray  *args,
                                        GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaDrawable *drawable = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      PikaLayer *floating_sel = pika_image_get_floating_selection (image);

      if (floating_sel)
        drawable = pika_layer_get_floating_sel_drawable (floating_sel);
      else
        drawable = NULL;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), drawable);

  return return_vals;
}

static PikaValueArray *
image_pick_color_invoker (PikaProcedure         *procedure,
                          Pika                  *pika,
                          PikaContext           *context,
                          PikaProgress          *progress,
                          const PikaValueArray  *args,
                          GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint num_drawables;
  const PikaItem **drawables;
  gdouble x;
  gdouble y;
  gboolean sample_merged;
  gboolean sample_average;
  gdouble average_radius;
  PikaRGB color = { 0.0, 0.0, 0.0, 1.0 };

  image = g_value_get_object (pika_value_array_index (args, 0));
  num_drawables = g_value_get_int (pika_value_array_index (args, 1));
  drawables = (const PikaItem **) pika_value_get_object_array (pika_value_array_index (args, 2));
  x = g_value_get_double (pika_value_array_index (args, 3));
  y = g_value_get_double (pika_value_array_index (args, 4));
  sample_merged = g_value_get_boolean (pika_value_array_index (args, 5));
  sample_average = g_value_get_boolean (pika_value_array_index (args, 6));
  average_radius = g_value_get_double (pika_value_array_index (args, 7));

  if (success)
    {
      gint i;

      if (! sample_merged)
        {
          if (num_drawables == 0)
            {
              success = FALSE;
            }
          else
            {
              for (i = 0; i < num_drawables; i++)
                if (pika_item_get_image (PIKA_ITEM (drawables[i])) != image)
                  {
                    success = FALSE;
                    break;
                  }
            }
        }

      if (success && sample_average)
        {
          if (average_radius <= 0.0)
            success = FALSE;
        }

      if (success)
        {
          GList *drawable_list = NULL;

          for (i = 0; i < num_drawables; i++)
            {
              PikaPickable *pickable = (PikaPickable *) drawables[i];

              drawable_list = g_list_prepend (drawable_list, pickable);
              if (! sample_merged)
                pika_pickable_flush (pickable);
            }

          if (sample_merged)
            pika_pickable_flush (PIKA_PICKABLE (image));

          success = pika_image_pick_color (image,
                                           drawable_list,
                                           (gint) x, (gint) y,
                                           FALSE,
                                           sample_merged,
                                           sample_average,
                                           average_radius,
                                           NULL,
                                           NULL,
                                           &color);

          g_list_free (drawable_list);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    pika_value_set_rgb (pika_value_array_index (return_vals, 1), &color);

  return return_vals;
}

static PikaValueArray *
image_pick_correlate_layer_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint x;
  gint y;
  PikaLayer *layer = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  x = g_value_get_int (pika_value_array_index (args, 1));
  y = g_value_get_int (pika_value_array_index (args, 2));

  if (success)
    {
      layer = pika_image_pick_layer (image, x, y, NULL);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), layer);

  return return_vals;
}

static PikaValueArray *
image_insert_layer_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaLayer *layer;
  PikaLayer *parent;
  gint position;

  image = g_value_get_object (pika_value_array_index (args, 0));
  layer = g_value_get_object (pika_value_array_index (args, 1));
  parent = g_value_get_object (pika_value_array_index (args, 2));
  position = g_value_get_int (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_pdb_item_is_floating (PIKA_ITEM (layer), image, error) &&
          pika_pdb_image_is_base_type (image,
                                       pika_drawable_get_base_type (PIKA_DRAWABLE (layer)),
                                       error) &&
          (parent == NULL ||
           (pika_pdb_item_is_in_tree (PIKA_ITEM (parent), image, 0, error) &&
            pika_pdb_item_is_group (PIKA_ITEM (parent), error))))
        {
          if (position == -1 && parent == NULL)
            parent = PIKA_IMAGE_ACTIVE_PARENT;

          /* see layer-new */
          if (pika_drawable_is_gray (PIKA_DRAWABLE (layer)))
            pika_layer_fix_format_space (layer, TRUE, FALSE);

          success = pika_image_add_layer (image, layer,
                                          parent, MAX (position, -1), TRUE);
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_remove_layer_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaLayer *layer;

  image = g_value_get_object (pika_value_array_index (args, 0));
  layer = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_attached (PIKA_ITEM (layer), image, 0, error))
        pika_image_remove_layer (image, layer, TRUE, NULL);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_freeze_layers_invoker (PikaProcedure         *procedure,
                             Pika                  *pika,
                             PikaContext           *context,
                             PikaProgress          *progress,
                             const PikaValueArray  *args,
                             GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      PikaPlugIn    *plug_in   = pika->plug_in_manager->current_plug_in;
      PikaContainer *container = pika_image_get_layers (image);

      if (plug_in)
        success = pika_plug_in_cleanup_layers_freeze (plug_in, image);

      if (success)
        pika_container_freeze (container);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_thaw_layers_invoker (PikaProcedure         *procedure,
                           Pika                  *pika,
                           PikaContext           *context,
                           PikaProgress          *progress,
                           const PikaValueArray  *args,
                           GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      PikaPlugIn    *plug_in   = pika->plug_in_manager->current_plug_in;
      PikaContainer *container = pika_image_get_layers (image);

      if (plug_in)
        success = pika_plug_in_cleanup_layers_thaw (plug_in, image);

      if (success)
        success = pika_container_frozen (container);

      if (success)
        pika_container_thaw (container);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_insert_channel_invoker (PikaProcedure         *procedure,
                              Pika                  *pika,
                              PikaContext           *context,
                              PikaProgress          *progress,
                              const PikaValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaChannel *channel;
  PikaChannel *parent;
  gint position;

  image = g_value_get_object (pika_value_array_index (args, 0));
  channel = g_value_get_object (pika_value_array_index (args, 1));
  parent = g_value_get_object (pika_value_array_index (args, 2));
  position = g_value_get_int (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_pdb_item_is_floating (PIKA_ITEM (channel), image, error) &&
          (parent == NULL ||
           (pika_pdb_item_is_in_tree (PIKA_ITEM (parent), image, 0, error) &&
            pika_pdb_item_is_group (PIKA_ITEM (parent), error))))
        {
          if (position == -1 && parent == NULL)
            parent = PIKA_IMAGE_ACTIVE_PARENT;

          success = pika_image_add_channel (image, channel,
                                            parent, MAX (position, -1), TRUE);
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_remove_channel_invoker (PikaProcedure         *procedure,
                              Pika                  *pika,
                              PikaContext           *context,
                              PikaProgress          *progress,
                              const PikaValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaChannel *channel;

  image = g_value_get_object (pika_value_array_index (args, 0));
  channel = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_attached (PIKA_ITEM (channel), image, 0, error))
        pika_image_remove_channel (image, channel, TRUE, NULL);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_freeze_channels_invoker (PikaProcedure         *procedure,
                               Pika                  *pika,
                               PikaContext           *context,
                               PikaProgress          *progress,
                               const PikaValueArray  *args,
                               GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      PikaPlugIn    *plug_in   = pika->plug_in_manager->current_plug_in;
      PikaContainer *container = pika_image_get_channels (image);

      if (plug_in)
        success = pika_plug_in_cleanup_channels_freeze (plug_in, image);

      if (success)
        pika_container_freeze (container);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_thaw_channels_invoker (PikaProcedure         *procedure,
                             Pika                  *pika,
                             PikaContext           *context,
                             PikaProgress          *progress,
                             const PikaValueArray  *args,
                             GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      PikaPlugIn    *plug_in   = pika->plug_in_manager->current_plug_in;
      PikaContainer *container = pika_image_get_channels (image);

      if (plug_in)
        success = pika_plug_in_cleanup_channels_thaw (plug_in, image);

      if (success)
        success = pika_container_frozen (container);

      if (success)
        pika_container_thaw (container);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_insert_vectors_invoker (PikaProcedure         *procedure,
                              Pika                  *pika,
                              PikaContext           *context,
                              PikaProgress          *progress,
                              const PikaValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaVectors *vectors;
  PikaVectors *parent;
  gint position;

  image = g_value_get_object (pika_value_array_index (args, 0));
  vectors = g_value_get_object (pika_value_array_index (args, 1));
  parent = g_value_get_object (pika_value_array_index (args, 2));
  position = g_value_get_int (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_pdb_item_is_floating (PIKA_ITEM (vectors), image, error) &&
          (parent == NULL ||
           (pika_pdb_item_is_in_tree (PIKA_ITEM (parent), image, 0, error) &&
            pika_pdb_item_is_group (PIKA_ITEM (parent), error))))
        {
          if (position == -1 && parent == NULL)
            parent = PIKA_IMAGE_ACTIVE_PARENT;

          success = pika_image_add_vectors (image, vectors,
                                            parent, MAX (position, -1), TRUE);
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_remove_vectors_invoker (PikaProcedure         *procedure,
                              Pika                  *pika,
                              PikaContext           *context,
                              PikaProgress          *progress,
                              const PikaValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaVectors *vectors;

  image = g_value_get_object (pika_value_array_index (args, 0));
  vectors = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_attached (PIKA_ITEM (vectors), image, 0, error))
        pika_image_remove_vectors (image, vectors, TRUE, NULL);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_freeze_vectors_invoker (PikaProcedure         *procedure,
                              Pika                  *pika,
                              PikaContext           *context,
                              PikaProgress          *progress,
                              const PikaValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      PikaPlugIn    *plug_in   = pika->plug_in_manager->current_plug_in;
      PikaContainer *container = pika_image_get_vectors (image);

      if (plug_in)
        success = pika_plug_in_cleanup_vectors_freeze (plug_in, image);

      if (success)
        pika_container_freeze (container);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_thaw_vectors_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      PikaPlugIn    *plug_in   = pika->plug_in_manager->current_plug_in;
      PikaContainer *container = pika_image_get_vectors (image);

      if (plug_in)
        success = pika_plug_in_cleanup_vectors_thaw (plug_in, image);

      if (success)
        success = pika_container_frozen (container);

      if (success)
        pika_container_thaw (container);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_item_position_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaItem *item;
  gint position = 0;

  image = g_value_get_object (pika_value_array_index (args, 0));
  item = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_in_tree (item, image, 0, error))
        position = pika_item_get_index (item);
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_int (pika_value_array_index (return_vals, 1), position);

  return return_vals;
}

static PikaValueArray *
image_raise_item_invoker (PikaProcedure         *procedure,
                          Pika                  *pika,
                          PikaContext           *context,
                          PikaProgress          *progress,
                          const PikaValueArray  *args,
                          GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaItem *item;

  image = g_value_get_object (pika_value_array_index (args, 0));
  item = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_in_tree (item, image, 0, error))
        success = pika_image_raise_item (image, item, error);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_lower_item_invoker (PikaProcedure         *procedure,
                          Pika                  *pika,
                          PikaContext           *context,
                          PikaProgress          *progress,
                          const PikaValueArray  *args,
                          GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaItem *item;

  image = g_value_get_object (pika_value_array_index (args, 0));
  item = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_in_tree (item, image, 0, error))
        success = pika_image_lower_item (image, item, error);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_raise_item_to_top_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaItem *item;

  image = g_value_get_object (pika_value_array_index (args, 0));
  item = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_in_tree (item, image, 0, error))
        success = pika_image_raise_item_to_top (image, item);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_lower_item_to_bottom_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaItem *item;

  image = g_value_get_object (pika_value_array_index (args, 0));
  item = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_in_tree (item, image, 0, error))
        success = pika_image_lower_item_to_bottom (image, item);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_reorder_item_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaItem *item;
  PikaItem *parent;
  gint position;

  image = g_value_get_object (pika_value_array_index (args, 0));
  item = g_value_get_object (pika_value_array_index (args, 1));
  parent = g_value_get_object (pika_value_array_index (args, 2));
  position = g_value_get_int (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_pdb_item_is_in_tree (item, image, 0, error) &&
          (parent == NULL ||
           (pika_pdb_item_is_in_same_tree (item, parent, image, error) &&
            pika_pdb_item_is_group (parent, error) &&
            pika_pdb_item_is_not_ancestor (item, parent, error))))
        {
          success = pika_image_reorder_item (image, item, parent, position,
                                             TRUE, NULL);
        }
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_flatten_invoker (PikaProcedure         *procedure,
                       Pika                  *pika,
                       PikaContext           *context,
                       PikaProgress          *progress,
                       const PikaValueArray  *args,
                       GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaLayer *layer = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      layer = pika_image_flatten (image, context,
                                  progress, error);

      if (! layer)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), layer);

  return return_vals;
}

static PikaValueArray *
image_merge_visible_layers_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint merge_type;
  PikaLayer *layer = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  merge_type = g_value_get_enum (pika_value_array_index (args, 1));

  if (success)
    {
      GList *layers;

      layers = pika_image_merge_visible_layers (image, context, merge_type,
                                                FALSE, FALSE, progress);

      if (layers)
        /* With merge_selected_groups set to FALSE, we always get only a
         * single selected layer.
         */
        layer = layers->data;

      if (! layer)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), layer);

  return return_vals;
}

static PikaValueArray *
image_merge_down_invoker (PikaProcedure         *procedure,
                          Pika                  *pika,
                          PikaContext           *context,
                          PikaProgress          *progress,
                          const PikaValueArray  *args,
                          GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaLayer *merge_layer;
  gint merge_type;
  PikaLayer *layer = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  merge_layer = g_value_get_object (pika_value_array_index (args, 1));
  merge_type = g_value_get_enum (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_pdb_item_is_attached (PIKA_ITEM (merge_layer), image, 0, error))
        {
          GList *merge_layers = g_list_prepend (NULL, merge_layer);
          GList *layers;

          layers = pika_image_merge_down (image, merge_layers, context,
                                          merge_type, progress, error);
          g_list_free (merge_layers);

          if (! layers)
            success = FALSE;
          else
            layer = layers->data;

          g_list_free (layers);
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), layer);

  return return_vals;
}

static PikaValueArray *
image_merge_layer_group_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaLayer *layer_group;
  PikaLayer *layer = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  layer_group = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_pdb_item_is_attached (PIKA_ITEM (layer_group), image, 0, error) &&
          pika_pdb_item_is_group (PIKA_ITEM (layer_group), error))
        {
          layer = pika_image_merge_group_layer (image,
                                                PIKA_GROUP_LAYER (layer_group));

          if (! layer)
            success = FALSE;
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), layer);

  return return_vals;
}

static PikaValueArray *
image_get_colormap_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  GBytes *colormap = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      guchar *colormap_data;

      colormap_data = pika_image_get_colormap (image);
      colormap = g_bytes_new_take (colormap_data,
                                   3 * pika_image_get_colormap_size (image));
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_boxed (pika_value_array_index (return_vals, 1), colormap);

  return return_vals;
}

static PikaValueArray *
image_set_colormap_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  GBytes *colormap;

  image = g_value_get_object (pika_value_array_index (args, 0));
  colormap = g_value_get_boxed (pika_value_array_index (args, 1));

  if (success)
    {
      pika_image_set_colormap (image,
                               g_bytes_get_data (colormap, NULL),
                               g_bytes_get_size (colormap) / 3,
                               TRUE);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_palette_invoker (PikaProcedure         *procedure,
                           Pika                  *pika,
                           PikaContext           *context,
                           PikaProgress          *progress,
                           const PikaValueArray  *args,
                           GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaPalette *colormap = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      colormap = pika_image_get_colormap_palette (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), colormap);

  return return_vals;
}

static PikaValueArray *
image_get_metadata_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gchar *metadata_string = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      PikaMetadata *metadata = pika_image_get_metadata (image);

      if (metadata)
        metadata_string = pika_metadata_serialize (metadata);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_string (pika_value_array_index (return_vals, 1), metadata_string);

  return return_vals;
}

static PikaValueArray *
image_set_metadata_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  const gchar *metadata_string;

  image = g_value_get_object (pika_value_array_index (args, 0));
  metadata_string = g_value_get_string (pika_value_array_index (args, 1));

  if (success)
    {
      PikaMetadata *metadata = pika_metadata_deserialize (metadata_string);

      pika_image_set_metadata (image, metadata, TRUE);

      if (metadata)
        g_object_unref (metadata);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_clean_all_invoker (PikaProcedure         *procedure,
                         Pika                  *pika,
                         PikaContext           *context,
                         PikaProgress          *progress,
                         const PikaValueArray  *args,
                         GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      pika_image_clean_all (image);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_is_dirty_invoker (PikaProcedure         *procedure,
                        Pika                  *pika,
                        PikaContext           *context,
                        PikaProgress          *progress,
                        const PikaValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gboolean dirty = FALSE;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      dirty = pika_image_is_dirty (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_boolean (pika_value_array_index (return_vals, 1), dirty);

  return return_vals;
}

static PikaValueArray *
image_thumbnail_invoker (PikaProcedure         *procedure,
                         Pika                  *pika,
                         PikaContext           *context,
                         PikaProgress          *progress,
                         const PikaValueArray  *args,
                         GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint width;
  gint height;
  gint actual_width = 0;
  gint actual_height = 0;
  gint bpp = 0;
  GBytes *thumbnail_data = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  width = g_value_get_int (pika_value_array_index (args, 1));
  height = g_value_get_int (pika_value_array_index (args, 2));

  if (success)
    {
      PikaTempBuf *buf;
      gint         dwidth, dheight;

      pika_assert (PIKA_VIEWABLE_MAX_PREVIEW_SIZE >= 1024);

      /* Adjust the width/height ratio */
      dwidth  = pika_image_get_width  (image);
      dheight = pika_image_get_height (image);

      if (dwidth > dheight)
        height = MAX (1, (width * dheight) / dwidth);
      else
        width  = MAX (1, (height * dwidth) / dheight);

      pika_pickable_flush (PIKA_PICKABLE (image));

      buf = pika_viewable_get_new_preview (PIKA_VIEWABLE (image), context,
                                           width, height);

      if (buf)
        {
          actual_width         = pika_temp_buf_get_width  (buf);
          actual_height        = pika_temp_buf_get_height (buf);
          bpp                  = babl_format_get_bytes_per_pixel (pika_temp_buf_get_format (buf));
          thumbnail_data       = g_bytes_new (pika_temp_buf_get_data (buf),
                                              pika_temp_buf_get_data_size (buf));

          pika_temp_buf_unref (buf);
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), actual_width);
      g_value_set_int (pika_value_array_index (return_vals, 2), actual_height);
      g_value_set_int (pika_value_array_index (return_vals, 3), bpp);
      g_value_take_boxed (pika_value_array_index (return_vals, 4), thumbnail_data);
    }

  return return_vals;
}

static PikaValueArray *
image_get_selected_layers_invoker (PikaProcedure         *procedure,
                                   Pika                  *pika,
                                   PikaContext           *context,
                                   PikaProgress          *progress,
                                   const PikaValueArray  *args,
                                   GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint num_layers = 0;
  PikaLayer **layers = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      GList *list = pika_image_get_selected_layers (image);

      num_layers = g_list_length (list);

      if (num_layers)
        {
          gint i;

          layers = g_new (PikaLayer *, num_layers);

          for (i = 0; i < num_layers; i++, list = g_list_next (list))
            layers[i] = g_object_ref (list->data);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_layers);
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_LAYER, (GObject **) layers, num_layers);
    }

  return return_vals;
}

static PikaValueArray *
image_set_selected_layers_invoker (PikaProcedure         *procedure,
                                   Pika                  *pika,
                                   PikaContext           *context,
                                   PikaProgress          *progress,
                                   const PikaValueArray  *args,
                                   GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  gint num_layers;
  const PikaLayer **layers;

  image = g_value_get_object (pika_value_array_index (args, 0));
  num_layers = g_value_get_int (pika_value_array_index (args, 1));
  layers = (const PikaLayer **) pika_value_get_object_array (pika_value_array_index (args, 2));

  if (success)
    {
      GList *selected_layers = NULL;
      gint   i;

      for (i = 0; i < num_layers; i++)
        selected_layers = g_list_prepend (selected_layers,
                                          PIKA_LAYER (layers[i]));

      pika_image_set_selected_layers (image, selected_layers);
      g_list_free (selected_layers);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_selected_channels_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint num_channels = 0;
  PikaChannel **channels = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      GList *list = pika_image_get_selected_channels (image);

      num_channels = g_list_length (list);

      if (num_channels)
        {
          gint i;

          channels = g_new (PikaChannel *, num_channels);

          for (i = 0; i < num_channels; i++, list = g_list_next (list))
            channels[i] = g_object_ref (list->data);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_channels);
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_CHANNEL, (GObject **) channels, num_channels);
    }

  return return_vals;
}

static PikaValueArray *
image_set_selected_channels_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  gint num_channels;
  const PikaChannel **channels;

  image = g_value_get_object (pika_value_array_index (args, 0));
  num_channels = g_value_get_int (pika_value_array_index (args, 1));
  channels = (const PikaChannel **) pika_value_get_object_array (pika_value_array_index (args, 2));

  if (success)
    {
      GList *selected_channels = NULL;
      gint   i;

      for (i = 0; i < num_channels; i++)
        selected_channels = g_list_prepend (selected_channels,
                                            PIKA_CHANNEL (channels[i]));

      pika_image_set_selected_channels (image, selected_channels);
      g_list_free (selected_channels);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_selected_vectors_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint num_vectors = 0;
  PikaVectors **vectors = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      GList *list = pika_image_get_selected_vectors (image);

      num_vectors = g_list_length (list);

      if (num_vectors)
        {
          gint i;

          vectors = g_new (PikaVectors *, num_vectors);

          for (i = 0; i < num_vectors; i++, list = g_list_next (list))
            vectors[i] = g_object_ref (list->data);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_vectors);
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_VECTORS, (GObject **) vectors, num_vectors);
    }

  return return_vals;
}

static PikaValueArray *
image_set_selected_vectors_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  gint num_vectors;
  const PikaVectors **vectors;

  image = g_value_get_object (pika_value_array_index (args, 0));
  num_vectors = g_value_get_int (pika_value_array_index (args, 1));
  vectors = (const PikaVectors **) pika_value_get_object_array (pika_value_array_index (args, 2));

  if (success)
    {
      GList *selected_vectors = NULL;
      gint   i;

      for (i = 0; i < num_vectors; i++)
        selected_vectors = g_list_prepend (selected_vectors,
                                           PIKA_LAYER (vectors[i]));

      pika_image_set_selected_vectors (image, selected_vectors);
      g_list_free (selected_vectors);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_selected_drawables_invoker (PikaProcedure         *procedure,
                                      Pika                  *pika,
                                      PikaContext           *context,
                                      PikaProgress          *progress,
                                      const PikaValueArray  *args,
                                      GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint num_drawables = 0;
  PikaItem **drawables = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      GList *list = pika_image_get_selected_drawables (image);

      num_drawables = g_list_length (list);

      if (num_drawables)
        {
          gint i;

          drawables = g_new (PikaItem *, num_drawables);

          for (i = 0; i < num_drawables; i++, list = g_list_next (list))
            drawables[i] = g_object_ref (list->data);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_drawables);
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_ITEM, (GObject **) drawables, num_drawables);
    }

  return return_vals;
}

static PikaValueArray *
image_get_selection_invoker (PikaProcedure         *procedure,
                             Pika                  *pika,
                             PikaContext           *context,
                             PikaProgress          *progress,
                             const PikaValueArray  *args,
                             GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaSelection *selection = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      selection = PIKA_SELECTION (pika_image_get_mask (image));

      if (! selection)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), selection);

  return return_vals;
}

static PikaValueArray *
image_get_component_active_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint component;
  gboolean active = FALSE;

  image = g_value_get_object (pika_value_array_index (args, 0));
  component = g_value_get_enum (pika_value_array_index (args, 1));

  if (success)
    {
      if (component == PIKA_CHANNEL_GRAY)
        success = pika_pdb_image_is_base_type (image, PIKA_GRAY, error);
      else if (component == PIKA_CHANNEL_INDEXED)
        success = pika_pdb_image_is_base_type (image, PIKA_INDEXED, error);
      else
        success = pika_pdb_image_is_base_type (image, PIKA_RGB, error);

      if (success)
        active = pika_image_get_component_active (image, component);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_boolean (pika_value_array_index (return_vals, 1), active);

  return return_vals;
}

static PikaValueArray *
image_set_component_active_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  gint component;
  gboolean active;

  image = g_value_get_object (pika_value_array_index (args, 0));
  component = g_value_get_enum (pika_value_array_index (args, 1));
  active = g_value_get_boolean (pika_value_array_index (args, 2));

  if (success)
    {
      if (component == PIKA_CHANNEL_GRAY)
        success = pika_pdb_image_is_base_type (image, PIKA_GRAY, error);
      else if (component == PIKA_CHANNEL_INDEXED)
        success = pika_pdb_image_is_base_type (image, PIKA_INDEXED, error);
      else
        success = pika_pdb_image_is_base_type (image, PIKA_RGB, error);

      if (success)
        pika_image_set_component_active (image, component, active);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_component_visible_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gint component;
  gboolean visible = FALSE;

  image = g_value_get_object (pika_value_array_index (args, 0));
  component = g_value_get_enum (pika_value_array_index (args, 1));

  if (success)
    {
      if (component == PIKA_CHANNEL_GRAY)
        success = pika_pdb_image_is_base_type (image, PIKA_GRAY, error);
      else if (component == PIKA_CHANNEL_INDEXED)
        success = pika_pdb_image_is_base_type (image, PIKA_INDEXED, error);
      else
        success = pika_pdb_image_is_base_type (image, PIKA_RGB, error);

      if (success)
        visible = pika_image_get_component_visible (image, component);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_boolean (pika_value_array_index (return_vals, 1), visible);

  return return_vals;
}

static PikaValueArray *
image_set_component_visible_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  gint component;
  gboolean visible;

  image = g_value_get_object (pika_value_array_index (args, 0));
  component = g_value_get_enum (pika_value_array_index (args, 1));
  visible = g_value_get_boolean (pika_value_array_index (args, 2));

  if (success)
    {
      if (component == PIKA_CHANNEL_GRAY)
        success = pika_pdb_image_is_base_type (image, PIKA_GRAY, error);
      else if (component == PIKA_CHANNEL_INDEXED)
        success = pika_pdb_image_is_base_type (image, PIKA_INDEXED, error);
      else
        success = pika_pdb_image_is_base_type (image, PIKA_RGB, error);

      if (success)
        pika_image_set_component_visible (image, component, visible);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_file_invoker (PikaProcedure         *procedure,
                        Pika                  *pika,
                        PikaContext           *context,
                        PikaProgress          *progress,
                        const PikaValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  GFile *file = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      file = pika_image_get_any_file (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), file);

  return return_vals;
}

static PikaValueArray *
image_set_file_invoker (PikaProcedure         *procedure,
                        Pika                  *pika,
                        PikaContext           *context,
                        PikaProgress          *progress,
                        const PikaValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  GFile *file;

  image = g_value_get_object (pika_value_array_index (args, 0));
  file = g_value_get_object (pika_value_array_index (args, 1));

  if (success)
    {
      gchar *uri;
      gchar *folded_uri;
      gchar *folded_ext;

      uri        = g_file_get_uri (file);
      folded_uri = g_utf8_casefold (uri, -1);
      folded_ext = g_utf8_casefold (".xcf", -1);

      if (! g_str_has_suffix (folded_uri, folded_ext))
        {
          gchar *dot = g_strrstr (uri, ".");

          if (dot != NULL && strstr (dot + 1, G_DIR_SEPARATOR_S) == NULL)
            g_printerr ("%s: failure to set file '%s' with extension '%s'. "
                        "The extension must be '.xcf'.\n",
                        "pika_image_set_file", uri, dot + 1);
          else
            g_printerr ("%s: failure to set file '%s' without extension. "
                        "The extension must be '.xcf'.\n",
                        "pika_image_set_file", uri);

          success = FALSE;
        }
      if (success)
        pika_image_set_file (image, file);

      g_free (uri);
      g_free (folded_uri);
      g_free (folded_ext);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_xcf_file_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  GFile *file = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      file = pika_image_get_file (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), file);

  return return_vals;
}

static PikaValueArray *
image_get_imported_file_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  GFile *file = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      file = pika_image_get_imported_file (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), file);

  return return_vals;
}

static PikaValueArray *
image_get_exported_file_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  GFile *file = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      file = pika_image_get_exported_file (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), file);

  return return_vals;
}

static PikaValueArray *
image_get_name_invoker (PikaProcedure         *procedure,
                        Pika                  *pika,
                        PikaContext           *context,
                        PikaProgress          *progress,
                        const PikaValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gchar *name = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      name = g_strdup (pika_image_get_display_name (image));
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_string (pika_value_array_index (return_vals, 1), name);

  return return_vals;
}

static PikaValueArray *
image_get_resolution_invoker (PikaProcedure         *procedure,
                              Pika                  *pika,
                              PikaContext           *context,
                              PikaProgress          *progress,
                              const PikaValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gdouble xresolution = 0.0;
  gdouble yresolution = 0.0;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      pika_image_get_resolution (image, &xresolution, &yresolution);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_double (pika_value_array_index (return_vals, 1), xresolution);
      g_value_set_double (pika_value_array_index (return_vals, 2), yresolution);
    }

  return return_vals;
}

static PikaValueArray *
image_set_resolution_invoker (PikaProcedure         *procedure,
                              Pika                  *pika,
                              PikaContext           *context,
                              PikaProgress          *progress,
                              const PikaValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  gdouble xresolution;
  gdouble yresolution;

  image = g_value_get_object (pika_value_array_index (args, 0));
  xresolution = g_value_get_double (pika_value_array_index (args, 1));
  yresolution = g_value_get_double (pika_value_array_index (args, 2));

  if (success)
    {
      if (! isfinite (xresolution) ||
          xresolution < PIKA_MIN_RESOLUTION || xresolution > PIKA_MAX_RESOLUTION ||
          ! isfinite (yresolution) ||
          yresolution < PIKA_MIN_RESOLUTION || yresolution > PIKA_MAX_RESOLUTION)
        {
          g_set_error_literal (error, PIKA_PDB_ERROR,
                               PIKA_PDB_ERROR_INVALID_ARGUMENT,
                               _("Image resolution is out of bounds, "
                                 "using the default resolution instead."));
          success = FALSE;
        }
      else
        {
          pika_image_set_resolution (image, xresolution, yresolution);
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_unit_invoker (PikaProcedure         *procedure,
                        Pika                  *pika,
                        PikaContext           *context,
                        PikaProgress          *progress,
                        const PikaValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  PikaUnit unit = PIKA_UNIT_PIXEL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      unit = pika_image_get_unit (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_int (pika_value_array_index (return_vals, 1), unit);

  return return_vals;
}

static PikaValueArray *
image_set_unit_invoker (PikaProcedure         *procedure,
                        Pika                  *pika,
                        PikaContext           *context,
                        PikaProgress          *progress,
                        const PikaValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  PikaUnit unit;

  image = g_value_get_object (pika_value_array_index (args, 0));
  unit = g_value_get_int (pika_value_array_index (args, 1));

  if (success)
    {
      pika_image_set_unit (image, unit);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_tattoo_state_invoker (PikaProcedure         *procedure,
                                Pika                  *pika,
                                PikaContext           *context,
                                PikaProgress          *progress,
                                const PikaValueArray  *args,
                                GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  guint tattoo_state = 0;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      tattoo_state = pika_image_get_tattoo_state (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_uint (pika_value_array_index (return_vals, 1), tattoo_state);

  return return_vals;
}

static PikaValueArray *
image_set_tattoo_state_invoker (PikaProcedure         *procedure,
                                Pika                  *pika,
                                PikaContext           *context,
                                PikaProgress          *progress,
                                const PikaValueArray  *args,
                                GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  guint tattoo_state;

  image = g_value_get_object (pika_value_array_index (args, 0));
  tattoo_state = g_value_get_uint (pika_value_array_index (args, 1));

  if (success)
    {
      pika_image_set_tattoo_state (image, tattoo_state);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_layer_by_tattoo_invoker (PikaProcedure         *procedure,
                                   Pika                  *pika,
                                   PikaContext           *context,
                                   PikaProgress          *progress,
                                   const PikaValueArray  *args,
                                   GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  guint tattoo;
  PikaLayer *layer = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  tattoo = g_value_get_uint (pika_value_array_index (args, 1));

  if (success)
    {
      layer = pika_image_get_layer_by_tattoo (image, tattoo);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), layer);

  return return_vals;
}

static PikaValueArray *
image_get_channel_by_tattoo_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  guint tattoo;
  PikaChannel *channel = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  tattoo = g_value_get_uint (pika_value_array_index (args, 1));

  if (success)
    {
      channel = pika_image_get_channel_by_tattoo (image, tattoo);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), channel);

  return return_vals;
}

static PikaValueArray *
image_get_vectors_by_tattoo_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  guint tattoo;
  PikaVectors *vectors = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  tattoo = g_value_get_uint (pika_value_array_index (args, 1));

  if (success)
    {
      vectors = pika_image_get_vectors_by_tattoo (image, tattoo);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), vectors);

  return return_vals;
}

static PikaValueArray *
image_get_layer_by_name_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  const gchar *name;
  PikaLayer *layer = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  name = g_value_get_string (pika_value_array_index (args, 1));

  if (success)
    {
      layer = pika_image_get_layer_by_name (image, name);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), layer);

  return return_vals;
}

static PikaValueArray *
image_get_channel_by_name_invoker (PikaProcedure         *procedure,
                                   Pika                  *pika,
                                   PikaContext           *context,
                                   PikaProgress          *progress,
                                   const PikaValueArray  *args,
                                   GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  const gchar *name;
  PikaChannel *channel = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  name = g_value_get_string (pika_value_array_index (args, 1));

  if (success)
    {
      channel = pika_image_get_channel_by_name (image, name);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), channel);

  return return_vals;
}

static PikaValueArray *
image_get_vectors_by_name_invoker (PikaProcedure         *procedure,
                                   Pika                  *pika,
                                   PikaContext           *context,
                                   PikaProgress          *progress,
                                   const PikaValueArray  *args,
                                   GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  const gchar *name;
  PikaVectors *vectors = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  name = g_value_get_string (pika_value_array_index (args, 1));

  if (success)
    {
      vectors = pika_image_get_vectors_by_name (image, name);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), vectors);

  return return_vals;
}

static PikaValueArray *
image_attach_parasite_invoker (PikaProcedure         *procedure,
                               Pika                  *pika,
                               PikaContext           *context,
                               PikaProgress          *progress,
                               const PikaValueArray  *args,
                               GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  const PikaParasite *parasite;

  image = g_value_get_object (pika_value_array_index (args, 0));
  parasite = g_value_get_boxed (pika_value_array_index (args, 1));

  if (success)
    {
      if (pika_image_parasite_validate (image, parasite, error))
        pika_image_parasite_attach (image, parasite, TRUE);
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_detach_parasite_invoker (PikaProcedure         *procedure,
                               Pika                  *pika,
                               PikaContext           *context,
                               PikaProgress          *progress,
                               const PikaValueArray  *args,
                               GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  const gchar *name;

  image = g_value_get_object (pika_value_array_index (args, 0));
  name = g_value_get_string (pika_value_array_index (args, 1));

  if (success)
    {
      pika_image_parasite_detach (image, name, TRUE);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_get_parasite_invoker (PikaProcedure         *procedure,
                            Pika                  *pika,
                            PikaContext           *context,
                            PikaProgress          *progress,
                            const PikaValueArray  *args,
                            GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  const gchar *name;
  PikaParasite *parasite = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  name = g_value_get_string (pika_value_array_index (args, 1));

  if (success)
    {
      parasite = pika_parasite_copy (pika_image_parasite_find (image, name));

      if (! parasite)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_boxed (pika_value_array_index (return_vals, 1), parasite);

  return return_vals;
}

static PikaValueArray *
image_get_parasite_list_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gchar **parasites = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      parasites = pika_image_parasite_list (image);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_boxed (pika_value_array_index (return_vals, 1), parasites);

  return return_vals;
}

static PikaValueArray *
image_policy_rotate_invoker (PikaProcedure         *procedure,
                             Pika                  *pika,
                             PikaContext           *context,
                             PikaProgress          *progress,
                             const PikaValueArray  *args,
                             GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  gboolean interactive;

  image = g_value_get_object (pika_value_array_index (args, 0));
  interactive = g_value_get_boolean (pika_value_array_index (args, 1));

  if (success)
    {
      pika_image_import_rotation_metadata (image, context, progress, interactive);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
image_policy_color_profile_invoker (PikaProcedure         *procedure,
                                    Pika                  *pika,
                                    PikaContext           *context,
                                    PikaProgress          *progress,
                                    const PikaValueArray  *args,
                                    GError               **error)
{
  gboolean success = TRUE;
  PikaImage *image;
  gboolean interactive;

  image = g_value_get_object (pika_value_array_index (args, 0));
  interactive = g_value_get_boolean (pika_value_array_index (args, 1));

  if (success)
    {
      pika_image_import_color_profile (image, context, progress, interactive);
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

void
register_image_procs (PikaPDB *pdb)
{
  PikaProcedure *procedure;

  /*
   * pika-image-id-is-valid
   */
  procedure = pika_procedure_new (image_id_is_valid_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-id-is-valid");
  pika_procedure_set_static_help (procedure,
                                  "Returns TRUE if the image ID is valid.",
                                  "This procedure checks if the given image ID is valid and refers to an existing image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Sven Neumann <sven@gimp.org>",
                                         "Sven Neumann",
                                         "2007");
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("image-id",
                                                 "image id",
                                                 "The image ID to check",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boolean ("valid",
                                                         "valid",
                                                         "Whether the image ID is valid",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-get-images
   */
  procedure = pika_procedure_new (get_images_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-get-images");
  pika_procedure_set_static_help (procedure,
                                  "Returns the list of images currently open.",
                                  "This procedure returns the list of images currently open in PIKA.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-images",
                                                     "num images",
                                                     "The number of images currently open",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("images",
                                                                 "images",
                                                                 "The list of images currently open.",
                                                                 PIKA_TYPE_IMAGE,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-new
   */
  procedure = pika_procedure_new (image_new_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-new");
  pika_procedure_set_static_help (procedure,
                                  "Creates a new image with the specified width, height, and type.",
                                  "Creates a new image, undisplayed, with the specified extents and type. A layer should be created and added before this image is displayed, or subsequent calls to 'pika-display-new' with this image as an argument will fail. Layers can be created using the 'pika-layer-new' commands. They can be added to an image using the 'pika-image-insert-layer' command.\n"
                                  "\n"
                                  "If your image's type if INDEXED, a colormap must also be added with 'pika-image-set-colormap'. An indexed image without a colormap will output unexpected colors.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("width",
                                                 "width",
                                                 "The width of the image",
                                                 1, PIKA_MAX_IMAGE_SIZE, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("height",
                                                 "height",
                                                 "The height of the image",
                                                 1, PIKA_MAX_IMAGE_SIZE, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("type",
                                                  "type",
                                                  "The type of image",
                                                  PIKA_TYPE_IMAGE_BASE_TYPE,
                                                  PIKA_RGB,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_image ("image",
                                                          "image",
                                                          "The newly created image",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-new-with-precision
   */
  procedure = pika_procedure_new (image_new_with_precision_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-new-with-precision");
  pika_procedure_set_static_help (procedure,
                                  "Creates a new image with the specified width, height, type and precision.",
                                  "Creates a new image, undisplayed with the specified extents, type and precision. Indexed images can only be created at PIKA_PRECISION_U8_NON_LINEAR precision. See 'pika-image-new' for further details.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2012");
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("width",
                                                 "width",
                                                 "The width of the image",
                                                 1, PIKA_MAX_IMAGE_SIZE, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("height",
                                                 "height",
                                                 "The height of the image",
                                                 1, PIKA_MAX_IMAGE_SIZE, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("type",
                                                  "type",
                                                  "The type of image",
                                                  PIKA_TYPE_IMAGE_BASE_TYPE,
                                                  PIKA_RGB,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("precision",
                                                  "precision",
                                                  "The precision",
                                                  PIKA_TYPE_PRECISION,
                                                  PIKA_PRECISION_U8_LINEAR,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_image ("image",
                                                          "image",
                                                          "The newly created image",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-duplicate
   */
  procedure = pika_procedure_new (image_duplicate_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-duplicate");
  pika_procedure_set_static_help (procedure,
                                  "Duplicate the specified image",
                                  "This procedure duplicates the specified image, copying all layers, channels, and image information.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1997");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_image ("new-image",
                                                          "new image",
                                                          "The new, duplicated image",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-delete
   */
  procedure = pika_procedure_new (image_delete_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-delete");
  pika_procedure_set_static_help (procedure,
                                  "Delete the specified image.",
                                  "If there are no displays associated with this image it will be deleted. This means that you can not delete an image through the PDB that was created by the user. If the associated display was however created through the PDB and you know the display ID, you may delete the display. Removal of the last associated display will then delete the image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-base-type
   */
  procedure = pika_procedure_new (image_get_base_type_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-base-type");
  pika_procedure_set_static_help (procedure,
                                  "Get the base type of the image.",
                                  "This procedure returns the image's base type. Layers in the image must be of this subtype, but can have an optional alpha channel.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_enum ("base-type",
                                                      "base type",
                                                      "The image's base type",
                                                      PIKA_TYPE_IMAGE_BASE_TYPE,
                                                      PIKA_RGB,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-precision
   */
  procedure = pika_procedure_new (image_get_precision_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-precision");
  pika_procedure_set_static_help (procedure,
                                  "Get the precision of the image.",
                                  "This procedure returns the image's precision.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2012");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_enum ("precision",
                                                      "precision",
                                                      "The image's precision",
                                                      PIKA_TYPE_PRECISION,
                                                      PIKA_PRECISION_U8_LINEAR,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-default-new-layer-mode
   */
  procedure = pika_procedure_new (image_get_default_new_layer_mode_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-default-new-layer-mode");
  pika_procedure_set_static_help (procedure,
                                  "Get the default mode for newly created layers of this image.",
                                  "Returns the default mode for newly created layers of this image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2017");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_enum ("mode",
                                                      "mode",
                                                      "The layer mode",
                                                      PIKA_TYPE_LAYER_MODE,
                                                      PIKA_LAYER_MODE_NORMAL,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-width
   */
  procedure = pika_procedure_new (image_get_width_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-width");
  pika_procedure_set_static_help (procedure,
                                  "Return the width of the image",
                                  "This procedure returns the image's width. This value is independent of any of the layers in this image. This is the \"canvas\" width.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("width",
                                                     "width",
                                                     "The image's width",
                                                     G_MININT32, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-height
   */
  procedure = pika_procedure_new (image_get_height_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-height");
  pika_procedure_set_static_help (procedure,
                                  "Return the height of the image",
                                  "This procedure returns the image's height. This value is independent of any of the layers in this image. This is the \"canvas\" height.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("height",
                                                     "height",
                                                     "The image's height",
                                                     G_MININT32, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-layers
   */
  procedure = pika_procedure_new (image_get_layers_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-layers");
  pika_procedure_set_static_help (procedure,
                                  "Returns the list of root layers contained in the specified image.",
                                  "This procedure returns the list of root layers contained in the specified image. The order of layers is from topmost to bottommost.\n"
                                  "Note that this is not the full list of layers, but only the root layers, i.e. layers with no parents themselves. If you need all layers, it is up to you to verify that any of these layers is a group layer with 'pika-item-is-group' and to obtain its children with 'pika-item-get-children' (possibly recursively checking if these have children too).",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-layers",
                                                     "num layers",
                                                     "The number of root layers contained in the image",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("layers",
                                                                 "layers",
                                                                 "The list of layers contained in the image.",
                                                                 PIKA_TYPE_LAYER,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-channels
   */
  procedure = pika_procedure_new (image_get_channels_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-channels");
  pika_procedure_set_static_help (procedure,
                                  "Returns the list of channels contained in the specified image.",
                                  "This procedure returns the list of channels contained in the specified image. This does not include the selection mask, or layer masks. The order is from topmost to bottommost. Note that \"channels\" are custom channels and do not include the image's color components.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-channels",
                                                     "num channels",
                                                     "The number of channels contained in the image",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("channels",
                                                                 "channels",
                                                                 "The list of channels contained in the image.",
                                                                 PIKA_TYPE_CHANNEL,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-vectors
   */
  procedure = pika_procedure_new (image_get_vectors_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-vectors");
  pika_procedure_set_static_help (procedure,
                                  "Returns the list of vectors contained in the specified image.",
                                  "This procedure returns the list of vectors contained in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Simon Budig",
                                         "Simon Budig",
                                         "2005");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-vectors",
                                                     "num vectors",
                                                     "The number of vectors contained in the image",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("vectors",
                                                                 "vectors",
                                                                 "The list of vectors contained in the image.",
                                                                 PIKA_TYPE_VECTORS,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-unset-active-channel
   */
  procedure = pika_procedure_new (image_unset_active_channel_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-unset-active-channel");
  pika_procedure_set_static_help (procedure,
                                  "Unsets the active channel in the specified image.",
                                  "If an active channel exists, it is unset. There then exists no active channel, and if desired, one can be set through a call to 'Set Active Channel'. No error is returned in the case of no existing active channel.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-floating-sel
   */
  procedure = pika_procedure_new (image_get_floating_sel_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-floating-sel");
  pika_procedure_set_static_help (procedure,
                                  "Return the floating selection of the image.",
                                  "This procedure returns the image's floating selection, if it exists. If it doesn't exist, -1 is returned as the layer ID.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("floating-sel",
                                                          "floating sel",
                                                          "The image's floating selection",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-floating-sel-attached-to
   */
  procedure = pika_procedure_new (image_floating_sel_attached_to_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-floating-sel-attached-to");
  pika_procedure_set_static_help (procedure,
                                  "Return the drawable the floating selection is attached to.",
                                  "This procedure returns the drawable the image's floating selection is attached to, if it exists. If it doesn't exist, -1 is returned as the drawable ID.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Wolfgang Hofer",
                                         "Wolfgang Hofer",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_drawable ("drawable",
                                                             "drawable",
                                                             "The drawable the floating selection is attached to",
                                                             FALSE,
                                                             PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-pick-color
   */
  procedure = pika_procedure_new (image_pick_color_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-pick-color");
  pika_procedure_set_static_help (procedure,
                                  "Determine the color at the given coordinates",
                                  "This tool determines the color at the specified coordinates. The returned color is an RGB triplet even for grayscale and indexed drawables. If the coordinates lie outside of the extents of the specified drawables, then an error is returned. All drawables must belong to the image and be of the same type.\n"
                                  "If only one drawable is given and it has an alpha channel, the algorithm examines the alpha value of the drawable at the coordinates. If the alpha value is completely transparent (0), then an error is returned. With several drawables specified, the composite image with only these drawables is used.\n"
                                  "If the sample_merged parameter is TRUE, the data of the composite image will be used instead of that for the specified drawables. This is equivalent to sampling for colors after merging all visible layers. In the case of a merged sampling, the supplied drawables are ignored.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-drawables",
                                                 "num drawables",
                                                 "The number of drawables",
                                                 1, G_MAXINT32, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_object_array ("drawables",
                                                             "drawables",
                                                             "The drawables to pick from",
                                                             PIKA_TYPE_ITEM,
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("x",
                                                    "x",
                                                    "x coordinate of upper-left corner of rectangle",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("y",
                                                    "y",
                                                    "y coordinate of upper-left corner of rectangle",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("sample-merged",
                                                     "sample merged",
                                                     "Use the composite image, not the drawables",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("sample-average",
                                                     "sample average",
                                                     "Average the color of all the pixels in a specified radius",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("average-radius",
                                                    "average radius",
                                                    "The radius of pixels to average",
                                                    0, G_MAXDOUBLE, 0,
                                                    PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_rgb ("color",
                                                        "color",
                                                        "The return color",
                                                        TRUE,
                                                        NULL,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-pick-correlate-layer
   */
  procedure = pika_procedure_new (image_pick_correlate_layer_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-pick-correlate-layer");
  pika_procedure_set_static_help (procedure,
                                  "Find the layer visible at the specified coordinates.",
                                  "This procedure finds the layer which is visible at the specified coordinates. Layers which do not qualify are those whose extents do not pass within the specified coordinates, or which are transparent at the specified coordinates. This procedure will return -1 if no layer is found.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("x",
                                                 "x",
                                                 "The x coordinate for the pick",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("y",
                                                 "y",
                                                 "The y coordinate for the pick",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("layer",
                                                          "layer",
                                                          "The layer found at the specified coordinates",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-insert-layer
   */
  procedure = pika_procedure_new (image_insert_layer_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-insert-layer");
  pika_procedure_set_static_help (procedure,
                                  "Add the specified layer to the image.",
                                  "This procedure adds the specified layer to the image at the given position. If the specified parent is a valid layer group (See 'pika-item-is-group' and 'pika-layer-group-new') then the layer is added inside the group. If the parent is 0, the layer is added inside the main stack, outside of any group. The position argument specifies the location of the layer inside the stack (or the group, if a valid parent was supplied), starting from the top (0) and increasing. If the position is specified as -1 and the parent is specified as 0, then the layer is inserted above the active layer, or inside the group if the active layer is a layer group. The layer type must be compatible with the image base type.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_layer ("layer",
                                                      "layer",
                                                      "The layer",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_layer ("parent",
                                                      "parent",
                                                      "The parent layer",
                                                      TRUE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("position",
                                                 "position",
                                                 "The layer position",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-remove-layer
   */
  procedure = pika_procedure_new (image_remove_layer_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-remove-layer");
  pika_procedure_set_static_help (procedure,
                                  "Remove the specified layer from the image.",
                                  "This procedure removes the specified layer from the image. If the layer doesn't exist, an error is returned. If there are no layers left in the image, this call will fail. If this layer is the last layer remaining, the image will become empty and have no active layer.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_layer ("layer",
                                                      "layer",
                                                      "The layer",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-freeze-layers
   */
  procedure = pika_procedure_new (image_freeze_layers_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-freeze-layers");
  pika_procedure_set_static_help (procedure,
                                  "Freeze the image's layer list.",
                                  "This procedure freezes the layer list of the image, suppressing any updates to the Layers dialog in response to changes to the image's layers. This can significantly improve performance while applying changes affecting the layer list.\n"
                                  "\n"
                                  "Each call to 'pika-image-freeze-layers' should be matched by a corresponding call to 'pika-image-thaw-layers', undoing its effects.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Ell",
                                         "Ell",
                                         "2018");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-thaw-layers
   */
  procedure = pika_procedure_new (image_thaw_layers_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-thaw-layers");
  pika_procedure_set_static_help (procedure,
                                  "Thaw the image's layer list.",
                                  "This procedure thaws the layer list of the image, re-enabling updates to the Layers dialog.\n"
                                  "\n"
                                  "This procedure should match a corresponding call to 'pika-image-freeze-layers'.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Ell",
                                         "Ell",
                                         "2018");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-insert-channel
   */
  procedure = pika_procedure_new (image_insert_channel_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-insert-channel");
  pika_procedure_set_static_help (procedure,
                                  "Add the specified channel to the image.",
                                  "This procedure adds the specified channel to the image at the given position. Since channel groups are not currently supported, the parent argument must always be 0. The position argument specifies the location of the channel inside the stack, starting from the top (0) and increasing. If the position is specified as -1, then the channel is inserted above the active channel.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_channel ("channel",
                                                        "channel",
                                                        "The channel",
                                                        FALSE,
                                                        PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_channel ("parent",
                                                        "parent",
                                                        "The parent channel",
                                                        TRUE,
                                                        PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("position",
                                                 "position",
                                                 "The channel position",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-remove-channel
   */
  procedure = pika_procedure_new (image_remove_channel_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-remove-channel");
  pika_procedure_set_static_help (procedure,
                                  "Remove the specified channel from the image.",
                                  "This procedure removes the specified channel from the image. If the channel doesn't exist, an error is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_channel ("channel",
                                                        "channel",
                                                        "The channel",
                                                        FALSE,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-freeze-channels
   */
  procedure = pika_procedure_new (image_freeze_channels_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-freeze-channels");
  pika_procedure_set_static_help (procedure,
                                  "Freeze the image's channel list.",
                                  "This procedure freezes the channel list of the image, suppressing any updates to the Channels dialog in response to changes to the image's channels. This can significantly improve performance while applying changes affecting the channel list.\n"
                                  "\n"
                                  "Each call to 'pika-image-freeze-channels' should be matched by a corresponding call to 'pika-image-thaw-channels', undoing its effects.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Ell",
                                         "Ell",
                                         "2018");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-thaw-channels
   */
  procedure = pika_procedure_new (image_thaw_channels_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-thaw-channels");
  pika_procedure_set_static_help (procedure,
                                  "Thaw the image's channel list.",
                                  "This procedure thaws the channel list of the image, re-enabling updates to the Channels dialog.\n"
                                  "\n"
                                  "This procedure should match a corresponding call to 'pika-image-freeze-channels'.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Ell",
                                         "Ell",
                                         "2018");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-insert-vectors
   */
  procedure = pika_procedure_new (image_insert_vectors_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-insert-vectors");
  pika_procedure_set_static_help (procedure,
                                  "Add the specified vectors to the image.",
                                  "This procedure adds the specified vectors to the image at the given position. Since vectors groups are not currently supported, the parent argument must always be 0. The position argument specifies the location of the vectors inside the stack, starting from the top (0) and increasing. If the position is specified as -1, then the vectors is inserted above the active vectors.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_vectors ("vectors",
                                                        "vectors",
                                                        "The vectors",
                                                        FALSE,
                                                        PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_vectors ("parent",
                                                        "parent",
                                                        "The parent vectors",
                                                        TRUE,
                                                        PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("position",
                                                 "position",
                                                 "The vectors position",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-remove-vectors
   */
  procedure = pika_procedure_new (image_remove_vectors_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-remove-vectors");
  pika_procedure_set_static_help (procedure,
                                  "Remove the specified path from the image.",
                                  "This procedure removes the specified path from the image. If the path doesn't exist, an error is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Simon Budig",
                                         "Simon Budig",
                                         "2005");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_vectors ("vectors",
                                                        "vectors",
                                                        "The vectors object",
                                                        FALSE,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-freeze-vectors
   */
  procedure = pika_procedure_new (image_freeze_vectors_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-freeze-vectors");
  pika_procedure_set_static_help (procedure,
                                  "Freeze the image's vectors list.",
                                  "This procedure freezes the vectors list of the image, suppressing any updates to the Paths dialog in response to changes to the image's vectors. This can significantly improve performance while applying changes affecting the vectors list.\n"
                                  "\n"
                                  "Each call to 'pika-image-freeze-vectors' should be matched by a corresponding call to 'pika-image-thaw-vectors', undoing its effects.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Ell",
                                         "Ell",
                                         "2018");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-thaw-vectors
   */
  procedure = pika_procedure_new (image_thaw_vectors_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-thaw-vectors");
  pika_procedure_set_static_help (procedure,
                                  "Thaw the image's vectors list.",
                                  "This procedure thaws the vectors list of the image, re-enabling updates to the Paths dialog.\n"
                                  "\n"
                                  "This procedure should match a corresponding call to 'pika-image-freeze-vectors'.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Ell",
                                         "Ell",
                                         "2018");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-item-position
   */
  procedure = pika_procedure_new (image_get_item_position_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-item-position");
  pika_procedure_set_static_help (procedure,
                                  "Returns the position of the item in its level of its item tree.",
                                  "This procedure determines the position of the specified item in its level in its item tree in the image. If the item doesn't exist in the image, or the item is not part of an item tree, an error is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2010");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_item ("item",
                                                     "item",
                                                     "The item",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("position",
                                                     "position",
                                                     "The position of the item in its level in the item tree",
                                                     G_MININT32, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-raise-item
   */
  procedure = pika_procedure_new (image_raise_item_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-raise-item");
  pika_procedure_set_static_help (procedure,
                                  "Raise the specified item in its level in its item tree",
                                  "This procedure raises the specified item one step in the item tree. The procedure call will fail if there is no item above it.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2010");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_item ("item",
                                                     "item",
                                                     "The item to raise",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-lower-item
   */
  procedure = pika_procedure_new (image_lower_item_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-lower-item");
  pika_procedure_set_static_help (procedure,
                                  "Lower the specified item in its level in its item tree",
                                  "This procedure lowers the specified item one step in the item tree. The procedure call will fail if there is no item below it.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2010");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_item ("item",
                                                     "item",
                                                     "The item to lower",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-raise-item-to-top
   */
  procedure = pika_procedure_new (image_raise_item_to_top_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-raise-item-to-top");
  pika_procedure_set_static_help (procedure,
                                  "Raise the specified item to the top of its level in its item tree",
                                  "This procedure raises the specified item to top of its level in the item tree. It will not move the item if there is no item above it.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2010");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_item ("item",
                                                     "item",
                                                     "The item to raise to top",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-lower-item-to-bottom
   */
  procedure = pika_procedure_new (image_lower_item_to_bottom_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-lower-item-to-bottom");
  pika_procedure_set_static_help (procedure,
                                  "Lower the specified item to the bottom of its level in its item tree",
                                  "This procedure lowers the specified item to bottom of its level in the item tree. It will not move the layer if there is no layer below it.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2010");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_item ("item",
                                                     "item",
                                                     "The item to lower to bottom",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-reorder-item
   */
  procedure = pika_procedure_new (image_reorder_item_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-reorder-item");
  pika_procedure_set_static_help (procedure,
                                  "Reorder the specified item within its item tree",
                                  "This procedure reorders the specified item within its item tree.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2010");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_item ("item",
                                                     "item",
                                                     "The item to reorder",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_item ("parent",
                                                     "parent",
                                                     "The new parent item",
                                                     TRUE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("position",
                                                 "position",
                                                 "The new position of the item",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-flatten
   */
  procedure = pika_procedure_new (image_flatten_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-flatten");
  pika_procedure_set_static_help (procedure,
                                  "Flatten all visible layers into a single layer. Discard all invisible layers.",
                                  "This procedure combines the visible layers in a manner analogous to merging with the CLIP_TO_IMAGE merge type. Non-visible layers are discarded, and the resulting image is stripped of its alpha channel.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("layer",
                                                          "layer",
                                                          "The resulting layer",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-merge-visible-layers
   */
  procedure = pika_procedure_new (image_merge_visible_layers_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-merge-visible-layers");
  pika_procedure_set_static_help (procedure,
                                  "Merge the visible image layers into one.",
                                  "This procedure combines the visible layers into a single layer using the specified merge type. A merge type of EXPAND_AS_NECESSARY expands the final layer to encompass the areas of the visible layers. A merge type of CLIP_TO_IMAGE clips the final layer to the extents of the image. A merge type of CLIP_TO_BOTTOM_LAYER clips the final layer to the size of the bottommost layer.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_enum ("merge-type",
                                                     "merge type",
                                                     "The type of merge",
                                                     PIKA_TYPE_MERGE_TYPE,
                                                     PIKA_EXPAND_AS_NECESSARY,
                                                     PIKA_PARAM_READWRITE));
  pika_param_spec_enum_exclude_value (PIKA_PARAM_SPEC_ENUM (procedure->args[1]),
                                      PIKA_FLATTEN_IMAGE);
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("layer",
                                                          "layer",
                                                          "The resulting layer",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-merge-down
   */
  procedure = pika_procedure_new (image_merge_down_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-merge-down");
  pika_procedure_set_static_help (procedure,
                                  "Merge the layer passed and the first visible layer below.",
                                  "This procedure combines the passed layer and the first visible layer below it using the specified merge type. A merge type of EXPAND_AS_NECESSARY expands the final layer to encompass the areas of the visible layers. A merge type of CLIP_TO_IMAGE clips the final layer to the extents of the image. A merge type of CLIP_TO_BOTTOM_LAYER clips the final layer to the size of the bottommost layer.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Larry Ewing",
                                         "Larry Ewing",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_layer ("merge-layer",
                                                      "merge layer",
                                                      "The layer to merge down from",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_enum ("merge-type",
                                                     "merge type",
                                                     "The type of merge",
                                                     PIKA_TYPE_MERGE_TYPE,
                                                     PIKA_EXPAND_AS_NECESSARY,
                                                     PIKA_PARAM_READWRITE));
  pika_param_spec_enum_exclude_value (PIKA_PARAM_SPEC_ENUM (procedure->args[2]),
                                      PIKA_FLATTEN_IMAGE);
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("layer",
                                                          "layer",
                                                          "The resulting layer",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-merge-layer-group
   */
  procedure = pika_procedure_new (image_merge_layer_group_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-merge-layer-group");
  pika_procedure_set_static_help (procedure,
                                  "Merge the passed layer group's layers into one normal layer.",
                                  "This procedure combines the layers of the passed layer group into a single normal layer, replacing the group.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Ell",
                                         "Ell",
                                         "2019");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_layer ("layer-group",
                                                      "layer group",
                                                      "The layer group to merge",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("layer",
                                                          "layer",
                                                          "The resulting layer",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-colormap
   */
  procedure = pika_procedure_new (image_get_colormap_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-colormap");
  pika_procedure_set_static_help (procedure,
                                  "Returns the image's colormap",
                                  "This procedure returns an actual pointer to the image's colormap, as well as the number of bytes contained in the colormap. The actual number of colors in the transmitted colormap will be 'num-bytes' / 3. If the image is not in Indexed color mode, no colormap is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boxed ("colormap",
                                                       "colormap",
                                                       "The image's colormap.",
                                                       G_TYPE_BYTES,
                                                       PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-colormap
   */
  procedure = pika_procedure_new (image_set_colormap_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-colormap");
  pika_procedure_set_static_help (procedure,
                                  "Sets the entries in the image's colormap.",
                                  "This procedure sets the entries in the specified image's colormap. The number of entries is specified by the 'num-bytes' parameter and corresponds to the number of INT8 triples that must be contained in the 'colormap' array. The actual number of colors in the transmitted colormap is 'num-bytes' / 3.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boxed ("colormap",
                                                   "colormap",
                                                   "The new colormap values",
                                                   G_TYPE_BYTES,
                                                   PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-palette
   */
  procedure = pika_procedure_new (image_get_palette_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-palette");
  pika_procedure_set_static_help (procedure,
                                  "Returns the image's colormap",
                                  "This procedure returns the image's colormap as a PikaPalette. If the image is not in Indexed color mode, %NULL is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2023");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_palette ("colormap",
                                                            "colormap",
                                                            "The image's colormap.",
                                                            FALSE,
                                                            PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-metadata
   */
  procedure = pika_procedure_new (image_get_metadata_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-metadata");
  pika_procedure_set_static_help (procedure,
                                  "Returns the image's metadata.",
                                  "Returns exif/iptc/xmp metadata from the image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_string ("metadata-string",
                                                           "metadata string",
                                                           "The exif/ptc/xmp metadata as a string",
                                                           FALSE, FALSE, FALSE,
                                                           NULL,
                                                           PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-metadata
   */
  procedure = pika_procedure_new (image_set_metadata_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-metadata");
  pika_procedure_set_static_help (procedure,
                                  "Set the image's metadata.",
                                  "Sets exif/iptc/xmp metadata on the image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("metadata-string",
                                                       "metadata string",
                                                       "The exif/ptc/xmp metadata as a string",
                                                       FALSE, FALSE, FALSE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-clean-all
   */
  procedure = pika_procedure_new (image_clean_all_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-clean-all");
  pika_procedure_set_static_help (procedure,
                                  "Set the image dirty count to 0.",
                                  "This procedure sets the specified image's dirty count to 0, allowing operations to occur without having a 'dirtied' image. This is especially useful for creating and loading images which should not initially be considered dirty, even though layers must be created, filled, and installed in the image. Note that save plug-ins must NOT call this function themselves after saving the image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-is-dirty
   */
  procedure = pika_procedure_new (image_is_dirty_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-is-dirty");
  pika_procedure_set_static_help (procedure,
                                  "Checks if the image has unsaved changes.",
                                  "This procedure checks the specified image's dirty count to see if it needs to be saved. Note that saving the image does not automatically set the dirty count to 0, you need to call 'pika-image-clean-all' after calling a save procedure to make the image clean.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boolean ("dirty",
                                                         "dirty",
                                                         "TRUE if the image has unsaved changes.",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-thumbnail
   */
  procedure = pika_procedure_new (image_thumbnail_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-thumbnail");
  pika_procedure_set_static_help (procedure,
                                  "Get a thumbnail of an image.",
                                  "This function gets data from which a thumbnail of an image preview can be created. Maximum x or y dimension is 1024 pixels. The pixels are returned in RGB[A] or GRAY[A] format. The bpp return value gives the number of bits per pixel in the image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Andy Thomas",
                                         "Andy Thomas",
                                         "1999");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("width",
                                                 "width",
                                                 "The requested thumbnail width",
                                                 1, 1024, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("height",
                                                 "height",
                                                 "The requested thumbnail height",
                                                 1, 1024, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("actual-width",
                                                     "actual width",
                                                     "The previews width",
                                                     G_MININT32, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("actual-height",
                                                     "actual height",
                                                     "The previews height",
                                                     G_MININT32, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("bpp",
                                                     "bpp",
                                                     "The previews bpp",
                                                     G_MININT32, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boxed ("thumbnail-data",
                                                       "thumbnail data",
                                                       "The thumbnail data",
                                                       G_TYPE_BYTES,
                                                       PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-selected-layers
   */
  procedure = pika_procedure_new (image_get_selected_layers_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-selected-layers");
  pika_procedure_set_static_help (procedure,
                                  "Returns the specified image's selected layers.",
                                  "This procedure returns the list of selected layers in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2020");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-layers",
                                                     "num layers",
                                                     "The number of selected layers in the image",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("layers",
                                                                 "layers",
                                                                 "The list of selected layers in the image.",
                                                                 PIKA_TYPE_LAYER,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-selected-layers
   */
  procedure = pika_procedure_new (image_set_selected_layers_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-selected-layers");
  pika_procedure_set_static_help (procedure,
                                  "Sets the specified image's selected layers.",
                                  "The layers are set as the selected layers in the image. Any previous selected layers or channels are unselected. An exception is a previously existing floating selection, in which case this procedure will return an execution error.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2021");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-layers",
                                                 "num layers",
                                                 "The number of layers to select",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_object_array ("layers",
                                                             "layers",
                                                             "The list of layers to select",
                                                             PIKA_TYPE_LAYER,
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-selected-channels
   */
  procedure = pika_procedure_new (image_get_selected_channels_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-selected-channels");
  pika_procedure_set_static_help (procedure,
                                  "Returns the specified image's selected channels.",
                                  "This procedure returns the list of selected channels in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2022");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-channels",
                                                     "num channels",
                                                     "The number of selected channels in the image",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("channels",
                                                                 "channels",
                                                                 "The list of selected channels in the image.",
                                                                 PIKA_TYPE_CHANNEL,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-selected-channels
   */
  procedure = pika_procedure_new (image_set_selected_channels_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-selected-channels");
  pika_procedure_set_static_help (procedure,
                                  "Sets the specified image's selected channels.",
                                  "The channels are set as the selected channels in the image. Any previous selected layers or channels are unselected. An exception is a previously existing floating selection, in which case this procedure will return an execution error.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2022");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-channels",
                                                 "num channels",
                                                 "The number of channels to select",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_object_array ("channels",
                                                             "channels",
                                                             "The list of channels to select",
                                                             PIKA_TYPE_CHANNEL,
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-selected-vectors
   */
  procedure = pika_procedure_new (image_get_selected_vectors_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-selected-vectors");
  pika_procedure_set_static_help (procedure,
                                  "Returns the specified image's selected vectors.",
                                  "This procedure returns the list of selected vectors in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2022");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-vectors",
                                                     "num vectors",
                                                     "The number of selected vectors in the image",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("vectors",
                                                                 "vectors",
                                                                 "The list of selected vectors in the image.",
                                                                 PIKA_TYPE_VECTORS,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-selected-vectors
   */
  procedure = pika_procedure_new (image_set_selected_vectors_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-selected-vectors");
  pika_procedure_set_static_help (procedure,
                                  "Sets the specified image's selected vectors.",
                                  "The vectors are set as the selected vectors in the image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2022");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-vectors",
                                                 "num vectors",
                                                 "The number of vectors to select",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_object_array ("vectors",
                                                             "vectors",
                                                             "The list of vectors to select",
                                                             PIKA_TYPE_VECTORS,
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-selected-drawables
   */
  procedure = pika_procedure_new (image_get_selected_drawables_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-selected-drawables");
  pika_procedure_set_static_help (procedure,
                                  "Get the image's selected drawables",
                                  "This procedure returns the list of selected drawable in the specified image. This can be either layers, channels, or a layer mask.\n"
                                  "The active drawables are the active image channels. If there are none, these are the active image layers. If the active image layer has a layer mask and the layer mask is in edit mode, then the layer mask is the active drawable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2022");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-drawables",
                                                     "num drawables",
                                                     "The number of selected drawables in the image",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("drawables",
                                                                 "drawables",
                                                                 "The list of selected drawables in the image.",
                                                                 PIKA_TYPE_ITEM,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-selection
   */
  procedure = pika_procedure_new (image_get_selection_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-selection");
  pika_procedure_set_static_help (procedure,
                                  "Returns the specified image's selection.",
                                  "This will always return a valid ID for a selection -- which is represented as a channel internally.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_selection ("selection",
                                                              "selection",
                                                              "The selection channel",
                                                              FALSE,
                                                              PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-component-active
   */
  procedure = pika_procedure_new (image_get_component_active_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-component-active");
  pika_procedure_set_static_help (procedure,
                                  "Returns if the specified image's image component is active.",
                                  "This procedure returns if the specified image's image component (i.e. Red, Green, Blue intensity channels in an RGB image) is active or inactive -- whether or not it can be modified. If the specified component is not valid for the image type, an error is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("component",
                                                  "component",
                                                  "The image component",
                                                  PIKA_TYPE_CHANNEL_TYPE,
                                                  PIKA_CHANNEL_RED,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boolean ("active",
                                                         "active",
                                                         "Component is active",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-component-active
   */
  procedure = pika_procedure_new (image_set_component_active_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-component-active");
  pika_procedure_set_static_help (procedure,
                                  "Sets if the specified image's image component is active.",
                                  "This procedure sets if the specified image's image component (i.e. Red, Green, Blue intensity channels in an RGB image) is active or inactive -- whether or not it can be modified. If the specified component is not valid for the image type, an error is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("component",
                                                  "component",
                                                  "The image component",
                                                  PIKA_TYPE_CHANNEL_TYPE,
                                                  PIKA_CHANNEL_RED,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("active",
                                                     "active",
                                                     "Component is active",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-component-visible
   */
  procedure = pika_procedure_new (image_get_component_visible_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-component-visible");
  pika_procedure_set_static_help (procedure,
                                  "Returns if the specified image's image component is visible.",
                                  "This procedure returns if the specified image's image component (i.e. Red, Green, Blue intensity channels in an RGB image) is visible or invisible -- whether or not it can be seen. If the specified component is not valid for the image type, an error is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("component",
                                                  "component",
                                                  "The image component",
                                                  PIKA_TYPE_CHANNEL_TYPE,
                                                  PIKA_CHANNEL_RED,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boolean ("visible",
                                                         "visible",
                                                         "Component is visible",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-component-visible
   */
  procedure = pika_procedure_new (image_set_component_visible_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-component-visible");
  pika_procedure_set_static_help (procedure,
                                  "Sets if the specified image's image component is visible.",
                                  "This procedure sets if the specified image's image component (i.e. Red, Green, Blue intensity channels in an RGB image) is visible or invisible -- whether or not it can be seen. If the specified component is not valid for the image type, an error is returned.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("component",
                                                  "component",
                                                  "The image component",
                                                  PIKA_TYPE_CHANNEL_TYPE,
                                                  PIKA_CHANNEL_RED,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("visible",
                                                     "visible",
                                                     "Component is visible",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-file
   */
  procedure = pika_procedure_new (image_get_file_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-file");
  pika_procedure_set_static_help (procedure,
                                  "Returns the file for the specified image.",
                                  "This procedure returns the file associated with the specified image. The image has a file only if it was loaded or imported from a file or has since been saved or exported. Otherwise, this function returns %NULL. See also pika-image-get-imported-file to get the current file if it was imported from a non-PIKA file format and not yet saved, or pika-image-get-exported-file if the image has been exported to a non-PIKA file format.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Sven Neumann <sven@gimp.org>",
                                         "Sven Neumann",
                                         "2009");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_object ("file",
                                                        "file",
                                                        "The file.",
                                                        G_TYPE_FILE,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-file
   */
  procedure = pika_procedure_new (image_set_file_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-file");
  pika_procedure_set_static_help (procedure,
                                  "Sets the specified XCF image's file.",
                                  "This procedure sets the specified image's file.\n"
                                  "This is to set the XCF file associated with your image. In particular, do not use this function to set the imported file in file import plug-ins. This is done by the core process.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_object ("file",
                                                    "file",
                                                    "The new image file",
                                                    G_TYPE_FILE,
                                                    PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-xcf-file
   */
  procedure = pika_procedure_new (image_get_xcf_file_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-xcf-file");
  pika_procedure_set_static_help (procedure,
                                  "Returns the XCF file for the specified image.",
                                  "This procedure returns the XCF file associated with the image. If there is no such file, this procedure returns %NULL.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Eric Grivel <pika@lumenssolutions.com>",
                                         "Eric Grivel",
                                         "2011");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_object ("file",
                                                        "file",
                                                        "The imported XCF file.",
                                                        G_TYPE_FILE,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-imported-file
   */
  procedure = pika_procedure_new (image_get_imported_file_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-imported-file");
  pika_procedure_set_static_help (procedure,
                                  "Returns the imported file for the specified image.",
                                  "This procedure returns the file associated with the specified image if the image was imported from a non-native Pika format. If the image was not imported, or has since been saved in the native Gimp format, this procedure returns %NULL.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Eric Grivel <pika@lumenssolutions.com>",
                                         "Eric Grivel",
                                         "2011");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_object ("file",
                                                        "file",
                                                        "The imported file.",
                                                        G_TYPE_FILE,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-exported-file
   */
  procedure = pika_procedure_new (image_get_exported_file_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-exported-file");
  pika_procedure_set_static_help (procedure,
                                  "Returns the exported file for the specified image.",
                                  "This procedure returns the file associated with the specified image if the image was exported a non-native PIKA format. If the image was not exported, this procedure returns %NULL.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Eric Grivel <pika@lumenssolutions.com>",
                                         "Eric Grivel",
                                         "2011");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_object ("file",
                                                        "file",
                                                        "The exported file.",
                                                        G_TYPE_FILE,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-name
   */
  procedure = pika_procedure_new (image_get_name_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-name");
  pika_procedure_set_static_help (procedure,
                                  "Returns the specified image's name.",
                                  "This procedure returns the image's name. If the image has a filename or an URI, then the returned name contains the filename's or URI's base name (the last component of the path). Otherwise it is the translated string \"Untitled\". The returned name is formatted like the image name in the image window title, it may contain '[]', '(imported)' etc. and should only be used to label user interface elements. Never use it to construct filenames.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_string ("name",
                                                           "name",
                                                           "The name.",
                                                           FALSE, FALSE, FALSE,
                                                           NULL,
                                                           PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-resolution
   */
  procedure = pika_procedure_new (image_get_resolution_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-resolution");
  pika_procedure_set_static_help (procedure,
                                  "Returns the specified image's resolution.",
                                  "This procedure returns the specified image's resolution in dots per inch. This value is independent of any of the layers in this image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Austin Donnelly",
                                         "Austin Donnelly",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("xresolution",
                                                        "xresolution",
                                                        "The resolution in the x-axis, in dots per inch",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("yresolution",
                                                        "yresolution",
                                                        "The resolution in the y-axis, in dots per inch",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-resolution
   */
  procedure = pika_procedure_new (image_set_resolution_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-resolution");
  pika_procedure_set_static_help (procedure,
                                  "Sets the specified image's resolution.",
                                  "This procedure sets the specified image's resolution in dots per inch. This value is independent of any of the layers in this image. No scaling or resizing is performed.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Austin Donnelly",
                                         "Austin Donnelly",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("xresolution",
                                                    "xresolution",
                                                    "The new image resolution in the x-axis, in dots per inch",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("yresolution",
                                                    "yresolution",
                                                    "The new image resolution in the y-axis, in dots per inch",
                                                    -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                    PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-unit
   */
  procedure = pika_procedure_new (image_get_unit_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-unit");
  pika_procedure_set_static_help (procedure,
                                  "Returns the specified image's unit.",
                                  "This procedure returns the specified image's unit. This value is independent of any of the layers in this image. See the pika_unit_*() procedure definitions for the valid range of unit IDs and a description of the unit system.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_unit ("unit",
                                                         "unit",
                                                         "The unit",
                                                         TRUE,
                                                         FALSE,
                                                         PIKA_UNIT_PIXEL,
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-unit
   */
  procedure = pika_procedure_new (image_set_unit_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-unit");
  pika_procedure_set_static_help (procedure,
                                  "Sets the specified image's unit.",
                                  "This procedure sets the specified image's unit. No scaling or resizing is performed. This value is independent of any of the layers in this image. See the pika_unit_*() procedure definitions for the valid range of unit IDs and a description of the unit system.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_unit ("unit",
                                                     "unit",
                                                     "The new image unit",
                                                     FALSE,
                                                     FALSE,
                                                     PIKA_UNIT_INCH,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-tattoo-state
   */
  procedure = pika_procedure_new (image_get_tattoo_state_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-tattoo-state");
  pika_procedure_set_static_help (procedure,
                                  "Returns the tattoo state associated with the image.",
                                  "This procedure returns the tattoo state of the image. Use only by save/load plug-ins that wish to preserve an images tattoo state. Using this function at other times will produce unexpected results.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Andy Thomas",
                                         "Andy Thomas",
                                         "2000");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_uint ("tattoo-state",
                                                      "tattoo state",
                                                      "The tattoo state",
                                                      1, G_MAXUINT32, 1,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-set-tattoo-state
   */
  procedure = pika_procedure_new (image_set_tattoo_state_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-set-tattoo-state");
  pika_procedure_set_static_help (procedure,
                                  "Set the tattoo state associated with the image.",
                                  "This procedure sets the tattoo state of the image. Use only by save/load plug-ins that wish to preserve an images tattoo state. Using this function at other times will produce unexpected results. A full check of uniqueness of states in layers, channels and paths will be performed by this procedure and a execution failure will be returned if this fails. A failure will also be returned if the new tattoo state value is less than the maximum tattoo value from all of the tattoos from the paths, layers and channels. After the image data has been loaded and all the tattoos have been set then this is the last procedure that should be called. If effectively does a status check on the tattoo values that have been set to make sure that all is OK.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Andy Thomas",
                                         "Andy Thomas",
                                         "2000");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_uint ("tattoo-state",
                                                  "tattoo state",
                                                  "The new image tattoo state",
                                                  1, G_MAXUINT32, 1,
                                                  PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-layer-by-tattoo
   */
  procedure = pika_procedure_new (image_get_layer_by_tattoo_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-layer-by-tattoo");
  pika_procedure_set_static_help (procedure,
                                  "Find a layer with a given tattoo in an image.",
                                  "This procedure returns the layer with the given tattoo in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jay Cox",
                                         "Jay Cox",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_uint ("tattoo",
                                                  "tattoo",
                                                  "The tattoo of the layer to find",
                                                  1, G_MAXUINT32, 1,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("layer",
                                                          "layer",
                                                          "The layer with the specified tattoo",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-channel-by-tattoo
   */
  procedure = pika_procedure_new (image_get_channel_by_tattoo_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-channel-by-tattoo");
  pika_procedure_set_static_help (procedure,
                                  "Find a channel with a given tattoo in an image.",
                                  "This procedure returns the channel with the given tattoo in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jay Cox",
                                         "Jay Cox",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_uint ("tattoo",
                                                  "tattoo",
                                                  "The tattoo of the channel to find",
                                                  1, G_MAXUINT32, 1,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_channel ("channel",
                                                            "channel",
                                                            "The channel with the specified tattoo",
                                                            FALSE,
                                                            PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-vectors-by-tattoo
   */
  procedure = pika_procedure_new (image_get_vectors_by_tattoo_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-vectors-by-tattoo");
  pika_procedure_set_static_help (procedure,
                                  "Find a vectors with a given tattoo in an image.",
                                  "This procedure returns the vectors with the given tattoo in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Simon Budig",
                                         "Simon Budig",
                                         "2005");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_uint ("tattoo",
                                                  "tattoo",
                                                  "The tattoo of the vectors to find",
                                                  1, G_MAXUINT32, 1,
                                                  PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_vectors ("vectors",
                                                            "vectors",
                                                            "The vectors with the specified tattoo",
                                                            FALSE,
                                                            PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-layer-by-name
   */
  procedure = pika_procedure_new (image_get_layer_by_name_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-layer-by-name");
  pika_procedure_set_static_help (procedure,
                                  "Find a layer with a given name in an image.",
                                  "This procedure returns the layer with the given name in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2011");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("name",
                                                       "name",
                                                       "The name of the layer to find",
                                                       FALSE, FALSE, TRUE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("layer",
                                                          "layer",
                                                          "The layer with the specified name",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-channel-by-name
   */
  procedure = pika_procedure_new (image_get_channel_by_name_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-channel-by-name");
  pika_procedure_set_static_help (procedure,
                                  "Find a channel with a given name in an image.",
                                  "This procedure returns the channel with the given name in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2011");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("name",
                                                       "name",
                                                       "The name of the channel to find",
                                                       FALSE, FALSE, TRUE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_channel ("channel",
                                                            "channel",
                                                            "The channel with the specified name",
                                                            FALSE,
                                                            PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-vectors-by-name
   */
  procedure = pika_procedure_new (image_get_vectors_by_name_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-vectors-by-name");
  pika_procedure_set_static_help (procedure,
                                  "Find a vectors with a given name in an image.",
                                  "This procedure returns the vectors with the given name in the specified image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2011");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("name",
                                                       "name",
                                                       "The name of the vectors to find",
                                                       FALSE, FALSE, TRUE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_vectors ("vectors",
                                                            "vectors",
                                                            "The vectors with the specified name",
                                                            FALSE,
                                                            PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-attach-parasite
   */
  procedure = pika_procedure_new (image_attach_parasite_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-attach-parasite");
  pika_procedure_set_static_help (procedure,
                                  "Add a parasite to an image.",
                                  "This procedure attaches a parasite to an image. It has no return values.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jay Cox",
                                         "Jay Cox",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_parasite ("parasite",
                                                         "parasite",
                                                         "The parasite to attach to an image",
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-detach-parasite
   */
  procedure = pika_procedure_new (image_detach_parasite_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-detach-parasite");
  pika_procedure_set_static_help (procedure,
                                  "Removes a parasite from an image.",
                                  "This procedure detaches a parasite from an image. It has no return values.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jay Cox",
                                         "Jay Cox",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("name",
                                                       "name",
                                                       "The name of the parasite to detach from an image.",
                                                       FALSE, FALSE, FALSE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-parasite
   */
  procedure = pika_procedure_new (image_get_parasite_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-parasite");
  pika_procedure_set_static_help (procedure,
                                  "Look up a parasite in an image",
                                  "Finds and returns the parasite that was previously attached to an image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jay Cox",
                                         "Jay Cox",
                                         "1998");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("name",
                                                       "name",
                                                       "The name of the parasite to find",
                                                       FALSE, FALSE, FALSE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_parasite ("parasite",
                                                             "parasite",
                                                             "The found parasite",
                                                             PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-get-parasite-list
   */
  procedure = pika_procedure_new (image_get_parasite_list_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-get-parasite-list");
  pika_procedure_set_static_help (procedure,
                                  "List all parasites.",
                                  "Returns a list of the names of all currently attached parasites. These names can later be used to get the actual #PikaParasite with 'pika-image-get-parasite' when needed.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Marc Lehmann",
                                         "Marc Lehmann",
                                         "1999");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boxed ("parasites",
                                                       "parasites",
                                                       "The names of currently attached parasites",
                                                       G_TYPE_STRV,
                                                       PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-policy-rotate
   */
  procedure = pika_procedure_new (image_policy_rotate_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-policy-rotate");
  pika_procedure_set_static_help (procedure,
                                  "Execute the \"Orientation\" metadata policy.",
                                  "Process the image according to the rotation policy as set in Preferences. If PIKA is running as a GUI and interactive is TRUE, a dialog may be presented to the user depending on the set policy. Otherwise, if the policy does not mandate the action to perform, the image will be rotated following the Orientation metadata.\n"
                                  "If you wish absolutely to rotate a loaded image following the Orientation metadata, do not use this function and process the metadata yourself. Indeed even with `interactive` to FALSE, user settings may leave the image unrotated.\n"
                                  "Finally it is unnecessary to call this function in a format load procedure because this is called automatically by the core code when loading any image. You should only call this function explicitly when loading an image through a PDB call.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2020");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interactive",
                                                     "interactive",
                                                     "Querying the user through a dialog is a possibility",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-image-policy-color-profile
   */
  procedure = pika_procedure_new (image_policy_color_profile_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-image-policy-color-profile");
  pika_procedure_set_static_help (procedure,
                                  "Execute the color profile conversion policy.",
                                  "Process the image according to the color profile policy as set in Preferences.\n"
                                  "If PIKA is running as a GUI and interactive is TRUE, a dialog may be presented to the user depending on the policy. Otherwise, if the policy does not mandate the conversion to perform, the conversion to the preferred RGB or grayscale profile will happen, defaulting to built-in profiles if no preferred profiles were set in `Preferences`.\n"
                                  "This function should be used only if you want to follow user settings. If you intend to convert to a specific profile, call preferably 'pika-image-convert-color-profile'. And if you wish to leave whatever profile an image has, do not call any of these functions.\n"
                                  "Finally it is unnecessary to call this function in a format load procedure because this is called automatically by the core code when loading any image. You should only call this function explicitly when loading an image through a PDB call.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Jehan",
                                         "Jehan",
                                         "2020");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("interactive",
                                                     "interactive",
                                                     "Querying the user through a dialog is a possibility",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);
}
