home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / gap / gap_range_ops.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-06  |  60.9 KB  |  1,865 lines

  1. /* gap_range_ops.c
  2.  * 1997.11.06 hof (Wolfgang Hofer)
  3.  *
  4.  * GAP ... Gimp Animation Plugins
  5.  *
  6.  * This Module contains implementation of range based frame operations.
  7.  * - gap_range_to_multilayer 
  8.  * - gap_range_flatten
  9.  * - gap_range_layer_del
  10.  * - gap_range_conv
  11.  * - gap_anim_scale
  12.  * - gap_anim_resize
  13.  * - gap_anim_crop
  14.  *
  15.  */
  16. /* The GIMP -- an image manipulation program
  17.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  18.  *
  19.  * This program is free software; you can redistribute it and/or modify
  20.  * it under the terms of the GNU General Public License as published by
  21.  * the Free Software Foundation; either version 2 of the License, or
  22.  * (at your option) any later version.
  23.  *
  24.  * This program is distributed in the hope that it will be useful,
  25.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  * GNU General Public License for more details.
  28.  *
  29.  * You should have received a copy of the GNU General Public License
  30.  * along with this program; if not, write to the Free Software
  31.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  32.  */
  33.  
  34. /* revision history
  35.  * 1.1.28a; 2000/11/05   hof: check for GIMP_PDB_SUCCESS (not for FALSE)
  36.  * 1.1.24a  2000/07/01   hof: bugfix: flatten of singlelayer images has to remove alpha channel
  37.  * 1.1.17b  2000/02/26   hof: bugfixes
  38.  * 1.1.14a  2000/01/06   hof: gap_range_to_multilayer: use framerate (from video info file) in framenames
  39.  *                            bugfix: gap_range_to_multilayer: first save current frame
  40.  * 1.1.10a  1999/10/22   hof: bugfix: have to use the changed PDB-Interface
  41.  *                            for gimp_convert_indexed
  42.  *                            (with extended dither options and extra dialog window)
  43.  * 1.1.9a   1999/09/21   hof: bugfix GIMP_RUN_NONINTERACTIVE did not work in
  44.  *                            plug_in_gap_range_convert
  45.  *                            plug_in_gap_range_layer_del
  46.  *                            plug_in_gap_range_flatten
  47.  * 1.1.8    1999/08/31   hof: frames convert: save subsequent frames
  48.  *                            with rumode GIMP_RUN_WITH_LAST_VALS 
  49.  * 0.97.00; 1998/10/19   hof: gap_range_to_multilayer: extended layer selection
  50.  * 0.96.03; 1998/08/31   hof: gap_range_to_multilayer: all params available
  51.  *                            in non-interactive runmode
  52.  * 0.96.02; 1998/08/05   hof: - p_frames_to_multilayer added framerate support
  53.  * 0.96.00; 1998/07/01   hof: - added scale, resize and crop 
  54.  *                              (affects full range == all anim frames)
  55.  *                            - now using gap_arr_dialog.h
  56.  * 0.94.01; 1998/04/28   hof: added flatten_mode to plugin: gap_range_to_multilayer
  57.  * 0.92.00  1998.01.10   hof: bugfix in p_frames_to_multilayer
  58.  *                            layers need alpha (to be raise/lower able) 
  59.  * 0.90.00               first development release
  60.  */
  61. #include "config.h"
  62.  
  63. /* SYTEM (UNIX) includes */ 
  64. #include <stdio.h>
  65. #include <stdlib.h>
  66. #include <string.h>
  67. #include <sys/types.h>
  68. #include <errno.h>
  69. #ifdef HAVE_UNISTD_H
  70. #include <unistd.h>
  71. #endif
  72.  
  73. /* GIMP includes */
  74. #include "gtk/gtk.h"
  75. #include "config.h"
  76. #include "libgimp/stdplugins-intl.h"
  77. #include "libgimp/gimp.h"
  78.  
  79. /* GAP includes */
  80. #include "gap_layer_copy.h"
  81. #include "gap_lib.h"
  82. #include "gap_pdb_calls.h"
  83. #include "gap_match.h"
  84. #include "gap_arr_dialog.h"
  85. #include "gap_resi_dialog.h"
  86. #include "gap_mod_layer.h"
  87. #include "gap_range_ops.h"
  88.  
  89. extern      int gap_debug; /* ==0  ... dont print debug infos */
  90.  
  91.  
  92. /* ============================================================================
  93.  * p_anim_sizechange_dialog
  94.  *   dialog window with 2 (or 4) entry fields
  95.  *   where the user can select the new Anim Frame (Image)-Size
  96.  *   (if cnt == 4 additional Inputfields for offests are available)
  97.  * return -1  in case of cancel or any error
  98.  *            (include check for change of current frame)
  99.  * return positve (0 or layerstack position) if everythig OK
  100.  * ============================================================================
  101.  */
  102. static int 
  103. p_anim_sizechange_dialog(t_anim_info *ainfo_ptr, t_gap_asiz asiz_mode,
  104.                long *size_x, long *size_y, 
  105.                long *offs_x, long *offs_y)
  106. {
  107.   static t_arr_arg  argv[4];
  108.   gint   cnt;
  109.   gchar *title;
  110.   gchar *hline;
  111.   gint   l_width;
  112.   gint   l_height;
  113.   gint   l_rc;
  114.  
  115.   /* get info about the image (size is common to all frames) */
  116.   l_width  = gimp_image_width(ainfo_ptr->image_id);
  117.   l_height = gimp_image_height(ainfo_ptr->image_id);
  118.  
  119.   p_init_arr_arg(&argv[0], WGT_INT_PAIR);
  120.   argv[0].label_txt = _("New Width:");
  121.   argv[0].constraint = FALSE;
  122.   argv[0].int_min   = 1;
  123.   argv[0].int_max   = 1024;
  124.   argv[0].umin      = 1;
  125.   argv[0].umax      = 10000;
  126.   argv[0].int_ret   = l_width;
  127.   
  128.   p_init_arr_arg(&argv[1], WGT_INT_PAIR);
  129.   argv[1].label_txt = _("New Height:");
  130.   argv[1].constraint = FALSE;
  131.   argv[1].int_min    = 1;
  132.   argv[1].int_max    = 1024;
  133.   argv[1].umin       = 1;
  134.   argv[1].umax       = 10000;
  135.   argv[1].int_ret   = l_height;
  136.   
  137.   p_init_arr_arg(&argv[2], WGT_INT_PAIR);
  138.   argv[2].label_txt = _("Offset X:");
  139.   argv[2].constraint = FALSE;
  140.   argv[2].int_min    = 0;
  141.   argv[2].int_max    = l_width;
  142.   argv[2].umin       = 0;
  143.   argv[2].umax       = 10000;
  144.   argv[2].int_ret   = 0;
  145.   
  146.   p_init_arr_arg(&argv[3], WGT_INT_PAIR);
  147.   argv[3].label_txt = _("Offset Y:");
  148.   argv[3].constraint = FALSE;
  149.   argv[3].int_min    = 0;
  150.   argv[3].int_max    = l_height;
  151.   argv[3].umin       = 0;
  152.   argv[3].umax       = 10000;
  153.   argv[3].int_ret   = 0;
  154.  
  155.   switch(asiz_mode)
  156.   {
  157.     case ASIZ_CROP:
  158.       title = _("Crop AnimFrames (all)");
  159.       hline = g_strdup_printf (_("Crop (original %dx%d)"), l_width, l_height);
  160.       argv[0].int_max   = l_width;
  161.       argv[0].constraint = TRUE;
  162.       argv[1].int_max   = l_height;
  163.       argv[1].constraint = TRUE;
  164.       argv[2].constraint = TRUE;
  165.       argv[3].constraint = TRUE;
  166.       cnt = 4;
  167.       break;
  168.     case ASIZ_RESIZE:
  169.       title = _("Resize AnimFrames (all)");
  170.       hline = g_strdup_printf (_("Resize (original %dx%d)"), l_width, l_height);
  171.       argv[2].int_min    = -l_width;
  172.       argv[3].int_min    = -l_height;
  173.      cnt = 4;
  174.       break;
  175.     default:
  176.       title = _("Scale AnimFrames (all)");
  177.       hline = g_strdup_printf (_("Scale (original %dx%d)"), l_width, l_height);
  178.       cnt = 2;
  179.       break;
  180.   }
  181.   
  182.   if(0 != p_chk_framerange(ainfo_ptr))   return -1;
  183.  
  184.   /* array dialog can handle all asiz_mode type (and is already prepared for)
  185.    * BUT: RESIZE and SCALE should use the same dialogs as used in gimp
  186.    *      on single Images.
  187.    *      Therfore I made a procedure p_resi_dialog
  188.    */
  189.   if(asiz_mode == ASIZ_CROP)
  190.   {
  191.     l_rc = p_array_dialog(title, hline, cnt, argv);
  192.     g_free (hline);
  193.     
  194.       *size_x = (long)(argv[0].int_ret);
  195.       *size_y = (long)(argv[1].int_ret);
  196.       *offs_x = (long)(argv[2].int_ret);
  197.       *offs_y = (long)(argv[3].int_ret);
  198.  
  199.       /* Clip size down to image borders */      
  200.       if((*size_x + *offs_x) > l_width)
  201.       {
  202.         *size_x = l_width - *offs_x;
  203.       }
  204.       if((*size_y + *offs_y) > l_height)
  205.       {
  206.         *size_y = l_height - *offs_y;
  207.       }
  208.   }
  209.   else
  210.   {
  211.     l_rc = p_resi_dialog(ainfo_ptr->image_id, asiz_mode, title,
  212.                          size_x, size_y, offs_x, offs_y);
  213.   }
  214.   
  215.  
  216.   if(l_rc == TRUE)
  217.   {
  218.        if(0 != p_chk_framechange(ainfo_ptr))
  219.        {
  220.            return -1;
  221.        }
  222.        return 0;        /* OK */
  223.   }
  224.   else
  225.   {
  226.      return -1;
  227.   }
  228.    
  229. }    /* end p_anim_sizechange_dialog */
  230.  
  231.  
  232. /* ============================================================================
  233.  * p_range_dialog
  234.  *   dialog window with 2 (or 3) entry fields
  235.  *   where the user can select a frame range (FROM TO)
  236.  *   (if cnt == 3 additional Layerstackposition)
  237.  * return -1  in case of cancel or any error
  238.  *            (include check for change of current frame)
  239.  * return positve (0 or layerstack position) if everythig OK
  240.  * ============================================================================
  241.  */
  242. static int 
  243. p_range_dialog(t_anim_info *ainfo_ptr,
  244.                long *range_from, long *range_to, 
  245.                char *title, char *hline, gint cnt)
  246. {
  247.   static t_arr_arg  argv[3];
  248.  
  249.  
  250.   if(cnt != 3)  cnt = 2;
  251.  
  252.   p_init_arr_arg(&argv[0], WGT_INT_PAIR);
  253.   argv[0].label_txt = _("From:");
  254.   argv[0].constraint = TRUE;
  255.   argv[0].int_min   = (gint)ainfo_ptr->first_frame_nr;
  256.   argv[0].int_max   = (gint)ainfo_ptr->last_frame_nr;
  257.   argv[0].int_ret   = (gint)ainfo_ptr->curr_frame_nr;
  258.   
  259.   p_init_arr_arg(&argv[1], WGT_INT_PAIR);
  260.   argv[1].label_txt = _("To:");
  261.   argv[1].constraint = TRUE;
  262.   argv[1].int_min   = (gint)ainfo_ptr->first_frame_nr;
  263.   argv[1].int_max   = (gint)ainfo_ptr->last_frame_nr;
  264.   argv[1].int_ret   = (gint)ainfo_ptr->last_frame_nr;
  265.   
  266.   p_init_arr_arg(&argv[2], WGT_INT_PAIR);
  267.   argv[2].label_txt = _("Layerstack:");
  268.   argv[2].constraint = FALSE;
  269.   argv[2].int_min   = 0;
  270.   argv[2].int_max   = 99;
  271.   argv[2].umin      = 0;
  272.   argv[2].umax      = 999999;
  273.   argv[2].int_ret   = 0;
  274.   
  275.   if(0 != p_chk_framerange(ainfo_ptr))   return -1;
  276.   if(TRUE == p_array_dialog(title, hline, cnt, argv))
  277.   {   *range_from = (long)(argv[0].int_ret);
  278.       *range_to   = (long)(argv[1].int_ret);
  279.  
  280.        if(0 != p_chk_framechange(ainfo_ptr))
  281.        {
  282.            return -1;
  283.        }
  284.        return (int)(argv[2].int_ret);
  285.   }
  286.   else
  287.   {
  288.      return -1;
  289.   }
  290.    
  291. }    /* end p_range_dialog */
  292.  
  293. /* ============================================================================
  294.  * p_convert_indexed_dialog
  295.  *
  296.  * extra dialog with dither options (when converting to indexed image type)
  297.  *   return  0 .. OK 
  298.  *          -1 .. in case of Error or cancel
  299.  * ============================================================================
  300.  */
  301. static long
  302. p_convert_indexed_dialog(gint32 *dest_colors, gint32 *dest_dither,
  303.               gint32 *palette_type, gint32 *alpha_dither, gint32 *remove_unused, 
  304.                       char *palette,   gint len_palette)
  305. {
  306. #define ARGC_INDEXED 6  
  307.   static t_arr_arg  argv[ARGC_INDEXED];
  308.   static char *radio_paltype[4]  = { N_("Generate Optimal Palette")
  309.                                    , N_("WEB Palette")
  310.                    , N_("Use Custom Palette")
  311.                    , N_("Use Black/White (1-Bit) Palette")
  312.                    };
  313.   static char *radio_dither[4]  = { N_("Floyd-Steinberg Color Dithering (Normal)")
  314.                                   , N_("Floyd-Steinberg Color Dithering (Reduced Color Bleeding)")
  315.                   , N_("Positioned Color Dithering")
  316.                                   , N_("No Color Dithering")
  317.                   };
  318.   static int gettextize_loop = 0;
  319.  
  320.   for (;gettextize_loop < 4; gettextize_loop++)
  321.     radio_paltype[gettextize_loop] = gettext(radio_paltype[gettextize_loop]);
  322.   
  323.   for (;gettextize_loop < 4; gettextize_loop++)
  324.     radio_dither[gettextize_loop] = gettext(radio_dither[gettextize_loop]);
  325.  
  326.   p_init_arr_arg(&argv[0], WGT_RADIO);
  327.   argv[0].label_txt = _("Palette Type");
  328.   argv[0].help_txt  = NULL;
  329.   argv[0].radio_argc  = 4;
  330.   argv[0].radio_argv = radio_paltype;
  331.   argv[0].radio_ret  = 0;
  332.  
  333.   p_init_arr_arg(&argv[1], WGT_TEXT);
  334.   argv[1].label_txt = _("Custom Palette");
  335.   argv[1].help_txt  = _("Name of a cutom palette\n(is ignored if Palette Type is not custom)");
  336.   argv[1].text_buf_len = len_palette;
  337.   argv[1].text_buf_ret = palette;
  338.  
  339.   p_init_arr_arg(&argv[2], WGT_TOGGLE);
  340.   argv[2].label_txt = _("Remove Unused");
  341.   argv[2].help_txt  = _("Remove unused or double colors\n(is ignored if Palette Type is not custom)");
  342.   argv[2].int_ret   = 1;
  343.  
  344.   p_init_arr_arg(&argv[3], WGT_INT_PAIR);
  345.   argv[3].constraint = TRUE;
  346.   argv[3].label_txt = _("Number of Colors");
  347.   argv[3].help_txt  = _("Number of resulting Colors         \n(ignored if Palette Type is not Generate optimal palette)");
  348.   argv[3].int_min   = 2;
  349.   argv[3].int_max   = 256;
  350.   argv[3].int_ret   = 255;
  351.  
  352.  
  353.   p_init_arr_arg(&argv[4], WGT_RADIO);
  354.   argv[4].label_txt = _("Dither Options");
  355.   argv[4].help_txt  = NULL;
  356.   argv[4].radio_argc  = 4;
  357.   argv[4].radio_argv = radio_dither;
  358.   argv[4].radio_ret  = 0;
  359.   
  360.   p_init_arr_arg(&argv[5], WGT_TOGGLE);
  361.   argv[5].label_txt = _("Enable transparency");
  362.   argv[5].help_txt  = _("Enable dithering of transparency");
  363.   argv[5].int_ret   = 0;
  364.  
  365.   if(TRUE == p_array_dialog( _("Convert Frames to Indexed"),
  366.                                  _("Palette and Dither Settings"), 
  367.                                   ARGC_INDEXED, argv))
  368.   {
  369.       switch(argv[0].radio_ret)
  370.       {
  371.         case 3: 
  372.            *palette_type = GIMP_MONO_PALETTE;
  373.            break;
  374.         case 2: 
  375.            *palette_type = GIMP_CUSTOM_PALETTE;
  376.            break;
  377.         case 1: 
  378.            *palette_type = GIMP_WEB_PALETTE;
  379.            break;
  380.         default:
  381.            *palette_type = GIMP_MAKE_PALETTE;
  382.            break;
  383.       }
  384.       *remove_unused = (gint32)(argv[2].int_ret);;
  385.       *dest_colors = (gint32)(argv[3].int_ret);
  386.       switch(argv[4].radio_ret)
  387.       {
  388.         case 3: 
  389.            *dest_dither = GIMP_NO_DITHER;
  390.            break;
  391.         case 2: 
  392.            *dest_dither = GIMP_FIXED_DITHER;
  393.            break;
  394.         case 1: 
  395.            *dest_dither = GIMP_FSLOWBLEED_DITHER;
  396.            break;
  397.         default:
  398.            *dest_dither = GIMP_FS_DITHER;
  399.            break;
  400.       }
  401.  
  402.       *alpha_dither = (gint32)(argv[5].int_ret);
  403.       
  404.       return 0;
  405.   }
  406.   else
  407.   {
  408.      return -1;
  409.   }
  410. }
  411.  
  412.  
  413. /* ============================================================================
  414.  * p_convert_dialog
  415.  *
  416.  *   return  0 .. OK 
  417.  *          -1 .. in case of Error or cancel
  418.  * ============================================================================
  419.  */
  420. static long
  421. p_convert_dialog(t_anim_info *ainfo_ptr,
  422.                       long *range_from, long *range_to, long *flatten,
  423.                       GimpImageBaseType *dest_type, gint32 *dest_colors, gint32 *dest_dither,
  424.                       char *basename, gint len_base,
  425.                       char *extension, gint len_ext,
  426.               gint32 *palette_type, gint32 *alpha_dither, gint32 *remove_unused, 
  427.                       char *palette,   gint len_palette)
  428. {
  429.   static t_arr_arg  argv[7];
  430.   static char *radio_args[4]  = { 
  431.     N_("Keep Type"), 
  432.     N_("Convert to RGB"), 
  433.     N_("Convert to Gray"), 
  434.     N_("Convert to Indexed") 
  435.   };
  436.   static int gettextize_loop = 0;
  437.  
  438.   for (;gettextize_loop < 4; gettextize_loop++)
  439.     radio_args[gettextize_loop] = gettext(radio_args[gettextize_loop]);
  440.   
  441.   p_init_arr_arg(&argv[0], WGT_INT_PAIR);
  442.   argv[0].constraint = TRUE;
  443.   argv[0].label_txt = _("From Frame:");
  444.   argv[0].help_txt  = _("first handled frame");
  445.   argv[0].int_min   = (gint)ainfo_ptr->first_frame_nr;
  446.   argv[0].int_max   = (gint)ainfo_ptr->last_frame_nr;
  447.   argv[0].int_ret   = (gint)ainfo_ptr->curr_frame_nr;
  448.   
  449.   p_init_arr_arg(&argv[1], WGT_INT_PAIR);
  450.   argv[1].constraint = TRUE;
  451.   argv[1].label_txt = _("To Frame:");
  452.   argv[1].help_txt  = _("last handled frame");
  453.   argv[1].int_min   = (gint)ainfo_ptr->first_frame_nr;
  454.   argv[1].int_max   = (gint)ainfo_ptr->last_frame_nr;
  455.   argv[1].int_ret   = (gint)ainfo_ptr->last_frame_nr;
  456.  
  457.   p_init_arr_arg(&argv[2], WGT_LABEL);
  458.   argv[2].label_txt = _("\nSelect destination fileformat by extension\noptionally convert imagetype\n");
  459.  
  460.   p_init_arr_arg(&argv[3], WGT_FILESEL);
  461.   argv[3].label_txt = _("Basename:");
  462.   argv[3].help_txt  = _("basename of the resulting frames       \n(0001.ext is added)");
  463.   argv[3].text_buf_len = len_base;
  464.   argv[3].text_buf_ret = basename;
  465.  
  466.   p_init_arr_arg(&argv[4], WGT_TEXT);
  467.   argv[4].label_txt = _("Extension:");
  468.   argv[4].help_txt  = _("extension of resulting frames       \n(is also used to define Fileformat)");
  469.   argv[4].text_buf_len = len_ext;
  470.   argv[4].text_buf_ret = extension;
  471.   
  472.  
  473.   p_init_arr_arg(&argv[5], WGT_OPTIONMENU);
  474.   argv[5].label_txt = _("Imagetype:");
  475.   argv[5].help_txt  = _("Convert to, or keep imagetype           \n(most fileformats can't handle all types)");
  476.   argv[5].radio_argc  = 4;
  477.   argv[5].radio_argv = radio_args;
  478.   argv[5].radio_ret  = 0;
  479.  
  480.   p_init_arr_arg(&argv[6], WGT_TOGGLE);
  481.   argv[6].label_txt = _("Flatten:");
  482.   argv[6].help_txt  = _("Flatten all resulting frames               \n(most fileformats need flattened frames)");
  483.   argv[6].int_ret   = 1;
  484.  
  485.   if(0 != p_chk_framerange(ainfo_ptr))   return -1;
  486.  
  487.   if(TRUE == p_array_dialog( _("Convert Frames to other Formats"),
  488.                                  _("Convert Settings"), 
  489.                                   7, argv))
  490.   {
  491.       *range_from  = (long)(argv[0].int_ret);
  492.       *range_to    = (long)(argv[1].int_ret);
  493.       switch(argv[5].radio_ret)
  494.       {
  495.         case 1: 
  496.            *dest_type = GIMP_RGB;
  497.            break;
  498.         case 2: 
  499.            *dest_type = GIMP_GRAY;
  500.            break;
  501.         case 3: 
  502.            *dest_type = GIMP_INDEXED;
  503.            break;
  504.         default:
  505.       *dest_type = 9444;   /*  huh ??  */
  506.            break;
  507.       }
  508.       *flatten     = (long)(argv[6].int_ret);
  509.  
  510.       *dest_colors = 255;
  511.       *dest_dither = 0;
  512.       *palette_type = 2; /* WEB palette */
  513.       *alpha_dither = 0;
  514.       *remove_unused = 0;
  515.       
  516.        if(*dest_type == GIMP_INDEXED)
  517.        {
  518.           /* Open a 2.nd dialog for the Dither Options */
  519.           if(0 != p_convert_indexed_dialog(dest_colors,
  520.                                        dest_dither,
  521.                        palette_type,
  522.                        alpha_dither,
  523.                        remove_unused,
  524.                        palette,
  525.                        len_palette
  526.         ))
  527.       {
  528.              return -1;
  529.       }
  530.        }
  531.       
  532.        if(0 != p_chk_framechange(ainfo_ptr))
  533.        {
  534.            return -1;
  535.        }
  536.        return 0;
  537.   }
  538.   else
  539.   {
  540.      return -1;
  541.   }
  542. }        /* end p_convert_dialog */
  543.  
  544. /* ============================================================================
  545.  * p_range_to_multilayer_dialog
  546.  *   dialog window with 4 entry fields
  547.  *   where the user can select a frame range (FROM TO)
  548.  * return -1  in case of cancel or any error
  549.  *            (include check for change of current frame)
  550.  * return positve (0 or layerstack position) if everythig OK
  551.  * ============================================================================
  552.  */
  553. static int 
  554. p_range_to_multilayer_dialog(t_anim_info *ainfo_ptr,
  555.                long *range_from, long *range_to, 
  556.                long *flatten_mode, long *bg_visible,
  557.                long *framrate, char *frame_basename, gint len_frame_basename,
  558.                char *title, char *hline,
  559.  
  560.            gint32 *sel_mode, gint32 *sel_case,
  561.            gint32 *sel_invert, char *sel_pattern)
  562. {
  563.   static t_arr_arg  argv[10];
  564.   
  565.   static char *radio_args[4]  = { N_("Expand as necessary"), 
  566.                                  N_("Clipped to image"),
  567.                                  N_("Clipped to bottom layer"), 
  568.                                  N_("Flattened image") };
  569.   static char *radio_help[4]  = { N_("Resulting Layer Size is made of the outline-rectangle \nof all visible layers (may differ from frame to frame)"), 
  570.                                  N_("Resulting Layer Size is the frame size"),
  571.                                  N_("Resulting Layer Size is the size of the bottom layer\n(may differ from frame to frame)"), 
  572.                                  N_("Resulting Layer Size is the frame size     \ntransparent parts are filled with BG color") };
  573.   /* Layer select modes */
  574.   static char *sel_args[7]    = { N_("Pattern is equal to LayerName"),
  575.                                   N_("Pattern is Start of LayerName"),
  576.                                   N_("Pattern is End of Layername"),
  577.                                   N_("Pattern is a Part of LayerName"),
  578.                                   N_("Pattern is LayerstackNumber List"),
  579.                                   N_("Pattern is REVERSE-stack List"),
  580.                                   N_("All Visible (ignore Pattern)")
  581.                                   };
  582.   static char *sel_help[7]    = { N_("select all Layers where Layername is equal to Pattern"),
  583.                                   N_("select all Layers where Layername starts with Pattern"),
  584.                                   N_("select all Layers where Layername ends up with Pattern"),
  585.                                   N_("select all Layers where Layername contains Pattern"),
  586.                                   N_("select Layerstack positions.\n0, 4-5, 8\nwhere 0 == Top-layer"),
  587.                                   N_("select Layerstack positions.\n0, 4-5, 8\nwhere 0 == BG-layer"),
  588.                                   N_("select all visible Layers")
  589.                                   };
  590.   static int gettextize_radio = 0, gettextize_sel = 0;
  591.   for (;gettextize_radio < 4; gettextize_radio++) {
  592.     radio_args[gettextize_radio] = gettext(radio_args[gettextize_radio]);
  593.     radio_help[gettextize_radio] = gettext(radio_help[gettextize_radio]);
  594.   }
  595.   for (;gettextize_sel < 4; gettextize_sel++) {
  596.     sel_args[gettextize_sel] = gettext(sel_args[gettextize_sel]);
  597.     sel_help[gettextize_sel] = gettext(sel_help[gettextize_sel]);
  598.   }
  599.  
  600.   p_init_arr_arg(&argv[0], WGT_INT_PAIR);
  601.   argv[0].constraint = TRUE;
  602.   argv[0].label_txt = _("From:");
  603.   argv[0].help_txt  = _("first handled frame");
  604.   argv[0].int_min   = (gint)ainfo_ptr->first_frame_nr;
  605.   argv[0].int_max   = (gint)ainfo_ptr->last_frame_nr;
  606.   argv[0].int_ret   = (gint)ainfo_ptr->curr_frame_nr;
  607.   
  608.   p_init_arr_arg(&argv[1], WGT_INT_PAIR);
  609.   argv[1].constraint = TRUE;
  610.   argv[1].label_txt = _("To:");
  611.   argv[1].help_txt  = _("last handled frame");
  612.   argv[1].int_min   = (gint)ainfo_ptr->first_frame_nr;
  613.   argv[1].int_max   = (gint)ainfo_ptr->last_frame_nr;
  614.   argv[1].int_ret   = (gint)ainfo_ptr->last_frame_nr;
  615.  
  616.   p_init_arr_arg(&argv[2], WGT_TEXT);
  617.   argv[2].label_txt = _("Layer Basename:");
  618.   argv[2].help_txt  = _("Basename for all Layers    \n[####] is replaced by frame number");
  619.   argv[2].text_buf_len = len_frame_basename;
  620.   argv[2].text_buf_ret = frame_basename;
  621.  
  622.   /* Framerate is not used any longer */
  623. /*  
  624.   p_init_arr_arg(&argv[3], WGT_INT_PAIR);
  625.   argv[3].constraint = FALSE;
  626.   argv[3].label_txt = "Framerate :";
  627.   argv[3].help_txt  = "Framedelay in ms";
  628.   argv[3].int_min   = (gint)0;
  629.   argv[3].int_max   = (gint)300;
  630.   argv[3].int_ret   = (gint)50;
  631.  */
  632.   p_init_arr_arg(&argv[3], WGT_LABEL);
  633.   argv[3].label_txt = " ";
  634.   
  635.   p_init_arr_arg(&argv[4], WGT_RADIO);
  636.   argv[4].label_txt = _("Layer Mergemode:");
  637.   argv[4].radio_argc = 4;
  638.   argv[4].radio_argv = radio_args;
  639.   argv[4].radio_help_argv = radio_help;
  640.   argv[4].radio_ret  = 1;
  641.   
  642.   p_init_arr_arg(&argv[5], WGT_TOGGLE);
  643.   argv[5].label_txt = _("Exclude BG-Layer");
  644.   argv[5].help_txt  = _("Exclude the BG-Layers    \nin all handled frames\nregardless to selection");
  645.   argv[5].int_ret   = 0;   /* 1: exclude BG Layer from all selections */
  646.  
  647.  
  648.   /* Layer select mode RADIO buttons */
  649.   p_init_arr_arg(&argv[6], WGT_RADIO);
  650.   argv[6].label_txt = _("Select Layer(s):");
  651.   argv[6].radio_argc = 7;
  652.   argv[6].radio_argv = sel_args;
  653.   argv[6].radio_help_argv = sel_help;
  654.   argv[6].radio_ret  = 6;
  655.  
  656.   /* Layer select pattern string */
  657.   g_snprintf (sel_pattern, 2, "0");
  658.   p_init_arr_arg(&argv[7], WGT_TEXT);
  659.   argv[7].label_txt = _("Select Pattern:");
  660.   argv[7].entry_width = 140;       /* pixel */
  661.   argv[7].help_txt  = _("String to identify layer names    \nor layerstack position numbers\n0,3-5");
  662.   argv[7].text_buf_len = MAX_LAYERNAME;
  663.   argv[7].text_buf_ret = sel_pattern;
  664.  
  665.   /* case sensitive checkbutton */
  666.   p_init_arr_arg(&argv[8], WGT_TOGGLE);
  667.   argv[8].label_txt = _("Case sensitive");
  668.   argv[8].help_txt  = _("Lowercase and UPPERCASE letters are considered as different");
  669.   argv[8].int_ret   = 1;
  670.  
  671.   /* invert selection checkbutton */
  672.   p_init_arr_arg(&argv[9], WGT_TOGGLE);
  673.   argv[9].label_txt = _("Invert Selection");
  674.   argv[9].help_txt  = _("Use all unselected Layers");
  675.   argv[9].int_ret   = 0;
  676.  
  677.  
  678.  
  679.   
  680.   if(0 != p_chk_framerange(ainfo_ptr))   return -1;
  681.  
  682.   if(TRUE == p_array_dialog(title, hline, 10, argv))
  683.   {   *range_from   = (long)(argv[0].int_ret);
  684.       *range_to     = (long)(argv[1].int_ret);
  685.       *framrate     = (long)(argv[3].int_ret);
  686.       *flatten_mode = (long)(argv[4].int_ret);
  687.       if (argv[5].int_ret == 0)  *bg_visible = 1; /* 1: use BG like any Layer */
  688.       else                       *bg_visible = 0; /* 0: exclude (ignore) BG Layer */
  689.  
  690.       *sel_mode     = argv[6].int_ret;
  691.                    /*     [7] sel_pattern  */
  692.       *sel_case     = argv[8].int_ret;
  693.       *sel_invert   = argv[9].int_ret;
  694.  
  695.        if(0 != p_chk_framechange(ainfo_ptr))
  696.        {
  697.            return -1;
  698.        }
  699.        return 0;
  700.   }
  701.   else
  702.   {
  703.      return -1;
  704.   }
  705.    
  706. }    /* end p_range_to_multilayer_dialog */
  707.  
  708.  
  709. /* ============================================================================
  710.  * p_frames_to_multilayer
  711.  * returns   image_id of the new created multilayer image
  712.  *           (or -1 on error)
  713.  * ============================================================================
  714.  */
  715. static gint32
  716. p_frames_to_multilayer(t_anim_info *ainfo_ptr,
  717.                       long range_from, long range_to,
  718.                       long flatten_mode, long bg_visible,
  719.                       long framerate, char *frame_basename,
  720.               gint32 sel_mode, gint32 sel_case,
  721.               gint32 sel_invert, char *sel_pattern)
  722. {
  723.   GimpImageBaseType l_type;
  724.   guint   l_width, l_height;
  725.   long    l_cur_frame_nr;
  726.   long    l_step, l_begin, l_end;
  727.   long    l_vidx;
  728.   gint32  l_tmp_image_id;
  729.   gint32  l_new_image_id;
  730.   gint32  l_cp_layer_id;
  731.   gint32  l_tmp_layer_id;
  732.   gint    l_src_offset_x, l_src_offset_y;    /* layeroffsets as they were in src_image */
  733.   gint       l_nlayers;
  734.   gint32    *l_layers_list;
  735.   gint       l_visible;
  736.   gint       l_nvisible;
  737.   gint       l_nlayers_result;
  738.   gdouble    l_percentage, l_percentage_step;  
  739.   static  char l_layername[256];
  740.   t_LayliElem *l_layli_ptr;
  741.   gint32     l_sel_cnt;
  742.  
  743.  
  744.   l_percentage = 0.0;
  745.   l_nlayers_result = 0;
  746.   if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  747.   { 
  748.     gimp_progress_init( _("Creating Layer-Animated Image..."));
  749.   }
  750.  
  751.   l_tmp_layer_id = -1;
  752.   
  753.   /* get info about the image (size and type is common to all frames) */
  754.   l_width  = gimp_image_width(ainfo_ptr->image_id);
  755.   l_height = gimp_image_height(ainfo_ptr->image_id);
  756.   l_type   = gimp_image_base_type(ainfo_ptr->image_id);
  757.   
  758.   l_new_image_id = gimp_image_new(l_width, l_height,l_type);
  759.   l_visible = TRUE;   /* only the 1.st layer should be visible */
  760.  
  761.   l_begin = range_from;
  762.   l_end   = range_to;
  763.   
  764.   if(range_from > range_to)
  765.   {
  766.     l_step  = -1;     /* operate in descending (reverse) order */
  767.     l_percentage_step = 1.0 / ((1.0 + range_from) - range_to);
  768.  
  769.     if(range_to < ainfo_ptr->first_frame_nr)
  770.     { l_begin = ainfo_ptr->first_frame_nr;
  771.     }
  772.     if(range_from > ainfo_ptr->last_frame_nr)
  773.     { l_end = ainfo_ptr->last_frame_nr;
  774.     }
  775.   }
  776.   else
  777.   {
  778.     l_step  = 1;      /* operate in ascending order */
  779.     l_percentage_step = 1.0 / ((1.0 + range_to) - range_from);
  780.  
  781.     if(range_from < ainfo_ptr->first_frame_nr)
  782.     { l_begin = ainfo_ptr->first_frame_nr;
  783.     }
  784.     if(range_to > ainfo_ptr->last_frame_nr)
  785.     { l_end = ainfo_ptr->last_frame_nr;
  786.     }
  787.   }
  788.   
  789.   
  790.   l_cur_frame_nr = l_begin;
  791.   while(1)
  792.   {
  793.     /* build the frame name */
  794.     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
  795.     ainfo_ptr->new_filename = p_alloc_fname(ainfo_ptr->basename,
  796.                                         l_cur_frame_nr,
  797.                                         ainfo_ptr->extension);
  798.     if(ainfo_ptr->new_filename == NULL)
  799.        goto error;
  800.  
  801.     /* load current frame into temporary image */
  802.     l_tmp_image_id = p_load_image(ainfo_ptr->new_filename);
  803.     if(l_tmp_image_id < 0)
  804.        goto error;
  805.        
  806.     /* get informations (id, visible, selected) about all layers */
  807.     l_layli_ptr = p_alloc_layli(l_tmp_image_id, &l_sel_cnt, &l_nlayers,
  808.                                sel_mode, sel_case, sel_invert, sel_pattern);
  809.     if(l_layli_ptr == NULL)
  810.         goto error;
  811.  
  812.     l_nvisible  = l_sel_cnt;  /* count visible Layers == all selected layers */
  813.     for(l_vidx=0; l_vidx < l_nlayers; l_vidx++)
  814.     {
  815.       /* set all selected layers visible, all others invisible */
  816.       l_tmp_layer_id = l_layli_ptr[l_vidx].layer_id;
  817.       gimp_layer_set_visible(l_tmp_layer_id,
  818.                              l_layli_ptr[l_vidx].selected);
  819.  
  820.       if((bg_visible == 0) && (l_vidx == (l_nlayers -1)))
  821.       {
  822.          /* set BG_Layer invisible */
  823.          gimp_layer_set_visible(l_tmp_layer_id, FALSE);
  824.      if(l_layli_ptr[l_vidx].selected)
  825.      {
  826.        l_nvisible--;
  827.      }
  828.       }
  829.     }
  830.  
  831.     g_free(l_layli_ptr);
  832.  
  833.     if((flatten_mode >= FLAM_MERG_EXPAND) && (flatten_mode <= FLAM_MERG_CLIP_BG))
  834.     {
  835.        if(gap_debug) fprintf(stderr, "p_frames_to_multilayer: %d MERGE visible layers=%d\n", (int)flatten_mode, (int)l_nvisible);
  836.  
  837.        /* merge all visible Layers */
  838.        if(l_nvisible > 1)  gimp_image_merge_visible_layers  (l_tmp_image_id, flatten_mode);
  839.     }
  840.     else
  841.     {
  842.         if(gap_debug) fprintf(stderr, "p_frames_to_multilayer: %d FLATTEN\n", (int)flatten_mode);
  843.         /* flatten temporary image (reduce to single layer) */
  844.         gimp_image_flatten (l_tmp_image_id);
  845.     }
  846.  
  847.     /* copy (the only visible) layer from temporary image */
  848.     l_layers_list = gimp_image_get_layers(l_tmp_image_id, &l_nlayers);
  849.     if(l_layers_list != NULL)
  850.     {
  851.       for(l_vidx=0; l_vidx < l_nlayers; l_vidx++)
  852.       {
  853.         l_tmp_layer_id = l_layers_list[l_vidx];
  854.  
  855.         /* stop at 1.st visible layer (this should be the only visible layer) */        
  856.         if(gimp_layer_get_visible(l_tmp_layer_id)) break;
  857.  
  858.         /* stop at 1.st layer if image was flattened */
  859.         if((flatten_mode < FLAM_MERG_EXPAND) || (flatten_mode > FLAM_MERG_CLIP_BG))  break;
  860.       }
  861.       g_free (l_layers_list);
  862.       
  863.       if(l_vidx < l_nlayers)
  864.       {
  865.          l_cp_layer_id = p_my_layer_copy(l_new_image_id,
  866.                                      l_tmp_layer_id,
  867.                                      100.0,   /* Opacity */
  868.                                      0,       /* NORMAL */
  869.                                      &l_src_offset_x,
  870.                                      &l_src_offset_y);
  871.  
  872.         /* add the copied layer to current destination image */
  873.         gimp_image_add_layer(l_new_image_id, l_cp_layer_id, 0);
  874.         gimp_layer_set_offsets(l_cp_layer_id, l_src_offset_x, l_src_offset_y);
  875.  
  876.         l_nlayers_result++;
  877.  
  878.  
  879.         /* add aplha channel to all layers
  880.          * (without alpha raise and lower would not work on that layers)
  881.          */
  882.         gimp_layer_add_alpha(l_cp_layer_id);
  883.  
  884.         /* set name and visibility */
  885.         if (frame_basename == NULL)  frame_basename = "frame_[####]";
  886.         if (*frame_basename == '\0') frame_basename = "frame_[####]";
  887.         
  888.     p_substitute_framenr(&l_layername[0], sizeof(l_layername),
  889.                           frame_basename, (long)l_cur_frame_nr);
  890.         gimp_layer_set_name(l_cp_layer_id, &l_layername[0]);
  891.  
  892.         gimp_layer_set_visible(l_cp_layer_id, l_visible);
  893.         l_visible = FALSE;   /* all further layers are set invisible */
  894.       }
  895.       /* else: tmp image has no visible layers, ignore that frame */
  896.     }
  897.  
  898.     /* destroy the tmp image */
  899.     gimp_image_delete(l_tmp_image_id);
  900.     
  901.     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  902.     { 
  903.       l_percentage += l_percentage_step;
  904.       gimp_progress_update (l_percentage);
  905.     }
  906.  
  907.     /* advance to next frame */
  908.     if(l_cur_frame_nr == l_end)
  909.        break;
  910.     l_cur_frame_nr += l_step;
  911.  
  912.   }
  913.  
  914.   p_prevent_empty_image(l_new_image_id);
  915.   
  916.   return l_new_image_id;
  917.  
  918. error:
  919.   gimp_image_delete(l_new_image_id);
  920.   return -1;
  921.   
  922. }    /* end p_frames_to_multilayer */
  923.  
  924.  
  925.  
  926. /* ============================================================================
  927.  * gap_range_to_multilayer
  928.  * ============================================================================
  929.  */
  930. gint32 gap_range_to_multilayer(GimpRunModeType run_mode, gint32 image_id,
  931.                              long range_from, long range_to,
  932.                              long flatten_mode, long bg_visible,
  933.                              long   framerate,
  934.                  char  *frame_basename, int frame_basename_len,
  935.                  gint32 sel_mode, gint32 sel_case,
  936.                  gint32 sel_invert, char *sel_pattern)
  937. {
  938.   gint32  new_image_id;
  939.   gint32  l_rc;
  940.   long   l_from, l_to;
  941.   t_anim_info *ainfo_ptr;
  942.   t_video_info *vin_ptr;
  943.   gint32    l_sel_mode;
  944.   gint32    l_sel_case;
  945.   gint32    l_sel_invert;
  946.   gdouble   l_framerate;
  947.   
  948.   char      l_sel_pattern[MAX_LAYERNAME];
  949.  
  950.   l_rc = -1;
  951.   ainfo_ptr = p_alloc_ainfo(image_id, run_mode);
  952.   if(ainfo_ptr != NULL)
  953.   {
  954.     if (0 == p_dir_ainfo(ainfo_ptr))
  955.     {
  956.       if(run_mode == GIMP_RUN_INTERACTIVE)
  957.       {
  958.      l_framerate = 24.0;
  959.          vin_ptr = p_get_video_info(ainfo_ptr->basename);
  960.          if(vin_ptr)
  961.      {
  962.        if(vin_ptr->framerate > 0) l_framerate = vin_ptr->framerate;
  963.        g_free(vin_ptr);
  964.      }     
  965.          g_snprintf(frame_basename, frame_basename_len, "frame_[####] (%dms)", (int)(1000/l_framerate));
  966.          framerate = 0;
  967.          l_rc = p_range_to_multilayer_dialog (ainfo_ptr, &l_from, &l_to,
  968.                                 &flatten_mode, &bg_visible,
  969.                                 &framerate, frame_basename, frame_basename_len, 
  970.                                 _("Frames to Image"),
  971.                                 _("Create Multilayer-Image from Frames"),
  972.                 &l_sel_mode, &sel_case,
  973.                 &sel_invert, &l_sel_pattern[0]
  974.                 );
  975.       }
  976.       else
  977.       {
  978.          l_from = range_from;
  979.          l_to   = range_to;
  980.          l_rc = 0;
  981.      l_sel_mode    = sel_mode;
  982.      l_sel_case    = sel_case;
  983.      l_sel_invert  = sel_invert;
  984.   
  985.          strncpy(&l_sel_pattern[0], sel_pattern, sizeof(l_sel_pattern) -1);
  986.      l_sel_pattern[sizeof(l_sel_pattern) -1] = '\0';
  987.       }
  988.  
  989.       if(l_rc >= 0)
  990.       {
  991.          l_rc = p_save_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  992.          if(l_rc >= 0)
  993.          {
  994.            new_image_id = p_frames_to_multilayer(ainfo_ptr, l_from, l_to, 
  995.                                              flatten_mode, bg_visible,
  996.                                              framerate, frame_basename,
  997.                          l_sel_mode, sel_case,
  998.                          sel_invert, &l_sel_pattern[0]);
  999.            gimp_display_new(new_image_id);
  1000.            l_rc = new_image_id;
  1001.      }
  1002.       }
  1003.     }
  1004.     p_free_ainfo(&ainfo_ptr);
  1005.   }
  1006.   
  1007.   return(l_rc);    
  1008. }    /* end gap_range_to_multilayer */
  1009.  
  1010. /* ============================================================================
  1011.  * p_type_convert
  1012.  *   convert image to desired type (reduce to dest_colors for INDEXED type)
  1013.  * ============================================================================
  1014.  */
  1015. static int
  1016. p_type_convert(gint32 image_id, GimpImageBaseType dest_type, gint32 dest_colors, gint32 dest_dither,
  1017.            gint32 palette_type, gint32  alpha_dither, gint32  remove_unused,  char *palette)
  1018. {
  1019.   GimpParam     *l_params;
  1020.   gint        l_retvals;
  1021.   int         l_rc;
  1022.  
  1023.   l_rc = 0;
  1024.   l_params = NULL;
  1025.  
  1026.   switch(dest_type)
  1027.   {
  1028.     case GIMP_INDEXED:
  1029.       if(gap_debug) fprintf(stderr, "DEBUG: p_type_convert to INDEXED ncolors=%d, palette_type=%d palette_name=%s'\n",
  1030.                                    (int)dest_colors, (int)palette_type, palette);
  1031.       l_params = gimp_run_procedure ("gimp_convert_indexed",
  1032.                        &l_retvals,
  1033.                        GIMP_PDB_IMAGE,    image_id,
  1034.                        GIMP_PDB_INT32,    dest_dither,      /* value 1== floyd-steinberg */
  1035.                        GIMP_PDB_INT32,    palette_type,     /* value 0: MAKE_PALETTE, 2: WEB_PALETTE 4:CUSTOM_PALETTE */
  1036.                        GIMP_PDB_INT32,    dest_colors,
  1037.                        GIMP_PDB_INT32,    alpha_dither,
  1038.                        GIMP_PDB_INT32,    remove_unused,
  1039.                        GIMP_PDB_STRING,   palette,         /* name of custom palette */                       
  1040.                        GIMP_PDB_END);
  1041.       break;
  1042.     case GIMP_GRAY:
  1043.       if(gap_debug) fprintf(stderr, "DEBUG: p_type_convert to GRAY'\n");
  1044.       l_params = gimp_run_procedure ("gimp_convert_grayscale",
  1045.                        &l_retvals,
  1046.                        GIMP_PDB_IMAGE,    image_id,
  1047.                        GIMP_PDB_END);
  1048.       break;
  1049.     case GIMP_RGB:
  1050.       if(gap_debug) fprintf(stderr, "DEBUG: p_type_convert to RGB'\n");
  1051.       l_params = gimp_run_procedure ("gimp_convert_rgb",
  1052.                        &l_retvals,
  1053.                        GIMP_PDB_IMAGE,    image_id,
  1054.                        GIMP_PDB_END);
  1055.       break;
  1056.     default:
  1057.       if(gap_debug) fprintf(stderr, "DEBUG: p_type_convert AS_IT_IS (dont convert)'\n");
  1058.       return 0;
  1059.       break;
  1060.   }
  1061.  
  1062.  
  1063.   if (l_params[0].data.d_status != GIMP_PDB_SUCCESS) 
  1064.   {  l_rc = -1;
  1065.   }
  1066.   
  1067.   g_free(l_params);
  1068.   return (l_rc);
  1069. }    /* end p_type_convert */
  1070.  
  1071. /* ============================================================================
  1072.  * p_frames_convert
  1073.  *    convert frames (multiple images) into desired fileformat and type
  1074.  *    (flatten the images if desired)
  1075.  *
  1076.  *   if save_proc_name == NULL
  1077.  *   then   use xcf save (and flatten image)
  1078.  *          and new_basename and new_extension
  1079.  *
  1080.  * returns   value >= 0 if all is ok 
  1081.  *           (or -1 on error)
  1082.  * ============================================================================
  1083.  */
  1084. static int
  1085. p_frames_convert(t_anim_info *ainfo_ptr,
  1086.                  long range_from, long range_to,
  1087.                  char *save_proc_name, char *new_basename, char *new_extension,
  1088.                  int flatten,
  1089.                  GimpImageBaseType dest_type, gint32 dest_colors, gint32 dest_dither,
  1090.          gint32  palette_type, gint32  alpha_dither, gint32  remove_unused,  char   *palette)
  1091. {
  1092.   GimpRunModeType l_run_mode;
  1093.   gint32  l_tmp_image_id;
  1094.   long    l_cur_frame_nr;
  1095.   long    l_step, l_begin, l_end;
  1096.   gint    l_nlayers;
  1097.   gint    l_img_already_flat;
  1098.   gint32 *l_layers_list;
  1099.   gdouble l_percentage, l_percentage_step;
  1100.   char   *l_sav_name;
  1101.   int     l_rc;
  1102.   gint    l_overwrite_mode;
  1103.   static  t_but_arg  l_argv[3];
  1104.  
  1105.   
  1106.   l_rc = 0;
  1107.   l_overwrite_mode = 0;
  1108.   l_percentage = 0.0;
  1109.   l_run_mode  = ainfo_ptr->run_mode;
  1110.   if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  1111.   { 
  1112.     if(save_proc_name == NULL) gimp_progress_init( _("Flattening Frames..."));
  1113.     else                       gimp_progress_init( _("Converting Frames..."));
  1114.   }
  1115.  
  1116.  
  1117.   l_begin = range_from;
  1118.   l_end   = range_to;
  1119.   
  1120.   if(range_from > range_to)
  1121.   {
  1122.     l_step  = -1;     /* operate in descending (reverse) order */
  1123.     l_percentage_step = 1.0 / ((1.0 + range_from) - range_to);
  1124.  
  1125.     if(range_to < ainfo_ptr->first_frame_nr)
  1126.     { l_begin = ainfo_ptr->first_frame_nr;
  1127.     }
  1128.     if(range_from > ainfo_ptr->last_frame_nr)
  1129.     { l_end = ainfo_ptr->last_frame_nr;
  1130.     }
  1131.   }
  1132.   else
  1133.   {
  1134.     l_step  = 1;      /* operate in ascending order */
  1135.     l_percentage_step = 1.0 / ((1.0 + range_to) - range_from);
  1136.  
  1137.     if(range_from < ainfo_ptr->first_frame_nr)
  1138.     { l_begin = ainfo_ptr->first_frame_nr;
  1139.     }
  1140.     if(range_to > ainfo_ptr->last_frame_nr)
  1141.     { l_end = ainfo_ptr->last_frame_nr;
  1142.     }
  1143.   }
  1144.   
  1145.   
  1146.   l_cur_frame_nr = l_begin;
  1147.   while(l_rc >= 0)
  1148.   {
  1149.     /* build the frame name */
  1150.     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
  1151.     ainfo_ptr->new_filename = p_alloc_fname(ainfo_ptr->basename,
  1152.                                         l_cur_frame_nr,
  1153.                                         ainfo_ptr->extension);
  1154.     if(ainfo_ptr->new_filename == NULL)
  1155.        return -1;
  1156.  
  1157.     /* load current frame */
  1158.     l_tmp_image_id = p_load_image(ainfo_ptr->new_filename);
  1159.     if(l_tmp_image_id < 0)
  1160.        return -1;
  1161.  
  1162.     l_img_already_flat = FALSE; /* an image without any layer is considered as not flattend */
  1163.     l_layers_list = gimp_image_get_layers(l_tmp_image_id, &l_nlayers);
  1164.     if(l_layers_list != NULL)
  1165.     {
  1166.       if( (l_nlayers == 1)
  1167.       &&  (! gimp_drawable_has_alpha(l_layers_list[0]))
  1168.       &&  (! gimp_layer_get_visible(l_layers_list[0])))
  1169.       {
  1170.         l_img_already_flat = TRUE;
  1171.       }
  1172.       g_free (l_layers_list);
  1173.     }
  1174.  
  1175.     if((l_img_already_flat == FALSE) &&  (flatten != 0))
  1176.     {
  1177.        gint32 l_dummy_layer_id;
  1178.        if(gap_debug) fprintf(stderr, "DEBUG: p_frames_convert flatten tmp image'\n");
  1179.  
  1180.         /* hof:
  1181.      * we add dummy layers to make sure that flatten works on any kind of image.
  1182.      * even if the image had no layer at all, or all its layers were invisible.
  1183.      *   (flatten need at least 2 layers and at least one visible layer to work.
  1184.      *    if just invisible layers are flattened 
  1185.      *    we do not get a resulting layer (returned l_layer_id == -1)
  1186.      */
  1187.         l_dummy_layer_id = gimp_layer_new(l_tmp_image_id, "dummy",
  1188.                                  1, 
  1189.                  1,
  1190.                  ((gint)(gimp_image_base_type(l_tmp_image_id)) * 2),
  1191.                                  100.0,     /* Opacity full opaque */     
  1192.                                  0);        /* NORMAL */
  1193.          gimp_image_add_layer(l_tmp_image_id, l_dummy_layer_id, 0);
  1194.      gimp_layer_set_offsets(l_dummy_layer_id, -1, -1);
  1195.      
  1196.      if(l_nlayers == 0)
  1197.      {
  1198.        /* on empty images we need 2 dummies to make flatten happy */
  1199.            l_dummy_layer_id = gimp_layer_new(l_tmp_image_id, "dummy2",
  1200.                                    1, 
  1201.                    1,
  1202.                    ((gint)(gimp_image_base_type(l_tmp_image_id)) * 2),
  1203.                                    100.0,     /* Opacity full opaque */     
  1204.                                    0);        /* NORMAL */
  1205.            gimp_image_add_layer(l_tmp_image_id, l_dummy_layer_id, 0);
  1206.        gimp_layer_set_offsets(l_dummy_layer_id, -1, -1);
  1207.      }
  1208.  
  1209.        
  1210.        /* flatten current frame image (reduce to single layer) */
  1211.        gimp_image_flatten (l_tmp_image_id);
  1212.  
  1213.        /* save back the current frame with same name */
  1214.        if(save_proc_name == NULL)
  1215.        {
  1216.           l_rc = p_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename);
  1217.        }
  1218.     }
  1219.  
  1220.     if(save_proc_name != NULL)
  1221.     {
  1222.        if(dest_type != gimp_image_base_type(l_tmp_image_id))
  1223.        {
  1224.           /* have to convert to desired type (RGB, INDEXED, GRAYSCALE) */
  1225.           p_type_convert(l_tmp_image_id, dest_type, dest_colors, dest_dither,
  1226.                      palette_type, alpha_dither, remove_unused, palette);
  1227.        }
  1228.     
  1229.     
  1230.        /* build the name for output image */
  1231.        l_sav_name = p_alloc_fname(new_basename,
  1232.                                   l_cur_frame_nr,
  1233.                                   new_extension);
  1234.        if(l_sav_name != NULL)
  1235.        {
  1236.           if(1 == p_file_exists(l_sav_name))
  1237.           {
  1238.             if (l_overwrite_mode < 1)
  1239.             {
  1240.                l_argv[0].but_txt  = _("Overwrite Frame");
  1241.                l_argv[0].but_val  = 0;
  1242.                l_argv[1].but_txt  = _("Overwrite All");
  1243.                l_argv[1].but_val  = 1;
  1244.                l_argv[2].but_txt  = _("Cancel");
  1245.                l_argv[2].but_val  = -1;
  1246.  
  1247.                l_overwrite_mode =  p_buttons_dialog  ( _("GAP Question"), l_sav_name, 3, l_argv, -1);
  1248.             }
  1249.           
  1250.           }
  1251.  
  1252.           if(l_overwrite_mode < 0)  { l_rc = -1; }
  1253.           else
  1254.           {
  1255.             /* save with selected save procedure
  1256.              * (regardless if image was flattened or not)
  1257.              */
  1258.              l_rc = p_save_named_image(l_tmp_image_id, l_sav_name, l_run_mode);
  1259.              if(l_rc < 0)
  1260.              {
  1261.                p_msg_win(ainfo_ptr->run_mode, _("Convert Frames: SAVE operation FAILED.\n"
  1262.                         "Desired save plugin can't handle type\n"
  1263.                         "or desired save plugin not available."));
  1264.              }
  1265.           }
  1266.           if(l_run_mode == GIMP_RUN_INTERACTIVE)
  1267.           {
  1268.             l_run_mode  = GIMP_RUN_WITH_LAST_VALS;  /* for all further calls */
  1269.           }
  1270.           g_free(l_sav_name);
  1271.        }
  1272.     }
  1273.  
  1274.     /* destroy the tmp image */
  1275.     gimp_image_delete(l_tmp_image_id);
  1276.  
  1277.     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  1278.     { 
  1279.       l_percentage += l_percentage_step;
  1280.       gimp_progress_update (l_percentage);
  1281.     }
  1282.  
  1283.     /* advance to next frame */
  1284.     if((l_cur_frame_nr == l_end) || (l_rc < 0))
  1285.        break;
  1286.     l_cur_frame_nr += l_step;
  1287.  
  1288.   }
  1289.  
  1290.  
  1291.   return l_rc;  
  1292. }    /* end p_frames_convert */
  1293.  
  1294.  
  1295.  
  1296. /* ============================================================================
  1297.  * p_image_sizechange
  1298.  *     scale, resize or crop one image
  1299.  * ============================================================================
  1300.  */
  1301. static
  1302. int p_image_sizechange(gint32 image_id,
  1303.                t_gap_asiz asiz_mode,
  1304.                long size_x, long size_y,
  1305.                long offs_x, long offs_y
  1306. )
  1307. {
  1308.   GimpParam     *l_params;
  1309.   gint        l_retvals;
  1310.  
  1311.   switch(asiz_mode)
  1312.   {
  1313.     case ASIZ_CROP:
  1314.       l_params = gimp_run_procedure ("gimp_crop",
  1315.                      &l_retvals,
  1316.                      GIMP_PDB_IMAGE,    image_id,
  1317.                      GIMP_PDB_INT32,    size_x,
  1318.                      GIMP_PDB_INT32,    size_y,
  1319.                      GIMP_PDB_INT32,    offs_x,
  1320.                      GIMP_PDB_INT32,    offs_y,
  1321.                      GIMP_PDB_END);
  1322.       break;
  1323.     case ASIZ_RESIZE:
  1324.       gimp_image_resize(image_id, (guint)size_x, (guint)size_y, (gint)offs_x, (gint)offs_y);
  1325.       break;
  1326.     default:
  1327.       l_params = gimp_run_procedure ("gimp_image_scale",
  1328.                      &l_retvals,
  1329.                      GIMP_PDB_IMAGE,    image_id,
  1330.                      GIMP_PDB_INT32,    size_x,
  1331.                      GIMP_PDB_INT32,    size_y,
  1332.                      GIMP_PDB_END);
  1333.       break;
  1334.   }
  1335.  
  1336.   return 0;
  1337. }    /* end p_image_sizechange */
  1338.  
  1339. /* ============================================================================
  1340.  * p_anim_sizechange
  1341.  *     scale, resize or crop all frames in the animation
  1342.  * ============================================================================
  1343.  */
  1344. static
  1345. gint32 p_anim_sizechange(t_anim_info *ainfo_ptr,
  1346.                t_gap_asiz asiz_mode,
  1347.                long size_x, long size_y,
  1348.                long offs_x, long offs_y
  1349. )
  1350. {
  1351.   guint   l_width, l_height;
  1352.   long    l_cur_frame_nr;
  1353.   long    l_step, l_begin, l_end;
  1354.   gint32  l_tmp_image_id;
  1355.   gdouble    l_percentage, l_percentage_step;  
  1356.   GimpParam     *l_params;
  1357.   int         l_rc;
  1358.  
  1359.   l_rc = 0;
  1360.   l_params = NULL;
  1361.  
  1362.  
  1363.   l_percentage = 0.0;  
  1364.   if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  1365.   {
  1366.     switch(asiz_mode)
  1367.     {
  1368.       case ASIZ_CROP:
  1369.         gimp_progress_init( _("Cropping all Animation Frames..."));
  1370.         break;
  1371.       case ASIZ_RESIZE:
  1372.         gimp_progress_init( _("Resizing all Animation Frames..."));
  1373.         break;
  1374.       default:
  1375.         gimp_progress_init( _("Scaling all Animation Frames..."));
  1376.         break;
  1377.     }
  1378.   }
  1379.  
  1380.   
  1381.   /* get info about the image (size and type is common to all frames) */
  1382.   l_width  = gimp_image_width(ainfo_ptr->image_id);
  1383.   l_height = gimp_image_height(ainfo_ptr->image_id);
  1384.   
  1385.  
  1386.   l_begin = ainfo_ptr->first_frame_nr;
  1387.   l_end   = ainfo_ptr->last_frame_nr;
  1388.   
  1389.   l_step  = 1;      /* operate in ascending order */
  1390.   l_percentage_step = 1.0 / ((1.0 + l_end) - l_begin);
  1391.  
  1392.   
  1393.   l_cur_frame_nr = l_begin;
  1394.   
  1395.   while(1)
  1396.   {
  1397.     /* build the frame name */
  1398.     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
  1399.     ainfo_ptr->new_filename = p_alloc_fname(ainfo_ptr->basename,
  1400.                                         l_cur_frame_nr,
  1401.                                         ainfo_ptr->extension);
  1402.     if(ainfo_ptr->new_filename == NULL)
  1403.        return -1;
  1404.  
  1405.     /* load current frame into temporary image */
  1406.     l_tmp_image_id = p_load_image(ainfo_ptr->new_filename);
  1407.     if(l_tmp_image_id < 0)
  1408.        return -1;
  1409.  
  1410.     l_rc = p_image_sizechange(l_tmp_image_id, asiz_mode,
  1411.                               size_x, size_y, offs_x, offs_y);
  1412.     if(l_rc < 0) break;
  1413.  
  1414.     /* save back the current frame with same name */
  1415.     l_rc = p_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename);
  1416.     if(l_rc < 0) break;
  1417.  
  1418.     /* destroy the tmp image */
  1419.     gimp_image_delete(l_tmp_image_id);
  1420.     
  1421.     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  1422.     { 
  1423.       l_percentage += l_percentage_step;
  1424.       gimp_progress_update (l_percentage);
  1425.     }
  1426.  
  1427.     /* advance to next frame */
  1428.     if(l_cur_frame_nr == l_end)
  1429.        break;
  1430.     l_cur_frame_nr += l_step;
  1431.  
  1432.   }   /* end while loop over all frames*/
  1433.  
  1434.   return l_rc;
  1435. }    /* end  p_anim_sizechange */
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441. /* ============================================================================
  1442.  * gap_range_flatten
  1443.  * ============================================================================
  1444.  */
  1445. int    gap_range_flatten(GimpRunModeType run_mode, gint32 image_id,
  1446.                          long range_from, long range_to)
  1447. {
  1448.   int    l_rc;
  1449.   long   l_from, l_to;
  1450.   t_anim_info *ainfo_ptr;
  1451.  
  1452.   l_rc = -1;
  1453.   ainfo_ptr = p_alloc_ainfo(image_id, run_mode);
  1454.   if(ainfo_ptr != NULL)
  1455.   {
  1456.     if (0 == p_dir_ainfo(ainfo_ptr))
  1457.     {
  1458.       if(run_mode == GIMP_RUN_INTERACTIVE)
  1459.       {
  1460.          l_rc = p_range_dialog (ainfo_ptr, &l_from, &l_to,
  1461.                                 _("Flatten Frames"),
  1462.                                 _("Select Frame Range"), 2);
  1463.  
  1464.       }
  1465.       else
  1466.       {
  1467.          l_rc = 0;
  1468.          l_from = range_from;
  1469.          l_to   = range_to;
  1470.       }
  1471.  
  1472.       if(l_rc >= 0)
  1473.       {
  1474.          l_rc = p_save_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1475.          if(l_rc >= 0)
  1476.          {
  1477.            l_rc = p_frames_convert(ainfo_ptr, l_from, l_to, NULL, NULL, NULL, 1, 0,0,0, 0,0,0, ""); 
  1478.            p_load_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1479.          }
  1480.       }
  1481.     }
  1482.     p_free_ainfo(&ainfo_ptr);
  1483.   }
  1484.   
  1485.   return(l_rc);    
  1486. }    /* end gap_range_flatten */
  1487.  
  1488.  
  1489.  
  1490.  
  1491. /* ============================================================================
  1492.  * p_frames_layer_del
  1493.  * returns   image_id of the new created multilayer image
  1494.  *           (or -1 on error)
  1495.  * ============================================================================
  1496.  */
  1497. static int
  1498. p_frames_layer_del(t_anim_info *ainfo_ptr,
  1499.                    long range_from, long range_to, long position)
  1500. {
  1501.   gint32  l_tmp_image_id;
  1502.  
  1503.   long    l_cur_frame_nr;
  1504.   long    l_step, l_begin, l_end;
  1505.   gint32  l_tmp_layer_id;
  1506.   gint       l_nlayers;
  1507.   gint32    *l_layers_list;
  1508.   gdouble    l_percentage, l_percentage_step;  
  1509.   gchar     *l_buff;
  1510.   int        l_rc;
  1511.   
  1512.  
  1513.   l_rc = 0;
  1514.   l_percentage = 0.0;  
  1515.   if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  1516.   {
  1517.     l_buff = g_strdup_printf (_("Removing Layer (pos:%ld) from Frames..."), position); 
  1518.     gimp_progress_init(l_buff);
  1519.     g_free (l_buff);
  1520.   }
  1521.  
  1522.  
  1523.   /* get info about the image (size and type is common to all frames) */
  1524.  
  1525.   l_begin = range_from;
  1526.   l_end   = range_to;
  1527.   
  1528.   if(range_from > range_to)
  1529.   {
  1530.     l_step  = -1;     /* operate in descending (reverse) order */
  1531.     l_percentage_step = 1.0 / ((1.0 + range_from) - range_to);
  1532.  
  1533.     if(range_to < ainfo_ptr->first_frame_nr)
  1534.     { l_begin = ainfo_ptr->first_frame_nr;
  1535.     }
  1536.     if(range_from > ainfo_ptr->last_frame_nr)
  1537.     { l_end = ainfo_ptr->last_frame_nr;
  1538.     }
  1539.   }
  1540.   else
  1541.   {
  1542.     l_step  = 1;      /* operate in ascending order */
  1543.     l_percentage_step = 1.0 / ((1.0 + range_to) - range_from);
  1544.  
  1545.     if(range_from < ainfo_ptr->first_frame_nr)
  1546.     { l_begin = ainfo_ptr->first_frame_nr;
  1547.     }
  1548.     if(range_to > ainfo_ptr->last_frame_nr)
  1549.     { l_end = ainfo_ptr->last_frame_nr;
  1550.     }
  1551.   }
  1552.   
  1553.  
  1554.   l_cur_frame_nr = l_begin;
  1555.   while(1)
  1556.   {
  1557.     /* build the frame name */
  1558.     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
  1559.     ainfo_ptr->new_filename = p_alloc_fname(ainfo_ptr->basename,
  1560.                                         l_cur_frame_nr,
  1561.                                         ainfo_ptr->extension);
  1562.     if(ainfo_ptr->new_filename == NULL)
  1563.        return -1;
  1564.  
  1565.     /* load current frame */
  1566.     l_tmp_image_id = p_load_image(ainfo_ptr->new_filename);
  1567.     if(l_tmp_image_id < 0)
  1568.        return -1;
  1569.  
  1570.     /* remove layer[position] */
  1571.     l_layers_list = gimp_image_get_layers(l_tmp_image_id, &l_nlayers);
  1572.     if(l_layers_list != NULL)
  1573.     {
  1574.       /* findout layer id of the requestetd position within layerstack */
  1575.       if(position < l_nlayers) l_tmp_layer_id = l_layers_list[position];
  1576.       else                     l_tmp_layer_id = l_layers_list[l_nlayers -1];
  1577.  
  1578.       g_free (l_layers_list);
  1579.    
  1580.       /* check for last layer (MUST NOT be deleted !) */ 
  1581.       if(l_nlayers > 1)
  1582.       {
  1583.         /* remove and delete requested layer */
  1584.         gimp_image_remove_layer(l_tmp_image_id, l_tmp_layer_id);
  1585.  
  1586.         /*  gimp_layer_delete(l_tmp_layer_id); */ /* gives sigsegv ERROR */
  1587.         /* A: gimp_image_remove_layer does automatic delete 
  1588.          *    if layer is not attched to any image
  1589.          * B: gimp_layer_delete has a BUG
  1590.          */
  1591.  
  1592.  
  1593.         /* save current frame */
  1594.         l_rc = p_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename);
  1595.       }
  1596.     }
  1597.  
  1598.     /* destroy the tmp image */
  1599.     gimp_image_delete(l_tmp_image_id);
  1600.  
  1601.     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  1602.     { 
  1603.       l_percentage += l_percentage_step;
  1604.       gimp_progress_update (l_percentage);
  1605.     }
  1606.  
  1607.     /* advance to next frame */
  1608.     if((l_cur_frame_nr == l_end) || (l_rc < 0))
  1609.        break;
  1610.     l_cur_frame_nr += l_step;
  1611.  
  1612.   }
  1613.  
  1614.  
  1615.   return l_rc;  
  1616. }    /* end p_frames_layer_del */
  1617.  
  1618.  
  1619. /* ============================================================================
  1620.  * gap_range_layer_del
  1621.  * ============================================================================
  1622.  */
  1623. int gap_range_layer_del(GimpRunModeType run_mode, gint32 image_id,
  1624.                          long range_from, long range_to, long position)
  1625. {
  1626.   int    l_rc;
  1627.   long   l_position;
  1628.   long   l_from, l_to;
  1629.   t_anim_info *ainfo_ptr;
  1630.  
  1631.   l_rc = -1;
  1632.   l_position = 0;
  1633.   ainfo_ptr = p_alloc_ainfo(image_id, run_mode);
  1634.   if(ainfo_ptr != NULL)
  1635.   {
  1636.     if (0 == p_dir_ainfo(ainfo_ptr))
  1637.     {
  1638.       if(run_mode == GIMP_RUN_INTERACTIVE)
  1639.       {
  1640.          l_rc = p_range_dialog (ainfo_ptr, &l_from, &l_to,
  1641.                                 _("Delete Layers in Frames"),
  1642.                                 _("Select Frame Range & Position"), 3);
  1643.          l_position = l_rc;
  1644.  
  1645.       }
  1646.       else
  1647.       {
  1648.          l_rc = 0;
  1649.          l_from = range_from;
  1650.          l_to   = range_to;
  1651.          l_position = position;
  1652.       }
  1653.  
  1654.       if(l_rc >= 0)
  1655.       {
  1656.          l_rc = p_save_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1657.          if(l_rc >= 0)
  1658.          {
  1659.            l_rc = p_frames_layer_del(ainfo_ptr, l_from, l_to, l_position);
  1660.            p_load_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1661.          }
  1662.       }
  1663.     }
  1664.     p_free_ainfo(&ainfo_ptr);
  1665.   }
  1666.   
  1667.   return(l_rc);    
  1668. }    /* end gap_range_layer_del */
  1669.  
  1670.  
  1671. /* ============================================================================
  1672.  * gap_range_conv
  1673.  *   convert frame range to any gimp supported fileformat
  1674.  * ============================================================================
  1675.  */
  1676. gint32 gap_range_conv(GimpRunModeType run_mode, gint32 image_id,
  1677.                       long range_from, long range_to,
  1678.                       long       flatten,
  1679.                       GimpImageBaseType dest_type,
  1680.                       gint32     dest_colors,
  1681.                       gint32     dest_dither,
  1682.                       char      *basename,
  1683.                       char      *extension,
  1684.                       gint32     palette_type,
  1685.                       gint32     alpha_dither,
  1686.                       gint32     remove_unused,
  1687.               char   *palette)
  1688. {
  1689.   gint32  l_rc;
  1690.   long   l_from, l_to;
  1691.   long   l_flatten;
  1692.   gint32     l_dest_colors;
  1693.   gint32     l_dest_dither;
  1694.   gint32     l_palette_type;
  1695.   gint32     l_alpha_dither;
  1696.   gint32     l_remove_unused;
  1697.   GimpImageBaseType l_dest_type;
  1698.   
  1699.   t_anim_info *ainfo_ptr;
  1700.   char  l_save_proc_name[128];
  1701.   char  l_basename[256];
  1702.   char *l_basename_ptr;
  1703.   long  l_number;
  1704.   char  l_extension[32];
  1705.   char  l_palette[256];
  1706.  
  1707.   strcpy(l_save_proc_name, "gimp_file_save");
  1708.   strcpy(l_extension, ".tif");
  1709.  
  1710.   l_rc = -1;
  1711.   ainfo_ptr = p_alloc_ainfo(image_id, run_mode);
  1712.   if(ainfo_ptr != NULL)
  1713.   {
  1714.     if (0 == p_dir_ainfo(ainfo_ptr))
  1715.     {
  1716.       strncpy(l_basename, ainfo_ptr->basename, sizeof(l_basename) -1);
  1717.       l_basename[sizeof(l_basename) -1] = '\0';
  1718.  
  1719.       if(run_mode == GIMP_RUN_INTERACTIVE)
  1720.       {
  1721.          
  1722.          l_flatten = 1;
  1723.          /* p_convert_dialog : select destination type
  1724.           * to find out extension
  1725.           */
  1726.      strcpy(l_palette, "Default");
  1727.          l_rc = p_convert_dialog (ainfo_ptr, &l_from, &l_to, &l_flatten,
  1728.                                   &l_dest_type, &l_dest_colors, &l_dest_dither,
  1729.                                   &l_basename[0], sizeof(l_basename),
  1730.                                   &l_extension[0], sizeof(l_extension),
  1731.                   &l_palette_type, &l_alpha_dither, &l_remove_unused,
  1732.                   &l_palette[0], sizeof(l_palette));
  1733.  
  1734.       }
  1735.       else
  1736.       {
  1737.          l_rc = 0;
  1738.          l_from    = range_from;
  1739.          l_to      = range_to;
  1740.          l_flatten = flatten;
  1741.          l_dest_type   = dest_type;
  1742.          l_dest_colors = dest_colors;
  1743.          l_dest_dither = dest_dither;
  1744.          l_palette_type   = palette_type;
  1745.          l_alpha_dither   = alpha_dither;
  1746.          l_remove_unused  = remove_unused;
  1747.          if(basename != NULL)
  1748.          {
  1749.             strncpy(l_basename, basename, sizeof(l_basename) -1);
  1750.             l_basename[sizeof(l_basename) -1] = '\0';
  1751.          }
  1752.          if(palette != NULL)
  1753.          {
  1754.             strncpy(l_palette, palette, sizeof(l_palette) -1);
  1755.             l_palette[sizeof(l_palette) -1] = '\0';
  1756.          }
  1757.          strncpy(l_extension, extension, sizeof(l_extension) -1);
  1758.          l_extension[sizeof(l_extension) -1] = '\0';
  1759.          
  1760.       }
  1761.  
  1762.       if(l_rc >= 0)
  1763.       {
  1764.          /* cut off extension and trailing frame number */
  1765.          l_basename_ptr = p_alloc_basename(&l_basename[0], &l_number);
  1766.          if(l_basename_ptr == NULL)  { l_rc = -1; }
  1767.          else
  1768.          {
  1769.             l_rc = p_frames_convert(ainfo_ptr, l_from, l_to,
  1770.                                     l_save_proc_name,
  1771.                                     l_basename_ptr,
  1772.                                     l_extension,
  1773.                                     l_flatten,
  1774.                                     l_dest_type,
  1775.                                     l_dest_colors,
  1776.                                     l_dest_dither,
  1777.                     l_palette_type,
  1778.                     l_alpha_dither,
  1779.                     l_remove_unused,
  1780.                     l_palette);
  1781.             g_free(l_basename_ptr);
  1782.          }
  1783.       }
  1784.     }
  1785.     p_free_ainfo(&ainfo_ptr);
  1786.   }
  1787.   
  1788.   return(l_rc);    
  1789. }    /* end gap_range_conv */
  1790.  
  1791.  
  1792.  
  1793. /* ============================================================================
  1794.  * gap_anim_sizechange
  1795.  *    scale, resize or crop all anim_frame images of the animation
  1796.  *    (depending on asiz_mode)
  1797.  * ============================================================================
  1798.  */
  1799. int gap_anim_sizechange(GimpRunModeType run_mode, t_gap_asiz asiz_mode, gint32 image_id,
  1800.                   long size_x, long size_y, long offs_x, long offs_y)
  1801. {
  1802.   int    l_rc;
  1803.   long   l_size_x, l_size_y;
  1804.   long   l_offs_x, l_offs_y;
  1805.   t_anim_info *ainfo_ptr;
  1806.   
  1807.   l_rc = 0;
  1808.   ainfo_ptr = p_alloc_ainfo(image_id, run_mode);
  1809.   if(ainfo_ptr != NULL)
  1810.   {
  1811.     if (0 == p_dir_ainfo(ainfo_ptr))
  1812.     {
  1813.       if(run_mode == GIMP_RUN_INTERACTIVE)
  1814.       {
  1815.          l_rc = p_anim_sizechange_dialog (ainfo_ptr, asiz_mode,
  1816.                                           &l_size_x, &l_size_y,
  1817.                                           &l_offs_x, &l_offs_y);
  1818.       }
  1819.       else
  1820.       {
  1821.          l_size_x = size_x;
  1822.          l_size_y = size_y;
  1823.          l_offs_x = offs_x;
  1824.          l_offs_y = offs_y;
  1825.       }
  1826.  
  1827.       if(l_rc >= 0)
  1828.       {
  1829.          l_rc = p_save_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1830.          if(l_rc >= 0)
  1831.          {
  1832.            /* we have to resize the current anim frame image in gimp's ram
  1833.             *(from where we were invoked)
  1834.             * Note: All anim frames on disc and the current one in ram
  1835.             *       must fit in size and type, to allow further animation operations.
  1836.             *       (Restriction of duplicate_into)
  1837.             */
  1838.            l_rc = p_image_sizechange(ainfo_ptr->image_id, asiz_mode,
  1839.                                      l_size_x, l_size_y, l_offs_x, l_offs_y);
  1840.  
  1841.            if(l_rc == 0)
  1842.            {
  1843.               /* sizechange for all anim frames on disk */
  1844.               l_rc = p_anim_sizechange(ainfo_ptr, asiz_mode,
  1845.                                        l_size_x, l_size_y,
  1846.                                        l_offs_x, l_offs_y );
  1847.            }
  1848.            /* p_load_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename); */
  1849.            /* dont need to reload, because the same sizechange operation was
  1850.             * applied both to ram-image and dikfile
  1851.             *
  1852.             * But we must clear all undo steps. 
  1853.             * (If the user could undo the sizechange on the current image,
  1854.             *  it would not fit to the other frames on disk.)
  1855.             */
  1856.            gimp_image_undo_enable(ainfo_ptr->image_id); /* clear undo stack */
  1857.          }
  1858.       }
  1859.     }
  1860.     p_free_ainfo(&ainfo_ptr);
  1861.   }
  1862.   
  1863.   return(l_rc);    
  1864. }    /* end gap_anim_sizechange */
  1865.