/* gap_split.c * 1997.11.06 hof (Wolfgang Hofer) * * GAP ... Gimp Animation Plugins * * This Module contains * - gap_split_image * */ /* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* revision history * 1.1.9a; 1999/09/21 hof: bugfix RUN_NONINTERACTIVE mode did not work * 1.1.8a; 1999/08/31 hof: accept anim framenames without underscore '_' * 1.1.5a; 1999/05/08 hof: bugix (dont mix GDrawableType with GImageType) * 0.96.00; 1998/07/01 hof: - added scale, resize and crop * (affects full range == all anim frames) * - now using gap_arr_dialog.h * 0.94.01; 1998/04/28 hof: added flatten_mode to plugin: gap_range_to_multilayer * 0.92.00 1998.01.10 hof: bugfix in p_frames_to_multilayer * layers need alpha (to be raise/lower able) * 0.90.00 first development release */ #include "config.h" /* SYTEM (UNIX) includes */ #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif /* GIMP includes */ #include "gtk/gtk.h" #include "config.h" #include "libgimp/stdplugins-intl.h" #include "libgimp/gimp.h" /* GAP includes */ #include "gap_layer_copy.h" #include "gap_lib.h" #include "gap_arr_dialog.h" extern int gap_debug; /* ==0 ... dont print debug infos */ /* ============================================================================ * p_split_image * * returns value >= 0 if all is ok return the image_id of * the new created image (the last handled anim frame) * (or -1 on error) * ============================================================================ */ static int p_split_image(t_anim_info *ainfo_ptr, char *new_extension, gint invers, gint no_alpha) { GImageType l_type; guint l_width, l_height; GRunModeType l_run_mode; gint32 l_new_image_id; gint l_nlayers; gint32 *l_layers_list; gint32 l_src_layer_id; gint32 l_cp_layer_id; gint l_src_offset_x, l_src_offset_y; /* layeroffsets as they were in src_image */ gdouble l_percentage, l_percentage_step; char *l_sav_name; char *l_str; gint32 l_rc; int l_idx; long l_layer_idx; if(gap_debug) printf("DEBUG: p_split_image inv:%d no_alpha:%d ext:%s\n", (int)invers, (int)no_alpha, new_extension); l_rc = -1; l_percentage = 0.0; l_run_mode = ainfo_ptr->run_mode; if(ainfo_ptr->run_mode == RUN_INTERACTIVE) { gimp_progress_init( _("Splitting into Frames ..")); } l_new_image_id = -1; /* get info about the image */ l_width = gimp_image_width(ainfo_ptr->image_id); l_height = gimp_image_height(ainfo_ptr->image_id); l_type = gimp_image_base_type(ainfo_ptr->image_id); l_layers_list = gimp_image_get_layers(ainfo_ptr->image_id, &l_nlayers); if(l_layers_list != NULL) { l_percentage_step = 1.0 / (l_nlayers); for(l_idx = 0; l_idx < l_nlayers; l_idx++) { if(l_new_image_id >= 0) { /* destroy the tmp image (it was saved to disk before) */ gimp_image_delete(l_new_image_id); } if(invers == TRUE) l_layer_idx = l_idx; else l_layer_idx = (l_nlayers - 1 ) - l_idx; l_src_layer_id = l_layers_list[l_layer_idx]; /* create new image */ l_new_image_id = gimp_image_new(l_width, l_height,l_type); if(l_new_image_id < 0) { l_rc = -1; break; } /* copy the layer */ l_cp_layer_id = p_my_layer_copy(l_new_image_id, l_src_layer_id, 100.0, /* Opacity */ 0, /* NORMAL */ &l_src_offset_x, &l_src_offset_y); /* add the copied layer to current destination image */ gimp_image_add_layer(l_new_image_id, l_cp_layer_id, 0); gimp_layer_set_offsets(l_cp_layer_id, l_src_offset_x, l_src_offset_y); /* delete alpha channel ? */ if (no_alpha == TRUE) { /* add a dummy layer (flatten needs at least 2 layers) */ l_cp_layer_id = gimp_layer_new(l_new_image_id, "dummy", 4, 4, /* width, height */ ((l_type * 2 ) + 1), /* convert from GImageType to GDrawableType, and add alpha */ 0.0, /* Opacity full transparent */ 0); /* NORMAL */ gimp_image_add_layer(l_new_image_id, l_cp_layer_id, 0); gimp_image_flatten (l_new_image_id); } /* build the name for output image */ l_str = p_strdup_add_underscore(ainfo_ptr->basename); l_sav_name = p_alloc_fname(l_str, (l_idx +1), /* start at 1 (not at 0) */ new_extension); g_free(l_str); if(l_sav_name != NULL) { /* save with selected save procedure * (regardless if image was flattened or not) */ l_rc = p_save_named_image(l_new_image_id, l_sav_name, l_run_mode); if(l_rc < 0) { p_msg_win(ainfo_ptr->run_mode, _("Split Frames: SAVE operation FAILED\n- desired save plugin cant handle type\n- or desired save plugin not available\n")); break; } l_run_mode = RUN_NONINTERACTIVE; /* for all further calls */ /* set image name */ gimp_image_set_filename (l_new_image_id, l_sav_name); /* prepare return value */ l_rc = l_new_image_id; g_free(l_sav_name); } /* save as frame */ /* show progress bar */ if(ainfo_ptr->run_mode == RUN_INTERACTIVE) { l_percentage += l_percentage_step; gimp_progress_update (l_percentage); } } g_free (l_layers_list); } return l_rc; } /* end p_split_image */ /* ============================================================================ * p_split_dialog * * return 0 (OK) * or -1 in case of Error or cancel * ============================================================================ */ static long p_split_dialog(t_anim_info *ainfo_ptr, gint *inverse_order, gint *no_alpha, char *extension, gint len_ext) { static t_arr_arg argv[4]; gchar *buf; buf = g_strdup_printf (_("%s\n%s\n(%s_0001.%s)\n"), _("Make a frame (diskfile) from each Layer"), _("frames are named: base_nr.extension"), ainfo_ptr->basename, extension); p_init_arr_arg(&argv[0], WGT_LABEL); argv[0].label_txt = &buf[0]; p_init_arr_arg(&argv[1], WGT_TEXT); argv[1].label_txt = _("Extension:"); argv[1].help_txt = _("extension of resulting frames \n(is also used to define Fileformat)"); argv[1].text_buf_len = len_ext; argv[1].text_buf_ret = extension; p_init_arr_arg(&argv[2], WGT_TOGGLE); argv[2].label_txt = _("Inverse Order :"); argv[2].help_txt = _("Start frame 0001 at Top Layer"); argv[2].int_ret = 0; p_init_arr_arg(&argv[3], WGT_TOGGLE); argv[3].label_txt = _("Flatten :"); argv[3].help_txt = _("Remove Alpha Channel in resulting Frames, \ntransparent parts are filled with BG color"); argv[3].int_ret = 0; if(TRUE == p_array_dialog( _("Split Image into Frames"), _("Split Settings :"), 4, argv)) { g_free (buf); *inverse_order = argv[2].int_ret; *no_alpha = argv[3].int_ret; return 0; } else { g_free (buf); return -1; } } /* end p_split_dialog */ /* ============================================================================ * gap_split_image * Split one (multilayer) image into anim-frames * one frame per layer. * ============================================================================ */ int gap_split_image(GRunModeType run_mode, gint32 image_id, gint32 inverse_order, gint32 no_alpha, char *extension) { gint32 l_new_image_id; gint32 l_rc; gint32 l_inverse_order; gint32 l_no_alpha; t_anim_info *ainfo_ptr; char l_extension[32]; strcpy(l_extension, ".xcf"); l_rc = -1; ainfo_ptr = p_alloc_ainfo(image_id, run_mode); if(ainfo_ptr != NULL) { if (0 == p_dir_ainfo(ainfo_ptr)) { if(ainfo_ptr->frame_cnt != 0) { p_msg_win(run_mode, _("OPERATION CANCELLED\nThis image is already an AnimFrame\nTry again on a Duplicate\n(image/channel ops/duplicate)")); return -1; } else { if(run_mode == RUN_INTERACTIVE) { l_rc = p_split_dialog (ainfo_ptr, &l_inverse_order, &l_no_alpha, &l_extension[0], sizeof(l_extension)); } else { l_rc = 0; l_inverse_order = inverse_order; l_no_alpha = no_alpha; strncpy(l_extension, extension, sizeof(l_extension) -1); l_extension[sizeof(l_extension) -1] = '\0'; } if(l_rc >= 0) { l_new_image_id = p_split_image(ainfo_ptr, l_extension, l_inverse_order, l_no_alpha); /* create a display for the new created image * (it is the first or the last frame of the * new created animation sequence) */ gimp_display_new(l_new_image_id); l_rc = l_new_image_id; } } } p_free_ainfo(&ainfo_ptr); } return(l_rc); } /* end gap_split_image */