home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / iwarp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-28  |  42.2 KB  |  1,594 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. /* IWarp  a plug-in for the GIMP
  20.    Version 0.1 
  21.    
  22.    IWarp is a gimp plug-in for interactive image warping. To apply the 
  23.    selected deformation to the image, press the left mouse button and 
  24.    move the mouse pointer in the preview image.
  25.    
  26.    Copyright (C) 1997 Norbert Schmitz
  27.    nobert.schmitz@student.uni-tuebingen.de
  28.  
  29.    Most of the gimp and gtk specific code is taken from other plug-ins 
  30.  
  31.    v0.11a
  32.     animation of non-alpha layers (background) creates now layers with 
  33.     alpha channel. (thanks to Adrian Likins for reporting this bug)
  34.  
  35.   v0.12 
  36.     fixes a very bad bug. 
  37.      (thanks to Arthur Hagen for reporting it)
  38.     
  39. */
  40.  
  41. #include "config.h"
  42.  
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <stdio.h>
  46.  
  47. #include <gtk/gtk.h>
  48.  
  49. #include <libgimp/gimp.h>
  50. #include <libgimp/gimpui.h>
  51.  
  52. #include "libgimp/stdplugins-intl.h"
  53.  
  54.  
  55. #define MAX_PREVIEW_WIDTH      256
  56. #define MAX_PREVIEW_HEIGHT     256
  57. #define MAX_DEFORM_AREA_RADIUS 100
  58.  
  59. #define SCALE_WIDTH    100
  60. #define MAX_NUM_FRAMES 100
  61.  
  62. typedef enum
  63. {
  64.   GROW,
  65.   SHRINK,
  66.   MOVE,
  67.   REMOVE,
  68.   SWIRL_CCW,
  69.   SWIRL_CW
  70. } DeformMode;
  71.  
  72. typedef struct
  73. {
  74.   gint run;
  75. } iwarp_interface;
  76.  
  77. typedef struct
  78. {
  79.   gint        deform_area_radius;
  80.   gdouble     deform_amount;
  81.   DeformMode  deform_mode;
  82.   gboolean    do_bilinear;
  83.   gboolean    do_supersample;
  84.   gdouble     supersample_threshold;
  85.   gint        max_supersample_depth;
  86. } iwarp_vals_t; 
  87.  
  88.  
  89. /* Declare local functions.
  90.  */
  91. static void      query  (void);
  92. static void      run    (gchar     *name,
  93.              gint       nparams,
  94.              GimpParam    *param,
  95.              gint      *nreturn_vals,
  96.              GimpParam   **return_vals);
  97.  
  98. static void      iwarp                   (void);
  99. static void      iwarp_frame             (void);
  100.  
  101. static gboolean  iwarp_dialog            (void);
  102. static void      iwarp_animate_dialog    (GtkWidget *dlg,
  103.                       GtkWidget *notebook);
  104.  
  105. static void      iwarp_settings_dialog   (GtkWidget *dlg,
  106.                       GtkWidget *notebook);
  107.  
  108. static void      iwarp_ok_callback       (GtkWidget *widget,
  109.                       gpointer   data);
  110. static void      iwarp_reset_callback    (GtkWidget *widget,
  111.                       gpointer   data);
  112.  
  113. static gint      iwarp_motion_callback   (GtkWidget *widget,
  114.                       GdkEvent  *event);
  115.  
  116. static void      iwarp_update_preview    (gint       x0,
  117.                       gint       y0,
  118.                       gint       x1,
  119.                       gint       y1);
  120.  
  121. static void      iwarp_get_pixel         (gint       x,
  122.                       gint       y,
  123.                       guchar    *pixel);
  124.  
  125. static void      iwarp_get_deform_vector (gdouble    x,
  126.                       gdouble    y, 
  127.                       gdouble   *xv,
  128.                       gdouble   *yv);
  129.  
  130. static void      iwarp_get_point         (gdouble    x,
  131.                       gdouble    y,
  132.                       guchar    *color);
  133.  
  134. static gint      iwarp_supersample_test  (GimpVector2 *v0,
  135.                       GimpVector2 *v1, 
  136.                       GimpVector2 *v2,
  137.                       GimpVector2 *v3);
  138.  
  139. static void      iwarp_getsample         (GimpVector2  v0,
  140.                       GimpVector2  v1,
  141.                       GimpVector2  v2,
  142.                       GimpVector2  v3, 
  143.                       gdouble      x,
  144.                       gdouble      y,
  145.                       gint        *sample,
  146.                       gint        *cc,
  147.                       gint         depth,
  148.                       gdouble      scale);
  149.  
  150. static void      iwarp_supersample       (gint       sxl,
  151.                       gint       syl,
  152.                       gint       sxr,
  153.                       gint       syr,
  154.                       guchar    *dest_data,
  155.                       gint       stride,
  156.                       gint      *progress,
  157.                       gint       max_progress);
  158.  
  159. static guchar    iwarp_transparent_color (gint       x,
  160.                       gint       y);
  161.  
  162. static void      iwarp_cpy_images        (void);
  163.  
  164. static void      iwarp_preview_get_pixel (gint       x,
  165.                       gint       y,
  166.                       guchar   **color);
  167.  
  168. static void      iwarp_preview_get_point (gdouble    x,
  169.                       gdouble    y,
  170.                       guchar    *color);
  171.  
  172. static void      iwarp_deform            (gint       x,
  173.                       gint       y,
  174.                       gdouble    vx,
  175.                       gdouble    vy);
  176.  
  177. static void      iwarp_move              (gint       x,
  178.                       gint       y,
  179.                       gint       xx,
  180.                       gint       yy);
  181.  
  182.  
  183. GimpPlugInInfo PLUG_IN_INFO =
  184. {
  185.   NULL,  /* init_proc  */
  186.   NULL,  /* quit_proc  */
  187.   query, /* query_proc */
  188.   run,   /* run_proc   */
  189. };
  190.  
  191. static iwarp_interface wint = 
  192. {
  193.   FALSE
  194. };
  195.  
  196. static iwarp_vals_t iwarp_vals = 
  197. {
  198.   20,
  199.   0.3,
  200.   MOVE,
  201.   TRUE,
  202.   FALSE,
  203.   2.0,
  204.   2
  205. }; 
  206.  
  207. static GimpDrawable   *drawable = NULL;
  208. static GimpDrawable   *destdrawable = NULL;
  209. static GtkWidget   *preview = NULL;
  210. static guchar      *srcimage = NULL;
  211. static guchar      *dstimage = NULL;
  212. static gint         preview_width, preview_height;
  213. static gint         sel_width, sel_height;
  214. static gint         image_bpp;
  215. static gint         preserve_trans;
  216. static GimpVector2 *deform_vectors = NULL;
  217. static GimpVector2 *deform_area_vectors = NULL;
  218. static gint         lastx, lasty;
  219. static gdouble      filter[MAX_DEFORM_AREA_RADIUS];
  220. static gboolean     do_animate = FALSE;
  221. static gboolean     do_animate_reverse = FALSE;
  222. static gboolean     do_animate_ping_pong = FALSE;
  223. static gdouble      supersample_threshold_2;
  224. static gint         xl, yl, xh, yh;
  225. static gint         tile_width, tile_height;
  226. static GimpTile       *tile = NULL;
  227. static gdouble      pre2img, img2pre;
  228. static gint         preview_bpp;
  229. static gdouble      animate_deform_value = 1.0;
  230. static gint32       imageID;
  231. static gint         animate_num_frames = 2;
  232. static gint         frame_number;
  233. static gint         layer_alpha;
  234.  
  235.  
  236. MAIN ()
  237.  
  238. static void
  239. query (void)
  240. {
  241.   static GimpParamDef args[] =
  242.   {
  243.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  244.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  245.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
  246.   };
  247.   static gint nargs = sizeof (args) / sizeof (args[0]);
  248.  
  249.   gimp_install_procedure ("plug_in_iwarp",
  250.               "Interactive warping of the specified drawable",
  251.               "Interactive warping of the specified drawable",
  252.               "Norbert Schmitz",
  253.               "Norbert Schmitz",
  254.               "1997",
  255.               N_("<Image>/Filters/Distorts/IWarp..."),
  256.               "RGB*, GRAY*",
  257.               GIMP_PLUGIN,
  258.               nargs, 0,
  259.               args, NULL);
  260. }
  261.  
  262. static void
  263. run (gchar   *name,
  264.      gint     nparams,
  265.      GimpParam  *param,
  266.      gint    *nreturn_vals,
  267.      GimpParam **return_vals)
  268. {
  269.   static GimpParam values[1];
  270.   GimpRunModeType run_mode;
  271.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  272.  
  273.   run_mode = param[0].data.d_int32;
  274.  
  275.   /*  Get the specified drawable  */
  276.   destdrawable = drawable = gimp_drawable_get (param[2].data.d_drawable);
  277.   imageID = param[1].data.d_int32;
  278.  
  279.   /*  Make sure that the drawable is gray or RGB color  */
  280.   if (gimp_drawable_is_rgb (drawable->id) ||
  281.       gimp_drawable_is_gray (drawable->id))
  282.     {
  283.       switch (run_mode)
  284.     {
  285.         case GIMP_RUN_INTERACTIVE:
  286.           INIT_I18N_UI();
  287.           gimp_get_data ("plug_in_iwarp", &iwarp_vals);
  288.           gimp_tile_cache_ntiles (2 * (drawable->width + gimp_tile_width ()-1) /
  289.                   gimp_tile_width ());
  290.           if (iwarp_dialog())
  291.         iwarp();
  292.           gimp_set_data ("plug_in_iwarp", &iwarp_vals, sizeof (iwarp_vals_t));
  293.        gimp_displays_flush ();
  294.       break;
  295.  
  296.         case GIMP_RUN_NONINTERACTIVE:
  297.       status = GIMP_PDB_CALLING_ERROR;
  298.         break;
  299.  
  300.         case GIMP_RUN_WITH_LAST_VALS:
  301.       status = GIMP_PDB_CALLING_ERROR;
  302.         break;
  303.  
  304.         default:
  305.       break;
  306.     }
  307.     }
  308.   else
  309.     {
  310.       status = GIMP_PDB_EXECUTION_ERROR;
  311.     }
  312.  
  313.   *nreturn_vals = 1;
  314.   *return_vals = values;
  315.  
  316.   values[0].type = GIMP_PDB_STATUS;
  317.   values[0].data.d_status = status;
  318.  
  319.   gimp_drawable_detach (drawable);
  320.  
  321.   g_free (srcimage);
  322.   g_free (dstimage);  
  323.   g_free (deform_vectors);
  324.   g_free (deform_area_vectors);
  325. }
  326.  
  327. static void
  328. iwarp_get_pixel (gint    x,
  329.          gint    y,
  330.          guchar *pixel)
  331. {
  332.  static gint  old_col = -1;
  333.  static gint  old_row = -1;
  334.  guchar      *data;
  335.  gint         col, row;
  336.  gint         i;
  337.  
  338.  if (x >= xl && x < xh && y  >= yl && y < yh)
  339.    {
  340.      col = x / tile_width;
  341.      row = y / tile_height;
  342.      if (col != old_col || row != old_row)
  343.        {
  344.      gimp_tile_unref (tile, FALSE);
  345.      tile = gimp_drawable_get_tile (drawable, FALSE, row, col);
  346.      gimp_tile_ref (tile);
  347.      old_col = col;
  348.      old_row = row;
  349.        }
  350.      data =
  351.        tile->data +
  352.        (tile->ewidth * (y % tile_height) +
  353.     x % tile_width) * image_bpp;
  354.      for (i = 0; i < image_bpp; i++)
  355.        *pixel++ = *data++;
  356.    }
  357.  else
  358.    {
  359.      pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
  360.    }
  361. }
  362.  
  363. static void
  364. iwarp_get_deform_vector (gdouble  x,
  365.              gdouble  y,
  366.              gdouble *xv,
  367.              gdouble *yv)
  368. {
  369.   gint    i, xi, yi;
  370.   gdouble dx, dy, my0, my1, mx0, mx1;
  371.  
  372.   if (x >= 0 && x < (preview_width - 1) && y >= 0  && y < (preview_height - 1))
  373.     { 
  374.       xi = (gint) x;
  375.       yi = (gint) y;
  376.       dx = x-xi;
  377.       dy = y-yi;
  378.       i = (yi * preview_width + xi);
  379.       mx0 =
  380.     deform_vectors[i].x +
  381.     (deform_vectors[i+1].x -
  382.      deform_vectors[i].x) * dx;
  383.       mx1 =
  384.     deform_vectors[i+preview_width].x +
  385.     (deform_vectors[i+preview_width+1].x -
  386.      deform_vectors[i+preview_width].x) * dx;
  387.       my0 =
  388.     deform_vectors[i].y +
  389.     dx * (deform_vectors[i+1].y -
  390.           deform_vectors[i].y);
  391.       my1 =
  392.     deform_vectors[i+preview_width].y +
  393.     dx * (deform_vectors[i+preview_width+1].y -
  394.           deform_vectors[i+preview_width].y);
  395.       *xv = mx0 + dy * (mx1 - mx0);
  396.       *yv = my0 + dy * (my1 - my0); 
  397.     }
  398.   else
  399.     {
  400.       *xv = *yv = 0.0; 
  401.     }
  402. }
  403.  
  404. static void
  405. iwarp_get_point (gdouble  x,
  406.          gdouble  y,
  407.          guchar  *color)
  408. {
  409.   gdouble dx, dy, m0, m1;
  410.   guchar  p0[4], p1[4], p2[4], p3[4]; 
  411.   gint    xi, yi, i;
  412.   
  413.   xi = (gint) x;
  414.   yi = (gint) y;
  415.   dx = x - xi;
  416.   dy = y - yi; 
  417.   iwarp_get_pixel (xi, yi, p0);
  418.   iwarp_get_pixel (xi + 1, yi, p1);
  419.   iwarp_get_pixel (xi, yi + 1, p2);
  420.   iwarp_get_pixel (xi + 1, yi + 1, p3);              
  421.   for (i = 0; i < image_bpp; i++)
  422.     {
  423.       m0 = p0[i] + dx * (p1[i] - p0[i]);
  424.       m1 = p2[i] + dx * (p3[i] - p2[i]);
  425.       color[i] = (guchar) (m0 + dy * (m1 - m0));
  426.     }
  427.  
  428. static gboolean
  429. iwarp_supersample_test (GimpVector2 *v0,
  430.             GimpVector2 *v1,
  431.             GimpVector2 *v2,
  432.             GimpVector2 *v3)
  433. {
  434.   gdouble dx, dy;
  435.  
  436.   dx = 1.0+v1->x - v0->x;
  437.   dy = v1->y - v0->y;
  438.   if (dx * dx + dy * dy > supersample_threshold_2)
  439.     return TRUE;
  440.  
  441.   dx = 1.0+v2->x - v3->x;
  442.   dy = v2->y - v3->y;
  443.   if (dx*dx+dy*dy > supersample_threshold_2) 
  444.     return TRUE;
  445.  
  446.   dx = v2->x - v0->x;
  447.   dy = 1.0+v2->y - v0->y;
  448.   if (dx*dx+dy*dy > supersample_threshold_2) 
  449.     return TRUE;
  450.  
  451.   dx = v3->x - v1->x;
  452.   dy = 1.0+v3->y - v1->y;
  453.   if (dx*dx+dy*dy > supersample_threshold_2) 
  454.     return TRUE; 
  455.  
  456.   return FALSE;
  457. }
  458.  
  459. static void
  460. iwarp_getsample (GimpVector2  v0,
  461.          GimpVector2  v1,
  462.          GimpVector2  v2,
  463.          GimpVector2  v3, 
  464.          gdouble      x,
  465.          gdouble      y,
  466.          gint        *sample,
  467.          gint        *cc,
  468.          gint         depth,
  469.          gdouble      scale)
  470. {
  471.   gint        i;
  472.   gdouble     xv, yv;
  473.   GimpVector2 v01, v13, v23, v02, vm;
  474.   guchar      c[4];
  475.  
  476.   if ((depth >= iwarp_vals.max_supersample_depth) ||
  477.       (!iwarp_supersample_test (&v0, &v1, &v2, &v3)))
  478.     {
  479.       iwarp_get_deform_vector (img2pre * (x - xl),
  480.                    img2pre * (y - yl),
  481.                    &xv, &yv);
  482.       xv *= animate_deform_value;
  483.       yv *= animate_deform_value;
  484.       iwarp_get_point (pre2img * xv + x, pre2img * yv + y, c);
  485.       for (i = 0;  i < image_bpp; i++)
  486.     sample[i] += c[i];
  487.       (*cc)++;
  488.     }
  489.  else
  490.    {
  491.      scale *= 0.5;
  492.      iwarp_get_deform_vector (img2pre * (x - xl),
  493.                   img2pre * (y - yl),
  494.                   &xv, &yv);
  495.      xv *= animate_deform_value;
  496.      yv *= animate_deform_value;
  497.      iwarp_get_point (pre2img * xv + x, pre2img * yv + y, c);
  498.      for (i = 0;  i < image_bpp; i++)
  499.        sample[i] += c[i];
  500.      (*cc)++;
  501.      vm.x = xv;
  502.      vm.y = yv;
  503.  
  504.      iwarp_get_deform_vector (img2pre * (x - xl),
  505.                   img2pre * (y - yl - scale),
  506.                   &xv, &yv);
  507.      xv *= animate_deform_value;
  508.      yv *= animate_deform_value;
  509.      v01.x = xv;
  510.      v01.y = yv;
  511.   
  512.      iwarp_get_deform_vector (img2pre * (x - xl + scale),
  513.                   img2pre * (y - yl),
  514.                   &xv, &yv);
  515.      xv *= animate_deform_value;
  516.      yv *= animate_deform_value;
  517.      v13.x = xv;
  518.      v13.y = yv;
  519.  
  520.      iwarp_get_deform_vector (img2pre * (x - xl),
  521.                   img2pre * (y - yl + scale),
  522.                   &xv, &yv);
  523.      xv *= animate_deform_value;
  524.      yv *= animate_deform_value;
  525.      v23.x = xv;
  526.      v23.y = yv;
  527.  
  528.      iwarp_get_deform_vector (img2pre * (x - xl - scale),
  529.                   img2pre * (y - yl),
  530.                   &xv, &yv);
  531.      xv *= animate_deform_value;
  532.      yv *= animate_deform_value;
  533.      v02.x = xv;
  534.      v02.y = yv;
  535.  
  536.      iwarp_getsample (v0, v01, vm, v02,
  537.               x-scale, y-scale,
  538.               sample, cc, depth + 1,
  539.               scale);
  540.      iwarp_getsample (v01, v1, v13, vm,
  541.               x + scale, y - scale,
  542.               sample, cc, depth + 1,
  543.               scale);
  544.      iwarp_getsample (v02, vm, v23, v2,
  545.               x - scale, y + scale,
  546.               sample, cc, depth + 1,
  547.               scale);
  548.      iwarp_getsample (vm, v13, v3, v23,
  549.               x + scale, y + scale,
  550.               sample, cc, depth + 1,
  551.               scale);
  552.    }
  553. }
  554.  
  555. static void
  556. iwarp_supersample (gint    sxl,
  557.            gint    syl,
  558.            gint    sxr,
  559.            gint    syr,
  560.            guchar *dest_data,
  561.            gint    stride,
  562.            gint   *progress,
  563.            gint    max_progress)
  564. {
  565.   gint         i, wx, wy, col, row, cc;
  566.   GimpVector2 *srow, *srow_old, *vh;
  567.   gdouble      xv, yv;
  568.   gint         color[4];
  569.   guchar      *dest;
  570.  
  571.   wx = sxr - sxl + 1;
  572.   wy = syr - syl + 1;
  573.   srow     = g_new (GimpVector2, sxr - sxl + 1);
  574.   srow_old = g_new (GimpVector2, sxr - sxl + 1);
  575.  
  576.   for (i = sxl; i < (sxr + 1); i++)
  577.     {
  578.       iwarp_get_deform_vector (img2pre * (-0.5 + i - xl),
  579.                    img2pre * (-0.5 + syl - yl),
  580.                    &xv, &yv);
  581.       xv *= animate_deform_value;
  582.       yv *= animate_deform_value;
  583.       srow_old[i-sxl].x = xv;
  584.       srow_old[i-sxl].y = yv;
  585.     }
  586.  
  587.   for (col = syl; col < syr; col++)
  588.     {
  589.       iwarp_get_deform_vector (img2pre * (-0.5 + sxl - xl),
  590.                    img2pre * (0.5 + col - yl),
  591.                    &xv, &yv);
  592.       xv *= animate_deform_value;
  593.       yv *= animate_deform_value;
  594.       srow[0].x = xv;
  595.       srow[0].y = yv; 
  596.       for (row = sxl; row <sxr; row++)
  597.     {
  598.       iwarp_get_deform_vector (img2pre * (0.5 + row - xl),
  599.                    img2pre * (0.5 + col - yl),
  600.                    &xv, &yv);
  601.       xv *= animate_deform_value;
  602.       yv *= animate_deform_value;
  603.       srow[row-sxl+1].x = xv;
  604.       srow[row-sxl+1].y = yv;
  605.       cc = 0;
  606.       color[0] = color[1] = color[2] = color[3] = 0;
  607.       iwarp_getsample (srow_old[row-sxl], srow_old[row-sxl+1],
  608.                srow[row-sxl], srow[row-sxl+1],
  609.                row, col, color, &cc, 0, 1.0);
  610.       if (layer_alpha)
  611.         dest = dest_data + (col-syl) * (stride) + (row-sxl) * (image_bpp+1);
  612.       else 
  613.         dest = dest_data + (col-syl) * stride + (row-sxl) * image_bpp;
  614.       for (i = 0; i < image_bpp; i++)
  615.         *dest++ = color[i] / cc;
  616.       if (layer_alpha)
  617.         *dest++ = 255; 
  618.       (*progress)++;
  619.     }
  620.  
  621.       gimp_progress_update ((gdouble) (*progress) / max_progress);
  622.       vh = srow_old;
  623.       srow_old = srow;
  624.       srow = vh;   
  625.     }
  626.  
  627.   g_free (srow);
  628.   g_free (srow_old);
  629. }
  630.  
  631. static void
  632. iwarp_frame (void)
  633. {
  634.   GimpPixelRgn  dest_rgn;
  635.   gpointer   pr;
  636.   guchar    *dest_row, *dest;
  637.   gint       row, col;
  638.   gint       i;
  639.   gint       progress, max_progress;
  640.   guchar     color[4];
  641.   gdouble    xv, yv;
  642.  
  643.   progress = 0;
  644.   max_progress = (yh-yl)*(xh-xl);
  645.  
  646.   gimp_pixel_rgn_init (&dest_rgn, destdrawable,
  647.                xl, yl, xh-xl, yh-yl, TRUE, TRUE);
  648.  
  649.   if (!do_animate)
  650.     gimp_progress_init (_("Warping..."));
  651.  
  652.   for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
  653.        pr != NULL;
  654.        pr = gimp_pixel_rgns_process (pr))
  655.     {
  656.       dest_row = dest_rgn.data;
  657.       if (!iwarp_vals.do_supersample)
  658.     {
  659.       for (row = dest_rgn.y; row < (dest_rgn.y + dest_rgn.h); row++)
  660.         {
  661.           dest = dest_row;
  662.           for (col = dest_rgn.x; col < (dest_rgn.x + dest_rgn.w); col++)
  663.         {
  664.           progress++;
  665.           iwarp_get_deform_vector (img2pre * (col -xl),
  666.                        img2pre * (row -yl),
  667.                        &xv ,&yv);
  668.           xv *= animate_deform_value;
  669.           yv *= animate_deform_value;
  670.           if (fabs(xv) > 0.0 || fabs(yv) > 0.0)
  671.             {
  672.               iwarp_get_point (pre2img * xv + col,
  673.                        pre2img *yv + row,
  674.                        color);
  675.               for (i = 0; i < image_bpp; i++)
  676.             *dest++ = color[i];
  677.               if (layer_alpha)
  678.             *dest++ = 255;
  679.             }
  680.           else
  681.             {
  682.               iwarp_get_pixel (col, row, color);
  683.               for (i = 0; i < image_bpp; i++)
  684.             *dest++ = color[i];
  685.               if (layer_alpha)
  686.             *dest++ = 255;
  687.             }
  688.         }
  689.           dest_row += dest_rgn.rowstride;
  690.           gimp_progress_update ((gdouble) (progress) / max_progress);
  691.         }
  692.     }
  693.       else
  694.     {
  695.       supersample_threshold_2 =
  696.         iwarp_vals.supersample_threshold * iwarp_vals.supersample_threshold; 
  697.       iwarp_supersample (dest_rgn.x, dest_rgn.y,
  698.                  dest_rgn.x + dest_rgn.w, dest_rgn.y + dest_rgn.h,
  699.                  dest_rgn.data,
  700.                  dest_rgn.rowstride,
  701.                  &progress, max_progress);
  702.     } 
  703.     }
  704.  
  705.   gimp_drawable_flush (destdrawable);
  706.   gimp_drawable_merge_shadow (destdrawable->id, TRUE);
  707.   gimp_drawable_update (destdrawable->id, xl, yl, (xh - xl), (yh - yl));
  708. }
  709.  
  710. static void
  711. iwarp (void)
  712. {
  713.   gint     i;
  714.   gint32   layerID;
  715.   gint32  *animlayers;
  716.   gchar   *st;
  717.   gdouble  delta;
  718.  
  719.   if (animate_num_frames > 1 && do_animate)
  720.     {
  721.       animlayers = g_new (gint32, animate_num_frames);
  722.       if (do_animate_reverse)
  723.     {
  724.       animate_deform_value = 1.0;
  725.       delta = -1.0 / (animate_num_frames - 1);
  726.     }
  727.       else
  728.     {
  729.       animate_deform_value = 0.0;
  730.       delta = 1.0 / (animate_num_frames - 1);
  731.     }
  732.       layerID = gimp_image_get_active_layer (imageID);
  733.       if (image_bpp == 1 || image_bpp == 3)
  734.     layer_alpha = TRUE;
  735.       else
  736.     layer_alpha = FALSE;
  737.       frame_number = 0;
  738.       for (i = 0; i < animate_num_frames; i++)
  739.     {
  740.       st = g_strdup_printf (_("Frame %d"), i);
  741.       animlayers[i] = _gimp_layer_copy (layerID, TRUE);
  742.       gimp_layer_set_name (animlayers[i], st);
  743.       g_free (st);
  744.       destdrawable = gimp_drawable_get (animlayers[i]);
  745.       st = g_strdup_printf (_("Warping Frame Nr %d ..."), frame_number);
  746.       gimp_progress_init (st);
  747.       g_free (st);
  748.       if (animate_deform_value >0.0)
  749.         iwarp_frame ();
  750.       gimp_image_add_layer (imageID, animlayers[i], 0);
  751.       animate_deform_value = animate_deform_value + delta;
  752.       frame_number++;
  753.     }
  754.       if (do_animate_ping_pong)
  755.     {
  756.       st = g_strdup_printf (_("Warping Frame Nr %d ..."), frame_number);
  757.       gimp_progress_init (_("Ping Pong"));
  758.       g_free (st);
  759.       for (i = 0; i < animate_num_frames; i++)
  760.         {
  761.           gimp_progress_update ((gdouble) i / (animate_num_frames - 1));
  762.           layerID = _gimp_layer_copy (animlayers[animate_num_frames-i-1],
  763.                       TRUE); 
  764.           st = g_strdup_printf (_("Frame %d"), i + animate_num_frames);
  765.           gimp_layer_set_name (layerID, st);
  766.           g_free (st);
  767.           gimp_image_add_layer (imageID, layerID, 0); 
  768.         }
  769.     }
  770.       g_free (animlayers);
  771.     } 
  772.   else
  773.     {
  774.       animate_deform_value = 1.0;
  775.       iwarp_frame ();
  776.     }
  777.   if (tile != NULL)
  778.     {
  779.       gimp_tile_unref (tile, FALSE);
  780.       tile = NULL;
  781.     }
  782. }
  783.  
  784. static guchar
  785. iwarp_transparent_color (gint x,
  786.              gint y)
  787. {
  788.   if ((y % (GIMP_CHECK_SIZE * 4)) > (GIMP_CHECK_SIZE * 2))
  789.     {
  790.       if ((x % (GIMP_CHECK_SIZE * 4)) > (GIMP_CHECK_SIZE * 2))
  791.     return GIMP_CHECK_DARK * 255;
  792.       else
  793.     return GIMP_CHECK_LIGHT * 255;
  794.     }
  795.   else
  796.     {
  797.       if ((x % (GIMP_CHECK_SIZE * 4)) < (GIMP_CHECK_SIZE * 2))
  798.     return GIMP_CHECK_DARK * 255;
  799.       else
  800.     return GIMP_CHECK_LIGHT * 255;
  801.     }
  802. }
  803.  
  804. static void
  805. iwarp_cpy_images (void)
  806. {
  807.   gint     i, j, k, p;
  808.   gdouble  alpha;
  809.   guchar  *srccolor, *dstcolor;
  810.  
  811.   if (image_bpp == 1 || image_bpp ==3) 
  812.     {
  813.       memcpy (dstimage, srcimage, preview_width * preview_height * preview_bpp);
  814.     }
  815.   else
  816.     {
  817.       for (i = 0; i< preview_width; i++) 
  818.     for (j = 0; j< preview_height; j++)
  819.       {
  820.         p = (j * preview_width + i);
  821.         srccolor = srcimage + p * image_bpp;
  822.         alpha = (gdouble) srccolor[image_bpp-1] / 255;
  823.         dstcolor = dstimage + p * preview_bpp;
  824.         for (k = 0; k < preview_bpp; k++)
  825.           {
  826.         *dstcolor++ = (guchar)
  827.           (alpha *srccolor[k]+(1.0-alpha) *
  828.            iwarp_transparent_color (i,j));
  829.           }
  830.       }  
  831.     }
  832. }
  833.  
  834. static void
  835. iwarp_init (void)
  836. {
  837.   gint       y, x, xi, i;
  838.   GimpPixelRgn  srcrgn;
  839.   guchar    *pts;
  840.   guchar    *linebuffer = NULL;
  841.   gdouble    dx, dy;
  842.  
  843.   gimp_drawable_mask_bounds (drawable->id, &xl, &yl, &xh, &yh);
  844.   sel_width = xh-xl;
  845.   sel_height = yh-yl;
  846.   image_bpp = gimp_drawable_bpp (drawable->id);
  847.   if (gimp_drawable_is_layer (drawable->id))
  848.     preserve_trans = (gimp_layer_get_preserve_transparency (drawable->id));
  849.   else
  850.     preserve_trans = FALSE;
  851.   if (image_bpp < 3)
  852.     preview_bpp = 1;
  853.   else
  854.     preview_bpp = 3;
  855.   dx = (gdouble) sel_width / MAX_PREVIEW_WIDTH;
  856.   dy = (gdouble) sel_height / MAX_PREVIEW_HEIGHT;
  857.   if (dx >dy)
  858.     pre2img = dx;
  859.   else
  860.     pre2img = dy;
  861.   if (dx <=1.0 && dy <= 1.0)
  862.     pre2img = 1.0;  
  863.   img2pre = 1.0 / pre2img;
  864.   preview_width = (gint) (sel_width / pre2img);
  865.   preview_height = (gint) (sel_height / pre2img);
  866.   tile_width = gimp_tile_width ();
  867.   tile_height = gimp_tile_height ();
  868.  
  869.   srcimage = g_new (guchar, preview_width * preview_height * image_bpp);
  870.   dstimage = g_new (guchar, preview_width * preview_height * preview_bpp);
  871.   deform_vectors = g_new (GimpVector2, preview_width * preview_height);
  872.   deform_area_vectors = g_new (GimpVector2,
  873.                    (MAX_DEFORM_AREA_RADIUS * 2 + 1) *
  874.                    (MAX_DEFORM_AREA_RADIUS * 2 + 1));
  875.   linebuffer = g_new (guchar, sel_width * image_bpp);
  876.  
  877.   for (i = 0; i < preview_width * preview_height; i++) 
  878.     deform_vectors[i].x = deform_vectors[i].y = 0.0;
  879.  
  880.   gimp_pixel_rgn_init (&srcrgn, drawable,
  881.                xl, yl, sel_width, sel_height, FALSE, FALSE);
  882.  
  883.   for (y = 0; y < preview_height; y++)
  884.     {
  885.       gimp_pixel_rgn_get_row (&srcrgn, linebuffer,
  886.                   xl, (gint) (pre2img * y) + yl, sel_width);
  887.       for (x = 0; x < preview_width; x++)
  888.     {
  889.       pts = srcimage + (y * preview_width +x) * image_bpp;
  890.       xi = (gint) (pre2img * x);
  891.       for (i = 0; i < image_bpp; i++)
  892.         {
  893.           *pts++ = linebuffer[xi*image_bpp+i];
  894.         }
  895.     }
  896.     }
  897.   iwarp_cpy_images ();
  898.   for (i = 0; i < MAX_DEFORM_AREA_RADIUS; i++)
  899.     {
  900.       filter[i] = 
  901.     pow ((cos (sqrt((gdouble) i / MAX_DEFORM_AREA_RADIUS) * G_PI) + 1) *
  902.          0.5, 0.7); /*0.7*/
  903.     }
  904.   g_free (linebuffer);
  905. }
  906.  
  907. static void
  908. iwarp_animate_dialog (GtkWidget *dlg,
  909.               GtkWidget *notebook)
  910.   GtkWidget *vbox;
  911.   GtkWidget *frame;
  912.   GtkWidget *table;
  913.   GtkWidget *button;
  914.   GtkObject *scale_data;
  915.  
  916.   vbox = gtk_vbox_new (FALSE, 4);
  917.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
  918.  
  919.   button = gtk_check_button_new_with_label (_("Animate"));
  920.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  921.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), do_animate);
  922.   gtk_signal_connect (GTK_OBJECT (button), "toggled",
  923.                       GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  924.                       &do_animate);
  925.   gtk_widget_show (button);
  926.  
  927.   frame = gtk_frame_new (NULL);
  928.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  929.   gtk_widget_show (frame);
  930.  
  931.   gtk_object_set_data (GTK_OBJECT (button), "set_sensitive", frame);
  932.   gtk_widget_set_sensitive (frame, do_animate);
  933.  
  934.   table = gtk_table_new (3, 3, FALSE);
  935.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  936.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  937.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  938.   gtk_container_add (GTK_CONTAINER (frame), table);
  939.   gtk_widget_show (table);
  940.  
  941.   scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  942.                      _("Number of Frames:"), SCALE_WIDTH, 0,
  943.                      animate_num_frames,
  944.                      2, MAX_NUM_FRAMES, 1.0, 10.0, 1,
  945.                      TRUE, 0, 0,
  946.                      NULL, NULL);
  947.   gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
  948.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  949.               &animate_num_frames);
  950.  
  951.   button = gtk_check_button_new_with_label (_("Reverse"));
  952.   gtk_table_attach (GTK_TABLE (table), button, 0, 3, 1, 2,
  953.             GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); 
  954.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  955.                       GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  956.                       &do_animate_reverse);
  957.   gtk_widget_show (button);
  958.  
  959.   button = gtk_check_button_new_with_label (_("Ping Pong"));
  960.   gtk_table_attach (GTK_TABLE (table), button, 0, 3, 2, 3,
  961.             GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); 
  962.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  963.                       GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  964.                       &do_animate_ping_pong);
  965.   gtk_widget_show (button);
  966.  
  967.   gtk_widget_show (vbox);
  968.  
  969.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
  970.                 vbox,
  971.                 gtk_label_new (_("Animate")));
  972. }
  973.  
  974. static void
  975. iwarp_settings_dialog (GtkWidget *dlg,
  976.                GtkWidget *notebook)
  977. {
  978.   GtkWidget *vbox;
  979.   GtkWidget *vbox2;
  980.   GtkWidget *vbox3;
  981.   GtkWidget *hbox;
  982.   GtkWidget *frame;
  983.   GtkWidget *button;
  984.   GtkWidget *table;
  985.   GtkObject *scale_data;
  986.   GtkWidget *widget[3];
  987.   gint       i;
  988.  
  989.   vbox = gtk_vbox_new (FALSE, 4);
  990.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
  991.  
  992.   table = gtk_table_new (2, 3, FALSE);
  993.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  994.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  995.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  996.   gtk_widget_show (table);
  997.  
  998.   scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  999.                      _("Deform Radius:"), SCALE_WIDTH, 0,
  1000.                      iwarp_vals.deform_area_radius,
  1001.                      5.0, MAX_DEFORM_AREA_RADIUS, 1.0, 10.0, 0,
  1002.                      TRUE, 0, 0,
  1003.                      NULL, NULL);
  1004.   gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
  1005.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  1006.               &iwarp_vals.deform_area_radius);
  1007.  
  1008.   scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
  1009.                      _("Deform Amount:"), SCALE_WIDTH, 0,
  1010.                      iwarp_vals.deform_amount,
  1011.                      0.0, 1.0, 0.01, 0.1, 2,
  1012.                      TRUE, 0, 0,
  1013.                      NULL, NULL);
  1014.   gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
  1015.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1016.               &iwarp_vals.deform_amount);
  1017.  
  1018.   frame = gtk_frame_new (_("Deform Mode"));
  1019.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  1020.   gtk_widget_show (frame);
  1021.  
  1022.   hbox = gtk_hbox_new (TRUE, 4);
  1023.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
  1024.   gtk_container_add (GTK_CONTAINER (frame), hbox);
  1025.   gtk_widget_show (hbox);
  1026.  
  1027.   vbox2 = gimp_radio_group_new2 (FALSE, NULL,
  1028.                  gimp_radio_button_update,
  1029.                  &iwarp_vals.deform_mode,
  1030.                  (gpointer) iwarp_vals.deform_mode,
  1031.  
  1032.                  _("Move"),      (gpointer) MOVE, NULL,
  1033.                  _("Grow"),      (gpointer) GROW, NULL,
  1034.                  _("Swirl CCW"), (gpointer) SWIRL_CCW, NULL,
  1035.                  _("Remove"),    (gpointer) REMOVE, &widget[0],
  1036.                  _("Shrink"),    (gpointer) SHRINK, &widget[1],
  1037.                  _("Swirl CW"),  (gpointer) SWIRL_CW, &widget[2],
  1038.  
  1039.                  NULL);
  1040.   gtk_container_add (GTK_CONTAINER (hbox), vbox2);
  1041.   gtk_widget_show (vbox2);
  1042.  
  1043.   vbox3 = gtk_vbox_new (FALSE, 1);
  1044.   gtk_container_add (GTK_CONTAINER (hbox), vbox3);
  1045.   gtk_widget_show (vbox3);
  1046.  
  1047.   for (i = 0; i < 3; i++)
  1048.     {
  1049.       gtk_object_ref (GTK_OBJECT (widget[i]));
  1050.       gtk_widget_hide (widget[i]);
  1051.       gtk_container_remove (GTK_CONTAINER (vbox2), widget[i]);
  1052.       gtk_box_pack_start (GTK_BOX (vbox3), widget[i],
  1053.                           FALSE, FALSE, 0);
  1054.       gtk_widget_show (widget[i]);
  1055.       gtk_object_unref (GTK_OBJECT (widget[i]));
  1056.     }
  1057.  
  1058.   button = gtk_check_button_new_with_label (_("Bilinear"));
  1059.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
  1060.                 iwarp_vals.do_bilinear);
  1061.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  1062.   gtk_signal_connect (GTK_OBJECT (button), "toggled",
  1063.                       GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  1064.                       &iwarp_vals.do_bilinear);
  1065.   gtk_widget_show(button);
  1066.  
  1067.   frame = gtk_frame_new (NULL);
  1068.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  1069.   gtk_widget_show (frame);
  1070.  
  1071.   vbox2 = gtk_vbox_new (FALSE, 4);
  1072.   gtk_container_set_border_width (GTK_CONTAINER (vbox2), 4);
  1073.   gtk_container_add (GTK_CONTAINER (frame), vbox2);
  1074.   gtk_widget_show (vbox2);
  1075.  
  1076.   button = gtk_check_button_new_with_label (_("Adaptive Supersample"));
  1077.   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
  1078.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
  1079.                 iwarp_vals.do_supersample);
  1080.   gtk_signal_connect (GTK_OBJECT (button), "toggled",
  1081.                       GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  1082.                       &iwarp_vals.do_supersample);
  1083.   gtk_widget_show (button);
  1084.  
  1085.   table = gtk_table_new (2, 3, FALSE);
  1086.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  1087.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  1088.   gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, FALSE, 0);
  1089.   gtk_widget_show (table);
  1090.  
  1091.   gtk_object_set_data (GTK_OBJECT (button), "set_sensitive", table);
  1092.   gtk_widget_set_sensitive (table, iwarp_vals.do_supersample);
  1093.  
  1094.   scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  1095.                      _("Max Depth:"), SCALE_WIDTH, 0,
  1096.                      iwarp_vals.max_supersample_depth,
  1097.                      1.0, 5.0, 1.1, 1.0, 0,
  1098.                      TRUE, 0, 0,
  1099.                      NULL, NULL);
  1100.   gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
  1101.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  1102.               &iwarp_vals.max_supersample_depth);
  1103.  
  1104.   scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
  1105.                      _("Threshold:"), SCALE_WIDTH, 0,
  1106.                      iwarp_vals.supersample_threshold,
  1107.                      1.0, 10.0, 0.01, 0.1, 2,
  1108.                      TRUE, 0, 0,
  1109.                      NULL, NULL);
  1110.   gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
  1111.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1112.               &iwarp_vals.supersample_threshold);
  1113.  
  1114.   gtk_widget_show (vbox);
  1115.  
  1116.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
  1117.                 vbox,
  1118.                 gtk_label_new (_("Settings")));
  1119. }
  1120.  
  1121. static gboolean
  1122. iwarp_dialog (void)
  1123. {
  1124.   GtkWidget *dlg;
  1125.   GtkWidget *main_hbox;
  1126.   GtkWidget *frame;
  1127.   GtkWidget *abox;
  1128.   GtkWidget *pframe;
  1129.   GtkWidget *notebook;
  1130.  
  1131.   gimp_ui_init ("iwarp", TRUE);
  1132.  
  1133.   iwarp_init ();
  1134.  
  1135.   dlg = gimp_dialog_new (_("IWarp"), "iwarp",
  1136.              gimp_standard_help_func, "filters/iwarp.html",
  1137.              GTK_WIN_POS_MOUSE,
  1138.              FALSE, TRUE, FALSE,
  1139.  
  1140.              _("OK"), iwarp_ok_callback,
  1141.              NULL, NULL, NULL, TRUE, FALSE,
  1142.              _("Reset"), iwarp_reset_callback,
  1143.              NULL, NULL, NULL, FALSE, FALSE,
  1144.              _("Cancel"), gtk_widget_destroy,
  1145.              NULL, 1, NULL, FALSE, TRUE,
  1146.  
  1147.              NULL);
  1148.  
  1149.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  1150.               GTK_SIGNAL_FUNC (gtk_main_quit),
  1151.               NULL);
  1152.  
  1153.   main_hbox = gtk_hbox_new (FALSE, 6);
  1154.   gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 6);
  1155.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), main_hbox,
  1156.               FALSE, FALSE, 0);
  1157.  
  1158.   frame = gtk_frame_new (_("Preview"));
  1159.   gtk_box_pack_start (GTK_BOX (main_hbox), frame, FALSE, FALSE, 0);
  1160.   gtk_widget_show (frame);
  1161.  
  1162.   abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  1163.   gtk_container_set_border_width (GTK_CONTAINER (abox), 4);
  1164.   gtk_container_add (GTK_CONTAINER (frame), abox);
  1165.   gtk_widget_show (abox);
  1166.  
  1167.   pframe = gtk_frame_new (NULL);
  1168.   gtk_frame_set_shadow_type (GTK_FRAME (pframe), GTK_SHADOW_IN);
  1169.   gtk_container_add (GTK_CONTAINER (abox), pframe);
  1170.   gtk_widget_show (pframe); 
  1171.  
  1172.   if (preview_bpp == 3)
  1173.     preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  1174.   else
  1175.     preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
  1176.   gtk_preview_size (GTK_PREVIEW (preview), preview_width, preview_height);
  1177.   iwarp_update_preview (0, 0, preview_width, preview_height);
  1178.   gtk_container_add (GTK_CONTAINER (pframe), preview);
  1179.   gtk_widget_show (preview);
  1180.  
  1181.   gtk_widget_set_events (preview,
  1182.              GDK_BUTTON_PRESS_MASK |
  1183.              GDK_BUTTON_RELEASE_MASK |
  1184.              GDK_BUTTON1_MOTION_MASK | 
  1185.              GDK_POINTER_MOTION_HINT_MASK);
  1186.   gtk_signal_connect (GTK_OBJECT(preview), "event",
  1187.               GTK_SIGNAL_FUNC (iwarp_motion_callback),
  1188.               NULL);
  1189.  
  1190.   notebook = gtk_notebook_new ();
  1191.   gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
  1192.   gtk_box_pack_start (GTK_BOX (main_hbox), notebook, TRUE, TRUE, 0);
  1193.  
  1194.   iwarp_settings_dialog (dlg, notebook);
  1195.   iwarp_animate_dialog (dlg, notebook);
  1196.  
  1197.   gtk_widget_show (notebook);
  1198.  
  1199.   gtk_widget_show (main_hbox);
  1200.   gtk_widget_show (dlg);
  1201.  
  1202.   gtk_main ();
  1203.   gdk_flush ();
  1204.  
  1205.   return wint.run;   
  1206. }
  1207.  
  1208. static void 
  1209. iwarp_update_preview (gint x0,
  1210.               gint y0,
  1211.               gint x1,
  1212.               gint y1)
  1213. {
  1214.   gint i;
  1215.   GdkRectangle rect;
  1216.  
  1217.   if (x0 < 0)
  1218.     x0 = 0;
  1219.   if (y0 < 0)
  1220.     y0 = 0;
  1221.   if (x1 >= preview_width)
  1222.     x1 = preview_width;
  1223.   if (y1 >= preview_height)
  1224.     y1 = preview_height;
  1225.   for (i = y0; i < y1; i++)
  1226.     gtk_preview_draw_row (GTK_PREVIEW (preview),
  1227.               dstimage + (i * preview_width + x0) * preview_bpp,
  1228.               x0, i,x1-x0);
  1229.   rect.x = x0;
  1230.   rect.y = y0;
  1231.   rect.width = x1-x0;
  1232.   rect.height = y1-y0;  
  1233.   gtk_widget_draw (preview, &rect);
  1234.   gdk_flush ();
  1235. }
  1236.  
  1237. static void
  1238. iwarp_preview_get_pixel (gint     x,
  1239.              gint     y,
  1240.              guchar **color)
  1241. {
  1242.   static guchar black[4] = { 0, 0, 0, 0 };
  1243.  
  1244.   if (x < 0 || x >= preview_width || y<0 || y >= preview_height)
  1245.     { 
  1246.       *color = black;
  1247.       return;
  1248.     }
  1249.   *color = srcimage + (y * preview_width + x) * image_bpp; 
  1250.  
  1251. static void
  1252. iwarp_preview_get_point (gdouble  x,
  1253.              gdouble  y,
  1254.              guchar  *color)
  1255. {
  1256.   gint     xi, yi, j;
  1257.   gdouble  dx, dy, m0, m1;
  1258.   guchar  *p0, *p1, *p2, *p3;
  1259.  
  1260.   xi = (gint) x;
  1261.   yi = (gint) y;
  1262.   if (iwarp_vals.do_bilinear)
  1263.     {
  1264.       dx = x-xi;
  1265.       dy = y-yi; 
  1266.       iwarp_preview_get_pixel (xi, yi, &p0);
  1267.       iwarp_preview_get_pixel (xi + 1, yi, &p1);
  1268.       iwarp_preview_get_pixel (xi, yi + 1, &p2);
  1269.       iwarp_preview_get_pixel (xi + 1, yi + 1, &p3);
  1270.       for (j = 0; j < image_bpp; j++)
  1271.     {
  1272.       m0 = p0[j] + dx * (p1[j] - p0[j]);
  1273.       m1 = p2[j] + dx * (p3[j] - p2[j]);
  1274.       color[j] = (guchar) (m0 + dy * (m1 - m0));  
  1275.     }
  1276.     }
  1277.   else
  1278.     {
  1279.       iwarp_preview_get_pixel (xi, yi, &p0);
  1280.       for (j = 0; j < image_bpp; j++)
  1281.     color[j] = p0[j];
  1282.     }
  1283. }
  1284.  
  1285. static void 
  1286. iwarp_deform (gint    x,
  1287.           int     y,
  1288.           gdouble vx,
  1289.           gdouble vy)
  1290. {
  1291.   gint    xi, yi, ptr, fptr, x0, x1, y0, y1, radius2, length2;
  1292.   gdouble deform_value, xn, yn, nvx=0, nvy=0, emh, em, edge_width, xv, yv, alpha;
  1293.   guchar  color[4];
  1294.  
  1295.   if (x - iwarp_vals.deform_area_radius <0)
  1296.     x0 = -x;
  1297.   else
  1298.     x0 = -iwarp_vals.deform_area_radius;
  1299.  
  1300.   if (x + iwarp_vals.deform_area_radius >= preview_width)
  1301.     x1 = preview_width - x - 1;
  1302.   else
  1303.     x1 = iwarp_vals.deform_area_radius;
  1304.  
  1305.   if (y - iwarp_vals.deform_area_radius < 0)
  1306.     y0 = -y;
  1307.   else
  1308.     y0 = -iwarp_vals.deform_area_radius;
  1309.  
  1310.   if (y + iwarp_vals.deform_area_radius >= preview_height)
  1311.     y1 = preview_height-y-1;
  1312.   else
  1313.     y1 = iwarp_vals.deform_area_radius;
  1314.  
  1315.   radius2 = iwarp_vals.deform_area_radius * iwarp_vals.deform_area_radius;
  1316.  
  1317.   for (yi = y0; yi <= y1; yi++)
  1318.     for (xi = x0; xi <= x1; xi++)
  1319.       {
  1320.     length2 = (xi * xi + yi * yi) * MAX_DEFORM_AREA_RADIUS / radius2;
  1321.     if (length2 < MAX_DEFORM_AREA_RADIUS)
  1322.       {
  1323.         ptr = (y + yi) * preview_width + x + xi;   
  1324.         fptr =
  1325.           (yi + iwarp_vals.deform_area_radius) *
  1326.           (iwarp_vals.deform_area_radius * 2 + 1) +
  1327.           xi +
  1328.           iwarp_vals.deform_area_radius;
  1329.  
  1330.         switch (iwarp_vals.deform_mode)
  1331.           {
  1332.           case GROW:
  1333.         deform_value = filter[length2] *  0.1* iwarp_vals.deform_amount;
  1334.         nvx = -deform_value * xi;
  1335.         nvy = -deform_value * yi;
  1336.         break;
  1337.  
  1338.           case SHRINK:
  1339.         deform_value = filter[length2] * 0.1* iwarp_vals.deform_amount;
  1340.         nvx = deform_value * xi;
  1341.         nvy = deform_value * yi;
  1342.         break;
  1343.  
  1344.           case SWIRL_CW:
  1345.         deform_value = filter[length2] * iwarp_vals.deform_amount * 0.5;
  1346.         nvx =  deform_value * yi;
  1347.         nvy = -deform_value * xi;
  1348.         break;
  1349.  
  1350.           case SWIRL_CCW:
  1351.         deform_value = filter[length2] *iwarp_vals.deform_amount * 0.5;
  1352.         nvx = -deform_value * yi;
  1353.         nvy =  deform_value  * xi;
  1354.         break;
  1355.  
  1356.           case MOVE:
  1357.         deform_value = filter[length2] * iwarp_vals.deform_amount;
  1358.         nvx = deform_value * vx;
  1359.         nvy = deform_value * vy;
  1360.         break;
  1361.  
  1362.           default:
  1363.         break;
  1364.           }
  1365.  
  1366.         if (iwarp_vals.deform_mode == REMOVE)
  1367.           {
  1368.         deform_value =
  1369.           1.0 - 0.5 * iwarp_vals.deform_amount * filter[length2];
  1370.         deform_area_vectors[fptr].x =
  1371.           deform_value * deform_vectors[ptr].x ;
  1372.         deform_area_vectors[fptr].y =
  1373.           deform_value * deform_vectors[ptr].y ;
  1374.           } 
  1375.         else
  1376.           {
  1377.         edge_width = 0.2 *  iwarp_vals.deform_area_radius;
  1378.         emh = em = 1.0;
  1379.         if (x+xi < edge_width)
  1380.           em = (gdouble) (x + xi) / edge_width;
  1381.         if (y + yi < edge_width)
  1382.           emh = (gdouble) (y + yi) / edge_width;
  1383.         if (emh <em)
  1384.           em = emh;
  1385.         if (preview_width - x - xi - 1 < edge_width)
  1386.           emh = (gdouble) (preview_width - x - xi - 1) / edge_width;
  1387.         if (emh < em)
  1388.           em = emh;
  1389.         if (preview_height-y-yi-1 < edge_width)
  1390.           emh = (gdouble) (preview_height - y - yi - 1) / edge_width;
  1391.         if (emh <em)
  1392.           em = emh;
  1393.  
  1394.         nvx = nvx * em;
  1395.         nvy = nvy * em;
  1396.  
  1397.         iwarp_get_deform_vector (nvx + x+ xi, nvy + y + yi, &xv, &yv);
  1398.         xv = nvx +xv;
  1399.         if (xv +x+xi <0.0)
  1400.           xv = -x - xi;
  1401.         else if (xv + x +xi > (preview_width-1))
  1402.           xv = preview_width - x -xi-1;
  1403.         yv = nvy +yv;
  1404.         if (yv + y + yi < 0.0)
  1405.           yv = -y - yi;
  1406.         else if (yv + y + yi > (preview_height-1))
  1407.           yv = preview_height - y -yi - 1;
  1408.         deform_area_vectors[fptr].x = xv;
  1409.         deform_area_vectors[fptr].y = yv;
  1410.           }
  1411.  
  1412.         xn = deform_area_vectors[fptr].x + x + xi;
  1413.         yn = deform_area_vectors[fptr].y + y + yi;
  1414.  
  1415.         /* gcc - shut up! */
  1416.         alpha = 1;
  1417.  
  1418.         /* Yeah, it is ugly but since color is a pointer into image-data
  1419.          * I must not change color[image_bpp - 1]  ...
  1420.          */
  1421.         if (preserve_trans && (image_bpp == 4 || image_bpp == 2))
  1422.           {
  1423.         iwarp_preview_get_point (x + xi, y + yi, color);
  1424.         alpha = (gdouble) color[image_bpp - 1] / 255;
  1425.           }
  1426.  
  1427.         iwarp_preview_get_point (xn, yn, color);
  1428.  
  1429.         if (!preserve_trans && (image_bpp == 4 || image_bpp == 2))
  1430.           {
  1431.         alpha = (gdouble) color[image_bpp - 1] / 255;
  1432.           }
  1433.  
  1434.         if (preview_bpp == 3)
  1435.           {
  1436.         if (image_bpp == 4)
  1437.           {
  1438.             dstimage[ptr*3] =
  1439.               (guchar) (alpha * color[0] +
  1440.                 (1.0 - alpha) *
  1441.                 iwarp_transparent_color (x + xi, y + yi));
  1442.             dstimage[ptr*3+1] =
  1443.               (guchar) (alpha * color[1] +
  1444.                 (1.0 - alpha) *
  1445.                 iwarp_transparent_color (x + xi, y + yi));
  1446.             dstimage[ptr*3+2] =
  1447.               (guchar) (alpha * color[2] +
  1448.                 (1.0 - alpha) *
  1449.                 iwarp_transparent_color (x + xi, y + yi));
  1450.           }
  1451.         else
  1452.           {
  1453.             dstimage[ptr*3] = color[0];
  1454.             dstimage[ptr*3+1] = color[1];
  1455.             dstimage[ptr*3+2] = color[2];
  1456.           }
  1457.           }
  1458.         else
  1459.           {
  1460.         if (image_bpp == 2)
  1461.           {
  1462.             dstimage[ptr] =
  1463.               (guchar) (alpha * color[0] +
  1464.                 (1.0 - alpha) *
  1465.                 iwarp_transparent_color (x + xi, y + yi)) ;
  1466.           }
  1467.         else
  1468.           {
  1469.             dstimage[ptr] = color[0];
  1470.           }
  1471.           }
  1472.       }
  1473.       }
  1474.  
  1475.   for (yi = y0; yi <= y1; yi++)
  1476.     for (xi = x0; xi <= x1; xi++)
  1477.       {
  1478.     length2 = (xi*xi+yi*yi) * MAX_DEFORM_AREA_RADIUS / radius2;
  1479.     if (length2 <MAX_DEFORM_AREA_RADIUS)
  1480.       {
  1481.         ptr = (yi +y) * preview_width + xi +x;
  1482.         fptr =
  1483.           (yi+iwarp_vals.deform_area_radius) *
  1484.           (iwarp_vals.deform_area_radius*2+1) +
  1485.           xi +
  1486.           iwarp_vals.deform_area_radius;
  1487.         deform_vectors[ptr].x = deform_area_vectors[fptr].x;
  1488.         deform_vectors[ptr].y = deform_area_vectors[fptr].y;
  1489.       }
  1490.       }
  1491.  
  1492.   iwarp_update_preview (x + x0, y + y0, x + x1 + 1, y + y1 + 1);   
  1493.  
  1494. static void
  1495. iwarp_move (gint x,
  1496.         gint y,
  1497.         gint xx,
  1498.         gint yy)
  1499. {
  1500.   gdouble l, dx, dy, xf, yf;
  1501.   gint    num, i, x0, y0; 
  1502.  
  1503.   dx = x-xx;
  1504.   dy = y-yy;
  1505.   l= sqrt (dx * dx + dy * dy);
  1506.   num = (gint) (l * 2 / iwarp_vals.deform_area_radius) + 1;
  1507.   dx /= num;
  1508.   dy /= num;
  1509.   xf = xx + dx; yf = yy + dy; 
  1510.   for (i=0; i< num; i++)
  1511.     {
  1512.       x0 = (gint) xf;
  1513.       y0 = (gint) yf;
  1514.       iwarp_deform (x0, y0, -dx, -dy);
  1515.       xf += dx;
  1516.       yf += dy;
  1517.     }
  1518.  
  1519. static void
  1520. iwarp_ok_callback (GtkWidget *widget,
  1521.             gpointer   data)
  1522. {
  1523.   wint.run = TRUE;
  1524.  
  1525.   gtk_widget_destroy (GTK_WIDGET (data));
  1526. }
  1527.  
  1528. static gint
  1529. iwarp_motion_callback (GtkWidget *widget,
  1530.                GdkEvent  *event)
  1531. {
  1532.   GdkEventButton *mb;
  1533.   gint x, y;
  1534.  
  1535.   mb = (GdkEventButton *) event; 
  1536.   switch (event->type)
  1537.     {
  1538.     case GDK_BUTTON_PRESS:
  1539.       lastx = mb->x;
  1540.       lasty = mb->y;
  1541.       break;
  1542.  
  1543.     case GDK_BUTTON_RELEASE:
  1544.       if (mb->state & GDK_BUTTON1_MASK)
  1545.     {
  1546.       x = mb->x;
  1547.       y = mb->y;
  1548.       if (iwarp_vals.deform_mode == MOVE)
  1549.         iwarp_move (x, y, lastx, lasty);
  1550.       else
  1551.         iwarp_deform (x, y, 0.0, 0.0);
  1552.     }
  1553.       break;
  1554.  
  1555.    case GDK_MOTION_NOTIFY:
  1556.      if (mb->state & GDK_BUTTON1_MASK)
  1557.        {
  1558.      x = mb->x;
  1559.      y = mb->y;
  1560.      if (iwarp_vals.deform_mode == MOVE)
  1561.        iwarp_move (x, y, lastx, lasty);
  1562.      else
  1563.        iwarp_deform (x, y, 0.0, 0.0);
  1564.      lastx = x;
  1565.      lasty = y;
  1566.      gtk_widget_get_pointer (widget, NULL, NULL); 
  1567.        }
  1568.      break;
  1569.  
  1570.     default:
  1571.       break;
  1572.     }
  1573.  
  1574.   return FALSE;
  1575. }
  1576.  
  1577. static void
  1578. iwarp_reset_callback (GtkWidget *widget,
  1579.               gpointer   data)
  1580. {
  1581.   gint i;
  1582.  
  1583.   iwarp_cpy_images ();
  1584.   for (i = 0; i < preview_width * preview_height; i++)
  1585.     deform_vectors[i].x = deform_vectors[i].y = 0.0;
  1586.  
  1587.   iwarp_update_preview (0, 0, preview_width, preview_height);   
  1588. }
  1589.