Beispiel #1
0
PyObject *
pygimp_pixel_rgn_new(PyGimpDrawable *drawable, int x, int y,
		     int width, int height, int dirty, int shadow)
{
    PyGimpPixelRgn *self;
    int drw_width;
    int drw_height;

    self = PyObject_NEW(PyGimpPixelRgn, &PyGimpPixelRgn_Type);

    if (self == NULL || drawable == NULL)
        return NULL;

    drw_width = gimp_drawable_width(drawable->ID);
    drw_height = gimp_drawable_height(drawable->ID);

    if(x < 0) x = 0;
    if(y < 0) y = 0;
    if(width < 0) width = drw_width - x;
    if(height < 0) height = drw_height - y;
    if(x >= drw_width) x = drw_width - 1;
    if(y >= drw_height) y = drw_height - 1;
    if(x + width > drw_width) width = drw_width - x;
    if(y + height > drw_height) height = drw_height - y;

    gimp_pixel_rgn_init(&(self->pr), drawable->drawable, x, y, width, height,
			dirty, shadow);

    self->drawable = drawable;
    Py_INCREF(drawable);

    return (PyObject *)self;
}
Beispiel #2
0
void
combo_get_active (GtkWidget * combo, PreviewData * p_data,
		  gint32 * layer_ID_add, gboolean status,
		  GdkPixbuf ** pixbuf_add, SizeInfo * size_info)
{
  gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo), layer_ID_add);
  if (status == TRUE)
    {
      if (*pixbuf_add)
        {
          g_object_unref (G_OBJECT (*pixbuf_add));
        }
      gimp_drawable_offsets (*layer_ID_add, &(size_info->x_off), &(size_info->y_off));

      size_info->x_off -= p_data->x_off;
      size_info->y_off -= p_data->y_off;

      size_info->width = gimp_drawable_width(*layer_ID_add);
      size_info->height = gimp_drawable_height(*layer_ID_add);

      size_info_scale(size_info, p_data->factor);

      *pixbuf_add = gimp_drawable_get_thumbnail(*layer_ID_add, size_info->width, size_info->height, GIMP_PIXBUF_KEEP_ALPHA);
    }
  preview_build_pixbuf (p_data);
  gtk_widget_queue_draw (p_data->area);
}
/**
 * gimp_drawable_get:
 * @drawable_ID: the ID of the drawable
 *
 * This function creates a #GimpDrawable structure for the core
 * drawable identified by @drawable_ID. The returned structure
 * contains some basic information about the drawable and can also
 * hold tile data for transfer to and from the core.
 *
 * Note that the name of this function is somewhat misleading, because
 * it suggests that it simply returns a handle.  This is not the case:
 * if the function is called multiple times, it creates separate tile
 * lists each time, which will usually produce undesired results.
 *
 * When a plug-in has finished working with a drawable, before exiting
 * it should call gimp_drawable_detach() to make sure that all tile data is
 * transferred back to the core.
 *
 * Return value: a new #GimpDrawable wrapper
 **/
GimpDrawable *
gimp_drawable_get (gint32 drawable_ID)
{
  GimpDrawable *drawable;
  gint          width;
  gint          height;
  gint          bpp;

  width  = gimp_drawable_width  (drawable_ID);
  height = gimp_drawable_height (drawable_ID);
  bpp    = gimp_drawable_bpp    (drawable_ID);

  g_return_val_if_fail (width > 0 && height > 0 && bpp > 0, NULL);

  drawable = g_slice_new0 (GimpDrawable);

  drawable->drawable_id  = drawable_ID;
  drawable->width        = width;
  drawable->height       = height;
  drawable->bpp          = bpp;
  drawable->ntile_rows   = (height + TILE_HEIGHT - 1) / TILE_HEIGHT;
  drawable->ntile_cols   = (width  + TILE_WIDTH  - 1) / TILE_WIDTH;

  return drawable;
}
Beispiel #4
0
/*
 * Return TRUE iff the specified drawable can be used as a mask-size /
 * exponent map with the source image. The map and the image must have the
 * same dimensions.
 */
static gboolean
oilify_map_constrain (gint32   image_id G_GNUC_UNUSED,
                      gint32   drawable_id,
                      gpointer data)
{
  GimpDrawable *drawable = data;

  return (gimp_drawable_width (drawable_id)  == (gint) drawable->width &&
          gimp_drawable_height (drawable_id) == (gint) drawable->height);
}
Beispiel #5
0
static gboolean
displace_map_constrain (gint32   image_id,
                        gint32   drawable_id,
                        gpointer data)
{
  GimpDrawable *drawable = data;

  return (gimp_drawable_width (drawable_id)  == drawable->width &&
          gimp_drawable_height (drawable_id) == drawable->height);
}
Beispiel #6
0
static void
check_drawables (void)
{
  if (mapvals.bump_mapped)
    {
      if (mapvals.bumpmap_id != -1 &&
          gimp_item_get_image (mapvals.bumpmap_id) == -1)
        {
          mapvals.bump_mapped = FALSE;
          mapvals.bumpmap_id  = -1;
        }

      if (gimp_drawable_is_indexed (mapvals.bumpmap_id) ||
          (gimp_drawable_width (mapvals.drawable_id) !=
           gimp_drawable_width (mapvals.bumpmap_id)) ||
          (gimp_drawable_height (mapvals.drawable_id) !=
           gimp_drawable_height (mapvals.bumpmap_id)))
        {
          mapvals.bump_mapped = FALSE;
          mapvals.bumpmap_id  = -1;
        }
    }

  if (mapvals.env_mapped)
    {
      if (mapvals.envmap_id != -1 &&
          gimp_item_get_image (mapvals.envmap_id) == -1)
        {
          mapvals.env_mapped = FALSE;
          mapvals.envmap_id  = -1;
        }

      if (gimp_drawable_is_gray (mapvals.envmap_id) ||
          gimp_drawable_has_alpha (mapvals.envmap_id))
        {
          mapvals.env_mapped = FALSE;
          mapvals.envmap_id  = -1;
        }
    }
}
Beispiel #7
0
static GtkWidget *
ico_preview_new (gint32 layer)
{
  GtkWidget *image;
  GdkPixbuf *pixbuf;
  gint       width  = gimp_drawable_width (layer);
  gint       height = gimp_drawable_height (layer);

  pixbuf = gimp_drawable_get_thumbnail (layer,
                                        MIN (width, 128), MIN (height, 128),
                                        GIMP_PIXBUF_SMALL_CHECKS);
  image = gtk_image_new_from_pixbuf (pixbuf);
  g_object_unref (pixbuf);

  return image;
}
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
  GeglRectangle result = {0,0,0,0};
  GeglChantO   *o = GEGL_CHANT_PROPERTIES (operation);

  if (o->drawableID)
  { 
    g_printf("Bounds\n");

    result.x      = 0;
    result.y      = 0;
    result.width  = gimp_drawable_width (o->drawableID);
    result.height = gimp_drawable_height (o->drawableID);
    /*
    result.width  = ((GimpDrawable*) o->drawableID)->width;
    result.height = ((GimpDrawable*) o->drawableID)->height;
    */
  }
  return result;
}
Beispiel #9
0
static void
align_layers_get_align_offsets (gint32  drawable_id,
                                gint   *x,
                                gint   *y)
{
  gint width  = gimp_drawable_width  (drawable_id);
  gint height = gimp_drawable_height (drawable_id);

  switch (VALS.h_base)
    {
    case H_BASE_LEFT:
      *x = 0;
      break;
    case H_BASE_CENTER:
      *x = width / 2;
      break;
    case H_BASE_RIGHT:
      *x = width;
      break;
    default:
      *x = 0;
      break;
    }

  switch (VALS.v_base)
    {
    case V_BASE_TOP:
      *y = 0;
      break;
    case V_BASE_CENTER:
      *y = height / 2;
      break;
    case V_BASE_BOTTOM:
      *y = height;
      break;
    default:
      *y = 0;
      break;
    }
}
Beispiel #10
0
static void
ico_dialog_check_compat (GtkWidget   *dialog,
                         IcoSaveInfo *info)
{
  GtkWidget *warning;
  gboolean   warn = FALSE;
  gint       i;

  for (i = 0; i < info->num_icons; i++)
    {
      if (gimp_drawable_width (info->layers[i]) > 255  ||
          gimp_drawable_height (info->layers[i]) > 255 ||
          info->compress[i])
        {
          warn = TRUE;
          break;
        }
    }

  warning = g_object_get_data (G_OBJECT (dialog), "warning");

  gtk_widget_set_visible (warning, warn);
}
Beispiel #11
0
Preview_t *
make_preview (GimpDrawable *drawable)
{
   Preview_t *data = g_new(Preview_t, 1);
   GtkAdjustment *hadj;
   GtkAdjustment *vadj;
   GtkWidget *preview;
   GtkWidget *window;
   GtkWidget *button, *arrow;
   GtkWidget *ruler;
   GtkWidget *table;
   GtkWidget *scrollbar;
   gint width, height;

   data->drawable = drawable;
   data->preview = preview = gimp_preview_area_new ();

   g_object_set_data (G_OBJECT (preview), "preview", data);
   gtk_widget_set_events(GTK_WIDGET(preview), PREVIEW_MASK);
   g_signal_connect_after(preview, "expose-event",
                          G_CALLBACK(preview_expose), data);
   g_signal_connect (preview, "size-allocate",
                     G_CALLBACK (preview_size_allocate), (gpointer)data);

   /* Handle drop of links in preview widget */
   gtk_drag_dest_set(preview, GTK_DEST_DEFAULT_ALL, target_table,
                     2, GDK_ACTION_COPY);
   g_signal_connect(preview, "drag-data-received",
                    G_CALLBACK(handle_drop), NULL);

   data->widget_width = data->width =
       gimp_drawable_width(drawable->drawable_id);
   data->widget_height = data->height =
       gimp_drawable_height(drawable->drawable_id);
   gtk_widget_set_size_request (preview, data->widget_width,
                                data->widget_height);

   /* The main table */
   data->window = table = gtk_table_new(3, 3, FALSE);
   gtk_table_set_col_spacings (GTK_TABLE (table), 1);
   gtk_table_set_row_spacings (GTK_TABLE (table), 1);

   /* Create button with arrow */
   button = gtk_button_new();
   gtk_widget_set_can_focus (button, FALSE);
   gtk_table_attach(GTK_TABLE(table), button, 0, 1, 0, 1, GTK_FILL, GTK_FILL,
                    0, 0);
   gtk_widget_set_events(button,
                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
   g_signal_connect(button, "button-press-event",
                    G_CALLBACK(arrow_cb), NULL);
   gtk_widget_show(button);

   arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
   gtk_container_add(GTK_CONTAINER(button), arrow);
   gtk_widget_show(arrow);

   /* Create horizontal ruler */
   data->hruler = ruler = gimp_ruler_new (GTK_ORIENTATION_HORIZONTAL);
   g_signal_connect_swapped(preview, "motion-notify-event",
                            G_CALLBACK(GTK_WIDGET_GET_CLASS(ruler)->motion_notify_event),
                            ruler);

   gtk_table_attach(GTK_TABLE(table), ruler, 1, 2, 0, 1,
                    GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
   gtk_widget_show(ruler);

   /* Create vertical ruler */
   data->vruler = ruler = gimp_ruler_new (GTK_ORIENTATION_VERTICAL);
   g_signal_connect_swapped(preview, "motion-notify-event",
                            G_CALLBACK(GTK_WIDGET_GET_CLASS(ruler)->motion_notify_event),
                            ruler);
   gtk_table_attach(GTK_TABLE(table), ruler, 0, 1, 1, 2,
                    GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
   gtk_widget_show(ruler);

   window = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(window),
                                  GTK_POLICY_NEVER, GTK_POLICY_NEVER);
   width = (data->width > 600) ? 600 : data->width;
   height = (data->height > 400) ? 400 : data->height;
   gtk_widget_set_size_request(window, width, height);
   gtk_table_attach(GTK_TABLE(table), window, 1, 2, 1, 2, GTK_FILL, GTK_FILL,
                    0, 0);
   gtk_widget_show(window);

   hadj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (window));

   g_signal_connect (hadj, "changed",
                     G_CALLBACK (scroll_adj_changed),
                     data->hruler);
   g_signal_connect (hadj, "value-changed",
                     G_CALLBACK (scroll_adj_changed),
                     data->hruler);

   vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (window));

   g_signal_connect (vadj, "changed",
                     G_CALLBACK (scroll_adj_changed),
                     data->vruler);
   g_signal_connect (vadj, "value-changed",
                     G_CALLBACK (scroll_adj_changed),
                     data->vruler);

   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(window), preview);

   scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, hadj);
   gtk_table_attach(GTK_TABLE(table), scrollbar, 1, 2, 2, 3,
                    GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
   gtk_widget_show (scrollbar);

   scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, vadj);
   gtk_table_attach(GTK_TABLE(table), scrollbar,  2, 3, 1, 2,
                    GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
   gtk_widget_show (scrollbar);

   gtk_widget_show (preview);

   gimp_pixel_rgn_init(&data->src_rgn, drawable, 0, 0, data->width,
                       data->height, FALSE, FALSE);
   render_preview(data, &data->src_rgn);

   gtk_widget_show(table);

   return data;
}
Beispiel #12
0
/* Decompose an image. It returns the number of new (gray) images.
   The image IDs for the new images are returned in image_ID_dst.
   On failure, -1 is returned.
*/
static gint32
decompose (gint32       image_ID,
           gint32       drawable_ID,
           const gchar *extract_type,
           gint32      *image_ID_dst,
           gint32      *nlayers,
           gint32      *layer_ID_dst)
{
  const gchar  *layername;
  gint          i, j, extract_idx, scan_lines;
  gint          height, width, tile_height, num_layers;
  gchar        *filename;
  guchar       *src;
  guchar       *dst[MAX_EXTRACT_IMAGES];
  GimpDrawable *drawable_src;
  GimpDrawable *drawable_dst[MAX_EXTRACT_IMAGES];
  GimpPixelRgn  pixel_rgn_src;
  GimpPixelRgn  pixel_rgn_dst[MAX_EXTRACT_IMAGES];

  extract_idx = -1;   /* Search extract type */
  for (j = 0; j < G_N_ELEMENTS (extract); j++)
    {
      if (g_ascii_strcasecmp (extract_type, extract[j].type) == 0)
	{
	  extract_idx = j;
	  break;
	}
    }
  if (extract_idx < 0)
    return -1;

  /* Check structure of source image */
  drawable_src = gimp_drawable_get (drawable_ID);
  if (drawable_src->bpp < 3)
    {
      g_message ("Not an RGB image.");
      return -1;
    }
  if ((extract[extract_idx].extract_fun == extract_alpha ||
       extract[extract_idx].extract_fun == extract_rgba) &&
      (!gimp_drawable_has_alpha (drawable_ID)))
    {
      g_message ("No alpha channel available.");
      return -1;
    }

  width  = drawable_src->width;
  height = drawable_src->height;

  tile_height = gimp_tile_height ();
  gimp_pixel_rgn_init (&pixel_rgn_src, drawable_src, 0, 0, width, height,
                       FALSE, FALSE);

  /* allocate a buffer for retrieving information from the src pixel region  */
  src = g_new (guchar, tile_height * width * drawable_src->bpp);

  /* Create all new gray images */
  num_layers = extract[extract_idx].num_images;
  if (num_layers > MAX_EXTRACT_IMAGES)
    num_layers = MAX_EXTRACT_IMAGES;

  for (j = 0; j < num_layers; j++)
    {
      /* Build a filename like <imagename>-<channel>.<extension> */
      gchar   *fname;
      gchar   *extension;
      gdouble  xres, yres;

      fname = gimp_image_get_filename (image_ID);

      if (fname)
        {
          extension = fname + strlen (fname) - 1;

          while (extension >= fname)
            {
              if (*extension == '.') break;
              extension--;
            }
          if (extension >= fname)
            {
              *(extension++) = '\0';

              if (decovals.as_layers)
                filename = g_strdup_printf ("%s-%s.%s", fname,
                                            gettext (extract[extract_idx].type),
                                            extension);
              else
                filename = g_strdup_printf ("%s-%s.%s", fname,
                                            gettext (extract[extract_idx].channel_name[j]),
                                            extension);
            }
          else
            {
              if (decovals.as_layers)
                filename = g_strdup_printf ("%s-%s", fname,
                                            gettext (extract[extract_idx].type));
              else
                filename = g_strdup_printf ("%s-%s", fname,
                                            gettext (extract[extract_idx].channel_name[j]));
            }
        }
      else
        {
          filename = g_strdup (gettext (extract[extract_idx].channel_name[j]));
        }

      gimp_image_get_resolution (image_ID, &xres, &yres);

      if (decovals.as_layers)
        {
          layername = gettext (extract[extract_idx].channel_name[j]);

          if (j == 0)
            image_ID_dst[j] = create_new_image (filename, layername,
                                                width, height, GIMP_GRAY,
                                                xres, yres,
                                                layer_ID_dst + j,
                                                drawable_dst + j,
                                                pixel_rgn_dst + j);
          else
            layer_ID_dst[j] = create_new_layer (image_ID_dst[0], j, layername,
                                                width, height, GIMP_GRAY,
                                                drawable_dst + j,
                                                pixel_rgn_dst + j);
        }
      else
        {
          image_ID_dst[j] = create_new_image (filename, NULL,
                                              width, height, GIMP_GRAY,
                                              xres, yres,
                                              layer_ID_dst + j,
                                              drawable_dst + j,
                                              pixel_rgn_dst + j);
        }

      g_free (filename);
      g_free (fname);
      dst[j] = g_new (guchar, tile_height * width);
    }

  i = 0;
  while (i < height)
    {
      /* Get source pixel region */
      scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i);
      gimp_pixel_rgn_get_rect (&pixel_rgn_src, src, 0, i, width, scan_lines);

      /* Extract the channel information */
      extract[extract_idx].extract_fun (src, drawable_src->bpp, scan_lines*width,
					dst);

      /* Transfer the registration color */
      if (decovals.use_registration)
        transfer_registration_color (src, drawable_src->bpp, scan_lines*width,
                                     dst, extract[extract_idx].num_images);

      /* Set destination pixel regions */
      for (j = 0; j < num_layers; j++)
	gimp_pixel_rgn_set_rect (&(pixel_rgn_dst[j]), dst[j], 0, i, width,
				 scan_lines);
      i += scan_lines;

      gimp_progress_update ((gdouble) i / (gdouble) height);
    }

  g_free (src);

  for (j = 0; j < num_layers; j++)
    {
      gimp_drawable_detach (drawable_dst[j]);
      gimp_drawable_update (layer_ID_dst[j], 0, 0,
                            gimp_drawable_width (layer_ID_dst[j]),
                            gimp_drawable_height (layer_ID_dst[j]));
      gimp_layer_add_alpha (layer_ID_dst[j]);
      g_free (dst[j]);
    }

  gimp_drawable_detach (drawable_src);

  *nlayers = num_layers;

  return (decovals.as_layers ? 1 : num_layers);
}
Beispiel #13
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam values[1];

  GimpDrawable      *drawable;
  GimpPDBStatusType  status;
  GimpRunMode        run_mode;
  gdouble            xhsiz, yhsiz;
  GimpRGB            background;

  status   = GIMP_PDB_SUCCESS;
  run_mode = param[0].data.d_int32;

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

  *nreturn_vals = 1;
  *return_vals  = values;

  INIT_I18N ();

  /* Get the active drawable info */

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

  img_width     = gimp_drawable_width (drawable->drawable_id);
  img_height    = gimp_drawable_height (drawable->drawable_id);
  img_has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

  gimp_drawable_mask_bounds (drawable->drawable_id,
                             &sel_x1, &sel_y1, &sel_x2, &sel_y2);

  /* Calculate scaling parameters */

  sel_width  = sel_x2 - sel_x1;
  sel_height = sel_y2 - sel_y1;

  cen_x = (double) (sel_x1 + sel_x2 - 1) / 2.0;
  cen_y = (double) (sel_y1 + sel_y2 - 1) / 2.0;

  xhsiz = (double) (sel_width - 1) / 2.0;
  yhsiz = (double) (sel_height - 1) / 2.0;

  if (xhsiz < yhsiz)
    {
      scale_x = yhsiz / xhsiz;
      scale_y = 1.0;
    }
  else if (xhsiz > yhsiz)
    {
      scale_x = 1.0;
      scale_y = xhsiz / yhsiz;
    }
  else
    {
      scale_x = 1.0;
      scale_y = 1.0;
    }

  /* Get background color */
  gimp_context_get_background (&background);
  gimp_rgb_set_alpha (&background, 0.0);
  gimp_drawable_get_color_uchar (drawable->drawable_id, &background,
                                 back_color);

  /* See how we will run */

  switch (run_mode)
    {
    case GIMP_RUN_INTERACTIVE:
      /* Possibly retrieve data */
      gimp_get_data (PLUG_IN_PROC, &pcvals);

      /* Get information from the dialog */
      if (! polarize_dialog (drawable))
        return;

      break;

    case GIMP_RUN_NONINTERACTIVE:
      /* Make sure all the arguments are present */
      if (nparams != 8)
        {
          status = GIMP_PDB_CALLING_ERROR;
        }
      else
        {
          pcvals.circle  = param[3].data.d_float;
          pcvals.angle  = param[4].data.d_float;
          pcvals.backwards  = param[5].data.d_int32;
          pcvals.inverse  = param[6].data.d_int32;
          pcvals.polrec  = param[7].data.d_int32;
        }
      break;

    case GIMP_RUN_WITH_LAST_VALS:
      /* Possibly retrieve data */
      gimp_get_data (PLUG_IN_PROC, &pcvals);
      break;

    default:
      break;
    }

  /* Distort the image */
  if ((status == GIMP_PDB_SUCCESS) &&
      (gimp_drawable_is_rgb (drawable->drawable_id) ||
       gimp_drawable_is_gray (drawable->drawable_id)))
    {
      /* Set the tile cache size */
      gimp_tile_cache_ntiles (2 * (drawable->width + gimp_tile_width() - 1) /
                              gimp_tile_width ());

      /* Run! */
      polarize (drawable);

      /* If run mode is interactive, flush displays */
      if (run_mode != GIMP_RUN_NONINTERACTIVE)
        gimp_displays_flush ();

      /* Store data */
      if (run_mode == GIMP_RUN_INTERACTIVE)
        gimp_set_data (PLUG_IN_PROC, &pcvals, sizeof (polarize_vals_t));
    }
  else if (status == GIMP_PDB_SUCCESS)
    status = GIMP_PDB_EXECUTION_ERROR;

  values[0].data.d_status = status;

  gimp_drawable_detach (drawable);
}
Beispiel #14
0
guint
gimp_channel_height (gint32 channel_ID)
{
  return gimp_drawable_height (channel_ID);
}
Beispiel #15
0
static void
compute_preview (gint startx, gint starty, gint w, gint h)
{
  gint xcnt, ycnt, f1, f2;
  gdouble imagex, imagey;
  gint32 index = 0;
  GimpRGB color;
  GimpRGB lightcheck, darkcheck;
  GimpVector3 pos;
  get_ray_func ray_func;

  if (xpostab_size != w)
    {
      if (xpostab)
        {
          g_free (xpostab);
          xpostab = NULL;
        }
    }

  if (!xpostab)
    {
      xpostab = g_new (gdouble, w);
      xpostab_size = w;
    }

  if (ypostab_size != h)
    {
      if (ypostab)
        {
          g_free (ypostab);
          ypostab = NULL;
        }
    }

  if (!ypostab)
    {
      ypostab = g_new (gdouble, h);
      ypostab_size = h;
    }

  for (xcnt = 0; xcnt < w; xcnt++)
    xpostab[xcnt] = (gdouble) width *((gdouble) xcnt / (gdouble) w);
  for (ycnt = 0; ycnt < h; ycnt++)
    ypostab[ycnt] = (gdouble) height *((gdouble) ycnt / (gdouble) h);

  precompute_init (width, height);

  gimp_rgba_set (&lightcheck,
                 GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT,
                 1.0);
  gimp_rgba_set (&darkcheck, GIMP_CHECK_DARK, GIMP_CHECK_DARK,
                 GIMP_CHECK_DARK, 1.0);

  if (mapvals.bump_mapped == TRUE && mapvals.bumpmap_id != -1)
    {
      gimp_pixel_rgn_init (&bump_region,
                           gimp_drawable_get (mapvals.bumpmap_id),
                           0, 0, width, height, FALSE, FALSE);
    }

  imagey = 0;

  if (mapvals.previewquality)
    ray_func = get_ray_color;
  else
    ray_func = get_ray_color_no_bilinear;

  if (mapvals.env_mapped == TRUE && mapvals.envmap_id != -1)
    {
      env_width = gimp_drawable_width (mapvals.envmap_id);
      env_height = gimp_drawable_height (mapvals.envmap_id);

      gimp_pixel_rgn_init (&env_region,
                           gimp_drawable_get (mapvals.envmap_id), 0,
                           0, env_width, env_height, FALSE, FALSE);

      if (mapvals.previewquality)
        ray_func = get_ray_color_ref;
      else
        ray_func = get_ray_color_no_bilinear_ref;
    }

  for (ycnt = 0; ycnt < PREVIEW_HEIGHT; ycnt++)
    {
      for (xcnt = 0; xcnt < PREVIEW_WIDTH; xcnt++)
        {
          if ((ycnt >= starty && ycnt < (starty + h)) &&
              (xcnt >= startx && xcnt < (startx + w)))
            {
              imagex = xpostab[xcnt - startx];
              imagey = ypostab[ycnt - starty];
              pos = int_to_posf (imagex, imagey);

              if (mapvals.bump_mapped == TRUE &&
                  mapvals.bumpmap_id != -1 &&
                  xcnt == startx)
                {
                  pos_to_float (pos.x, pos.y, &imagex, &imagey);
                  precompute_normals (0, width, RINT (imagey));
                }

              color = (*ray_func) (&pos);

              if (color.a < 1.0)
                {
                  f1 = ((xcnt % 32) < 16);
                  f2 = ((ycnt % 32) < 16);
                  f1 = f1 ^ f2;

                  if (f1)
                    {
                      if (color.a == 0.0)
                        color = lightcheck;
                      else
                        gimp_rgb_composite (&color,
                                            &lightcheck,
                                            GIMP_RGB_COMPOSITE_BEHIND);
                    }
                  else
                    {
                      if (color.a == 0.0)
                        color = darkcheck;
                      else
                        gimp_rgb_composite (&color,
                                            &darkcheck,
                                            GIMP_RGB_COMPOSITE_BEHIND);
                    }
                }

              gimp_rgb_get_uchar (&color,
                                  preview_rgb_data + index,
                                  preview_rgb_data + index +
                                  1,
                                  preview_rgb_data + index +
                                  2);
              index += 3;
              imagex++;
            }
          else
            {
              preview_rgb_data[index++] = 200;
              preview_rgb_data[index++] = 200;
              preview_rgb_data[index++] = 200;
            }
        }
    }
}
Beispiel #16
0
static void
ico_dialog_update_icon_preview (GtkWidget *dialog,
                                gint32     layer,
                                gint       bpp)
{
  GtkWidget *preview = ico_dialog_get_layer_preview (dialog, layer);
  GdkPixbuf *pixbuf;
  gint       w       = gimp_drawable_width (layer);
  gint       h       = gimp_drawable_height (layer);

  if (! preview)
    return;

  if (bpp <= 8)
    {
      GimpDrawable *drawable;
      GimpDrawable *tmp;
      GimpPixelRgn  src_pixel_rgn, dst_pixel_rgn;
      gint32        image;
      gint32        tmp_image;
      gint32        tmp_layer;
      guchar       *buffer;
      guchar       *cmap;
      gint          num_colors;

      image = gimp_item_get_image (layer);

      tmp_image = gimp_image_new (w, h, gimp_image_base_type (image));
      gimp_image_undo_disable (tmp_image);

      if (gimp_drawable_is_indexed (layer))
        {
          cmap = gimp_image_get_colormap (image, &num_colors);
          gimp_image_set_colormap (tmp_image, cmap, num_colors);
          g_free (cmap);
        }

      tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h,
                                  gimp_drawable_type (layer),
                                  100, GIMP_NORMAL_MODE);
      gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0);

      drawable = gimp_drawable_get (layer);
      tmp      = gimp_drawable_get (tmp_layer);

      gimp_pixel_rgn_init (&src_pixel_rgn, drawable, 0, 0, w, h, FALSE, FALSE);
      gimp_pixel_rgn_init (&dst_pixel_rgn, tmp,      0, 0, w, h, TRUE, FALSE);

      buffer = g_malloc (w * h * 4);
      gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h);
      gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);

      gimp_drawable_detach (tmp);
      gimp_drawable_detach (drawable);

      if (gimp_drawable_is_indexed (layer))
        gimp_image_convert_rgb (tmp_image);

      gimp_image_convert_indexed (tmp_image,
                                  GIMP_FS_DITHER, GIMP_MAKE_PALETTE,
                                  1 <<bpp, TRUE, FALSE, "dummy");

      cmap = gimp_image_get_colormap (tmp_image, &num_colors);
      if ( num_colors == (1 << bpp) &&
           !ico_cmap_contains_black (cmap, num_colors))
        {
          /* Windows icons with color maps need the color black.
           * We need to eliminate one more color to make room for black.
           */
          if (gimp_drawable_is_indexed (layer))
            {
              g_free (cmap);
              cmap = gimp_image_get_colormap (image, &num_colors);
              gimp_image_set_colormap (tmp_image, cmap, num_colors);
            }
          else if (gimp_drawable_is_gray (layer))
            {
              gimp_image_convert_grayscale (tmp_image);
            }
          else
            {
              gimp_image_convert_rgb (tmp_image);
            }

          tmp = gimp_drawable_get (tmp_layer);
          gimp_pixel_rgn_init (&dst_pixel_rgn,
                               tmp, 0, 0, w, h, TRUE, FALSE);
          gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
          gimp_drawable_detach (tmp);

          if (!gimp_drawable_is_rgb (layer))
            gimp_image_convert_rgb (tmp_image);

          gimp_image_convert_indexed (tmp_image,
                                      GIMP_FS_DITHER, GIMP_MAKE_PALETTE,
                                      (1<<bpp) - 1, TRUE, FALSE, "dummy");
        }
      g_free (cmap);
      g_free (buffer);

      pixbuf = gimp_drawable_get_thumbnail (tmp_layer,
                                            MIN (w, 128), MIN (h, 128),
                                            GIMP_PIXBUF_SMALL_CHECKS);

      gimp_image_delete (tmp_image);
    }
  else if (bpp == 24)
    {
      GimpDrawable *drawable;
      GimpDrawable *tmp;
      GimpPixelRgn  src_pixel_rgn, dst_pixel_rgn;
      gint32        image;
      gint32        tmp_image;
      gint32        tmp_layer;
      guchar       *buffer;
      GimpParam    *return_vals;
      gint          n_return_vals;

      image = gimp_item_get_image (layer);

      tmp_image = gimp_image_new (w, h, gimp_image_base_type (image));
      gimp_image_undo_disable (tmp_image);

      if (gimp_drawable_is_indexed (layer))
        {
          guchar *cmap;
          gint    num_colors;

          cmap = gimp_image_get_colormap (image, &num_colors);
          gimp_image_set_colormap (tmp_image, cmap, num_colors);
          g_free (cmap);
        }

      tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h,
                                  gimp_drawable_type (layer),
                                  100, GIMP_NORMAL_MODE);
      gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0);

      drawable = gimp_drawable_get (layer);
      tmp      = gimp_drawable_get (tmp_layer);

      gimp_pixel_rgn_init (&src_pixel_rgn, drawable, 0, 0, w, h, FALSE, FALSE);
      gimp_pixel_rgn_init (&dst_pixel_rgn, tmp,      0, 0, w, h, TRUE, FALSE);

      buffer = g_malloc (w * h * 4);
      gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h);
      gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h);
      g_free (buffer);

      gimp_drawable_detach (tmp);
      gimp_drawable_detach (drawable);

      if (gimp_drawable_is_indexed (layer))
        gimp_image_convert_rgb (tmp_image);

      return_vals =
        gimp_run_procedure ("plug-in-threshold-alpha", &n_return_vals,
                            GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE,
                            GIMP_PDB_IMAGE, tmp_image,
                            GIMP_PDB_DRAWABLE, tmp_layer,
                            GIMP_PDB_INT32, ICO_ALPHA_THRESHOLD,
                            GIMP_PDB_END);
      gimp_destroy_params (return_vals, n_return_vals);

      pixbuf = gimp_drawable_get_thumbnail (tmp_layer,
                                            MIN (w, 128), MIN (h, 128),
                                            GIMP_PIXBUF_SMALL_CHECKS);

      gimp_image_delete (tmp_image);
    }
  else
    {
      pixbuf = gimp_drawable_get_thumbnail (layer,
                                            MIN (w, 128), MIN (h, 128),
                                            GIMP_PIXBUF_SMALL_CHECKS);
    }

  gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
  g_object_unref (pixbuf);
}
Beispiel #17
0
static gboolean
ico_write_png (FILE   *fp,
               gint32  layer,
               gint32  depth)
{
  png_structp png_ptr;
  png_infop   info_ptr;
  png_byte  **row_pointers;
  gint        i, rowstride;
  gint        width, height;
  gint        num_colors_used;
  guchar     *palette;
  guchar     *buf;

  row_pointers = NULL;
  palette = NULL;
  buf = NULL;

  width = gimp_drawable_width (layer);
  height = gimp_drawable_height (layer);

  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if ( !png_ptr )
    return FALSE;

  info_ptr = png_create_info_struct (png_ptr);
  if ( !info_ptr )
    {
      png_destroy_write_struct (&png_ptr, NULL);
      return FALSE;
    }

  if (setjmp (png_jmpbuf (png_ptr)))
    {
      png_destroy_write_struct (&png_ptr, &info_ptr);
      if ( row_pointers )
        g_free (row_pointers);
      if (palette)
        g_free (palette);
      if (buf)
        g_free (buf);
      return FALSE;
    }

  ico_image_get_reduced_buf (layer, depth, &num_colors_used,
                             &palette, &buf);

  png_init_io (png_ptr, fp);
  png_set_IHDR (png_ptr, info_ptr, width, height,
                8,
                PNG_COLOR_TYPE_RGBA,
                PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_DEFAULT,
                PNG_FILTER_TYPE_DEFAULT);
  png_write_info (png_ptr, info_ptr);

  rowstride = ico_rowstride (width, 32);
  row_pointers = g_new (png_byte*, height);
  for (i = 0; i < height; i++)
    {
      row_pointers[i] = buf + rowstride * i;
    }
  png_write_image (png_ptr, row_pointers);

  row_pointers = NULL;

  png_write_end (png_ptr, info_ptr);
  png_destroy_write_struct (&png_ptr, &info_ptr);

  g_free (row_pointers);
  g_free (palette);
  g_free (buf);
  return TRUE;
}
Beispiel #18
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam values[1];
  gint sel_x1, sel_y1, sel_x2, sel_y2;
  gint img_height, img_width, img_bpp, img_has_alpha;

  GimpDrawable      *drawable;
  GimpRunMode        run_mode;
  GimpPDBStatusType  status;

  *nreturn_vals = 1;
  *return_vals  = values;

  status = GIMP_PDB_SUCCESS;

  if (param[0].type != GIMP_PDB_INT32)
    status = GIMP_PDB_CALLING_ERROR;
  run_mode = param[0].data.d_int32;

  INIT_I18N ();

  if (param[2].type != GIMP_PDB_DRAWABLE)
    status = GIMP_PDB_CALLING_ERROR;

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

  img_width = gimp_drawable_width (drawable->drawable_id);
  img_height = gimp_drawable_height (drawable->drawable_id);
  img_bpp = gimp_drawable_bpp (drawable->drawable_id);
  img_has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
  gimp_drawable_mask_bounds (drawable->drawable_id,
                             &sel_x1, &sel_y1, &sel_x2, &sel_y2);

  if (!gimp_drawable_is_rgb (drawable->drawable_id))
    status = GIMP_PDB_CALLING_ERROR;

  if (status == GIMP_PDB_SUCCESS)
    {
      gr = g_rand_new ();

      memset (&qbist_info, 0, sizeof (qbist_info));
      create_info (&qbist_info.info);
      qbist_info.oversampling = 4;

      switch (run_mode)
        {
        case GIMP_RUN_INTERACTIVE:
          /* Possibly retrieve data */
          gimp_get_data (PLUG_IN_PROC, &qbist_info);

          /* Get information from the dialog */
          if (dialog_run ())
            {
              status = GIMP_PDB_SUCCESS;
              gimp_set_data (PLUG_IN_PROC, &qbist_info, sizeof (QbistInfo));
            }
          else
            status = GIMP_PDB_EXECUTION_ERROR;
          break;

        case GIMP_RUN_NONINTERACTIVE:
          status = GIMP_PDB_CALLING_ERROR;
          break;

        case GIMP_RUN_WITH_LAST_VALS:
          /* Possibly retrieve data */
          gimp_get_data (PLUG_IN_PROC, &qbist_info);
          status = GIMP_PDB_SUCCESS;
          break;

        default:
          status = GIMP_PDB_CALLING_ERROR;
          break;
        }

      if (status == GIMP_PDB_SUCCESS)
        {
          GimpPixelRgn imagePR;
          gpointer     pr;

          gimp_tile_cache_ntiles ((drawable->width + gimp_tile_width () - 1) /
                                  gimp_tile_width ());
          gimp_pixel_rgn_init (&imagePR, drawable,
                               0, 0, img_width, img_height, TRUE, TRUE);

          optimize (&qbist_info.info);

          gimp_progress_init (_("Qbist"));

          for (pr = gimp_pixel_rgns_register (1, &imagePR);
               pr != NULL;
               pr = gimp_pixel_rgns_process (pr))
            {
              gint row;

              for (row = 0; row < imagePR.h; row++)
                {
                  qbist (&qbist_info.info,
                         imagePR.data + row * imagePR.rowstride,
                         imagePR.x,
                         imagePR.y + row,
                         imagePR.w,
                         sel_x2 - sel_x1,
                         sel_y2 - sel_y1,
                         imagePR.bpp,
                         qbist_info.oversampling);
                }

              gimp_progress_update ((gfloat) (imagePR.y - sel_y1) /
                                    (gfloat) (sel_y2 - sel_y1));
            }

          gimp_drawable_flush (drawable);
          gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
          gimp_drawable_update (drawable->drawable_id,
                                sel_x1, sel_y1,
                                (sel_x2 - sel_x1), (sel_y2 - sel_y1));

          gimp_displays_flush ();
        }

      g_rand_free (gr);
    }

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

  gimp_drawable_detach (drawable);
}
Beispiel #19
0
static gboolean
ico_write_icon (FILE   *fp,
                gint32  layer,
                gint32  depth)
{
  IcoFileDataHeader  header;
  gint               and_len, xor_len, palette_index, x, y;
  gint               num_colors = 0, num_colors_used = 0, black_index = 0;
  gint               width, height;
  guchar            *buf = NULL, *pixel;
  guint32           *buf32;
  guchar            *palette;
  GHashTable        *color_to_slot = NULL;
  guchar            *xor_map, *and_map;

  guint32           *palette32 = NULL;
  gint               palette_len = 0;

  D(("Creating data structures for icon %i ------------------------\n",
     num_icon));

  width = gimp_drawable_width (layer);
  height = gimp_drawable_height (layer);

  header.header_size     = 40;
  header.width          = width;
  header.height         = 2 * height;
  header.planes         = 1;
  header.bpp            = depth;
  header.compression    = 0;
  header.image_size     = 0;
  header.x_res          = 0;
  header.y_res          = 0;
  header.used_clrs      = 0;
  header.important_clrs = 0;

  num_colors = (1L << header.bpp);

  D(("  header size %i, w %i, h %i, planes %i, bpp %i\n",
     header.header_size, header.width, header.height, header.planes,
     header.bpp));

  /* Reduce colors in copy of image */
  ico_image_get_reduced_buf (layer, header.bpp, &num_colors_used,
                             &palette, &buf);
  buf32 = (guint32 *) buf;

  /* Set up colormap and and_map when necessary: */
  if (header.bpp <= 8)
    {
      /* Create a colormap */
      palette32 = ico_create_palette (palette,
                                      num_colors, num_colors_used,
                                      &black_index);
      palette_len = num_colors * 4;

      color_to_slot = ico_create_color_to_palette_map (palette32,
                                                       num_colors_used);
      D(("  created %i-slot colormap with %i colors, black at slot %i\n",
         num_colors, num_colors_used, black_index));
    }

  /* Create and_map. It's padded out to 32 bits per line: */
  and_map = ico_alloc_map (width, height, 1, &and_len);

  for (y = 0; y < height; y++)
    for (x = 0; x < width; x++)
      {
        pixel = (guint8 *) &buf32[y * width + x];

        ico_set_bit_in_data (and_map, width,
                             (height - y -1) * width + x,
                             (pixel[3] > ICO_ALPHA_THRESHOLD ? 0 : 1));
      }

  xor_map = ico_alloc_map (width, height, header.bpp, &xor_len);

  /* Now fill in the xor map */
  switch (header.bpp)
    {
    case 1:
      for (y = 0; y < height; y++)
        for (x = 0; x < width; x++)
          {
            pixel = (guint8 *) &buf32[y * width + x];
            palette_index = ico_get_palette_index (color_to_slot, pixel[0],
                                                   pixel[1], pixel[2]);

            if (ico_get_bit_from_data (and_map, width,
                                       (height - y - 1) * width + x))
              {
                ico_set_bit_in_data (xor_map, width,
                                     (height - y -1) * width + x,
                                     black_index);
              }
            else
              {
                ico_set_bit_in_data (xor_map, width,
                                     (height - y -1) * width + x,
                                     palette_index);
              }
          }
      break;

    case 4:
      for (y = 0; y < height; y++)
        for (x = 0; x < width; x++)
          {
            pixel = (guint8 *) &buf32[y * width + x];
            palette_index = ico_get_palette_index(color_to_slot, pixel[0],
                                                  pixel[1], pixel[2]);

            if (ico_get_bit_from_data (and_map, width,
                                       (height - y - 1) * width + x))
              {
                ico_set_nibble_in_data (xor_map, width,
                                        (height - y -1) * width + x,
                                        black_index);
              }
            else
              {
                ico_set_nibble_in_data (xor_map, width,
                                        (height - y - 1) * width + x,
                                        palette_index);
              }
          }
      break;

    case 8:
      for (y = 0; y < height; y++)
        for (x = 0; x < width; x++)
          {
            pixel = (guint8 *) &buf32[y * width + x];
            palette_index = ico_get_palette_index (color_to_slot,
                                                   pixel[0],
                                                   pixel[1],
                                                   pixel[2]);

            if (ico_get_bit_from_data (and_map, width,
                                       (height - y - 1) * width + x))
              {
                ico_set_byte_in_data (xor_map, width,
                                      (height - y - 1) * width + x,
                                      black_index);
              }
            else
              {
                ico_set_byte_in_data (xor_map, width,
                                      (height - y - 1) * width + x,
                                      palette_index);
              }

          }
      break;

    case 24:
      for (y = 0; y < height; y++)
        {
          guchar *row = xor_map + (xor_len * (height - y - 1) / height);

          for (x = 0; x < width; x++)
            {
              pixel = (guint8 *) &buf32[y * width + x];

              row[0] = pixel[2];
              row[1] = pixel[1];
              row[2] = pixel[0];

              row += 3;
            }
        }
      break;

    default:
      for (y = 0; y < height; y++)
        for (x = 0; x < width; x++)
          {
            pixel = (guint8 *) &buf32[y * width + x];

            ((guint32 *) xor_map)[(height - y -1) * width + x] =
              GUINT32_TO_LE ((pixel[0] << 16) |
                             (pixel[1] << 8)  |
                             (pixel[2])       |
                             (pixel[3] << 24));
          }
    }

  D(("  filled and_map of length %i, xor_map of length %i\n",
     and_len, xor_len));

  if (color_to_slot)
    g_hash_table_destroy (color_to_slot);

  g_free (palette);
  g_free (buf);

  ico_write_int32 (fp, (guint32*) &header, 3);
  ico_write_int16 (fp, &header.planes, 2);
  ico_write_int32 (fp, &header.compression, 6);

  if (palette_len)
    ico_write_int8 (fp, (guint8 *) palette32, palette_len);

  ico_write_int8 (fp, xor_map, xor_len);
  ico_write_int8 (fp, and_map, and_len);

  g_free (palette32);
  g_free (xor_map);
  g_free (and_map);

  return TRUE;
}
Beispiel #20
0
static gint32
tile (gint32  image_id,
      gint32  drawable_id,
      gint32 *layer_id)
{
  GimpPixelRgn       src_rgn;
  GimpPixelRgn       dest_rgn;
  GimpDrawable      *drawable;
  GimpDrawable      *new_layer;
  GimpImageBaseType  image_type   = GIMP_RGB;
  gint32             new_image_id = 0;
  gint               old_width;
  gint               old_height;
  gint               i, j;
  gint               progress;
  gint               max_progress;
  gpointer           pr;

  /* sanity check parameters */
  if (tvals.new_width < 1 || tvals.new_height < 1)
    {
      *layer_id = -1;
      return -1;
    }

  /* initialize */
  old_width  = gimp_drawable_width  (drawable_id);
  old_height = gimp_drawable_height (drawable_id);

  if (tvals.new_image)
    {
      /*  create  a new image  */
      switch (gimp_drawable_type (drawable_id))
        {
        case GIMP_RGB_IMAGE:
        case GIMP_RGBA_IMAGE:
          image_type = GIMP_RGB;
          break;

        case GIMP_GRAY_IMAGE:
        case GIMP_GRAYA_IMAGE:
          image_type = GIMP_GRAY;
          break;

        case GIMP_INDEXED_IMAGE:
        case GIMP_INDEXEDA_IMAGE:
          image_type = GIMP_INDEXED;
          break;
        }

      new_image_id = gimp_image_new (tvals.new_width, tvals.new_height,
                                     image_type);
      gimp_image_undo_disable (new_image_id);

      *layer_id = gimp_layer_new (new_image_id, _("Background"),
                                  tvals.new_width, tvals.new_height,
                                  gimp_drawable_type (drawable_id),
                                  100, GIMP_NORMAL_MODE);

      if (*layer_id == -1)
        return -1;

      gimp_image_insert_layer (new_image_id, *layer_id, -1, 0);
      new_layer = gimp_drawable_get (*layer_id);

      /*  Get the source drawable  */
      drawable = gimp_drawable_get (drawable_id);
    }
  else
    {
      gimp_image_undo_group_start (image_id);

      gimp_image_resize (image_id,
                         tvals.new_width, tvals.new_height,
                         0, 0);

      if (gimp_item_is_layer (drawable_id))
        gimp_layer_resize (drawable_id,
                           tvals.new_width, tvals.new_height,
                           0, 0);

      /*  Get the source drawable  */
      drawable = gimp_drawable_get (drawable_id);
      new_layer = drawable;
    }

  /*  progress  */
  progress = 0;
  max_progress = tvals.new_width * tvals.new_height;

  /*  tile...  */
  for (i = 0; i < tvals.new_height; i += old_height)
    {
      gint height = old_height;

      if (height + i > tvals.new_height)
        height = tvals.new_height - i;

      for (j = 0; j < tvals.new_width; j += old_width)
        {
          gint width = old_width;
          gint c;

          if (width + j > tvals.new_width)
            width = tvals.new_width - j;

          gimp_pixel_rgn_init (&src_rgn, drawable,
                               0, 0, width, height, FALSE, FALSE);
          gimp_pixel_rgn_init (&dest_rgn, new_layer,
                               j, i, width, height, TRUE, FALSE);

          for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn), c = 0;
               pr != NULL;
               pr = gimp_pixel_rgns_process (pr), c++)
            {
              gint k;

              for (k = 0; k < src_rgn.h; k++)
                memcpy (dest_rgn.data + k * dest_rgn.rowstride,
                        src_rgn.data + k * src_rgn.rowstride,
                        src_rgn.w * src_rgn.bpp);

              progress += src_rgn.w * src_rgn.h;

              if (c % 16 == 0)
                gimp_progress_update ((gdouble) progress /
                                      (gdouble) max_progress);
            }
        }
    }

  gimp_drawable_update (new_layer->drawable_id,
                        0, 0, new_layer->width, new_layer->height);

  gimp_drawable_detach (drawable);

  if (tvals.new_image)
    {
      gimp_drawable_detach (new_layer);

      /*  copy the colormap, if necessary  */
      if (image_type == GIMP_INDEXED)
        {
          guchar *cmap;
          gint    ncols;

          cmap = gimp_image_get_colormap (image_id, &ncols);
          gimp_image_set_colormap (new_image_id, cmap, ncols);
          g_free (cmap);
        }

      gimp_image_undo_enable (new_image_id);
    }
  else
    {
      gimp_image_undo_group_end (image_id);
    }

  return new_image_id;
}
Beispiel #21
0
gint
guess_new_size (GtkWidget * button, PreviewData * p_data, GuessDir direction)
{
  gint32 disc_layer_ID;
  GimpDrawable *drawable;
  gint z1, z2, k;
  gint z1min, z1max, z2max;
  gint width, height;
  gint lw, lh;
  gint x_off, y_off;
  gint bpp, c_bpp;
  GimpPixelRgn rgn_in;
  guchar *line;
  gboolean has_alpha;
  gdouble sum;
  gint mask_size;
  gint max_mask_size = 0;
  gint old_size;
  gint new_size;

  disc_layer_ID = p_data->vals->disc_layer_ID;
  switch (direction)
    {
      case GUESS_DIR_HOR:
        old_size = p_data->old_width;
        break;
      case GUESS_DIR_VERT:
        old_size = p_data->old_height;
        break;
      default:
        g_message("You just found a bug");
        return 0;
    }

  LAYER_CHECK_ACTION(disc_layer_ID, gtk_dialog_response (GTK_DIALOG (dlg), RESPONSE_REFRESH), old_size);

  width = gimp_drawable_width (disc_layer_ID);
  height = gimp_drawable_height (disc_layer_ID);
  has_alpha = gimp_drawable_has_alpha (disc_layer_ID);
  bpp = gimp_drawable_bpp (disc_layer_ID);
  c_bpp = bpp - (has_alpha ? 1 : 0);

  drawable = gimp_drawable_get (disc_layer_ID);
  gimp_pixel_rgn_init (&rgn_in, drawable, 0, 0, width, height, FALSE, FALSE);


  gimp_drawable_offsets (disc_layer_ID, &x_off, &y_off);

  x_off -= p_data->x_off;
  y_off -= p_data->y_off;

  lw = (MIN (p_data->old_width, width + x_off) - MAX (0, x_off));
  lh = (MIN (p_data->old_height, height + y_off) - MAX (0, y_off));

  switch (direction)
    {
      case GUESS_DIR_HOR:
        z1min = MAX (0, y_off);
        z1max = MIN (p_data->old_height, height + y_off);
        z2max = lw;
        break;
      case GUESS_DIR_VERT:
        z1min = MAX (0, x_off);
        z1max = MIN (p_data->old_width, width + x_off);
        z2max = lh;
        break;
      default:
        g_message("You just found a bug");
        return 0;
    }

  line = g_try_new (guchar, bpp * z2max);

  for (z1 = z1min; z1 < z1max; z1++)
    {
      switch (direction)
        {
          case GUESS_DIR_HOR:
            gimp_pixel_rgn_get_row (&rgn_in, line, MAX (0, -x_off), z1 - y_off, z2max);
            break;
          case GUESS_DIR_VERT:
            gimp_pixel_rgn_get_col (&rgn_in, line, z1 - x_off, MAX (0, -y_off), z2max);
            break;
        }

      mask_size = 0;
      for (z2 = 0; z2 < z2max; z2++)
	{
	  sum = 0;
	  for (k = 0; k < c_bpp; k++)
	    {
	      sum += line[bpp * z2 + k];
	    }

	  sum /= (255 * c_bpp);
	  if (has_alpha)
	    {
	      sum *= (gdouble) line[bpp * (z2 + 1) - 1] / 255;
	    }

	  if (sum >= (0.5 / c_bpp))
	    {
	      mask_size++;
	    }
	}
      if (mask_size > max_mask_size)
	{
	  max_mask_size = mask_size;
	}

    }

  new_size = old_size - max_mask_size;

  g_free (line);
  gimp_drawable_detach (drawable);

  return new_size;
}
Beispiel #22
0
static void
edge (GimpDrawable *drawable)
{
  GimpPixelRgn      src_rgn, dest_rgn;
  gpointer          pr;
  GimpPixelFetcher *pft;
  guchar           *srcrow, *src;
  guchar           *destrow, *dest;
  guchar            pix00[4], pix01[4], pix02[4];
  guchar            pix10[4], pix11[4], pix12[4];
  guchar            pix20[4], pix21[4], pix22[4];
  glong             width, height;
  gint              alpha;
  gboolean          has_alpha;
  gint              chan;
  gint              x, y;
  gint              x1, y1, x2, y2;
  gint              maxval;
  gint              cur_progress;
  gint              max_progress;
  gdouble           per_progress;

  if (evals.amount < 1.0)
    evals.amount = 1.0;

  pft = gimp_pixel_fetcher_new (drawable, FALSE);
  gimp_pixel_fetcher_set_edge_mode (pft, evals.wrapmode);

  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

  width     = gimp_drawable_width (drawable->drawable_id);
  height    = gimp_drawable_height (drawable->drawable_id);
  alpha     = gimp_drawable_bpp (drawable->drawable_id);
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
  if (has_alpha)
    alpha--;

  maxval = 255;

  cur_progress = 0;
  per_progress = 0.0;
  max_progress = (x2 - x1) * (y2 - y1) / 100;

  gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, x2-x1, y2-y1, FALSE, FALSE);
  gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, x2-x1, y2-y1, TRUE, TRUE);

  for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn);
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr))
    {
      srcrow  = src_rgn.data;
      destrow = dest_rgn.data;

      for (y = dest_rgn.y;
           y < (dest_rgn.y + dest_rgn.h);
           y++, srcrow += src_rgn.rowstride, destrow += dest_rgn.rowstride)
        {
          src  = srcrow;
          dest = destrow;

          for (x = dest_rgn.x;
               x < (dest_rgn.x + dest_rgn.w);
               x++,  src += src_rgn.bpp, dest += dest_rgn.bpp)
            {
              if (dest_rgn.x < x &&  x < dest_rgn.x + dest_rgn.w - 2 &&
                  dest_rgn.y < y &&  y < dest_rgn.y + dest_rgn.h - 2)
                {
                  /*
                   * 3x3 kernel is inside of the tile -- do fast
                   * version
                   */
                  for (chan = 0; chan < alpha; chan++)
                    {
                      /* get the 3x3 kernel into a guchar array,
                       * and send it to edge_detect */
                      guchar kernel[9];
                      gint   i,j;

#define PIX(X,Y)  src[ (Y-1)*(int)src_rgn.rowstride + (X-1)*(int)src_rgn.bpp + chan ]
                      /* make convolution */
                      for(i = 0; i < 3; i++)
                        for(j = 0; j < 3; j++)
                          kernel[3*i + j] = PIX(i,j);

#undef  PIX

                      dest[chan] = edge_detect (kernel);
                    }
                }
              else
                {
                  /*
                   * The kernel is not inside of the tile -- do slow
                   * version
                   */

                  gimp_pixel_fetcher_get_pixel (pft, x-1, y-1, pix00);
                  gimp_pixel_fetcher_get_pixel (pft, x  , y-1, pix10);
                  gimp_pixel_fetcher_get_pixel (pft, x+1, y-1, pix20);
                  gimp_pixel_fetcher_get_pixel (pft, x-1, y  , pix01);
                  gimp_pixel_fetcher_get_pixel (pft, x  , y  , pix11);
                  gimp_pixel_fetcher_get_pixel (pft, x+1, y  , pix21);
                  gimp_pixel_fetcher_get_pixel (pft, x-1, y+1, pix02);
                  gimp_pixel_fetcher_get_pixel (pft, x  , y+1, pix12);
                  gimp_pixel_fetcher_get_pixel (pft, x+1, y+1, pix22);

                  for (chan = 0; chan < alpha; chan++)
                    {
                      guchar kernel[9];

                      kernel[0] = pix00[chan];
                      kernel[1] = pix01[chan];
                      kernel[2] = pix02[chan];
                      kernel[3] = pix10[chan];
                      kernel[4] = pix11[chan];
                      kernel[5] = pix12[chan];
                      kernel[6] = pix20[chan];
                      kernel[7] = pix21[chan];
                      kernel[8] = pix22[chan];

                      dest[chan] = edge_detect (kernel);
                    }
                }
              if (has_alpha)
                dest[alpha] = src[alpha];
            }
        }
      cur_progress += dest_rgn.w * dest_rgn.h;

      if (cur_progress > max_progress)
        {
          cur_progress = cur_progress - max_progress;
          per_progress = per_progress + 0.01;
          gimp_progress_update (per_progress);
        }
    }

  gimp_progress_update (1.0);

  gimp_pixel_fetcher_destroy (pft);

  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));
}
static gboolean apply_watermark(watermark_settings settings, image_output out) 
{
    gboolean success = TRUE;
    gint32 layerId;
    gdouble posX, posY;
    gint wmwidth, wmheight, wmasc, wmdesc;
    
    if (settings->mode) {
        if (strlen(settings->text) == 0) {
            return TRUE;
        }
        
        GimpRGB old_foreground, new_foreground;
        
        gimp_context_get_foreground(&old_foreground);
        gimp_rgb_parse_hex (&new_foreground, gdk_color_to_string(&(settings->color)), strlen(gdk_color_to_string(&(settings->color))));
        gimp_context_set_foreground(&new_foreground);
        
        gimp_text_get_extents_fontname(
            settings->text,
            pango_font_description_get_size(settings->font) / PANGO_SCALE,
            GIMP_PIXELS,
            pango_font_description_get_family(settings->font),
            &wmwidth,
            &wmheight,
            &wmasc,
            &wmdesc
        );

        if (settings->position == WM_POS_TL) {
            posX = 10;
            posY = 5;
        }
        else if (settings->position == WM_POS_TC) {
            posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2);
            posY = 5;
        }
        else if (settings->position == WM_POS_TR) {
            posX = gimp_image_width(out->image_id) - wmwidth - 10;
            posY = 5;
        }
        else if (settings->position == WM_POS_BL) {
            posX = 10;
            posY = gimp_image_height(out->image_id) - wmheight - 5;
        }
        else if (settings->position == WM_POS_BC) {
            posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2);
            posY = gimp_image_height(out->image_id) - wmheight - 5;
        }
        else if (settings->position == WM_POS_BR) {
            posX = gimp_image_width(out->image_id) - wmwidth - 10;
            posY = gimp_image_height(out->image_id) - wmheight - 5;
        }
        else if (settings->position == WM_POS_CL) {
            posX = 10;
            posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2);
        }
        else if (settings->position == WM_POS_CR) {
            posX = gimp_image_width(out->image_id) - wmwidth - 10;
            posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2);
        }
        else {
            posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2);
            posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2);
        }
        
        layerId = gimp_text_fontname(
            out->image_id,
            -1,
            posX,
            posY,
            settings->text,
            -1,
            TRUE,
            pango_font_description_get_size(settings->font) / PANGO_SCALE,
            GIMP_PIXELS,
            pango_font_description_get_family(settings->font)
        );
        gimp_context_set_foreground(&old_foreground);
        gimp_layer_set_opacity(layerId, settings->opacity);
    }
    else {
        if (!g_file_test(settings->image_file, G_FILE_TEST_IS_REGULAR)) {//((access(settings->image_file, R_OK) == -1)) {
            // error, can't access image file
            return TRUE;
        }
        
        layerId = gimp_file_load_layer(
            GIMP_RUN_NONINTERACTIVE,
            out->image_id,
            settings->image_file
        );
        
        gimp_layer_set_opacity(layerId, settings->opacity);
        wmwidth = gimp_drawable_width(layerId);
        wmheight = gimp_drawable_height(layerId);
        
        #if USE_API26
        
            gimp_image_add_layer(
                out->image_id,
                layerId,
                0
            );
        
        #else
        
            // starting from 2.8, gimp_image_add_layer is deprecated. 
            // use gimp_image_insert_layer instead
            gimp_image_insert_layer(
                out->image_id,
                layerId,
                0,
                0
            );
            
        #endif
        
        if (settings->position == WM_POS_TL) {
            posX = 10;
            posY = 10;
        }
        else if (settings->position == WM_POS_TC) {
            posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2);
            posY = 10;
        }
        else if (settings->position == WM_POS_TR) {
            posX = gimp_image_width(out->image_id) - wmwidth - 10;
            posY = 10;
        }
        else if (settings->position == WM_POS_BL) {
            posX = 10;
            posY = gimp_image_height(out->image_id) - wmheight - 10;
        }
        else if (settings->position == WM_POS_BC) {
            posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2);
            posY = gimp_image_height(out->image_id) - wmheight - 10;
        }
        else if (settings->position == WM_POS_BR) {
            posX = gimp_image_width(out->image_id) - wmwidth - 10;
            posY = gimp_image_height(out->image_id) - wmheight - 10;
        }
        else if (settings->position == WM_POS_CL) {
            posX = 10;
            posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2);
        }
        else if (settings->position == WM_POS_CR) {
            posX = gimp_image_width(out->image_id) - wmwidth - 10;
            posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2);
        }
        else {
            posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2);
            posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2);
        }
        
        gimp_layer_set_offsets(
            layerId,
            posX,
            posY
        );   
    }
    
    // refresh all drawables
    g_free(out->drawable_ids);
    out->drawable_ids = gimp_image_get_layers(out->image_id, &out->drawable_count);
    
    return success;
}
gboolean dialog (
	PlugInVals         *vals,
	PlugInUIVals       *ui_vals)
{
  if (!gimp_drawable_is_valid(vals->image_drawable_id)) {
	  vals->image_drawable_id = default_vals.image_drawable_id;
  }
  if (!gimp_drawable_is_valid(vals->mask_drawable_id)) {
	  vals->mask_drawable_id = default_vals.mask_drawable_id;
  }
  if (!gimp_vectors_is_valid(vals->stop_path_id)) {
	  vals->stop_path_id = default_vals.stop_path_id;
  }
  vals->output_drawable_id = vals->image_drawable_id;

  print_vals(vals);
  set_defaults(ui_vals);
  interface_vals.imageID = gimp_drawable_get_image(vals->image_drawable_id);
  interface_vals.image_name = gimp_image_get_name(interface_vals.imageID);
  interface_vals.image_drawable = NULL;
  interface_vals.mask_drawable = NULL;
  if (vals->image_drawable_id >= 0) {
#ifdef DEBUG
	  g_warning("There is an input image drawable id");
#endif
	  interface_vals.image_drawable = gimp_drawable_get(vals->image_drawable_id);
  }
  if (vals->mask_drawable_id >= 0) {
	  interface_vals.mask_drawable = gimp_drawable_get(vals->mask_drawable_id);
  } else {
	  interface_vals.mask_drawable = NULL;
  }

  ui_state = ui_vals;

  //if there is a selection create mask drawable and fill

  gimp_drawable_mask_bounds(vals->image_drawable_id,&interface_vals.selectionX0,
		  	  	  	  	  	  	  	  	  	  	  	&interface_vals.selectionY0,
		  	  	  	  	  	  	  	  	  	  	  	&interface_vals.selectionX1,
		  	  	  	  	  	  	  	  		  	  	&interface_vals.selectionY1);
  interface_vals.selectionWidth = interface_vals.selectionX1-interface_vals.selectionX0;
  interface_vals.selectionHeight = interface_vals.selectionY1-interface_vals.selectionY0;

  gint image_width = gimp_drawable_width(vals->image_drawable_id);
  gint image_height = gimp_drawable_height(vals->image_drawable_id);

  interface_vals.selectionX0 -= PREVIEW_SIZE*0.1;
  if (interface_vals.selectionX0 < 0) interface_vals.selectionX0 = 0;
  interface_vals.selectionX1 += PREVIEW_SIZE*0.1;
  if (interface_vals.selectionX1 > image_width) interface_vals.selectionX1 = image_width;
  interface_vals.selectionY0 -= PREVIEW_SIZE*0.1;
  if (interface_vals.selectionY0 < 0) interface_vals.selectionY0 = 0;
  interface_vals.selectionY1 += PREVIEW_SIZE*0.1;
  if (interface_vals.selectionY1 > image_height) interface_vals.selectionY1 = image_height;

  interface_vals.selectionWidth = interface_vals.selectionX1-interface_vals.selectionX0;
  interface_vals.selectionHeight = interface_vals.selectionY1-interface_vals.selectionY0;

  //vals->mask_drawable_id = gimp_image_get_selection(gimp_drawable_get_image(vals->image_drawable_id));
  //g_warning("there is a selection with id = %d",vals->mask_drawable_id);
  //if (interface_vals.mask_drawable != NULL) gimp_drawable_detach(interface_vals.mask_drawable);
  //interface_vals.mask_drawable = gimp_drawable_get(vals->mask_drawable_id);


#ifdef DEBUG
  g_warning("image dims: x0,x1,y0,y1 = %d,%d,%d,%d",interface_vals.selectionX0,interface_vals.selectionX1,interface_vals.selectionY0,interface_vals.selectionY1);
#endif
  gchar text[100];
  sprintf(text,"Inpainting: %s",interface_vals.image_name);

  gimp_ui_init (PLUGIN_NAME, TRUE);

  GtkWidget* dlg = gimp_dialog_new (text, PLUGIN_NAME,
                         NULL, 0,
			 gimp_standard_help_func, "gimp-inpaint-BCT",

			 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
			 GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
			 GTK_STOCK_OK,     GTK_RESPONSE_OK,


			 NULL);

  gimp_window_set_transient (GTK_WINDOW (dlg));

  GtkWidget* vbox = gtk_vbox_new (FALSE, 10);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
		  vbox, FALSE, FALSE, 0);
  gtk_widget_show (vbox);

  /* Preview */
  GtkWidget* hbox = gtk_hbox_new (TRUE, 0);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  GtkWidget* frame = gtk_frame_new (NULL);
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame);

//  interface_vals.preview = TRUE;
//  interface_vals.preview_widget = GIMP_DRAWABLE_PREVIEW (gimp_drawable_preview_new(interface_vals.image_drawable,&interface_vals.preview));
//  gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (interface_vals.preview_widget));
//  gtk_widget_show (GTK_WIDGET (interface_vals.preview_widget));

  interface_vals.previewWidth  = MIN (interface_vals.selectionWidth,  PREVIEW_SIZE);
  interface_vals.previewHeight = MIN (interface_vals.selectionHeight, PREVIEW_SIZE);
  interface_vals.preview_widget = gimp_preview_area_new ();
  gtk_widget_set_size_request (interface_vals.preview_widget,
		  interface_vals.previewWidth, interface_vals.previewHeight);
  gtk_container_add (GTK_CONTAINER (frame), interface_vals.preview_widget);
  gtk_widget_show (interface_vals.preview_widget);

  buildPreviewSourceImage (vals);


  /* Source and Mask selection */
  GtkWidget* table = gtk_table_new (5, 3, FALSE);
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  //gtk_table_set_row_spacing (GTK_TABLE (table), 1, 12);
  //gtk_table_set_row_spacing (GTK_TABLE (table), 3, 12);
  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  gtk_widget_show (table);

  GtkWidget* label = gtk_label_new (_("Source:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
		  GTK_FILL, GTK_FILL, 0, 0);
  gtk_widget_show (label);

  GtkWidget* combo = gimp_drawable_combo_box_new (NULL, NULL);
#ifdef DEBUG
  g_warning("setting initi value of source combo box as %d",vals->image_drawable_id);
#endif
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), vals->image_drawable_id,
		  G_CALLBACK (dialogSourceChangedCallback),vals);

  gtk_table_attach (GTK_TABLE (table), combo, 1, 3, 0, 1,
		  GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  gtk_widget_show (combo);

  label = gtk_label_new(_("Mask:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
		  GTK_FILL, GTK_FILL, 0, 0);
  gtk_widget_show (label);

  interface_vals.mask_combo_widget = gimp_drawable_combo_box_new (NULL, NULL);
  if (interface_vals.mask_type == SELECTION) {
	  gtk_widget_set_sensitive(interface_vals.mask_combo_widget,FALSE);
  }
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (interface_vals.mask_combo_widget),
		  vals->mask_drawable_id,
  	  	  G_CALLBACK (dialogMaskChangedCallback),vals);


  gtk_table_attach (GTK_TABLE (table), interface_vals.mask_combo_widget, 1, 3, 1, 2,
		  GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  gtk_widget_show (interface_vals.mask_combo_widget);




  label = gtk_label_new (_("Stop Path:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
		  GTK_FILL, GTK_FILL, 0, 0);
  gtk_widget_show (label);

  interface_vals.stop_path_combo_widget = gimp_vectors_combo_box_new (NULL, NULL);
  gtk_widget_set_sensitive(interface_vals.stop_path_combo_widget,FALSE);
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (interface_vals.stop_path_combo_widget), vals->stop_path_id,
		  G_CALLBACK (dialogStopPathChangedCallback),vals);
  gtk_table_attach (GTK_TABLE (table), interface_vals.stop_path_combo_widget, 1, 3, 2, 3,
		  GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  gtk_widget_show (interface_vals.stop_path_combo_widget);


  label = gtk_label_new(_("Mask Type:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
		  GTK_FILL, GTK_FILL, 0, 0);
  gtk_widget_show (label);

  interface_vals.mask_type_widget = gtk_combo_box_new_text();
  gint num_vectors;
  gimp_image_get_vectors(interface_vals.imageID,&num_vectors);

  gtk_combo_box_append_text(GTK_COMBO_BOX(interface_vals.mask_type_widget),"Selection");

  if (num_vectors > 0)
	  gtk_combo_box_append_text(GTK_COMBO_BOX(interface_vals.mask_type_widget),"Selection With Stop Path");

  gtk_combo_box_append_text(GTK_COMBO_BOX(interface_vals.mask_type_widget),"Binary Mask");
  if (num_vectors > 0)
	  gtk_combo_box_append_text(GTK_COMBO_BOX(interface_vals.mask_type_widget),"Binary Mask With Stop Path");
  gtk_combo_box_append_text(GTK_COMBO_BOX(interface_vals.mask_type_widget),"Mask Including Ordering");

  if (interface_vals.mask_type == SELECTION) {
	  int mt_index = 0 + (vals->stop_path_id > 0);
	  gtk_combo_box_set_active(GTK_COMBO_BOX(interface_vals.mask_type_widget),mt_index);
  } else if (interface_vals.mask_type == BINARY_MASK) {
	  int mt_index = 1 + (num_vectors > 0) + (vals->stop_path_id > 0);
	  gtk_combo_box_set_active(GTK_COMBO_BOX(interface_vals.mask_type_widget),mt_index);
  } else {
	  int mt_index = 2 + 2*(num_vectors > 0);
	  gtk_combo_box_set_active(GTK_COMBO_BOX(interface_vals.mask_type_widget),mt_index);
  }

  g_signal_connect (interface_vals.mask_type_widget, "changed",
		  G_CALLBACK(maskTypeChangedCallback), vals);
  maskTypeChangedCallback(GTK_COMBO_BOX(interface_vals.mask_type_widget),vals);


  gtk_table_attach (GTK_TABLE (table), interface_vals.mask_type_widget, 1, 3, 3, 4,
		  GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  gtk_widget_show (interface_vals.mask_type_widget);

  // Create the parameter table
//  table = gtk_table_new (5, 3, FALSE);
//  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
//  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
//  gtk_container_set_border_width (GTK_CONTAINER (table), 12);
//  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
//
//  gtk_widget_show (table);

  interface_vals.threshold_scale = gimp_scale_entry_new (GTK_TABLE (table), 0, 4,"_Mask Threshold:", SCALE_WIDTH, 0,vals->threshold, 0, 255, 0.1, 0.2, EPS_DIGITS,TRUE, 0, 0,NULL, NULL);
   g_signal_connect (interface_vals.threshold_scale, "value_changed", 	G_CALLBACK(dialogThresholdChanged), vals);

   GtkWidget *separator = gtk_hseparator_new ();
   gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 5);
   gtk_widget_show (separator);

   table = gtk_table_new (5, 3, FALSE);
   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
   //gtk_table_set_row_spacing (GTK_TABLE (table), 1, 12);
   //gtk_table_set_row_spacing (GTK_TABLE (table), 3, 12);
   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
   gtk_widget_show (table);


  interface_vals.epsilon_scale = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,"_Pixel neighborhood (epsilon):", SCALE_WIDTH, 0,vals->epsilon, 1, SCALE_MAX, 0.5, 0.2, EPS_DIGITS,TRUE, 0, 0,NULL, NULL);
  g_signal_connect (interface_vals.epsilon_scale, "value_changed", 	G_CALLBACK(gimp_float_adjustment_update), &vals->epsilon);

  interface_vals.kappa_scale = gimp_scale_entry_new (GTK_TABLE (table), 0, 1, "_Sharpness (kappa in %):", SCALE_WIDTH, 0,	vals->kappa, 0, CONV_MAX, 1, 0.1, KAPPA_DIGITS,TRUE, 0, 0,NULL, NULL);
  g_signal_connect (interface_vals.kappa_scale, "value_changed", 	G_CALLBACK(gimp_float_adjustment_update), &vals->kappa);

  interface_vals.sigma_scale = gimp_scale_entry_new (GTK_TABLE (table), 0, 2, "_Pre-smoothing (sigma):", SCALE_WIDTH, 0,	vals->sigma, 0, SCALE_MAX, 0.1, 0.1, SMOOTH_DIGITS,TRUE, 0, 0,NULL, NULL);
  g_signal_connect (interface_vals.sigma_scale, "value_changed", 	G_CALLBACK(gimp_float_adjustment_update), &vals->sigma);

  interface_vals.rho_scale = gimp_scale_entry_new (GTK_TABLE (table), 0, 3, "_Post-smoothing (rho):", SCALE_WIDTH, 0,	 vals->rho, 0.001, SCALE_MAX, 0.1, 0.1, SMOOTH_DIGITS,TRUE, 0, 0,NULL, NULL);
  g_signal_connect (interface_vals.rho_scale, "value_changed", 	G_CALLBACK(gimp_float_adjustment_update), &vals->rho);


//  // test extra button
//  GtkWidget *togglebutton = gtk_check_button_new_with_label("Inpaint Animation");
//  gtk_toggle_button_set_active( (GtkToggleButton *) togglebutton, ui_vals->anim_mode);
//  gtk_widget_show(togglebutton);
//
//  gimp_table_attach_aligned(GTK_TABLE (table),0,4,NULL,0,0,togglebutton,1,TRUE);
//
//  g_signal_connect (togglebutton, "toggled",	G_CALLBACK(gimp_toggle_button_update), &ui_vals->anim_mode);

  GtkWidget *default_param_button =   gtk_button_new_with_label("Default Parameters");
  gtk_widget_show(default_param_button);
  gtk_table_attach((GtkTable *)table,default_param_button,0,1,4,5,GTK_EXPAND,GTK_EXPAND,0,0);
  g_signal_connect (default_param_button, "clicked",	G_CALLBACK(set_default_param), NULL);
  //test end

  // Display dialog
  gtk_widget_show(dlg);
  renderPreview(vals);

  GtkResponseType status = gimp_dialog_run (GIMP_DIALOG (dlg));

  while (status == GTK_RESPONSE_APPLY) {
	  render (vals);
	  gimp_displays_flush ();
	  status = gimp_dialog_run (GIMP_DIALOG (dlg));
  }
  ui_vals->mask_type = interface_vals.mask_type;
  destroy();
  gtk_widget_destroy (dlg);

  return (status == GTK_RESPONSE_OK);
}
Beispiel #25
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam   values[1];
  GimpRunMode        run_mode;
  GimpPDBStatusType  status;
  GimpDrawable      *drawable;
  gint               x1, y1, x2, y2;

  INIT_I18N ();

  status   = GIMP_PDB_SUCCESS;
  run_mode = param[0].data.d_int32;

  *nreturn_vals = 1;
  *return_vals  = values;

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

  /* Get the active drawable info */

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

  img_width  = gimp_drawable_width (drawable->drawable_id);
  img_height = gimp_drawable_height (drawable->drawable_id);
  img_bpp    = gimp_drawable_bpp (drawable->drawable_id);

  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

  mbvals.center_x = (gdouble) (x1 + x2 - 1) / 2.0;
  mbvals.center_y = (gdouble) (y1 + y2 - 1) / 2.0;

  /* Set the tile cache size */
  gimp_tile_cache_ntiles (2 * drawable->ntile_cols);

  switch (run_mode)
    {
    case GIMP_RUN_INTERACTIVE:
      /* Possibly retrieve data */
      gimp_get_data (PLUG_IN_PROC, &mbvals);

      /* Get information from the dialog */
      if (! mblur_dialog (param[1].data.d_image, drawable))
        return;
      break;

    case GIMP_RUN_NONINTERACTIVE:
      if (strcmp (name, PLUG_IN_PROC_INWARD) == 0)
        mbvals.blur_outward = FALSE;

      if (nparams == 8)
        {
          mbvals.center_x = param[6].data.d_float;
          mbvals.center_y = param[7].data.d_float;
        }
      else if (nparams != 6)
        {
          status = GIMP_PDB_CALLING_ERROR;
        }

      if (status == GIMP_PDB_SUCCESS)
        {
          mbvals.mblur_type = param[3].data.d_int32;
          mbvals.length     = param[4].data.d_int32;
          mbvals.angle      = param[5].data.d_int32;
        }

    if ((mbvals.mblur_type < 0) || (mbvals.mblur_type > MBLUR_MAX))
      status= GIMP_PDB_CALLING_ERROR;
    break;

    case GIMP_RUN_WITH_LAST_VALS:
      /* Possibly retrieve data */
      gimp_get_data (PLUG_IN_PROC, &mbvals);
      break;

    default:
      break;
    }

  /* Blur the image */

  if ((status == GIMP_PDB_SUCCESS) &&
      (gimp_drawable_is_rgb(drawable->drawable_id) ||
       gimp_drawable_is_gray(drawable->drawable_id)))
    {

      /* Run! */
      has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
      mblur (drawable, NULL);

      /* If run mode is interactive, flush displays */
      if (run_mode != GIMP_RUN_NONINTERACTIVE)
        gimp_displays_flush ();

      /* Store data */
      if (run_mode == GIMP_RUN_INTERACTIVE)
        gimp_set_data (PLUG_IN_PROC, &mbvals, sizeof (mblur_vals_t));
    }
  else if (status == GIMP_PDB_SUCCESS)
    status = GIMP_PDB_EXECUTION_ERROR;

  values[0].data.d_status = status;

  gimp_drawable_detach (drawable);
}
static void
compose_row (gint          frame_num,
             DisposeType   dispose,
             gint          row_num,
             guchar       *dest,
             gint          dest_width,
             GimpDrawable *drawable,
             gboolean      cleanup)
{
  static guchar *line_buf = NULL;
  guchar        *srcptr;
  GimpPixelRgn   pixel_rgn;
  gint           rawx, rawy, rawbpp, rawwidth, rawheight;
  gint           i;
  gboolean       has_alpha;

  if (cleanup)
    {
      if (line_buf)
        {
          g_free (line_buf);
          line_buf = NULL;
        }

      return;
    }

  if (dispose == DISPOSE_REPLACE)
    {
      total_alpha (dest, dest_width, pixelstep);
    }

  gimp_drawable_offsets (drawable->drawable_id,
                         &rawx,
                         &rawy);

  rawheight = gimp_drawable_height (drawable->drawable_id);

  /* this frame has nothing to give us for this row; return */
  if (row_num >= rawheight + rawy ||
      row_num < rawy)
    return;

  rawbpp = gimp_drawable_bpp (drawable->drawable_id);
  rawwidth = gimp_drawable_width (drawable->drawable_id);
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

  if (line_buf)
    {
      g_free (line_buf);
      line_buf = NULL;
    }
  line_buf = g_malloc (rawwidth * rawbpp);

  /* Initialise and fetch the raw new frame row */

  gimp_pixel_rgn_init (&pixel_rgn,
                       drawable,
                       0, row_num - rawy,
                       rawwidth, 1,
                       FALSE,
                       FALSE);
  gimp_pixel_rgn_get_rect (&pixel_rgn,
                           line_buf,
                           0, row_num - rawy,
                           rawwidth, 1);

  /* render... */

  srcptr = line_buf;

  for (i=rawx; i<rawwidth+rawx; i++)
    {
      if (i>=0 && i<dest_width)
        {
          if ((!has_alpha) || ((*(srcptr+rawbpp-1))&128))
            {
              gint pi;

              for (pi = 0; pi < pixelstep-1; pi++)
                {
                  dest[i*pixelstep +pi] = *(srcptr + pi);
                }
              dest[i*pixelstep + pixelstep - 1] = 255;
            }
        }

      srcptr += rawbpp;
    }

}
Beispiel #27
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam  values[3];
  GimpRunMode       run_mode;
  GimpPDBStatusType status    = GIMP_PDB_SUCCESS;
  gint32            new_layer = -1;
  gint              width;
  gint              height;

  run_mode = param[0].data.d_int32;

  INIT_I18N ();

  *nreturn_vals = 3;
  *return_vals  = values;

  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = status;
  values[1].type          = GIMP_PDB_IMAGE;
  values[2].type          = GIMP_PDB_LAYER;

  width  = gimp_drawable_width  (param[2].data.d_drawable);
  height = gimp_drawable_height (param[2].data.d_drawable);

  switch (run_mode)
    {
    case GIMP_RUN_INTERACTIVE:
      /*  Possibly retrieve data  */
      gimp_get_data (PLUG_IN_PROC, &tvals);

      /*  First acquire information with a dialog  */
      if (! tile_dialog (param[1].data.d_image,
                         param[2].data.d_drawable))
        return;
      break;

    case GIMP_RUN_NONINTERACTIVE:
      /*  Make sure all the arguments are there!  */
      if (nparams != 6)
        {
          status = GIMP_PDB_CALLING_ERROR;
        }
      else
        {
          tvals.new_width  = param[3].data.d_int32;
          tvals.new_height = param[4].data.d_int32;
          tvals.new_image  = param[5].data.d_int32 ? TRUE : FALSE;

          if (tvals.new_width < 0 || tvals.new_height < 0)
            status = GIMP_PDB_CALLING_ERROR;
        }
      break;

    case GIMP_RUN_WITH_LAST_VALS:
      /*  Possibly retrieve data  */
      gimp_get_data (PLUG_IN_PROC, &tvals);
      break;

    default:
      break;
    }

  if (status == GIMP_PDB_SUCCESS)
    {
      gimp_progress_init (_("Tiling"));

      values[1].data.d_image = tile (param[1].data.d_image,
                                     param[2].data.d_drawable,
                                     &new_layer);
      values[2].data.d_layer = new_layer;

      /*  Store data  */
      if (run_mode == GIMP_RUN_INTERACTIVE)
        gimp_set_data (PLUG_IN_PROC, &tvals, sizeof (TileVals));

      if (run_mode != GIMP_RUN_NONINTERACTIVE)
        {
          if (tvals.new_image)
            gimp_display_new (values[1].data.d_image);
          else
            gimp_displays_flush ();
        }
    }

  values[0].data.d_status = status;
}
Beispiel #28
0
// Run the plugin
static void
run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals)
{
	// Return values
  static GimpParam values[1];

  gint sel_x1, sel_y1, sel_x2, sel_y2, w, h, padding;
	PluginData         pd;
  GimpRunMode        run_mode;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;

  *nreturn_vals = 1;
  *return_vals  = values;

  if (param[0].type!= GIMP_PDB_INT32) 
	  status=GIMP_PDB_CALLING_ERROR;
  if (param[2].type!=GIMP_PDB_DRAWABLE)
	  status=GIMP_PDB_CALLING_ERROR;

  run_mode = (GimpRunMode) param[0].data.d_int32;
	
	pd.drawable = gimp_drawable_get(param[2].data.d_drawable);
	gimp_drawable_mask_bounds(pd.drawable->drawable_id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
	pd.selection_width = sel_x2 - sel_x1;
  pd.selection_height = sel_y2 - sel_y1;
  pd.selection_offset_x = sel_x1;
  pd.selection_offset_y = sel_y1;
  pd.image_width = gimp_drawable_width(pd.drawable->drawable_id);
  pd.image_height = gimp_drawable_height(pd.drawable->drawable_id);
  pd.channel_count = gimp_drawable_bpp(pd.drawable->drawable_id);

  pd.point_grabbed = -1;

	if (run_mode == GIMP_RUN_INTERACTIVE)
	{
		// Interactive call with dialog
		dialog(&pd);
		if (pd.curve_user.count > 0)
		{
			gimp_set_data (PLUG_IN_BINARY, pd.curve_user.user_points, sizeof (GdkPoint) * pd.curve_user.count);
		}
	}
	else if (run_mode == GIMP_RUN_WITH_LAST_VALS)
	{
		// Read a saved curve and apply it
		fft_prepare(&pd);
		gimp_get_data(PLUG_IN_BINARY, pd.curve_user.user_points);
		pd.curve_user.count = gimp_get_data_size(PLUG_IN_BINARY) / sizeof (GdkPoint);
		gimp_pixel_rgn_init(&pd.region, pd.drawable, 0, 0, pd.image_width, pd.image_height, TRUE, TRUE);
		fft_apply(&pd);
		gimp_pixel_rgn_set_rect(&pd.region, pd.img_pixels, 0, 0, pd.image_width, pd.image_height);
		gimp_drawable_flush(pd.drawable);
		gimp_drawable_merge_shadow(pd.drawable->drawable_id, TRUE);
		gimp_drawable_update(pd.drawable->drawable_id, pd.selection_offset_x, pd.selection_offset_y, pd.selection_width, pd.selection_height);
		fft_destroy(&pd);
		gimp_displays_flush();
	}
	else
	{
	  status = GIMP_PDB_CALLING_ERROR;	
	}
  values[0].type = GIMP_PDB_STATUS;
  values[0].data.d_status = status;
  gimp_drawable_detach(pd.drawable);
}
Beispiel #29
0
static gboolean
tile_dialog (gint32 image_ID,
             gint32 drawable_ID)
{
  GtkWidget *dlg;
  GtkWidget *vbox;
  GtkWidget *frame;
  GtkWidget *sizeentry;
  GtkWidget *chainbutton;
  GtkWidget *toggle;
  gint       width;
  gint       height;
  gdouble    xres;
  gdouble    yres;
  GimpUnit   unit;
  gboolean   run;

  gimp_ui_init (PLUG_IN_BINARY, FALSE);

  width  = gimp_drawable_width (drawable_ID);
  height = gimp_drawable_height (drawable_ID);
  unit   = gimp_image_get_unit (image_ID);
  gimp_image_get_resolution (image_ID, &xres, &yres);

  tvals.new_width  = width;
  tvals.new_height = height;

  dlg = gimp_dialog_new (_("Tile"), PLUG_IN_BINARY,
                         NULL, 0,
                         gimp_standard_help_func, PLUG_IN_PROC,

                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                         GTK_STOCK_OK,     GTK_RESPONSE_OK,

                         NULL);

  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dlg),
                                           GTK_RESPONSE_OK,
                                           GTK_RESPONSE_CANCEL,
                                           -1);

  gimp_window_set_transient (GTK_WINDOW (dlg));

  vbox = gtk_vbox_new (FALSE, 12);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
                      vbox, TRUE, TRUE, 0);
  gtk_widget_show (vbox);

  frame = gimp_frame_new (_("Tile to New Size"));
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame);

  sizeentry = gimp_coordinates_new (unit, "%a", TRUE, TRUE, 8,
                                    GIMP_SIZE_ENTRY_UPDATE_SIZE,

                                    tvals.constrain, TRUE,

                                    _("_Width:"), width, xres,
                                    1, GIMP_MAX_IMAGE_SIZE,
                                    0, width,

                                    _("_Height:"), height, yres,
                                    1, GIMP_MAX_IMAGE_SIZE,
                                    0, height);
  gtk_container_add (GTK_CONTAINER (frame), sizeentry);
  gtk_table_set_row_spacing (GTK_TABLE (sizeentry), 1, 6);
  gtk_widget_show (sizeentry);

  chainbutton = GTK_WIDGET (GIMP_COORDINATES_CHAINBUTTON (sizeentry));

  toggle = gtk_check_button_new_with_mnemonic (_("C_reate new image"));
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), tvals.new_image);
  gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  gtk_widget_show (toggle);

  g_signal_connect (toggle, "toggled",
                    G_CALLBACK (gimp_toggle_button_update),
                    &tvals.new_image);

  gtk_widget_show (dlg);

  run = (gimp_dialog_run (GIMP_DIALOG (dlg)) == GTK_RESPONSE_OK);

  if (run)
    {
      tvals.new_width =
        RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (sizeentry), 0));
      tvals.new_height =
        RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (sizeentry), 1));

      tvals.constrain =
        gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chainbutton));
    }

  gtk_widget_destroy (dlg);

  return run;
}
Beispiel #30
0
static cairo_surface_t *
print_surface_from_drawable (gint32   drawable_ID,
                             GError **error)
{
  GeglBuffer         *buffer   = gimp_drawable_get_buffer (drawable_ID);
  const Babl         *format;
  cairo_surface_t    *surface;
  cairo_status_t      status;
  const gint          width    = gimp_drawable_width  (drawable_ID);
  const gint          height   = gimp_drawable_height (drawable_ID);
  GeglBufferIterator *iter;
  guchar             *pixels;
  gint                stride;
  guint               count    = 0;
  guint               done     = 0;

  if (gimp_drawable_has_alpha (drawable_ID))
    format = babl_format ("cairo-ARGB32");
  else
    format = babl_format ("cairo-RGB24");

  surface = cairo_image_surface_create (gimp_drawable_has_alpha (drawable_ID) ?
                                        CAIRO_FORMAT_ARGB32 :
                                        CAIRO_FORMAT_RGB24,
                                        width, height);

  status = cairo_surface_status (surface);
  if (status != CAIRO_STATUS_SUCCESS)
    {
      switch (status)
        {
        case CAIRO_STATUS_INVALID_SIZE:
          g_set_error_literal (error,
                               GIMP_PLUGIN_PRINT_ERROR,
                               GIMP_PLUGIN_PRINT_ERROR_FAILED,
                               _("Cannot handle the size (either width or height) of the image."));
          break;
        default:
          g_set_error (error,
                       GIMP_PLUGIN_PRINT_ERROR,
                       GIMP_PLUGIN_PRINT_ERROR_FAILED,
                       "Cairo error: %s",
                       cairo_status_to_string (status));
          break;
        }

      return NULL;
    }

  pixels = cairo_image_surface_get_data (surface);
  stride = cairo_image_surface_get_stride (surface);

  iter = gegl_buffer_iterator_new (buffer,
                                   GEGL_RECTANGLE (0, 0, width, height), 0,
                                   format,
                                   GEGL_BUFFER_READ, GEGL_ABYSS_NONE);

  while (gegl_buffer_iterator_next (iter))
    {
      const guchar *src  = iter->data[0];
      guchar       *dest = pixels + iter->roi->y * stride + iter->roi->x * 4;
      gint          y;

      for (y = 0; y < iter->roi->height; y++)
        {
          memcpy (dest, src, iter->roi->width * 4);

          src  += iter->roi->width * 4;
          dest += stride;
        }

      done += iter->roi->height * iter->roi->width;

      if (count++ % 16 == 0)
        gimp_progress_update ((gdouble) done / (width * height));
    }

  g_object_unref (buffer);

  cairo_surface_mark_dirty (surface);

  gimp_progress_update (1.0);

  return surface;
}