/** * gimp_image_set_cmap: * @image_ID: The image. * @cmap: The new colormap values. * @num_colors: Number of colors in the colormap array. * * This procedure is deprecated! Use gimp_image_set_colormap() instead. * * Returns: TRUE on success. */ gboolean gimp_image_set_cmap (gint32 image_ID, const guchar *cmap, gint num_colors) { return gimp_image_set_colormap (image_ID, cmap, num_colors); }
static void lcms_image_transform_indexed (gint32 image, cmsHPROFILE src_profile, cmsHPROFILE dest_profile, GimpColorRenderingIntent intent, gboolean bpc) { cmsHTRANSFORM transform; guchar *cmap; gint num_colors; cmap = gimp_image_get_colormap (image, &num_colors); transform = cmsCreateTransform (src_profile, TYPE_RGB_8, dest_profile, TYPE_RGB_8, intent, bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0); if (transform) { cmsDoTransform (transform, cmap, cmap, num_colors); cmsDeleteTransform(transform); } else { g_warning ("cmsCreateTransform() failed!"); } gimp_image_set_colormap (image, cmap, num_colors); }
static void indexed_autostretch_hsv (gint32 image_ID) { guchar *cmap; AutostretchData data = {0.0, 1.0, 0.0, 1.0}; gint ncols, i; cmap = gimp_image_get_colormap (image_ID, &ncols); if (!cmap) { g_message (_("autostretch_hsv: cmap was NULL! Quitting...\n")); gimp_quit (); } for (i = 0; i < ncols; i++) { find_max (&cmap[i * 3], 3, &data); } for (i = 0; i < ncols; i++) { autostretch_hsv_func (&cmap[i * 3], &cmap[i * 3], 3, &data); } gimp_image_set_colormap (image_ID, cmap, ncols); }
static void lcms_image_transform_indexed (gint32 image, cmsHPROFILE src_profile, cmsHPROFILE dest_profile, GimpColorRenderingIntent intent, gboolean bpc) { cmsHTRANSFORM transform; guchar *cmap; gint n_cmap_bytes; cmsUInt32Number format = TYPE_RGB_8; cmap = gimp_image_get_colormap (image, &n_cmap_bytes); transform = cmsCreateTransform (src_profile, format, dest_profile, format, intent, cmsFLAGS_NOOPTIMIZE | (bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0)); if (transform) { cmsDoTransform (transform, cmap, cmap, n_cmap_bytes / 3); cmsDeleteTransform (transform); } else { g_warning ("cmsCreateTransform() failed!"); } gimp_image_set_colormap (image, cmap, n_cmap_bytes); }
static void indexed_normalize (gint32 image_ID) /* a.d.m. */ { guchar *cmap; gint ncols,i; gint hi=0,lo=255; cmap = gimp_image_get_colormap (image_ID, &ncols); if (cmap==NULL) { g_printerr ("normalize: cmap was NULL! Quitting...\n"); return; } for (i=0;i<ncols;i++) { if (cmap[i*3 +0] > hi) hi=cmap[i*3 +0]; if (cmap[i*3 +1] > hi) hi=cmap[i*3 +1]; if (cmap[i*3 +2] > hi) hi=cmap[i*3 +2]; if (cmap[i*3 +0] < lo) lo=cmap[i*3 +0]; if (cmap[i*3 +1] < lo) lo=cmap[i*3 +1]; if (cmap[i*3 +2] < lo) lo=cmap[i*3 +2]; } if (hi!=lo) for (i=0;i<ncols;i++) { cmap[i*3 +0] = (255 * (cmap[i*3 +0] - lo)) / (hi-lo); cmap[i*3 +1] = (255 * (cmap[i*3 +1] - lo)) / (hi-lo); cmap[i*3 +2] = (255 * (cmap[i*3 +2] - lo)) / (hi-lo); } gimp_image_set_colormap (image_ID, cmap, ncols); }
static void gimp_image_duplicate_colormap (GimpImage *image, GimpImage *new_image) { if (gimp_image_get_base_type (new_image) == GIMP_INDEXED) gimp_image_set_colormap (new_image, gimp_image_get_colormap (image), gimp_image_get_colormap_size (image), FALSE); }
static void gimp_image_convert_profile_indexed (GimpImage *image, GimpColorProfile *src_profile, GimpColorProfile *dest_profile, GimpColorRenderingIntent intent, gboolean bpc, GimpProgress *progress) { cmsHPROFILE src_lcms; cmsHPROFILE dest_lcms; guchar *cmap; gint n_colors; GimpColorTransform transform; src_lcms = gimp_color_profile_get_lcms_profile (src_profile); dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile); n_colors = gimp_image_get_colormap_size (image); cmap = g_memdup (gimp_image_get_colormap (image), n_colors * 3); transform = cmsCreateTransform (src_lcms, TYPE_RGB_8, dest_lcms, TYPE_RGB_8, intent, cmsFLAGS_NOOPTIMIZE | (bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0)); if (transform) { cmsDoTransform (transform, cmap, cmap, n_colors); cmsDeleteTransform (transform); gimp_image_set_colormap (image, cmap, n_colors, TRUE); } else { g_warning ("cmsCreateTransform() failed!"); } g_free (cmap); }
static void gimp_display_shell_drop_drawable (GtkWidget *widget, gint x, gint y, GimpViewable *viewable, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *image = shell->display->image; GType new_type; GimpItem *new_item; gboolean new_image = FALSE; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! image) { GimpImage *src_image = gimp_item_get_image (GIMP_ITEM (viewable)); GimpDrawable *drawable = GIMP_DRAWABLE (viewable); GimpImageBaseType type; gdouble xres; gdouble yres; type = GIMP_IMAGE_TYPE_BASE_TYPE (gimp_drawable_type (drawable)); image = gimp_create_image (shell->display->gimp, gimp_item_width (GIMP_ITEM (viewable)), gimp_item_height (GIMP_ITEM (viewable)), type, TRUE); gimp_image_undo_disable (image); if (type == GIMP_INDEXED) gimp_image_set_colormap (image, gimp_image_get_colormap (src_image), gimp_image_get_colormap_size (src_image), FALSE); gimp_image_get_resolution (src_image, &xres, &yres); gimp_image_set_resolution (image, xres, yres); gimp_image_set_unit (image, gimp_image_get_unit (src_image)); gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0); g_object_unref (image); new_image = TRUE; } if (GIMP_IS_LAYER (viewable)) new_type = G_TYPE_FROM_INSTANCE (viewable); else new_type = GIMP_TYPE_LAYER; new_item = gimp_item_convert (GIMP_ITEM (viewable), image, new_type); if (new_item) { GimpLayer *new_layer = GIMP_LAYER (new_item); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); if (! new_image) gimp_display_shell_dnd_position_item (shell, new_item); gimp_item_set_visible (new_item, TRUE, FALSE); gimp_item_set_linked (new_item, FALSE, FALSE); gimp_image_add_layer (image, new_layer, -1); gimp_image_undo_group_end (image); gimp_display_shell_dnd_flush (shell, image); } if (new_image) gimp_image_undo_enable (image); }
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); }
static void run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[4]; GimpPDBStatusType status = GIMP_PDB_SUCCESS; GError *error = NULL; gint32 image_ID; INIT_I18N (); *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; if (strcmp (name, LOAD_PROC) == 0) { image_ID = load_image (param[1].data.d_string, FALSE, &error); } else if (strcmp (name, LOAD_THUMB_PROC) == 0) { image_ID = load_image (param[0].data.d_string, TRUE, &error); } else { status = GIMP_PDB_CALLING_ERROR; } if (status == GIMP_PDB_SUCCESS) { if (image_ID != -1) { /* The GIF format only tells you how many bits per pixel * are in the image, not the actual number of used indices (D'OH!) * * So if we're not careful, repeated load/save of a transparent GIF * without intermediate indexed->RGB->indexed pumps up the number of * bits used, as we add an index each time for the transparent * colour. Ouch. We either do some heavier analysis at save-time, * or trim down the number of GIMP colours at load-time. We do the * latter for now. */ #ifdef GIFDEBUG g_print ("GIF: Highest used index is %d\n", highest_used_index); #endif if (! promote_to_rgb) gimp_image_set_colormap (image_ID, gimp_cmap, highest_used_index + 1); *nreturn_vals = 2; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image_ID; if (strcmp (name, LOAD_THUMB_PROC) == 0) { *nreturn_vals = 4; values[2].type = GIMP_PDB_INT32; values[2].data.d_int32 = gimp_image_width (image_ID); values[3].type = GIMP_PDB_INT32; values[3].data.d_int32 = gimp_image_height (image_ID); } } else { status = GIMP_PDB_EXECUTION_ERROR; if (error) { *nreturn_vals = 2; values[1].type = GIMP_PDB_STRING; values[1].data.d_string = error->message; } } } values[0].data.d_status = status; }
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); }
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; }
GimpImage * gimp_image_duplicate (GimpImage *image) { GimpImage *new_image; GimpLayer *floating_layer; GList *list; GimpLayer *active_layer = NULL; GimpChannel *active_channel = NULL; GimpVectors *active_vectors = NULL; GimpDrawable *new_floating_sel_drawable = NULL; GimpDrawable *floating_sel_drawable = NULL; gchar *filename; gint count; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); gimp_set_busy_until_idle (image->gimp); /* Create a new image */ new_image = gimp_create_image (image->gimp, image->width, image->height, image->base_type, FALSE); gimp_image_undo_disable (new_image); /* Store the folder to be used by the save dialog */ filename = gimp_image_get_filename (image); if (filename) { g_object_set_data_full (G_OBJECT (new_image), "gimp-image-dirname", g_path_get_dirname (filename), (GDestroyNotify) g_free); g_free (filename); } /* Copy the colormap if necessary */ if (new_image->base_type == GIMP_INDEXED) gimp_image_set_colormap (new_image, gimp_image_get_colormap (image), gimp_image_get_colormap_size (image), FALSE); /* Copy resolution information */ new_image->xresolution = image->xresolution; new_image->yresolution = image->yresolution; new_image->resolution_unit = image->resolution_unit; /* Copy floating layer */ floating_layer = gimp_image_floating_sel (image); if (floating_layer) { floating_sel_relax (floating_layer, FALSE); floating_sel_drawable = floating_layer->fs.drawable; floating_layer = NULL; } /* Copy the layers */ for (list = GIMP_LIST (image->layers)->list, count = 0; list; list = g_list_next (list)) { GimpLayer *layer = list->data; GimpLayer *new_layer; new_layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (layer), new_image, G_TYPE_FROM_INSTANCE (layer), FALSE)); /* Make sure the copied layer doesn't say: "<old layer> copy" */ gimp_object_set_name (GIMP_OBJECT (new_layer), gimp_object_get_name (GIMP_OBJECT (layer))); /* Make sure that if the layer has a layer mask, * its name isn't screwed up */ if (new_layer->mask) gimp_object_set_name (GIMP_OBJECT (new_layer->mask), gimp_object_get_name (GIMP_OBJECT (layer->mask))); if (gimp_image_get_active_layer (image) == layer) active_layer = new_layer; if (image->floating_sel == layer) floating_layer = new_layer; if (floating_sel_drawable == GIMP_DRAWABLE (layer)) new_floating_sel_drawable = GIMP_DRAWABLE (new_layer); if (floating_layer != new_layer) gimp_image_add_layer (new_image, new_layer, count++); } /* Copy the channels */ for (list = GIMP_LIST (image->channels)->list, count = 0; list; list = g_list_next (list)) { GimpChannel *channel = list->data; GimpChannel *new_channel; new_channel = GIMP_CHANNEL (gimp_item_convert (GIMP_ITEM (channel), new_image, G_TYPE_FROM_INSTANCE (channel), FALSE)); /* Make sure the copied channel doesn't say: "<old channel> copy" */ gimp_object_set_name (GIMP_OBJECT (new_channel), gimp_object_get_name (GIMP_OBJECT (channel))); if (gimp_image_get_active_channel (image) == channel) active_channel = (new_channel); if (floating_sel_drawable == GIMP_DRAWABLE (channel)) new_floating_sel_drawable = GIMP_DRAWABLE (new_channel); gimp_image_add_channel (new_image, new_channel, count++); } /* Copy any vectors */ for (list = GIMP_LIST (image->vectors)->list, count = 0; list; list = g_list_next (list)) { GimpVectors *vectors = list->data; GimpVectors *new_vectors; new_vectors = GIMP_VECTORS (gimp_item_convert (GIMP_ITEM (vectors), new_image, G_TYPE_FROM_INSTANCE (vectors), FALSE)); /* Make sure the copied vectors doesn't say: "<old vectors> copy" */ gimp_object_set_name (GIMP_OBJECT (new_vectors), gimp_object_get_name (GIMP_OBJECT (vectors))); if (gimp_image_get_active_vectors (image) == vectors) active_vectors = new_vectors; gimp_image_add_vectors (new_image, new_vectors, count++); } /* Copy the selection mask */ { TileManager *src_tiles; TileManager *dest_tiles; PixelRegion srcPR, destPR; src_tiles = gimp_drawable_get_tiles (GIMP_DRAWABLE (image->selection_mask)); dest_tiles = gimp_drawable_get_tiles (GIMP_DRAWABLE (new_image->selection_mask)); pixel_region_init (&srcPR, src_tiles, 0, 0, image->width, image->height, FALSE); pixel_region_init (&destPR, dest_tiles, 0, 0, image->width, image->height, TRUE); copy_region (&srcPR, &destPR); new_image->selection_mask->bounds_known = FALSE; new_image->selection_mask->boundary_known = FALSE; } if (floating_layer) floating_sel_attach (floating_layer, new_floating_sel_drawable); /* Set active layer, active channel, active vectors */ if (active_layer) gimp_image_set_active_layer (new_image, active_layer); if (active_channel) gimp_image_set_active_channel (new_image, active_channel); if (active_vectors) gimp_image_set_active_vectors (new_image, active_vectors); /* Copy state of all color channels */ for (count = 0; count < MAX_CHANNELS; count++) { new_image->visible[count] = image->visible[count]; new_image->active[count] = image->active[count]; } /* Copy any guides */ for (list = image->guides; list; list = g_list_next (list)) { GimpGuide *guide = list->data; gint position = gimp_guide_get_position (guide); switch (gimp_guide_get_orientation (guide)) { case GIMP_ORIENTATION_HORIZONTAL: gimp_image_add_hguide (new_image, position, FALSE); break; case GIMP_ORIENTATION_VERTICAL: gimp_image_add_vguide (new_image, position, FALSE); break; default: g_error ("Unknown guide orientation.\n"); } } /* Copy any sample points */ for (list = image->sample_points; list; list = g_list_next (list)) { GimpSamplePoint *sample_point = list->data; gimp_image_add_sample_point_at_pos (new_image, sample_point->x, sample_point->y, FALSE); } /* Copy the grid */ if (image->grid) gimp_image_set_grid (new_image, image->grid, FALSE); /* Copy the quick mask info */ new_image->quick_mask_state = image->quick_mask_state; new_image->quick_mask_inverted = image->quick_mask_inverted; new_image->quick_mask_color = image->quick_mask_color; /* Copy parasites */ if (image->parasites) { g_object_unref (new_image->parasites); new_image->parasites = gimp_parasite_list_copy (image->parasites); } gimp_image_undo_enable (new_image); return new_image; }
static gboolean remap (gint32 image_ID, gint num_colors, guchar *map) { guchar *cmap; guchar *new_cmap; guchar *new_cmap_i; gint ncols; gint num_layers; gint32 *layers; gint i, j, k; glong pixels = 0; glong processed = 0; guchar pixel_map[256]; gboolean valid[256]; cmap = gimp_image_get_colormap (image_ID, &ncols); g_return_val_if_fail (cmap != NULL, FALSE); g_return_val_if_fail (ncols > 0, FALSE); if (num_colors != ncols) { g_message (_("Invalid remap array was passed to remap function")); return FALSE; } for (i = 0; i < ncols; i++) valid[i] = FALSE; for (i = 0; i < ncols; i++) { if (map[i] >= ncols) { g_message (_("Invalid remap array was passed to remap function")); return FALSE; } valid[map[i]] = TRUE; pixel_map[map[i]] = i; } for (i = 0; i < ncols; i++) if (valid[i] == FALSE) { g_message (_("Invalid remap array was passed to remap function")); return FALSE; } new_cmap = g_new (guchar, ncols * 3); new_cmap_i = new_cmap; for (i = 0; i < ncols; i++) { j = map[i] * 3; *new_cmap_i++ = cmap[j]; *new_cmap_i++ = cmap[j + 1]; *new_cmap_i++ = cmap[j + 2]; } gimp_image_undo_group_start (image_ID); gimp_image_set_colormap (image_ID, new_cmap, ncols); g_free (cmap); g_free (new_cmap); gimp_progress_init (_("Rearranging the colormap")); layers = gimp_image_get_layers (image_ID, &num_layers); for (k = 0; k < num_layers; k++) pixels += gimp_drawable_width (layers[k]) * gimp_drawable_height (layers[k]); for (k = 0; k < num_layers; k++) { GimpDrawable *drawable; GimpPixelRgn src_rgn, dest_rgn; gint width, height, bytespp; gint update; gpointer pr; drawable = gimp_drawable_get (layers[k]); width = drawable->width; height = drawable->height; bytespp = drawable->bpp; gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&dest_rgn, drawable, 0, 0, width, height, TRUE, TRUE); for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn), update = 0; pr != NULL; pr = gimp_pixel_rgns_process (pr), update++) { const guchar *src_row = src_rgn.data; guchar *dest_row = dest_rgn.data; for (i = 0; i < src_rgn.h; i++) { const guchar *src = src_row; guchar *dest = dest_row; if (bytespp == 1) { for (j = 0; j < src_rgn.w; j++) *dest++ = pixel_map[*src++]; } else { for (j = 0; j < src_rgn.w; j++) { *dest++ = pixel_map[*src++]; *dest++ = *src++; } } src_row += src_rgn.rowstride; dest_row += dest_rgn.rowstride; } processed += src_rgn.w * src_rgn.h; update %= 16; if (update == 0) gimp_progress_update ((gdouble) processed / pixels); } gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, 0, 0, width, height); gimp_drawable_detach (drawable); } gimp_progress_update (1.0); gimp_image_undo_group_end (image_ID); return TRUE; }
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; }
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; }
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); }