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

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * Gradient Map plug-in
  5.  * Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20.  */
  21.  
  22. /*
  23.  * version 1.06
  24.  * This plug-in requires GIMP v0.99.10 or above.
  25.  *
  26.  * This plug-in maps the image using active gradient. (See help_string
  27.  * in query ()).
  28.  *
  29.  *    Eiichi Takamori <taka@ma1.seikyou.ne.jp>
  30.  *    http://ha1.seikyou.ne.jp/home/taka/gimp/
  31.  *
  32.  * Changes from version 1.05 to version 1.06:
  33.  * - Fixed bug that completely white pixel (= grayscale 255) was not
  34.  *   mapped properly.  (Thanks to Dov Grobgeld)
  35.  *
  36.  * Changes from version 1.04 to version 1.05:
  37.  * - Now it uses gimp_gradients_sample_uniform () instead of blend
  38.  *   tool. Maybe right thing.
  39.  *
  40.  * Changes from revision 1.1 to version 1.04:
  41.  * - Fix bug that it didn't work with alpha channel.
  42.  * - Changed calling `gimp_blend' so that it works in v0.99.9.
  43.  * - Changed calling `gimp_blend' so that it works with Quartic's
  44.  *   asupsample patch.
  45.  * - Fix the way to calculate luminosity of RGB image.
  46.  *   (Thanks to Michael Lamertz)
  47.  */
  48.  
  49. #include "config.h"
  50.  
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53.  
  54. #include <libgimp/gimp.h>
  55.  
  56. #include "libgimp/stdplugins-intl.h"
  57.  
  58.  
  59. #ifdef RCSID
  60. static char rcsid[] = "$Id: gradmap.c,v 1.11 2000/08/22 01:26:54 neo Exp $";
  61. #endif
  62.  
  63. /* Some useful macros */
  64.  
  65. #define NSAMPLES    256
  66. #define TILE_CACHE_SIZE 32
  67. #define LUMINOSITY(X)    (INTENSITY (X[0], X[1], X[2]))
  68.  
  69. /* Declare a local function.
  70.  */
  71. static void     query        (void);
  72. static void     run        (gchar     *name,
  73.                  gint     nparams,
  74.                  GimpParam     *param,
  75.                  gint     *nreturn_vals,
  76.                  GimpParam     **return_vals);
  77.  
  78. static void     gradmap    (GimpDrawable *drawable);
  79. static guchar *     get_samples    (GimpDrawable *drawable );
  80.  
  81.  
  82. GimpPlugInInfo PLUG_IN_INFO =
  83. {
  84.   NULL,     /* init_proc  */
  85.   NULL,     /* quit_proc  */
  86.   query, /* query_proc */
  87.   run,     /* run_proc   */
  88. };
  89.  
  90. MAIN ()
  91.  
  92. static void
  93. query()
  94. {
  95.   static GimpParamDef args[]=
  96.     {
  97.       { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  98.       { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  99.       { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
  100.    };
  101.   static gint nargs = sizeof (args) / sizeof (args[0]);
  102.  
  103.   gimp_install_procedure ("plug_in_gradmap",
  104.                           "Map the contents of the specified drawable with "
  105.               "active gradient",
  106.                           " This plug-in maps the contents of the specified "
  107.               "drawable with active gradient. It calculates "
  108.               "luminosity of each pixel and replaces the pixel "
  109.               "by the sample of active gradient at the position "
  110.               "proportional to that luminosity. Complete black "
  111.               "pixel becomes the leftmost color of the gradient, "
  112.               "and complete white becomes the rightmost. Works on "
  113.               "both Grayscale and RGB image with/without alpha "
  114.               "channel.",
  115.               "Eiichi Takamori",
  116.               "Eiichi Takamori",
  117.               "1997",
  118.               N_("<Image>/Filters/Colors/Map/Gradient Map"),
  119.               "RGB*, GRAY*",
  120.               GIMP_PLUGIN,
  121.               nargs, 0,
  122.               args, NULL);
  123. }
  124.  
  125. static void
  126. run (gchar   *name,
  127.      gint    nparams,
  128.      GimpParam  *param,
  129.      gint    *nreturn_vals,
  130.      GimpParam  **return_vals)
  131. {
  132.   static GimpParam values[1];
  133.   GimpDrawable *drawable;
  134.   GimpRunModeType run_mode;
  135.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  136.  
  137.   run_mode = param[0].data.d_int32;
  138.  
  139.   INIT_I18N();
  140.  
  141.   *nreturn_vals = 1;
  142.   *return_vals = values;
  143.  
  144.   values[0].type = GIMP_PDB_STATUS;
  145.   values[0].data.d_status = status;
  146.  
  147.   /*  Get the specified drawable  */
  148.   drawable = gimp_drawable_get (param[2].data.d_drawable);
  149.  
  150.   /*  Make sure that the drawable is gray or RGB color    */
  151.   if (gimp_drawable_is_rgb (drawable->id) ||
  152.       gimp_drawable_is_gray (drawable->id))
  153.     {
  154.       gimp_progress_init ( _("Gradient Map..."));
  155.       gimp_tile_cache_ntiles (TILE_CACHE_SIZE);
  156.  
  157.       gradmap (drawable);
  158.  
  159.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  160.     gimp_displays_flush ();
  161.     }
  162.   else
  163.     {
  164.       /* g_message ("gradmap: cannot operate on indexed color images"); */
  165.       status = GIMP_PDB_EXECUTION_ERROR;
  166.     }
  167.  
  168.   values[0].data.d_status = status;
  169.  
  170.   gimp_drawable_detach (drawable);
  171. }
  172.  
  173. static void
  174. gradmap (GimpDrawable *drawable)
  175. {
  176.   GimpPixelRgn    src_rgn, dest_rgn;
  177.   gpointer    pr;
  178.   guchar    *src_row, *dest_row;
  179.   guchar    *src, *dest;
  180.   gint        progress, max_progress;
  181.   gint        x1, y1, x2, y2;
  182.   gint        row, col;
  183.   gint        bpp, color, has_alpha, alpha;
  184.   guchar    *samples, *samp;
  185.   gint        lum;                /* luminosity */
  186.   gint        b;
  187.  
  188.   gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
  189.  
  190.   bpp = alpha = gimp_drawable_bpp( drawable->id );
  191.   color = gimp_drawable_is_rgb( drawable->id );
  192.   has_alpha = gimp_drawable_has_alpha( drawable->id );
  193.   if( has_alpha )
  194.     alpha--;
  195.  
  196.   samples = get_samples (drawable);
  197.  
  198.   gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, x2-x1, y2-y1, FALSE, FALSE);
  199.   gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, x2-x1, y2-y1, TRUE, TRUE);
  200.  
  201.   /* Initialize progress */
  202.   progress = 0;
  203.   max_progress = (x2 - x1) * (y2 - y1);
  204.  
  205.   for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn);
  206.        pr != NULL; pr = gimp_pixel_rgns_process (pr))
  207.     {
  208.       src_row = src_rgn.data;
  209.       dest_row = dest_rgn.data;
  210.  
  211.       for ( row = 0; row < src_rgn.h; row++ )
  212.     {
  213.       src = src_row;
  214.       dest = dest_row;
  215.  
  216.       for ( col = 0; col < src_rgn.w; col++ )
  217.         {
  218.           if( color )
  219.         {
  220.           lum = LUMINOSITY (src);
  221.           lum = CLAMP (lum, 0, 255);    /* to make sure */
  222.         }
  223.           else
  224.         lum = src[0];
  225.  
  226.           samp = &samples[lum * bpp];
  227.           for( b = 0; b < bpp; b++ )
  228.         dest[b] = samp[b];
  229.  
  230.           src += src_rgn.bpp;
  231.           dest += dest_rgn.bpp;
  232.         }
  233.       src_row += src_rgn.rowstride;
  234.       dest_row += dest_rgn.rowstride;
  235.     }
  236.       /* Update progress */
  237.       progress += src_rgn.w * src_rgn.h;
  238.       gimp_progress_update ((double) progress / (double) max_progress);
  239.     }
  240.  
  241.   g_free (samples);
  242.  
  243.   gimp_drawable_flush (drawable);
  244.   gimp_drawable_merge_shadow (drawable->id, TRUE);
  245.   gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
  246. }
  247.  
  248. /*
  249.   Returns 256 samples of active gradient.
  250.   Each sample has (gimp_drawable_bpp (drawable->id)) bytes.
  251.  */
  252. static guchar *
  253. get_samples (GimpDrawable *drawable)
  254. {
  255.   gdouble    *f_samples, *f_samp;    /* float samples */
  256.   guchar    *b_samples, *b_samp;    /* byte samples */
  257.   gint        bpp, color, has_alpha, alpha;
  258.   gint        i, j;
  259.  
  260.   f_samples = gimp_gradients_sample_uniform (NSAMPLES);
  261.  
  262.   bpp        = gimp_drawable_bpp (drawable->id);
  263.   color        = gimp_drawable_is_rgb (drawable->id);
  264.   has_alpha = gimp_drawable_has_alpha (drawable->id);
  265.   alpha        = (has_alpha ? bpp - 1 : bpp);
  266.  
  267.   b_samples = g_new (guchar, NSAMPLES * bpp);
  268.  
  269.   for (i = 0; i < NSAMPLES; i++)
  270.     {
  271.       b_samp = &b_samples[i * bpp];
  272.       f_samp = &f_samples[i * 4];
  273.       if (color)
  274.     for (j = 0; j < 3; j++)
  275.       b_samp[j] = f_samp[j] * 255;
  276.       else
  277.     b_samp[0] = LUMINOSITY (f_samp) * 255;
  278.  
  279.       if (has_alpha)
  280.     b_samp[alpha] = f_samp[3] * 255;
  281.     }
  282.  
  283.   g_free (f_samples);
  284.   return b_samples;
  285. }
  286.