Beispiel #1
0
GimpImage *
gimp_create_image (Gimp              *gimp,
                   gint               width,
                   gint               height,
                   GimpImageBaseType  type,
                   GimpPrecision      precision,
                   gboolean           attach_comment)
{
  GimpImage *image;

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);

  image = gimp_image_new (gimp, width, height, type, precision);

  if (attach_comment)
    {
      const gchar *comment;

      comment = gimp_template_get_comment (gimp->config->default_image);

      if (comment)
        {
          GimpParasite *parasite = gimp_parasite_new ("gimp-comment",
                                                      GIMP_PARASITE_PERSISTENT,
                                                      strlen (comment) + 1,
                                                      comment);
          gimp_image_parasite_attach (image, parasite);
          gimp_parasite_free (parasite);
        }
    }

  return image;
}
Beispiel #2
0
/* ============================================================================
 * gap_image_new_with_layer_of_samesize
 * ============================================================================
 * create empty image
 *  if layer_id is NOT NULL then create one full transparent layer at full image size
 *  and return the layer_id
 */
gint32
gap_image_new_with_layer_of_samesize(gint32 old_image_id, gint32 *layer_id)
{
  GimpImageBaseType  l_type;
  guint       l_width;
  guint       l_height;
  gint32      new_image_id;
  gdouble     l_xresoulution, l_yresoulution;
  gint32     l_unit;


  /* create empty image  */
  l_width  = gimp_image_width(old_image_id);
  l_height = gimp_image_height(old_image_id);
  l_type   = gimp_image_base_type(old_image_id);
  l_unit   = gimp_image_get_unit(old_image_id);
  gimp_image_get_resolution(old_image_id, &l_xresoulution, &l_yresoulution);

  new_image_id = gimp_image_new(l_width, l_height,l_type);
  gimp_image_set_resolution(new_image_id, l_xresoulution, l_yresoulution);
  gimp_image_set_unit(new_image_id, l_unit);

  if(layer_id)
  {
    l_type   = (l_type * 2); /* convert from GimpImageBaseType to GimpImageType */
    *layer_id = gimp_layer_new(new_image_id, "dummy",
                                 l_width, l_height,  l_type,
                                 0.0,       /* Opacity full transparent */
                                 0);        /* NORMAL */
    gimp_image_insert_layer(new_image_id, *layer_id, 0, 0);
  }

  return (new_image_id);

}  /* end gap_image_new_with_layer_of_samesize */
Beispiel #3
0
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
static gint32
create_new_image (const gchar        *filename,
                  const gchar        *layername,
                  guint               width,
                  guint               height,
                  GimpImageBaseType   type,
                  gdouble             xres,
                  gdouble             yres,
                  gint32             *layer_ID,
                  GimpDrawable      **drawable,
                  GimpPixelRgn       *pixel_rgn)
{
  gint32 image_ID;

  image_ID = gimp_image_new (width, height, type);

  gimp_image_undo_disable (image_ID);
  gimp_image_set_filename (image_ID, filename);
  gimp_image_set_resolution (image_ID, xres, yres);

  *layer_ID = create_new_layer (image_ID, 0,
                                layername, width, height, type,
                                drawable, pixel_rgn);

  return image_ID;
}
Beispiel #4
0
/* ----------------------------------------------------
 * gap_image_create_unicolor_image
 * ----------------------------------------------------
 * - create a new image with one black filled layer
 *   (both have the requested size)
 *
 * return the new created image_id
 *   and the layer_id of the black_layer
 */
gint32
gap_image_create_unicolor_image(gint32 *layer_id, gint32 width , gint32 height
                       , gdouble r_f, gdouble g_f, gdouble b_f, gdouble a_f)
{
  gint32 l_empty_layer_id;
  gint32 l_image_id;

  *layer_id = -1;
  l_image_id = gimp_image_new(width, height, GIMP_RGB);
  if(l_image_id >= 0)
  {
    l_empty_layer_id = gimp_layer_new(l_image_id, "black_background",
                          width, height,
                          GIMP_RGBA_IMAGE,
                          100.0,     /* Opacity full opaque */
                          GIMP_NORMAL_MODE);
    gimp_image_insert_layer(l_image_id, l_empty_layer_id, 0, 0);

    /* clear layer to unique color */
    gap_layer_clear_to_color(l_empty_layer_id, r_f, g_f, b_f, a_f);

    *layer_id = l_empty_layer_id;
  }
  return(l_image_id);
}       /* end gap_image_create_unicolor_image */
Beispiel #5
0
static gint32
create_image (GdkPixbuf   *pixbuf,
              GdkRegion   *shape,
              const gchar *name)
{
  gint32     image;
  gint32     layer;
  gdouble    xres, yres;
  gchar     *comment;
  gint       width, height;
  gboolean   status;

  status = gimp_progress_init (_("Importing screenshot"));

  width  = gdk_pixbuf_get_width (pixbuf);
  height = gdk_pixbuf_get_height (pixbuf);

  image = gimp_image_new (width, height, GIMP_RGB);
  gimp_image_undo_disable (image);

  gimp_get_monitor_resolution (&xres, &yres);
  gimp_image_set_resolution (image, xres, yres);

  comment = gimp_get_default_comment ();
  if (comment)
    {
      GimpParasite *parasite;

      parasite = gimp_parasite_new ("gimp-comment", GIMP_PARASITE_PERSISTENT,
                                    strlen (comment) + 1, comment);

      gimp_image_parasite_attach (image, parasite);
      gimp_parasite_free (parasite);

      g_free (comment);
    }

  layer = gimp_layer_new_from_pixbuf (image,
                                      name ? name : _("Screenshot"),
                                      pixbuf,
                                      100, GIMP_NORMAL_MODE, 0.0, 1.0);
  gimp_image_add_layer (image, layer, 0);

  if (shape && ! gdk_region_empty (shape))
    {
      image_select_shape (image, shape);

      if (! gimp_selection_is_empty (image))
        {
          gimp_layer_add_alpha (layer);
          gimp_edit_clear (layer);
          gimp_selection_none (image);
        }
    }

  gimp_image_undo_enable (image);

  return image;
}
Beispiel #6
0
/*
 * sendBMPToGIMP
 *
 * Take the captured data and send it across
 * to GIMP.
 */
static void
sendBMPToGimp(HBITMAP hBMP, HDC hDC, RECT rect)
{
  int		width, height;
  int		imageType, layerType;
  gint32	image_id;
  gint32	layer_id;
  GimpPixelRgn	pixel_rgn;
  GimpDrawable    *drawable;

  /* Our width and height */
  width = (rect.right - rect.left);
  height = (rect.bottom - rect.top);

  /* Check that we got the memory */
  if (!capBytes) {
    g_message (_("No data captured"));
    return;
  }

  /* Flip the red and blue bytes */
  flipRedAndBlueBytes(width, height);

  /* Set up the image and layer types */
  imageType = GIMP_RGB;
  layerType = GIMP_RGB_IMAGE;

  /* Create the GIMP image and layers */
  image_id = gimp_image_new(width, height, imageType);
  layer_id = gimp_layer_new(image_id, _("Background"),
			    ROUND4(width), height,
			    layerType, 100, GIMP_NORMAL_MODE);
  gimp_image_insert_layer(image_id, layer_id, -1, 0);

  /* Get our drawable */
  drawable = gimp_drawable_get(layer_id);

  gimp_tile_cache_size(ROUND4(width) * gimp_tile_height() * 3);

  /* Initialize a pixel region for writing to the image */
  gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0,
		      ROUND4(width), height, TRUE, FALSE);

  gimp_pixel_rgn_set_rect(&pixel_rgn, (guchar *) capBytes,
			  0, 0, ROUND4(width), height);

  /* HB: update data BEFORE size change */
  gimp_drawable_flush(drawable);
  /* Now resize the layer down to the correct size if necessary. */
  if (width != ROUND4(width)) {
    gimp_layer_resize (layer_id, width, height, 0, 0);
    gimp_image_resize (image_id, width, height, 0, 0);
  }
  /* Finish up */
  gimp_drawable_detach(drawable);
  gimp_display_new (image_id);

  return;
}
Beispiel #7
0
static void
preview_update_preview (GimpPreview  *preview,
                        GimpDrawable *drawable)
{
  gint          x1, y1;
  gint          width, height;
  gint          bpp;
  guchar       *buffer;
  GimpPixelRgn  src_rgn;
  GimpPixelRgn  preview_rgn;
  gint32        image_id, src_image_id;
  gint32        preview_id;
  GimpDrawable *preview_drawable;

  bpp = gimp_drawable_bpp (drawable->drawable_id);

  gimp_preview_get_position (preview, &x1, &y1);
  gimp_preview_get_size (preview, &width, &height);

  buffer = g_new (guchar, width * height * bpp);

  gimp_pixel_rgn_init (&src_rgn, drawable,
                       x1, y1, width, height, FALSE, FALSE);
  gimp_pixel_rgn_get_rect (&src_rgn, buffer,
                           x1, y1, width, height);

  /* set up gimp drawable for rendering preview into */
  src_image_id = gimp_drawable_get_image (drawable->drawable_id);
  image_id = gimp_image_new (width, height,
                             gimp_image_base_type (src_image_id));
  preview_id = gimp_layer_new (image_id, "preview", width, height,
                               gimp_drawable_type (drawable->drawable_id),
                               100,
                               GIMP_NORMAL_MODE);
  preview_drawable = gimp_drawable_get (preview_id);
  gimp_image_add_layer (image_id, preview_id, 0);
  gimp_layer_set_offsets (preview_id, 0, 0);
  gimp_pixel_rgn_init (&preview_rgn, preview_drawable,
                       0, 0, width, height, TRUE, TRUE);
  gimp_pixel_rgn_set_rect (&preview_rgn, buffer,
                           0, 0, width, height);
  gimp_drawable_flush (preview_drawable);
  gimp_drawable_merge_shadow (preview_id, TRUE);
  gimp_drawable_update (preview_id, 0, 0, width, height);

  dog (image_id, preview_drawable, dogvals.inner, dogvals.outer, FALSE);

  gimp_pixel_rgn_get_rect (&preview_rgn, buffer,
                           0, 0, width, height);

  gimp_preview_draw_buffer (preview, buffer, width * bpp);

  gimp_image_delete (image_id);
  g_free (buffer);
}
Beispiel #8
0
static gint32
create_gimp_image (PSDimage    *img_a,
                   const gchar *filename)
{
  gint32 image_id = -1;

  img_a->base_type = GIMP_RGB;

  /* Create gimp image */
  IFDBG(2) g_debug ("Create image");
  image_id = gimp_image_new (img_a->columns, img_a->rows, img_a->base_type);

  gimp_image_set_filename (image_id, filename);
  gimp_image_undo_disable (image_id);

  return image_id;
}
Beispiel #9
0
static gint32
load_image (const gchar  *filename,
            GError      **load_error)
{
  gint32        image;
  gint32        layer;
  GdkPixbuf    *pixbuf;
  gint          width;
  gint          height;
  GError       *error = NULL;

  pixbuf = load_rsvg_pixbuf (filename, &load_vals, &error);

  if (! pixbuf)
    {
      /*  Do not rely on librsvg setting GError on failure!  */
      g_set_error (load_error,
                   error ? error->domain : 0, error ? error->code : 0,
                   _("Could not open '%s' for reading: %s"),
                   gimp_filename_to_utf8 (filename),
                   error ? error->message : _("Unknown reason"));
      g_clear_error (&error);

      return -1;
    }

  gimp_progress_init (_("Rendering SVG"));

  width  = gdk_pixbuf_get_width (pixbuf);
  height = gdk_pixbuf_get_height (pixbuf);

  image = gimp_image_new (width, height, GIMP_RGB);
  gimp_image_undo_disable (image);

  gimp_image_set_filename (image, filename);
  gimp_image_set_resolution (image,
                             load_vals.resolution, load_vals.resolution);

  layer = gimp_layer_new_from_pixbuf (image, _("Rendered SVG"), pixbuf,
                                      100, GIMP_NORMAL_MODE, 0.0, 1.0);
  gimp_image_insert_layer (image, layer, -1, 0);

  gimp_image_undo_enable (image);

  return image;
}
Beispiel #10
0
/* ----------------------------------------
 * p_createEmptyEdgeDrawable
 * ----------------------------------------
 * create the (empty) edge drawable as layer of a new image
 *
 */
static void
p_createEmptyEdgeDrawable(GapEdgeContext *ectx)
{
  ectx->edgeImageId = gimp_image_new(ectx->refDrawable->width
                                   , ectx->refDrawable->height
                                   , GIMP_GRAY
                                   );
  ectx->edgeDrawableId = gimp_layer_new(ectx->edgeImageId
                , "edge"
                , ectx->refDrawable->width
                , ectx->refDrawable->height
                , GIMP_GRAY_IMAGE
                , 100.0   /* full opacity */
                , 0       /* normal mode */
                );

  gimp_image_add_layer (ectx->edgeImageId, ectx->edgeDrawableId, 0 /* stackposition */ );

  ectx->edgeDrawable = gimp_drawable_get(ectx->edgeDrawableId);
  
}  /* end p_createEmptyEdgeDrawable */
Beispiel #11
0
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
static gint32
create_new_image (const gchar    *filename,
                  guint           width,
                  guint           height,
                  GimpImageType   gdtype,
                  gint32         *layer_ID,
                  GimpDrawable  **drawable,
                  GimpPixelRgn   *pixel_rgn)
{
  gint32            image_ID;
  GimpImageBaseType gitype;

  if ((gdtype == GIMP_GRAY_IMAGE) || (gdtype == GIMP_GRAYA_IMAGE))
    gitype = GIMP_GRAY;
  else if ((gdtype == GIMP_INDEXED_IMAGE) || (gdtype == GIMP_INDEXEDA_IMAGE))
    gitype = GIMP_INDEXED;
  else
    gitype = GIMP_RGB;

  image_ID = gimp_image_new (width, height, gitype);
  gimp_image_set_filename (image_ID, filename);

  gimp_image_undo_disable (image_ID);
  *layer_ID = gimp_layer_new (image_ID, _("Background"), width, height,
                              gdtype, 100, GIMP_NORMAL_MODE);
  gimp_image_insert_layer (image_ID, *layer_ID, -1, 0);

  if (drawable)
    {
      *drawable = gimp_drawable_get (*layer_ID);
      if (pixel_rgn != NULL)
        gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width,
                             (*drawable)->height, TRUE, FALSE);
    }

  return image_ID;
}
Beispiel #12
0
gint32
file_vtf_load_image (const gchar *fname, GError **error)
{
    gimp_progress_init_printf ("Opening '%s'", gimp_filename_to_utf8 (fname));

    gint32 image = -1;
    std::auto_ptr<Vtf::File> vtf (new Vtf::File);

    try {
        vtf->load(fname);

        Vtf::HiresImageResource* vres = (Vtf::HiresImageResource*)
                                        vtf->findResource (Vtf::Resource::TypeHires);
        if (!vres)
            throw Vtf::Exception ("Cound not find high-resolution image");

        image = gimp_image_new (vres->width (), vres->height  (), GIMP_RGB);
        gimp_image_set_filename (image, fname);

        guint16 i, frame_count = vres->frameCount ();
        for (i = 0; i < frame_count; i++) {
            if (!file_vtf_load_layer (vres, image, i)) {
                g_set_error (error, 0, 0, "Unsupported format %s",
                             Vtf::formatToString (vres->format()));
                gimp_image_delete (image);
                image = -1;
                break;
            }
        }

        gimp_progress_update (1.0);
    } catch (std::exception& e) {
        g_set_error (error, 0, 0, e.what ());
    }

    return image;
}
Beispiel #13
0
gint32
file_vtf_load_thumbnail_image (const gchar *fname, gint *width, gint *height,
                               GError **error)
{
    gint32 image = -1;
    gimp_progress_init_printf ("Opening thumbnail for '%s'",
                               gimp_filename_to_utf8 (fname));

    Vtf::File *vtf = new Vtf::File;
    try {
        vtf->load(fname);

        Vtf::HiresImageResource* vres = (Vtf::HiresImageResource*)
                                        vtf->findResource(Vtf::Resource::TypeHires);
        if (!vres)
            throw Vtf::Exception ("Cound not find high-resolution image");

        *width = static_cast<gint> (vres->width ());
        *height = static_cast<gint> (vres->height ());

        image = gimp_image_new (*width, *height, GIMP_RGB);
        if (!file_vtf_load_layer (vres, image, 0)) {
            g_set_error (error, 0, 0, "Unsupported format %s",
                         Vtf::formatToString(vres->format()));
            gimp_image_delete (image);
            image = -1;
        }

        gimp_progress_update (1.0);
    } catch (std::exception& e) {
        g_set_error (error, 0, 0, e.what());
    }

    delete vtf;
    return image;
}
Beispiel #14
0
static void
snapshot_ready (GObject      *source_object,
                GAsyncResult *result,
                gpointer      user_data)
{
  WebKitWebView   *view = WEBKIT_WEB_VIEW (source_object);
  cairo_surface_t *surface;

  surface = webkit_web_view_get_snapshot_finish (view, result,
                                                 &webpagevals.error);

  if (surface)
    {
      gint   width;
      gint   height;
      gint32 layer;

      width  = cairo_image_surface_get_width (surface);
      height = cairo_image_surface_get_height (surface);

      webpagevals.image = gimp_image_new (width, height, GIMP_RGB);

      gimp_image_undo_disable (webpagevals.image);
      layer = gimp_layer_new_from_surface (webpagevals.image, _("Webpage"),
                                           surface,
                                           0.25, 1.0);
      gimp_image_insert_layer (webpagevals.image, layer, -1, 0);
      gimp_image_undo_enable (webpagevals.image);

      cairo_surface_destroy (surface);
    }

  gimp_progress_update (1.0);

  gtk_main_quit ();
}
Beispiel #15
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);
}
Beispiel #16
0
static GimpPDBStatusType plt_load(gchar *filename, gint32 *image_id)
{
    FILE *stream = 0;
    unsigned int i;

    // Using uint for guaranteed sizes across all systems
    // guint may or may not work (?)
    uint8_t  plt_version[8];
    uint32_t plt_width  = 0;
    uint32_t plt_height = 0;
    uint8_t *buffer;

    uint8_t px_value = 0;
    uint8_t px_layer = 0;
    uint32_t num_px = 0;

    gint32 newImgID   = -1;
    gint32 newLayerID = -1;
    gint32 plt_layer_ids[PLT_NUM_LAYERS];
    guint8 pixel[2] = {0, 255}; // GRAYA image = 2 Channels: Value + Alpha

    stream = fopen(filename, "rb");
    if(stream == 0)
    {
        g_message("Error opening file.\n");
        return (GIMP_PDB_EXECUTION_ERROR);
    }

    gimp_progress_init_printf("Opening %s", filename);
    gimp_progress_update(0.0);

    // Read header: Version, should be 8x1 bytes = "PLT V1  "
    if (fread(plt_version, 1, 8, stream) < 8)
    {
        g_message("Invalid plt file: Unable to read version information.\n");
        fclose(stream);
        return (GIMP_PDB_EXECUTION_ERROR);
    }
    if (g_ascii_strncasecmp(plt_version, PLT_HEADER_VERSION, 8) != 0)
    {

        g_message("Invalid plt file: Version mismatch.\n");
        fclose(stream);
        return (GIMP_PDB_EXECUTION_ERROR);
    }
    // Read header: Next 8 bytes don't matter
    fseek(stream, 8, SEEK_CUR);
    // Read header: Width
    if (fread(&plt_width, 4, 1, stream) < 1)
    {
        g_message("Invalid plt file: Unable to read width.\n");
        fclose(stream);
        return (GIMP_PDB_EXECUTION_ERROR);
    }
    // Read header: Height
    if (fread(&plt_height, 4, 1, stream) < 1)
    {
        g_message("Invalid plt file: Unable to read height.\n");
        fclose(stream);
        return (GIMP_PDB_EXECUTION_ERROR);
    }

    // Create a new image
    newImgID = gimp_image_new(plt_width, plt_height, GIMP_GRAY);
    if(newImgID == -1)
    {
        g_message("Unable to allocate new image.\n");
        fclose(stream);
        return (GIMP_PDB_EXECUTION_ERROR);
    }
    gimp_image_set_filename(newImgID, filename);

    // Create the 10 plt layers, add them to the new image and save their ID's
    for (i = 0; i < PLT_NUM_LAYERS; i++)
    {
        newLayerID = gimp_layer_new(newImgID,
                                    plt_layernames[i],
                                    plt_width, plt_height,
                                    GIMP_GRAYA_IMAGE,
                                    100.0,
                                    GIMP_NORMAL_MODE);
        gimp_image_insert_layer(newImgID, newLayerID, 0, 0);
        plt_layer_ids[i] = newLayerID;
    }

    // Read image data
    // Expecting width*height (value, layer) tuples = 2*width*height bytes
    num_px = plt_width * plt_height;
    buffer = (uint8_t*) g_malloc(sizeof(uint8_t)*2*num_px);
    if (fread(buffer, 1, 2*num_px, stream) < (2*num_px))
    {
        g_message("Image size mismatch.\n");
        fclose(stream);
        g_free(buffer);
        gimp_image_delete(newImgID);
        return (GIMP_PDB_EXECUTION_ERROR);
    }
    for (i = 0; i < num_px; i++)
    {
        pixel[0] = buffer[2*i];
        px_layer = buffer[2*i+1];
        gimp_drawable_set_pixel(plt_layer_ids[px_layer],
                                i % plt_width,
                                plt_height - (int)(floor(i / plt_width)) - 1,
                                2,
                                pixel);
        gimp_progress_update((float) i/ (float) num_px);
    }
    gimp_progress_update(1.0);
    gimp_image_set_active_layer(newImgID, plt_layer_ids[0]);

    fclose(stream);

    g_free(buffer);

    *image_id = newImgID;
    return (GIMP_PDB_SUCCESS);
}
Beispiel #17
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 #18
0
static gint32 load_image (char *filename)
{
	FILE *fp;

	gint32 image_ID = -1;
	gint32 layer_ID;
	GPixelRgn pixel_rgn;
	GDrawable *drawable;
	guchar *data;
	GDrawableType dtype;
	GImageType itype;
	struct stat st;
  
	int width, height, bpp=0;
	int i, j, k;
	int pelbytes, tileheight, wbytes, bsize, npels, pels, ncols, npals;
	int badread;
	gushort tmpval;

	if (stat (filename,&st) == -1) return -1;

	fp = fopen (filename, "rb");
	if (!fp) return -1;
	bs = (bs_header_t *) g_malloc (st.st_size);
	fread (bs,st.st_size,1,fp);
	fclose (fp);

	if (bs->magic != BS_MAGIC)
	{
		printf("not a .bs file\n");
		return -1;
	}

	gimp_get_data ("bs_width",&width);
	gimp_get_data ("bs_height",&height);

	printf("%d x %d\n",width,height);

	itype	= RGB;
	dtype	= RGB_IMAGE;

	image_ID = gimp_image_new (width, height, itype);
	gimp_image_set_filename (image_ID, filename);
	layer_ID = gimp_layer_new (image_ID,
		"Background",
		width, height,
		dtype,
		100,
		NORMAL_MODE);
	gimp_image_add_layer (image_ID, layer_ID, 0);
	drawable = gimp_drawable_get (layer_ID);
	gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, TRUE, FALSE);
	data = (guchar *) g_malloc (width * height * 3);

	bs_init();
	bs_decode_rgb24 (data,bs,width,height,0);
	
	printf ("image decoded!\n");
	
	gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, 0, width, height);
	g_free (data);
	gimp_drawable_flush (drawable);
	gimp_drawable_detach (drawable);
	return image_ID;
}
Beispiel #19
0
/*
 * 'load_image()' - Load a WMF image into a new image window.
 */
static gint32
load_image (const gchar  *filename,
            GError      **error)
{
  gint32        image;
  gint32        layer;
  GimpDrawable *drawable;
  guchar       *pixels;
  GimpPixelRgn  pixel_rgn;
  guint         width, height;
  guint         rowstride;
  guint         count = 0;
  guint         done  = 0;
  gpointer      pr;

  pixels = wmf_load_file (filename, &width, &height, error);

  if (! pixels)
    return -1;

  rowstride = width * 4;

  gimp_progress_init_printf (_("Opening '%s'"),
                             gimp_filename_to_utf8 (filename));

  image = gimp_image_new (width, height, GIMP_RGB);
  gimp_image_set_filename (image, filename);
  gimp_image_set_resolution (image,
                             load_vals.resolution, load_vals.resolution);

  layer = gimp_layer_new (image,
                          _("Rendered WMF"),
                          width, height,
                          GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);

  drawable = gimp_drawable_get (layer);

  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, TRUE, FALSE);

  for (pr = gimp_pixel_rgns_register (1, &pixel_rgn);
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr))
    {
      const guchar *src  = pixels + pixel_rgn.y * rowstride + pixel_rgn.x * 4;
      guchar       *dest = pixel_rgn.data;
      gint          y;

      for (y = 0; y < pixel_rgn.h; y++)
        {
          memcpy (dest, src, pixel_rgn.w * pixel_rgn.bpp);

          src  += rowstride;
          dest += pixel_rgn.rowstride;
        }

      done += pixel_rgn.h * pixel_rgn.w;

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

  g_free (pixels);

  gimp_drawable_detach (drawable);

  gimp_progress_update (1.0);

  /* Tell GIMP to display the image.
   */
  gimp_image_insert_layer (image, layer, -1, 0);
  gimp_drawable_flush (drawable);

  return image;
}
Beispiel #20
0
gint32
load_djvu (const gchar * filename, 
          GimpRunMode runmode, 
          gboolean preview)

{
  
  GimpPixelRgn rgn_in;
  GimpDrawable *drawable;
  gint32 volatile image_ID;
  gint32 layer_ID;
  int x1, y1, x2, y2, width, height;
   unsigned char *src = NULL;
  int file_length;



ctx = ddjvu_context_create("gimp");
//
doc = ddjvu_document_create_by_filename(ctx,filename, TRUE);



while (! ddjvu_document_decoding_done(doc))
    handle(TRUE);
  




  i = ddjvu_document_get_pagenum(doc);
  dialog( &pageno ,i);
//processing the page
  
page = ddjvu_page_create_by_pageno(doc, pageno-1);
while (! ddjvu_page_decoding_done(page))
    handle(TRUE);

if (ddjvu_page_decoding_error(page))
{
 fprintf(stderr,"unexpected error ");
 exit(10);
}

// ddjvu variables

  ddjvu_rect_t prect;
  ddjvu_rect_t rrect;
  ddjvu_format_style_t style;
  ddjvu_render_mode_t mode;
  ddjvu_format_t *fmt;
  int iw = ddjvu_page_get_width(page);
  int ih = ddjvu_page_get_height(page);
  int dpi = ddjvu_page_get_resolution(page);
  ddjvu_page_type_t type = ddjvu_page_get_type(page);
  char *image = 0;
  int rowsize;

//end of ddjvu variables
style= DDJVU_FORMAT_RGB24;
mode=DDJVU_RENDER_COLOR;
fmt = ddjvu_format_create(style, 0, 0);
ddjvu_format_set_row_order(fmt, 1);

      prect.w = iw;
      prect.h = ih;

       prect.x = 0;
       prect.y = 0;

       flag_scale=150;

     prect.w = (unsigned int) (iw * flag_scale) / dpi;
     prect.h = (unsigned int) (ih * flag_scale) / dpi;
       
      rrect = prect;

 rowsize = (rrect.w *3);
 image = (char*)malloc(rowsize * rrect.h);
  
//generating page
ddjvu_page_render(page, mode, &prect, &rrect, fmt, rowsize, image);

ddjvu_page_release(page);
char *s =image;
  /* create output image */

  width = prect.w;
  height =  prect.h;
  x1 = 0;
  y1 = 0;
  x2 = prect.w;
  y2 = prect.h;


  image_ID = gimp_image_new (width, height, GIMP_RGB);
  layer_ID = gimp_layer_new (image_ID, _("Background"),
			     width, height, GIMP_RGB, 100, GIMP_NORMAL_MODE);
  gimp_image_add_layer (image_ID, layer_ID, 0);
  drawable = gimp_drawable_get (layer_ID);	// initializes the drawable     
  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
  gimp_pixel_rgn_init (&rgn_in, drawable, x1, y1,
		       x2 - x1, y2 - y1, TRUE, TRUE);
  gimp_pixel_rgn_set_rect (&rgn_in,  image, 0, 0, width, height);
      //g_free (buf);
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, x2 - x1, y2 - y1);
  gimp_image_set_filename (image_ID, filename);
  return image_ID;
  image =NULL;
 

//not handling any error
if (doc)
    ddjvu_document_release(doc);
  if (ctx)
    ddjvu_context_release(ctx);
    
}
Beispiel #21
0
void ptRun(const gchar*     Name,
           gint       NrParameters,
           const GimpParam* Parameter,
           gint *nreturn_vals,
           GimpParam **return_vals) {
  printf("(%s,%d) '%s'\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
  printf("Name         : '%s'\n",Name);
  printf("NrParameters : %d\n",NrParameters);
  if (!strcmp(Name,"photivoSendToGimp")) {
    printf("RunMode      : %d\n",Parameter[0].data.d_int32);
    printf("FileName1    : '%s'\n",Parameter[1].data.d_string);
    printf("FileName2    : '%s'\n",Parameter[2].data.d_string);

    QFile GimpFile(Parameter[1].data.d_string);
    bool result = GimpFile.open(QIODevice::ReadOnly | QIODevice::Text);
    assert(result);

    QTextStream In(&GimpFile);

    QString ImageFileName = In.readLine();
    QString ExifFileName  = In.readLine();
    QString ICCFileName   = In.readLine();

    // Read image
    FILE *InputFile = fopen(ImageFileName.toLocal8Bit().data(),"rb");
    if (!InputFile) {
      ptLogError(1,ImageFileName.toLocal8Bit().data());
      return; // ptError_FileOpen;
    }

    short    Colors;
    unsigned short Width;
    unsigned short Height;
    unsigned short BitsPerColor;
    char     Buffer[128];

    // Extremely naive. Probably just enough for testcases.
    char *s = fgets(Buffer,127,InputFile);
    assert ( s );
    int n = sscanf(Buffer,"P%hd",&Colors);
    assert ( 1 == n );
    assert(Colors == 6 );
    do {
      s = fgets(Buffer,127,InputFile);
      assert ( s );
    } while (Buffer[0] == '#');
    sscanf(Buffer,"%hd %hd",&Width,&Height);
    s = fgets(Buffer,127,InputFile);
    assert ( s );
    sscanf(Buffer,"%hd",&BitsPerColor);
    assert(BitsPerColor == 0xffff);

    Colors = 3;

    unsigned short (* ImageForGimp)[3] =
      (unsigned short (*)[3]) CALLOC2(Width*Height,sizeof(*ImageForGimp));
    ptMemoryError(ImageForGimp,__FILE__,__LINE__);

    unsigned short*  PpmRow = (unsigned short *) CALLOC2(Width*Height,sizeof(*PpmRow));
    ptMemoryError(PpmRow,__FILE__,__LINE__);

    for (unsigned short Row=0; Row<Height; Row++) {
      size_t RV = fread(PpmRow,Colors*2,Width,InputFile);
      if (RV != (size_t) Width) {
        printf("ReadPpm error. Expected %d bytes. Got %d\n",Width,(int)RV);
        exit(EXIT_FAILURE);
      }
      if (htons(0x55aa) != 0x55aa) {
        swab((char *)PpmRow,(char *)PpmRow,Width*Colors*2);
      }
      for (unsigned short Col=0; Col<Width; Col++) {
        for (short c=0;c<3;c++) {
          ImageForGimp[Row*Width+Col][c] = PpmRow[Col*Colors+c];
        }
      }
    }

    FREE2(PpmRow);
    FCLOSE(InputFile);

    QFile ExifFile(ExifFileName);
    result = ExifFile.open(QIODevice::ReadOnly);
    assert(result);
    qint64 FileSize = ExifFile.size();
    QDataStream ExifIn(&ExifFile);
    char* ExifBuffer = (char *) MALLOC2(FileSize);
    ptMemoryError(ExifBuffer,__FILE__,__LINE__);
    unsigned ExifBufferLength = ExifIn.readRawData(ExifBuffer,FileSize);
    ExifFile.close();

    QFile ICCFile(ICCFileName);
    result = ICCFile.open(QIODevice::ReadOnly);
    assert(result);
    qint64 FileSize2 = ICCFile.size();
    QDataStream ICCIn(&ICCFile);
    char* ICCBuffer = (char *) MALLOC2(FileSize2);
    ptMemoryError(ICCBuffer,__FILE__,__LINE__);
    unsigned ICCBufferLength = ICCIn.readRawData(ICCBuffer,FileSize2);
    ICCFile.close();

    // And now copy to gimp.
    gint32 GimpImage = gimp_image_new(Width,
                                      Height,
                                      GIMP_RGB);
    assert (GimpImage != -1);
    gint32 GimpLayer = gimp_layer_new(GimpImage,
                                      "BG",
                                      Width,
                                      Height,
                                      GIMP_RGB_IMAGE,
                                      100.0,
                                      GIMP_NORMAL_MODE);
#if GIMP_MINOR_VERSION<=6
    gimp_image_add_layer(GimpImage,GimpLayer,0);
#else
    gimp_image_insert_layer(GimpImage,GimpLayer,0,0);
#endif
    GimpDrawable* Drawable = gimp_drawable_get(GimpLayer);
    GimpPixelRgn PixelRegion;
    gimp_pixel_rgn_init(&PixelRegion,
                        Drawable,
                        0,
                        0,
                        Drawable->width,
                        Drawable->height,
                        true,
                        false);
    unsigned short TileHeight = gimp_tile_height();
    for (unsigned short Row=0; Row<Height; Row+=TileHeight) {
      unsigned short NrRows = MIN(Height-Row, (int)TileHeight);
      guint8* Buffer = g_new(guint8,TileHeight*Width*3);
      for (unsigned short i=0; i<NrRows; i++) {
        for (unsigned short j=0; j<Width; j++) {
          for (short c=0;c<3;c++) {
            Buffer[3*(i*Width+j)+c] =
              ImageForGimp[(Row+i)*Width+j][c]>>8;
          }
        }
      }
      gimp_pixel_rgn_set_rect(&PixelRegion,
                              Buffer,
                              0,
                              Row,
                              Width,
                              NrRows);
      g_free(Buffer);
    }
    gimp_drawable_flush(Drawable);
    gimp_drawable_detach(Drawable);
    FREE2(ImageForGimp);
    GimpParasite* GimpExifData = gimp_parasite_new("exif-data",
                                                   GIMP_PARASITE_PERSISTENT,
                                                   ExifBufferLength,
                                                   ExifBuffer);
    gimp_image_parasite_attach(GimpImage,GimpExifData);
    gimp_parasite_free(GimpExifData);
    FREE2(ExifBuffer);

    GimpParasite* GimpICCData = gimp_parasite_new("icc-profile",
                                                   GIMP_PARASITE_PERSISTENT,
                                                   ICCBufferLength,
                                                   ICCBuffer);
    gimp_image_parasite_attach(GimpImage,GimpICCData);
    gimp_parasite_free(GimpICCData);
    FREE2(ICCBuffer);

    static GimpParam Values[2];
    *nreturn_vals = 2;
    *return_vals = Values;
    Values[0].type = GIMP_PDB_STATUS;
    Values[0].data.d_status = GIMP_PDB_SUCCESS;
    Values[1].type = GIMP_PDB_IMAGE;
    Values[1].data.d_image = GimpImage;

    QFile::remove(ImageFileName);
    QFile::remove(ExifFileName);
    QFile::remove(ICCFileName);
    QFile::remove(Parameter[1].data.d_string);

  }
Beispiel #22
0
gboolean load_image(const gchar *filename,
                    gint32      *image_ID,
                    GError     **error)
{
    gboolean              status      = FALSE;
    gchar                *indata      = NULL;
    gsize                 indatalen;
    gint                  width;
    gint                  height;
    WebPMux              *mux         = NULL;
    WebPData              wp_data;
    uint32_t              flags;
    uint8_t              *outdata     = NULL;

#ifdef GIMP_2_9
    /* Initialize GEGL */
    gegl_init(NULL, NULL);
#endif

    do {

        /* Attempt to read the file contents from disk */
        if (g_file_get_contents(filename,
                                &indata,
                                &indatalen,
                                error) == FALSE) {
            break;
        }

        /* Validate WebP data, grabbing the width and height */
        if (!WebPGetInfo(indata, indatalen, &width, &height)) {
            break;
        }

        /* Create a WebPMux from the contents of the file */
        wp_data.bytes = (uint8_t*)indata;
        wp_data.size = indatalen;

        mux = WebPMuxCreate(&wp_data, 1);
        if (mux == NULL) {
            break;
        }

        /* Retrieve the features present */
        if (WebPMuxGetFeatures(mux, &flags) != WEBP_MUX_OK) {
            break;
        }

        /* TODO: decode the image in "chunks" or "tiles" */
        /* TODO: check if an alpha channel is present */

        /* Create the new image and associated layer */
        *image_ID = gimp_image_new(width, height, GIMP_RGB);

#ifdef WEBP_0_5
        if (flags & ANIMATION_FLAG) {
            int frames, i;

            /* Retrieve the number of frames */
            WebPMuxNumChunks(mux, WEBP_CHUNK_ANMF, &frames);

            /* Loop over each of the frames */
            for (i = 0; i < frames; ++i) {
                WebPMuxFrameInfo frame = {0};

                /* Retrieve the data for the frame */
                if (WebPMuxGetFrame(mux, i, &frame) != WEBP_MUX_OK) {
                    goto error;
                }

                /* Decode the frame */
                outdata = WebPDecodeRGBA(frame.bitstream.bytes,
                                         frame.bitstream.size,
                                         &width, &height);

                /* Free the compressed data */
                WebPDataClear(&frame.bitstream);

                if (!outdata) {
                    goto error;
                }

                /* Create a layer for the frame */
                char name[255];
                snprintf(name, 255, "Frame %d", (i + 1));

                if (create_layer(*image_ID,
                                 outdata,
                                 0,
                                 (gchar*)name,
                                 width, height,
                                 frame.x_offset,
                                 frame.y_offset) == FALSE) {
                    goto error;
                }
            }

            /* If all is well, jump *over* the error label - otherwise
               leave the loop and begin cleaning things up */

            goto success;

        error:
            break;

        success: ;

        } else {
#endif

            /* Attempt to decode the data as a WebP image */
            outdata = WebPDecodeRGBA(indata, indatalen, &width, &height);
            if (!outdata) {
                break;
            }

            /* Create a single layer */
            status = create_layer(*image_ID,
                                  outdata,
                                  0,
                                  "Background",
                                  width, height,
                                  0, 0);

#ifdef WEBP_0_5
        }

#ifdef GIMP_2_9
        /* Load a color profile if one was provided */
        if (flags & ICCP_FLAG) {
            WebPData          icc_profile;
            GimpColorProfile *profile;

            /* Load the ICC profile from the file */
            WebPMuxGetChunk(mux, "ICCP", &icc_profile);

            /* Have Gimp load the color profile */
            profile = gimp_color_profile_new_from_icc_profile(
                        icc_profile.bytes, icc_profile.size, NULL);
            if (profile) {
                gimp_image_set_color_profile(image_ID, profile);
                g_object_unref(profile);
            }
        }
#endif
#endif
        /* Set the filename for the image */
        gimp_image_set_filename(*image_ID, filename);

    } while(0);

    /* Delete the mux object */
    if (mux) {
        WebPMuxDelete(mux);
    }

    /* Free the data read from disk */
    if (indata) {
        g_free(indata);
    }

    return status;
}
static gint32
do_optimizations (GimpRunMode run_mode,
                  gboolean    diff_only)
{
  GimpPixelRgn   pixel_rgn;
  static guchar *rawframe = NULL;
  guchar        *srcptr;
  guchar        *destptr;
  gint           row, this_frame_num;
  guint32        frame_sizebytes;
  gint32         new_layer_id;
  DisposeType    dispose;
  guchar        *this_frame = NULL;
  guchar        *last_frame = NULL;
  guchar        *opti_frame = NULL;
  guchar        *back_frame = NULL;

  gint           this_delay;
  gint           cumulated_delay = 0;
  gint           last_true_frame = -1;
  gint           buflen;

  gchar         *oldlayer_name;
  gchar         *newlayer_name;

  gboolean       can_combine;

  gint32         bbox_top, bbox_bottom, bbox_left, bbox_right;
  gint32         rbox_top, rbox_bottom, rbox_left, rbox_right;

  switch (opmode)
    {
    case OPUNOPTIMIZE:
      gimp_progress_init (_("Unoptimizing animation"));
      break;
    case OPFOREGROUND:
      gimp_progress_init (_("Removing animation background"));
      break;
    case OPBACKGROUND:
      gimp_progress_init (_("Finding animation background"));
      break;
    case OPOPTIMIZE:
    default:
      gimp_progress_init (_("Optimizing animation"));
      break;
    }

  width     = gimp_image_width (image_id);
  height    = gimp_image_height (image_id);
  layers    = gimp_image_get_layers (image_id, &total_frames);
  imagetype = gimp_image_base_type (image_id);
  pixelstep = (imagetype == GIMP_RGB) ? 4 : 2;

  /*  gimp_tile_cache_ntiles(total_frames * (width / gimp_tile_width() + 1) );*/


  drawabletype_alpha = (imagetype == GIMP_RGB) ? GIMP_RGBA_IMAGE :
    ((imagetype == GIMP_INDEXED) ? GIMP_INDEXEDA_IMAGE : GIMP_GRAYA_IMAGE);

  frame_sizebytes = width * height * pixelstep;

  this_frame = g_malloc (frame_sizebytes);
  last_frame = g_malloc (frame_sizebytes);
  opti_frame = g_malloc (frame_sizebytes);

  if (opmode == OPBACKGROUND ||
      opmode == OPFOREGROUND)
    back_frame = g_malloc (frame_sizebytes);

  total_alpha (this_frame, width*height, pixelstep);
  total_alpha (last_frame, width*height, pixelstep);

  new_image_id = gimp_image_new(width, height, imagetype);
  gimp_image_undo_disable (new_image_id);

  if (imagetype == GIMP_INDEXED)
    {
      palette = gimp_image_get_colormap (image_id, &ncolours);
      gimp_image_set_colormap (new_image_id, palette, ncolours);
    }

#if 1
  if (opmode == OPBACKGROUND ||
      opmode == OPFOREGROUND)
    {
      /* iterate through all rows of all frames, find statistical
         mode for each pixel position. */
      gint     i,j;
      guchar **these_rows;
      guchar **red;
      guchar **green;
      guchar **blue;
      guint  **count;
      guint   *num_colours;

      these_rows = g_new (guchar *, total_frames);
      red =        g_new (guchar *, total_frames);
      green =      g_new (guchar *, total_frames);
      blue =       g_new (guchar *, total_frames);
      count =      g_new (guint *, total_frames);

      num_colours = g_new (guint, width);

      for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++)
        {
          these_rows[this_frame_num] = g_malloc(width * pixelstep);

          red[this_frame_num]   = g_new (guchar, width);
          green[this_frame_num] = g_new (guchar, width);
          blue[this_frame_num]  = g_new (guchar, width);

          count[this_frame_num] = g_new0(guint, width);
        }

      for (row = 0; row < height; row++)
        {
          memset(num_colours, 0, width * sizeof(guint));

          for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++)
            {
              drawable =
                gimp_drawable_get (layers[total_frames-(this_frame_num+1)]);

              dispose = get_frame_disposal (this_frame_num);

              compose_row(this_frame_num,
                          dispose,
                          row,
                          these_rows[this_frame_num],
                          width,
                          drawable,
                          FALSE
                          );

              gimp_drawable_detach(drawable);
            }

          for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++)
            {
              for (i=0; i<width; i++)
                {
                  if (these_rows[this_frame_num][i * pixelstep + pixelstep -1]
                      >= 128)
                    {
                      for (j=0; j<num_colours[i]; j++)
                        {

                          switch (pixelstep)
                            {
                            case 4:
                              if (these_rows[this_frame_num][i * 4 +0] ==
                                  red[j][i] &&
                                  these_rows[this_frame_num][i * 4 +1] ==
                                  green[j][i] &&
                                  these_rows[this_frame_num][i * 4 +2] ==
                                  blue[j][i])
                                {
                                  (count[j][i])++;
                                  goto same;
                                }
                              break;
                            case 2:
                              if (these_rows[this_frame_num][i * 2 +0] ==
                                  red[j][i])
                                {
                                  (count[j][i])++;
                                  goto same;
                                }
                              break;
                            default:
                              g_error ("Eeep!");
                              break;
                            }
                        }

                      count[num_colours[i]][i] = 1;
                      red[num_colours[i]][i] =
                        these_rows[this_frame_num][i * pixelstep];
                      if (pixelstep == 4)
                        {
                          green[num_colours[i]][i] =
                            these_rows[this_frame_num][i * 4 +1];
                          blue[num_colours[i]][i] =
                            these_rows[this_frame_num][i * 4 +2];
                        }
                      num_colours[i]++;
                    }
                same:
                  /* nop */;
                }
            }

          for (i=0; i<width; i++)
            {
              guint  best_count = 0;
              guchar best_r = 255, best_g = 0, best_b = 255;

              for (j=0; j<num_colours[i]; j++)
                {
                  if (count[j][i] > best_count)
                    {
                      best_count = count[j][i];
                      best_r = red[j][i];
                      best_g = green[j][i];
                      best_b = blue[j][i];
                    }
                }

              back_frame[width * pixelstep * row +i*pixelstep + 0] = best_r;
              if (pixelstep == 4)
                {
                  back_frame[width * pixelstep * row +i*pixelstep + 1] =
                    best_g;
                  back_frame[width * pixelstep * row +i*pixelstep + 2] =
                    best_b;
                }
              back_frame[width * pixelstep * row +i*pixelstep +pixelstep-1] =
                (best_count == 0) ? 0 : 255;

              if (best_count == 0)
                g_warning("yayyyy!");
            }
          /*      memcpy(&back_frame[width * pixelstep * row],
                  these_rows[0],
                  width * pixelstep);*/
        }

      for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++)
        {
          g_free (these_rows[this_frame_num]);
          g_free (red[this_frame_num]);
          g_free (green[this_frame_num]);
          g_free (blue[this_frame_num]);
          g_free (count[this_frame_num]);
        }

      g_free (these_rows);
      g_free (red);
      g_free (green);
      g_free (blue);
      g_free (count);
      g_free (num_colours);
    }
Beispiel #24
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;
  SeparateContext mysc;
  //enum separate_function func = SEP_NONE;
  run_mode = param[0].data.d_int32;


  /* setup for localization */
  INIT_I18N ();

  cmsErrorAction( LCMS_ERROR_IGNORE );

  mysc.filename = NULL;
  if( nparams != ( run_mode == GIMP_RUN_NONINTERACTIVE ? 2 : 1 ) )
    status = GIMP_PDB_CALLING_ERROR;
  else if( run_mode == GIMP_RUN_NONINTERACTIVE ) {
    if( param[1].type != GIMP_PDB_STRING || strlen( param[1].data.d_string ) == 0 )
      status = GIMP_PDB_CALLING_ERROR;
    else
      mysc.filename = g_strdup( param[1].data.d_string );
  } else {
    gint size = gimp_get_data_size( "plug-in-separate-import/lastpath" );
    if( size ) {
      mysc.filename = g_malloc( size );
      gimp_get_data( "plug-in-separate-import/lastpath", mysc.filename );
    }
  }

  if( status == GIMP_PDB_SUCCESS && ( run_mode == GIMP_RUN_NONINTERACTIVE || separate_import_dialog( &mysc ) ) ) {
    gint i, j, x, y;
    TIFF *in;
    guint32 width, height, stripSize, stripCount, stripHeight;
    gint16 bps, spp, step, planerConfig, photometric, inkset, resolutionUnit;
    float xres, yres;
    const gchar *layerNames[] = { "C", "M", "Y", "K" };
    guchar *buf, *maskbuf[4], *srcbuf, *destbuf[4], *iccProfile;
    gint32 layers[5], masks[4];
    GimpDrawable *drw[4];
    GimpPixelRgn rgn[4];
    GimpRGB primaries[4] = { { .180, .541, .870, 1.0 },
                             { .925, .149, .388, 1.0 },
                             { .929, .862, .129, 1.0 },
                             { 0, 0, 0, 1.0 }  };

    gchar *str = NULL;
    gchar *baseName = g_path_get_basename( gimp_filename_to_utf8( mysc.filename ) );

#ifdef G_OS_WIN32
    {
      gchar *_filename = NULL; // win32 filename encoding(not UTF-8)
      _filename = g_win32_locale_filename_from_utf8( mysc.filename );
      in = TIFFOpen( _filename ? _filename : mysc.filename, "r" );
      g_free( _filename );
    }
#else
    in = TIFFOpen( mysc.filename, "r" );
#endif

    if( !in ) {
      str = g_strdup_printf( _( "Cannot open : \"%s\"" ), baseName );
      gimp_message( str );
      g_free( str );
      status = GIMP_PDB_EXECUTION_ERROR;
    } else {
      if( ( TIFFGetField( in, TIFFTAG_BITSPERSAMPLE, &bps ) == FALSE || ( bps != 8 && bps != 16 ) ) ||
          ( TIFFGetField( in, TIFFTAG_SAMPLESPERPIXEL, &spp ) == FALSE || spp != 4 ) ||
          ( TIFFGetField( in, TIFFTAG_PHOTOMETRIC, &photometric ) == FALSE || photometric != PHOTOMETRIC_SEPARATED ) ||
          ( TIFFGetField( in, TIFFTAG_PLANARCONFIG, &planerConfig ) == FALSE || planerConfig != PLANARCONFIG_CONTIG ) ||
          ( TIFFGetField( in, TIFFTAG_INKSET, &inkset ) == TRUE && inkset != INKSET_CMYK ) ) {
        str = g_strdup_printf( _( "\"%s\" is unsupported." ), baseName );
        gimp_message( str );
        g_free( str );
        status = GIMP_PDB_EXECUTION_ERROR;
      } else {
        stripCount = TIFFNumberOfStrips( in );
        stripSize = TIFFStripSize( in );
        TIFFGetField( in, TIFFTAG_IMAGEWIDTH, &width );
        TIFFGetField( in, TIFFTAG_IMAGELENGTH, &height );
        TIFFGetField( in, TIFFTAG_ROWSPERSTRIP, &stripHeight );
        TIFFGetField( in, TIFFTAG_RESOLUTIONUNIT, &resolutionUnit );
        TIFFGetField( in, TIFFTAG_XRESOLUTION, &xres );
        TIFFGetField( in, TIFFTAG_YRESOLUTION, &yres );

#if 0
        str = g_strdup_printf( "Photometric : %d  BPS : %d  SPP : %d\nInkset : %d  StripCount : %d", photometric, bps, spp, inkset, stripCount );
        gimp_message( str );
        g_free( str );
#endif

        step = ( bps == 16 ) ? 2 : 1;

        buf = g_malloc( stripSize );

        values[1].data.d_image = gimp_image_new( width, height, GIMP_RGB );
        gimp_image_set_resolution( values[1].data.d_image, xres, yres );
        gimp_context_push();
        for( i = 0; i < 4; i++ ) {
          layers[i] = gimp_layer_new( values[1].data.d_image, layerNames[i], width, height, GIMP_RGBA_IMAGE, 100.0, GIMP_DARKEN_ONLY_MODE );
          gimp_context_set_foreground( &primaries[i] );
          gimp_drawable_fill( layers[i], GIMP_FOREGROUND_FILL );
          gimp_image_add_layer( values[1].data.d_image, layers[i], i );
          masks[i] = gimp_layer_create_mask( layers[i], GIMP_ADD_BLACK_MASK );
          gimp_layer_add_mask( layers[i], masks[i] );
          drw[i] = gimp_drawable_get( masks[i] );
          maskbuf[i] = g_malloc( width * stripHeight );
        }
        gimp_context_pop();
        layers[4] = gimp_layer_new( values[1].data.d_image, _( "Background" ), width, height, GIMP_RGB_IMAGE, 100.0, GIMP_NORMAL_MODE );
        gimp_drawable_fill( layers[4], GIMP_WHITE_FILL );
        gimp_image_add_layer( values[1].data.d_image, layers[4], 4 );

        str = g_strdup_printf( _( "Reading \"%s\"..." ), baseName );
        gimp_progress_init( str );
        g_free( str );

        for( i = 0; i < stripCount; i++ ) {
          guint32 size = TIFFReadEncodedStrip( in, i, buf, stripSize );
          guint32 rowCount = ( size < stripSize ? height % stripHeight : stripHeight );
          srcbuf = buf;
          if( bps == 16 )
            srcbuf++;
          for( j = 0; j < 4; j++ ) {
            gimp_pixel_rgn_init( &( rgn[j] ), drw[j],
                                 0, stripHeight * i, width, rowCount,
                                 FALSE, FALSE );
            destbuf[j] = maskbuf[j];
          }
          for( y = 0; y < rowCount; y++ ) {
            for( x = 0; x < width; x++ ) {
              *destbuf[0]++ = *srcbuf;
              srcbuf += step;
              *destbuf[1]++ = *srcbuf;
              srcbuf += step;
              *destbuf[2]++ = *srcbuf;
              srcbuf += step;
              *destbuf[3]++ = *srcbuf;
              srcbuf += step;
              //srcbuf += spp > 4 ? spp - 4 : 0;
            }
          }
          gimp_pixel_rgn_set_rect( &( rgn[0] ), maskbuf[0], 0, stripHeight * i, width, rowCount );
          gimp_pixel_rgn_set_rect( &( rgn[1] ), maskbuf[1], 0, stripHeight * i, width, rowCount );
          gimp_pixel_rgn_set_rect( &( rgn[2] ), maskbuf[2], 0, stripHeight * i, width, rowCount );
          gimp_pixel_rgn_set_rect( &( rgn[3] ), maskbuf[3], 0, stripHeight * i, width, rowCount );
          gimp_progress_update( (gdouble)i / stripCount );
        }
        g_free( buf );
        for( i = 0; i < 4; i++ ) {
          g_free( maskbuf[i] );
          gimp_drawable_detach( drw[i] );
        }

#ifdef ENABLE_COLOR_MANAGEMENT
        if ( TIFFGetField( in, TIFFTAG_ICCPROFILE, &width, &iccProfile ) ) {
          GimpParasite *parasite;

          parasite = gimp_parasite_new( CMYKPROFILE, 0, width, iccProfile );
          gimp_image_parasite_attach( values[1].data.d_image, parasite );
          gimp_parasite_free( parasite );

          //g_free( iccProfile ); // This causes clash on TIFFClose( in ).
        }
#endif
      }
      TIFFClose( in );
    }
    g_free( baseName );
  } else
    status = GIMP_PDB_CANCEL;

  *return_vals = values;
  values[0].type = GIMP_PDB_STATUS;
  values[0].data.d_status = status;
  if( status == GIMP_PDB_SUCCESS ) {
    *nreturn_vals = 2;
    values[1].type = GIMP_PDB_IMAGE;
    if( run_mode != GIMP_RUN_NONINTERACTIVE ) {
      gimp_image_undo_enable( values[1].data.d_image );
      gimp_display_new( values[1].data.d_image );
      gimp_displays_flush();
    }
    gimp_set_data( "plug-in-separate-import/lastpath", mysc.filename, strlen( mysc.filename ) + 1 );
  } else
    *nreturn_vals = 1;

  g_free( mysc.filename );
}
static void
border (gint32 image_ID)
{
  GdkPixbuf *pixbuf = NULL;
  int        texture_width;
  int        texture_height;
  gdouble    margin_x;
  gdouble    margin_y;

  pixbuf = gdk_pixbuf_new_from_inline (-1, bvals.border->texture, FALSE, NULL);

  if (pixbuf)
  {
    texture_width = gdk_pixbuf_get_width (pixbuf);
    texture_height = gdk_pixbuf_get_height (pixbuf);

    gint32 texture_image = gimp_image_new (texture_width, texture_height, GIMP_RGB);
    gint32 texture_layer = gimp_layer_new_from_pixbuf (texture_image, "texture", pixbuf, 100, GIMP_NORMAL_MODE, 0, 0);
    gimp_image_add_layer (texture_image, texture_layer, -1);

    gint width = gimp_image_width (image_ID);
    gint height = gimp_image_height (image_ID);

    if (bvals.border->top || bvals.border->bottom || bvals.border->left || bvals.border->right)
    {
      width += bvals.border->left + bvals.border->right;
      height += bvals.border->top + bvals.border->bottom;
      gimp_image_resize (image_ID,
                         width,
                         height,
                         bvals.border->left,
                         bvals.border->top);
    }

    gint32 layer = gimp_layer_new (image_ID, "border",
                                   width, height,
                                   GIMP_RGBA_IMAGE,
                                   100,
                                   GIMP_NORMAL_MODE);
    gimp_image_add_layer (image_ID, layer, -1);

    if (width > texture_width - bvals.border->length)
      margin_x = (texture_width - bvals.border->length) / 2;
    else
      margin_x = (gdouble) width / 2;
    if (height > texture_height - bvals.border->length)
      margin_y = (texture_height - bvals.border->length) / 2;
    else
      margin_y = (gdouble) height / 2;

    /* fix gimp_context_set_pattern ("Clipboard") only works on English versions of Gimp */
    //gimp_context_set_pattern ("Clipboard");
    INIT_I18N ();
    gimp_context_set_pattern (_("Clipboard"));

    if (width > margin_x * 2) {
      /* top */
      gimp_rect_select (texture_image,
                        margin_x,
                        0,
                        texture_width - margin_x * 2,
                        margin_y,
                        GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
      gimp_edit_copy (texture_layer);
      gimp_rect_select (image_ID,
                        margin_x,
                        0,
                        width - margin_x * 2,
                        margin_y,
                        GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
      gimp_edit_fill (layer, GIMP_PATTERN_FILL);

      /* bottom */
      gimp_rect_select (texture_image,
                        margin_x,
                        texture_height - margin_y,
                        texture_width - margin_x * 2,
                        texture_height,
                        GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
      gimp_edit_copy (texture_layer);
      gimp_rect_select (image_ID,
                        margin_x,
                        height - margin_y,
                        width - margin_x * 2,
                        height,
                        GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
      gimp_edit_fill (layer, GIMP_PATTERN_FILL);
    }

    if (height > margin_y * 2) {
      /* left */
      gimp_rect_select (texture_image,
                        0,
                        margin_y,
                        margin_x,
                        texture_height - margin_y * 2,
                        GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
      gimp_edit_copy (texture_layer);
      gimp_rect_select (image_ID,
                        0,
                        margin_y,
                        margin_x,
                        height - margin_y * 2,
                        GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
      gimp_edit_fill (layer, GIMP_PATTERN_FILL);

      /* right */
      gimp_rect_select (texture_image,
                        texture_width - margin_x,
                        margin_y,
                        margin_x,
                        texture_height - margin_y * 2,
                        GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
      gimp_edit_copy (texture_layer);
      gimp_rect_select (image_ID,
                        width - margin_x,
                        margin_y,
                        margin_x,
                        height - margin_y * 2,
                        GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
      gimp_edit_fill (layer, GIMP_PATTERN_FILL);
    }

    /* top left */
    gimp_rect_select (texture_image,
                      0,
                      0,
                      margin_x,
                      margin_y,
                      GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
    gimp_edit_copy (texture_layer);
    gimp_rect_select (image_ID,
                      0,
                      0,
                      margin_x,
                      margin_y,
                      GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
    gimp_edit_fill (layer, GIMP_PATTERN_FILL);

    /* top right */
    gimp_rect_select (texture_image,
                      texture_width - margin_x,
                      0,
                      margin_x,
                      margin_y,
                      GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
    gimp_edit_copy (texture_layer);
    gimp_rect_select (image_ID,
                      width - margin_x,
                      0,
                      margin_x,
                      margin_y,
                      GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
    gimp_edit_fill (layer, GIMP_PATTERN_FILL);

    /* bottom left */
    gimp_rect_select (texture_image,
                      0,
                      texture_height - margin_y,
                      margin_x,
                      margin_y,
                      GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
    gimp_edit_copy (texture_layer);
    gimp_rect_select (image_ID,
                      0,
                      height - margin_y,
                      margin_x,
                      margin_y,
                      GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
    gimp_edit_fill (layer, GIMP_PATTERN_FILL);

    /* bottom right */
    gimp_rect_select (texture_image,
                      texture_width - margin_x,
                      texture_height - margin_y,
                      margin_x,
                      margin_y,
                      GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
    gimp_edit_copy (texture_layer);
    gimp_rect_select (image_ID,
                      width - margin_x,
                      height - margin_y,
                      margin_x,
                      margin_y,
                      GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
    gimp_edit_fill (layer, GIMP_PATTERN_FILL);

    gimp_image_merge_down(image_ID, layer, GIMP_CLIP_TO_IMAGE);

    gimp_selection_none (image_ID);
  }
}
static gint32
load_image (PopplerDocument        *doc,
            const gchar            *filename,
            GimpRunMode             run_mode,
            GimpPageSelectorTarget  target,
            guint32                 resolution,
            PdfSelectedPages       *pages)
{
    gint32   image_ID = 0;
    gint32  *images   = NULL;
    gint     i;
    gdouble  scale;
    gdouble  doc_progress = 0;

    if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
        images = g_new0 (gint32, pages->n_pages);

    gimp_progress_init_printf (_("Opening '%s'"),
                               gimp_filename_to_utf8 (filename));

    scale = resolution / gimp_unit_get_factor (GIMP_UNIT_POINT);

    /* read the file */

    for (i = 0; i < pages->n_pages; i++)
    {
        PopplerPage *page;
        gchar       *page_label;
        gdouble      page_width;
        gdouble      page_height;

        GdkPixbuf   *buf;
        gint         width;
        gint         height;

        page = poppler_document_get_page (doc, pages->pages[i]);

        poppler_page_get_size (page, &page_width, &page_height);
        width  = page_width  * scale;
        height = page_height * scale;

        g_object_get (G_OBJECT (page), "label", &page_label, NULL);

        if (! image_ID)
        {
            gchar *name;

            image_ID = gimp_image_new (width, height, GIMP_RGB);
            gimp_image_undo_disable (image_ID);

            if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
                name = g_strdup_printf (_("%s-%s"), filename, page_label);
            else
                name = g_strdup_printf (_("%s-pages"), filename);

            gimp_image_set_filename (image_ID, name);
            g_free (name);

            gimp_image_set_resolution (image_ID, resolution, resolution);
        }

        buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);

        poppler_page_render_to_pixbuf (page, 0, 0, width, height, scale, 0, buf);

        layer_from_pixbuf (image_ID, page_label, i, buf,
                           doc_progress, 1.0 / pages->n_pages);

        g_free (page_label);
        g_object_unref (buf);

        doc_progress = (double) (i + 1) / pages->n_pages;
        gimp_progress_update (doc_progress);

        if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
        {
            images[i] = image_ID;

            gimp_image_undo_enable (image_ID);
            gimp_image_clean_all (image_ID);

            image_ID = 0;
        }
    }

    if (image_ID)
    {
        gimp_image_undo_enable (image_ID);
        gimp_image_clean_all (image_ID);
    }

    if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
    {
        if (run_mode != GIMP_RUN_NONINTERACTIVE)
        {
            /* Display images in reverse order.  The last will be
             * displayed by GIMP itself
             */
            for (i = pages->n_pages - 1; i > 0; i--)
                gimp_display_new (images[i]);
        }

        image_ID = images[0];

        g_free (images);
    }

    return image_ID;
}
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
    static GimpParam  values[6];
    GimpRunMode       run_mode;
    GimpPDBStatusType status   = GIMP_PDB_SUCCESS;
    gint32            image_ID = -1;
    PopplerDocument  *doc      = NULL;
    GError           *error    = NULL;

    run_mode = param[0].data.d_int32;

    INIT_I18N ();

    *nreturn_vals = 1;
    *return_vals  = values;

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

    if (! g_thread_supported ())
        g_thread_init (NULL);

    if (strcmp (name, LOAD_PROC) == 0)
    {
        PdfSelectedPages pages = { 0, NULL };

        switch (run_mode)
        {
        case GIMP_RUN_INTERACTIVE:
            /* Possibly retrieve last settings */
            gimp_get_data (LOAD_PROC, &loadvals);

            doc = open_document (param[1].data.d_string, &error);

            if (!doc)
            {
                status = GIMP_PDB_EXECUTION_ERROR;
                break;
            }

            if (load_dialog (doc, &pages))
                gimp_set_data (LOAD_PROC, &loadvals, sizeof(loadvals));
            else
                status = GIMP_PDB_CANCEL;
            break;

        case GIMP_RUN_WITH_LAST_VALS:
            /* FIXME: implement last vals mode */
            status = GIMP_PDB_EXECUTION_ERROR;
            break;

        case GIMP_RUN_NONINTERACTIVE:
            doc = open_document (param[1].data.d_string, &error);

            if (doc)
            {
                PopplerPage *test_page = poppler_document_get_page (doc, 0);

                if (test_page)
                {
                    pages.n_pages = 1;
                    pages.pages = g_new (gint, 1);
                    pages.pages[0] = 0;

                    g_object_unref (test_page);
                }
                else
                {
                    status = GIMP_PDB_EXECUTION_ERROR;
                    g_object_unref (doc);
                }
            }
            else
            {
                status = GIMP_PDB_EXECUTION_ERROR;
            }
            break;
        }

        if (status == GIMP_PDB_SUCCESS)
        {
            image_ID = load_image (doc, param[1].data.d_string,
                                   run_mode,
                                   loadvals.target,
                                   loadvals.resolution,
                                   &pages);

            if (image_ID != -1)
            {
                *nreturn_vals = 2;
                values[1].type         = GIMP_PDB_IMAGE;
                values[1].data.d_image = image_ID;
            }
            else
            {
                status = GIMP_PDB_EXECUTION_ERROR;
            }
        }

        if (doc)
            g_object_unref (doc);

        g_free (pages.pages);
    }
    else if (strcmp (name, LOAD_THUMB_PROC) == 0)
    {
        if (nparams < 2)
        {
            status = GIMP_PDB_CALLING_ERROR;
        }
        else
        {
            gdouble      width     = 0;
            gdouble      height    = 0;
            gdouble      scale;
            gint32       image     = -1;
            gint         num_pages = 0;
            GdkPixbuf   *pixbuf    = NULL;

            /* Possibly retrieve last settings */
            gimp_get_data (LOAD_PROC, &loadvals);

            doc = open_document (param[0].data.d_string, &error);

            if (doc)
            {
                PopplerPage *page = poppler_document_get_page (doc, 0);

                if (page)
                {
                    poppler_page_get_size (page, &width, &height);

                    g_object_unref (page);
                }

                num_pages = poppler_document_get_n_pages (doc);

                pixbuf = get_thumbnail (doc, 0, param[1].data.d_int32);

                g_object_unref (doc);
            }

            if (pixbuf)
            {
                image = gimp_image_new (gdk_pixbuf_get_width  (pixbuf),
                                        gdk_pixbuf_get_height (pixbuf),
                                        GIMP_RGB);

                gimp_image_undo_disable (image);

                layer_from_pixbuf (image, "thumbnail", 0, pixbuf, 0.0, 1.0);
                g_object_unref (pixbuf);

                gimp_image_undo_enable (image);
                gimp_image_clean_all (image);
            }

            scale = loadvals.resolution / gimp_unit_get_factor (GIMP_UNIT_POINT);

            width  *= scale;
            height *= scale;

            if (image != -1)
            {
                *nreturn_vals = 6;

                values[1].type         = GIMP_PDB_IMAGE;
                values[1].data.d_image = image;
                values[2].type         = GIMP_PDB_INT32;
                values[2].data.d_int32 = width;
                values[3].type         = GIMP_PDB_INT32;
                values[3].data.d_int32 = height;
                values[4].type         = GIMP_PDB_INT32;
                values[4].data.d_int32 = GIMP_RGB_IMAGE;
                values[5].type         = GIMP_PDB_INT32;
                values[5].data.d_int32 = num_pages;
            }
            else
            {
                status = GIMP_PDB_EXECUTION_ERROR;
            }
        }

    }
    else
    {
        status = GIMP_PDB_CALLING_ERROR;
    }

    if (status != GIMP_PDB_SUCCESS && error)
    {
        *nreturn_vals = 2;
        values[1].type          = GIMP_PDB_STRING;
        values[1].data.d_string = error->message;
    }

    values[0].data.d_status = status;
}
static gint32
ReadImage (FILE        *fd,
           const gchar *filename,
           gint         len,
           gint         height,
           CMap         cmap,
           gint         ncols,
           gint         format,
           gint         interlace,
           gint         number,
           guint        leftpos,
           guint        toppos,
           guint        screenwidth,
           guint        screenheight)
{
  static gint32 image_ID   = -1;
  static gint   frame_number = 1;

  gint32        layer_ID;
  GimpPixelRgn  pixel_rgn;
  GimpDrawable *drawable;
  guchar       *dest, *temp;
  guchar        c;
  gint          xpos = 0, ypos = 0, pass = 0;
  gint          cur_progress, max_progress;
  gint          v;
  gint          i, j;
  gchar        *framename;
  gchar        *framename_ptr;
  gboolean      alpha_frame = FALSE;
  static gint   previous_disposal;

  /* Guard against bogus frame size */
  if (len < 1 || height < 1)
    {
      g_message ("Bogus frame dimensions");
      return -1;
    }

  /*
   **  Initialize the Compression routines
   */
  if (! ReadOK (fd, &c, 1))
    {
      g_message ("EOF / read error on image data");
      return -1;
    }

  if (LZWReadByte (fd, TRUE, c) < 0)
    {
      g_message ("Error while reading");
      return -1;
    }

  if (frame_number == 1)
    {
      /* Guard against bogus logical screen size values */
      if (screenwidth == 0)
        screenwidth = len;

      if (screenheight == 0)
        screenheight = height;

      image_ID = gimp_image_new (screenwidth, screenheight, GIMP_INDEXED);
      gimp_image_set_filename (image_ID, filename);

      for (i = 0, j = 0; i < ncols; i++)
        {
          used_cmap[0][i] = gimp_cmap[j++] = cmap[0][i];
          used_cmap[1][i] = gimp_cmap[j++] = cmap[1][i];
          used_cmap[2][i] = gimp_cmap[j++] = cmap[2][i];
        }

      gimp_image_set_colormap (image_ID, gimp_cmap, ncols);

      if (Gif89.delayTime < 0)
        framename = g_strdup (_("Background"));
      else
        framename = g_strdup_printf (_("Background (%d%s)"),
                                     10 * Gif89.delayTime, "ms");

      previous_disposal = Gif89.disposal;

      if (Gif89.transparent == -1)
        {
          layer_ID = gimp_layer_new (image_ID, framename,
                                     len, height,
                                     GIMP_INDEXED_IMAGE, 100, GIMP_NORMAL_MODE);
        }
      else
        {
          layer_ID = gimp_layer_new (image_ID, framename,
                                     len, height,
                                     GIMP_INDEXEDA_IMAGE, 100, GIMP_NORMAL_MODE);
          alpha_frame=TRUE;
        }

      g_free (framename);
    }
  else /* NOT FIRST FRAME */
    {
      gimp_progress_set_text_printf (_("Opening '%s' (frame %d)"),
                                     gimp_filename_to_utf8 (filename),
                                     frame_number);
      gimp_progress_pulse ();

       /* If the colourmap is now different, we have to promote to RGB! */
      if (! promote_to_rgb)
        {
          for (i = 0; i < ncols; i++)
            {
              if ((used_cmap[0][i] != cmap[0][i]) ||
                  (used_cmap[1][i] != cmap[1][i]) ||
                  (used_cmap[2][i] != cmap[2][i]))
                {
                  /* Everything is RGB(A) from now on... sigh. */
                  promote_to_rgb = TRUE;

                  /* Promote everything we have so far into RGB(A) */
#ifdef GIFDEBUG
                  g_print ("GIF: Promoting image to RGB...\n");
#endif
                  gimp_image_convert_rgb (image_ID);

                  break;
                }
            }
        }

      if (Gif89.delayTime < 0)
        framename = g_strdup_printf (_("Frame %d"), frame_number);
      else
        framename = g_strdup_printf (_("Frame %d (%d%s)"),
                                     frame_number, 10 * Gif89.delayTime, "ms");

      switch (previous_disposal)
        {
        case 0x00:
          break; /* 'don't care' */
        case 0x01:
          framename_ptr = framename;
          framename = g_strconcat (framename, " (combine)", NULL);
          g_free (framename_ptr);
          break;
        case 0x02:
          framename_ptr = framename;
          framename = g_strconcat (framename, " (replace)", NULL);
          g_free (framename_ptr);
          break;
        case 0x03:  /* Rarely-used, and unhandled by many
                       loaders/players (including GIMP: we treat as
                       'combine' mode). */
          framename_ptr = framename;
          framename = g_strconcat (framename, " (combine) (!)", NULL);
          g_free (framename_ptr);
          break;
        case 0x04: /* I've seen a composite of this type. stvo_online_banner2.gif */
        case 0x05:
        case 0x06: /* I've seen a composite of this type. bn31.Gif */
        case 0x07:
          framename_ptr = framename;
          framename = g_strconcat (framename, " (unknown disposal)", NULL);
          g_free (framename_ptr);
          g_message (_("GIF: Undocumented GIF composite type %d is "
                       "not handled.  Animation might not play or "
                       "re-save perfectly."),
                     previous_disposal);
          break;
        default:
          g_message ("Disposal word got corrupted.  Bug.");
          break;
        }
      previous_disposal = Gif89.disposal;

      layer_ID = gimp_layer_new (image_ID, framename,
                                 len, height,
                                 promote_to_rgb ?
                                 GIMP_RGBA_IMAGE : GIMP_INDEXEDA_IMAGE,
                                 100, GIMP_NORMAL_MODE);
      alpha_frame = TRUE;
      g_free (framename);
    }

  frame_number++;

  gimp_image_insert_layer (image_ID, layer_ID, -1, 0);
  gimp_layer_translate (layer_ID, (gint) leftpos, (gint) toppos);

  drawable = gimp_drawable_get (layer_ID);

  cur_progress = 0;
  max_progress = height;

  if (alpha_frame)
    dest = (guchar *) g_malloc (len * height * (promote_to_rgb ? 4 : 2));
  else
    dest = (guchar *) g_malloc (len * height);

#ifdef GIFDEBUG
    g_print ("GIF: reading %d by %d%s GIF image, ncols=%d\n",
             len, height, interlace ? " interlaced" : "", ncols);
#endif

  if (! alpha_frame && promote_to_rgb)
    {
      /* I don't see how one would easily construct a GIF in which
         this could happen, but it's a mad mad world. */
      g_message ("Ouch!  Can't handle non-alpha RGB frames.\n"
                 "Please file a bug report in GIMP's bugzilla.");
      gimp_quit ();
    }

  while ((v = LZWReadByte (fd, FALSE, c)) >= 0)
    {
      if (alpha_frame)
        {
          if (((guchar) v > highest_used_index) && !(v == Gif89.transparent))
            highest_used_index = (guchar) v;

          if (promote_to_rgb)
            {
              temp = dest + ( (ypos * len) + xpos ) * 4;
              *(temp  ) = (guchar) cmap[0][v];
              *(temp+1) = (guchar) cmap[1][v];
              *(temp+2) = (guchar) cmap[2][v];
              *(temp+3) = (guchar) ((v == Gif89.transparent) ? 0 : 255);
            }
          else
            {
              temp = dest + ( (ypos * len) + xpos ) * 2;
              *temp = (guchar) v;
              *(temp+1) = (guchar) ((v == Gif89.transparent) ? 0 : 255);
            }
        }
      else
        {
          if ((guchar) v > highest_used_index)
            highest_used_index = (guchar) v;

          temp = dest + (ypos * len) + xpos;
          *temp = (guchar) v;
        }

      xpos++;
      if (xpos == len)
        {
          xpos = 0;
          if (interlace)
            {
              switch (pass)
                {
                case 0:
                case 1:
                  ypos += 8;
                  break;
                case 2:
                  ypos += 4;
                  break;
                case 3:
                  ypos += 2;
                  break;
                }

              if (ypos >= height)
                {
                  pass++;
                  switch (pass)
                    {
                    case 1:
                      ypos = 4;
                      break;
                    case 2:
                      ypos = 2;
                      break;
                    case 3:
                      ypos = 1;
                      break;
                    default:
                      goto fini;
                    }
                }
            }
          else
            {
              ypos++;
            }

          if (frame_number == 1)
            {
              cur_progress++;
              if ((cur_progress % 16) == 0)
                gimp_progress_update ((gdouble) cur_progress /
                                      (gdouble) max_progress);
            }
        }

      if (ypos >= height)
        break;
    }

 fini:
  if (LZWReadByte (fd, FALSE, c) >= 0)
    g_print ("GIF: too much input data, ignoring extra...\n");

  gimp_pixel_rgn_init (&pixel_rgn, drawable,
                       0, 0, drawable->width, drawable->height, TRUE, FALSE);
  gimp_pixel_rgn_set_rect (&pixel_rgn, dest,
                           0, 0, drawable->width, drawable->height);

  g_free (dest);

  gimp_drawable_flush (drawable);
  gimp_drawable_detach (drawable);

  return image_ID;
}
Beispiel #29
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;
}
Beispiel #30
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);
}