/* The GIMP -- an image manipulation program
 * Copyright (C) 1995-1999 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 2 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/* NOTE: This file is autogenerated by pdbgen.pl. */

#include "procedural_db.h"

#include <string.h>

#include "apptypes.h"
#include "channel.h"
#include "cursorutil.h"
#include "drawable.h"
#include "gdisplay.h"
#include "gimage.h"
#include "gimpimage.h"
#include "layer.h"
#include "layer_pvt.h"

#include "libgimp/gimplimits.h"

static ProcRecord image_list_proc;
static ProcRecord image_new_proc;
static ProcRecord image_resize_proc;
static ProcRecord image_scale_proc;
static ProcRecord image_delete_proc;
static ProcRecord image_free_shadow_proc;
static ProcRecord image_get_layers_proc;
static ProcRecord image_get_channels_proc;
static ProcRecord image_unset_active_channel_proc;
static ProcRecord image_pick_correlate_layer_proc;
static ProcRecord image_raise_layer_proc;
static ProcRecord image_lower_layer_proc;
static ProcRecord image_raise_layer_to_top_proc;
static ProcRecord image_lower_layer_to_bottom_proc;
static ProcRecord image_merge_visible_layers_proc;
static ProcRecord image_merge_down_proc;
static ProcRecord image_flatten_proc;
static ProcRecord image_add_layer_proc;
static ProcRecord image_remove_layer_proc;
static ProcRecord image_add_layer_mask_proc;
static ProcRecord image_remove_layer_mask_proc;
static ProcRecord image_raise_channel_proc;
static ProcRecord image_lower_channel_proc;
static ProcRecord image_add_channel_proc;
static ProcRecord image_remove_channel_proc;
static ProcRecord image_active_drawable_proc;
static ProcRecord image_base_type_proc;
static ProcRecord image_get_cmap_proc;
static ProcRecord image_set_cmap_proc;
static ProcRecord image_undo_is_enabled_proc;
static ProcRecord image_undo_enable_proc;
static ProcRecord image_undo_disable_proc;
static ProcRecord image_undo_freeze_proc;
static ProcRecord image_undo_thaw_proc;
static ProcRecord image_clean_all_proc;
static ProcRecord image_floating_selection_proc;
static ProcRecord image_floating_sel_attached_to_proc;
static ProcRecord image_thumbnail_proc;
static ProcRecord image_width_proc;
static ProcRecord image_height_proc;
static ProcRecord image_get_active_layer_proc;
static ProcRecord image_set_active_layer_proc;
static ProcRecord image_get_active_channel_proc;
static ProcRecord image_set_active_channel_proc;
static ProcRecord image_get_selection_proc;
static ProcRecord image_get_component_active_proc;
static ProcRecord image_set_component_active_proc;
static ProcRecord image_get_component_visible_proc;
static ProcRecord image_set_component_visible_proc;
static ProcRecord image_get_filename_proc;
static ProcRecord image_set_filename_proc;
static ProcRecord image_get_resolution_proc;
static ProcRecord image_set_resolution_proc;
static ProcRecord image_get_unit_proc;
static ProcRecord image_set_unit_proc;
static ProcRecord image_get_layer_by_tattoo_proc;
static ProcRecord image_get_channel_by_tattoo_proc;

void
register_gimage_procs (void)
{
  procedural_db_register (&image_list_proc);
  procedural_db_register (&image_new_proc);
  procedural_db_register (&image_resize_proc);
  procedural_db_register (&image_scale_proc);
  procedural_db_register (&image_delete_proc);
  procedural_db_register (&image_free_shadow_proc);
  procedural_db_register (&image_get_layers_proc);
  procedural_db_register (&image_get_channels_proc);
  procedural_db_register (&image_unset_active_channel_proc);
  procedural_db_register (&image_pick_correlate_layer_proc);
  procedural_db_register (&image_raise_layer_proc);
  procedural_db_register (&image_lower_layer_proc);
  procedural_db_register (&image_raise_layer_to_top_proc);
  procedural_db_register (&image_lower_layer_to_bottom_proc);
  procedural_db_register (&image_merge_visible_layers_proc);
  procedural_db_register (&image_merge_down_proc);
  procedural_db_register (&image_flatten_proc);
  procedural_db_register (&image_add_layer_proc);
  procedural_db_register (&image_remove_layer_proc);
  procedural_db_register (&image_add_layer_mask_proc);
  procedural_db_register (&image_remove_layer_mask_proc);
  procedural_db_register (&image_raise_channel_proc);
  procedural_db_register (&image_lower_channel_proc);
  procedural_db_register (&image_add_channel_proc);
  procedural_db_register (&image_remove_channel_proc);
  procedural_db_register (&image_active_drawable_proc);
  procedural_db_register (&image_base_type_proc);
  procedural_db_register (&image_get_cmap_proc);
  procedural_db_register (&image_set_cmap_proc);
  procedural_db_register (&image_undo_is_enabled_proc);
  procedural_db_register (&image_undo_enable_proc);
  procedural_db_register (&image_undo_disable_proc);
  procedural_db_register (&image_undo_freeze_proc);
  procedural_db_register (&image_undo_thaw_proc);
  procedural_db_register (&image_clean_all_proc);
  procedural_db_register (&image_floating_selection_proc);
  procedural_db_register (&image_floating_sel_attached_to_proc);
  procedural_db_register (&image_thumbnail_proc);
  procedural_db_register (&image_width_proc);
  procedural_db_register (&image_height_proc);
  procedural_db_register (&image_get_active_layer_proc);
  procedural_db_register (&image_set_active_layer_proc);
  procedural_db_register (&image_get_active_channel_proc);
  procedural_db_register (&image_set_active_channel_proc);
  procedural_db_register (&image_get_selection_proc);
  procedural_db_register (&image_get_component_active_proc);
  procedural_db_register (&image_set_component_active_proc);
  procedural_db_register (&image_get_component_visible_proc);
  procedural_db_register (&image_set_component_visible_proc);
  procedural_db_register (&image_get_filename_proc);
  procedural_db_register (&image_set_filename_proc);
  procedural_db_register (&image_get_resolution_proc);
  procedural_db_register (&image_set_resolution_proc);
  procedural_db_register (&image_get_unit_proc);
  procedural_db_register (&image_set_unit_proc);
  procedural_db_register (&image_get_layer_by_tattoo_proc);
  procedural_db_register (&image_get_channel_by_tattoo_proc);
}

/* Yuup, this is somewhat unsmooth, to say the least */

static void
gimlist_cb (gpointer im,
	    gpointer data)
{
  GSList **l = (GSList **) data;
  *l = g_slist_prepend (*l, im);
}

static Argument *
image_list_invoker (Argument *args)
{
  Argument *return_args;
  gint32 num_images = 0;
  gint32 *image_ids = NULL;
  GSList *list = NULL;
  int i;

  gimage_foreach (gimlist_cb, &list);
  num_images = g_slist_length (list);

  if (num_images)
    {
      image_ids = g_new (gint32, num_images);
      for (i = 0; i < num_images; i++, list = list->next)
	image_ids[i] = pdb_image_to_id (GIMP_IMAGE (list->data));
    }

  return_args = procedural_db_return_args (&image_list_proc, TRUE);

  return_args[1].value.pdb_int = num_images;
  return_args[2].value.pdb_pointer = image_ids;

  return return_args;
}

static ProcArg image_list_outargs[] =
{
  {
    PDB_INT32,
    "num_images",
    "The number of images currently open"
  },
  {
    PDB_INT32ARRAY,
    "image_ids",
    "The list of images currently open"
  }
};

static ProcRecord image_list_proc =
{
  "gimp_image_list",
  "Returns the list of images currently open.",
  "This procedure returns the list of images currently open in the GIMP.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  0,
  NULL,
  2,
  image_list_outargs,
  { { image_list_invoker } }
};

static Argument *
image_new_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  gint32 width;
  gint32 height;
  gint32 type;
  GimpImage *gimage = NULL;

  width = args[0].value.pdb_int;
  if (width <= 0)
    success = FALSE;

  height = args[1].value.pdb_int;
  if (height <= 0)
    success = FALSE;

  type = args[2].value.pdb_int;
  if (type < RGB || type > INDEXED)
    success = FALSE;

  if (success)
    success = (gimage = gimage_new (width, height, type)) != NULL;

  return_args = procedural_db_return_args (&image_new_proc, success);

  if (success)
    return_args[1].value.pdb_int = pdb_image_to_id (gimage);

  return return_args;
}

static ProcArg image_new_inargs[] =
{
  {
    PDB_INT32,
    "width",
    "The width of the image"
  },
  {
    PDB_INT32,
    "height",
    "The height of the image"
  },
  {
    PDB_INT32,
    "type",
    "The type of image: { RGB (0), GRAY (1), INDEXED (2) }"
  }
};

static ProcArg image_new_outargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The ID of the newly created image"
  }
};

static ProcRecord image_new_proc =
{
  "gimp_image_new",
  "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 'gimp_display_new' with this image as an argument will fail. Layers can be created using the 'gimp_layer_new' commands. They can be added to an image using the 'gimp_image_add_layer' command.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_new_inargs,
  1,
  image_new_outargs,
  { { image_new_invoker } }
};

static Argument *
image_resize_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  gint32 new_width;
  gint32 new_height;
  gint32 offx;
  gint32 offy;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  new_width = args[1].value.pdb_int;
  if (new_width <= 0)
    success = FALSE;

  new_height = args[2].value.pdb_int;
  if (new_height <= 0)
    success = FALSE;

  offx = args[3].value.pdb_int;

  offy = args[4].value.pdb_int;

  if (success)
    {
      gimp_add_busy_cursors_until_idle ();
      gimage_resize (gimage, new_width, new_height, offx, offy);
    }

  return procedural_db_return_args (&image_resize_proc, success);
}

static ProcArg image_resize_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "new_width",
    "New image width: 0 < new_width"
  },
  {
    PDB_INT32,
    "new_height",
    "New image height: 0 < new_height"
  },
  {
    PDB_INT32,
    "offx",
    "x offset between upper left corner of old and new images: (new - old)"
  },
  {
    PDB_INT32,
    "offy",
    "y offset between upper left corner of old and new images: (new - old)"
  }
};

static ProcRecord image_resize_proc =
{
  "gimp_image_resize",
  "Resize the image to the specified extents.",
  "This procedure resizes the image so that it's new width and height are equal to the supplied parameters. Offsets are also provided which describe the position of the previous image's content. No bounds checking is currently provided, so don't supply parameters that are out of bounds. All channels within the image are resized according to the specified parameters; this includes the image selection mask. All layers within the image are repositioned according to the specified offsets.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  5,
  image_resize_inargs,
  0,
  NULL,
  { { image_resize_invoker } }
};

static Argument *
image_scale_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  gint32 new_width;
  gint32 new_height;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  new_width = args[1].value.pdb_int;
  if (new_width <= 0)
    success = FALSE;

  new_height = args[2].value.pdb_int;
  if (new_height <= 0)
    success = FALSE;

  if (success)
    {
      gimp_add_busy_cursors_until_idle ();
      gimage_scale (gimage, new_width, new_height);
    }

  return procedural_db_return_args (&image_scale_proc, success);
}

static ProcArg image_scale_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "new_width",
    "New image width: 0 < new_width"
  },
  {
    PDB_INT32,
    "new_height",
    "New image height: 0 < new_height"
  }
};

static ProcRecord image_scale_proc =
{
  "gimp_image_scale",
  "Scale the image to the specified extents.",
  "This procedure scales the image so that it's new width and height are equal to the supplied parameters. Offsets are also provided which describe the position of the previous image's content. No bounds checking is currently provided, so don't supply parameters that are out of bounds. All channels within the image are scaled according to the specified parameters; this includes the image selection mask. All layers within the image are repositioned according to the specified offsets.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_scale_inargs,
  0,
  NULL,
  { { image_scale_invoker } }
};

static Argument *
image_delete_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    gimage_delete (gimage);

  return procedural_db_return_args (&image_delete_proc, success);
}

static ProcArg image_delete_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcRecord image_delete_proc =
{
  "gimp_image_delete",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_delete_inargs,
  0,
  NULL,
  { { image_delete_invoker } }
};

static Argument *
image_free_shadow_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    gimage_free_shadow (gimage);

  return procedural_db_return_args (&image_free_shadow_proc, success);
}

static ProcArg image_free_shadow_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcRecord image_free_shadow_proc =
{
  "gimp_image_free_shadow",
  "Free the specified image's shadow data (if it exists).",
  "This procedure is intended as a memory saving device. If any shadow memory has been allocated, it will be freed automatically on a call to 'gimp_image_delete'.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_free_shadow_inargs,
  0,
  NULL,
  { { image_free_shadow_invoker } }
};

static Argument *
image_get_layers_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 num_layers = 0;
  gint32 *layer_ids = NULL;
  GSList *list = NULL;
  int i;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    {
      list = gimage->layers;
      num_layers = g_slist_length (list);
    
      if (num_layers)
	{
	  layer_ids = g_new (gint32, num_layers);
	  for (i = 0; i < num_layers; i++, list = list->next)
	    layer_ids[i] = drawable_ID (GIMP_DRAWABLE (list->data));
	}
    }

  return_args = procedural_db_return_args (&image_get_layers_proc, success);

  if (success)
    {
      return_args[1].value.pdb_int = num_layers;
      return_args[2].value.pdb_pointer = layer_ids;
    }

  return return_args;
}

static ProcArg image_get_layers_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_layers_outargs[] =
{
  {
    PDB_INT32,
    "num_layers",
    "The number of layers contained in the image"
  },
  {
    PDB_INT32ARRAY,
    "layer_ids",
    "The list of layers contained in the image"
  }
};

static ProcRecord image_get_layers_proc =
{
  "gimp_image_get_layers",
  "Returns the list of layers contained in the specified image.",
  "This procedure returns the list of layers contained in the specified image. The order of layers is from topmost to bottommost.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_get_layers_inargs,
  2,
  image_get_layers_outargs,
  { { image_get_layers_invoker } }
};

static Argument *
image_get_channels_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 num_channels = 0;
  gint32 *channel_ids = NULL;
  GSList *list = NULL;
  int i;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    {
      list = gimage->channels;
      num_channels = g_slist_length (list);
    
      if (num_channels)
	{
	  channel_ids = g_new (gint32, num_channels);
	  for (i = 0; i < num_channels; i++, list = list->next)
	    channel_ids[i] = drawable_ID (GIMP_DRAWABLE (list->data));
	}
    }

  return_args = procedural_db_return_args (&image_get_channels_proc, success);

  if (success)
    {
      return_args[1].value.pdb_int = num_channels;
      return_args[2].value.pdb_pointer = channel_ids;
    }

  return return_args;
}

static ProcArg image_get_channels_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_channels_outargs[] =
{
  {
    PDB_INT32,
    "num_channels",
    "The number of channels contained in the image"
  },
  {
    PDB_INT32ARRAY,
    "channel_ids",
    "The list of channels contained in the image"
  }
};

static ProcRecord image_get_channels_proc =
{
  "gimp_image_get_channels",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_get_channels_inargs,
  2,
  image_get_channels_outargs,
  { { image_get_channels_invoker } }
};

static Argument *
image_unset_active_channel_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    gimage_unset_active_channel (gimage);

  return procedural_db_return_args (&image_unset_active_channel_proc, success);
}

static ProcArg image_unset_active_channel_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcRecord image_unset_active_channel_proc =
{
  "gimp_image_unset_active_channel",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_unset_active_channel_inargs,
  0,
  NULL,
  { { image_unset_active_channel_invoker } }
};

static Argument *
image_pick_correlate_layer_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 x;
  gint32 y;
  GimpLayer *layer = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  x = args[1].value.pdb_int;

  y = args[2].value.pdb_int;

  if (success)
    layer = gimage_pick_correlate_layer (gimage, x, y);

  return_args = procedural_db_return_args (&image_pick_correlate_layer_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (layer));

  return return_args;
}

static ProcArg image_pick_correlate_layer_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "x",
    "The x coordinate for the pick"
  },
  {
    PDB_INT32,
    "y",
    "The y coordinate for the pick"
  }
};

static ProcArg image_pick_correlate_layer_outargs[] =
{
  {
    PDB_LAYER,
    "layer",
    "The layer found at the specified coordinates"
  }
};

static ProcRecord image_pick_correlate_layer_proc =
{
  "gimp_image_pick_correlate_layer",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_pick_correlate_layer_inargs,
  1,
  image_pick_correlate_layer_outargs,
  { { image_pick_correlate_layer_invoker } }
};

static Argument *
image_raise_layer_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  if (success)
    success = gimage_raise_layer (gimage, layer) != NULL;

  return procedural_db_return_args (&image_raise_layer_proc, success);
}

static ProcArg image_raise_layer_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer to raise"
  }
};

static ProcRecord image_raise_layer_proc =
{
  "gimp_image_raise_layer",
  "Raise the specified layer in the image's layer stack",
  "This procedure raises the specified layer one step in the existing layer stack. It will not move the layer if there is no layer above it, or the layer has no alpha channel.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_raise_layer_inargs,
  0,
  NULL,
  { { image_raise_layer_invoker } }
};

static Argument *
image_lower_layer_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  if (success)
    success = gimage_lower_layer (gimage, layer) != NULL;

  return procedural_db_return_args (&image_lower_layer_proc, success);
}

static ProcArg image_lower_layer_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer to lower"
  }
};

static ProcRecord image_lower_layer_proc =
{
  "gimp_image_lower_layer",
  "Lower the specified layer in the image's layer stack",
  "This procedure lowers the specified layer one step in the existing layer stack. It will not move the layer if there is no layer below it, or the layer has no alpha channel.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_lower_layer_inargs,
  0,
  NULL,
  { { image_lower_layer_invoker } }
};

static Argument *
image_raise_layer_to_top_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  if (success)
    success = gimage_raise_layer_to_top (gimage, layer) != NULL;

  return procedural_db_return_args (&image_raise_layer_to_top_proc, success);
}

static ProcArg image_raise_layer_to_top_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer to raise to top"
  }
};

static ProcRecord image_raise_layer_to_top_proc =
{
  "gimp_image_raise_layer_to_top",
  "Raise the specified layer in the image's layer stack to top of stack",
  "This procedure raises the specified layer to top of the existing layer stack. It will not move the layer if there is no layer above it, or the layer has no alpha channel.",
  "Wolfgang Hofer, Sven Neumann",
  "Wolfgang Hofer",
  "1998",
  PDB_INTERNAL,
  2,
  image_raise_layer_to_top_inargs,
  0,
  NULL,
  { { image_raise_layer_to_top_invoker } }
};

static Argument *
image_lower_layer_to_bottom_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  if (success)
    success = gimage_lower_layer_to_bottom (gimage, layer) != NULL;

  return procedural_db_return_args (&image_lower_layer_to_bottom_proc, success);
}

static ProcArg image_lower_layer_to_bottom_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer to lower to bottom"
  }
};

static ProcRecord image_lower_layer_to_bottom_proc =
{
  "gimp_image_lower_layer_to_bottom",
  "Lower the specified layer in the image's layer stack to bottom of stack",
  "This procedure lowers the specified layer to bottom of the existing layer stack. It will not move the layer if there is no layer below it, or the layer has no alpha channel.",
  "Wolfgang Hofer, Sven Neumann",
  "Wolfgang Hofer",
  "1998",
  PDB_INTERNAL,
  2,
  image_lower_layer_to_bottom_inargs,
  0,
  NULL,
  { { image_lower_layer_to_bottom_invoker } }
};

static Argument *
image_merge_visible_layers_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 merge_type;
  GimpLayer *layer = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  merge_type = args[1].value.pdb_int;
  if (merge_type < EXPAND_AS_NECESSARY || merge_type > CLIP_TO_BOTTOM_LAYER)
    success = FALSE;

  if (success)
    {
      layer = gimage_merge_visible_layers (gimage, merge_type);
      success = layer != NULL;
    }

  return_args = procedural_db_return_args (&image_merge_visible_layers_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (layer));

  return return_args;
}

static ProcArg image_merge_visible_layers_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "merge_type",
    "The type of merge: { EXPAND_AS_NECESSARY (0), CLIP_TO_IMAGE (1), CLIP_TO_BOTTOM_LAYER (2) }"
  }
};

static ProcArg image_merge_visible_layers_outargs[] =
{
  {
    PDB_LAYER,
    "layer",
    "The resulting layer"
  }
};

static ProcRecord image_merge_visible_layers_proc =
{
  "gimp_image_merge_visible_layers",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_merge_visible_layers_inargs,
  1,
  image_merge_visible_layers_outargs,
  { { image_merge_visible_layers_invoker } }
};

static Argument *
image_merge_down_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  GimpLayer *merge_layer;
  gint32 merge_type;
  GimpLayer *layer = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  merge_layer = layer_get_ID (args[1].value.pdb_int);
  if (merge_layer == NULL)
    success = FALSE;

  merge_type = args[2].value.pdb_int;
  if (merge_type < EXPAND_AS_NECESSARY || merge_type > CLIP_TO_BOTTOM_LAYER)
    success = FALSE;

  if (success)
    {
      layer = gimp_image_merge_down (gimage, merge_layer, merge_type);
      success = layer != NULL;
    }

  return_args = procedural_db_return_args (&image_merge_down_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (layer));

  return return_args;
}

static ProcArg image_merge_down_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "merge_layer",
    "The layer to merge down from"
  },
  {
    PDB_INT32,
    "merge_type",
    "The type of merge: { EXPAND_AS_NECESSARY (0), CLIP_TO_IMAGE (1), CLIP_TO_BOTTOM_LAYER (2) }"
  }
};

static ProcArg image_merge_down_outargs[] =
{
  {
    PDB_LAYER,
    "layer",
    "The resulting layer"
  }
};

static ProcRecord image_merge_down_proc =
{
  "gimp_image_merge_down",
  "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.",
  "Larry Ewing",
  "Larry Ewing",
  "1998",
  PDB_INTERNAL,
  3,
  image_merge_down_inargs,
  1,
  image_merge_down_outargs,
  { { image_merge_down_invoker } }
};

static Argument *
image_flatten_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  GimpLayer *layer = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    success = (layer = gimage_flatten (gimage)) != NULL;

  return_args = procedural_db_return_args (&image_flatten_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (layer));

  return return_args;
}

static ProcArg image_flatten_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_flatten_outargs[] =
{
  {
    PDB_LAYER,
    "layer",
    "The resulting layer"
  }
};

static ProcRecord image_flatten_proc =
{
  "gimp_image_flatten",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_flatten_inargs,
  1,
  image_flatten_outargs,
  { { image_flatten_invoker } }
};

static Argument *
image_add_layer_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;
  gint32 position;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  position = args[2].value.pdb_int;

  if (success)
    {
      if ((drawable_color (GIMP_DRAWABLE (layer)) && gimage_base_type (gimage) != RGB) ||
	  (drawable_gray (GIMP_DRAWABLE (layer)) && gimage_base_type (gimage) != GRAY) ||
	  (drawable_indexed (GIMP_DRAWABLE (layer)) && gimage_base_type (gimage) != INDEXED))
	success = FALSE;
      else
	success = gimage_add_layer (gimage, layer, MAX (position, -1)) != NULL;
    }

  return procedural_db_return_args (&image_add_layer_proc, success);
}

static ProcArg image_add_layer_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer"
  },
  {
    PDB_INT32,
    "position",
    "The layer position"
  }
};

static ProcRecord image_add_layer_proc =
{
  "gimp_image_add_layer",
  "Add the specified layer to the image.",
  "This procedure adds the specified layer to the gimage at the given position. If the position is specified as -1, then the layer is inserted at the top of the layer stack. If the layer to be added has no alpha channel, it must be added at position 0. The layer type must be compatible with the image base type.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_add_layer_inargs,
  0,
  NULL,
  { { image_add_layer_invoker } }
};

static Argument *
image_remove_layer_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  if (success)
    gimage_remove_layer (gimage, layer);

  return procedural_db_return_args (&image_remove_layer_proc, success);
}

static ProcArg image_remove_layer_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer"
  }
};

static ProcRecord image_remove_layer_proc =
{
  "gimp_image_remove_layer",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_remove_layer_inargs,
  0,
  NULL,
  { { image_remove_layer_invoker } }
};

static Argument *
image_add_layer_mask_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;
  LayerMask *mask;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  mask = layer_mask_get_ID (args[2].value.pdb_int);
  if (mask == NULL)
    success = FALSE;

  if (success)
    success = gimage_add_layer_mask (gimage, layer, mask) != NULL;

  return procedural_db_return_args (&image_add_layer_mask_proc, success);
}

static ProcArg image_add_layer_mask_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer to receive the mask"
  },
  {
    PDB_CHANNEL,
    "mask",
    "The mask to add to the layer"
  }
};

static ProcRecord image_add_layer_mask_proc =
{
  "gimp_image_add_layer_mask",
  "Add a layer mask to the specified layer.",
  "This procedure adds a layer mask to the specified layer. Layer masks serve as an additional alpha channel for a layer. This procedure will fail if a number of prerequisites aren't met. The layer cannot already have a layer mask. The specified mask must exist and have the same dimensions as the layer. Both the mask and the layer must have been created for use with the specified image.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_add_layer_mask_inargs,
  0,
  NULL,
  { { image_add_layer_mask_invoker } }
};

static Argument *
image_remove_layer_mask_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;
  gint32 mode;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  mode = args[2].value.pdb_int;
  if (mode < APPLY || mode > DISCARD)
    success = FALSE;

  if (success)
    gimage_remove_layer_mask (gimage, layer, mode);

  return procedural_db_return_args (&image_remove_layer_mask_proc, success);
}

static ProcArg image_remove_layer_mask_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer from which to remove mask"
  },
  {
    PDB_INT32,
    "mode",
    "Removal mode: { APPLY (0), DISCARD (1) }"
  }
};

static ProcRecord image_remove_layer_mask_proc =
{
  "gimp_image_remove_layer_mask",
  "Remove the specified layer mask from the layer.",
  "This procedure removes the specified layer mask from the layer. If the mask doesn't exist, an error is returned.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_remove_layer_mask_inargs,
  0,
  NULL,
  { { image_remove_layer_mask_invoker } }
};

static Argument *
image_raise_channel_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  Channel *channel;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  channel = channel_get_ID (args[1].value.pdb_int);
  if (channel == NULL)
    success = FALSE;

  if (success)
    success = gimage_raise_channel (gimage, channel) != NULL;

  return procedural_db_return_args (&image_raise_channel_proc, success);
}

static ProcArg image_raise_channel_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_CHANNEL,
    "channel",
    "The channel to raise"
  }
};

static ProcRecord image_raise_channel_proc =
{
  "gimp_image_raise_channel",
  "Raise the specified channel in the image's channel stack",
  "This procedure raises the specified channel one step in the existing channel stack. It will not move the channel if there is no channel above it.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_raise_channel_inargs,
  0,
  NULL,
  { { image_raise_channel_invoker } }
};

static Argument *
image_lower_channel_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *layer;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  layer = layer_get_ID (args[1].value.pdb_int);
  if (layer == NULL)
    success = FALSE;

  if (success)
    success = gimage_lower_layer (gimage, layer) != NULL;

  return procedural_db_return_args (&image_lower_channel_proc, success);
}

static ProcArg image_lower_channel_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "layer",
    "The layer to lower"
  }
};

static ProcRecord image_lower_channel_proc =
{
  "gimp_image_lower_channel",
  "Lower the specified layer in the image's layer stack",
  "This procedure lowers the specified layer one step in the existing layer stack. It will not move the layer if there is no layer below it, or the layer has no alpha channel.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_lower_channel_inargs,
  0,
  NULL,
  { { image_lower_channel_invoker } }
};

static Argument *
image_add_channel_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  Channel *channel;
  gint32 position;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  channel = channel_get_ID (args[1].value.pdb_int);
  if (channel == NULL)
    success = FALSE;

  position = args[2].value.pdb_int;

  if (success)
    success = gimage_add_channel (gimage, channel, MAX (position, -1)) != NULL;

  return procedural_db_return_args (&image_add_channel_proc, success);
}

static ProcArg image_add_channel_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_CHANNEL,
    "channel",
    "The channel"
  },
  {
    PDB_INT32,
    "position",
    "The channel position"
  }
};

static ProcRecord image_add_channel_proc =
{
  "gimp_image_add_channel",
  "Add the specified channel to the image.",
  "This procedure adds the specified channel to the image. The position channel is not currently used, so the channel is always inserted at the top of the channel stack.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_add_channel_inargs,
  0,
  NULL,
  { { image_add_channel_invoker } }
};

static Argument *
image_remove_channel_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  Channel *channel;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  channel = channel_get_ID (args[1].value.pdb_int);
  if (channel == NULL)
    success = FALSE;

  if (success)
    gimage_remove_channel (gimage, channel);

  return procedural_db_return_args (&image_remove_channel_proc, success);
}

static ProcArg image_remove_channel_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_CHANNEL,
    "channel",
    "The channel"
  }
};

static ProcRecord image_remove_channel_proc =
{
  "gimp_image_remove_channel",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_remove_channel_inargs,
  0,
  NULL,
  { { image_remove_channel_invoker } }
};

static Argument *
image_active_drawable_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  GimpDrawable *drawable = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    success = (drawable = gimage_active_drawable (gimage)) != NULL;

  return_args = procedural_db_return_args (&image_active_drawable_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (drawable));

  return return_args;
}

static ProcArg image_active_drawable_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_active_drawable_outargs[] =
{
  {
    PDB_DRAWABLE,
    "drawable",
    "The active drawable"
  }
};

static ProcRecord image_active_drawable_proc =
{
  "gimp_image_active_drawable",
  "Get the image's active drawable",
  "This procedure returns the ID of the image's active drawable. This can be either a layer, a channel, or a layer mask. The active drawable is specified by the active image channel. If that is -1, then by the active image layer. 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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_active_drawable_inargs,
  1,
  image_active_drawable_outargs,
  { { image_active_drawable_invoker } }
};

static Argument *
image_base_type_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 base_type = 0;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    base_type = gimage_base_type (gimage);

  return_args = procedural_db_return_args (&image_base_type_proc, success);

  if (success)
    return_args[1].value.pdb_int = base_type;

  return return_args;
}

static ProcArg image_base_type_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_base_type_outargs[] =
{
  {
    PDB_INT32,
    "base_type",
    "The image's base type: { RGB (0), GRAY (1), INDEXED (2) }"
  }
};

static ProcRecord image_base_type_proc =
{
  "gimp_image_base_type",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_base_type_inargs,
  1,
  image_base_type_outargs,
  { { image_base_type_invoker } }
};

static Argument *
image_get_cmap_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 num_bytes = 0;
  guint8 *cmap = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    {
      num_bytes = gimage->num_cols * 3;
      cmap = g_new (guint8, num_bytes);
      memcpy (cmap, gimage_cmap (gimage), num_bytes);
    }

  return_args = procedural_db_return_args (&image_get_cmap_proc, success);

  if (success)
    {
      return_args[1].value.pdb_int = num_bytes;
      return_args[2].value.pdb_pointer = cmap;
    }

  return return_args;
}

static ProcArg image_get_cmap_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_cmap_outargs[] =
{
  {
    PDB_INT32,
    "num_bytes",
    "Number of bytes in the colormap array: 0 < num_bytes"
  },
  {
    PDB_INT8ARRAY,
    "cmap",
    "The image's colormap"
  }
};

static ProcRecord image_get_cmap_proc =
{
  "gimp_image_get_cmap",
  "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 of base type INDEXED, this pointer will be NULL.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_get_cmap_inargs,
  2,
  image_get_cmap_outargs,
  { { image_get_cmap_invoker } }
};

static Argument *
image_set_cmap_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  gint32 num_bytes;
  guint8 *cmap;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  num_bytes = args[1].value.pdb_int;
  if (num_bytes < 0 || num_bytes > 768)
    success = FALSE;

  cmap = (guint8 *) args[2].value.pdb_pointer;

  if (success)
    {
      if (gimage->cmap)
	{
	  g_free (gimage->cmap);
	  gimage->cmap = NULL;
	}
      if (num_bytes)
	{
	  gimage->cmap = g_new (guchar, COLORMAP_SIZE);
	  memcpy (gimage->cmap, cmap, num_bytes);
	}
      gimage->num_cols = num_bytes / 3;
    
      /* A colormap alteration affects the whole image */
      gdisplays_update_area (gimage, 0, 0, gimage->width, gimage->height);
    }

  return procedural_db_return_args (&image_set_cmap_proc, success);
}

static ProcArg image_set_cmap_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "num_bytes",
    "Number of bytes in the colormap array: 0 <= num_bytes <= 768"
  },
  {
    PDB_INT8ARRAY,
    "cmap",
    "The new colormap values"
  }
};

static ProcRecord image_set_cmap_proc =
{
  "gimp_image_set_cmap",
  "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 \"cmap\" array. The actual number of colors in the transmitted colormap is \"num_bytes\" / 3.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_set_cmap_inargs,
  0,
  NULL,
  { { image_set_cmap_invoker } }
};

static Argument *
image_undo_is_enabled_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gboolean enabled = FALSE;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    enabled = gimp_image_undo_is_enabled (gimage);

  return_args = procedural_db_return_args (&image_undo_is_enabled_proc, success);

  if (success)
    return_args[1].value.pdb_int = enabled;

  return return_args;
}

static ProcArg image_undo_is_enabled_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_undo_is_enabled_outargs[] =
{
  {
    PDB_INT32,
    "enabled",
    "True if undo is enabled for this image"
  }
};

static ProcRecord image_undo_is_enabled_proc =
{
  "gimp_image_undo_is_enabled",
  "Check if the image's undo stack is enabled.",
  "This procedure checks if the image's undo stack is currently enabled or disabled. This is useful when several plugins or scripts call each other and want to check if their caller has already used 'gimp_image_undo_disable' or 'gimp_image_undo_freeze'.",
  "Raphael Quinet",
  "Raphael Quinet",
  "1999",
  PDB_INTERNAL,
  1,
  image_undo_is_enabled_inargs,
  1,
  image_undo_is_enabled_outargs,
  { { image_undo_is_enabled_invoker } }
};

static Argument *
image_undo_enable_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    success = gimage_enable_undo (gimage);

  return_args = procedural_db_return_args (&image_undo_enable_proc, success);

  if (success)
    return_args[1].value.pdb_int = success ? TRUE : FALSE;

  return return_args;
}

static ProcArg image_undo_enable_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_undo_enable_outargs[] =
{
  {
    PDB_INT32,
    "enabled",
    "True if the image undo has been enabled"
  }
};

static ProcRecord image_undo_enable_proc =
{
  "gimp_image_undo_enable",
  "Enable the image's undo stack.",
  "This procedure enables the image's undo stack, allowing subsequent operations to store their undo steps. This is generally called in conjunction with 'gimp_image_undo_disable' to temporarily disable an image undo stack.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_undo_enable_inargs,
  1,
  image_undo_enable_outargs,
  { { image_undo_enable_invoker } }
};

static Argument *
image_undo_disable_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    success = gimage_disable_undo (gimage);

  return_args = procedural_db_return_args (&image_undo_disable_proc, success);

  if (success)
    return_args[1].value.pdb_int = success ? TRUE : FALSE;

  return return_args;
}

static ProcArg image_undo_disable_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_undo_disable_outargs[] =
{
  {
    PDB_INT32,
    "disabled",
    "True if the image undo has been disabled"
  }
};

static ProcRecord image_undo_disable_proc =
{
  "gimp_image_undo_disable",
  "Disable the image's undo stack.",
  "This procedure disables the image's undo stack, allowing subsequent operations to ignore their undo steps. This is generally called in conjunction with 'gimp_image_undo_enable' to temporarily disable an image undo stack. This is advantageous because saving undo steps can be time and memory intensive.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_undo_disable_inargs,
  1,
  image_undo_disable_outargs,
  { { image_undo_disable_invoker } }
};

static Argument *
image_undo_freeze_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    success = gimage_freeze_undo (gimage);

  return_args = procedural_db_return_args (&image_undo_freeze_proc, success);

  if (success)
    return_args[1].value.pdb_int = success ? TRUE : FALSE;

  return return_args;
}

static ProcArg image_undo_freeze_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_undo_freeze_outargs[] =
{
  {
    PDB_INT32,
    "frozen",
    "True if the image undo has been frozen"
  }
};

static ProcRecord image_undo_freeze_proc =
{
  "gimp_image_undo_freeze",
  "Freeze the image's undo stack.",
  "This procedure freezes the image's undo stack, allowing subsequent operations to ignore their undo steps. This is generally called in conjunction with 'gimp_image_undo_thaw' to temporarily disable an image undo stack. This is advantageous because saving undo steps can be time and memory intensive. 'gimp_image_undo_{freeze,thaw}' and 'gimp_image_undo_{disable,enable}' differ in that the former does not free up all undo steps when undo is thawed, so is more suited to interactive in-situ previews. It is important in this case that the image is back to the same state it was frozen in before thawing, else 'undo' behaviour is undefined.",
  "Adam D. Moss",
  "Adam D. Moss",
  "1999",
  PDB_INTERNAL,
  1,
  image_undo_freeze_inargs,
  1,
  image_undo_freeze_outargs,
  { { image_undo_freeze_invoker } }
};

static Argument *
image_undo_thaw_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    success = gimage_thaw_undo (gimage);

  return_args = procedural_db_return_args (&image_undo_thaw_proc, success);

  if (success)
    return_args[1].value.pdb_int = success ? TRUE : FALSE;

  return return_args;
}

static ProcArg image_undo_thaw_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_undo_thaw_outargs[] =
{
  {
    PDB_INT32,
    "thawed",
    "True if the image undo has been thawed"
  }
};

static ProcRecord image_undo_thaw_proc =
{
  "gimp_image_undo_thaw",
  "Thaw the image's undo stack.",
  "This procedure thaws the image's undo stack, allowing subsequent operations to store their undo steps. This is generally called in conjunction with 'gimp_image_undo_freeze' to temporarily freeze an image undo stack. 'gimp_image_undo_thaw' does NOT free the undo stack as 'gimp_image_undo_enable' does, so is suited for situations where one wishes to leave the undo stack in the same state in which one found it despite non-destructively playing with the image in the meantime. An example would be in-situ plugin previews. Balancing freezes and thaws and ensuring image consistancy is the responsibility of the caller.",
  "Adam D. Moss",
  "Adam D. Moss",
  "1999",
  PDB_INTERNAL,
  1,
  image_undo_thaw_inargs,
  1,
  image_undo_thaw_outargs,
  { { image_undo_thaw_invoker } }
};

static Argument *
image_clean_all_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    gimage_clean_all (gimage);

  return procedural_db_return_args (&image_clean_all_proc, success);
}

static ProcArg image_clean_all_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcRecord image_clean_all_proc =
{
  "gimp_image_clean_all",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_clean_all_inargs,
  0,
  NULL,
  { { image_clean_all_invoker } }
};

static Argument *
image_floating_selection_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  GimpLayer *floating_sel = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    floating_sel = gimage_floating_sel (gimage);

  return_args = procedural_db_return_args (&image_floating_selection_proc, success);

  if (success)
    return_args[1].value.pdb_int = floating_sel ? drawable_ID (GIMP_DRAWABLE (floating_sel)) : -1;

  return return_args;
}

static ProcArg image_floating_selection_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_floating_selection_outargs[] =
{
  {
    PDB_LAYER,
    "floating_sel",
    "The image's floating selection"
  }
};

static ProcRecord image_floating_selection_proc =
{
  "gimp_image_floating_selection",
  "Return the floating selection of the image.",
  "This procedure returns the image's floating_sel, if it exists. If it doesn't exist, -1 is returned as the layer ID.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_floating_selection_inargs,
  1,
  image_floating_selection_outargs,
  { { image_floating_selection_invoker } }
};

static Argument *
image_floating_sel_attached_to_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  GimpDrawable *drawable = NULL;
  Layer *floating_sel;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    {
      floating_sel = gimage_floating_sel (gimage);
    
      if (floating_sel)
	drawable = GIMP_DRAWABLE (GIMP_LAYER (floating_sel)->fs.drawable);
      else
	drawable = NULL;
    }

  return_args = procedural_db_return_args (&image_floating_sel_attached_to_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable ? drawable_ID (GIMP_DRAWABLE (drawable)) : -1;

  return return_args;
}

static ProcArg image_floating_sel_attached_to_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_floating_sel_attached_to_outargs[] =
{
  {
    PDB_DRAWABLE,
    "drawable",
    "The drawable the floating selection is attached to"
  }
};

static ProcRecord image_floating_sel_attached_to_proc =
{
  "gimp_image_floating_sel_attached_to",
  "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.",
  "Wolfgang Hofer",
  "Wolfgang Hofer",
  "1998",
  PDB_INTERNAL,
  1,
  image_floating_sel_attached_to_inargs,
  1,
  image_floating_sel_attached_to_outargs,
  { { image_floating_sel_attached_to_invoker } }
};

static Argument *
image_thumbnail_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 req_width;
  gint32 req_height;
  gint32 width = 0;
  gint32 height = 0;
  gint32 bpp = 0;
  gint32 num_bytes = 0;
  guint8 *thumbnail_data = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  req_width = args[1].value.pdb_int;
  if (req_width <= 0)
    success = FALSE;

  req_height = args[2].value.pdb_int;
  if (req_height <= 0)
    success = FALSE;

  if (success)
    {
      TempBuf * buf;
      gint dwidth, dheight;
    
      if (req_width <= 128 && req_height <= 128)
	{        
	  /* Adjust the width/height ratio */
	  dwidth = gimage->width;
	  dheight = gimage->height;
    
	  if (dwidth > dheight)
	    req_height = (req_width * dheight) / dwidth;
	  else
	    req_width = (req_height * dwidth) / dheight;
    
	  buf = gimp_image_construct_composite_preview (gimage,
							req_width,
							req_height);
	  num_bytes = buf->height * buf->width * buf->bytes;
	  thumbnail_data = g_new (guint8, num_bytes);
	  g_memmove (thumbnail_data, temp_buf_data (buf), num_bytes);
	  width = buf->width;        
	  height = buf->height;
	  bpp = buf->bytes;
	  temp_buf_free (buf);
	}
    }

  return_args = procedural_db_return_args (&image_thumbnail_proc, success);

  if (success)
    {
      return_args[1].value.pdb_int = width;
      return_args[2].value.pdb_int = height;
      return_args[3].value.pdb_int = bpp;
      return_args[4].value.pdb_int = num_bytes;
      return_args[5].value.pdb_pointer = thumbnail_data;
    }

  return return_args;
}

static ProcArg image_thumbnail_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "width",
    "The thumbnail width"
  },
  {
    PDB_INT32,
    "height",
    "The thumbnail height"
  }
};

static ProcArg image_thumbnail_outargs[] =
{
  {
    PDB_INT32,
    "width",
    "The previews width"
  },
  {
    PDB_INT32,
    "height",
    "The previews height"
  },
  {
    PDB_INT32,
    "bpp",
    "The previews bpp"
  },
  {
    PDB_INT32,
    "thumbnail_data_count",
    "The number of bytes in thumbnail data"
  },
  {
    PDB_INT8ARRAY,
    "thumbnail_data",
    "The thumbnail data"
  }
};

static ProcRecord image_thumbnail_proc =
{
  "gimp_image_thumbnail",
  "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 128 pixels. The pixles are returned in the RGB[A] format. The bpp return value gives the number of bytes in the image. The alpha channel also returned if the image has one.",
  "Andy Thomas",
  "Andy Thomas",
  "1999",
  PDB_INTERNAL,
  3,
  image_thumbnail_inargs,
  5,
  image_thumbnail_outargs,
  { { image_thumbnail_invoker } }
};

static Argument *
image_width_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  return_args = procedural_db_return_args (&image_width_proc, success);

  if (success)
    return_args[1].value.pdb_int = gimage->width;

  return return_args;
}

static ProcArg image_width_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_width_outargs[] =
{
  {
    PDB_INT32,
    "width",
    "The image's width"
  }
};

static ProcRecord image_width_proc =
{
  "gimp_image_width",
  "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.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_width_inargs,
  1,
  image_width_outargs,
  { { image_width_invoker } }
};

static Argument *
image_height_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  return_args = procedural_db_return_args (&image_height_proc, success);

  if (success)
    return_args[1].value.pdb_int = gimage->height;

  return return_args;
}

static ProcArg image_height_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_height_outargs[] =
{
  {
    PDB_INT32,
    "height",
    "The image's height"
  }
};

static ProcRecord image_height_proc =
{
  "gimp_image_height",
  "Return the height 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\" height.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_height_inargs,
  1,
  image_height_outargs,
  { { image_height_invoker } }
};

static Argument *
image_get_active_layer_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  GimpLayer *active_layer = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    active_layer = gimage_get_active_layer (gimage);

  return_args = procedural_db_return_args (&image_get_active_layer_proc, success);

  if (success)
    return_args[1].value.pdb_int = active_layer ? drawable_ID (GIMP_DRAWABLE (active_layer)) : -1;

  return return_args;
}

static ProcArg image_get_active_layer_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_active_layer_outargs[] =
{
  {
    PDB_LAYER,
    "active_layer",
    "The active layer"
  }
};

static ProcRecord image_get_active_layer_proc =
{
  "gimp_image_get_active_layer",
  "Returns the active layer of the specified image.",
  "If there is an active layer, its ID will be returned, otherwise, -1. If a channel is currently active, then no layer will be. If a layer mask is active, then this will return the associated layer.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_get_active_layer_inargs,
  1,
  image_get_active_layer_outargs,
  { { image_get_active_layer_invoker } }
};

static Argument *
image_set_active_layer_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GimpLayer *active_layer;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  active_layer = layer_get_ID (args[1].value.pdb_int);
  if (active_layer == NULL)
    success = FALSE;

  if (success)
    gimage_set_active_layer (gimage, active_layer);

  return procedural_db_return_args (&image_set_active_layer_proc, success);
}

static ProcArg image_set_active_layer_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_LAYER,
    "active_layer",
    "The new image active layer"
  }
};

static ProcRecord image_set_active_layer_proc =
{
  "gimp_image_set_active_layer",
  "Set the active layer of the specified image.",
  "If the layer exists, it is set as the active layer in the image. Any previous active layer or channel is set to inactive. An exception is a previously existing floating selection, in which case this procedure will return an execution error.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_set_active_layer_inargs,
  0,
  NULL,
  { { image_set_active_layer_invoker } }
};

static Argument *
image_get_active_channel_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  Channel *active_channel = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    active_channel = gimage_get_active_channel (gimage);

  return_args = procedural_db_return_args (&image_get_active_channel_proc, success);

  if (success)
    return_args[1].value.pdb_int = active_channel ? drawable_ID (GIMP_DRAWABLE (active_channel)) : -1;

  return return_args;
}

static ProcArg image_get_active_channel_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_active_channel_outargs[] =
{
  {
    PDB_CHANNEL,
    "active_channel",
    "The active channel"
  }
};

static ProcRecord image_get_active_channel_proc =
{
  "gimp_image_get_active_channel",
  "Returns the active channel of the specified image.",
  "If there is an active channel, this will return the channel ID, otherwise, -1.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_get_active_channel_inargs,
  1,
  image_get_active_channel_outargs,
  { { image_get_active_channel_invoker } }
};

static Argument *
image_set_active_channel_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  Channel *active_channel;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  active_channel = channel_get_ID (args[1].value.pdb_int);
  if (active_channel == NULL)
    success = FALSE;

  if (success)
    gimage_set_active_channel (gimage, active_channel);

  return procedural_db_return_args (&image_set_active_channel_proc, success);
}

static ProcArg image_set_active_channel_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_CHANNEL,
    "active_channel",
    "The new image active channel"
  }
};

static ProcRecord image_set_active_channel_proc =
{
  "gimp_image_set_active_channel",
  "Set the active channel of the specified image.",
  "If the channel exists, it is set as the active channel in the image. Any previous active channel or channel is set to inactive. An exception is a previously existing floating selection, in which case this procedure will return an execution error.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_set_active_channel_inargs,
  0,
  NULL,
  { { image_set_active_channel_invoker } }
};

static Argument *
image_get_selection_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  Channel *selection = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  if (success)
    success = (selection = gimage_get_mask (gimage)) != NULL;

  return_args = procedural_db_return_args (&image_get_selection_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (selection));

  return return_args;
}

static ProcArg image_get_selection_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_selection_outargs[] =
{
  {
    PDB_SELECTION,
    "selection",
    "The selection channel"
  }
};

static ProcRecord image_get_selection_proc =
{
  "gimp_image_get_selection",
  "Returns the selection of the specified image.",
  "This will always return a valid ID for a selection--which is represented as a channel internally.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_get_selection_inargs,
  1,
  image_get_selection_outargs,
  { { image_get_selection_invoker } }
};

static Argument *
image_get_component_active_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 component;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  component = args[1].value.pdb_int;
  if (component < RED_CHANNEL || component > INDEXED_CHANNEL)
    success = FALSE;

  if (success)
    {
      if (component == GRAY_CHANNEL)
	success = gimage_base_type (gimage) == GRAY;
      else if (component == INDEXED_CHANNEL)
	success = gimage_base_type (gimage) == INDEXED;
      else
	success = gimage_base_type (gimage) == RGB;
    }

  return_args = procedural_db_return_args (&image_get_component_active_proc, success);

  if (success)
    return_args[1].value.pdb_int = gimage_get_component_active (gimage, component);

  return return_args;
}

static ProcArg image_get_component_active_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "component",
    "The image component: { RED_CHANNEL (0), GREEN_CHANNEL (1), BLUE_CHANNEL (2), GRAY_CHANNEL (3), INDEXED_CHANNEL (4) }"
  }
};

static ProcArg image_get_component_active_outargs[] =
{
  {
    PDB_INT32,
    "active",
    "Component is active (TRUE or FALSE)"
  }
};

static ProcRecord image_get_component_active_proc =
{
  "gimp_image_get_component_active",
  "Returns the image component is active of the specified image.",
  "This procedure returns 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, and error is returned.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_get_component_active_inargs,
  1,
  image_get_component_active_outargs,
  { { image_get_component_active_invoker } }
};

static Argument *
image_set_component_active_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  gint32 component;
  gboolean active;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  component = args[1].value.pdb_int;
  if (component < RED_CHANNEL || component > INDEXED_CHANNEL)
    success = FALSE;

  active = args[2].value.pdb_int ? TRUE : FALSE;

  if (success)
    {
      if (component == GRAY_CHANNEL)
	success = gimage_base_type (gimage) == GRAY;
      else if (component == INDEXED_CHANNEL)
	success = gimage_base_type (gimage) == INDEXED;
      else
	success = gimage_base_type (gimage) == RGB;
    
      if (success)
	gimage_set_component_active (gimage, component, active);
    }

  return procedural_db_return_args (&image_set_component_active_proc, success);
}

static ProcArg image_set_component_active_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "component",
    "The image component: { RED_CHANNEL (0), GREEN_CHANNEL (1), BLUE_CHANNEL (2), GRAY_CHANNEL (3), INDEXED_CHANNEL (4) }"
  },
  {
    PDB_INT32,
    "active",
    "Component is active (TRUE or FALSE)"
  }
};

static ProcRecord image_set_component_active_proc =
{
  "gimp_image_set_component_active",
  "Set the image component is active of the specified image.",
  "This procedure sets 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, and error is returned.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_set_component_active_inargs,
  0,
  NULL,
  { { image_set_component_active_invoker } }
};

static Argument *
image_get_component_visible_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 component;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  component = args[1].value.pdb_int;
  if (component < RED_CHANNEL || component > INDEXED_CHANNEL)
    success = FALSE;

  if (success)
    {
      if (component == GRAY_CHANNEL)
	success = gimage_base_type (gimage) == GRAY;
      else if (component == INDEXED_CHANNEL)
	success = gimage_base_type (gimage) == INDEXED;
      else
	success = gimage_base_type (gimage) == RGB;
    }

  return_args = procedural_db_return_args (&image_get_component_visible_proc, success);

  if (success)
    return_args[1].value.pdb_int = gimage_get_component_visible (gimage, component);

  return return_args;
}

static ProcArg image_get_component_visible_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "component",
    "The image component: { RED_CHANNEL (0), GREEN_CHANNEL (1), BLUE_CHANNEL (2), GRAY_CHANNEL (3), INDEXED_CHANNEL (4) }"
  }
};

static ProcArg image_get_component_visible_outargs[] =
{
  {
    PDB_INT32,
    "visible",
    "Component is visible (TRUE or FALSE)"
  }
};

static ProcRecord image_get_component_visible_proc =
{
  "gimp_image_get_component_visible",
  "Returns the image component is visible of the specified image.",
  "This procedure returns 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, and error is returned.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_get_component_visible_inargs,
  1,
  image_get_component_visible_outargs,
  { { image_get_component_visible_invoker } }
};

static Argument *
image_set_component_visible_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  gint32 component;
  gboolean visible;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  component = args[1].value.pdb_int;
  if (component < RED_CHANNEL || component > INDEXED_CHANNEL)
    success = FALSE;

  visible = args[2].value.pdb_int ? TRUE : FALSE;

  if (success)
    {
      if (component == GRAY_CHANNEL)
	success = gimage_base_type (gimage) == GRAY;
      else if (component == INDEXED_CHANNEL)
	success = gimage_base_type (gimage) == INDEXED;
      else
	success = gimage_base_type (gimage) == RGB;
    
      if (success)
	gimage_set_component_visible (gimage, component, visible);
    }

  return procedural_db_return_args (&image_set_component_visible_proc, success);
}

static ProcArg image_set_component_visible_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "component",
    "The image component: { RED_CHANNEL (0), GREEN_CHANNEL (1), BLUE_CHANNEL (2), GRAY_CHANNEL (3), INDEXED_CHANNEL (4) }"
  },
  {
    PDB_INT32,
    "visible",
    "Component is visible (TRUE or FALSE)"
  }
};

static ProcRecord image_set_component_visible_proc =
{
  "gimp_image_set_component_visible",
  "Set the image component is visible of the specified image.",
  "This procedure sets 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, and error is returned.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  3,
  image_set_component_visible_inargs,
  0,
  NULL,
  { { image_set_component_visible_invoker } }
};

static Argument *
image_get_filename_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  return_args = procedural_db_return_args (&image_get_filename_proc, success);

  if (success)
    return_args[1].value.pdb_pointer = g_strdup (gimage_filename (gimage));

  return return_args;
}

static ProcArg image_get_filename_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_filename_outargs[] =
{
  {
    PDB_STRING,
    "filename",
    "The filename"
  }
};

static ProcRecord image_get_filename_proc =
{
  "gimp_image_get_filename",
  "Returns the filename of the specified image.",
  "This procedure returns the specified image's filename--if it was loaded or has since been saved. Otherwise, returns NULL.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  1,
  image_get_filename_inargs,
  1,
  image_get_filename_outargs,
  { { image_get_filename_invoker } }
};

static Argument *
image_set_filename_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  gchar *filename;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  filename = (gchar *) args[1].value.pdb_pointer;
  if (filename == NULL)
    success = FALSE;

  if (success)
    gimage_set_filename (gimage, filename);

  return procedural_db_return_args (&image_set_filename_proc, success);
}

static ProcArg image_set_filename_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_STRING,
    "filename",
    "The new image filename"
  }
};

static ProcRecord image_set_filename_proc =
{
  "gimp_image_set_filename",
  "Set the filename of the specified image.",
  "This procedure sets the specified image's filename.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,
  2,
  image_set_filename_inargs,
  0,
  NULL,
  { { image_set_filename_invoker } }
};

static Argument *
image_get_resolution_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  return_args = procedural_db_return_args (&image_get_resolution_proc, success);

  if (success)
    {
      return_args[1].value.pdb_float = gimage->xresolution;
      return_args[2].value.pdb_float = gimage->yresolution;
    }

  return return_args;
}

static ProcArg image_get_resolution_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_resolution_outargs[] =
{
  {
    PDB_FLOAT,
    "xresolution",
    "The resolutionin the x-axis, in dots per inch"
  },
  {
    PDB_FLOAT,
    "yresolution",
    "The resolutionin the y-axis, in dots per inch"
  }
};

static ProcRecord image_get_resolution_proc =
{
  "gimp_image_get_resolution",
  "Returns the resolution of the specified image.",
  "This procedure returns the specified image's resolution in dots per inch. This value is independent of any of the layers in this image.",
  "Austin Donnelly",
  "Austin Donnelly",
  "1998",
  PDB_INTERNAL,
  1,
  image_get_resolution_inargs,
  2,
  image_get_resolution_outargs,
  { { image_get_resolution_invoker } }
};

static Argument *
image_set_resolution_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  gdouble xresolution;
  gdouble yresolution;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  xresolution = args[1].value.pdb_float;

  yresolution = args[2].value.pdb_float;

  if (success)
    {
      if (xresolution < GIMP_MIN_RESOLUTION || xresolution > GIMP_MAX_RESOLUTION ||
	  yresolution < GIMP_MIN_RESOLUTION || yresolution > GIMP_MAX_RESOLUTION)
	success = FALSE;
      else
	{
	  gimage->xresolution = xresolution;
	  gimage->yresolution = yresolution;
	}
    }

  return procedural_db_return_args (&image_set_resolution_proc, success);
}

static ProcArg image_set_resolution_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_FLOAT,
    "xresolution",
    "The new image resolution (xresolution)in the x-axis, in dots per inch"
  },
  {
    PDB_FLOAT,
    "yresolution",
    "The new image resolution (yresolution)in the y-axis, in dots per inch"
  }
};

static ProcRecord image_set_resolution_proc =
{
  "gimp_image_set_resolution",
  "Set the resolution of the specified image.",
  "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.",
  "Austin Donnelly",
  "Austin Donnelly",
  "1998",
  PDB_INTERNAL,
  3,
  image_set_resolution_inargs,
  0,
  NULL,
  { { image_set_resolution_invoker } }
};

static Argument *
image_get_unit_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  return_args = procedural_db_return_args (&image_get_unit_proc, success);

  if (success)
    return_args[1].value.pdb_int = gimage->unit;

  return return_args;
}

static ProcArg image_get_unit_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  }
};

static ProcArg image_get_unit_outargs[] =
{
  {
    PDB_INT32,
    "unit",
    "The unit"
  }
};

static ProcRecord image_get_unit_proc =
{
  "gimp_image_get_unit",
  "Returns the unit of the specified image.",
  "This procedure returns the specified image's unit. This value is independent of any of the layers in this image. See the gimp_unit_* procedure definitions for the valid range of unit IDs and a description of the unit system.",
  "Michael Natterer",
  "Michael Natterer",
  "1998",
  PDB_INTERNAL,
  1,
  image_get_unit_inargs,
  1,
  image_get_unit_outargs,
  { { image_get_unit_invoker } }
};

static Argument *
image_set_unit_invoker (Argument *args)
{
  gboolean success = TRUE;
  GimpImage *gimage;
  GUnit unit;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  unit = args[1].value.pdb_int;
  if (unit < UNIT_INCH || unit >= gimp_unit_get_number_of_units ())
    success = FALSE;

  if (success)
    gimage->unit = unit;

  return procedural_db_return_args (&image_set_unit_proc, success);
}

static ProcArg image_set_unit_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "unit",
    "The new image unit"
  }
};

static ProcRecord image_set_unit_proc =
{
  "gimp_image_set_unit",
  "Set the unit of the specified image.",
  "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 gimp_unit_* procedure definitions for the valid range of unit IDs and a description of the unit system.",
  "Michael Natterer",
  "Michael Natterer",
  "1998",
  PDB_INTERNAL,
  2,
  image_set_unit_inargs,
  0,
  NULL,
  { { image_set_unit_invoker } }
};

static Argument *
image_get_layer_by_tattoo_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 tattoo;
  GimpLayer *layer = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  tattoo = args[1].value.pdb_int;
  if (tattoo == 0)
    success = FALSE;

  if (success)
    {
      layer = gimp_image_get_layer_by_tattoo (gimage, tattoo);
      success = layer != NULL;
    }

  return_args = procedural_db_return_args (&image_get_layer_by_tattoo_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (layer));

  return return_args;
}

static ProcArg image_get_layer_by_tattoo_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "tattoo",
    "The tattoo of the layer to find"
  }
};

static ProcArg image_get_layer_by_tattoo_outargs[] =
{
  {
    PDB_LAYER,
    "layer",
    "The layer with the specified tattoo"
  }
};

static ProcRecord image_get_layer_by_tattoo_proc =
{
  "gimp_image_get_layer_by_tattoo",
  "Find a layer with a given tattoo in an image.",
  "This procedure returns the layer with the given tattoo in the specified image.",
  "Jay Cox",
  "Jay Cox",
  "1998",
  PDB_INTERNAL,
  2,
  image_get_layer_by_tattoo_inargs,
  1,
  image_get_layer_by_tattoo_outargs,
  { { image_get_layer_by_tattoo_invoker } }
};

static Argument *
image_get_channel_by_tattoo_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpImage *gimage;
  gint32 tattoo;
  Channel *channel = NULL;

  gimage = pdb_id_to_image (args[0].value.pdb_int);
  if (gimage == NULL)
    success = FALSE;

  tattoo = args[1].value.pdb_int;
  if (tattoo == 0)
    success = FALSE;

  if (success)
    {
      channel = gimp_image_get_channel_by_tattoo (gimage, tattoo);
      success = channel != NULL;
    }

  return_args = procedural_db_return_args (&image_get_channel_by_tattoo_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (channel));

  return return_args;
}

static ProcArg image_get_channel_by_tattoo_inargs[] =
{
  {
    PDB_IMAGE,
    "image",
    "The image"
  },
  {
    PDB_INT32,
    "tattoo",
    "The tattoo of the channel to find"
  }
};

static ProcArg image_get_channel_by_tattoo_outargs[] =
{
  {
    PDB_CHANNEL,
    "channel",
    "The channel with the specified tattoo"
  }
};

static ProcRecord image_get_channel_by_tattoo_proc =
{
  "gimp_image_get_channel_by_tattoo",
  "Find a channel with a given tattoo in an image.",
  "This procedure returns the channel with the given tattoo in the specified image.",
  "Jay Cox",
  "Jay Cox",
  "1998",
  PDB_INTERNAL,
  2,
  image_get_channel_by_tattoo_inargs,
  1,
  image_get_channel_by_tattoo_outargs,
  { { image_get_channel_by_tattoo_invoker } }
};
