Leptonica  1.82.0
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  PROCNAME("pixGammaTRC");
187 
188  if (!pixs)
189  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
190  if (pixd && (pixd != pixs))
191  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
192  if (gamma <= 0.0) {
193  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
194  gamma = 1.0;
195  }
196  if (minval >= maxval)
197  return (PIX *)ERROR_PTR("minval not < maxval", procName, pixd);
198  cmap = pixGetColormap(pixs);
199  d = pixGetDepth(pixs);
200  if (!cmap && d != 8 && d != 32)
201  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
202 
203  if (gamma == 1.0 && minval == 0 && maxval == 255) /* no-op */
204  return pixCopy(pixd, pixs);
205 
206  if (!pixd) /* start with a copy if not in-place */
207  pixd = pixCopy(NULL, pixs);
208 
209  if (cmap) {
210  pixcmapGammaTRC(pixGetColormap(pixd), gamma, minval, maxval);
211  return pixd;
212  }
213 
214  /* pixd is 8 or 32 bpp */
215  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
216  return (PIX *)ERROR_PTR("nag not made", procName, pixd);
217  pixTRCMap(pixd, NULL, nag);
218  numaDestroy(&nag);
219 
220  return pixd;
221 }
222 
223 
243 PIX *
245  PIX *pixs,
246  PIX *pixm,
247  l_float32 gamma,
248  l_int32 minval,
249  l_int32 maxval)
250 {
251 l_int32 d;
252 NUMA *nag;
253 
254  PROCNAME("pixGammaTRCMasked");
255 
256  if (!pixm)
257  return pixGammaTRC(pixd, pixs, gamma, minval, maxval);
258 
259  if (!pixs)
260  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
261  if (pixGetColormap(pixs))
262  return (PIX *)ERROR_PTR("invalid: pixs has a colormap", procName, pixd);
263  if (pixd && (pixd != pixs))
264  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
265  d = pixGetDepth(pixs);
266  if (d != 8 && d != 32)
267  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
268  if (minval >= maxval)
269  return (PIX *)ERROR_PTR("minval not < maxval", procName, pixd);
270  if (gamma <= 0.0) {
271  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
272  gamma = 1.0;
273  }
274 
275  if (gamma == 1.0 && minval == 0 && maxval == 255)
276  return pixCopy(pixd, pixs);
277 
278  if (!pixd) /* start with a copy if not in-place */
279  pixd = pixCopy(NULL, pixs);
280 
281  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
282  return (PIX *)ERROR_PTR("nag not made", procName, pixd);
283  pixTRCMap(pixd, pixm, nag);
284  numaDestroy(&nag);
285 
286  return pixd;
287 }
288 
289 
307 PIX *
309  PIX *pixs,
310  l_float32 gamma,
311  l_int32 minval,
312  l_int32 maxval)
313 {
314 NUMA *nag;
315 PIX *pixalpha;
316 
317  PROCNAME("pixGammaTRCWithAlpha");
318 
319  if (!pixs || pixGetDepth(pixs) != 32)
320  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, pixd);
321  if (pixd && (pixd != pixs))
322  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
323  if (gamma <= 0.0) {
324  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
325  gamma = 1.0;
326  }
327  if (minval >= maxval)
328  return (PIX *)ERROR_PTR("minval not < maxval", procName, pixd);
329 
330  if (gamma == 1.0 && minval == 0 && maxval == 255)
331  return pixCopy(pixd, pixs);
332  if (!pixd) /* start with a copy if not in-place */
333  pixd = pixCopy(NULL, pixs);
334 
335  pixalpha = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL); /* save */
336  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
337  return (PIX *)ERROR_PTR("nag not made", procName, pixd);
338  pixTRCMap(pixd, NULL, nag);
339  pixSetRGBComponent(pixd, pixalpha, L_ALPHA_CHANNEL); /* restore */
340  pixSetSpp(pixd, 4);
341 
342  numaDestroy(&nag);
343  pixDestroy(&pixalpha);
344  return pixd;
345 }
346 
347 
368 NUMA *
369 numaGammaTRC(l_float32 gamma,
370  l_int32 minval,
371  l_int32 maxval)
372 {
373 l_int32 i, val;
374 l_float32 x, invgamma;
375 NUMA *na;
376 
377  PROCNAME("numaGammaTRC");
378 
379  if (minval >= maxval)
380  return (NUMA *)ERROR_PTR("minval not < maxval", procName, NULL);
381  if (gamma <= 0.0) {
382  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
383  gamma = 1.0;
384  }
385 
386  invgamma = 1. / gamma;
387  na = numaCreate(256);
388  for (i = 0; i < minval; i++)
389  numaAddNumber(na, 0);
390  for (i = minval; i <= maxval; i++) {
391  if (i < 0) continue;
392  if (i > 255) continue;
393  x = (l_float32)(i - minval) / (l_float32)(maxval - minval);
394  val = (l_int32)(255. * powf(x, invgamma) + 0.5);
395  val = L_MAX(val, 0);
396  val = L_MIN(val, 255);
397  numaAddNumber(na, val);
398  }
399  for (i = maxval + 1; i < 256; i++)
400  numaAddNumber(na, 255);
401 
402  return na;
403 }
404 
405 
406 /*-------------------------------------------------------------*
407  * Contrast enhancement *
408  *-------------------------------------------------------------*/
438 PIX *
440  PIX *pixs,
441  l_float32 factor)
442 {
443 l_int32 d;
444 NUMA *nac;
445 PIXCMAP *cmap;
446 
447  PROCNAME("pixContrastTRC");
448 
449  if (!pixs)
450  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
451  if (pixd && (pixd != pixs))
452  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
453  if (factor < 0.0) {
454  L_WARNING("factor must be >= 0.0; using 0.0\n", procName);
455  factor = 0.0;
456  }
457  if (factor == 0.0)
458  return pixCopy(pixd, pixs);
459 
460  cmap = pixGetColormap(pixs);
461  d = pixGetDepth(pixs);
462  if (!cmap && d != 8 && d != 32)
463  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
464 
465  if (!pixd) /* start with a copy if not in-place */
466  pixd = pixCopy(NULL, pixs);
467 
468  if (cmap) {
469  pixcmapContrastTRC(pixGetColormap(pixd), factor);
470  return pixd;
471  }
472 
473  /* pixd is 8 or 32 bpp */
474  if ((nac = numaContrastTRC(factor)) == NULL)
475  return (PIX *)ERROR_PTR("nac not made", procName, pixd);
476  pixTRCMap(pixd, NULL, nac);
477  numaDestroy(&nac);
478 
479  return pixd;
480 }
481 
482 
500 PIX *
502  PIX *pixs,
503  PIX *pixm,
504  l_float32 factor)
505 {
506 l_int32 d;
507 NUMA *nac;
508 
509  PROCNAME("pixContrastTRCMasked");
510 
511  if (!pixm)
512  return pixContrastTRC(pixd, pixs, factor);
513 
514  if (!pixs)
515  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
516  if (pixGetColormap(pixs))
517  return (PIX *)ERROR_PTR("invalid: pixs has a colormap", procName, pixd);
518  if (pixd && (pixd != pixs))
519  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
520  d = pixGetDepth(pixs);
521  if (d != 8 && d != 32)
522  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
523 
524  if (factor < 0.0) {
525  L_WARNING("factor must be >= 0.0; using 0.0\n", procName);
526  factor = 0.0;
527  }
528  if (factor == 0.0)
529  return pixCopy(pixd, pixs);
530 
531  if (!pixd) /* start with a copy if not in-place */
532  pixd = pixCopy(NULL, pixs);
533 
534  if ((nac = numaContrastTRC(factor)) == NULL)
535  return (PIX *)ERROR_PTR("nac not made", procName, pixd);
536  pixTRCMap(pixd, pixm, nac);
537  numaDestroy(&nac);
538 
539  return pixd;
540 }
541 
542 
559 NUMA *
560 numaContrastTRC(l_float32 factor)
561 {
562 l_int32 i, val;
563 l_float64 x, ymax, ymin, dely, scale;
564 NUMA *na;
565 
566  PROCNAME("numaContrastTRC");
567 
568  if (factor < 0.0) {
569  L_WARNING("factor must be >= 0.0; using 0.0; no enhancement\n",
570  procName);
571  factor = 0.0;
572  }
573  if (factor == 0.0)
574  return numaMakeSequence(0, 1, 256); /* linear map */
575 
576  scale = EnhanceScaleFactor;
577  ymax = atan((l_float64)(1.0 * factor * scale));
578  ymin = atan((l_float64)(-127. * factor * scale / 128.));
579  dely = ymax - ymin;
580  na = numaCreate(256);
581  for (i = 0; i < 256; i++) {
582  x = (l_float64)i;
583  val = (l_int32)((255. / dely) *
584  (-ymin + atan((l_float64)(factor * scale * (x - 127.) / 128.))) +
585  0.5);
586  numaAddNumber(na, val);
587  }
588 
589  return na;
590 }
591 
592 
593 /*-------------------------------------------------------------*
594  * Histogram equalization *
595  *-------------------------------------------------------------*/
629 PIX *
631  PIX *pixs,
632  l_float32 fract,
633  l_int32 factor)
634 {
635 l_int32 d;
636 NUMA *na;
637 PIX *pixt, *pix8;
638 PIXCMAP *cmap;
639 
640  PROCNAME("pixEqualizeTRC");
641 
642  if (!pixs)
643  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
644  if (pixd && (pixd != pixs))
645  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
646  cmap = pixGetColormap(pixs);
647  d = pixGetDepth(pixs);
648  if (d != 8 && d != 32 && !cmap)
649  return (PIX *)ERROR_PTR("pixs not 8/32 bpp or cmapped", procName, NULL);
650  if (fract < 0.0 || fract > 1.0)
651  return (PIX *)ERROR_PTR("fract not in [0.0 ... 1.0]", procName, NULL);
652  if (factor < 1)
653  return (PIX *)ERROR_PTR("sampling factor < 1", procName, NULL);
654 
655  if (fract == 0.0)
656  return pixCopy(pixd, pixs);
657 
658  /* If there is a colormap, remove it. */
659  if (cmap)
661  else
662  pixt = pixClone(pixs);
663 
664  /* Make a copy if necessary */
665  pixd = pixCopy(pixd, pixt);
666  pixDestroy(&pixt);
667 
668  d = pixGetDepth(pixd);
669  if (d == 8) {
670  na = numaEqualizeTRC(pixd, fract, factor);
671  pixTRCMap(pixd, NULL, na);
672  numaDestroy(&na);
673  } else { /* 32 bpp */
674  pix8 = pixGetRGBComponent(pixd, COLOR_RED);
675  na = numaEqualizeTRC(pix8, fract, factor);
676  pixTRCMap(pix8, NULL, na);
677  pixSetRGBComponent(pixd, pix8, COLOR_RED);
678  numaDestroy(&na);
679  pixDestroy(&pix8);
680  pix8 = pixGetRGBComponent(pixd, COLOR_GREEN);
681  na = numaEqualizeTRC(pix8, fract, factor);
682  pixTRCMap(pix8, NULL, na);
683  pixSetRGBComponent(pixd, pix8, COLOR_GREEN);
684  numaDestroy(&na);
685  pixDestroy(&pix8);
686  pix8 = pixGetRGBComponent(pixd, COLOR_BLUE);
687  na = numaEqualizeTRC(pix8, fract, factor);
688  pixTRCMap(pix8, NULL, na);
689  pixSetRGBComponent(pixd, pix8, COLOR_BLUE);
690  numaDestroy(&na);
691  pixDestroy(&pix8);
692  }
693 
694  return pixd;
695 }
696 
697 
716 NUMA *
718  l_float32 fract,
719  l_int32 factor)
720 {
721 l_int32 iin, iout, itarg;
722 l_float32 val, sum;
723 NUMA *nah, *nasum, *nad;
724 
725  PROCNAME("numaEqualizeTRC");
726 
727  if (!pix)
728  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
729  if (pixGetDepth(pix) != 8)
730  return (NUMA *)ERROR_PTR("pix not 8 bpp", procName, NULL);
731  if (fract < 0.0 || fract > 1.0)
732  return (NUMA *)ERROR_PTR("fract not in [0.0 ... 1.0]", procName, NULL);
733  if (factor < 1)
734  return (NUMA *)ERROR_PTR("sampling factor < 1", procName, NULL);
735 
736  if (fract == 0.0)
737  L_WARNING("fract = 0.0; no equalization requested\n", procName);
738 
739  if ((nah = pixGetGrayHistogram(pix, factor)) == NULL)
740  return (NUMA *)ERROR_PTR("histogram not made", procName, NULL);
741  numaGetSum(nah, &sum);
742  nasum = numaGetPartialSums(nah);
743 
744  nad = numaCreate(256);
745  for (iin = 0; iin < 256; iin++) {
746  numaGetFValue(nasum, iin, &val);
747  itarg = (l_int32)(255. * val / sum + 0.5);
748  iout = iin + (l_int32)(fract * (itarg - iin));
749  iout = L_MIN(iout, 255); /* to be safe */
750  numaAddNumber(nad, iout);
751  }
752 
753  numaDestroy(&nah);
754  numaDestroy(&nasum);
755  return nad;
756 }
757 
758 
759 /*-------------------------------------------------------------*
760  * Generic TRC mapping *
761  *-------------------------------------------------------------*/
783 l_int32
785  PIX *pixm,
786  NUMA *na)
787 {
788 l_int32 w, h, d, wm, hm, wpl, wplm, i, j, sval8, dval8;
789 l_uint32 sval32, dval32;
790 l_uint32 *data, *datam, *line, *linem, *tab;
791 
792  PROCNAME("pixTRCMap");
793 
794  if (!pixs)
795  return ERROR_INT("pixs not defined", procName, 1);
796  if (pixGetColormap(pixs))
797  return ERROR_INT("pixs is colormapped", procName, 1);
798  if (!na)
799  return ERROR_INT("na not defined", procName, 1);
800  if (numaGetCount(na) != 256)
801  return ERROR_INT("na not of size 256", procName, 1);
802  pixGetDimensions(pixs, &w, &h, &d);
803  if (d != 8 && d != 32)
804  return ERROR_INT("pixs not 8 or 32 bpp", procName, 1);
805  if (pixm) {
806  if (pixGetDepth(pixm) != 1)
807  return ERROR_INT("pixm not 1 bpp", procName, 1);
808  }
809 
810  tab = (l_uint32 *)numaGetIArray(na); /* get the array for efficiency */
811  wpl = pixGetWpl(pixs);
812  data = pixGetData(pixs);
813  if (!pixm) {
814  if (d == 8) {
815  for (i = 0; i < h; i++) {
816  line = data + i * wpl;
817  for (j = 0; j < w; j++) {
818  sval8 = GET_DATA_BYTE(line, j);
819  dval8 = tab[sval8];
820  SET_DATA_BYTE(line, j, dval8);
821  }
822  }
823  } else { /* d == 32 */
824  for (i = 0; i < h; i++) {
825  line = data + i * wpl;
826  for (j = 0; j < w; j++) {
827  sval32 = *(line + j);
828  dval32 =
829  tab[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
830  tab[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
831  tab[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
832  *(line + j) = dval32;
833  }
834  }
835  }
836  } else {
837  datam = pixGetData(pixm);
838  wplm = pixGetWpl(pixm);
839  pixGetDimensions(pixm, &wm, &hm, NULL);
840  if (d == 8) {
841  for (i = 0; i < h; i++) {
842  if (i >= hm)
843  break;
844  line = data + i * wpl;
845  linem = datam + i * wplm;
846  for (j = 0; j < w; j++) {
847  if (j >= wm)
848  break;
849  if (GET_DATA_BIT(linem, j) == 0)
850  continue;
851  sval8 = GET_DATA_BYTE(line, j);
852  dval8 = tab[sval8];
853  SET_DATA_BYTE(line, j, dval8);
854  }
855  }
856  } else { /* d == 32 */
857  for (i = 0; i < h; i++) {
858  if (i >= hm)
859  break;
860  line = data + i * wpl;
861  linem = datam + i * wplm;
862  for (j = 0; j < w; j++) {
863  if (j >= wm)
864  break;
865  if (GET_DATA_BIT(linem, j) == 0)
866  continue;
867  sval32 = *(line + j);
868  dval32 =
869  tab[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
870  tab[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
871  tab[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
872  *(line + j) = dval32;
873  }
874  }
875  }
876  }
877 
878  LEPT_FREE(tab);
879  return 0;
880 }
881 
882 
905 l_int32
907  PIX *pixm,
908  NUMA *nar,
909  NUMA *nag,
910  NUMA *nab)
911 {
912 l_int32 w, h, wm, hm, wpl, wplm, i, j;
913 l_uint32 sval32, dval32;
914 l_uint32 *data, *datam, *line, *linem, *tabr, *tabg, *tabb;
915 
916  PROCNAME("pixTRCMapGeneral");
917 
918  if (!pixs || pixGetDepth(pixs) != 32)
919  return ERROR_INT("pixs not defined or not 32 bpp", procName, 1);
920  if (pixm && pixGetDepth(pixm) != 1)
921  return ERROR_INT("pixm defined and not 1 bpp", procName, 1);
922  if (!nar || !nag || !nab)
923  return ERROR_INT("na{r,g,b} not all defined", procName, 1);
924  if (numaGetCount(nar) != 256 || numaGetCount(nag) != 256 ||
925  numaGetCount(nab) != 256)
926  return ERROR_INT("na{r,g,b} not all of size 256", procName, 1);
927 
928  /* Get the arrays for efficiency */
929  tabr = (l_uint32 *)numaGetIArray(nar);
930  tabg = (l_uint32 *)numaGetIArray(nag);
931  tabb = (l_uint32 *)numaGetIArray(nab);
932  pixGetDimensions(pixs, &w, &h, NULL);
933  wpl = pixGetWpl(pixs);
934  data = pixGetData(pixs);
935  if (!pixm) {
936  for (i = 0; i < h; i++) {
937  line = data + i * wpl;
938  for (j = 0; j < w; j++) {
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  } else {
948  datam = pixGetData(pixm);
949  wplm = pixGetWpl(pixm);
950  pixGetDimensions(pixm, &wm, &hm, NULL);
951  for (i = 0; i < h; i++) {
952  if (i >= hm)
953  break;
954  line = data + i * wpl;
955  linem = datam + i * wplm;
956  for (j = 0; j < w; j++) {
957  if (j >= wm)
958  break;
959  if (GET_DATA_BIT(linem, j) == 0)
960  continue;
961  sval32 = *(line + j);
962  dval32 =
963  tabr[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
964  tabg[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
965  tabb[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
966  *(line + j) = dval32;
967  }
968  }
969  }
970 
971  LEPT_FREE(tabr);
972  LEPT_FREE(tabg);
973  LEPT_FREE(tabb);
974  return 0;
975 }
976 
977 
978 
979 /*-----------------------------------------------------------------------*
980  * Unsharp masking *
981  *-----------------------------------------------------------------------*/
1000 PIX *
1002  l_int32 halfwidth,
1003  l_float32 fract)
1004 {
1005 l_int32 d;
1006 PIX *pix1, *pixd, *pixr, *pixrs, *pixg, *pixgs, *pixb, *pixbs;
1007 
1008  PROCNAME("pixUnsharpMasking");
1009 
1010  if (!pixs || (pixGetDepth(pixs) == 1))
1011  return (PIX *)ERROR_PTR("pixs not defined or 1 bpp", procName, NULL);
1012  if (fract <= 0.0 || halfwidth <= 0) {
1013  L_WARNING("no sharpening requested; clone returned\n", procName);
1014  return pixClone(pixs);
1015  }
1016 
1017  if (halfwidth == 1 || halfwidth == 2)
1018  return pixUnsharpMaskingFast(pixs, halfwidth, fract, L_BOTH_DIRECTIONS);
1019 
1020  /* Remove colormap; clone if possible; result is either 8 or 32 bpp */
1021  if ((pix1 = pixConvertTo8Or32(pixs, L_CLONE, 0)) == NULL)
1022  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1023 
1024  /* Sharpen */
1025  d = pixGetDepth(pix1);
1026  if (d == 8) {
1027  pixd = pixUnsharpMaskingGray(pix1, halfwidth, fract);
1028  } else { /* d == 32 */
1029  pixr = pixGetRGBComponent(pix1, COLOR_RED);
1030  pixrs = pixUnsharpMaskingGray(pixr, halfwidth, fract);
1031  pixDestroy(&pixr);
1032  pixg = pixGetRGBComponent(pix1, COLOR_GREEN);
1033  pixgs = pixUnsharpMaskingGray(pixg, halfwidth, fract);
1034  pixDestroy(&pixg);
1035  pixb = pixGetRGBComponent(pix1, COLOR_BLUE);
1036  pixbs = pixUnsharpMaskingGray(pixb, halfwidth, fract);
1037  pixDestroy(&pixb);
1038  pixd = pixCreateRGBImage(pixrs, pixgs, pixbs);
1039  pixDestroy(&pixrs);
1040  pixDestroy(&pixgs);
1041  pixDestroy(&pixbs);
1042  if (pixGetSpp(pixs) == 4)
1044  }
1045 
1046  pixDestroy(&pix1);
1047  return pixd;
1048 }
1049 
1050 
1069 PIX *
1071  l_int32 halfwidth,
1072  l_float32 fract)
1073 {
1074 l_int32 w, h, d;
1075 PIX *pixc, *pixd;
1076 PIXACC *pixacc;
1077 
1078  PROCNAME("pixUnsharpMaskingGray");
1079 
1080  if (!pixs)
1081  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1082  pixGetDimensions(pixs, &w, &h, &d);
1083  if (d != 8 || pixGetColormap(pixs) != NULL)
1084  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1085  if (fract <= 0.0 || halfwidth <= 0) {
1086  L_WARNING("no sharpening requested; clone returned\n", procName);
1087  return pixClone(pixs);
1088  }
1089  if (halfwidth == 1 || halfwidth == 2)
1090  return pixUnsharpMaskingGrayFast(pixs, halfwidth, fract,
1091  L_BOTH_DIRECTIONS);
1092 
1093  if ((pixc = pixBlockconvGray(pixs, NULL, halfwidth, halfwidth)) == NULL)
1094  return (PIX *)ERROR_PTR("pixc not made", procName, NULL);
1095 
1096  /* Steps:
1097  * (1) edge image is pixs - pixc (this is highpass part)
1098  * (2) multiply edge image by fract
1099  * (3) add fraction of edge to pixs
1100  *
1101  * To show how this is done with both interfaces to arithmetic
1102  * on integer Pix, here is the implementation in the lower-level
1103  * function calls:
1104  * pixt = pixInitAccumulate(w, h, 0x10000000)) == NULL)
1105  * pixAccumulate(pixt, pixs, L_ARITH_ADD);
1106  * pixAccumulate(pixt, pixc, L_ARITH_SUBTRACT);
1107  * pixMultConstAccumulate(pixt, fract, 0x10000000);
1108  * pixAccumulate(pixt, pixs, L_ARITH_ADD);
1109  * pixd = pixFinalAccumulate(pixt, 0x10000000, 8)) == NULL)
1110  * pixDestroy(&pixt);
1111  *
1112  * The code below does the same thing using the Pixacc accumulator,
1113  * hiding the details of the offset that is needed for subtraction.
1114  */
1115  pixacc = pixaccCreate(w, h, 1);
1116  pixaccAdd(pixacc, pixs);
1117  pixaccSubtract(pixacc, pixc);
1118  pixaccMultConst(pixacc, fract);
1119  pixaccAdd(pixacc, pixs);
1120  pixd = pixaccFinal(pixacc, 8);
1121  pixaccDestroy(&pixacc);
1122 
1123  pixDestroy(&pixc);
1124  return pixd;
1125 }
1126 
1127 
1166 PIX *
1168  l_int32 halfwidth,
1169  l_float32 fract,
1170  l_int32 direction)
1171 {
1172 l_int32 d;
1173 PIX *pixt, *pixd, *pixr, *pixrs, *pixg, *pixgs, *pixb, *pixbs;
1174 
1175  PROCNAME("pixUnsharpMaskingFast");
1176 
1177  if (!pixs || (pixGetDepth(pixs) == 1))
1178  return (PIX *)ERROR_PTR("pixs not defined or 1 bpp", procName, NULL);
1179  if (fract <= 0.0 || halfwidth <= 0) {
1180  L_WARNING("no sharpening requested; clone returned\n", procName);
1181  return pixClone(pixs);
1182  }
1183  if (halfwidth != 1 && halfwidth != 2)
1184  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1185  if (direction != L_HORIZ && direction != L_VERT &&
1186  direction != L_BOTH_DIRECTIONS)
1187  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1188 
1189  /* Remove colormap; clone if possible; result is either 8 or 32 bpp */
1190  if ((pixt = pixConvertTo8Or32(pixs, L_CLONE, 0)) == NULL)
1191  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
1192 
1193  /* Sharpen */
1194  d = pixGetDepth(pixt);
1195  if (d == 8) {
1196  pixd = pixUnsharpMaskingGrayFast(pixt, halfwidth, fract, direction);
1197  } else { /* d == 32 */
1199  pixrs = pixUnsharpMaskingGrayFast(pixr, halfwidth, fract, direction);
1200  pixDestroy(&pixr);
1202  pixgs = pixUnsharpMaskingGrayFast(pixg, halfwidth, fract, direction);
1203  pixDestroy(&pixg);
1205  pixbs = pixUnsharpMaskingGrayFast(pixb, halfwidth, fract, direction);
1206  pixDestroy(&pixb);
1207  pixd = pixCreateRGBImage(pixrs, pixgs, pixbs);
1208  if (pixGetSpp(pixs) == 4)
1210  pixDestroy(&pixrs);
1211  pixDestroy(&pixgs);
1212  pixDestroy(&pixbs);
1213  }
1214 
1215  pixDestroy(&pixt);
1216  return pixd;
1217 }
1218 
1219 
1220 
1237 PIX *
1239  l_int32 halfwidth,
1240  l_float32 fract,
1241  l_int32 direction)
1242 {
1243 PIX *pixd;
1244 
1245  PROCNAME("pixUnsharpMaskingGrayFast");
1246 
1247  if (!pixs)
1248  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1249  if (pixGetDepth(pixs) != 8 || pixGetColormap(pixs) != NULL)
1250  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1251  if (fract <= 0.0 || halfwidth <= 0) {
1252  L_WARNING("no sharpening requested; clone returned\n", procName);
1253  return pixClone(pixs);
1254  }
1255  if (halfwidth != 1 && halfwidth != 2)
1256  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1257  if (direction != L_HORIZ && direction != L_VERT &&
1258  direction != L_BOTH_DIRECTIONS)
1259  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1260 
1261  if (direction != L_BOTH_DIRECTIONS)
1262  pixd = pixUnsharpMaskingGray1D(pixs, halfwidth, fract, direction);
1263  else /* 2D sharpening */
1264  pixd = pixUnsharpMaskingGray2D(pixs, halfwidth, fract);
1265 
1266  return pixd;
1267 }
1268 
1269 
1286 PIX *
1288  l_int32 halfwidth,
1289  l_float32 fract,
1290  l_int32 direction)
1291 {
1292 l_int32 w, h, d, wpls, wpld, i, j, ival;
1293 l_uint32 *datas, *datad;
1294 l_uint32 *lines, *lines0, *lines1, *lines2, *lines3, *lines4, *lined;
1295 l_float32 val, a[5];
1296 PIX *pixd;
1297 
1298  PROCNAME("pixUnsharpMaskingGray1D");
1299 
1300  if (!pixs)
1301  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1302  pixGetDimensions(pixs, &w, &h, &d);
1303  if (d != 8 || pixGetColormap(pixs) != NULL)
1304  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1305  if (fract <= 0.0 || halfwidth <= 0) {
1306  L_WARNING("no sharpening requested; clone returned\n", procName);
1307  return pixClone(pixs);
1308  }
1309  if (halfwidth != 1 && halfwidth != 2)
1310  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1311 
1312  /* Initialize pixd with pixels from pixs that will not be
1313  * set when computing the sharpened values. */
1314  pixd = pixCopyBorder(NULL, pixs, halfwidth, halfwidth,
1315  halfwidth, halfwidth);
1316  datas = pixGetData(pixs);
1317  datad = pixGetData(pixd);
1318  wpls = pixGetWpl(pixs);
1319  wpld = pixGetWpl(pixd);
1320 
1321  if (halfwidth == 1) {
1322  a[0] = -fract / 3.0;
1323  a[1] = 1.0 + fract * 2.0 / 3.0;
1324  a[2] = a[0];
1325  } else { /* halfwidth == 2 */
1326  a[0] = -fract / 5.0;
1327  a[1] = a[0];
1328  a[2] = 1.0 + fract * 4.0 / 5.0;
1329  a[3] = a[0];
1330  a[4] = a[0];
1331  }
1332 
1333  if (direction == L_HORIZ) {
1334  for (i = 0; i < h; i++) {
1335  lines = datas + i * wpls;
1336  lined = datad + i * wpld;
1337  if (halfwidth == 1) {
1338  for (j = 1; j < w - 1; j++) {
1339  val = a[0] * GET_DATA_BYTE(lines, j - 1) +
1340  a[1] * GET_DATA_BYTE(lines, j) +
1341  a[2] * GET_DATA_BYTE(lines, j + 1);
1342  ival = (l_int32)val;
1343  ival = L_MAX(0, ival);
1344  ival = L_MIN(255, ival);
1345  SET_DATA_BYTE(lined, j, ival);
1346  }
1347  } else { /* halfwidth == 2 */
1348  for (j = 2; j < w - 2; j++) {
1349  val = a[0] * GET_DATA_BYTE(lines, j - 2) +
1350  a[1] * GET_DATA_BYTE(lines, j - 1) +
1351  a[2] * GET_DATA_BYTE(lines, j) +
1352  a[3] * GET_DATA_BYTE(lines, j + 1) +
1353  a[4] * GET_DATA_BYTE(lines, j + 2);
1354  ival = (l_int32)val;
1355  ival = L_MAX(0, ival);
1356  ival = L_MIN(255, ival);
1357  SET_DATA_BYTE(lined, j, ival);
1358  }
1359  }
1360  }
1361  } else { /* direction == L_VERT */
1362  if (halfwidth == 1) {
1363  for (i = 1; i < h - 1; i++) {
1364  lines0 = datas + (i - 1) * wpls;
1365  lines1 = datas + i * wpls;
1366  lines2 = datas + (i + 1) * wpls;
1367  lined = datad + i * wpld;
1368  for (j = 0; j < w; j++) {
1369  val = a[0] * GET_DATA_BYTE(lines0, j) +
1370  a[1] * GET_DATA_BYTE(lines1, j) +
1371  a[2] * GET_DATA_BYTE(lines2, j);
1372  ival = (l_int32)val;
1373  ival = L_MAX(0, ival);
1374  ival = L_MIN(255, ival);
1375  SET_DATA_BYTE(lined, j, ival);
1376  }
1377  }
1378  } else { /* halfwidth == 2 */
1379  for (i = 2; i < h - 2; i++) {
1380  lines0 = datas + (i - 2) * wpls;
1381  lines1 = datas + (i - 1) * wpls;
1382  lines2 = datas + i * wpls;
1383  lines3 = datas + (i + 1) * wpls;
1384  lines4 = datas + (i + 2) * wpls;
1385  lined = datad + i * wpld;
1386  for (j = 0; j < w; j++) {
1387  val = a[0] * GET_DATA_BYTE(lines0, j) +
1388  a[1] * GET_DATA_BYTE(lines1, j) +
1389  a[2] * GET_DATA_BYTE(lines2, j) +
1390  a[3] * GET_DATA_BYTE(lines3, j) +
1391  a[4] * GET_DATA_BYTE(lines4, j);
1392  ival = (l_int32)val;
1393  ival = L_MAX(0, ival);
1394  ival = L_MIN(255, ival);
1395  SET_DATA_BYTE(lined, j, ival);
1396  }
1397  }
1398  }
1399  }
1400 
1401  return pixd;
1402 }
1403 
1404 
1420 PIX *
1422  l_int32 halfwidth,
1423  l_float32 fract)
1424 {
1425 l_int32 w, h, d, wpls, wpld, wplf, i, j, ival, sval;
1426 l_uint32 *datas, *datad, *lines, *lined;
1427 l_float32 val, norm;
1428 l_float32 *dataf, *linef, *linef0, *linef1, *linef2, *linef3, *linef4;
1429 PIX *pixd;
1430 FPIX *fpix;
1431 
1432  PROCNAME("pixUnsharpMaskingGray2D");
1433 
1434  if (!pixs)
1435  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1436  pixGetDimensions(pixs, &w, &h, &d);
1437  if (d != 8 || pixGetColormap(pixs) != NULL)
1438  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1439  if (fract <= 0.0 || halfwidth <= 0) {
1440  L_WARNING("no sharpening requested; clone returned\n", procName);
1441  return pixClone(pixs);
1442  }
1443  if (halfwidth != 1 && halfwidth != 2)
1444  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1445 
1446  if ((pixd = pixCopyBorder(NULL, pixs, halfwidth, halfwidth,
1447  halfwidth, halfwidth)) == NULL)
1448  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1449  datad = pixGetData(pixd);
1450  wpld = pixGetWpl(pixd);
1451  datas = pixGetData(pixs);
1452  wpls = pixGetWpl(pixs);
1453 
1454  /* Do the low pass separably. Store the result of horizontal
1455  * smoothing in an intermediate fpix. */
1456  if ((fpix = fpixCreate(w, h)) == NULL) {
1457  pixDestroy(&pixd);
1458  return (PIX *)ERROR_PTR("fpix not made", procName, NULL);
1459  }
1460  dataf = fpixGetData(fpix);
1461  wplf = fpixGetWpl(fpix);
1462  if (halfwidth == 1) {
1463  for (i = 0; i < h; i++) {
1464  lines = datas + i * wpls;
1465  linef = dataf + i * wplf;
1466  for (j = 1; j < w - 1; j++) {
1467  val = GET_DATA_BYTE(lines, j - 1) +
1468  GET_DATA_BYTE(lines, j) +
1469  GET_DATA_BYTE(lines, j + 1);
1470  linef[j] = val;
1471  }
1472  }
1473  } else {
1474  for (i = 0; i < h; i++) {
1475  lines = datas + i * wpls;
1476  linef = dataf + i * wplf;
1477  for (j = 2; j < w - 2; j++) {
1478  val = GET_DATA_BYTE(lines, j - 2) +
1479  GET_DATA_BYTE(lines, j - 1) +
1480  GET_DATA_BYTE(lines, j) +
1481  GET_DATA_BYTE(lines, j + 1) +
1482  GET_DATA_BYTE(lines, j + 2);
1483  linef[j] = val;
1484  }
1485  }
1486  }
1487 
1488  /* Do vertical smoothing to finish the low-pass filter.
1489  * At each pixel, if L is the lowpass value, I is the
1490  * src pixel value and f is the fraction of highpass to
1491  * be added to I, then the highpass filter value is
1492  * H = I - L
1493  * and the new sharpened value is
1494  * N = I + f * H. */
1495  if (halfwidth == 1) {
1496  for (i = 1; i < h - 1; i++) {
1497  linef0 = dataf + (i - 1) * wplf;
1498  linef1 = dataf + i * wplf;
1499  linef2 = dataf + (i + 1) * wplf;
1500  lined = datad + i * wpld;
1501  lines = datas + i * wpls;
1502  norm = 1.0 / 9.0;
1503  for (j = 1; j < w - 1; j++) {
1504  val = norm * (linef0[j] + linef1[j] +
1505  linef2[j]); /* L: lowpass filter value */
1506  sval = GET_DATA_BYTE(lines, j); /* I: source pixel */
1507  ival = (l_int32)(sval + fract * (sval - val) + 0.5);
1508  ival = L_MAX(0, ival);
1509  ival = L_MIN(255, ival);
1510  SET_DATA_BYTE(lined, j, ival);
1511  }
1512  }
1513  } else {
1514  for (i = 2; i < h - 2; i++) {
1515  linef0 = dataf + (i - 2) * wplf;
1516  linef1 = dataf + (i - 1) * wplf;
1517  linef2 = dataf + i * wplf;
1518  linef3 = dataf + (i + 1) * wplf;
1519  linef4 = dataf + (i + 2) * wplf;
1520  lined = datad + i * wpld;
1521  lines = datas + i * wpls;
1522  norm = 1.0 / 25.0;
1523  for (j = 2; j < w - 2; j++) {
1524  val = norm * (linef0[j] + linef1[j] + linef2[j] + linef3[j] +
1525  linef4[j]); /* L: lowpass filter value */
1526  sval = GET_DATA_BYTE(lines, j); /* I: source pixel */
1527  ival = (l_int32)(sval + fract * (sval - val) + 0.5);
1528  ival = L_MAX(0, ival);
1529  ival = L_MIN(255, ival);
1530  SET_DATA_BYTE(lined, j, ival);
1531  }
1532  }
1533  }
1534 
1535  fpixDestroy(&fpix);
1536  return pixd;
1537 }
1538 
1539 
1540 /*-----------------------------------------------------------------------*
1541  * Hue and saturation modification *
1542  *-----------------------------------------------------------------------*/
1566 PIX *
1568  PIX *pixs,
1569  l_float32 fract)
1570 {
1571 l_int32 w, h, d, i, j, wpl, delhue;
1572 l_int32 rval, gval, bval, hval, sval, vval;
1573 l_uint32 *data, *line;
1574 
1575  PROCNAME("pixModifyHue");
1576 
1577  if (!pixs)
1578  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1579  if (pixGetColormap(pixs) != NULL)
1580  return (PIX *)ERROR_PTR("pixs colormapped", procName, NULL);
1581  if (pixd && (pixd != pixs))
1582  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
1583  pixGetDimensions(pixs, &w, &h, &d);
1584  if (d != 32)
1585  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1586  if (L_ABS(fract) > 1.0)
1587  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1588 
1589  pixd = pixCopy(pixd, pixs);
1590 
1591  delhue = (l_int32)(240 * fract);
1592  if (delhue == 0 || delhue == 240 || delhue == -240) {
1593  L_WARNING("no change requested in hue\n", procName);
1594  return pixd;
1595  }
1596  if (delhue < 0)
1597  delhue += 240;
1598 
1599  data = pixGetData(pixd);
1600  wpl = pixGetWpl(pixd);
1601  for (i = 0; i < h; i++) {
1602  line = data + i * wpl;
1603  for (j = 0; j < w; j++) {
1604  extractRGBValues(line[j], &rval, &gval, &bval);
1605  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1606  hval = (hval + delhue) % 240;
1607  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1608  composeRGBPixel(rval, gval, bval, line + j);
1609  }
1610  }
1611  if (pixGetSpp(pixs) == 4)
1613 
1614  return pixd;
1615 }
1616 
1617 
1640 PIX *
1642  PIX *pixs,
1643  l_float32 fract)
1644 {
1645 l_int32 w, h, d, i, j, wpl;
1646 l_int32 rval, gval, bval, hval, sval, vval;
1647 l_uint32 *data, *line;
1648 
1649  PROCNAME("pixModifySaturation");
1650 
1651  if (!pixs)
1652  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1653  pixGetDimensions(pixs, &w, &h, &d);
1654  if (d != 32)
1655  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1656  if (L_ABS(fract) > 1.0)
1657  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1658 
1659  pixd = pixCopy(pixd, pixs);
1660  if (fract == 0.0) {
1661  L_WARNING("no change requested in saturation\n", procName);
1662  return pixd;
1663  }
1664 
1665  data = pixGetData(pixd);
1666  wpl = pixGetWpl(pixd);
1667  for (i = 0; i < h; i++) {
1668  line = data + i * wpl;
1669  for (j = 0; j < w; j++) {
1670  extractRGBValues(line[j], &rval, &gval, &bval);
1671  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1672  if (fract < 0.0)
1673  sval = (l_int32)(sval * (1.0 + fract));
1674  else
1675  sval = (l_int32)(sval + fract * (255 - sval));
1676  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1677  composeRGBPixel(rval, gval, bval, line + j);
1678  }
1679  }
1680  if (pixGetSpp(pixs) == 4)
1682 
1683  return pixd;
1684 }
1685 
1686 
1695 l_int32
1697  l_int32 factor,
1698  l_float32 *psat)
1699 {
1700 l_int32 w, h, d, i, j, wpl, sum, count;
1701 l_int32 rval, gval, bval, hval, sval, vval;
1702 l_uint32 *data, *line;
1703 
1704  PROCNAME("pixMeasureSaturation");
1705 
1706  if (!psat)
1707  return ERROR_INT("pixs not defined", procName, 1);
1708  *psat = 0.0;
1709  if (!pixs)
1710  return ERROR_INT("pixs not defined", procName, 1);
1711  pixGetDimensions(pixs, &w, &h, &d);
1712  if (d != 32)
1713  return ERROR_INT("pixs not 32 bpp", procName, 1);
1714  if (factor < 1)
1715  return ERROR_INT("subsampling factor < 1", procName, 1);
1716 
1717  data = pixGetData(pixs);
1718  wpl = pixGetWpl(pixs);
1719  for (i = 0, sum = 0, count = 0; i < h; i += factor) {
1720  line = data + i * wpl;
1721  for (j = 0; j < w; j += factor) {
1722  extractRGBValues(line[j], &rval, &gval, &bval);
1723  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1724  sum += sval;
1725  count++;
1726  }
1727  }
1728 
1729  if (count > 0)
1730  *psat = (l_float32)sum / (l_float32)count;
1731  return 0;
1732 }
1733 
1734 
1757 PIX *
1759  PIX *pixs,
1760  l_float32 fract)
1761 {
1762 l_int32 w, h, d, i, j, wpl;
1763 l_int32 rval, gval, bval, hval, sval, vval;
1764 l_uint32 *data, *line;
1765 
1766  PROCNAME("pixModifyBrightness");
1767 
1768  if (!pixs)
1769  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1770  pixGetDimensions(pixs, &w, &h, &d);
1771  if (d != 32)
1772  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1773  if (L_ABS(fract) > 1.0)
1774  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1775 
1776  pixd = pixCopy(pixd, pixs);
1777  if (fract == 0.0) {
1778  L_WARNING("no change requested in brightness\n", procName);
1779  return pixd;
1780  }
1781 
1782  data = pixGetData(pixd);
1783  wpl = pixGetWpl(pixd);
1784  for (i = 0; i < h; i++) {
1785  line = data + i * wpl;
1786  for (j = 0; j < w; j++) {
1787  extractRGBValues(line[j], &rval, &gval, &bval);
1788  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1789  if (fract > 0.0)
1790  vval = (l_int32)(vval + fract * (255.0 - vval));
1791  else
1792  vval = (l_int32)(vval * (1.0 + fract));
1793  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1794  composeRGBPixel(rval, gval, bval, line + j);
1795  }
1796  }
1797  if (pixGetSpp(pixs) == 4)
1799 
1800  return pixd;
1801 }
1802 
1803 
1804 /*-----------------------------------------------------------------------*
1805  * Color shifting *
1806  *-----------------------------------------------------------------------*/
1838 PIX *
1840  l_float32 roff,
1841  l_float32 goff,
1842  l_float32 boff,
1843  l_float32 delta,
1844  l_int32 nincr)
1845 {
1846 char buf[64];
1847 l_int32 i, w, h;
1848 l_float32 del, ratio;
1849 L_BMF *bmf;
1850 PIX *pix1, *pix2, *pix3;
1851 PIXA *pixa;
1852 
1853  PROCNAME("pixMosaicColorShiftRGB");
1854 
1855  if (!pixs || pixGetDepth(pixs) != 32)
1856  return (PIX *)ERROR_PTR("pixs undefined or not rgb", procName, NULL);
1857  if (roff < -1.0 || roff > 1.0)
1858  return (PIX *)ERROR_PTR("roff not in [-1.0, 1.0]", procName, NULL);
1859  if (goff < -1.0 || goff > 1.0)
1860  return (PIX *)ERROR_PTR("goff not in [-1.0, 1.0]", procName, NULL);
1861  if (boff < -1.0 || boff > 1.0)
1862  return (PIX *)ERROR_PTR("boff not in [-1.0, 1.0]", procName, NULL);
1863  if (delta < 0.0 || delta > 0.1)
1864  return (PIX *)ERROR_PTR("delta not in [0.0, 0.1]", procName, NULL);
1865  if (delta == 0.0) delta = 0.04;
1866  if (nincr < 0 || nincr > 6)
1867  return (PIX *)ERROR_PTR("nincr not in [0, 6]", procName, NULL);
1868  if (nincr == 0) nincr = 2;
1869 
1870  /* Require width and height to be >= 100, and the aspect ratio <= 5.0 */
1871  pixGetDimensions(pixs, &w, &h, NULL);
1872  if (w < 100 || h < 100)
1873  return (PIX *)ERROR_PTR("w and h not both >= 100", procName, NULL);
1874  pixMaxAspectRatio(pixs, &ratio);
1875  if (ratio < 1.0 || ratio > 5.0) {
1876  L_ERROR("invalid aspect ratio %5.1f\n", procName, ratio);
1877  return NULL;
1878  }
1879 
1880  pixa = pixaCreate(3 * (2 * nincr + 1));
1881  bmf = bmfCreate(NULL, 8);
1882  pix1 = pixScaleToSize(pixs, 400, 0);
1883  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1884  pix2 = pixColorShiftRGB(pix1, roff + del, goff, boff);
1885  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1886  roff + del, goff, boff);
1887  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1888  L_ADD_BELOW, 0);
1889  pixaAddPix(pixa, pix3, L_INSERT);
1890  pixDestroy(&pix2);
1891  }
1892  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1893  pix2 = pixColorShiftRGB(pix1, roff, goff + del, boff);
1894  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1895  roff, goff + del, boff);
1896  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1897  L_ADD_BELOW, 0);
1898  pixaAddPix(pixa, pix3, L_INSERT);
1899  pixDestroy(&pix2);
1900  }
1901  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1902  pix2 = pixColorShiftRGB(pix1, roff, goff, boff + del);
1903  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1904  roff, goff, boff + del);
1905  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1906  L_ADD_BELOW, 0);
1907  pixaAddPix(pixa, pix3, L_INSERT);
1908  pixDestroy(&pix2);
1909  }
1910  pixDestroy(&pix1);
1911 
1912  pix1 = pixaDisplayTiledAndScaled(pixa, 32, 300, 2 * nincr + 1, 0, 30, 2);
1913  pixaDestroy(&pixa);
1914  bmfDestroy(&bmf);
1915  return pix1;
1916 }
1917 
1918 
1944 PIX *
1946  l_float32 rfract,
1947  l_float32 gfract,
1948  l_float32 bfract)
1949 {
1950 l_int32 w, h, i, j, wpls, wpld, rval, gval, bval;
1951 l_int32 *rlut, *glut, *blut;
1952 l_uint32 *datas, *datad, *lines, *lined;
1953 l_float32 fi;
1954 PIX *pixd;
1955 
1956  PROCNAME("pixColorShiftRGB");
1957 
1958  if (!pixs)
1959  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1960  if (pixGetDepth(pixs) != 32)
1961  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1962  if (rfract < -1.0 || rfract > 1.0)
1963  return (PIX *)ERROR_PTR("rfract not in [-1.0, 1.0]", procName, NULL);
1964  if (gfract < -1.0 || gfract > 1.0)
1965  return (PIX *)ERROR_PTR("gfract not in [-1.0, 1.0]", procName, NULL);
1966  if (bfract < -1.0 || bfract > 1.0)
1967  return (PIX *)ERROR_PTR("bfract not in [-1.0, 1.0]", procName, NULL);
1968  if (rfract == 0.0 && gfract == 0.0 && bfract == 0.0)
1969  return pixCopy(NULL, pixs);
1970 
1971  rlut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1972  glut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1973  blut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1974  for (i = 0; i < 256; i++) {
1975  fi = i;
1976  if (rfract >= 0) {
1977  rlut[i] = (l_int32)(fi + (255.0 - fi) * rfract);
1978  } else {
1979  rlut[i] = (l_int32)(fi * (1.0 + rfract));
1980  }
1981  if (gfract >= 0) {
1982  glut[i] = (l_int32)(fi + (255.0 - fi) * gfract);
1983  } else {
1984  glut[i] = (l_int32)(fi * (1.0 + gfract));
1985  }
1986  if (bfract >= 0) {
1987  blut[i] = (l_int32)(fi + (255.0 - fi) * bfract);
1988  } else {
1989  blut[i] = (l_int32)(fi * (1.0 + bfract));
1990  }
1991  }
1992 
1993  pixGetDimensions(pixs, &w, &h, NULL);
1994  datas = pixGetData(pixs);
1995  wpls = pixGetWpl(pixs);
1996  pixd = pixCreate(w, h, 32);
1997  datad = pixGetData(pixd);
1998  wpld = pixGetWpl(pixd);
1999  for (i = 0; i < h; i++) {
2000  lines = datas + i * wpls;
2001  lined = datad + i * wpld;
2002  for (j = 0; j < w; j++) {
2003  extractRGBValues(lines[j], &rval, &gval, &bval);
2004  composeRGBPixel(rlut[rval], glut[gval], blut[bval], lined + j);
2005  }
2006  }
2007 
2008  LEPT_FREE(rlut);
2009  LEPT_FREE(glut);
2010  LEPT_FREE(blut);
2011  return pixd;
2012 }
2013 
2014 /*-----------------------------------------------------------------------*
2015  * Darken gray (unsaturated) pixels
2016  *-----------------------------------------------------------------------*/
2043 PIX *
2045  PIX *pixs,
2046  l_int32 thresh,
2047  l_int32 satlimit)
2048 {
2049 l_int32 w, h, i, j, wpls, wpld;
2050 l_int32 rval, gval, bval, minrg, min, maxrg, max, sat;
2051 l_uint32 *datas, *datad, *lines, *lined;
2052 l_float32 ratio;
2053 
2054  PROCNAME("pixDarkenGray");
2055 
2056  if (!pixs || pixGetDepth(pixs) != 32)
2057  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
2058  if (thresh < 0 || thresh > 255)
2059  return (PIX *)ERROR_PTR("invalid thresh", procName, NULL);
2060  if (satlimit < 1)
2061  return (PIX *)ERROR_PTR("invalid satlimit", procName, NULL);
2062  if (pixd && (pixs != pixd))
2063  return (PIX *)ERROR_PTR("not new or in-place", procName, NULL);
2064 
2065  pixGetDimensions(pixs, &w, &h, NULL);
2066  datas = pixGetData(pixs);
2067  wpls = pixGetWpl(pixs);
2068  if ((pixd = pixCopy(pixd, pixs)) == NULL)
2069  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2070  datad = pixGetData(pixd);
2071  wpld = pixGetWpl(pixd);
2072 
2073  for (i = 0; i < h; i++) {
2074  lines = datas + i * wpls;
2075  lined = datad + i * wpld;
2076  for (j = 0; j < w; j++) {
2077  extractRGBValues(lines[j], &rval, &gval, &bval);
2078  minrg = L_MIN(rval, gval);
2079  min = L_MIN(minrg, bval);
2080  maxrg = L_MAX(rval, gval);
2081  max = L_MAX(maxrg, bval);
2082  sat = max - min;
2083  if (max >= thresh || sat >= satlimit)
2084  continue;
2085  ratio = (l_float32)sat / (l_float32)satlimit;
2086  composeRGBPixel((l_int32)(ratio * rval), (l_int32)(ratio * gval),
2087  (l_int32)(ratio * bval), &lined[j]);
2088  }
2089  }
2090  return pixd;
2091 }
2092 
2093 
2094 /*-----------------------------------------------------------------------*
2095  * General multiplicative constant color transform *
2096  *-----------------------------------------------------------------------*/
2115 PIX *
2117  l_float32 rfact,
2118  l_float32 gfact,
2119  l_float32 bfact)
2120 {
2121 l_int32 i, j, w, h, d, wpls, wpld;
2122 l_int32 ncolors, rval, gval, bval, nrval, ngval, nbval;
2123 l_uint32 nval;
2124 l_uint32 *datas, *datad, *lines, *lined;
2125 PIX *pixd;
2126 PIXCMAP *cmap;
2127 
2128  PROCNAME("pixMultConstantColor");
2129 
2130  if (!pixs)
2131  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2132  pixGetDimensions(pixs, &w, &h, &d);
2133  cmap = pixGetColormap(pixs);
2134  if (!cmap && d != 32)
2135  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
2136  rfact = L_MAX(0.0, rfact);
2137  gfact = L_MAX(0.0, gfact);
2138  bfact = L_MAX(0.0, bfact);
2139 
2140  if (cmap) {
2141  if ((pixd = pixCopy(NULL, pixs)) == NULL)
2142  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2143  cmap = pixGetColormap(pixd);
2144  ncolors = pixcmapGetCount(cmap);
2145  for (i = 0; i < ncolors; i++) {
2146  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2147  nrval = (l_int32)(rfact * rval);
2148  ngval = (l_int32)(gfact * gval);
2149  nbval = (l_int32)(bfact * bval);
2150  nrval = L_MIN(255, nrval);
2151  ngval = L_MIN(255, ngval);
2152  nbval = L_MIN(255, nbval);
2153  pixcmapResetColor(cmap, i, nrval, ngval, nbval);
2154  }
2155  return pixd;
2156  }
2157 
2158  if ((pixd = pixCreateTemplate(pixs)) == NULL)
2159  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2160  datas = pixGetData(pixs);
2161  datad = pixGetData(pixd);
2162  wpls = pixGetWpl(pixs);
2163  wpld = pixGetWpl(pixd);
2164  for (i = 0; i < h; i++) {
2165  lines = datas + i * wpls;
2166  lined = datad + i * wpld;
2167  for (j = 0; j < w; j++) {
2168  extractRGBValues(lines[j], &rval, &gval, &bval);
2169  nrval = (l_int32)(rfact * rval);
2170  ngval = (l_int32)(gfact * gval);
2171  nbval = (l_int32)(bfact * bval);
2172  nrval = L_MIN(255, nrval);
2173  ngval = L_MIN(255, ngval);
2174  nbval = L_MIN(255, nbval);
2175  composeRGBPixel(nrval, ngval, nbval, &nval);
2176  *(lined + j) = nval;
2177  }
2178  }
2179 
2180  return pixd;
2181 }
2182 
2183 
2217 PIX *
2219  L_KERNEL *kel)
2220 {
2221 l_int32 i, j, index, kw, kh, w, h, d, wpls, wpld;
2222 l_int32 ncolors, rval, gval, bval, nrval, ngval, nbval;
2223 l_uint32 nval;
2224 l_uint32 *datas, *datad, *lines, *lined;
2225 l_float32 v[9]; /* use linear array for convenience */
2226 PIX *pixd;
2227 PIXCMAP *cmap;
2228 
2229  PROCNAME("pixMultMatrixColor");
2230 
2231  if (!pixs)
2232  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2233  if (!kel)
2234  return (PIX *)ERROR_PTR("kel not defined", procName, NULL);
2235  kernelGetParameters(kel, &kw, &kh, NULL, NULL);
2236  if (kw != 3 || kh != 3)
2237  return (PIX *)ERROR_PTR("matrix not 3x3", procName, NULL);
2238  pixGetDimensions(pixs, &w, &h, &d);
2239  cmap = pixGetColormap(pixs);
2240  if (!cmap && d != 32)
2241  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
2242 
2243  for (i = 0, index = 0; i < 3; i++)
2244  for (j = 0; j < 3; j++, index++)
2245  kernelGetElement(kel, i, j, v + index);
2246 
2247  if (cmap) {
2248  if ((pixd = pixCopy(NULL, pixs)) == NULL)
2249  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2250  cmap = pixGetColormap(pixd);
2251  ncolors = pixcmapGetCount(cmap);
2252  for (i = 0; i < ncolors; i++) {
2253  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2254  nrval = (l_int32)(v[0] * rval + v[1] * gval + v[2] * bval);
2255  ngval = (l_int32)(v[3] * rval + v[4] * gval + v[5] * bval);
2256  nbval = (l_int32)(v[6] * rval + v[7] * gval + v[8] * bval);
2257  nrval = L_MAX(0, L_MIN(255, nrval));
2258  ngval = L_MAX(0, L_MIN(255, ngval));
2259  nbval = L_MAX(0, L_MIN(255, nbval));
2260  pixcmapResetColor(cmap, i, nrval, ngval, nbval);
2261  }
2262  return pixd;
2263  }
2264 
2265  if ((pixd = pixCreateTemplate(pixs)) == NULL)
2266  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2267  datas = pixGetData(pixs);
2268  datad = pixGetData(pixd);
2269  wpls = pixGetWpl(pixs);
2270  wpld = pixGetWpl(pixd);
2271  for (i = 0; i < h; i++) {
2272  lines = datas + i * wpls;
2273  lined = datad + i * wpld;
2274  for (j = 0; j < w; j++) {
2275  extractRGBValues(lines[j], &rval, &gval, &bval);
2276  nrval = (l_int32)(v[0] * rval + v[1] * gval + v[2] * bval);
2277  ngval = (l_int32)(v[3] * rval + v[4] * gval + v[5] * bval);
2278  nbval = (l_int32)(v[6] * rval + v[7] * gval + v[8] * bval);
2279  nrval = L_MAX(0, L_MIN(255, nrval));
2280  ngval = L_MAX(0, L_MIN(255, ngval));
2281  nbval = L_MAX(0, L_MIN(255, nbval));
2282  composeRGBPixel(nrval, ngval, nbval, &nval);
2283  *(lined + j) = nval;
2284  }
2285  }
2286 
2287  return pixd;
2288 }
2289 
2290 
2291 /*-------------------------------------------------------------*
2292  * Half-edge by bandpass *
2293  *-------------------------------------------------------------*/
2326 PIX *
2328  l_int32 sm1h,
2329  l_int32 sm1v,
2330  l_int32 sm2h,
2331  l_int32 sm2v)
2332 {
2333 l_int32 d;
2334 PIX *pixg, *pixacc, *pixc1, *pixc2;
2335 
2336  PROCNAME("pixHalfEdgeByBandpass");
2337 
2338  if (!pixs)
2339  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2340  if (sm1h == sm2h && sm1v == sm2v)
2341  return (PIX *)ERROR_PTR("sm2 = sm1", procName, NULL);
2342  d = pixGetDepth(pixs);
2343  if (d != 8 && d != 32)
2344  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
2345  if (d == 32)
2347  else /* d == 8 */
2348  pixg = pixClone(pixs);
2349 
2350  /* Make a convolution accumulator and use it twice */
2351  if ((pixacc = pixBlockconvAccum(pixg)) == NULL) {
2352  pixDestroy(&pixg);
2353  return (PIX *)ERROR_PTR("pixacc not made", procName, NULL);
2354  }
2355  if ((pixc1 = pixBlockconvGray(pixg, pixacc, sm1h, sm1v)) == NULL) {
2356  pixDestroy(&pixg);
2357  pixDestroy(&pixacc);
2358  return (PIX *)ERROR_PTR("pixc1 not made", procName, NULL);
2359  }
2360  pixc2 = pixBlockconvGray(pixg, pixacc, sm2h, sm2v);
2361  pixDestroy(&pixg);
2362  pixDestroy(&pixacc);
2363  if (!pixc2) {
2364  pixDestroy(&pixc1);
2365  return (PIX *)ERROR_PTR("pixc2 not made", procName, NULL);
2366  }
2367 
2368  /* Compute the half-edge using pixc1 - pixc2. */
2369  pixSubtractGray(pixc1, pixc1, pixc2);
2370  pixDestroy(&pixc2);
2371  return pixc1;
2372 }
l_ok numaGetSum(NUMA *na, l_float32 *psum)
numaGetSum()
Definition: numafunc1.c:538
l_ok pixCopyRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixCopyRGBComponent()
Definition: pix2.c:2690
PIX * pixConvertRGBToLuminance(PIX *pixs)
pixConvertRGBToLuminance()
Definition: pixconv.c:742
NUMA * pixGetGrayHistogram(PIX *pixs, l_int32 factor)
pixGetGrayHistogram()
Definition: pix4.c:115
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:169
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
PIX * pixContrastTRCMasked(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 factor)
pixContrastTRCMasked()
Definition: enhance.c:501
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
l_int32 h
Definition: dewarp.h:164
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2538
PIX * pixUnsharpMaskingGray2D(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMaskingGray2D()
Definition: enhance.c:1421
l_ok kernelGetParameters(L_KERNEL *kel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
kernelGetParameters()
Definition: kernel.c:274
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
Definition: pix.h:204
PIX * pixContrastTRC(PIX *pixd, PIX *pixs, l_float32 factor)
pixContrastTRC()
Definition: enhance.c:439
PIX * pixBlockconvAccum(PIX *pixs)
pixBlockconvAccum()
Definition: convolve.c:460
Definition: pix.h:713
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
PIX * pixUnsharpMaskingGrayFast(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingGrayFast()
Definition: enhance.c:1238
NUMA * numaGammaTRC(l_float32 gamma, l_int32 minval, l_int32 maxval)
numaGammaTRC()
Definition: enhance.c:369
PIX * pixModifyBrightness(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifyBrightness()
Definition: enhance.c:1758
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixGammaTRCWithAlpha(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRCWithAlpha()
Definition: enhance.c:308
l_int32 pixTRCMap(PIX *pixs, PIX *pixm, NUMA *na)
pixTRCMap()
Definition: enhance.c:784
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
NUMA * numaGetPartialSums(NUMA *na)
numaGetPartialSums()
Definition: numafunc1.c:579
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
l_ok pixaccMultConst(PIXACC *pixacc, l_float32 factor)
pixaccMultConst()
Definition: pixacc.c:298
l_int32 pixTRCMapGeneral(PIX *pixs, PIX *pixm, NUMA *nar, NUMA *nag, NUMA *nab)
pixTRCMapGeneral()
Definition: enhance.c:906
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
Definition: bmf.h:46
PIX * pixMultConstantColor(PIX *pixs, l_float32 rfact, l_float32 gfact, l_float32 bfact)
pixMultConstantColor()
Definition: enhance.c:2116
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:847
struct Pix * pixs
Definition: dewarp.h:154
void pixaccDestroy(PIXACC **ppixacc)
pixaccDestroy()
Definition: pixacc.c:162
PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtractGray()
Definition: pixarith.c:357
PIX * pixModifyHue(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifyHue()
Definition: enhance.c:1567
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
Definition: array.h:70
PIX * pixUnsharpMaskingGray(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMaskingGray()
Definition: enhance.c:1070
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
PIX * pixEqualizeTRC(PIX *pixd, PIX *pixs, l_float32 fract, l_int32 factor)
pixEqualizeTRC()
Definition: enhance.c:630
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:343
l_ok pixcmapContrastTRC(PIXCMAP *cmap, l_float32 factor)
pixcmapContrastTRC()
Definition: colormap.c:2385
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:824
l_int32 pixMeasureSaturation(PIX *pixs, l_int32 factor, l_float32 *psat)
pixMeasureSaturation()
Definition: enhance.c:1696
Definition: pix.h:543
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
PIX * pixColorShiftRGB(PIX *pixs, l_float32 rfract, l_float32 gfract, l_float32 bfract)
pixColorShiftRGB()
Definition: enhance.c:1945
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:376
PIX * pixGammaTRCMasked(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRCMasked()
Definition: enhance.c:244
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2423
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
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:1045
PIX * pixModifySaturation(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifySaturation()
Definition: enhance.c:1641
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:323
PIX * pixBlockconvGray(PIX *pixs, PIX *pixacc, l_int32 wc, l_int32 hc)
pixBlockconvGray()
Definition: convolve.c:216
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:821
Definition: pix.h:711
NUMA * numaContrastTRC(l_float32 factor)
numaContrastTRC()
Definition: enhance.c:560
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:281
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
Definition: colormap.c:966
l_float32 * fpixGetData(FPIX *fpix)
fpixGetData()
Definition: fpix1.c:519
PIX * pixaccFinal(PIXACC *pixacc, l_int32 outdepth)
pixaccFinal()
Definition: pixacc.c:193
PIX * pixMosaicColorShiftRGB(PIX *pixs, l_float32 roff, l_float32 goff, l_float32 boff, l_float32 delta, l_int32 nincr)
pixMosaicColorShiftRGB()
Definition: enhance.c:1839
Definition: pix.h:455
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixHalfEdgeByBandpass(PIX *pixs, l_int32 sm1h, l_int32 sm1v, l_int32 sm2h, l_int32 sm2v)
pixHalfEdgeByBandpass()
Definition: enhance.c:2327
FPIX * fpixCreate(l_int32 width, l_int32 height)
fpixCreate()
Definition: fpix1.c:156
l_ok kernelGetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 *pval)
kernelGetElement()
Definition: kernel.c:215
PIX * pixUnsharpMasking(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMasking()
Definition: enhance.c:1001
PIXACC * pixaccCreate(l_int32 w, l_int32 h, l_int32 negflag)
pixaccCreate()
Definition: pixacc.c:92
Definition: morph.h:88
Definition: pix.h:138
l_ok pixaccSubtract(PIXACC *pixacc, PIX *pix)
pixaccSubtract()
Definition: pixacc.c:276
PIX * pixGammaTRC(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRC()
Definition: enhance.c:176
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:708
PIX * pixUnsharpMaskingFast(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingFast()
Definition: enhance.c:1167
NUMA * numaEqualizeTRC(PIX *pix, l_float32 fract, l_int32 factor)
numaEqualizeTRC()
Definition: enhance.c:717
l_ok pixaccAdd(PIXACC *pixacc, PIX *pix)
pixaccAdd()
Definition: pixacc.c:254
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
PIX * pixUnsharpMaskingGray1D(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingGray1D()
Definition: enhance.c:1287
l_int32 w
Definition: dewarp.h:163
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:292
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIX * pixCopyBorder(PIX *pixd, PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixCopyBorder()
Definition: pix2.c:1769
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
l_ok pixcmapGammaTRC(PIXCMAP *cmap, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixcmapGammaTRC()
Definition: colormap.c:2330
PIX * pixDarkenGray(PIX *pixd, PIX *pixs, l_int32 thresh, l_int32 satlimit)
pixDarkenGray()
Definition: enhance.c:2044
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition: pixconv.c:3492
l_ok pixMaxAspectRatio(PIX *pixs, l_float32 *pratio)
pixMaxAspectRatio()
Definition: pix1.c:2013
Definition: pix.h:578
PIX * pixMultMatrixColor(PIX *pixs, L_KERNEL *kel)
pixMultMatrixColor()
Definition: enhance.c:2218
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:117