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_exchange_image.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-24  |  18.3 KB  |  534 lines

  1. /* gap_exchange_image.c
  2.  *   by hof (Wolfgang Hofer)
  3.  *
  4.  * GAP ... Gimp Animation Plugins
  5.  *
  6.  * basic anim functions:
  7.  *   This Plugin drops the content of the destination
  8.  *   image (all layers,channels, paths, parasites & guides)
  9.  *   and then moves (steal) the content of a source image to dst. image
  10.  *
  11.  */
  12. /* The GIMP -- an image manipulation program
  13.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  14.  *
  15.  * This program is free software; you can redistribute it and/or modify
  16.  * it under the terms of the GNU General Public License as published by
  17.  * the Free Software Foundation; either version 2 of the License, or
  18.  * (at your option) any later version.
  19.  *
  20.  * This program is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU General Public License for more details.
  24.  *
  25.  * You should have received a copy of the GNU General Public License
  26.  * along with this program; if not, write to the Free Software
  27.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  28.  */
  29.  
  30. /* revision history:
  31.  * 1.1.20a  2000/04/29   hof: bugfix in p_steal_content:  we must copy cmap before removing layers
  32.  *                            from src_image to avoid crash on indexed frames.
  33.  * 1.1.16a  2000/02/05   hof: handle path lockedstaus and image unit
  34.  * 1.1.15b  2000/01/30   hof: handle image specific parasites
  35.  * 1.1.15a  2000/01/25   hof: stopped gimp 1.0.x support (removed p_copy_content)
  36.  *                            handle pathes
  37.  * 0.98.00; 1998/11/30   hof: 1.st release
  38.  *                             (substitute for the procedure "gimp_duplicate_into"
  39.  *                              that was never part of the GIMP core)
  40.  */
  41.  
  42. /* SYTEM (UNIX) includes */ 
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <time.h>
  46. #include <string.h>
  47. #include <errno.h>
  48.  
  49. /* GIMP includes */
  50. #include "gtk/gtk.h"
  51. #include "libgimp/gimp.h"
  52.  
  53. /* GAP includes */
  54. #include "gap_layer_copy.h"
  55. #include "gap_pdb_calls.h"
  56. #include "gap_exchange_image.h"
  57. #include "gap_lib.h"
  58.  
  59.  
  60. extern      int gap_debug; /* ==0  ... dont print debug infos */
  61.  
  62.  
  63. /* ============================================================================
  64.  * p_steal_content
  65.  *   
  66.  *   steal or copy all elements
  67.  *     - layers, 
  68.  *     - channels, selections, 
  69.  *     - pathes,
  70.  *     - guides, 
  71.  *     - colormap
  72.  *     from src_image and add them to dst_image.
  73.  * ============================================================================
  74.  */
  75.  
  76. static int
  77. p_steal_content(gint32 dst_image_id, gint32 src_image_id)
  78. {
  79.    int     l_rc;
  80.    int     l_idx;
  81.    
  82.    gint    l_nlayers;
  83.    gint    l_nchannels;
  84.    gint32 *l_layers_list;
  85.    gint32 *l_channels_list;
  86.    gint32  l_layer_id;
  87.    gint32  l_channel_id;
  88.    gint32  l_new_channel_id;
  89.    gint32  l_layer_mask_id;
  90.    gint32  l_guide_id;
  91.    gint32  l_src_fsel_id;                 /* floating selection (in the src_image) */
  92.    gint32  l_src_fsel_attached_to_id;     /* the drawable where floating selection is attached to (in the src_image) */
  93.    gint32  l_fsel_attached_to_id;         /* the drawable id where to attach the floating selection (dst) */
  94.    gint32  l_fsel_id;                     /* the drawable id of the floating selection itself (dst)  */
  95.    gint32  l_active_layer_id;
  96.    gint32  l_active_channel_id;
  97.    gint32  l_x1, l_x2, l_y1, l_y2;
  98.    guchar *l_cmap;
  99.    gint    l_ncolors;
  100.    gchar   **l_path_names;
  101.    gchar    *l_current_pathname;
  102.    gint32   l_num_paths;
  103.    gdouble *l_path_points;
  104.    gint32   l_path_type;
  105.    gint32   l_path_closed;
  106.    gint32   l_num_points;
  107.    GimpParasite  *l_parasite;
  108.    gchar    **l_parasite_names = NULL;
  109.    gint32     l_num_parasites = 0;
  110.  
  111.    l_rc = -1;  /* init retcode to Errorstate */
  112.    l_layers_list = NULL;
  113.    l_channels_list = NULL;
  114.    l_active_layer_id = -1;
  115.    l_active_channel_id = -1;
  116.    l_fsel_attached_to_id = -1;    /* -1  assume fsel is not available (and not attached to any drawable) */
  117.    l_fsel_id = -1;                /* -1  assume there is no floating selection */
  118.  
  119.  
  120.    if(gap_debug) printf("GAP-DEBUG: START p_steal_content dst_id=%d src_id=%d\n", (int)dst_image_id, (int)src_image_id);
  121.  
  122.    /* gimp_image_undo_disable (src_image_id); */ /* does not work !! if active we can not steal layers */
  123.  
  124.    /*  Copy the colormap if necessary  */
  125.    if(gimp_image_base_type(src_image_id) == GIMP_INDEXED)
  126.    {
  127.        l_cmap = gimp_image_get_cmap (src_image_id, &l_ncolors);
  128.  
  129.        if(gap_debug) printf("GAP-DEBUG: copy colormap ncolors %d\n", (int)l_ncolors);
  130.        gimp_image_set_cmap(dst_image_id, l_cmap, l_ncolors);
  131.    }
  132.  
  133.    
  134.    /* check for floating selection */
  135.    l_src_fsel_attached_to_id = -1;
  136.    l_src_fsel_id = gimp_image_floating_selection(src_image_id);
  137.    if(l_src_fsel_id >= 0)
  138.    {
  139.        if(gap_debug) printf("GAP-DEBUG: call floating_sel_relax fsel_id=%d\n",
  140.                            (int)l_src_fsel_id);
  141.        
  142.        p_gimp_floating_sel_relax (l_src_fsel_id, FALSE);
  143.        l_src_fsel_attached_to_id = p_gimp_image_floating_sel_attached_to(src_image_id);
  144.    }
  145.   
  146.    /* steal all layers */
  147.    l_layers_list = gimp_image_get_layers(src_image_id, &l_nlayers);
  148.  
  149.    /* foreach layer do */
  150.    for(l_idx = l_nlayers -1; l_idx >= 0; l_idx--)
  151.    {
  152.      l_layer_id = l_layers_list[l_idx];
  153.      if(gap_debug) printf("GAP-DEBUG: START p_steal_content layer_id[%d]=%d\n", (int)l_idx, (int)l_layer_id);
  154.  
  155.  
  156.      if(l_layer_id  == gimp_image_get_active_layer(src_image_id))
  157.      {
  158.         l_active_layer_id = l_layer_id;
  159.      }
  160.  
  161.      l_layer_mask_id = gimp_layer_get_mask_id(l_layer_id);
  162.      if(l_layer_mask_id >= 0)
  163.      {
  164.         /* layer has layermask */
  165.         if(gap_debug) printf("GAP-DEBUG: START p_steal_content layer_mask_id=%d\n", (int)l_layer_mask_id);
  166.        
  167.         /* check for floating selection */
  168.         if(l_layer_mask_id == l_src_fsel_attached_to_id)
  169.         {
  170.            l_fsel_attached_to_id = l_layer_mask_id;   /* the floating selection is attached to this layer_mask */
  171.         }
  172.  
  173.         p_gimp_drawable_set_image(l_layer_mask_id, dst_image_id);
  174.      }
  175.  
  176.      /* remove layer from source */
  177.      gimp_image_remove_layer(src_image_id, l_layer_id);
  178.  
  179.      /* and set the dst_image as it's new Master */
  180.      p_gimp_drawable_set_image(l_layer_id, dst_image_id);
  181.  
  182.      if(l_layer_id == l_src_fsel_id)
  183.      {
  184.         l_fsel_id = l_layer_id;    /* this layer is the floating selection */
  185.      }
  186.      else
  187.      {
  188.         if(gap_debug) printf("GAP-DEBUG: START p_steal_content add_layer_id=%d\n", (int)l_layer_id);
  189.         /* add the layer on top of the images layerstak */
  190.         gimp_image_add_layer (dst_image_id, l_layer_id, 0);
  191.         
  192.         if(l_layer_id == l_src_fsel_attached_to_id)
  193.         {
  194.            l_fsel_attached_to_id = l_layer_id;    /* the floating selection is attached to this layer */
  195.         }
  196.      }
  197.  
  198.    }  /* end foreach layer */
  199.    
  200.    /* steal all channels */ 
  201.  
  202.    l_channels_list = gimp_image_get_channels(src_image_id, &l_nchannels);
  203.    
  204.    /* foreach channel do */
  205.    for(l_idx = l_nchannels -1; l_idx >= 0; l_idx--)
  206.    {
  207.       l_channel_id = l_channels_list[l_idx];
  208.       if(gap_debug) printf("GAP-DEBUG: START p_steal_content channel_id=%d\n", (int)l_channel_id);
  209.  
  210.       l_new_channel_id = p_my_channel_copy(dst_image_id, l_channel_id);
  211.                        
  212.       if (l_new_channel_id < 0)  { goto cleanup; }
  213.                       
  214.  
  215.        /* add channel on top of the channelstack */
  216.        gimp_image_add_channel (dst_image_id, l_new_channel_id, 0);
  217.  
  218.        /* adjust channelproperties */
  219.        gimp_channel_set_visible (l_new_channel_id, gimp_channel_get_visible(l_channel_id));
  220.        gimp_channel_set_show_masked (l_new_channel_id, gimp_channel_get_show_masked(l_channel_id));
  221.  
  222.        if(l_channel_id == l_src_fsel_attached_to_id)
  223.        {
  224.           l_fsel_attached_to_id = l_channel_id;    /* the floating_selection is attached to this channel */
  225.        }
  226.  
  227.        if(l_channel_id == gimp_image_get_active_channel(src_image_id))
  228.        {
  229.           l_active_channel_id = l_channel_id;
  230.        }
  231.  
  232.        /* remove channel from source */
  233.        gimp_image_remove_channel(src_image_id, l_channel_id);
  234.  
  235.        /* and set the dst_image as it's new Master */
  236.        p_gimp_drawable_set_image(l_channel_id, dst_image_id);
  237.        
  238.    }      /* end foreach channel */
  239.  
  240.    /* check and see if we have to copy the selection */
  241.    l_channel_id = gimp_image_get_selection(src_image_id);
  242.    if((p_get_gimp_selection_bounds(src_image_id, &l_x1, &l_y1, &l_x2, &l_y2))
  243.    && (l_channel_id >= 0))
  244.    {
  245.        if(gap_debug) printf("GAP-DEBUG: START p_steal_content selection_channel_id=%d\n", (int)l_channel_id);
  246.               
  247.        p_gimp_drawable_set_image(l_channel_id, dst_image_id);
  248.        p_gimp_selection_load (l_channel_id);
  249.     
  250.    }
  251.  
  252.  
  253.    /* attach the floating selection... */
  254.    if((l_fsel_id >= 0) && (l_fsel_attached_to_id >= 0))
  255.    {
  256.       if(gap_debug) printf("GAP-DEBUG: attaching floating_selection id=%d to id %d\n",
  257.                     (int)l_fsel_id, (int)l_fsel_attached_to_id);
  258.       if(p_gimp_floating_sel_attach (l_fsel_id, l_fsel_attached_to_id) < 0)
  259.       {
  260.          /* in case of error add floating_selection like an ordinary layer
  261.       * (if patches are not installed you'll get the error for sure)
  262.       */
  263.          printf("GAP: floating_selection is added as top-layer (attach failed)\n");
  264.          gimp_image_add_layer (dst_image_id, l_fsel_id, 0);
  265.  
  266.       }
  267.    }
  268.  
  269.    /* set active layer/channel */
  270.    if(l_active_channel_id >= 0)
  271.    {
  272.        if(gap_debug) printf("GAP-DEBUG: SET active channel %d\n", (int)l_active_channel_id);     
  273.        gimp_image_set_active_channel(dst_image_id, l_active_channel_id);
  274.    }
  275.    if(l_active_layer_id >= 0)
  276.    {
  277.        if(gap_debug) printf("GAP-DEBUG: SET active layer %d\n", (int)l_active_layer_id);     
  278.        gimp_image_set_active_layer(dst_image_id, l_active_layer_id);
  279.    }
  280.  
  281.    /* copy guides */
  282.    l_guide_id = p_gimp_image_findnext_guide(src_image_id, 0);  /* get 1.st guide */
  283.    while(l_guide_id > 0)
  284.    {
  285.       /* get position and orientation for the current guide ID */
  286.       p_gimp_image_add_guide(dst_image_id, 
  287.                              p_gimp_image_get_guide_position(src_image_id, l_guide_id),
  288.                              p_gimp_image_get_guide_orientation(src_image_id, l_guide_id)
  289.                              );
  290.       l_guide_id = p_gimp_image_findnext_guide(src_image_id, l_guide_id);
  291.    }
  292.  
  293.    /* copy paths */
  294.    l_path_names = p_gimp_path_list(src_image_id, &l_num_paths);
  295.    if((l_path_names != NULL) && (l_num_paths > 0))
  296.    {
  297.       l_current_pathname = p_gimp_path_get_current(src_image_id);
  298.       for(l_idx=l_num_paths-1; l_idx >= 0; l_idx--)
  299.       {
  300.      l_path_points = p_gimp_path_get_points(src_image_id, l_path_names[l_idx],
  301.                                &l_path_type, &l_path_closed, &l_num_points);
  302.          if((l_path_points != NULL) && (l_num_points > 0))
  303.      {
  304.         p_gimp_path_set_points(dst_image_id, l_path_names[l_idx],
  305.                                l_path_type, l_num_points, l_path_points);
  306.             p_gimp_path_set_locked(dst_image_id, l_path_names[l_idx],
  307.                                p_gimp_path_get_locked(src_image_id, l_path_names[l_idx]));
  308.       }
  309.                   
  310.          if(l_path_points)  g_free(l_path_points);         
  311.      
  312.      g_free(l_path_names[l_idx]);
  313.       }
  314.       if(l_current_pathname)
  315.       {
  316.          p_gimp_path_set_current(dst_image_id, l_current_pathname);
  317.          g_free(l_current_pathname);
  318.       }
  319.    }
  320.    if(l_path_names) g_free(l_path_names);
  321.  
  322.    /* copy image specific parasites
  323.     *  (drawable specific parasites are handled implicite
  324.     *   by stealing layers and channels)
  325.     */
  326.    l_parasite_names = p_gimp_image_parasite_list (src_image_id, &l_num_parasites);
  327.  
  328.    for(l_idx = 0; l_idx < l_num_parasites; l_idx++)
  329.    {
  330.      l_parasite = gimp_image_parasite_find(src_image_id, l_parasite_names[l_idx]);
  331.      if(l_parasite)
  332.      {
  333.     if(gap_debug) printf("copy image_parasite NAME:%s:\n",  l_parasite_names[l_idx]);
  334.  
  335.     gimp_image_attach_new_parasite(dst_image_id,
  336.                                     l_parasite->name,
  337.                     l_parasite->flags,
  338.                     l_parasite->size,
  339.                     l_parasite->data);
  340.     if(l_parasite->data) g_free(l_parasite->data);
  341.     if(l_parasite->name) g_free(l_parasite->name);
  342.     g_free(l_parasite);
  343.      }
  344.      g_free(l_parasite_names[l_idx]);
  345.    }
  346.    g_free(l_parasite_names);
  347.  
  348.    /* copy the image unit */ 
  349.    gimp_image_set_unit(dst_image_id, 
  350.                        gimp_image_get_unit(src_image_id));
  351.  
  352.    l_rc = 0;
  353.    
  354. cleanup:
  355.    if(l_layers_list) g_free (l_layers_list);
  356.    if(l_channels_list) g_free (l_channels_list);
  357.    
  358.    if(gap_debug) printf("GAP-DEBUG: END p_steal_content dst_id=%d src_id=%d  rc=%d\n",
  359.                  (int)dst_image_id, (int)src_image_id, l_rc);
  360.    return (l_rc);            /* 0 .. OK, or -1 on error */
  361. }   /* end p_steal_content */
  362.  
  363.  
  364. /* ============================================================================
  365.  * p_replace_img
  366.  *   
  367.  *   This procedure replaces the content of image_id 
  368.  *     with the content from src_image_id.
  369.  *     By stealing all its layers and channels.
  370.  * ============================================================================
  371.  */
  372.  
  373. static int
  374. p_replace_img(gint32 image_id, gint32 src_image_id)
  375. {
  376.    int     l_rc;
  377.    int     l_idx;
  378.    gint    l_nlayers;
  379.    gint    l_nchannels;
  380.    gint32 *l_layers_list;
  381.    gint32 *l_channels_list;
  382.    gint32  l_layer_id;
  383.    gint32  l_channel_id;
  384.    gint32  l_guide_id;
  385.    gint32  l_old_bg_layer_id;
  386.    gchar  **l_path_names;
  387.    gint32   l_num_paths;
  388.    gchar    **l_parasite_names = NULL;
  389.    gint32     l_num_parasites = 0;
  390.  
  391.    if(gap_debug) printf("\nGAP-DEBUG: START p_replace_img img_id=%d \n", (int)image_id);
  392.  
  393.    l_old_bg_layer_id = -1;
  394.  
  395.    gimp_image_undo_disable (image_id);
  396.    
  397.    /* remove selection (if there is any) */
  398.    p_gimp_selection_none(image_id);
  399.  
  400.    l_channels_list = gimp_image_get_channels(image_id, &l_nchannels);
  401.    
  402.    /* foreach channel do */
  403.    for(l_idx = 0; l_idx < l_nchannels; l_idx++)
  404.    {
  405.       l_channel_id = l_channels_list[l_idx];
  406.       gimp_image_remove_channel(image_id, l_channel_id);
  407.       gimp_channel_delete(l_channel_id);
  408.    }
  409.    if(l_channels_list) { g_free (l_channels_list); }
  410.  
  411.  
  412.    /* delete guides */
  413.    l_guide_id = p_gimp_image_findnext_guide(image_id, 0);  /* get 1.st guide */
  414.    while(l_guide_id > 0)
  415.    {
  416.       /* delete guide ID */
  417.       p_gimp_image_delete_guide(image_id, l_guide_id);
  418.       
  419.       /* get 1.st (of the remaining) guides */
  420.       l_guide_id = p_gimp_image_findnext_guide(image_id, 0); 
  421.    }
  422.  
  423.    /* delete paths */
  424.    l_path_names = p_gimp_path_list(image_id, &l_num_paths);
  425.    if((l_path_names != NULL) && (l_num_paths > 0))
  426.    {
  427.       for(l_idx=0; l_idx < l_num_paths; l_idx++)
  428.       {
  429.      p_gimp_path_delete(image_id, l_path_names[l_idx]);
  430.      g_free(l_path_names[l_idx]);
  431.       }
  432.    }
  433.    if(l_path_names) g_free(l_path_names);
  434.  
  435.    /* remove image specific parasites */   
  436.    l_parasite_names = p_gimp_image_parasite_list (image_id, &l_num_parasites);
  437.    if(l_parasite_names)
  438.    {
  439.      for(l_idx = 0; l_idx < l_num_parasites; l_idx++)
  440.      {
  441.        if(gap_debug) printf("detach image_parasite NAME:%s:\n",  l_parasite_names[l_idx]);
  442.        gimp_image_parasite_detach(image_id, l_parasite_names[l_idx]);
  443.        g_free(l_parasite_names[l_idx]);
  444.      }
  445.      g_free(l_parasite_names);
  446.    }
  447.  
  448.    /* get list of all (old) dst_layers to delete */
  449.    l_layers_list = gimp_image_get_layers(image_id, &l_nlayers);
  450.  
  451.    /* foreach (old) layer of the do */
  452.    for(l_idx = 0; l_idx < l_nlayers; l_idx++)
  453.    {
  454.      l_layer_id = l_layers_list[l_idx];
  455.      
  456.      if(l_idx == l_nlayers -1)
  457.      {
  458.         /* the background layer is renamed
  459.          * (if not GIMP 1.1 will rename the new imported 
  460.          *  Background Layer as "background#2")
  461.          * and deleted later.
  462.          * Important: the dst_image_id should not be completely empty.
  463.          *            anytime it may happen, that its display(s) is (are) updated
  464.          *            and this may crash on empty images.
  465.          */
  466.         gimp_layer_set_name(l_layer_id, "--old-bg-layer-will-die-soon");
  467.         l_old_bg_layer_id = l_layer_id;
  468.      }
  469.      else
  470.      {
  471.         if(gap_debug) printf("GAP-DEBUG: p_replace_img del layer_id=%d \n", (int)l_layer_id);
  472.         gimp_image_remove_layer(image_id, l_layer_id);
  473.         /* gimp_layer_delete(l_layer_id); */      /* did crash in gimp 1.0.2 ?? and in 1.1 too */
  474.      }
  475.    }
  476.    
  477.    /* steal all layers, channels and guides from src_image */
  478.    l_rc = p_steal_content(image_id, src_image_id);
  479.  
  480.    if(l_old_bg_layer_id >= 0)
  481.    {
  482.       /* now delete the (old) background layer */
  483.       if(gap_debug) printf("GAP-DEBUG: p_replace_img del (old bg) layer_id=%d \n", (int)l_old_bg_layer_id);
  484.       gimp_image_remove_layer(image_id, l_old_bg_layer_id);
  485.       /* gimp_layer_delete(l_old_bg_layer_id); */      /* did crash in gimp 1.0.2 ?? and in 1.1 too */
  486.    }
  487.  
  488.    if (l_layers_list) { g_free (l_layers_list); }
  489.  
  490.    gimp_image_undo_enable (image_id);
  491.    
  492.    if(gap_debug) printf("GAP-DEBUG: END p_replace_img img_id=%d  rc=%d\n", (int)image_id, l_rc);
  493.  
  494.    return l_rc;  /* OK */
  495.  
  496. }   /* end p_replace_img */
  497.  
  498.  
  499.  
  500. /* ============================================================================
  501.  * p_exchange_image
  502.  *   
  503.  *   
  504.  * ============================================================================
  505.  */
  506.  
  507. int p_exchange_image(gint32 dst_image_id, gint32 src_image_id)
  508. {
  509.    int l_rc;
  510.  
  511.    /* check for equal image type */
  512.    if(gimp_image_base_type(src_image_id) != gimp_image_base_type(dst_image_id))
  513.    {
  514.       printf("GAP: p_exchange_image Image Types are not equal\n");
  515.       return -1;
  516.    }
  517.  
  518.    /* check for equal width/height */
  519.    if((gimp_image_height(src_image_id) != gimp_image_height(dst_image_id))
  520.    || (gimp_image_width(src_image_id)  != gimp_image_width(dst_image_id)))
  521.    {
  522.       printf("GAP: p_exchange_image Image Size is not equal\n");
  523.       return -1;
  524.    }
  525.  
  526.    /* Now we drop content and copy (or steal) from src_image
  527.     * step by step, using many other PDB-Interfaces.
  528.     */
  529.    l_rc = p_replace_img(dst_image_id, src_image_id);
  530.  
  531.    return (l_rc);
  532.    
  533. }   /* end p_exchange_image */
  534.