Leptonica  1.83.1
Image processing and image analysis suite
enhance.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
118 #ifdef HAVE_CONFIG_H
119 #include <config_auto.h>
120 #endif /* HAVE_CONFIG_H */
121 
122 #include <math.h>
123 #include "allheaders.h"
124 
125  /* Scales contrast enhancement factor to have a useful range
126  * between 0.0 and 1.0 */
127 static const l_float32 EnhanceScaleFactor = 5.0;
128 
129 /*-------------------------------------------------------------*
130  * Gamma TRC (tone reproduction curve) mapping *
131  *-------------------------------------------------------------*/
175 PIX *
177  PIX *pixs,
178  l_float32 gamma,
179  l_int32 minval,
180  l_int32 maxval)
181 {
182 l_int32 d;
183 NUMA *nag;
184 PIXCMAP *cmap;
185 
186  if (!pixs)
187  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
188  if (pixd && (pixd != pixs))
189  return (PIX *)ERROR_PTR("pixd not null or pixs", __func__, pixd);
190  if (gamma <= 0.0) {
191  L_WARNING("gamma must be > 0.0; setting to 1.0\n", __func__);
192  gamma = 1.0;
193  }
194  if (minval >= maxval)
195  return (PIX *)ERROR_PTR("minval not < maxval", __func__, pixd);
196  cmap = pixGetColormap(pixs);
197  d = pixGetDepth(pixs);
198  if (!cmap && d != 8 && d != 32)
199  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", __func__, pixd);
200 
201  if (gamma == 1.0 && minval == 0 && maxval == 255) /* no-op */
202  return pixCopy(pixd, pixs);
203 
204  if (!pixd) /* start with a copy if not in-place */
205  pixd = pixCopy(NULL, pixs);
206 
207  if (cmap) {
208  pixcmapGammaTRC(pixGetColormap(pixd), gamma, minval, maxval);
209  return pixd;
210  }
211 
212  /* pixd is 8 or 32 bpp */
213  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
214  return (PIX *)ERROR_PTR("nag not made", __func__, pixd);
215  pixTRCMap(pixd, NULL, nag);
216  numaDestroy(&nag);
217 
218  return pixd;
219 }
220 
221 
241 PIX *
243  PIX *pixs,
244  PIX *pixm,
245  l_float32 gamma,
246  l_int32 minval,
247  l_int32 maxval)
248 {
249 l_int32 d;
250 NUMA *nag;
251 
252  if (!pixm)
253  return pixGammaTRC(pixd, pixs, gamma, minval, maxval);
254 
255  if (!pixs)
256  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
257  if (pixGetColormap(pixs))
258  return (PIX *)ERROR_PTR("invalid: pixs has a colormap", __func__, pixd);
259  if (pixd && (pixd != pixs))
260  return (PIX *)ERROR_PTR("pixd not null or pixs", __func__, pixd);
261  d = pixGetDepth(pixs);
262  if (d != 8 && d != 32)
263  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", __func__, pixd);
264  if (minval >= maxval)
265  return (PIX *)ERROR_PTR("minval not < maxval", __func__, pixd);
266  if (gamma <= 0.0) {
267  L_WARNING("gamma must be > 0.0; setting to 1.0\n", __func__);
268  gamma = 1.0;
269  }
270 
271  if (gamma == 1.0 && minval == 0 && maxval == 255)
272  return pixCopy(pixd, pixs);
273 
274  if (!pixd) /* start with a copy if not in-place */
275  pixd = pixCopy(NULL, pixs);
276 
277  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
278  return (PIX *)ERROR_PTR("nag not made", __func__, pixd);
279  pixTRCMap(pixd, pixm, nag);
280  numaDestroy(&nag);
281 
282  return pixd;
283 }
284 
285 
303 PIX *
305  PIX *pixs,
306  l_float32 gamma,
307  l_int32 minval,
308  l_int32 maxval)
309 {
310 NUMA *nag;
311 PIX *pixalpha;
312 
313  if (!pixs || pixGetDepth(pixs) != 32)
314  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, pixd);
315  if (pixd && (pixd != pixs))
316  return (PIX *)ERROR_PTR("pixd not null or pixs", __func__, pixd);
317  if (gamma <= 0.0) {
318  L_WARNING("gamma must be > 0.0; setting to 1.0\n", __func__);
319  gamma = 1.0;
320  }
321  if (minval >= maxval)
322  return (PIX *)ERROR_PTR("minval not < maxval", __func__, pixd);
323 
324  if (gamma == 1.0 && minval == 0 && maxval == 255)
325  return pixCopy(pixd, pixs);
326  if (!pixd) /* start with a copy if not in-place */
327  pixd = pixCopy(NULL, pixs);
328 
329  pixalpha = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL); /* save */
330  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
331  return (PIX *)ERROR_PTR("nag not made", __func__, pixd);
332  pixTRCMap(pixd, NULL, nag);
333  pixSetRGBComponent(pixd, pixalpha, L_ALPHA_CHANNEL); /* restore */
334  pixSetSpp(pixd, 4);
335 
336  numaDestroy(&nag);
337  pixDestroy(&pixalpha);
338  return pixd;
339 }
340 
341 
362 NUMA *
363 numaGammaTRC(l_float32 gamma,
364  l_int32 minval,
365  l_int32 maxval)
366 {
367 l_int32 i, val;
368 l_float32 x, invgamma;
369 NUMA *na;
370 
371  if (minval >= maxval)
372  return (NUMA *)ERROR_PTR("minval not < maxval", __func__, NULL);
373  if (gamma <= 0.0) {
374  L_WARNING("gamma must be > 0.0; setting to 1.0\n", __func__);
375  gamma = 1.0;
376  }
377 
378  invgamma = 1. / gamma;
379  na = numaCreate(256);
380  for (i = 0; i < minval; i++)
381  numaAddNumber(na, 0);
382  for (i = minval; i <= maxval; i++) {
383  if (i < 0) continue;
384  if (i > 255) continue;
385  x = (l_float32)(i - minval) / (l_float32)(maxval - minval);
386  val = (l_int32)(255. * powf(x, invgamma) + 0.5);
387  val = L_MAX(val, 0);
388  val = L_MIN(val, 255);
389  numaAddNumber(na, val);
390  }
391  for (i = maxval + 1; i < 256; i++)
392  numaAddNumber(na, 255);
393 
394  return na;
395 }
396 
397 
398 /*-------------------------------------------------------------*
399  * Contrast enhancement *
400  *-------------------------------------------------------------*/
430 PIX *
432  PIX *pixs,
433  l_float32 factor)
434 {
435 l_int32 d;
436 NUMA *nac;
437 PIXCMAP *cmap;
438 
439  if (!pixs)
440  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
441  if (pixd && (pixd != pixs))
442  return (PIX *)ERROR_PTR("pixd not null or pixs", __func__, pixd);
443  if (factor < 0.0) {
444  L_WARNING("factor must be >= 0.0; using 0.0\n", __func__);
445  factor = 0.0;
446  }
447  if (factor == 0.0)
448  return pixCopy(pixd, pixs);
449 
450  cmap = pixGetColormap(pixs);
451  d = pixGetDepth(pixs);
452  if (!cmap && d != 8 && d != 32)
453  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", __func__, pixd);
454 
455  if (!pixd) /* start with a copy if not in-place */
456  pixd = pixCopy(NULL, pixs);
457 
458  if (cmap) {
459  pixcmapContrastTRC(pixGetColormap(pixd), factor);
460  return pixd;
461  }
462 
463  /* pixd is 8 or 32 bpp */
464  if ((nac = numaContrastTRC(factor)) == NULL)
465  return (PIX *)ERROR_PTR("nac not made", __func__, pixd);
466  pixTRCMap(pixd, NULL, nac);
467  numaDestroy(&nac);
468 
469  return pixd;
470 }
471 
472 
490 PIX *
492  PIX *pixs,
493  PIX *pixm,
494  l_float32 factor)
495 {
496 l_int32 d;
497 NUMA *nac;
498 
499  if (!pixm)
500  return pixContrastTRC(pixd, pixs, factor);
501 
502  if (!pixs)
503  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
504  if (pixGetColormap(pixs))
505  return (PIX *)ERROR_PTR("invalid: pixs has a colormap", __func__, pixd);
506  if (pixd && (pixd != pixs))
507  return (PIX *)ERROR_PTR("pixd not null or pixs", __func__, pixd);
508  d = pixGetDepth(pixs);
509  if (d != 8 && d != 32)
510  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", __func__, pixd);
511 
512  if (factor < 0.0) {
513  L_WARNING("factor must be >= 0.0; using 0.0\n", __func__);
514  factor = 0.0;
515  }
516  if (factor == 0.0)
517  return pixCopy(pixd, pixs);
518 
519  if (!pixd) /* start with a copy if not in-place */
520  pixd = pixCopy(NULL, pixs);
521 
522  if ((nac = numaContrastTRC(factor)) == NULL)
523  return (PIX *)ERROR_PTR("nac not made", __func__, pixd);
524  pixTRCMap(pixd, pixm, nac);
525  numaDestroy(&nac);
526 
527  return pixd;
528 }
529 
530 
547 NUMA *
548 numaContrastTRC(l_float32 factor)
549 {
550 l_int32 i, val;
551 l_float64 x, ymax, ymin, dely, scale;
552 NUMA *na;
553 
554  if (factor < 0.0) {
555  L_WARNING("factor must be >= 0.0; using 0.0; no enhancement\n",
556  __func__);
557  factor = 0.0;
558  }
559  if (factor == 0.0)
560  return numaMakeSequence(0, 1, 256); /* linear map */
561 
562  scale = EnhanceScaleFactor;
563  ymax = atan((l_float64)(1.0 * factor * scale));
564  ymin = atan((l_float64)(-127. * factor * scale / 128.));
565  dely = ymax - ymin;
566  na = numaCreate(256);
567  for (i = 0; i < 256; i++) {
568  x = (l_float64)i;
569  val = (l_int32)((255. / dely) *
570  (-ymin + atan((l_float64)(factor * scale * (x - 127.) / 128.))) +
571  0.5);
572  numaAddNumber(na, val);
573  }
574 
575  return na;
576 }
577 
578 
579 /*-------------------------------------------------------------*
580  * Histogram equalization *
581  *-------------------------------------------------------------*/
615 PIX *
617  PIX *pixs,
618  l_float32 fract,
619  l_int32 factor)
620 {
621 l_int32 d;
622 NUMA *na;
623 PIX *pixt, *pix8;
624 PIXCMAP *cmap;
625 
626  if (!pixs)
627  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
628  if (pixd && (pixd != pixs))
629  return (PIX *)ERROR_PTR("pixd not null or pixs", __func__, pixd);
630  cmap = pixGetColormap(pixs);
631  d = pixGetDepth(pixs);
632  if (d != 8 && d != 32 && !cmap)
633  return (PIX *)ERROR_PTR("pixs not 8/32 bpp or cmapped", __func__, NULL);
634  if (fract < 0.0 || fract > 1.0)
635  return (PIX *)ERROR_PTR("fract not in [0.0 ... 1.0]", __func__, NULL);
636  if (factor < 1)
637  return (PIX *)ERROR_PTR("sampling factor < 1", __func__, NULL);
638 
639  if (fract == 0.0)
640  return pixCopy(pixd, pixs);
641 
642  /* If there is a colormap, remove it. */
643  if (cmap)
645  else
646  pixt = pixClone(pixs);
647 
648  /* Make a copy if necessary */
649  pixd = pixCopy(pixd, pixt);
650  pixDestroy(&pixt);
651 
652  d = pixGetDepth(pixd);
653  if (d == 8) {
654  na = numaEqualizeTRC(pixd, fract, factor);
655  pixTRCMap(pixd, NULL, na);
656  numaDestroy(&na);
657  } else { /* 32 bpp */
658  pix8 = pixGetRGBComponent(pixd, COLOR_RED);
659  na = numaEqualizeTRC(pix8, fract, factor);
660  pixTRCMap(pix8, NULL, na);
661  pixSetRGBComponent(pixd, pix8, COLOR_RED);
662  numaDestroy(&na);
663  pixDestroy(&pix8);
664  pix8 = pixGetRGBComponent(pixd, COLOR_GREEN);
665  na = numaEqualizeTRC(pix8, fract, factor);
666  pixTRCMap(pix8, NULL, na);
667  pixSetRGBComponent(pixd, pix8, COLOR_GREEN);
668  numaDestroy(&na);
669  pixDestroy(&pix8);
670  pix8 = pixGetRGBComponent(pixd, COLOR_BLUE);
671  na = numaEqualizeTRC(pix8, fract, factor);
672  pixTRCMap(pix8, NULL, na);
673  pixSetRGBComponent(pixd, pix8, COLOR_BLUE);
674  numaDestroy(&na);
675  pixDestroy(&pix8);
676  }
677 
678  return pixd;
679 }
680 
681 
700 NUMA *
702  l_float32 fract,
703  l_int32 factor)
704 {
705 l_int32 iin, iout, itarg;
706 l_float32 val, sum;
707 NUMA *nah, *nasum, *nad;
708 
709  if (!pix)
710  return (NUMA *)ERROR_PTR("pix not defined", __func__, NULL);
711  if (pixGetDepth(pix) != 8)
712  return (NUMA *)ERROR_PTR("pix not 8 bpp", __func__, NULL);
713  if (fract < 0.0 || fract > 1.0)
714  return (NUMA *)ERROR_PTR("fract not in [0.0 ... 1.0]", __func__, NULL);
715  if (factor < 1)
716  return (NUMA *)ERROR_PTR("sampling factor < 1", __func__, NULL);
717 
718  if (fract == 0.0)
719  L_WARNING("fract = 0.0; no equalization requested\n", __func__);
720 
721  if ((nah = pixGetGrayHistogram(pix, factor)) == NULL)
722  return (NUMA *)ERROR_PTR("histogram not made", __func__, NULL);
723  numaGetSum(nah, &sum);
724  nasum = numaGetPartialSums(nah);
725 
726  nad = numaCreate(256);
727  for (iin = 0; iin < 256; iin++) {
728  numaGetFValue(nasum, iin, &val);
729  itarg = (l_int32)(255. * val / sum + 0.5);
730  iout = iin + (l_int32)(fract * (itarg - iin));
731  iout = L_MIN(iout, 255); /* to be safe */
732  numaAddNumber(nad, iout);
733  }
734 
735  numaDestroy(&nah);
736  numaDestroy(&nasum);
737  return nad;
738 }
739 
740 
741 /*-------------------------------------------------------------*
742  * Generic TRC mapping *
743  *-------------------------------------------------------------*/
765 l_int32
767  PIX *pixm,
768  NUMA *na)
769 {
770 l_int32 w, h, d, wm, hm, wpl, wplm, i, j, sval8, dval8;
771 l_uint32 sval32, dval32;
772 l_uint32 *data, *datam, *line, *linem, *tab;
773 
774  if (!pixs)
775  return ERROR_INT("pixs not defined", __func__, 1);
776  if (pixGetColormap(pixs))
777  return ERROR_INT("pixs is colormapped", __func__, 1);
778  if (!na)
779  return ERROR_INT("na not defined", __func__, 1);
780  if (numaGetCount(na) != 256)
781  return ERROR_INT("na not of size 256", __func__, 1);
782  pixGetDimensions(pixs, &w, &h, &d);
783  if (d != 8 && d != 32)
784  return ERROR_INT("pixs not 8 or 32 bpp", __func__, 1);
785  if (pixm) {
786  if (pixGetDepth(pixm) != 1)
787  return ERROR_INT("pixm not 1 bpp", __func__, 1);
788  }
789 
790  tab = (l_uint32 *)numaGetIArray(na); /* get the array for efficiency */
791  wpl = pixGetWpl(pixs);
792  data = pixGetData(pixs);
793  if (!pixm) {
794  if (d == 8) {
795  for (i = 0; i < h; i++) {
796  line = data + i * wpl;
797  for (j = 0; j < w; j++) {
798  sval8 = GET_DATA_BYTE(line, j);
799  dval8 = tab[sval8];
800  SET_DATA_BYTE(line, j, dval8);
801  }
802  }
803  } else { /* d == 32 */
804  for (i = 0; i < h; i++) {
805  line = data + i * wpl;
806  for (j = 0; j < w; j++) {
807  sval32 = *(line + j);
808  dval32 =
809  tab[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
810  tab[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
811  tab[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
812  *(line + j) = dval32;
813  }
814  }
815  }
816  } else {
817  datam = pixGetData(pixm);
818  wplm = pixGetWpl(pixm);
819  pixGetDimensions(pixm, &wm, &hm, NULL);
820  if (d == 8) {
821  for (i = 0; i < h; i++) {
822  if (i >= hm)
823  break;
824  line = data + i * wpl;
825  linem = datam + i * wplm;
826  for (j = 0; j < w; j++) {
827  if (j >= wm)
828  break;
829  if (GET_DATA_BIT(linem, j) == 0)
830  continue;
831  sval8 = GET_DATA_BYTE(line, j);
832  dval8 = tab[sval8];
833  SET_DATA_BYTE(line, j, dval8);
834  }
835  }
836  } else { /* d == 32 */
837  for (i = 0; i < h; i++) {
838  if (i >= hm)
839  break;
840  line = data + i * wpl;
841  linem = datam + i * wplm;
842  for (j = 0; j < w; j++) {
843  if (j >= wm)
844  break;
845  if (GET_DATA_BIT(linem, j) == 0)
846  continue;
847  sval32 = *(line + j);
848  dval32 =
849  tab[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
850  tab[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
851  tab[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
852  *(line + j) = dval32;
853  }
854  }
855  }
856  }
857 
858  LEPT_FREE(tab);
859  return 0;
860 }
861 
862 
885 l_int32
887  PIX *pixm,
888  NUMA *nar,
889  NUMA *nag,
890  NUMA *nab)
891 {
892 l_int32 w, h, wm, hm, wpl, wplm, i, j;
893 l_uint32 sval32, dval32;
894 l_uint32 *data, *datam, *line, *linem, *tabr, *tabg, *tabb;
895 
896  if (!pixs || pixGetDepth(pixs) != 32)
897  return ERROR_INT("pixs not defined or not 32 bpp", __func__, 1);
898  if (pixm && pixGetDepth(pixm) != 1)
899  return ERROR_INT("pixm defined and not 1 bpp", __func__, 1);
900  if (!nar || !nag || !nab)
901  return ERROR_INT("na{r,g,b} not all defined", __func__, 1);
902  if (numaGetCount(nar) != 256 || numaGetCount(nag) != 256 ||
903  numaGetCount(nab) != 256)
904  return ERROR_INT("na{r,g,b} not all of size 256", __func__, 1);
905 
906  /* Get the arrays for efficiency */
907  tabr = (l_uint32 *)numaGetIArray(nar);
908  tabg = (l_uint32 *)numaGetIArray(nag);
909  tabb = (l_uint32 *)numaGetIArray(nab);
910  pixGetDimensions(pixs, &w, &h, NULL);
911  wpl = pixGetWpl(pixs);
912  data = pixGetData(pixs);
913  if (!pixm) {
914  for (i = 0; i < h; i++) {
915  line = data + i * wpl;
916  for (j = 0; j < w; j++) {
917  sval32 = *(line + j);
918  dval32 =
919  tabr[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
920  tabg[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
921  tabb[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
922  *(line + j) = dval32;
923  }
924  }
925  } else {
926  datam = pixGetData(pixm);
927  wplm = pixGetWpl(pixm);
928  pixGetDimensions(pixm, &wm, &hm, NULL);
929  for (i = 0; i < h; i++) {
930  if (i >= hm)
931  break;
932  line = data + i * wpl;
933  linem = datam + i * wplm;
934  for (j = 0; j < w; j++) {
935  if (j >= wm)
936  break;
937  if (GET_DATA_BIT(linem, j) == 0)
938  continue;
939  sval32 = *(line + j);
940  dval32 =
941  tabr[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
942  tabg[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
943  tabb[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
944  *(line + j) = dval32;
945  }
946  }
947  }
948 
949  LEPT_FREE(tabr);
950  LEPT_FREE(tabg);
951  LEPT_FREE(tabb);
952  return 0;
953 }
954 
955 
956 
957 /*-----------------------------------------------------------------------*
958  * Unsharp masking *
959  *-----------------------------------------------------------------------*/
978 PIX *
980  l_int32 halfwidth,
981  l_float32 fract)
982 {
983 l_int32 d;
984 PIX *pix1, *pixd, *pixr, *pixrs, *pixg, *pixgs, *pixb, *pixbs;
985 
986  if (!pixs || (pixGetDepth(pixs) == 1))
987  return (PIX *)ERROR_PTR("pixs not defined or 1 bpp", __func__, NULL);
988  if (fract <= 0.0 || halfwidth <= 0) {
989  L_WARNING("no sharpening requested; clone returned\n", __func__);
990  return pixClone(pixs);
991  }
992 
993  if (halfwidth == 1 || halfwidth == 2)
994  return pixUnsharpMaskingFast(pixs, halfwidth, fract, L_BOTH_DIRECTIONS);
995 
996  /* Remove colormap; clone if possible; result is either 8 or 32 bpp */
997  if ((pix1 = pixConvertTo8Or32(pixs, L_CLONE, 0)) == NULL)
998  return (PIX *)ERROR_PTR("pix1 not made", __func__, NULL);
999 
1000  /* Sharpen */
1001  d = pixGetDepth(pix1);
1002  if (d == 8) {
1003  pixd = pixUnsharpMaskingGray(pix1, halfwidth, fract);
1004  } else { /* d == 32 */
1005  pixr = pixGetRGBComponent(pix1, COLOR_RED);
1006  pixrs = pixUnsharpMaskingGray(pixr, halfwidth, fract);
1007  pixDestroy(&pixr);
1008  pixg = pixGetRGBComponent(pix1, COLOR_GREEN);
1009  pixgs = pixUnsharpMaskingGray(pixg, halfwidth, fract);
1010  pixDestroy(&pixg);
1011  pixb = pixGetRGBComponent(pix1, COLOR_BLUE);
1012  pixbs = pixUnsharpMaskingGray(pixb, halfwidth, fract);
1013  pixDestroy(&pixb);
1014  pixd = pixCreateRGBImage(pixrs, pixgs, pixbs);
1015  pixDestroy(&pixrs);
1016  pixDestroy(&pixgs);
1017  pixDestroy(&pixbs);
1018  if (pixGetSpp(pixs) == 4)
1019  pixCopyRGBComponent(pixd, pixs, L_ALPHA_CHANNEL);
1020  }
1021 
1022  pixDestroy(&pix1);
1023  return pixd;
1024 }
1025 
1026 
1045 PIX *
1047  l_int32 halfwidth,
1048  l_float32 fract)
1049 {
1050 l_int32 w, h, d;
1051 PIX *pixc, *pixd;
1052 PIXACC *pixacc;
1053 
1054  if (!pixs)
1055  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1056  pixGetDimensions(pixs, &w, &h, &d);
1057  if (d != 8 || pixGetColormap(pixs) != NULL)
1058  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", __func__, NULL);
1059  if (fract <= 0.0 || halfwidth <= 0) {
1060  L_WARNING("no sharpening requested; clone returned\n", __func__);
1061  return pixClone(pixs);
1062  }
1063  if (halfwidth == 1 || halfwidth == 2)
1064  return pixUnsharpMaskingGrayFast(pixs, halfwidth, fract,
1065  L_BOTH_DIRECTIONS);
1066 
1067  if ((pixc = pixBlockconvGray(pixs, NULL, halfwidth, halfwidth)) == NULL)
1068  return (PIX *)ERROR_PTR("pixc not made", __func__, NULL);
1069 
1070  /* Steps:
1071  * (1) edge image is pixs - pixc (this is highpass part)
1072  * (2) multiply edge image by fract
1073  * (3) add fraction of edge to pixs
1074  *
1075  * To show how this is done with both interfaces to arithmetic
1076  * on integer Pix, here is the implementation in the lower-level
1077  * function calls:
1078  * pixt = pixInitAccumulate(w, h, 0x10000000)) == NULL)
1079  * pixAccumulate(pixt, pixs, L_ARITH_ADD);
1080  * pixAccumulate(pixt, pixc, L_ARITH_SUBTRACT);
1081  * pixMultConstAccumulate(pixt, fract, 0x10000000);
1082  * pixAccumulate(pixt, pixs, L_ARITH_ADD);
1083  * pixd = pixFinalAccumulate(pixt, 0x10000000, 8)) == NULL)
1084  * pixDestroy(&pixt);
1085  *
1086  * The code below does the same thing using the Pixacc accumulator,
1087  * hiding the details of the offset that is needed for subtraction.
1088  */
1089  pixacc = pixaccCreate(w, h, 1);
1090  pixaccAdd(pixacc, pixs);
1091  pixaccSubtract(pixacc, pixc);
1092  pixaccMultConst(pixacc, fract);
1093  pixaccAdd(pixacc, pixs);
1094  pixd = pixaccFinal(pixacc, 8);
1095  pixaccDestroy(&pixacc);
1096 
1097  pixDestroy(&pixc);
1098  return pixd;
1099 }
1100 
1101 
1140 PIX *
1142  l_int32 halfwidth,
1143  l_float32 fract,
1144  l_int32 direction)
1145 {
1146 l_int32 d;
1147 PIX *pixt, *pixd, *pixr, *pixrs, *pixg, *pixgs, *pixb, *pixbs;
1148 
1149  if (!pixs || (pixGetDepth(pixs) == 1))
1150  return (PIX *)ERROR_PTR("pixs not defined or 1 bpp", __func__, NULL);
1151  if (fract <= 0.0 || halfwidth <= 0) {
1152  L_WARNING("no sharpening requested; clone returned\n", __func__);
1153  return pixClone(pixs);
1154  }
1155  if (halfwidth != 1 && halfwidth != 2)
1156  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", __func__, NULL);
1157  if (direction != L_HORIZ && direction != L_VERT &&
1158  direction != L_BOTH_DIRECTIONS)
1159  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
1160 
1161  /* Remove colormap; clone if possible; result is either 8 or 32 bpp */
1162  if ((pixt = pixConvertTo8Or32(pixs, L_CLONE, 0)) == NULL)
1163  return (PIX *)ERROR_PTR("pixt not made", __func__, NULL);
1164 
1165  /* Sharpen */
1166  d = pixGetDepth(pixt);
1167  if (d == 8) {
1168  pixd = pixUnsharpMaskingGrayFast(pixt, halfwidth, fract, direction);
1169  } else { /* d == 32 */
1170  pixr = pixGetRGBComponent(pixs, COLOR_RED);
1171  pixrs = pixUnsharpMaskingGrayFast(pixr, halfwidth, fract, direction);
1172  pixDestroy(&pixr);
1173  pixg = pixGetRGBComponent(pixs, COLOR_GREEN);
1174  pixgs = pixUnsharpMaskingGrayFast(pixg, halfwidth, fract, direction);
1175  pixDestroy(&pixg);
1176  pixb = pixGetRGBComponent(pixs, COLOR_BLUE);
1177  pixbs = pixUnsharpMaskingGrayFast(pixb, halfwidth, fract, direction);
1178  pixDestroy(&pixb);
1179  pixd = pixCreateRGBImage(pixrs, pixgs, pixbs);
1180  if (pixGetSpp(pixs) == 4)
1181  pixCopyRGBComponent(pixd, pixs, L_ALPHA_CHANNEL);
1182  pixDestroy(&pixrs);
1183  pixDestroy(&pixgs);
1184  pixDestroy(&pixbs);
1185  }
1186 
1187  pixDestroy(&pixt);
1188  return pixd;
1189 }
1190 
1191 
1192 
1209 PIX *
1211  l_int32 halfwidth,
1212  l_float32 fract,
1213  l_int32 direction)
1214 {
1215 PIX *pixd;
1216 
1217  if (!pixs)
1218  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1219  if (pixGetDepth(pixs) != 8 || pixGetColormap(pixs) != NULL)
1220  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", __func__, NULL);
1221  if (fract <= 0.0 || halfwidth <= 0) {
1222  L_WARNING("no sharpening requested; clone returned\n", __func__);
1223  return pixClone(pixs);
1224  }
1225  if (halfwidth != 1 && halfwidth != 2)
1226  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", __func__, NULL);
1227  if (direction != L_HORIZ && direction != L_VERT &&
1228  direction != L_BOTH_DIRECTIONS)
1229  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
1230 
1231  if (direction != L_BOTH_DIRECTIONS)
1232  pixd = pixUnsharpMaskingGray1D(pixs, halfwidth, fract, direction);
1233  else /* 2D sharpening */
1234  pixd = pixUnsharpMaskingGray2D(pixs, halfwidth, fract);
1235 
1236  return pixd;
1237 }
1238 
1239 
1256 PIX *
1258  l_int32 halfwidth,
1259  l_float32 fract,
1260  l_int32 direction)
1261 {
1262 l_int32 w, h, d, wpls, wpld, i, j, ival;
1263 l_uint32 *datas, *datad;
1264 l_uint32 *lines, *lines0, *lines1, *lines2, *lines3, *lines4, *lined;
1265 l_float32 val, a[5];
1266 PIX *pixd;
1267 
1268  if (!pixs)
1269  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1270  pixGetDimensions(pixs, &w, &h, &d);
1271  if (d != 8 || pixGetColormap(pixs) != NULL)
1272  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", __func__, NULL);
1273  if (fract <= 0.0 || halfwidth <= 0) {
1274  L_WARNING("no sharpening requested; clone returned\n", __func__);
1275  return pixClone(pixs);
1276  }
1277  if (halfwidth != 1 && halfwidth != 2)
1278  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", __func__, NULL);
1279 
1280  /* Initialize pixd with pixels from pixs that will not be
1281  * set when computing the sharpened values. */
1282  pixd = pixCopyBorder(NULL, pixs, halfwidth, halfwidth,
1283  halfwidth, halfwidth);
1284  datas = pixGetData(pixs);
1285  datad = pixGetData(pixd);
1286  wpls = pixGetWpl(pixs);
1287  wpld = pixGetWpl(pixd);
1288 
1289  if (halfwidth == 1) {
1290  a[0] = -fract / 3.0;
1291  a[1] = 1.0 + fract * 2.0 / 3.0;
1292  a[2] = a[0];
1293  } else { /* halfwidth == 2 */
1294  a[0] = -fract / 5.0;
1295  a[1] = a[0];
1296  a[2] = 1.0 + fract * 4.0 / 5.0;
1297  a[3] = a[0];
1298  a[4] = a[0];
1299  }
1300 
1301  if (direction == L_HORIZ) {
1302  for (i = 0; i < h; i++) {
1303  lines = datas + i * wpls;
1304  lined = datad + i * wpld;
1305  if (halfwidth == 1) {
1306  for (j = 1; j < w - 1; j++) {
1307  val = a[0] * GET_DATA_BYTE(lines, j - 1) +
1308  a[1] * GET_DATA_BYTE(lines, j) +
1309  a[2] * GET_DATA_BYTE(lines, j + 1);
1310  ival = (l_int32)val;
1311  ival = L_MAX(0, ival);
1312  ival = L_MIN(255, ival);
1313  SET_DATA_BYTE(lined, j, ival);
1314  }
1315  } else { /* halfwidth == 2 */
1316  for (j = 2; j < w - 2; j++) {
1317  val = a[0] * GET_DATA_BYTE(lines, j - 2) +
1318  a[1] * GET_DATA_BYTE(lines, j - 1) +
1319  a[2] * GET_DATA_BYTE(lines, j) +
1320  a[3] * GET_DATA_BYTE(lines, j + 1) +
1321  a[4] * GET_DATA_BYTE(lines, j + 2);
1322  ival = (l_int32)val;
1323  ival = L_MAX(0, ival);
1324  ival = L_MIN(255, ival);
1325  SET_DATA_BYTE(lined, j, ival);
1326  }
1327  }
1328  }
1329  } else { /* direction == L_VERT */
1330  if (halfwidth == 1) {
1331  for (i = 1; i < h - 1; i++) {
1332  lines0 = datas + (i - 1) * wpls;
1333  lines1 = datas + i * wpls;
1334  lines2 = datas + (i + 1) * wpls;
1335  lined = datad + i * wpld;
1336  for (j = 0; j < w; j++) {
1337  val = a[0] * GET_DATA_BYTE(lines0, j) +
1338  a[1] * GET_DATA_BYTE(lines1, j) +
1339  a[2] * GET_DATA_BYTE(lines2, j);
1340  ival = (l_int32)val;
1341  ival = L_MAX(0, ival);
1342  ival = L_MIN(255, ival);
1343  SET_DATA_BYTE(lined, j, ival);
1344  }
1345  }
1346  } else { /* halfwidth == 2 */
1347  for (i = 2; i < h - 2; i++) {
1348  lines0 = datas + (i - 2) * wpls;
1349  lines1 = datas + (i - 1) * wpls;
1350  lines2 = datas + i * wpls;
1351  lines3 = datas + (i + 1) * wpls;
1352  lines4 = datas + (i + 2) * wpls;
1353  lined = datad + i * wpld;
1354  for (j = 0; j < w; j++) {
1355  val = a[0] * GET_DATA_BYTE(lines0, j) +
1356  a[1] * GET_DATA_BYTE(lines1, j) +
1357  a[2] * GET_DATA_BYTE(lines2, j) +
1358  a[3] * GET_DATA_BYTE(lines3, j) +
1359  a[4] * GET_DATA_BYTE(lines4, j);
1360  ival = (l_int32)val;
1361  ival = L_MAX(0, ival);
1362  ival = L_MIN(255, ival);
1363  SET_DATA_BYTE(lined, j, ival);
1364  }
1365  }
1366  }
1367  }
1368 
1369  return pixd;
1370 }
1371 
1372 
1388 PIX *
1390  l_int32 halfwidth,
1391  l_float32 fract)
1392 {
1393 l_int32 w, h, d, wpls, wpld, wplf, i, j, ival, sval;
1394 l_uint32 *datas, *datad, *lines, *lined;
1395 l_float32 val, norm;
1396 l_float32 *dataf, *linef, *linef0, *linef1, *linef2, *linef3, *linef4;
1397 PIX *pixd;
1398 FPIX *fpix;
1399 
1400  if (!pixs)
1401  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1402  pixGetDimensions(pixs, &w, &h, &d);
1403  if (d != 8 || pixGetColormap(pixs) != NULL)
1404  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", __func__, NULL);
1405  if (fract <= 0.0 || halfwidth <= 0) {
1406  L_WARNING("no sharpening requested; clone returned\n", __func__);
1407  return pixClone(pixs);
1408  }
1409  if (halfwidth != 1 && halfwidth != 2)
1410  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", __func__, NULL);
1411 
1412  if ((pixd = pixCopyBorder(NULL, pixs, halfwidth, halfwidth,
1413  halfwidth, halfwidth)) == NULL)
1414  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
1415  datad = pixGetData(pixd);
1416  wpld = pixGetWpl(pixd);
1417  datas = pixGetData(pixs);
1418  wpls = pixGetWpl(pixs);
1419 
1420  /* Do the low pass separably. Store the result of horizontal
1421  * smoothing in an intermediate fpix. */
1422  if ((fpix = fpixCreate(w, h)) == NULL) {
1423  pixDestroy(&pixd);
1424  return (PIX *)ERROR_PTR("fpix not made", __func__, NULL);
1425  }
1426  dataf = fpixGetData(fpix);
1427  wplf = fpixGetWpl(fpix);
1428  if (halfwidth == 1) {
1429  for (i = 0; i < h; i++) {
1430  lines = datas + i * wpls;
1431  linef = dataf + i * wplf;
1432  for (j = 1; j < w - 1; j++) {
1433  val = GET_DATA_BYTE(lines, j - 1) +
1434  GET_DATA_BYTE(lines, j) +
1435  GET_DATA_BYTE(lines, j + 1);
1436  linef[j] = val;
1437  }
1438  }
1439  } else {
1440  for (i = 0; i < h; i++) {
1441  lines = datas + i * wpls;
1442  linef = dataf + i * wplf;
1443  for (j = 2; j < w - 2; j++) {
1444  val = GET_DATA_BYTE(lines, j - 2) +
1445  GET_DATA_BYTE(lines, j - 1) +
1446  GET_DATA_BYTE(lines, j) +
1447  GET_DATA_BYTE(lines, j + 1) +
1448  GET_DATA_BYTE(lines, j + 2);
1449  linef[j] = val;
1450  }
1451  }
1452  }
1453 
1454  /* Do vertical smoothing to finish the low-pass filter.
1455  * At each pixel, if L is the lowpass value, I is the
1456  * src pixel value and f is the fraction of highpass to
1457  * be added to I, then the highpass filter value is
1458  * H = I - L
1459  * and the new sharpened value is
1460  * N = I + f * H. */
1461  if (halfwidth == 1) {
1462  for (i = 1; i < h - 1; i++) {
1463  linef0 = dataf + (i - 1) * wplf;
1464  linef1 = dataf + i * wplf;
1465  linef2 = dataf + (i + 1) * wplf;
1466  lined = datad + i * wpld;
1467  lines = datas + i * wpls;
1468  norm = 1.0 / 9.0;
1469  for (j = 1; j < w - 1; j++) {
1470  val = norm * (linef0[j] + linef1[j] +
1471  linef2[j]); /* L: lowpass filter value */
1472  sval = GET_DATA_BYTE(lines, j); /* I: source pixel */
1473  ival = (l_int32)(sval + fract * (sval - val) + 0.5);
1474  ival = L_MAX(0, ival);
1475  ival = L_MIN(255, ival);
1476  SET_DATA_BYTE(lined, j, ival);
1477  }
1478  }
1479  } else {
1480  for (i = 2; i < h - 2; i++) {
1481  linef0 = dataf + (i - 2) * wplf;
1482  linef1 = dataf + (i - 1) * wplf;
1483  linef2 = dataf + i * wplf;
1484  linef3 = dataf + (i + 1) * wplf;
1485  linef4 = dataf + (i + 2) * wplf;
1486  lined = datad + i * wpld;
1487  lines = datas + i * wpls;
1488  norm = 1.0 / 25.0;
1489  for (j = 2; j < w - 2; j++) {
1490  val = norm * (linef0[j] + linef1[j] + linef2[j] + linef3[j] +
1491  linef4[j]); /* L: lowpass filter value */
1492  sval = GET_DATA_BYTE(lines, j); /* I: source pixel */
1493  ival = (l_int32)(sval + fract * (sval - val) + 0.5);
1494  ival = L_MAX(0, ival);
1495  ival = L_MIN(255, ival);
1496  SET_DATA_BYTE(lined, j, ival);
1497  }
1498  }
1499  }
1500 
1501  fpixDestroy(&fpix);
1502  return pixd;
1503 }
1504 
1505 
1506 /*-----------------------------------------------------------------------*
1507  * Hue and saturation modification *
1508  *-----------------------------------------------------------------------*/
1532 PIX *
1534  PIX *pixs,
1535  l_float32 fract)
1536 {
1537 l_int32 w, h, d, i, j, wpl, delhue;
1538 l_int32 rval, gval, bval, hval, sval, vval;
1539 l_uint32 *data, *line;
1540 
1541  if (!pixs)
1542  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1543  if (pixGetColormap(pixs) != NULL)
1544  return (PIX *)ERROR_PTR("pixs colormapped", __func__, NULL);
1545  if (pixd && (pixd != pixs))
1546  return (PIX *)ERROR_PTR("pixd not null or pixs", __func__, pixd);
1547  pixGetDimensions(pixs, &w, &h, &d);
1548  if (d != 32)
1549  return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
1550  if (L_ABS(fract) > 1.0)
1551  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", __func__, NULL);
1552 
1553  pixd = pixCopy(pixd, pixs);
1554 
1555  delhue = (l_int32)(240 * fract);
1556  if (delhue == 0 || delhue == 240 || delhue == -240) {
1557  L_WARNING("no change requested in hue\n", __func__);
1558  return pixd;
1559  }
1560  if (delhue < 0)
1561  delhue += 240;
1562 
1563  data = pixGetData(pixd);
1564  wpl = pixGetWpl(pixd);
1565  for (i = 0; i < h; i++) {
1566  line = data + i * wpl;
1567  for (j = 0; j < w; j++) {
1568  extractRGBValues(line[j], &rval, &gval, &bval);
1569  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1570  hval = (hval + delhue) % 240;
1571  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1572  composeRGBPixel(rval, gval, bval, line + j);
1573  }
1574  }
1575  if (pixGetSpp(pixs) == 4)
1576  pixCopyRGBComponent(pixd, pixs, L_ALPHA_CHANNEL);
1577 
1578  return pixd;
1579 }
1580 
1581 
1604 PIX *
1606  PIX *pixs,
1607  l_float32 fract)
1608 {
1609 l_int32 w, h, d, i, j, wpl;
1610 l_int32 rval, gval, bval, hval, sval, vval;
1611 l_uint32 *data, *line;
1612 
1613  if (!pixs)
1614  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1615  pixGetDimensions(pixs, &w, &h, &d);
1616  if (d != 32)
1617  return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
1618  if (L_ABS(fract) > 1.0)
1619  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", __func__, NULL);
1620 
1621  pixd = pixCopy(pixd, pixs);
1622  if (fract == 0.0) {
1623  L_WARNING("no change requested in saturation\n", __func__);
1624  return pixd;
1625  }
1626 
1627  data = pixGetData(pixd);
1628  wpl = pixGetWpl(pixd);
1629  for (i = 0; i < h; i++) {
1630  line = data + i * wpl;
1631  for (j = 0; j < w; j++) {
1632  extractRGBValues(line[j], &rval, &gval, &bval);
1633  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1634  if (fract < 0.0)
1635  sval = (l_int32)(sval * (1.0 + fract));
1636  else
1637  sval = (l_int32)(sval + fract * (255 - sval));
1638  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1639  composeRGBPixel(rval, gval, bval, line + j);
1640  }
1641  }
1642  if (pixGetSpp(pixs) == 4)
1643  pixCopyRGBComponent(pixd, pixs, L_ALPHA_CHANNEL);
1644 
1645  return pixd;
1646 }
1647 
1648 
1657 l_int32
1659  l_int32 factor,
1660  l_float32 *psat)
1661 {
1662 l_int32 w, h, d, i, j, wpl, sum, count;
1663 l_int32 rval, gval, bval, hval, sval, vval;
1664 l_uint32 *data, *line;
1665 
1666  if (!psat)
1667  return ERROR_INT("pixs not defined", __func__, 1);
1668  *psat = 0.0;
1669  if (!pixs)
1670  return ERROR_INT("pixs not defined", __func__, 1);
1671  pixGetDimensions(pixs, &w, &h, &d);
1672  if (d != 32)
1673  return ERROR_INT("pixs not 32 bpp", __func__, 1);
1674  if (factor < 1)
1675  return ERROR_INT("subsampling factor < 1", __func__, 1);
1676 
1677  data = pixGetData(pixs);
1678  wpl = pixGetWpl(pixs);
1679  for (i = 0, sum = 0, count = 0; i < h; i += factor) {
1680  line = data + i * wpl;
1681  for (j = 0; j < w; j += factor) {
1682  extractRGBValues(line[j], &rval, &gval, &bval);
1683  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1684  sum += sval;
1685  count++;
1686  }
1687  }
1688 
1689  if (count > 0)
1690  *psat = (l_float32)sum / (l_float32)count;
1691  return 0;
1692 }
1693 
1694 
1717 PIX *
1719  PIX *pixs,
1720  l_float32 fract)
1721 {
1722 l_int32 w, h, d, i, j, wpl;
1723 l_int32 rval, gval, bval, hval, sval, vval;
1724 l_uint32 *data, *line;
1725 
1726  if (!pixs)
1727  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1728  pixGetDimensions(pixs, &w, &h, &d);
1729  if (d != 32)
1730  return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
1731  if (L_ABS(fract) > 1.0)
1732  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", __func__, NULL);
1733 
1734  pixd = pixCopy(pixd, pixs);
1735  if (fract == 0.0) {
1736  L_WARNING("no change requested in brightness\n", __func__);
1737  return pixd;
1738  }
1739 
1740  data = pixGetData(pixd);
1741  wpl = pixGetWpl(pixd);
1742  for (i = 0; i < h; i++) {
1743  line = data + i * wpl;
1744  for (j = 0; j < w; j++) {
1745  extractRGBValues(line[j], &rval, &gval, &bval);
1746  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1747  if (fract > 0.0)
1748  vval = (l_int32)(vval + fract * (255.0 - vval));
1749  else
1750  vval = (l_int32)(vval * (1.0 + fract));
1751  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1752  composeRGBPixel(rval, gval, bval, line + j);
1753  }
1754  }
1755  if (pixGetSpp(pixs) == 4)
1756  pixCopyRGBComponent(pixd, pixs, L_ALPHA_CHANNEL);
1757 
1758  return pixd;
1759 }
1760 
1761 
1762 /*-----------------------------------------------------------------------*
1763  * Color shifting *
1764  *-----------------------------------------------------------------------*/
1796 PIX *
1798  l_float32 roff,
1799  l_float32 goff,
1800  l_float32 boff,
1801  l_float32 delta,
1802  l_int32 nincr)
1803 {
1804 char buf[64];
1805 l_int32 i, w, h;
1806 l_float32 del, ratio;
1807 L_BMF *bmf;
1808 PIX *pix1, *pix2, *pix3;
1809 PIXA *pixa;
1810 
1811  if (!pixs || pixGetDepth(pixs) != 32)
1812  return (PIX *)ERROR_PTR("pixs undefined or not rgb", __func__, NULL);
1813  if (roff < -1.0 || roff > 1.0)
1814  return (PIX *)ERROR_PTR("roff not in [-1.0, 1.0]", __func__, NULL);
1815  if (goff < -1.0 || goff > 1.0)
1816  return (PIX *)ERROR_PTR("goff not in [-1.0, 1.0]", __func__, NULL);
1817  if (boff < -1.0 || boff > 1.0)
1818  return (PIX *)ERROR_PTR("boff not in [-1.0, 1.0]", __func__, NULL);
1819  if (delta < 0.0 || delta > 0.1)
1820  return (PIX *)ERROR_PTR("delta not in [0.0, 0.1]", __func__, NULL);
1821  if (delta == 0.0) delta = 0.04;
1822  if (nincr < 0 || nincr > 6)
1823  return (PIX *)ERROR_PTR("nincr not in [0, 6]", __func__, NULL);
1824  if (nincr == 0) nincr = 2;
1825 
1826  /* Require width and height to be >= 100, and the aspect ratio <= 5.0 */
1827  pixGetDimensions(pixs, &w, &h, NULL);
1828  if (w < 100 || h < 100)
1829  return (PIX *)ERROR_PTR("w and h not both >= 100", __func__, NULL);
1830  pixMaxAspectRatio(pixs, &ratio);
1831  if (ratio < 1.0 || ratio > 5.0) {
1832  L_ERROR("invalid aspect ratio %5.1f\n", __func__, ratio);
1833  return NULL;
1834  }
1835 
1836  pixa = pixaCreate(3 * (2 * nincr + 1));
1837  bmf = bmfCreate(NULL, 8);
1838  pix1 = pixScaleToSize(pixs, 400, 0);
1839  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1840  pix2 = pixColorShiftRGB(pix1, roff + del, goff, boff);
1841  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1842  roff + del, goff, boff);
1843  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1844  L_ADD_BELOW, 0);
1845  pixaAddPix(pixa, pix3, L_INSERT);
1846  pixDestroy(&pix2);
1847  }
1848  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1849  pix2 = pixColorShiftRGB(pix1, roff, goff + del, boff);
1850  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1851  roff, goff + del, boff);
1852  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1853  L_ADD_BELOW, 0);
1854  pixaAddPix(pixa, pix3, L_INSERT);
1855  pixDestroy(&pix2);
1856  }
1857  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1858  pix2 = pixColorShiftRGB(pix1, roff, goff, boff + del);
1859  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1860  roff, goff, boff + del);
1861  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1862  L_ADD_BELOW, 0);
1863  pixaAddPix(pixa, pix3, L_INSERT);
1864  pixDestroy(&pix2);
1865  }
1866  pixDestroy(&pix1);
1867 
1868  pix1 = pixaDisplayTiledAndScaled(pixa, 32, 300, 2 * nincr + 1, 0, 30, 2);
1869  pixaDestroy(&pixa);
1870  bmfDestroy(&bmf);
1871  return pix1;
1872 }
1873 
1874 
1900 PIX *
1902  l_float32 rfract,
1903  l_float32 gfract,
1904  l_float32 bfract)
1905 {
1906 l_int32 w, h, i, j, wpls, wpld, rval, gval, bval;
1907 l_int32 *rlut, *glut, *blut;
1908 l_uint32 *datas, *datad, *lines, *lined;
1909 l_float32 fi;
1910 PIX *pixd;
1911 
1912  if (!pixs)
1913  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1914  if (pixGetDepth(pixs) != 32)
1915  return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
1916  if (rfract < -1.0 || rfract > 1.0)
1917  return (PIX *)ERROR_PTR("rfract not in [-1.0, 1.0]", __func__, NULL);
1918  if (gfract < -1.0 || gfract > 1.0)
1919  return (PIX *)ERROR_PTR("gfract not in [-1.0, 1.0]", __func__, NULL);
1920  if (bfract < -1.0 || bfract > 1.0)
1921  return (PIX *)ERROR_PTR("bfract not in [-1.0, 1.0]", __func__, NULL);
1922  if (rfract == 0.0 && gfract == 0.0 && bfract == 0.0)
1923  return pixCopy(NULL, pixs);
1924 
1925  rlut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1926  glut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1927  blut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1928  for (i = 0; i < 256; i++) {
1929  fi = i;
1930  if (rfract >= 0) {
1931  rlut[i] = (l_int32)(fi + (255.0 - fi) * rfract);
1932  } else {
1933  rlut[i] = (l_int32)(fi * (1.0 + rfract));
1934  }
1935  if (gfract >= 0) {
1936  glut[i] = (l_int32)(fi + (255.0 - fi) * gfract);
1937  } else {
1938  glut[i] = (l_int32)(fi * (1.0 + gfract));
1939  }
1940  if (bfract >= 0) {
1941  blut[i] = (l_int32)(fi + (255.0 - fi) * bfract);
1942  } else {
1943  blut[i] = (l_int32)(fi * (1.0 + bfract));
1944  }
1945  }
1946 
1947  pixGetDimensions(pixs, &w, &h, NULL);
1948  datas = pixGetData(pixs);
1949  wpls = pixGetWpl(pixs);
1950  pixd = pixCreate(w, h, 32);
1951  datad = pixGetData(pixd);
1952  wpld = pixGetWpl(pixd);
1953  for (i = 0; i < h; i++) {
1954  lines = datas + i * wpls;
1955  lined = datad + i * wpld;
1956  for (j = 0; j < w; j++) {
1957  extractRGBValues(lines[j], &rval, &gval, &bval);
1958  composeRGBPixel(rlut[rval], glut[gval], blut[bval], lined + j);
1959  }
1960  }
1961 
1962  LEPT_FREE(rlut);
1963  LEPT_FREE(glut);
1964  LEPT_FREE(blut);
1965  return pixd;
1966 }
1967 
1968 /*-----------------------------------------------------------------------*
1969  * Darken gray (unsaturated) pixels
1970  *-----------------------------------------------------------------------*/
1997 PIX *
1999  PIX *pixs,
2000  l_int32 thresh,
2001  l_int32 satlimit)
2002 {
2003 l_int32 w, h, i, j, wpls, wpld;
2004 l_int32 rval, gval, bval, minrg, min, maxrg, max, sat;
2005 l_uint32 *datas, *datad, *lines, *lined;
2006 l_float32 ratio;
2007 
2008  if (!pixs || pixGetDepth(pixs) != 32)
2009  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
2010  if (thresh < 0 || thresh > 255)
2011  return (PIX *)ERROR_PTR("invalid thresh", __func__, NULL);
2012  if (satlimit < 1)
2013  return (PIX *)ERROR_PTR("invalid satlimit", __func__, NULL);
2014  if (pixd && (pixs != pixd))
2015  return (PIX *)ERROR_PTR("not new or in-place", __func__, NULL);
2016 
2017  pixGetDimensions(pixs, &w, &h, NULL);
2018  datas = pixGetData(pixs);
2019  wpls = pixGetWpl(pixs);
2020  if ((pixd = pixCopy(pixd, pixs)) == NULL)
2021  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2022  datad = pixGetData(pixd);
2023  wpld = pixGetWpl(pixd);
2024 
2025  for (i = 0; i < h; i++) {
2026  lines = datas + i * wpls;
2027  lined = datad + i * wpld;
2028  for (j = 0; j < w; j++) {
2029  extractRGBValues(lines[j], &rval, &gval, &bval);
2030  minrg = L_MIN(rval, gval);
2031  min = L_MIN(minrg, bval);
2032  maxrg = L_MAX(rval, gval);
2033  max = L_MAX(maxrg, bval);
2034  sat = max - min;
2035  if (max >= thresh || sat >= satlimit)
2036  continue;
2037  ratio = (l_float32)sat / (l_float32)satlimit;
2038  composeRGBPixel((l_int32)(ratio * rval), (l_int32)(ratio * gval),
2039  (l_int32)(ratio * bval), &lined[j]);
2040  }
2041  }
2042  return pixd;
2043 }
2044 
2045 
2046 /*-----------------------------------------------------------------------*
2047  * General multiplicative constant color transform *
2048  *-----------------------------------------------------------------------*/
2067 PIX *
2069  l_float32 rfact,
2070  l_float32 gfact,
2071  l_float32 bfact)
2072 {
2073 l_int32 i, j, w, h, d, wpls, wpld;
2074 l_int32 ncolors, rval, gval, bval, nrval, ngval, nbval;
2075 l_uint32 nval;
2076 l_uint32 *datas, *datad, *lines, *lined;
2077 PIX *pixd;
2078 PIXCMAP *cmap;
2079 
2080  if (!pixs)
2081  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2082  pixGetDimensions(pixs, &w, &h, &d);
2083  cmap = pixGetColormap(pixs);
2084  if (!cmap && d != 32)
2085  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", __func__, NULL);
2086  rfact = L_MAX(0.0, rfact);
2087  gfact = L_MAX(0.0, gfact);
2088  bfact = L_MAX(0.0, bfact);
2089 
2090  if (cmap) {
2091  if ((pixd = pixCopy(NULL, pixs)) == NULL)
2092  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2093  cmap = pixGetColormap(pixd);
2094  ncolors = pixcmapGetCount(cmap);
2095  for (i = 0; i < ncolors; i++) {
2096  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2097  nrval = (l_int32)(rfact * rval);
2098  ngval = (l_int32)(gfact * gval);
2099  nbval = (l_int32)(bfact * bval);
2100  nrval = L_MIN(255, nrval);
2101  ngval = L_MIN(255, ngval);
2102  nbval = L_MIN(255, nbval);
2103  pixcmapResetColor(cmap, i, nrval, ngval, nbval);
2104  }
2105  return pixd;
2106  }
2107 
2108  if ((pixd = pixCreateTemplate(pixs)) == NULL)
2109  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2110  datas = pixGetData(pixs);
2111  datad = pixGetData(pixd);
2112  wpls = pixGetWpl(pixs);
2113  wpld = pixGetWpl(pixd);
2114  for (i = 0; i < h; i++) {
2115  lines = datas + i * wpls;
2116  lined = datad + i * wpld;
2117  for (j = 0; j < w; j++) {
2118  extractRGBValues(lines[j], &rval, &gval, &bval);
2119  nrval = (l_int32)(rfact * rval);
2120  ngval = (l_int32)(gfact * gval);
2121  nbval = (l_int32)(bfact * bval);
2122  nrval = L_MIN(255, nrval);
2123  ngval = L_MIN(255, ngval);
2124  nbval = L_MIN(255, nbval);
2125  composeRGBPixel(nrval, ngval, nbval, &nval);
2126  *(lined + j) = nval;
2127  }
2128  }
2129 
2130  return pixd;
2131 }
2132 
2133 
2167 PIX *
2169  L_KERNEL *kel)
2170 {
2171 l_int32 i, j, index, kw, kh, w, h, d, wpls, wpld;
2172 l_int32 ncolors, rval, gval, bval, nrval, ngval, nbval;
2173 l_uint32 nval;
2174 l_uint32 *datas, *datad, *lines, *lined;
2175 l_float32 v[9]; /* use linear array for convenience */
2176 PIX *pixd;
2177 PIXCMAP *cmap;
2178 
2179  if (!pixs)
2180  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2181  if (!kel)
2182  return (PIX *)ERROR_PTR("kel not defined", __func__, NULL);
2183  kernelGetParameters(kel, &kw, &kh, NULL, NULL);
2184  if (kw != 3 || kh != 3)
2185  return (PIX *)ERROR_PTR("matrix not 3x3", __func__, NULL);
2186  pixGetDimensions(pixs, &w, &h, &d);
2187  cmap = pixGetColormap(pixs);
2188  if (!cmap && d != 32)
2189  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", __func__, NULL);
2190 
2191  for (i = 0, index = 0; i < 3; i++)
2192  for (j = 0; j < 3; j++, index++)
2193  kernelGetElement(kel, i, j, v + index);
2194 
2195  if (cmap) {
2196  if ((pixd = pixCopy(NULL, pixs)) == NULL)
2197  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2198  cmap = pixGetColormap(pixd);
2199  ncolors = pixcmapGetCount(cmap);
2200  for (i = 0; i < ncolors; i++) {
2201  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2202  nrval = (l_int32)(v[0] * rval + v[1] * gval + v[2] * bval);
2203  ngval = (l_int32)(v[3] * rval + v[4] * gval + v[5] * bval);
2204  nbval = (l_int32)(v[6] * rval + v[7] * gval + v[8] * bval);
2205  nrval = L_MAX(0, L_MIN(255, nrval));
2206  ngval = L_MAX(0, L_MIN(255, ngval));
2207  nbval = L_MAX(0, L_MIN(255, nbval));
2208  pixcmapResetColor(cmap, i, nrval, ngval, nbval);
2209  }
2210  return pixd;
2211  }
2212 
2213  if ((pixd = pixCreateTemplate(pixs)) == NULL)
2214  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2215  datas = pixGetData(pixs);
2216  datad = pixGetData(pixd);
2217  wpls = pixGetWpl(pixs);
2218  wpld = pixGetWpl(pixd);
2219  for (i = 0; i < h; i++) {
2220  lines = datas + i * wpls;
2221  lined = datad + i * wpld;
2222  for (j = 0; j < w; j++) {
2223  extractRGBValues(lines[j], &rval, &gval, &bval);
2224  nrval = (l_int32)(v[0] * rval + v[1] * gval + v[2] * bval);
2225  ngval = (l_int32)(v[3] * rval + v[4] * gval + v[5] * bval);
2226  nbval = (l_int32)(v[6] * rval + v[7] * gval + v[8] * bval);
2227  nrval = L_MAX(0, L_MIN(255, nrval));
2228  ngval = L_MAX(0, L_MIN(255, ngval));
2229  nbval = L_MAX(0, L_MIN(255, nbval));
2230  composeRGBPixel(nrval, ngval, nbval, &nval);
2231  *(lined + j) = nval;
2232  }
2233  }
2234 
2235  return pixd;
2236 }
2237 
2238 
2239 /*-------------------------------------------------------------*
2240  * Half-edge by bandpass *
2241  *-------------------------------------------------------------*/
2274 PIX *
2276  l_int32 sm1h,
2277  l_int32 sm1v,
2278  l_int32 sm2h,
2279  l_int32 sm2v)
2280 {
2281 l_int32 d;
2282 PIX *pixg, *pixacc, *pixc1, *pixc2;
2283 
2284  if (!pixs)
2285  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2286  if (sm1h == sm2h && sm1v == sm2v)
2287  return (PIX *)ERROR_PTR("sm2 = sm1", __func__, NULL);
2288  d = pixGetDepth(pixs);
2289  if (d != 8 && d != 32)
2290  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", __func__, NULL);
2291  if (d == 32)
2292  pixg = pixConvertRGBToLuminance(pixs);
2293  else /* d == 8 */
2294  pixg = pixClone(pixs);
2295 
2296  /* Make a convolution accumulator and use it twice */
2297  if ((pixacc = pixBlockconvAccum(pixg)) == NULL) {
2298  pixDestroy(&pixg);
2299  return (PIX *)ERROR_PTR("pixacc not made", __func__, NULL);
2300  }
2301  if ((pixc1 = pixBlockconvGray(pixg, pixacc, sm1h, sm1v)) == NULL) {
2302  pixDestroy(&pixg);
2303  pixDestroy(&pixacc);
2304  return (PIX *)ERROR_PTR("pixc1 not made", __func__, NULL);
2305  }
2306  pixc2 = pixBlockconvGray(pixg, pixacc, sm2h, sm2v);
2307  pixDestroy(&pixg);
2308  pixDestroy(&pixacc);
2309  if (!pixc2) {
2310  pixDestroy(&pixc1);
2311  return (PIX *)ERROR_PTR("pixc2 not made", __func__, NULL);
2312  }
2313 
2314  /* Compute the half-edge using pixc1 - pixc2. */
2315  pixSubtractGray(pixc1, pixc1, pixc2);
2316  pixDestroy(&pixc2);
2317  return pixc1;
2318 }
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:168
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:118
l_ok pixcmapContrastTRC(PIXCMAP *cmap, l_float32 factor)
pixcmapContrastTRC()
Definition: colormap.c:2286
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:683
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
Definition: colormap.c:923
l_ok pixcmapGammaTRC(PIXCMAP *cmap, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixcmapGammaTRC()
Definition: colormap.c:2233
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:789
l_ok convertHSVToRGB(l_int32 hval, l_int32 sval, l_int32 vval, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
convertHSVToRGB()
Definition: colorspace.c:337
l_ok convertRGBToHSV(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *phval, l_int32 *psval, l_int32 *pvval)
convertRGBToHSV()
Definition: colorspace.c:277
PIX * pixBlockconvGray(PIX *pixs, PIX *pixacc, l_int32 wc, l_int32 hc)
pixBlockconvGray()
Definition: convolve.c:214
PIX * pixBlockconvAccum(PIX *pixs)
pixBlockconvAccum()
Definition: convolve.c:454
l_int32 pixMeasureSaturation(PIX *pixs, l_int32 factor, l_float32 *psat)
pixMeasureSaturation()
Definition: enhance.c:1658
NUMA * numaContrastTRC(l_float32 factor)
numaContrastTRC()
Definition: enhance.c:548
PIX * pixHalfEdgeByBandpass(PIX *pixs, l_int32 sm1h, l_int32 sm1v, l_int32 sm2h, l_int32 sm2v)
pixHalfEdgeByBandpass()
Definition: enhance.c:2275
PIX * pixModifyHue(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifyHue()
Definition: enhance.c:1533
PIX * pixEqualizeTRC(PIX *pixd, PIX *pixs, l_float32 fract, l_int32 factor)
pixEqualizeTRC()
Definition: enhance.c:616
PIX * pixDarkenGray(PIX *pixd, PIX *pixs, l_int32 thresh, l_int32 satlimit)
pixDarkenGray()
Definition: enhance.c:1998
PIX * pixUnsharpMaskingGrayFast(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingGrayFast()
Definition: enhance.c:1210
NUMA * numaGammaTRC(l_float32 gamma, l_int32 minval, l_int32 maxval)
numaGammaTRC()
Definition: enhance.c:363
PIX * pixColorShiftRGB(PIX *pixs, l_float32 rfract, l_float32 gfract, l_float32 bfract)
pixColorShiftRGB()
Definition: enhance.c:1901
PIX * pixContrastTRC(PIX *pixd, PIX *pixs, l_float32 factor)
pixContrastTRC()
Definition: enhance.c:431
PIX * pixUnsharpMaskingFast(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingFast()
Definition: enhance.c:1141
PIX * pixModifySaturation(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifySaturation()
Definition: enhance.c:1605
PIX * pixMultMatrixColor(PIX *pixs, L_KERNEL *kel)
pixMultMatrixColor()
Definition: enhance.c:2168
PIX * pixMultConstantColor(PIX *pixs, l_float32 rfact, l_float32 gfact, l_float32 bfact)
pixMultConstantColor()
Definition: enhance.c:2068
l_int32 pixTRCMap(PIX *pixs, PIX *pixm, NUMA *na)
pixTRCMap()
Definition: enhance.c:766
PIX * pixGammaTRC(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRC()
Definition: enhance.c:176
PIX * pixContrastTRCMasked(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 factor)
pixContrastTRCMasked()
Definition: enhance.c:491
PIX * pixMosaicColorShiftRGB(PIX *pixs, l_float32 roff, l_float32 goff, l_float32 boff, l_float32 delta, l_int32 nincr)
pixMosaicColorShiftRGB()
Definition: enhance.c:1797
l_int32 pixTRCMapGeneral(PIX *pixs, PIX *pixm, NUMA *nar, NUMA *nag, NUMA *nab)
pixTRCMapGeneral()
Definition: enhance.c:886
PIX * pixModifyBrightness(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifyBrightness()
Definition: enhance.c:1718
PIX * pixGammaTRCWithAlpha(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRCWithAlpha()
Definition: enhance.c:304
PIX * pixUnsharpMaskingGray2D(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMaskingGray2D()
Definition: enhance.c:1389
PIX * pixUnsharpMaskingGray(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMaskingGray()
Definition: enhance.c:1046
NUMA * numaEqualizeTRC(PIX *pix, l_float32 fract, l_int32 factor)
numaEqualizeTRC()
Definition: enhance.c:701
PIX * pixUnsharpMaskingGray1D(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingGray1D()
Definition: enhance.c:1257
PIX * pixGammaTRCMasked(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRCMasked()
Definition: enhance.c:242
PIX * pixUnsharpMasking(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMasking()
Definition: enhance.c:979
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:357
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:280
FPIX * fpixCreate(l_int32 width, l_int32 height)
fpixCreate()
Definition: fpix1.c:152
l_float32 * fpixGetData(FPIX *fpix)
fpixGetData()
Definition: fpix1.c:452
l_ok kernelGetParameters(L_KERNEL *kel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
kernelGetParameters()
Definition: kernel.c:264
l_ok kernelGetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 *pval)
kernelGetElement()
Definition: kernel.c:209
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:687
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:807
NUMA * numaGetPartialSums(NUMA *na)
numaGetPartialSums()
Definition: numafunc1.c:564
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:792
l_ok numaGetSum(NUMA *na, l_float32 *psum)
numaGetSum()
Definition: numafunc1.c:525
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
l_ok pixMaxAspectRatio(PIX *pixs, l_float32 *pratio)
pixMaxAspectRatio()
Definition: pix1.c:1904
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2464
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2410
l_ok pixCopyRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixCopyRGBComponent()
Definition: pix2.c:2669
PIX * pixCopyBorder(PIX *pixd, PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixCopyBorder()
Definition: pix2.c:1721
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2728
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2793
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2521
NUMA * pixGetGrayHistogram(PIX *pixs, l_int32 factor)
pixGetGrayHistogram()
Definition: pix4.c:115
@ COLOR_BLUE
Definition: pix.h:330
@ COLOR_RED
Definition: pix.h:328
@ L_ALPHA_CHANNEL
Definition: pix.h:331
@ COLOR_GREEN
Definition: pix.h:329
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:384
@ L_ADD_BELOW
Definition: pix.h:1003
@ L_CLONE
Definition: pix.h:506
@ L_INSERT
Definition: pix.h:504
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:404
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
PIX * pixaccFinal(PIXACC *pixacc, l_int32 outdepth)
pixaccFinal()
Definition: pixacc.c:188
l_ok pixaccSubtract(PIXACC *pixacc, PIX *pix)
pixaccSubtract()
Definition: pixacc.c:263
l_ok pixaccAdd(PIXACC *pixacc, PIX *pix)
pixaccAdd()
Definition: pixacc.c:243
void pixaccDestroy(PIXACC **ppixacc)
pixaccDestroy()
Definition: pixacc.c:159
PIXACC * pixaccCreate(l_int32 w, l_int32 h, l_int32 negflag)
pixaccCreate()
Definition: pixacc.c:93
l_ok pixaccMultConst(PIXACC *pixacc, l_float32 factor)
pixaccMultConst()
Definition: pixacc.c:283
PIX * pixaDisplayTiledAndScaled(PIXA *pixa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledAndScaled()
Definition: pixafunc2.c:1025
PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtractGray()
Definition: pixarith.c:351
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition: pixconv.c:3400
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324
PIX * pixConvertRGBToLuminance(PIX *pixs)
pixConvertRGBToLuminance()
Definition: pixconv.c:732
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:319
Definition: bmf.h:47
Definition: morph.h:89
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120