static gboolean apply_color(color_settings settings, image_output out) 
{
    gboolean success = TRUE;
    
    int default_drawable = out->drawable_ids[0];
    if (settings->brightness != 0 || settings->contrast != 0) {
        // brightness or contrast have been modified, apply the manipulation 
        
        if (!gimp_drawable_is_rgb(default_drawable)) {
            gimp_image_convert_rgb(out->image_id);
        }
        
        int i;
        for (i = 0; i < out->drawable_count; i++) {
            success = gimp_brightness_contrast(
                out->drawable_ids[i], 
                settings->brightness, 
                settings->contrast
            );
        }
    }
    
    if (settings->grayscale && !gimp_drawable_is_gray(default_drawable)) {
        // do grayscale conversion 
        success = gimp_image_convert_grayscale(out->image_id);
    }
    
    if (settings->levels_auto) {
        // do levels correction 
        int i;
        for (i = 0; i < out->drawable_count; i++) {
            success = gimp_levels_stretch(out->drawable_ids[i]);
        }
    }
    
    if (settings->curve_file != NULL && !gimp_drawable_is_indexed(default_drawable)) {
        // apply curve 
        
        if (!colorcurve_init) { // read from the curve file only the first time
            success = parse_curve_file(
                settings->curve_file, 
                &colorcurve_num_points_v, &colorcurve_ctr_points_v, 
                &colorcurve_num_points_r, &colorcurve_ctr_points_r, 
                &colorcurve_num_points_g, &colorcurve_ctr_points_g, 
                &colorcurve_num_points_b, &colorcurve_ctr_points_b, 
                &colorcurve_num_points_a, &colorcurve_ctr_points_a
            ); 
            
            colorcurve_init = TRUE;
        }
        else success = TRUE;
        
        if (success) {
            
            int i;
            for (i = 0; i < out->drawable_count; i++) {
                if (colorcurve_num_points_v >= 4 && colorcurve_num_points_v <= 34) {
                    success = gimp_curves_spline(out->drawable_ids[i], GIMP_HISTOGRAM_VALUE, colorcurve_num_points_v, colorcurve_ctr_points_v);
                }
                
                if (colorcurve_num_points_r >= 4 && colorcurve_num_points_r <= 34) {
                    success = gimp_curves_spline(out->drawable_ids[i], GIMP_HISTOGRAM_RED, colorcurve_num_points_r, colorcurve_ctr_points_r);
                }
                
                if (colorcurve_num_points_g >= 4 && colorcurve_num_points_g <= 34) {
                    success = gimp_curves_spline(out->drawable_ids[i], GIMP_HISTOGRAM_GREEN, colorcurve_num_points_g, colorcurve_ctr_points_g);
                }
                
                if (colorcurve_num_points_b >= 4 && colorcurve_num_points_b <= 34) {
                    success = gimp_curves_spline(out->drawable_ids[i], GIMP_HISTOGRAM_BLUE, colorcurve_num_points_b, colorcurve_ctr_points_b);
                }
                
                if (colorcurve_num_points_a >= 4 && colorcurve_num_points_a <= 34) {
                    success = gimp_curves_spline(out->drawable_ids[i], GIMP_HISTOGRAM_ALPHA, colorcurve_num_points_a, colorcurve_ctr_points_a);
                }
            }
        }
    }
    
    return success;
}
Пример #2
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);
}
Пример #3
0
static void
ico_image_get_reduced_buf (guint32   layer,
                           gint      bpp,
                           gint     *num_colors,
                           guchar  **cmap_out,
                           guchar  **buf_out)
{
  gint32      tmp_image;
  gint32      tmp_layer;
  gint        w, h;
  guchar     *buf;
  guchar     *cmap   = NULL;
  GeglBuffer *buffer = gimp_drawable_get_buffer (layer);
  const Babl *format;

  w = gegl_buffer_get_width  (buffer);
  h = gegl_buffer_get_height (buffer);

  switch (gimp_drawable_type (layer))
    {
    case GIMP_RGB_IMAGE:
      format = babl_format ("R'G'B' u8");
      break;

    case GIMP_RGBA_IMAGE:
      format = babl_format ("R'G'B'A u8");
      break;

    case GIMP_GRAY_IMAGE:
      format = babl_format ("Y' u8");
      break;

    case GIMP_GRAYA_IMAGE:
      format = babl_format ("Y'A u8");
      break;

    case GIMP_INDEXED_IMAGE:
    case GIMP_INDEXEDA_IMAGE:
      format = gegl_buffer_get_format (buffer);

    default:
      g_return_if_reached ();
    }

  *num_colors = 0;

  buf = g_new (guchar, w * h * 4);

  if (bpp <= 8 || bpp == 24 || babl_format_get_bytes_per_pixel (format) != 4)
    {
      gint32      image = gimp_item_get_image (layer);
      GeglBuffer *tmp;

      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, "tmp", w, h,
                                  gimp_drawable_type (layer),
                                  100, GIMP_NORMAL_MODE);
      gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0);

      tmp = gimp_drawable_get_buffer (tmp_layer);

      gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0,
                       format, buf,
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

      gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, tmp, NULL);

      g_object_unref (tmp);

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

      if (bpp <= 8)
        {
          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_buffer (tmp_layer);

              gegl_buffer_set (tmp, GEGL_RECTANGLE (0, 0, w, h), 0,
                               format, buf, GEGL_AUTO_ROWSTRIDE);

              g_object_unref (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);
              cmap = gimp_image_get_colormap (tmp_image, num_colors);
            }

          gimp_image_convert_rgb (tmp_image);
        }
      else if (bpp == 24)
        {
          GimpParam    *return_vals;
          gint          n_return_vals;

          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);
        }

      gimp_layer_add_alpha (tmp_layer);

      tmp = gimp_drawable_get_buffer (tmp_layer);

      gegl_buffer_get (tmp, GEGL_RECTANGLE (0, 0, w, h), 1.0,
                       NULL, buf,
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

      g_object_unref (tmp);

      gimp_image_delete (tmp_image);
    }
  else
    {
      gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0,
                       format, buf,
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
    }

  g_object_unref (buffer);

  *cmap_out = cmap;
  *buf_out = buf;
}
Пример #4
0
static void
export_convert_grayscale (gint32  image_ID,
                          gint32 *drawable_ID)
{
  gimp_image_convert_grayscale (image_ID);
}
Пример #5
0
/* -------------------------------------------------------
 * gap_image_set_selection_from_selection_or_drawable
 * -------------------------------------------------------
 * create a selection in the specified image_id.
 * The selection is a scaled copy of the selection in another image,
 * referred by ref_drawable_id, or a Grayscale copy of the specified ref_drawable_id
 * (in case the referred image has no selection or the flag force_from_drawable is TRUE)
 *
 *  - operates on a duplicate of the image referred by ref_drawable_id.
 *  - this duplicate is scaled to same size as specified image_id
 *
 * return TRUE in case the selection was successfully created .
 */
gboolean
gap_image_set_selection_from_selection_or_drawable(gint32 image_id, gint32 ref_drawable_id
  , gboolean force_from_drawable)
{
  gint32        l_aux_channel_id;
  gint32        ref_image_id;
  gint32        work_drawable_id;   /* the duplicate of the layer that is used as selction mask */
  gint32        dup_image_id;
  gboolean has_selection;
  gboolean non_empty;
  gint     x1, y1, x2, y2;

  if ((image_id < 0) || (ref_drawable_id < 0))
  {
    return (FALSE);
  }
  ref_image_id = gimp_item_get_image(ref_drawable_id);

  if (ref_image_id < 0)
  {
    printf("ref_drawable_id does not refer to a valid image layer_id:%d\n", (int)ref_drawable_id);
    return (FALSE);
  }



  dup_image_id = gimp_image_duplicate(ref_image_id);
  if (dup_image_id < 0)
  {
    printf("duplicating of image failed, referred souce image_id:%d\n", (int)ref_image_id);
    return (FALSE);
  }
  /* clear undo stack */
  if (gimp_image_undo_is_enabled(dup_image_id))
  {
    gimp_image_undo_disable(dup_image_id);
  }

  if ((gimp_image_width(image_id) != gimp_image_width(dup_image_id))
  ||  (gimp_image_height(image_id) != gimp_image_height(dup_image_id)))
  {
     if(gap_debug)
     {
       printf("scaling tmp image_id: %d\n", (int)dup_image_id);
     }
     gimp_image_scale(dup_image_id, gimp_image_width(image_id), gimp_image_height(image_id));
  }

  has_selection  = gimp_selection_bounds(ref_image_id, &non_empty, &x1, &y1, &x2, &y2);
  if ((has_selection) && (non_empty) && (force_from_drawable != TRUE))
  {
    /* use scaled copy of the already exisating selection in the referred image */
    work_drawable_id = gimp_image_get_selection(dup_image_id);
  }
  else
  {
    gint32        active_layer_stackposition;

    /* create selection as gray copy of the alt_selection layer */

    active_layer_stackposition = gap_layer_get_stackposition(ref_image_id, ref_drawable_id);

    if(gimp_image_base_type(dup_image_id) != GIMP_GRAY)
    {
       if(gap_debug)
       {
         printf("convert to GRAYSCALE tmp image_id: %d\n", (int)dup_image_id);
       }
       gimp_image_convert_grayscale(dup_image_id);
    }
    work_drawable_id = gap_layer_get_id_by_stackposition(dup_image_id, active_layer_stackposition);
    gimp_layer_resize_to_image_size (work_drawable_id);
  }

  gimp_selection_all(image_id);
  //l_sel_channel_id = gimp_image_get_selection(image_id);
  l_aux_channel_id = gimp_selection_save(image_id);

  /* copy the work drawable (layer or channel) into the selection channel
   * the work layer is a grayscale copy GRAY or GRAYA of the alt_selection layer
   *  that is already scaled and resized to fit the size of the target image
   * the work channel is the scaled selection of the image refred by ref_drawable_id
   *
   * copying is done into an auxiliary channel from where we regulary load the selection.
   * this is done because subseqent queries of the selection boudaries will deliver
   * full channel size rectangle after a direct copy into the selection.
   */
  gap_layer_copy_picked_channel (l_aux_channel_id  /* dst_drawable_id*/
                              , 0                  /* dst_channel_pick */
                              , work_drawable_id   /* src_drawable_id */
                              , 0                  /* src_channel_pick */
                              , FALSE              /* gboolean shadow */
                              );

  gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, l_aux_channel_id);
  gimp_image_remove_channel(image_id, l_aux_channel_id);

  gap_image_delete_immediate(dup_image_id);
  return (TRUE);

}  /* end gap_image_set_selection_from_selection_or_drawable */
Пример #6
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;
  const Babl *format;
  gint        w       = gimp_drawable_width (layer);
  gint        h       = gimp_drawable_height (layer);

  if (! preview)
    return;

  switch (gimp_drawable_type (layer))
    {
    case GIMP_RGB_IMAGE:
      format = babl_format ("R'G'B' u8");
      break;

    case GIMP_RGBA_IMAGE:
      format = babl_format ("R'G'B'A u8");
      break;

    case GIMP_GRAY_IMAGE:
      format = babl_format ("Y' u8");
      break;

    case GIMP_GRAYA_IMAGE:
      format = babl_format ("Y'A u8");
      break;

    case GIMP_INDEXED_IMAGE:
    case GIMP_INDEXEDA_IMAGE:
      format = gimp_drawable_get_format (layer);

    default:
      g_return_if_reached ();
    }

  if (bpp <= 8)
    {
      GeglBuffer *buffer;
      GeglBuffer *tmp;
      gint32      image;
      gint32      tmp_image;
      gint32      tmp_layer;
      guchar     *buf;
      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);

      buffer = gimp_drawable_get_buffer (layer);
      tmp    = gimp_drawable_get_buffer (tmp_layer);

      buf = g_malloc (w * h * 4);

      gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0,
                       format, buf,
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

      gegl_buffer_copy (buffer, NULL, tmp, NULL);

      g_object_unref (tmp);
      g_object_unref (buffer);

      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_buffer (tmp_layer);

          gegl_buffer_set (tmp, GEGL_RECTANGLE (0, 0, w, h), 0,
                           format, buf, GEGL_AUTO_ROWSTRIDE);

          g_object_unref (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 (buf);

      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)
    {
      GeglBuffer *buffer;
      GeglBuffer *tmp;
      gint32      image;
      gint32      tmp_image;
      gint32      tmp_layer;
      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);

      buffer = gimp_drawable_get_buffer (layer);
      tmp    = gimp_drawable_get_buffer (tmp_layer);

      gegl_buffer_copy (buffer, NULL, tmp, NULL);

      g_object_unref (tmp);
      g_object_unref (buffer);

      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);
}