gimphistogram.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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. #include "config.h"
  21. #ifdef ENABLE_MP
  22. #include <pthread.h>
  23. #endif /* ENABLE_MP */
  24. #include <glib.h>
  25. #include <libgimp/gimpmath.h>
  26. #include "gimphistogram.h"
  27. #include "pixel_region.h"
  28. #include "gimpdrawable.h"
  29. #include "channel.h"
  30. #include "gimpimage.h"
  31. #include "gimprc.h"
  32. struct _GimpHistogram
  33. {
  34. gint bins;
  35. gdouble **values;
  36. gint nchannels;
  37. #ifdef ENABLE_MP
  38. pthread_mutex_t mutex;
  39. gint nthreads;
  40. gdouble ***tmp_values;
  41. gchar *tmp_slots;
  42. #endif /* ENABLE_MP */
  43. };
  44. GimpHistogram *
  45. gimp_histogram_new (void)
  46. {
  47. GimpHistogram *histogram;
  48. histogram = g_new0 (GimpHistogram, 1);
  49. histogram->bins = 0;
  50. histogram->values = NULL;
  51. histogram->nchannels = 0;
  52. #ifdef ENABLE_MP
  53. histogram->nthreads = 0;
  54. histogram->tmp_values = NULL;
  55. histogram->tmp_slots = NULL;
  56. #endif /* ENABLE_MP */
  57. return histogram;
  58. }
  59. void
  60. gimp_histogram_free (GimpHistogram *histogram)
  61. {
  62. gint i;
  63. if (histogram->values)
  64. {
  65. for (i = 0; i < histogram->nchannels; i++)
  66. g_free (histogram->values[i]);
  67. g_free (histogram->values);
  68. }
  69. g_free (histogram);
  70. }
  71. static void
  72. gimp_histogram_calculate_sub_region (GimpHistogram *histogram,
  73. PixelRegion *region,
  74. PixelRegion *mask)
  75. {
  76. const guchar *src, *msrc;
  77. const guchar *m, *s;
  78. gdouble **values;
  79. gint h, w, max;
  80. #ifdef ENABLE_MP
  81. gint slot = 0;
  82. /* find an unused temporary slot to put our results in and lock it */
  83. pthread_mutex_lock (&histogram->mutex);
  84. {
  85. while (histogram->tmp_slots[slot])
  86. slot++;
  87. values = histogram->tmp_values[slot];
  88. histogram->tmp_slots[slot] = 1;
  89. }
  90. pthread_mutex_unlock (&histogram->mutex);
  91. #else /* !ENABLE_MP */
  92. values = histogram->values;
  93. #endif
  94. h = region->h;
  95. w = region->w;
  96. if (mask)
  97. {
  98. gdouble masked;
  99. src = region->data;
  100. msrc = mask->data;
  101. while (h--)
  102. {
  103. s = src;
  104. m = msrc;
  105. w = region->w;
  106. switch(region->bytes)
  107. {
  108. case 1:
  109. while (w--)
  110. {
  111. masked = m[0] / 255.0;
  112. values[0][s[0]] += masked;
  113. s += 1;
  114. m += 1;
  115. }
  116. break;
  117. case 2:
  118. while (w--)
  119. {
  120. masked = m[0] / 255.0;
  121. values[0][s[0]] += masked;
  122. values[1][s[1]] += masked;
  123. s += 2;
  124. m += 1;
  125. }
  126. break;
  127. case 3: /* calculate seperate value values */
  128. while (w--)
  129. {
  130. masked = m[0] / 255.0;
  131. values[1][s[0]] += masked;
  132. values[2][s[1]] += masked;
  133. values[3][s[2]] += masked;
  134. max = (s[0] > s[1]) ? s[0] : s[1];
  135. if (s[2] > max)
  136. values[0][s[2]] += masked;
  137. else
  138. values[0][max] += masked;
  139. s += 3;
  140. m += 1;
  141. }
  142. break;
  143. case 4: /* calculate seperate value values */
  144. while (w--)
  145. {
  146. masked = m[0] / 255.0;
  147. values[1][s[0]] += masked;
  148. values[2][s[1]] += masked;
  149. values[3][s[2]] += masked;
  150. values[4][s[3]] += masked;
  151. max = (s[0] > s[1]) ? s[0] : s[1];
  152. if (s[2] > max)
  153. values[0][s[2]] += masked;
  154. else
  155. values[0][max] += masked;
  156. s += 3;
  157. m += 1;
  158. }
  159. break;
  160. }
  161. src += region->rowstride;
  162. msrc += mask->rowstride;
  163. }
  164. }
  165. else /* no mask */
  166. {
  167. src = region->data;
  168. while (h--)
  169. {
  170. s = src;
  171. w = region->w;
  172. switch(region->bytes)
  173. {
  174. case 1:
  175. while (w--)
  176. {
  177. values[0][s[0]] += 1.0;
  178. s += 1;
  179. }
  180. break;
  181. case 2:
  182. while (w--)
  183. {
  184. values[0][s[0]] += 1.0;
  185. values[1][s[1]] += 1.0;
  186. s += 2;
  187. }
  188. break;
  189. case 3: /* calculate seperate value values */
  190. while (w--)
  191. {
  192. values[1][s[0]] += 1.0;
  193. values[2][s[1]] += 1.0;
  194. values[3][s[2]] += 1.0;
  195. max = (s[0] > s[1]) ? s[0] : s[1];
  196. if (s[2] > max)
  197. values[0][s[2]] += 1.0;
  198. else
  199. values[0][max] += 1.0;
  200. s += 3;
  201. }
  202. break;
  203. case 4: /* calculate seperate value values */
  204. while (w--)
  205. {
  206. values[1][s[0]] += 1.0;
  207. values[2][s[1]] += 1.0;
  208. values[3][s[2]] += 1.0;
  209. values[4][s[3]] += 1.0;
  210. max = (s[0] > s[1]) ? s[0] : s[1];
  211. if (s[2] > max)
  212. values[0][s[2]] += 1.0;
  213. else
  214. values[0][max] += 1.0;
  215. s += 4;
  216. }
  217. break;
  218. }
  219. src += region->rowstride;
  220. }
  221. }
  222. #ifdef ENABLE_MP
  223. /* unlock this slot */
  224. /* we shouldn't have to use mutex locks here */
  225. pthread_mutex_lock (&histogram->mutex);
  226. histogram->tmp_slots[slot] = 0;
  227. pthread_mutex_unlock (&histogram->mutex);
  228. #endif
  229. }
  230. static void
  231. gimp_histogram_alloc (GimpHistogram *histogram,
  232. gint bytes)
  233. {
  234. gint i;
  235. if (bytes + 1 != histogram->nchannels)
  236. {
  237. if (histogram->values)
  238. {
  239. for (i = 0; i < histogram->nchannels; i++)
  240. g_free (histogram->values[i]);
  241. g_free (histogram->values);
  242. }
  243. histogram->nchannels = bytes + 1;
  244. histogram->values = g_new0 (gdouble *, histogram->nchannels);
  245. for (i = 0; i < histogram->nchannels; i++)
  246. histogram->values[i] = g_new (double, 256);
  247. }
  248. }
  249. void
  250. gimp_histogram_calculate (GimpHistogram *histogram,
  251. PixelRegion *region,
  252. PixelRegion *mask)
  253. {
  254. gint i, j;
  255. #ifdef ENABLE_MP
  256. gint k;
  257. #endif
  258. gimp_histogram_alloc (histogram, region->bytes);
  259. #ifdef ENABLE_MP
  260. pthread_mutex_init (&histogram->mutex, NULL);
  261. histogram->tmp_slots = g_new0 (gchar, num_processors);
  262. histogram->tmp_values = g_new0 (gdouble **, num_processors);
  263. for (i = 0; i < num_processors; i++)
  264. {
  265. histogram->tmp_values[i] = g_new0 (double *, histogram->nchannels);
  266. histogram->tmp_slots[i] = 0;
  267. for (j = 0; j < histogram->nchannels; j++)
  268. {
  269. histogram->tmp_values[i][j] = g_new0 (gdouble, 256);
  270. for (k = 0; k < 256; k++)
  271. histogram->tmp_values[i][j][k] = 0.0;
  272. }
  273. }
  274. #endif
  275. for (i = 0; i < histogram->nchannels; i++)
  276. for (j = 0; j < 256; j++)
  277. histogram->values[i][j] = 0.0;
  278. pixel_regions_process_parallel ((p_func)gimp_histogram_calculate_sub_region,
  279. histogram, 2, region, mask);
  280. #ifdef ENABLE_MP
  281. /* add up all the tmp buffers and free their memmory */
  282. for (i = 0; i < num_processors; i++)
  283. {
  284. for (j = 0; j < histogram->nchannels; j++)
  285. {
  286. for (k = 0; k < 256; k++)
  287. histogram->values[j][k] += histogram->tmp_values[i][j][k];
  288. g_free (histogram->tmp_values[i][j]);
  289. }
  290. g_free (histogram->tmp_values[i]);
  291. }
  292. g_free (histogram->tmp_values);
  293. g_free (histogram->tmp_slots);
  294. #endif
  295. }
  296. void
  297. gimp_histogram_calculate_drawable (GimpHistogram *histogram,
  298. GimpDrawable *drawable)
  299. {
  300. PixelRegion region;
  301. PixelRegion mask;
  302. gint x1, y1, x2, y2;
  303. gint off_x, off_y;
  304. gboolean no_mask;
  305. no_mask = (drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2) == FALSE);
  306. pixel_region_init (&region, gimp_drawable_data (drawable), x1, y1,
  307. (x2 - x1), (y2 - y1), FALSE);
  308. if (!no_mask)
  309. {
  310. Channel *sel_mask;
  311. GimpImage *gimage;
  312. gimage = gimp_drawable_gimage (drawable);
  313. sel_mask = gimp_image_get_mask (gimage);
  314. drawable_offsets (drawable, &off_x, &off_y);
  315. pixel_region_init (&mask, gimp_drawable_data (GIMP_DRAWABLE (sel_mask)),
  316. x1 + off_x, y1 + off_y, (x2 - x1), (y2 - y1), FALSE);
  317. gimp_histogram_calculate (histogram, &region, &mask);
  318. }
  319. else
  320. {
  321. gimp_histogram_calculate (histogram, &region, NULL);
  322. }
  323. }
  324. gdouble
  325. gimp_histogram_get_maximum (GimpHistogram *histogram,
  326. GimpHistogramChannel channel)
  327. {
  328. gdouble max = 0.0;
  329. gint x;
  330. for (x = 0; x < 256; x++)
  331. if (histogram->values[channel][x] > max)
  332. max = histogram->values[channel][x];
  333. return max;
  334. }
  335. gdouble
  336. gimp_histogram_get_value (GimpHistogram *histogram,
  337. GimpHistogramChannel channel,
  338. gint bin)
  339. {
  340. if (channel < histogram->nchannels && bin >= 0 && bin < 256)
  341. return histogram->values[channel][bin];
  342. return 0.0;
  343. }
  344. gdouble
  345. gimp_histogram_get_channel (GimpHistogram *histogram,
  346. GimpHistogramChannel channel,
  347. gint bin)
  348. {
  349. if (histogram->nchannels > 3)
  350. return gimp_histogram_get_value (histogram, channel + 1, bin);
  351. else
  352. return gimp_histogram_get_value (histogram, channel , bin);
  353. }
  354. gint
  355. gimp_histogram_nchannels (GimpHistogram *histogram)
  356. {
  357. return histogram->nchannels - 1;
  358. }
  359. gdouble
  360. gimp_histogram_get_count (GimpHistogram *histogram,
  361. gint start,
  362. gint end)
  363. {
  364. gint i;
  365. gdouble count = 0.0;
  366. for (i = start; i <= end; i++)
  367. count += histogram->values[0][i];
  368. return count;
  369. }
  370. gdouble
  371. gimp_histogram_get_mean (GimpHistogram *histogram,
  372. GimpHistogramChannel channel,
  373. gint start,
  374. gint end)
  375. {
  376. gint i;
  377. gdouble mean = 0.0;
  378. gdouble count;
  379. for (i = start; i <= end; i++)
  380. mean += i * histogram->values[channel][i];
  381. count = gimp_histogram_get_count (histogram, start, end);
  382. if (count > 0.0)
  383. return mean / count;
  384. return mean;
  385. }
  386. gint
  387. gimp_histogram_get_median (GimpHistogram *histogram,
  388. GimpHistogramChannel channel,
  389. gint start,
  390. gint end)
  391. {
  392. gint i;
  393. gdouble sum = 0.0;
  394. gdouble count;
  395. count = gimp_histogram_get_count (histogram, start, end);
  396. for (i = start; i <= end; i++)
  397. {
  398. sum += histogram->values[channel][i];
  399. if (sum * 2 > count)
  400. return i;
  401. }
  402. return -1;
  403. }
  404. gdouble
  405. gimp_histogram_get_std_dev (GimpHistogram *histogram,
  406. GimpHistogramChannel channel,
  407. gint start,
  408. gint end)
  409. {
  410. gint i;
  411. gdouble dev = 0.0;
  412. gdouble count;
  413. gdouble mean;
  414. mean = gimp_histogram_get_mean (histogram, channel, start, end);
  415. count = gimp_histogram_get_count (histogram, start, end);
  416. if (count == 0.0)
  417. count = 1.0;
  418. for (i = start; i <= end; i++)
  419. dev += gimp_histogram_get_value (histogram, channel, i) *
  420. (i - mean) * (i - mean);
  421. return sqrt (dev / count);
  422. }