mirror of https://github.com/GNOME/gimp.git
336 lines
10 KiB
C
336 lines
10 KiB
C
/* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#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 */
|
|
|