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

  1. /* Tiler v0.31
  2.  * 22 May 1997
  3.  * Tim Rowley <tor@cs.brown.edu>
  4.  */
  5.  
  6. /* TODO:
  7.  * + better basis function
  8.  * + optimize
  9.  */
  10.  
  11. /* History:
  12.  * v0.1: initial version
  13.  * v0.2: fix edge conditions
  14.  * v0.3: port to 0.99 API
  15.  * v0.31: small bugfix
  16.  */
  17.  
  18. #include "config.h"
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include <libgimp/gimp.h>
  25.  
  26. #include "libgimp/stdplugins-intl.h"
  27.  
  28.  
  29. /* Declare local functions.
  30.  */
  31. static void query (void);
  32. static void run   (gchar   *name,
  33.            gint     nparams,
  34.            GimpParam  *param,
  35.            gint    *nreturn_vals,
  36.            GimpParam **return_vals);
  37.  
  38. static void tile  (GimpDrawable *drawable);
  39. static gint scale (gint       width,
  40.            gint       height,
  41.            gint       x,
  42.            gint       y,
  43.            gint       data);
  44.  
  45.  
  46. GimpPlugInInfo PLUG_IN_INFO =
  47. {
  48.   NULL,  /* init_proc  */
  49.   NULL,  /* quit_proc  */
  50.   query, /* query_proc */
  51.   run,   /* run_proc   */
  52. };
  53.  
  54. MAIN ()
  55.  
  56. static void
  57. query (void)
  58. {
  59.   static GimpParamDef args[] =
  60.   {
  61.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  62.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  63.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
  64.   };
  65.   static gint nargs = sizeof (args) / sizeof (args[0]);
  66.  
  67.   gimp_install_procedure ("plug_in_make_seamless",
  68.               "Seamless tile creation",
  69.               "This plugin creates a seamless tileable from the input image",
  70.               "Tim Rowley",
  71.               "Tim Rowley",
  72.               "1997",
  73.               N_("<Image>/Filters/Map/Make Seamless"),
  74.               "RGB*, GRAY*",
  75.               GIMP_PLUGIN,
  76.               nargs, 0,
  77.               args, NULL);
  78. }
  79.  
  80.  
  81. static void
  82. run (gchar   *name,
  83.      gint     nparams,
  84.      GimpParam  *param,
  85.      gint    *nreturn_vals,
  86.      GimpParam **return_vals)
  87. {
  88.   static GimpParam values[1];
  89.   GimpDrawable *drawable;
  90.   GimpRunModeType run_mode;
  91.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  92.  
  93.   run_mode = param[0].data.d_int32;
  94.  
  95.   INIT_I18N();
  96.  
  97.   /*  Get the specified drawable  */
  98.   drawable = gimp_drawable_get (param[2].data.d_drawable);
  99.  
  100.   /*  Make sure that the drawable is gray or RGB color  */
  101.   if (gimp_drawable_is_rgb (drawable->id) ||
  102.       gimp_drawable_is_gray (drawable->id))
  103.     {
  104.       gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));
  105.       tile(drawable);
  106.  
  107.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  108.     gimp_displays_flush ();
  109.     }
  110.   else
  111.     {
  112.       /* gimp_message ("laplace: cannot operate on indexed color images"); */
  113.       status = GIMP_PDB_EXECUTION_ERROR;
  114.     }
  115.  
  116.   *nreturn_vals = 1;
  117.   *return_vals = values;
  118.  
  119.   values[0].type = GIMP_PDB_STATUS;
  120.   values[0].data.d_status = status;
  121.  
  122.   gimp_drawable_detach (drawable);
  123. }
  124.  
  125.  
  126. static gint
  127. scale (gint width,
  128.        gint height,
  129.        gint x,
  130.        gint y,
  131.        gint data)
  132. {
  133.   gint A = width/2-1;
  134.   gint B = height/2-1;
  135.   gint a, b;
  136.  
  137.   if (x<width/2)
  138.     a = width/2-x-1; 
  139.   else if ((x==width/2) && (width&1))
  140.       return data;
  141.   else
  142.     a = x-width/2-(width&1);
  143.  
  144.   if (y<height/2)
  145.     b = height/2-y-1; 
  146.   else if ((y==height/2) && (height&1))
  147.     return data;
  148.   else
  149.     b = y-height/2-(height&1);
  150.   
  151.   if ((B*a<A*b) || ((B*a==A*b) && (a&1)))
  152.     {
  153.       a = A-a;
  154.       b = B-b;
  155.       if (a==A)
  156.     return data;
  157.       else
  158.     return data-((data*(A*B-a*B))/(A*b+A*B-a*B));
  159.     }
  160.   else
  161.     {
  162.       if (a==A)
  163.     return 0;
  164.       else 
  165.     return (data*(A*B-a*B))/(A*b+A*B-a*B);
  166.   }
  167. }
  168.  
  169.  
  170. static void
  171. tile (GimpDrawable *drawable)
  172. {
  173.   glong      width, height;
  174.   glong      bytes;
  175.   glong      val;
  176.   gint       wodd, hodd;
  177.   GimpPixelRgn  srcPR, destPR;
  178.   gint       x1, y1, x2, y2;
  179.   gint       row, col, x, y, c;
  180.   guchar    *cur_row, *dest_cur, *dest_top, *dest_bot;
  181.  
  182.   /* Get the input */
  183.  
  184.   gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
  185.   gimp_progress_init (_("Tiler..."));
  186.   
  187.   width  = drawable->width;
  188.   height = drawable->height;
  189.   bytes  = drawable->bpp;
  190.  
  191.   /*  allocate row buffers  */
  192.   cur_row  = g_new (guchar, (x2 - x1) * bytes);
  193.   dest_cur = g_new (guchar, (x2 - x1) * bytes);
  194.   dest_top = g_new (guchar, (x2 - x1) * bytes);
  195.   dest_bot = g_new (guchar, (x2 - x1) * bytes);
  196.  
  197.   gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  198.   gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);
  199.  
  200.   y = y2-y1;
  201.   x = x2-x1;
  202.  
  203.   wodd = x&1;
  204.   hodd = y&1;
  205.  
  206.   for (row = 0; row <y; row++)
  207.     {
  208.       gimp_pixel_rgn_get_row (&destPR, dest_cur, x1, y1+row, (x2-x1));
  209.       memset (dest_cur, 0, x*bytes);
  210.       gimp_pixel_rgn_set_row (&destPR, dest_cur, x1, y1+row, (x2-x1));
  211.     }
  212.  
  213.   for (row = 0; row < y; row++)
  214.     {
  215.       gimp_pixel_rgn_get_row (&srcPR, cur_row, x1, y1+row, (x2-x1));
  216.       gimp_pixel_rgn_get_row (&destPR, dest_cur, x1, y1+row, (x2-x1));
  217.       if (row >= y/2+hodd)
  218.     gimp_pixel_rgn_get_row (&destPR, dest_top,
  219.                 x1, y1+(row-y/2-hodd), (x2-x1));
  220.       if (row < y/2)
  221.     gimp_pixel_rgn_get_row (&destPR, dest_bot,
  222.                 x1, y1+(row+y/2+hodd), (x2-x1));
  223.  
  224.       for (col = 0; col < x; col++)
  225.     {
  226.       for (c=0; c<bytes; c++)
  227.         {
  228.           val = scale (x, y, col, row, cur_row[col*bytes+c]);
  229.  
  230.           /* Main image */
  231.           dest_cur[col*bytes+c] += val;
  232.           /* top left */
  233.           if ((col>=x/2+wodd) && (row>=y/2+hodd))
  234.         dest_top[(col-x/2-wodd)*bytes+c] += val;
  235.           /* top right */
  236.           if ((col<x/2) && (row>=y/2+hodd))
  237.         dest_top[(x/2+col+wodd)*bytes+c] += val;
  238.           /* bottom left */
  239.           if ((col>=x/2+wodd) && (row<y/2))
  240.         dest_bot[(col-x/2-wodd)*bytes+c] += val;
  241.           /* bottom right */
  242.           if ((col<x/2) && (row<y/2))
  243.         dest_bot[(col+x/2+wodd)*bytes+c] += val;
  244.         }
  245.     }
  246.  
  247.       gimp_pixel_rgn_set_row (&destPR, dest_cur, x1, y1+row, (x2-x1));
  248.       if (row >= y/2+hodd)
  249.     gimp_pixel_rgn_set_row (&destPR, dest_top,
  250.                 x1, y1+(row-y/2-hodd), (x2-x1));
  251.       if (row < y/2)
  252.     gimp_pixel_rgn_set_row (&destPR, dest_bot,
  253.                 x1, y1+(row+y/2+hodd), (x2-x1));
  254.  
  255.       if ((row % 5) == 0)
  256.     gimp_progress_update ((gdouble) row / (gdouble) (y2 - y1));
  257.     }
  258.  
  259.   gimp_drawable_flush (drawable);
  260.   gimp_drawable_merge_shadow (drawable->id, TRUE);
  261.   gimp_drawable_update (drawable->id, x1, y1, (x2-x1), (y2-y1));
  262. }
  263.