home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / gimphistogram.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-20  |  11.1 KB  |  503 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * gimphistogram module Copyright (C) 1999 Jay Cox <jaycox@earthlink.net>
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  */
  20.  
  21. #include "config.h"
  22.  
  23. #ifdef ENABLE_MP
  24. #include <pthread.h>
  25. #endif /* ENABLE_MP */
  26.  
  27. #include <glib.h>
  28.  
  29. #include <libgimp/gimpmath.h>
  30.  
  31. #include "gimphistogram.h"
  32. #include "pixel_region.h"
  33. #include "gimpdrawable.h"
  34. #include "channel.h"
  35. #include "gimpimage.h"
  36. #include "gimprc.h"
  37.  
  38.  
  39. struct _GimpHistogram
  40. {
  41.   gint      bins;
  42.   gdouble **values;
  43.   gint      nchannels;
  44.  
  45. #ifdef ENABLE_MP
  46.   pthread_mutex_t    mutex;
  47.   gint               nthreads;
  48.   gdouble         ***tmp_values;
  49.   gchar             *tmp_slots;
  50. #endif /* ENABLE_MP */
  51. };
  52.  
  53.  
  54. GimpHistogram *
  55. gimp_histogram_new (void)
  56. {
  57.   GimpHistogram *histogram;
  58.  
  59.   histogram = g_new0 (GimpHistogram, 1);
  60.   histogram->bins      = 0;
  61.   histogram->values    = NULL;
  62.   histogram->nchannels = 0;
  63.  
  64. #ifdef ENABLE_MP
  65.   histogram->nthreads   = 0;
  66.   histogram->tmp_values = NULL;
  67.   histogram->tmp_slots  = NULL;
  68. #endif /* ENABLE_MP */
  69.  
  70.   return histogram;
  71. }
  72.  
  73. void
  74. gimp_histogram_free (GimpHistogram *histogram)
  75. {
  76.   gint i;
  77.  
  78.   if (histogram->values)
  79.     {
  80.       for (i = 0; i < histogram->nchannels; i++)
  81.     g_free (histogram->values[i]);
  82.       g_free (histogram->values);
  83.     }
  84.  
  85.   g_free (histogram);
  86. }
  87.  
  88. static void
  89. gimp_histogram_calculate_sub_region (GimpHistogram *histogram,
  90.                      PixelRegion   *region, 
  91.                      PixelRegion   *mask)
  92. {
  93.   const guchar *src, *msrc;
  94.   const guchar *m, *s;
  95.   gdouble **values;
  96.   gint h, w, max;
  97.  
  98. #ifdef ENABLE_MP
  99.   gint slot = 0;
  100.  
  101.   /* find an unused temporary slot to put our results in and lock it */
  102.   pthread_mutex_lock (&histogram->mutex);
  103.   {
  104.     while (histogram->tmp_slots[slot])
  105.       slot++;
  106.     values = histogram->tmp_values[slot];
  107.     histogram->tmp_slots[slot] = 1;
  108.   }
  109.   pthread_mutex_unlock (&histogram->mutex);
  110. #else /* !ENABLE_MP */
  111.   values = histogram->values;
  112. #endif
  113.  
  114.   h = region->h;
  115.   w = region->w;
  116.  
  117.   if (mask)
  118.     {
  119.       gdouble masked;
  120.  
  121.       src = region->data;
  122.       msrc = region->data;
  123.  
  124.       while (h--)
  125.     {
  126.       s = src;
  127.       m = msrc;
  128.       w = region->w;
  129.  
  130.       switch(region->bytes)
  131.         {
  132.         case 1:
  133.           while (w--)
  134.         {
  135.           masked = m[0] / 255.0;
  136.           values[0][s[0]] += masked;
  137.           s += 1;
  138.           m += 1;
  139.         }
  140.           break;
  141.  
  142.         case 2:
  143.           while (w--)
  144.         {
  145.           masked = m[0] / 255.0;
  146.           values[0][s[0]] += masked;
  147.           values[1][s[1]] += masked;
  148.           s += 2;
  149.           m += 1;
  150.         }
  151.           break;
  152.  
  153.         case 3: /* calculate seperate value values */ 
  154.           while (w--)
  155.         {
  156.           masked = m[0] / 255.0;
  157.           values[1][s[0]] += masked;
  158.           values[2][s[1]] += masked;
  159.           values[3][s[2]] += masked;
  160.           max = (s[0] > s[1]) ? s[0] : s[1];
  161.           if (s[2] > max)
  162.             values[0][s[2]] += masked;
  163.           else
  164.             values[0][max] += masked;
  165.           s += 3;
  166.           m += 1;
  167.         }
  168.           break;
  169.  
  170.         case 4: /* calculate seperate value values */ 
  171.           while (w--)
  172.         {
  173.           masked = m[0] / 255.0;
  174.           values[1][s[0]] += masked;
  175.           values[2][s[1]] += masked;
  176.           values[3][s[2]] += masked;
  177.           values[4][s[3]] += masked;
  178.           max = (s[0] > s[1]) ? s[0] : s[1];
  179.           if (s[2] > max)
  180.             values[0][s[2]] += masked;
  181.           else
  182.             values[0][max] += masked;
  183.           s += 3;
  184.           m += 1;
  185.         }
  186.           break;
  187.         }
  188.  
  189.       src  += region->rowstride;
  190.       msrc += mask->rowstride;
  191.     }
  192.     }
  193.   else /* no mask */
  194.     {
  195.       src = region->data;
  196.  
  197.       while (h--)
  198.     {
  199.       s = src;
  200.       w = region->w;
  201.  
  202.       switch(region->bytes)
  203.         {
  204.         case 1:
  205.           while (w--)
  206.         {
  207.           values[0][s[0]] += 1.0;
  208.           s += 1;
  209.         }
  210.           break;
  211.  
  212.         case 2:
  213.           while (w--)
  214.         {
  215.           values[0][s[0]] += 1.0;
  216.           values[1][s[1]] += 1.0;
  217.           s += 2;
  218.         }
  219.           break;
  220.  
  221.         case 3: /* calculate seperate value values */ 
  222.           while (w--)
  223.         {
  224.           values[1][s[0]] += 1.0;
  225.           values[2][s[1]] += 1.0;
  226.           values[3][s[2]] += 1.0;
  227.           max = (s[0] > s[1]) ? s[0] : s[1];
  228.           if (s[2] > max)
  229.             values[0][s[2]] += 1.0;
  230.           else
  231.             values[0][max] += 1.0;
  232.           s += 3;
  233.         }
  234.           break;
  235.  
  236.         case 4: /* calculate seperate value values */ 
  237.           while (w--)
  238.         {
  239.           values[1][s[0]] += 1.0;
  240.           values[2][s[1]] += 1.0;
  241.           values[3][s[2]] += 1.0;
  242.           values[4][s[3]] += 1.0;
  243.           max = (s[0] > s[1]) ? s[0] : s[1];
  244.           if (s[2] > max)
  245.             values[0][s[2]] += 1.0;
  246.           else
  247.             values[0][max] += 1.0;
  248.           s += 4;
  249.         }
  250.           break;
  251.         }
  252.  
  253.       src += region->rowstride;
  254.     }
  255.     }
  256.  
  257. #ifdef ENABLE_MP
  258.   /* unlock this slot */
  259.   /* we shouldn't have to use mutex locks here */
  260.   pthread_mutex_lock (&histogram->mutex);
  261.   histogram->tmp_slots[slot] = 0;
  262.   pthread_mutex_unlock (&histogram->mutex);
  263. #endif
  264. }
  265.  
  266. static void 
  267. gimp_histogram_alloc (GimpHistogram *histogram, 
  268.               gint           bytes)
  269. {
  270.   gint i;
  271.  
  272.   if (bytes + 1 != histogram->nchannels)
  273.     {
  274.       if (histogram->values)
  275.     {
  276.       for (i = 0; i < histogram->nchannels; i++)
  277.         g_free (histogram->values[i]);
  278.       g_free (histogram->values);
  279.     }
  280.  
  281.       histogram->nchannels = bytes + 1;
  282.       histogram->values    = g_new0 (gdouble *, histogram->nchannels);
  283.  
  284.       for (i = 0; i < histogram->nchannels; i++)
  285.     histogram->values[i] = g_new (double, 256);
  286.     }
  287. }
  288.  
  289. void
  290. gimp_histogram_calculate (GimpHistogram *histogram, 
  291.               PixelRegion   *region,
  292.               PixelRegion   *mask)
  293. {
  294.   gint i, j;
  295. #ifdef ENABLE_MP
  296.   gint k;
  297. #endif
  298.  
  299.   gimp_histogram_alloc (histogram, region->bytes);
  300.  
  301. #ifdef ENABLE_MP
  302.   pthread_mutex_init (&histogram->mutex, NULL);
  303.   histogram->tmp_slots  = g_new0 (gchar, num_processors);
  304.   histogram->tmp_values = g_new0 (gdouble **, num_processors);
  305.  
  306.   for (i = 0; i < num_processors; i++)
  307.     {
  308.       histogram->tmp_values[i] = g_new0 (double *, histogram->nchannels);
  309.       histogram->tmp_slots[i]  = 0;
  310.  
  311.       for (j = 0; j < histogram->nchannels; j++)
  312.     {
  313.       histogram->tmp_values[i][j] = g_new0 (gdouble, 256);
  314.  
  315.       for (k = 0; k < 256; k++)
  316.         histogram->tmp_values[i][j][k] = 0.0;
  317.     }
  318.     }
  319. #endif
  320.  
  321.   for (i = 0; i < histogram->nchannels; i++)
  322.     for (j = 0; j < 256; j++)
  323.       histogram->values[i][j] = 0.0;
  324.  
  325.   pixel_regions_process_parallel ((p_func)gimp_histogram_calculate_sub_region,
  326.                   histogram, 2, region, mask);
  327.  
  328. #ifdef ENABLE_MP
  329.   /* add up all the tmp buffers and free their memmory */
  330.   for (i = 0; i < num_processors; i++)
  331.     {
  332.       for (j = 0; j < histogram->nchannels; j++)
  333.     {
  334.       for (k = 0; k < 256; k++)
  335.         histogram->values[j][k] += histogram->tmp_values[i][j][k];
  336.       g_free (histogram->tmp_values[i][j]);
  337.     }
  338.       g_free (histogram->tmp_values[i]);
  339.     }
  340.  
  341.   g_free (histogram->tmp_values);
  342.   g_free (histogram->tmp_slots);
  343. #endif
  344. }
  345.  
  346.  
  347. void
  348. gimp_histogram_calculate_drawable (GimpHistogram *histogram,
  349.                    GimpDrawable  *drawable)
  350. {
  351.   PixelRegion region;
  352.   PixelRegion mask;
  353.   gint        x1, y1, x2, y2;
  354.   gint        off_x, off_y;
  355.   gboolean    no_mask;
  356.  
  357.   no_mask = (drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2) == FALSE);
  358.   pixel_region_init (®ion, gimp_drawable_data (drawable), x1, y1,
  359.              (x2 - x1), (y2 - y1), FALSE);
  360.  
  361.   if (!no_mask)
  362.     {
  363.       Channel   *sel_mask;
  364.       GimpImage *gimage;
  365.  
  366.       gimage = gimp_drawable_gimage (drawable);
  367.       sel_mask = gimp_image_get_mask (gimage);
  368.  
  369.       drawable_offsets (drawable, &off_x, &off_y);
  370.       pixel_region_init (&mask, gimp_drawable_data (GIMP_DRAWABLE (sel_mask)),
  371.              x1 + off_x, y1 + off_y, (x2 - x1), (y2 - y1), FALSE);
  372.       gimp_histogram_calculate (histogram, ®ion, &mask);
  373.     }
  374.   else
  375.     {
  376.       gimp_histogram_calculate (histogram, ®ion, NULL);
  377.     }
  378. }
  379.  
  380. gdouble
  381. gimp_histogram_get_maximum (GimpHistogram        *histogram, 
  382.                 GimpHistogramChannel  channel)
  383. {
  384.   gdouble max = 0.0;
  385.   gint    x;
  386.  
  387.   for (x = 0; x < 256; x++)
  388.     if (histogram->values[channel][x] > max)
  389.       max = histogram->values[channel][x];
  390.  
  391.   return max;
  392. }
  393.  
  394. gdouble
  395. gimp_histogram_get_value (GimpHistogram        *histogram, 
  396.               GimpHistogramChannel  channel, 
  397.               gint                  bin)
  398. {
  399.   if (channel < histogram->nchannels && bin >= 0 && bin < 256)
  400.     return histogram->values[channel][bin];
  401.  
  402.   return 0.0;
  403. }
  404.  
  405. gdouble
  406. gimp_histogram_get_channel (GimpHistogram        *histogram, 
  407.                 GimpHistogramChannel  channel, 
  408.                 gint                  bin)
  409. {
  410.   if (histogram->nchannels > 3)
  411.     return gimp_histogram_get_value (histogram, channel + 1, bin);
  412.   else
  413.     return gimp_histogram_get_value (histogram, channel    , bin);
  414. }
  415.  
  416. gint
  417. gimp_histogram_nchannels (GimpHistogram *histogram)
  418. {
  419.   return histogram->nchannels - 1;
  420. }
  421.  
  422. gdouble
  423. gimp_histogram_get_count (GimpHistogram *histogram, 
  424.               gint           start, 
  425.               gint           end)
  426. {
  427.   gint    i;
  428.   gdouble count = 0.0;
  429.  
  430.   for (i = start; i <= end; i++)
  431.     count += histogram->values[0][i];
  432.  
  433.   return count;
  434. }
  435.  
  436. gdouble
  437. gimp_histogram_get_mean (GimpHistogram        *histogram, 
  438.              GimpHistogramChannel  channel,
  439.              gint                  start, 
  440.              gint                  end)
  441. {
  442.   gint    i;
  443.   gdouble mean = 0.0;
  444.   gdouble count;
  445.  
  446.   for (i = start; i <= end; i++)
  447.     mean += i * histogram->values[channel][i];
  448.  
  449.   count = gimp_histogram_get_count (histogram, start, end);
  450.  
  451.   if (count > 0.0)
  452.     return mean / count;
  453.  
  454.   return mean;
  455. }
  456.  
  457. gint
  458. gimp_histogram_get_median (GimpHistogram         *histogram, 
  459.                GimpHistogramChannel   channel, 
  460.                gint                   start, 
  461.                gint                   end)
  462. {
  463.   gint    i;
  464.   gdouble sum = 0.0;
  465.   gdouble count;
  466.  
  467.   count = gimp_histogram_get_count (histogram, start, end);
  468.  
  469.   for (i = start; i <= end; i++)
  470.     {
  471.       sum += i * histogram->values[channel][i];
  472.  
  473.       if (sum * 2 > count)
  474.     return i;
  475.     }
  476.  
  477.   return -1;
  478. }
  479.  
  480. gdouble
  481. gimp_histogram_get_std_dev (GimpHistogram        *histogram, 
  482.                 GimpHistogramChannel  channel,
  483.                 gint                  start, 
  484.                 gint                  end)
  485. {
  486.   gint    i;
  487.   gdouble dev = 0.0;
  488.   gdouble count;
  489.   gdouble mean;
  490.  
  491.   mean  = gimp_histogram_get_mean  (histogram, channel, start, end);
  492.   count = gimp_histogram_get_count (histogram, start, end);
  493.  
  494.   if (count == 0.0)
  495.     count = 1.0;
  496.  
  497.   for (i = start; i <= end; i++)
  498.     dev += gimp_histogram_get_value (histogram, channel, i) *
  499.       (i - mean) * (i - mean);
  500.  
  501.   return sqrt (dev / count);
  502. }
  503.