void callback_new_mask_button (GtkWidget * button, gpointer data) { gint32 layer_ID; NewLayerData *nl_data = NEW_LAYER_DATA (data); PreviewData *p_data = nl_data->preview_data; GimpImageType image_type; IMAGE_CHECK_ACTION(p_data->image_ID, gtk_dialog_response (GTK_DIALOG (dlg), RESPONSE_FATAL), ); switch (gimp_image_base_type (p_data->image_ID)) { case GIMP_RGB: image_type = GIMP_RGBA_IMAGE; break; case GIMP_GRAY: image_type = GIMP_GRAYA_IMAGE; break; default: return; } gimp_image_undo_group_start (p_data->image_ID); layer_ID = gimp_layer_new (p_data->image_ID, nl_data->name, p_data->old_width, p_data->old_height, image_type, 50, GIMP_NORMAL_MODE); gimp_image_add_layer (p_data->image_ID, layer_ID, -1); gimp_drawable_fill (layer_ID, GIMP_TRANSPARENT_FILL); gimp_layer_translate (layer_ID, p_data->x_off, p_data->y_off); gimp_image_undo_group_end (p_data->image_ID); *(nl_data->layer_ID) = layer_ID; *(nl_data->status) = TRUE; nl_data->preview_data->ui_vals->layer_on_edit_ID = layer_ID; nl_data->preview_data->ui_vals->layer_on_edit_type = nl_data->layer_type; nl_data->preview_data->ui_vals->layer_on_edit_is_new = TRUE; g_free(nl_data); gtk_dialog_response (GTK_DIALOG(dlg), RESPONSE_WORK_ON_AUX_LAYER); }
static gboolean apply_resize(resize_settings settings, image_output out) { gboolean success = FALSE; gint orig_w, orig_h, final_w, final_h, view_w, view_h; gdouble orig_res_x, orig_res_y; if (settings->change_res) { success = gimp_image_get_resolution( out->image_id, &orig_res_x, &orig_res_y ); if ((settings->new_res_x != orig_res_x) || (settings->new_res_y != orig_res_y)) { // change resolution success = gimp_image_set_resolution( out->image_id, settings->new_res_x, settings->new_res_y ); } } orig_w = gimp_image_width(out->image_id); orig_h = gimp_image_height(out->image_id); if (settings->resize_mode == RESIZE_PERCENT) { if (settings->stretch_mode == STRETCH_ASPECT) { gdouble newpct = min(settings->new_w_pc, settings->new_h_pc); final_w = view_w = round((orig_w * newpct) / 100.0); final_h = view_h = round((orig_h * newpct) / 100.0); } else if (settings->stretch_mode == STRETCH_PADDED) { gdouble newpct = min(settings->new_w_pc, settings->new_h_pc); final_w = round((orig_w * newpct) / 100.0); final_h = round((orig_h * newpct) / 100.0); view_w = round((orig_w * settings->new_w_pc) / 100.0); view_h = round((orig_h * settings->new_h_pc) / 100.0); } else { final_w = view_w = round((orig_w * settings->new_w_pc) / 100.0); final_h = view_h = round((orig_h * settings->new_h_pc) / 100.0); } } else { // user typed exact pixel size if (settings->resize_mode == RESIZE_PIXEL_WIDTH) { view_w = settings->new_w_px; // width is fixed if (settings->stretch_mode == STRETCH_ASPECT) { final_w = view_w; final_h = view_h = round(((float)final_w * orig_h) / orig_w); } else if (settings->stretch_mode == STRETCH_PADDED) { final_w = min(view_w, orig_w); final_h = round(((float)final_w * orig_h) / orig_w); view_h = max(orig_h, final_h); } else { final_w = view_w; final_h = view_h = orig_h; } } else if (settings->resize_mode == RESIZE_PIXEL_HEIGHT) { view_h = settings->new_h_px; // height is fixed if (settings->stretch_mode == STRETCH_ASPECT) { final_h = view_h; final_w = view_w = round(((float)final_h * orig_w) / orig_h); } else if (settings->stretch_mode == STRETCH_PADDED) { final_h = min(view_h, orig_h); final_w = round(((float)final_h * orig_w) / orig_h); view_w = max(orig_w, final_w); } else { final_h = view_h; final_w = view_w = orig_w; } } else { // both dimensions are defined if (settings->stretch_mode == STRETCH_ASPECT) { // Find which new dimension is the smallest percentage of the existing image dimension gdouble newwpct = (float)settings->new_w_px / (float)orig_w; gdouble newhpct = (float)settings->new_h_px / (float)orig_h; gdouble newpct = min(newwpct, newhpct); final_w = view_w = round(orig_w * newpct); final_h = view_h = round(orig_h * newpct); } else if (settings->stretch_mode == STRETCH_PADDED) { // Find which new dimension is the smallest percentage of the existing image dimension gdouble newwpct = (float)settings->new_w_px / (float)orig_w; gdouble newhpct = (float)settings->new_h_px / (float)orig_h; gdouble newpct = min(newwpct, newhpct); final_w = round(orig_w * newpct); final_h = round(orig_h * newpct); view_w = round(orig_w * newwpct); view_h = round(orig_h * newhpct); } else { final_w = view_w = settings->new_w_px; final_h = view_h = settings->new_h_px; } } } // do resize #if USE_API26 success = gimp_image_scale_full ( out->image_id, final_w, final_h, settings->interpolation ); #else // starting from 2.8, gimp_image_scale_full is deprecated. // use gimp_image_scale instead GimpInterpolationType old_interpolation; old_interpolation = gimp_context_get_interpolation(); success = gimp_context_set_interpolation (settings->interpolation); success = gimp_image_scale ( out->image_id, final_w, final_h ); success = gimp_context_set_interpolation (old_interpolation); #endif // add a padding if requested if (settings->stretch_mode == STRETCH_PADDED) { // the padding will be drawn using a coloured layer at the bottom of the image gint32 layerId = gimp_layer_new( out->image_id, "padding_layer", view_w, view_h, GIMP_RGBA_IMAGE, (settings->padding_color_alpha / (float)G_MAXUINT16) * 100, GIMP_NORMAL_MODE ); #if USE_API26 gimp_image_add_layer ( out->image_id, layerId, 0 ); gimp_image_lower_layer_to_bottom(out->image_id, layerId); #else gimp_image_insert_layer( out->image_id, layerId, 0, 0 ); gimp_image_lower_item_to_bottom(out->image_id, layerId); #endif // fill it with the selected color GimpRGB old_background, new_background; gimp_context_get_background(&old_background); gimp_rgb_parse_hex (&new_background, gdk_color_to_string(&(settings->padding_color)), strlen(gdk_color_to_string(&(settings->padding_color)))); gimp_context_set_background(&new_background); gimp_drawable_fill(layerId, GIMP_BACKGROUND_FILL); gimp_context_set_background(&old_background); // move it to the center gimp_layer_translate(layerId, -abs(view_w - final_w) / 2, -abs(view_h - final_h) / 2); // finish changing the canvas size accordingly success = gimp_image_resize_to_layers(out->image_id); } return success; }
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; }