Leptonica  1.77.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 #include <math.h>
119 #include "allheaders.h"
120 
121  /* Scales contrast enhancement factor to have a useful range
122  * between 0.0 and 1.0 */
123 static const l_float32 ENHANCE_SCALE_FACTOR = 5.;
124 
125  /* Default number of pixels sampled to determine histogram */
126 static const l_int32 DEFAULT_HISTO_SAMPLES = 100000;
127 
128 
129 /*-------------------------------------------------------------*
130  * Gamma TRC (tone reproduction curve) mapping *
131  *-------------------------------------------------------------*/
173 PIX *
175  PIX *pixs,
176  l_float32 gamma,
177  l_int32 minval,
178  l_int32 maxval)
179 {
180 l_int32 d;
181 NUMA *nag;
182 PIXCMAP *cmap;
183 
184  PROCNAME("pixGammaTRC");
185 
186  if (!pixs)
187  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
188  if (pixd && (pixd != pixs))
189  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
190  if (gamma <= 0.0) {
191  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
192  gamma = 1.0;
193  }
194  if (minval >= maxval)
195  return (PIX *)ERROR_PTR("minval not < maxval", procName, 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", procName, 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", procName, 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  PROCNAME("pixGammaTRCMasked");
253 
254  if (!pixm)
255  return pixGammaTRC(pixd, pixs, gamma, minval, maxval);
256 
257  if (!pixs)
258  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
259  if (pixGetColormap(pixs))
260  return (PIX *)ERROR_PTR("invalid: pixs has a colormap", procName, pixd);
261  if (pixd && (pixd != pixs))
262  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
263  d = pixGetDepth(pixs);
264  if (d != 8 && d != 32)
265  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
266  if (minval >= maxval)
267  return (PIX *)ERROR_PTR("minval not < maxval", procName, pixd);
268  if (gamma <= 0.0) {
269  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
270  gamma = 1.0;
271  }
272 
273  if (gamma == 1.0 && minval == 0 && maxval == 255)
274  return pixCopy(pixd, pixs);
275 
276  if (!pixd) /* start with a copy if not in-place */
277  pixd = pixCopy(NULL, pixs);
278 
279  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
280  return (PIX *)ERROR_PTR("nag not made", procName, pixd);
281  pixTRCMap(pixd, pixm, nag);
282  numaDestroy(&nag);
283 
284  return pixd;
285 }
286 
287 
305 PIX *
307  PIX *pixs,
308  l_float32 gamma,
309  l_int32 minval,
310  l_int32 maxval)
311 {
312 NUMA *nag;
313 PIX *pixalpha;
314 
315  PROCNAME("pixGammaTRCWithAlpha");
316 
317  if (!pixs || pixGetDepth(pixs) != 32)
318  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, pixd);
319  if (pixd && (pixd != pixs))
320  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
321  if (gamma <= 0.0) {
322  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
323  gamma = 1.0;
324  }
325  if (minval >= maxval)
326  return (PIX *)ERROR_PTR("minval not < maxval", procName, pixd);
327 
328  if (gamma == 1.0 && minval == 0 && maxval == 255)
329  return pixCopy(pixd, pixs);
330  if (!pixd) /* start with a copy if not in-place */
331  pixd = pixCopy(NULL, pixs);
332 
333  pixalpha = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL); /* save */
334  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
335  return (PIX *)ERROR_PTR("nag not made", procName, pixd);
336  pixTRCMap(pixd, NULL, nag);
337  pixSetRGBComponent(pixd, pixalpha, L_ALPHA_CHANNEL); /* restore */
338  pixSetSpp(pixd, 4);
339 
340  numaDestroy(&nag);
341  pixDestroy(&pixalpha);
342  return pixd;
343 }
344 
345 
365 NUMA *
366 numaGammaTRC(l_float32 gamma,
367  l_int32 minval,
368  l_int32 maxval)
369 {
370 l_int32 i, val;
371 l_float32 x, invgamma;
372 NUMA *na;
373 
374  PROCNAME("numaGammaTRC");
375 
376  if (minval >= maxval)
377  return (NUMA *)ERROR_PTR("minval not < maxval", procName, NULL);
378  if (gamma <= 0.0) {
379  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
380  gamma = 1.0;
381  }
382 
383  invgamma = 1. / gamma;
384  na = numaCreate(256);
385  for (i = 0; i < minval; i++)
386  numaAddNumber(na, 0);
387  for (i = minval; i <= maxval; i++) {
388  if (i < 0) continue;
389  if (i > 255) continue;
390  x = (l_float32)(i - minval) / (l_float32)(maxval - minval);
391  val = (l_int32)(255. * powf(x, invgamma) + 0.5);
392  val = L_MAX(val, 0);
393  val = L_MIN(val, 255);
394  numaAddNumber(na, val);
395  }
396  for (i = maxval + 1; i < 256; i++)
397  numaAddNumber(na, 255);
398 
399  return na;
400 }
401 
402 
403 /*-------------------------------------------------------------*
404  * Contrast enhancement *
405  *-------------------------------------------------------------*/
435 PIX *
437  PIX *pixs,
438  l_float32 factor)
439 {
440 l_int32 d;
441 NUMA *nac;
442 PIXCMAP *cmap;
443 
444  PROCNAME("pixContrastTRC");
445 
446  if (!pixs)
447  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
448  if (pixd && (pixd != pixs))
449  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
450  if (factor < 0.0) {
451  L_WARNING("factor must be >= 0.0; using 0.0\n", procName);
452  factor = 0.0;
453  }
454  if (factor == 0.0)
455  return pixCopy(pixd, pixs);
456 
457  cmap = pixGetColormap(pixs);
458  d = pixGetDepth(pixs);
459  if (!cmap && d != 8 && d != 32)
460  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
461 
462  if (!pixd) /* start with a copy if not in-place */
463  pixd = pixCopy(NULL, pixs);
464 
465  if (cmap) {
466  pixcmapContrastTRC(pixGetColormap(pixd), factor);
467  return pixd;
468  }
469 
470  /* pixd is 8 or 32 bpp */
471  if ((nac = numaContrastTRC(factor)) == NULL)
472  return (PIX *)ERROR_PTR("nac not made", procName, pixd);
473  pixTRCMap(pixd, NULL, nac);
474  numaDestroy(&nac);
475 
476  return pixd;
477 }
478 
479 
497 PIX *
499  PIX *pixs,
500  PIX *pixm,
501  l_float32 factor)
502 {
503 l_int32 d;
504 NUMA *nac;
505 
506  PROCNAME("pixContrastTRCMasked");
507 
508  if (!pixm)
509  return pixContrastTRC(pixd, pixs, factor);
510 
511  if (!pixs)
512  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
513  if (pixGetColormap(pixs))
514  return (PIX *)ERROR_PTR("invalid: pixs has a colormap", procName, pixd);
515  if (pixd && (pixd != pixs))
516  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
517  d = pixGetDepth(pixs);
518  if (d != 8 && d != 32)
519  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
520 
521  if (factor < 0.0) {
522  L_WARNING("factor must be >= 0.0; using 0.0\n", procName);
523  factor = 0.0;
524  }
525  if (factor == 0.0)
526  return pixCopy(pixd, pixs);
527 
528  if (!pixd) /* start with a copy if not in-place */
529  pixd = pixCopy(NULL, pixs);
530 
531  if ((nac = numaContrastTRC(factor)) == NULL)
532  return (PIX *)ERROR_PTR("nac not made", procName, pixd);
533  pixTRCMap(pixd, pixm, nac);
534  numaDestroy(&nac);
535 
536  return pixd;
537 }
538 
539 
556 NUMA *
557 numaContrastTRC(l_float32 factor)
558 {
559 l_int32 i, val;
560 l_float64 x, ymax, ymin, dely, scale;
561 NUMA *na;
562 
563  PROCNAME("numaContrastTRC");
564 
565  if (factor < 0.0) {
566  L_WARNING("factor must be >= 0.0; using 0.0; no enhancement\n",
567  procName);
568  factor = 0.0;
569  }
570  if (factor == 0.0)
571  return numaMakeSequence(0, 1, 256); /* linear map */
572 
573  scale = ENHANCE_SCALE_FACTOR;
574  ymax = atan((l_float64)(1.0 * factor * scale));
575  ymin = atan((l_float64)(-127. * factor * scale / 128.));
576  dely = ymax - ymin;
577  na = numaCreate(256);
578  for (i = 0; i < 256; i++) {
579  x = (l_float64)i;
580  val = (l_int32)((255. / dely) *
581  (-ymin + atan((l_float64)(factor * scale * (x - 127.) / 128.))) +
582  0.5);
583  numaAddNumber(na, val);
584  }
585 
586  return na;
587 }
588 
589 
590 /*-------------------------------------------------------------*
591  * Histogram equalization *
592  *-------------------------------------------------------------*/
626 PIX *
628  PIX *pixs,
629  l_float32 fract,
630  l_int32 factor)
631 {
632 l_int32 d;
633 NUMA *na;
634 PIX *pixt, *pix8;
635 PIXCMAP *cmap;
636 
637  PROCNAME("pixEqualizeTRC");
638 
639  if (!pixs)
640  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
641  if (pixd && (pixd != pixs))
642  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
643  cmap = pixGetColormap(pixs);
644  d = pixGetDepth(pixs);
645  if (d != 8 && d != 32 && !cmap)
646  return (PIX *)ERROR_PTR("pixs not 8/32 bpp or cmapped", procName, NULL);
647  if (fract < 0.0 || fract > 1.0)
648  return (PIX *)ERROR_PTR("fract not in [0.0 ... 1.0]", procName, NULL);
649  if (factor < 1)
650  return (PIX *)ERROR_PTR("sampling factor < 1", procName, NULL);
651 
652  if (fract == 0.0)
653  return pixCopy(pixd, pixs);
654 
655  /* If there is a colormap, remove it. */
656  if (cmap)
658  else
659  pixt = pixClone(pixs);
660 
661  /* Make a copy if necessary */
662  pixd = pixCopy(pixd, pixt);
663  pixDestroy(&pixt);
664 
665  d = pixGetDepth(pixd);
666  if (d == 8) {
667  na = numaEqualizeTRC(pixd, fract, factor);
668  pixTRCMap(pixd, NULL, na);
669  numaDestroy(&na);
670  } else { /* 32 bpp */
671  pix8 = pixGetRGBComponent(pixd, COLOR_RED);
672  na = numaEqualizeTRC(pix8, fract, factor);
673  pixTRCMap(pix8, NULL, na);
674  pixSetRGBComponent(pixd, pix8, COLOR_RED);
675  numaDestroy(&na);
676  pixDestroy(&pix8);
677  pix8 = pixGetRGBComponent(pixd, COLOR_GREEN);
678  na = numaEqualizeTRC(pix8, fract, factor);
679  pixTRCMap(pix8, NULL, na);
680  pixSetRGBComponent(pixd, pix8, COLOR_GREEN);
681  numaDestroy(&na);
682  pixDestroy(&pix8);
683  pix8 = pixGetRGBComponent(pixd, COLOR_BLUE);
684  na = numaEqualizeTRC(pix8, fract, factor);
685  pixTRCMap(pix8, NULL, na);
686  pixSetRGBComponent(pixd, pix8, COLOR_BLUE);
687  numaDestroy(&na);
688  pixDestroy(&pix8);
689  }
690 
691  return pixd;
692 }
693 
694 
713 NUMA *
715  l_float32 fract,
716  l_int32 factor)
717 {
718 l_int32 iin, iout, itarg;
719 l_float32 val, sum;
720 NUMA *nah, *nasum, *nad;
721 
722  PROCNAME("numaEqualizeTRC");
723 
724  if (!pix)
725  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
726  if (pixGetDepth(pix) != 8)
727  return (NUMA *)ERROR_PTR("pix not 8 bpp", procName, NULL);
728  if (fract < 0.0 || fract > 1.0)
729  return (NUMA *)ERROR_PTR("fract not in [0.0 ... 1.0]", procName, NULL);
730  if (factor < 1)
731  return (NUMA *)ERROR_PTR("sampling factor < 1", procName, NULL);
732 
733  if (fract == 0.0)
734  L_WARNING("fract = 0.0; no equalization requested\n", procName);
735 
736  if ((nah = pixGetGrayHistogram(pix, factor)) == NULL)
737  return (NUMA *)ERROR_PTR("histogram not made", procName, NULL);
738  numaGetSum(nah, &sum);
739  nasum = numaGetPartialSums(nah);
740 
741  nad = numaCreate(256);
742  for (iin = 0; iin < 256; iin++) {
743  numaGetFValue(nasum, iin, &val);
744  itarg = (l_int32)(255. * val / sum + 0.5);
745  iout = iin + (l_int32)(fract * (itarg - iin));
746  iout = L_MIN(iout, 255); /* to be safe */
747  numaAddNumber(nad, iout);
748  }
749 
750  numaDestroy(&nah);
751  numaDestroy(&nasum);
752  return nad;
753 }
754 
755 
756 /*-------------------------------------------------------------*
757  * Generic TRC mapping *
758  *-------------------------------------------------------------*/
780 l_int32
782  PIX *pixm,
783  NUMA *na)
784 {
785 l_int32 w, h, d, wm, hm, wpl, wplm, i, j, sval8, dval8;
786 l_uint32 sval32, dval32;
787 l_uint32 *data, *datam, *line, *linem, *tab;
788 
789  PROCNAME("pixTRCMap");
790 
791  if (!pixs)
792  return ERROR_INT("pixs not defined", procName, 1);
793  if (pixGetColormap(pixs))
794  return ERROR_INT("pixs is colormapped", procName, 1);
795  if (!na)
796  return ERROR_INT("na not defined", procName, 1);
797  if (numaGetCount(na) != 256)
798  return ERROR_INT("na not of size 256", procName, 1);
799  pixGetDimensions(pixs, &w, &h, &d);
800  if (d != 8 && d != 32)
801  return ERROR_INT("pixs not 8 or 32 bpp", procName, 1);
802  if (pixm) {
803  if (pixGetDepth(pixm) != 1)
804  return ERROR_INT("pixm not 1 bpp", procName, 1);
805  }
806 
807  tab = (l_uint32 *)numaGetIArray(na); /* get the array for efficiency */
808  wpl = pixGetWpl(pixs);
809  data = pixGetData(pixs);
810  if (!pixm) {
811  if (d == 8) {
812  for (i = 0; i < h; i++) {
813  line = data + i * wpl;
814  for (j = 0; j < w; j++) {
815  sval8 = GET_DATA_BYTE(line, j);
816  dval8 = tab[sval8];
817  SET_DATA_BYTE(line, j, dval8);
818  }
819  }
820  } else { /* d == 32 */
821  for (i = 0; i < h; i++) {
822  line = data + i * wpl;
823  for (j = 0; j < w; j++) {
824  sval32 = *(line + j);
825  dval32 =
826  tab[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
827  tab[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
828  tab[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
829  *(line + j) = dval32;
830  }
831  }
832  }
833  } else {
834  datam = pixGetData(pixm);
835  wplm = pixGetWpl(pixm);
836  pixGetDimensions(pixm, &wm, &hm, NULL);
837  if (d == 8) {
838  for (i = 0; i < h; i++) {
839  if (i >= hm)
840  break;
841  line = data + i * wpl;
842  linem = datam + i * wplm;
843  for (j = 0; j < w; j++) {
844  if (j >= wm)
845  break;
846  if (GET_DATA_BIT(linem, j) == 0)
847  continue;
848  sval8 = GET_DATA_BYTE(line, j);
849  dval8 = tab[sval8];
850  SET_DATA_BYTE(line, j, dval8);
851  }
852  }
853  } else { /* d == 32 */
854  for (i = 0; i < h; i++) {
855  if (i >= hm)
856  break;
857  line = data + i * wpl;
858  linem = datam + i * wplm;
859  for (j = 0; j < w; j++) {
860  if (j >= wm)
861  break;
862  if (GET_DATA_BIT(linem, j) == 0)
863  continue;
864  sval32 = *(line + j);
865  dval32 =
866  tab[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
867  tab[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
868  tab[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
869  *(line + j) = dval32;
870  }
871  }
872  }
873  }
874 
875  LEPT_FREE(tab);
876  return 0;
877 }
878 
879 
880 
881 /*-----------------------------------------------------------------------*
882  * Unsharp masking *
883  *-----------------------------------------------------------------------*/
902 PIX *
904  l_int32 halfwidth,
905  l_float32 fract)
906 {
907 l_int32 d;
908 PIX *pixt, *pixd, *pixr, *pixrs, *pixg, *pixgs, *pixb, *pixbs;
909 
910  PROCNAME("pixUnsharpMasking");
911 
912  if (!pixs || (pixGetDepth(pixs) == 1))
913  return (PIX *)ERROR_PTR("pixs not defined or 1 bpp", procName, NULL);
914  if (fract <= 0.0 || halfwidth <= 0) {
915  L_WARNING("no sharpening requested; clone returned\n", procName);
916  return pixClone(pixs);
917  }
918 
919  if (halfwidth == 1 || halfwidth == 2)
920  return pixUnsharpMaskingFast(pixs, halfwidth, fract, L_BOTH_DIRECTIONS);
921 
922  /* Remove colormap; clone if possible; result is either 8 or 32 bpp */
923  if ((pixt = pixConvertTo8Or32(pixs, L_CLONE, 0)) == NULL)
924  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
925 
926  /* Sharpen */
927  d = pixGetDepth(pixt);
928  if (d == 8) {
929  pixd = pixUnsharpMaskingGray(pixt, halfwidth, fract);
930  } else { /* d == 32 */
932  pixrs = pixUnsharpMaskingGray(pixr, halfwidth, fract);
933  pixDestroy(&pixr);
935  pixgs = pixUnsharpMaskingGray(pixg, halfwidth, fract);
936  pixDestroy(&pixg);
938  pixbs = pixUnsharpMaskingGray(pixb, halfwidth, fract);
939  pixDestroy(&pixb);
940  pixd = pixCreateRGBImage(pixrs, pixgs, pixbs);
941  pixDestroy(&pixrs);
942  pixDestroy(&pixgs);
943  pixDestroy(&pixbs);
944  if (pixGetSpp(pixs) == 4)
945  pixScaleAndTransferAlpha(pixd, pixs, 1.0, 1.0);
946  }
947 
948  pixDestroy(&pixt);
949  return pixd;
950 }
951 
952 
971 PIX *
973  l_int32 halfwidth,
974  l_float32 fract)
975 {
976 l_int32 w, h, d;
977 PIX *pixc, *pixd;
978 PIXACC *pixacc;
979 
980  PROCNAME("pixUnsharpMaskingGray");
981 
982  if (!pixs)
983  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
984  pixGetDimensions(pixs, &w, &h, &d);
985  if (d != 8 || pixGetColormap(pixs) != NULL)
986  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
987  if (fract <= 0.0 || halfwidth <= 0) {
988  L_WARNING("no sharpening requested; clone returned\n", procName);
989  return pixClone(pixs);
990  }
991  if (halfwidth == 1 || halfwidth == 2)
992  return pixUnsharpMaskingGrayFast(pixs, halfwidth, fract,
993  L_BOTH_DIRECTIONS);
994 
995  if ((pixc = pixBlockconvGray(pixs, NULL, halfwidth, halfwidth)) == NULL)
996  return (PIX *)ERROR_PTR("pixc not made", procName, NULL);
997 
998  /* Steps:
999  * (1) edge image is pixs - pixc (this is highpass part)
1000  * (2) multiply edge image by fract
1001  * (3) add fraction of edge to pixs
1002  *
1003  * To show how this is done with both interfaces to arithmetic
1004  * on integer Pix, here is the implementation in the lower-level
1005  * function calls:
1006  * pixt = pixInitAccumulate(w, h, 0x10000000)) == NULL)
1007  * pixAccumulate(pixt, pixs, L_ARITH_ADD);
1008  * pixAccumulate(pixt, pixc, L_ARITH_SUBTRACT);
1009  * pixMultConstAccumulate(pixt, fract, 0x10000000);
1010  * pixAccumulate(pixt, pixs, L_ARITH_ADD);
1011  * pixd = pixFinalAccumulate(pixt, 0x10000000, 8)) == NULL)
1012  * pixDestroy(&pixt);
1013  *
1014  * The code below does the same thing using the Pixacc accumulator,
1015  * hiding the details of the offset that is needed for subtraction.
1016  */
1017  pixacc = pixaccCreate(w, h, 1);
1018  pixaccAdd(pixacc, pixs);
1019  pixaccSubtract(pixacc, pixc);
1020  pixaccMultConst(pixacc, fract);
1021  pixaccAdd(pixacc, pixs);
1022  pixd = pixaccFinal(pixacc, 8);
1023  pixaccDestroy(&pixacc);
1024 
1025  pixDestroy(&pixc);
1026  return pixd;
1027 }
1028 
1029 
1068 PIX *
1070  l_int32 halfwidth,
1071  l_float32 fract,
1072  l_int32 direction)
1073 {
1074 l_int32 d;
1075 PIX *pixt, *pixd, *pixr, *pixrs, *pixg, *pixgs, *pixb, *pixbs;
1076 
1077  PROCNAME("pixUnsharpMaskingFast");
1078 
1079  if (!pixs || (pixGetDepth(pixs) == 1))
1080  return (PIX *)ERROR_PTR("pixs not defined or 1 bpp", procName, NULL);
1081  if (fract <= 0.0 || halfwidth <= 0) {
1082  L_WARNING("no sharpening requested; clone returned\n", procName);
1083  return pixClone(pixs);
1084  }
1085  if (halfwidth != 1 && halfwidth != 2)
1086  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1087  if (direction != L_HORIZ && direction != L_VERT &&
1088  direction != L_BOTH_DIRECTIONS)
1089  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1090 
1091  /* Remove colormap; clone if possible; result is either 8 or 32 bpp */
1092  if ((pixt = pixConvertTo8Or32(pixs, L_CLONE, 0)) == NULL)
1093  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
1094 
1095  /* Sharpen */
1096  d = pixGetDepth(pixt);
1097  if (d == 8) {
1098  pixd = pixUnsharpMaskingGrayFast(pixt, halfwidth, fract, direction);
1099  } else { /* d == 32 */
1101  pixrs = pixUnsharpMaskingGrayFast(pixr, halfwidth, fract, direction);
1102  pixDestroy(&pixr);
1104  pixgs = pixUnsharpMaskingGrayFast(pixg, halfwidth, fract, direction);
1105  pixDestroy(&pixg);
1107  pixbs = pixUnsharpMaskingGrayFast(pixb, halfwidth, fract, direction);
1108  pixDestroy(&pixb);
1109  pixd = pixCreateRGBImage(pixrs, pixgs, pixbs);
1110  if (pixGetSpp(pixs) == 4)
1111  pixScaleAndTransferAlpha(pixd, pixs, 1.0, 1.0);
1112  pixDestroy(&pixrs);
1113  pixDestroy(&pixgs);
1114  pixDestroy(&pixbs);
1115  }
1116 
1117  pixDestroy(&pixt);
1118  return pixd;
1119 }
1120 
1121 
1122 
1139 PIX *
1141  l_int32 halfwidth,
1142  l_float32 fract,
1143  l_int32 direction)
1144 {
1145 PIX *pixd;
1146 
1147  PROCNAME("pixUnsharpMaskingGrayFast");
1148 
1149  if (!pixs)
1150  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1151  if (pixGetDepth(pixs) != 8 || pixGetColormap(pixs) != NULL)
1152  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1153  if (fract <= 0.0 || halfwidth <= 0) {
1154  L_WARNING("no sharpening requested; clone returned\n", procName);
1155  return pixClone(pixs);
1156  }
1157  if (halfwidth != 1 && halfwidth != 2)
1158  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1159  if (direction != L_HORIZ && direction != L_VERT &&
1160  direction != L_BOTH_DIRECTIONS)
1161  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1162 
1163  if (direction != L_BOTH_DIRECTIONS)
1164  pixd = pixUnsharpMaskingGray1D(pixs, halfwidth, fract, direction);
1165  else /* 2D sharpening */
1166  pixd = pixUnsharpMaskingGray2D(pixs, halfwidth, fract);
1167 
1168  return pixd;
1169 }
1170 
1171 
1188 PIX *
1190  l_int32 halfwidth,
1191  l_float32 fract,
1192  l_int32 direction)
1193 {
1194 l_int32 w, h, d, wpls, wpld, i, j, ival;
1195 l_uint32 *datas, *datad;
1196 l_uint32 *lines, *lines0, *lines1, *lines2, *lines3, *lines4, *lined;
1197 l_float32 val, a[5];
1198 PIX *pixd;
1199 
1200  PROCNAME("pixUnsharpMaskingGray1D");
1201 
1202  if (!pixs)
1203  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1204  pixGetDimensions(pixs, &w, &h, &d);
1205  if (d != 8 || pixGetColormap(pixs) != NULL)
1206  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1207  if (fract <= 0.0 || halfwidth <= 0) {
1208  L_WARNING("no sharpening requested; clone returned\n", procName);
1209  return pixClone(pixs);
1210  }
1211  if (halfwidth != 1 && halfwidth != 2)
1212  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1213 
1214  /* Initialize pixd with pixels from pixs that will not be
1215  * set when computing the sharpened values. */
1216  pixd = pixCopyBorder(NULL, pixs, halfwidth, halfwidth,
1217  halfwidth, halfwidth);
1218  datas = pixGetData(pixs);
1219  datad = pixGetData(pixd);
1220  wpls = pixGetWpl(pixs);
1221  wpld = pixGetWpl(pixd);
1222 
1223  if (halfwidth == 1) {
1224  a[0] = -fract / 3.0;
1225  a[1] = 1.0 + fract * 2.0 / 3.0;
1226  a[2] = a[0];
1227  } else { /* halfwidth == 2 */
1228  a[0] = -fract / 5.0;
1229  a[1] = a[0];
1230  a[2] = 1.0 + fract * 4.0 / 5.0;
1231  a[3] = a[0];
1232  a[4] = a[0];
1233  }
1234 
1235  if (direction == L_HORIZ) {
1236  for (i = 0; i < h; i++) {
1237  lines = datas + i * wpls;
1238  lined = datad + i * wpld;
1239  if (halfwidth == 1) {
1240  for (j = 1; j < w - 1; j++) {
1241  val = a[0] * GET_DATA_BYTE(lines, j - 1) +
1242  a[1] * GET_DATA_BYTE(lines, j) +
1243  a[2] * GET_DATA_BYTE(lines, j + 1);
1244  ival = (l_int32)val;
1245  ival = L_MAX(0, ival);
1246  ival = L_MIN(255, ival);
1247  SET_DATA_BYTE(lined, j, ival);
1248  }
1249  } else { /* halfwidth == 2 */
1250  for (j = 2; j < w - 2; j++) {
1251  val = a[0] * GET_DATA_BYTE(lines, j - 2) +
1252  a[1] * GET_DATA_BYTE(lines, j - 1) +
1253  a[2] * GET_DATA_BYTE(lines, j) +
1254  a[3] * GET_DATA_BYTE(lines, j + 1) +
1255  a[4] * GET_DATA_BYTE(lines, j + 2);
1256  ival = (l_int32)val;
1257  ival = L_MAX(0, ival);
1258  ival = L_MIN(255, ival);
1259  SET_DATA_BYTE(lined, j, ival);
1260  }
1261  }
1262  }
1263  } else { /* direction == L_VERT */
1264  if (halfwidth == 1) {
1265  for (i = 1; i < h - 1; i++) {
1266  lines0 = datas + (i - 1) * wpls;
1267  lines1 = datas + i * wpls;
1268  lines2 = datas + (i + 1) * wpls;
1269  lined = datad + i * wpld;
1270  for (j = 0; j < w; j++) {
1271  val = a[0] * GET_DATA_BYTE(lines0, j) +
1272  a[1] * GET_DATA_BYTE(lines1, j) +
1273  a[2] * GET_DATA_BYTE(lines2, j);
1274  ival = (l_int32)val;
1275  ival = L_MAX(0, ival);
1276  ival = L_MIN(255, ival);
1277  SET_DATA_BYTE(lined, j, ival);
1278  }
1279  }
1280  } else { /* halfwidth == 2 */
1281  for (i = 2; i < h - 2; i++) {
1282  lines0 = datas + (i - 2) * wpls;
1283  lines1 = datas + (i - 1) * wpls;
1284  lines2 = datas + i * wpls;
1285  lines3 = datas + (i + 1) * wpls;
1286  lines4 = datas + (i + 2) * wpls;
1287  lined = datad + i * wpld;
1288  for (j = 0; j < w; j++) {
1289  val = a[0] * GET_DATA_BYTE(lines0, j) +
1290  a[1] * GET_DATA_BYTE(lines1, j) +
1291  a[2] * GET_DATA_BYTE(lines2, j) +
1292  a[3] * GET_DATA_BYTE(lines3, j) +
1293  a[4] * GET_DATA_BYTE(lines4, j);
1294  ival = (l_int32)val;
1295  ival = L_MAX(0, ival);
1296  ival = L_MIN(255, ival);
1297  SET_DATA_BYTE(lined, j, ival);
1298  }
1299  }
1300  }
1301  }
1302 
1303  return pixd;
1304 }
1305 
1306 
1322 PIX *
1324  l_int32 halfwidth,
1325  l_float32 fract)
1326 {
1327 l_int32 w, h, d, wpls, wpld, wplf, i, j, ival, sval;
1328 l_uint32 *datas, *datad, *lines, *lined;
1329 l_float32 val, norm;
1330 l_float32 *dataf, *linef, *linef0, *linef1, *linef2, *linef3, *linef4;
1331 PIX *pixd;
1332 FPIX *fpix;
1333 
1334  PROCNAME("pixUnsharpMaskingGray2D");
1335 
1336  if (!pixs)
1337  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1338  pixGetDimensions(pixs, &w, &h, &d);
1339  if (d != 8 || pixGetColormap(pixs) != NULL)
1340  return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1341  if (fract <= 0.0 || halfwidth <= 0) {
1342  L_WARNING("no sharpening requested; clone returned\n", procName);
1343  return pixClone(pixs);
1344  }
1345  if (halfwidth != 1 && halfwidth != 2)
1346  return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1347 
1348  if ((pixd = pixCopyBorder(NULL, pixs, halfwidth, halfwidth,
1349  halfwidth, halfwidth)) == NULL)
1350  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1351  datad = pixGetData(pixd);
1352  wpld = pixGetWpl(pixd);
1353  datas = pixGetData(pixs);
1354  wpls = pixGetWpl(pixs);
1355 
1356  /* Do the low pass separably. Store the result of horizontal
1357  * smoothing in an intermediate fpix. */
1358  if ((fpix = fpixCreate(w, h)) == NULL) {
1359  pixDestroy(&pixd);
1360  return (PIX *)ERROR_PTR("fpix not made", procName, NULL);
1361  }
1362  dataf = fpixGetData(fpix);
1363  wplf = fpixGetWpl(fpix);
1364  if (halfwidth == 1) {
1365  for (i = 0; i < h; i++) {
1366  lines = datas + i * wpls;
1367  linef = dataf + i * wplf;
1368  for (j = 1; j < w - 1; j++) {
1369  val = GET_DATA_BYTE(lines, j - 1) +
1370  GET_DATA_BYTE(lines, j) +
1371  GET_DATA_BYTE(lines, j + 1);
1372  linef[j] = val;
1373  }
1374  }
1375  } else {
1376  for (i = 0; i < h; i++) {
1377  lines = datas + i * wpls;
1378  linef = dataf + i * wplf;
1379  for (j = 2; j < w - 2; j++) {
1380  val = GET_DATA_BYTE(lines, j - 2) +
1381  GET_DATA_BYTE(lines, j - 1) +
1382  GET_DATA_BYTE(lines, j) +
1383  GET_DATA_BYTE(lines, j + 1) +
1384  GET_DATA_BYTE(lines, j + 2);
1385  linef[j] = val;
1386  }
1387  }
1388  }
1389 
1390  /* Do vertical smoothing to finish the low-pass filter.
1391  * At each pixel, if L is the lowpass value, I is the
1392  * src pixel value and f is the fraction of highpass to
1393  * be added to I, then the highpass filter value is
1394  * H = I - L
1395  * and the new sharpened value is
1396  * N = I + f * H. */
1397  if (halfwidth == 1) {
1398  for (i = 1; i < h - 1; i++) {
1399  linef0 = dataf + (i - 1) * wplf;
1400  linef1 = dataf + i * wplf;
1401  linef2 = dataf + (i + 1) * wplf;
1402  lined = datad + i * wpld;
1403  lines = datas + i * wpls;
1404  norm = 1.0 / 9.0;
1405  for (j = 1; j < w - 1; j++) {
1406  val = norm * (linef0[j] + linef1[j] +
1407  linef2[j]); /* L: lowpass filter value */
1408  sval = GET_DATA_BYTE(lines, j); /* I: source pixel */
1409  ival = (l_int32)(sval + fract * (sval - val) + 0.5);
1410  ival = L_MAX(0, ival);
1411  ival = L_MIN(255, ival);
1412  SET_DATA_BYTE(lined, j, ival);
1413  }
1414  }
1415  } else {
1416  for (i = 2; i < h - 2; i++) {
1417  linef0 = dataf + (i - 2) * wplf;
1418  linef1 = dataf + (i - 1) * wplf;
1419  linef2 = dataf + i * wplf;
1420  linef3 = dataf + (i + 1) * wplf;
1421  linef4 = dataf + (i + 2) * wplf;
1422  lined = datad + i * wpld;
1423  lines = datas + i * wpls;
1424  norm = 1.0 / 25.0;
1425  for (j = 2; j < w - 2; j++) {
1426  val = norm * (linef0[j] + linef1[j] + linef2[j] + linef3[j] +
1427  linef4[j]); /* L: lowpass filter value */
1428  sval = GET_DATA_BYTE(lines, j); /* I: source pixel */
1429  ival = (l_int32)(sval + fract * (sval - val) + 0.5);
1430  ival = L_MAX(0, ival);
1431  ival = L_MIN(255, ival);
1432  SET_DATA_BYTE(lined, j, ival);
1433  }
1434  }
1435  }
1436 
1437  fpixDestroy(&fpix);
1438  return pixd;
1439 }
1440 
1441 
1442 /*-----------------------------------------------------------------------*
1443  * Hue and saturation modification *
1444  *-----------------------------------------------------------------------*/
1467 PIX *
1469  PIX *pixs,
1470  l_float32 fract)
1471 {
1472 l_int32 w, h, d, i, j, wpl, delhue;
1473 l_int32 rval, gval, bval, hval, sval, vval;
1474 l_uint32 *data, *line;
1475 
1476  PROCNAME("pixModifyHue");
1477 
1478  if (!pixs)
1479  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1480  if (pixGetColormap(pixs) != NULL)
1481  return (PIX *)ERROR_PTR("pixs colormapped", procName, NULL);
1482  if (pixd && (pixd != pixs))
1483  return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
1484  pixGetDimensions(pixs, &w, &h, &d);
1485  if (d != 32)
1486  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1487  if (L_ABS(fract) > 1.0)
1488  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1489 
1490  pixd = pixCopy(pixd, pixs);
1491 
1492  delhue = (l_int32)(240 * fract);
1493  if (delhue == 0 || delhue == 240 || delhue == -240) {
1494  L_WARNING("no change requested in hue\n", procName);
1495  return pixd;
1496  }
1497  if (delhue < 0)
1498  delhue += 240;
1499 
1500  data = pixGetData(pixd);
1501  wpl = pixGetWpl(pixd);
1502  for (i = 0; i < h; i++) {
1503  line = data + i * wpl;
1504  for (j = 0; j < w; j++) {
1505  extractRGBValues(line[j], &rval, &gval, &bval);
1506  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1507  hval = (hval + delhue) % 240;
1508  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1509  composeRGBPixel(rval, gval, bval, line + j);
1510  }
1511  }
1512  if (pixGetSpp(pixs) == 4)
1513  pixScaleAndTransferAlpha(pixd, pixs, 1.0, 1.0);
1514 
1515  return pixd;
1516 }
1517 
1518 
1540 PIX *
1542  PIX *pixs,
1543  l_float32 fract)
1544 {
1545 l_int32 w, h, d, i, j, wpl;
1546 l_int32 rval, gval, bval, hval, sval, vval;
1547 l_uint32 *data, *line;
1548 
1549  PROCNAME("pixModifySaturation");
1550 
1551  if (!pixs)
1552  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1553  pixGetDimensions(pixs, &w, &h, &d);
1554  if (d != 32)
1555  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1556  if (L_ABS(fract) > 1.0)
1557  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1558 
1559  pixd = pixCopy(pixd, pixs);
1560  if (fract == 0.0) {
1561  L_WARNING("no change requested in saturation\n", procName);
1562  return pixd;
1563  }
1564 
1565  data = pixGetData(pixd);
1566  wpl = pixGetWpl(pixd);
1567  for (i = 0; i < h; i++) {
1568  line = data + i * wpl;
1569  for (j = 0; j < w; j++) {
1570  extractRGBValues(line[j], &rval, &gval, &bval);
1571  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1572  if (fract < 0.0)
1573  sval = (l_int32)(sval * (1.0 + fract));
1574  else
1575  sval = (l_int32)(sval + fract * (255 - sval));
1576  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1577  composeRGBPixel(rval, gval, bval, line + j);
1578  }
1579  }
1580  if (pixGetSpp(pixs) == 4)
1581  pixScaleAndTransferAlpha(pixd, pixs, 1.0, 1.0);
1582 
1583  return pixd;
1584 }
1585 
1586 
1595 l_int32
1597  l_int32 factor,
1598  l_float32 *psat)
1599 {
1600 l_int32 w, h, d, i, j, wpl, sum, count;
1601 l_int32 rval, gval, bval, hval, sval, vval;
1602 l_uint32 *data, *line;
1603 
1604  PROCNAME("pixMeasureSaturation");
1605 
1606  if (!psat)
1607  return ERROR_INT("pixs not defined", procName, 1);
1608  *psat = 0.0;
1609  if (!pixs)
1610  return ERROR_INT("pixs not defined", procName, 1);
1611  pixGetDimensions(pixs, &w, &h, &d);
1612  if (d != 32)
1613  return ERROR_INT("pixs not 32 bpp", procName, 1);
1614  if (factor < 1)
1615  return ERROR_INT("subsampling factor < 1", procName, 1);
1616 
1617  data = pixGetData(pixs);
1618  wpl = pixGetWpl(pixs);
1619  for (i = 0, sum = 0, count = 0; i < h; i += factor) {
1620  line = data + i * wpl;
1621  for (j = 0; j < w; j += factor) {
1622  extractRGBValues(line[j], &rval, &gval, &bval);
1623  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1624  sum += sval;
1625  count++;
1626  }
1627  }
1628 
1629  if (count > 0)
1630  *psat = (l_float32)sum / (l_float32)count;
1631  return 0;
1632 }
1633 
1634 
1656 PIX *
1658  PIX *pixs,
1659  l_float32 fract)
1660 {
1661 l_int32 w, h, d, i, j, wpl;
1662 l_int32 rval, gval, bval, hval, sval, vval;
1663 l_uint32 *data, *line;
1664 
1665  PROCNAME("pixModifyBrightness");
1666 
1667  if (!pixs)
1668  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1669  pixGetDimensions(pixs, &w, &h, &d);
1670  if (d != 32)
1671  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1672  if (L_ABS(fract) > 1.0)
1673  return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1674 
1675  pixd = pixCopy(pixd, pixs);
1676  if (fract == 0.0) {
1677  L_WARNING("no change requested in brightness\n", procName);
1678  return pixd;
1679  }
1680 
1681  data = pixGetData(pixd);
1682  wpl = pixGetWpl(pixd);
1683  for (i = 0; i < h; i++) {
1684  line = data + i * wpl;
1685  for (j = 0; j < w; j++) {
1686  extractRGBValues(line[j], &rval, &gval, &bval);
1687  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1688  if (fract > 0.0)
1689  vval = (l_int32)(vval + fract * (255.0 - vval));
1690  else
1691  vval = (l_int32)(vval * (1.0 + fract));
1692  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1693  composeRGBPixel(rval, gval, bval, line + j);
1694  }
1695  }
1696  if (pixGetSpp(pixs) == 4)
1697  pixScaleAndTransferAlpha(pixd, pixs, 1.0, 1.0);
1698 
1699  return pixd;
1700 }
1701 
1702 
1703 /*-----------------------------------------------------------------------*
1704  * Color shifting *
1705  *-----------------------------------------------------------------------*/
1735 PIX *
1737  l_float32 roff,
1738  l_float32 goff,
1739  l_float32 boff,
1740  l_float32 delta,
1741  l_int32 nincr)
1742 {
1743 char buf[64];
1744 l_int32 i;
1745 l_float32 del;
1746 L_BMF *bmf;
1747 PIX *pix1, *pix2, *pix3;
1748 PIXA *pixa;
1749 
1750  PROCNAME("pixMosaicColorShiftRGB");
1751 
1752  if (!pixs || pixGetDepth(pixs) != 32)
1753  return (PIX *)ERROR_PTR("pixs undefined or not rgb", procName, NULL);
1754  if (roff < -1.0 || roff > 1.0)
1755  return (PIX *)ERROR_PTR("roff not in [-1.0, 1.0]", procName, NULL);
1756  if (goff < -1.0 || goff > 1.0)
1757  return (PIX *)ERROR_PTR("goff not in [-1.0, 1.0]", procName, NULL);
1758  if (boff < -1.0 || boff > 1.0)
1759  return (PIX *)ERROR_PTR("boff not in [-1.0, 1.0]", procName, NULL);
1760  if (delta < 0.0 || delta > 0.1)
1761  return (PIX *)ERROR_PTR("delta not in [0.0, 0.1]", procName, NULL);
1762  if (delta == 0.0) delta = 0.04;
1763  if (nincr < 0 || nincr > 6)
1764  return (PIX *)ERROR_PTR("nincr not in [0, 6]", procName, NULL);
1765  if (nincr == 0) nincr = 2;
1766 
1767  pixa = pixaCreate(3 * (2 * nincr + 1));
1768  bmf = bmfCreate(NULL, 8);
1769  pix1 = pixScaleToSize(pixs, 400, 0);
1770  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1771  pix2 = pixColorShiftRGB(pix1, roff + del, goff, boff);
1772  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1773  roff + del, goff, boff);
1774  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1775  L_ADD_BELOW, 0);
1776  pixaAddPix(pixa, pix3, L_INSERT);
1777  pixDestroy(&pix2);
1778  }
1779  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1780  pix2 = pixColorShiftRGB(pix1, roff, goff + del, boff);
1781  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1782  roff, goff + del, boff);
1783  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1784  L_ADD_BELOW, 0);
1785  pixaAddPix(pixa, pix3, L_INSERT);
1786  pixDestroy(&pix2);
1787  }
1788  for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1789  pix2 = pixColorShiftRGB(pix1, roff, goff, boff + del);
1790  snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1791  roff, goff, boff + del);
1792  pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1793  L_ADD_BELOW, 0);
1794  pixaAddPix(pixa, pix3, L_INSERT);
1795  pixDestroy(&pix2);
1796  }
1797  pixDestroy(&pix1);
1798 
1799  pix1 = pixaDisplayTiledAndScaled(pixa, 32, 300, 2 * nincr + 1, 0, 30, 2);
1800  pixaDestroy(&pixa);
1801  bmfDestroy(&bmf);
1802  return pix1;
1803 }
1804 
1805 
1831 PIX *
1833  l_float32 rfract,
1834  l_float32 gfract,
1835  l_float32 bfract)
1836 {
1837 l_int32 w, h, i, j, wpls, wpld, rval, gval, bval;
1838 l_int32 *rlut, *glut, *blut;
1839 l_uint32 *datas, *datad, *lines, *lined;
1840 l_float32 fi;
1841 PIX *pixd;
1842 
1843  PROCNAME("pixColorShiftRGB");
1844 
1845  if (!pixs)
1846  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1847  if (pixGetDepth(pixs) != 32)
1848  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1849  if (rfract < -1.0 || rfract > 1.0)
1850  return (PIX *)ERROR_PTR("rfract not in [-1.0, 1.0]", procName, NULL);
1851  if (gfract < -1.0 || gfract > 1.0)
1852  return (PIX *)ERROR_PTR("gfract not in [-1.0, 1.0]", procName, NULL);
1853  if (bfract < -1.0 || bfract > 1.0)
1854  return (PIX *)ERROR_PTR("bfract not in [-1.0, 1.0]", procName, NULL);
1855  if (rfract == 0.0 && gfract == 0.0 && bfract == 0.0)
1856  return pixCopy(NULL, pixs);
1857 
1858  rlut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1859  glut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1860  blut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1861  for (i = 0; i < 256; i++) {
1862  fi = i;
1863  if (rfract >= 0) {
1864  rlut[i] = (l_int32)(fi + (255.0 - fi) * rfract);
1865  } else {
1866  rlut[i] = (l_int32)(fi * (1.0 + rfract));
1867  }
1868  if (gfract >= 0) {
1869  glut[i] = (l_int32)(fi + (255.0 - fi) * gfract);
1870  } else {
1871  glut[i] = (l_int32)(fi * (1.0 + gfract));
1872  }
1873  if (bfract >= 0) {
1874  blut[i] = (l_int32)(fi + (255.0 - fi) * bfract);
1875  } else {
1876  blut[i] = (l_int32)(fi * (1.0 + bfract));
1877  }
1878  }
1879 
1880  pixGetDimensions(pixs, &w, &h, NULL);
1881  datas = pixGetData(pixs);
1882  wpls = pixGetWpl(pixs);
1883  pixd = pixCreate(w, h, 32);
1884  datad = pixGetData(pixd);
1885  wpld = pixGetWpl(pixd);
1886  for (i = 0; i < h; i++) {
1887  lines = datas + i * wpls;
1888  lined = datad + i * wpld;
1889  for (j = 0; j < w; j++) {
1890  extractRGBValues(lines[j], &rval, &gval, &bval);
1891  composeRGBPixel(rlut[rval], glut[gval], blut[bval], lined + j);
1892  }
1893  }
1894 
1895  LEPT_FREE(rlut);
1896  LEPT_FREE(glut);
1897  LEPT_FREE(blut);
1898  return pixd;
1899 }
1900 
1901 /*-----------------------------------------------------------------------*
1902  * Darken gray (unsaturated) pixels
1903  *-----------------------------------------------------------------------*/
1928 PIX *
1930  PIX *pixs,
1931  l_int32 thresh,
1932  l_int32 satlimit)
1933 {
1934 l_int32 w, h, i, j, wpls, wpld;
1935 l_int32 rval, gval, bval, minrg, min, maxrg, max, sat;
1936 l_uint32 *datas, *datad, *lines, *lined;
1937 l_float32 ratio;
1938 
1939  PROCNAME("pixDarkenGray");
1940 
1941  if (!pixs || pixGetDepth(pixs) != 32)
1942  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1943  if (thresh < 0 || thresh > 255)
1944  return (PIX *)ERROR_PTR("invalid thresh", procName, NULL);
1945  if (satlimit < 1)
1946  return (PIX *)ERROR_PTR("invalid satlimit", procName, NULL);
1947  if (pixd && (pixs != pixd))
1948  return (PIX *)ERROR_PTR("not new or in-place", procName, NULL);
1949 
1950  pixGetDimensions(pixs, &w, &h, NULL);
1951  datas = pixGetData(pixs);
1952  wpls = pixGetWpl(pixs);
1953  if ((pixd = pixCopy(pixd, pixs)) == NULL)
1954  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1955  datad = pixGetData(pixd);
1956  wpld = pixGetWpl(pixd);
1957 
1958  for (i = 0; i < h; i++) {
1959  lines = datas + i * wpls;
1960  lined = datad + i * wpld;
1961  for (j = 0; j < w; j++) {
1962  extractRGBValues(lines[j], &rval, &gval, &bval);
1963  minrg = L_MIN(rval, gval);
1964  min = L_MIN(minrg, bval);
1965  maxrg = L_MAX(rval, gval);
1966  max = L_MAX(maxrg, bval);
1967  sat = max - min;
1968  if (max >= thresh || sat >= satlimit)
1969  continue;
1970  ratio = (l_float32)sat / (l_float32)satlimit;
1971  composeRGBPixel((l_int32)(ratio * rval), (l_int32)(ratio * gval),
1972  (l_int32)(ratio * bval), &lined[j]);
1973  }
1974  }
1975  return pixd;
1976 }
1977 
1978 
1979 /*-----------------------------------------------------------------------*
1980  * General multiplicative constant color transform *
1981  *-----------------------------------------------------------------------*/
2000 PIX *
2002  l_float32 rfact,
2003  l_float32 gfact,
2004  l_float32 bfact)
2005 {
2006 l_int32 i, j, w, h, d, wpls, wpld;
2007 l_int32 ncolors, rval, gval, bval, nrval, ngval, nbval;
2008 l_uint32 nval;
2009 l_uint32 *datas, *datad, *lines, *lined;
2010 PIX *pixd;
2011 PIXCMAP *cmap;
2012 
2013  PROCNAME("pixMultConstantColor");
2014 
2015  if (!pixs)
2016  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2017  pixGetDimensions(pixs, &w, &h, &d);
2018  cmap = pixGetColormap(pixs);
2019  if (!cmap && d != 32)
2020  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
2021  rfact = L_MAX(0.0, rfact);
2022  gfact = L_MAX(0.0, gfact);
2023  bfact = L_MAX(0.0, bfact);
2024 
2025  if (cmap) {
2026  if ((pixd = pixCopy(NULL, pixs)) == NULL)
2027  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2028  cmap = pixGetColormap(pixd);
2029  ncolors = pixcmapGetCount(cmap);
2030  for (i = 0; i < ncolors; i++) {
2031  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2032  nrval = (l_int32)(rfact * rval);
2033  ngval = (l_int32)(gfact * gval);
2034  nbval = (l_int32)(bfact * bval);
2035  nrval = L_MIN(255, nrval);
2036  ngval = L_MIN(255, ngval);
2037  nbval = L_MIN(255, nbval);
2038  pixcmapResetColor(cmap, i, nrval, ngval, nbval);
2039  }
2040  return pixd;
2041  }
2042 
2043  if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL)
2044  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2045  datas = pixGetData(pixs);
2046  datad = pixGetData(pixd);
2047  wpls = pixGetWpl(pixs);
2048  wpld = pixGetWpl(pixd);
2049  for (i = 0; i < h; i++) {
2050  lines = datas + i * wpls;
2051  lined = datad + i * wpld;
2052  for (j = 0; j < w; j++) {
2053  extractRGBValues(lines[j], &rval, &gval, &bval);
2054  nrval = (l_int32)(rfact * rval);
2055  ngval = (l_int32)(gfact * gval);
2056  nbval = (l_int32)(bfact * bval);
2057  nrval = L_MIN(255, nrval);
2058  ngval = L_MIN(255, ngval);
2059  nbval = L_MIN(255, nbval);
2060  composeRGBPixel(nrval, ngval, nbval, &nval);
2061  *(lined + j) = nval;
2062  }
2063  }
2064 
2065  return pixd;
2066 }
2067 
2068 
2102 PIX *
2104  L_KERNEL *kel)
2105 {
2106 l_int32 i, j, index, kw, kh, w, h, d, wpls, wpld;
2107 l_int32 ncolors, rval, gval, bval, nrval, ngval, nbval;
2108 l_uint32 nval;
2109 l_uint32 *datas, *datad, *lines, *lined;
2110 l_float32 v[9]; /* use linear array for convenience */
2111 PIX *pixd;
2112 PIXCMAP *cmap;
2113 
2114  PROCNAME("pixMultMatrixColor");
2115 
2116  if (!pixs)
2117  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2118  if (!kel)
2119  return (PIX *)ERROR_PTR("kel not defined", procName, NULL);
2120  kernelGetParameters(kel, &kw, &kh, NULL, NULL);
2121  if (kw != 3 || kh != 3)
2122  return (PIX *)ERROR_PTR("matrix not 3x3", procName, NULL);
2123  pixGetDimensions(pixs, &w, &h, &d);
2124  cmap = pixGetColormap(pixs);
2125  if (!cmap && d != 32)
2126  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
2127 
2128  for (i = 0, index = 0; i < 3; i++)
2129  for (j = 0; j < 3; j++, index++)
2130  kernelGetElement(kel, i, j, v + index);
2131 
2132  if (cmap) {
2133  if ((pixd = pixCopy(NULL, pixs)) == NULL)
2134  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2135  cmap = pixGetColormap(pixd);
2136  ncolors = pixcmapGetCount(cmap);
2137  for (i = 0; i < ncolors; i++) {
2138  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2139  nrval = (l_int32)(v[0] * rval + v[1] * gval + v[2] * bval);
2140  ngval = (l_int32)(v[3] * rval + v[4] * gval + v[5] * bval);
2141  nbval = (l_int32)(v[6] * rval + v[7] * gval + v[8] * bval);
2142  nrval = L_MAX(0, L_MIN(255, nrval));
2143  ngval = L_MAX(0, L_MIN(255, ngval));
2144  nbval = L_MAX(0, L_MIN(255, nbval));
2145  pixcmapResetColor(cmap, i, nrval, ngval, nbval);
2146  }
2147  return pixd;
2148  }
2149 
2150  if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL)
2151  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2152  datas = pixGetData(pixs);
2153  datad = pixGetData(pixd);
2154  wpls = pixGetWpl(pixs);
2155  wpld = pixGetWpl(pixd);
2156  for (i = 0; i < h; i++) {
2157  lines = datas + i * wpls;
2158  lined = datad + i * wpld;
2159  for (j = 0; j < w; j++) {
2160  extractRGBValues(lines[j], &rval, &gval, &bval);
2161  nrval = (l_int32)(v[0] * rval + v[1] * gval + v[2] * bval);
2162  ngval = (l_int32)(v[3] * rval + v[4] * gval + v[5] * bval);
2163  nbval = (l_int32)(v[6] * rval + v[7] * gval + v[8] * bval);
2164  nrval = L_MAX(0, L_MIN(255, nrval));
2165  ngval = L_MAX(0, L_MIN(255, ngval));
2166  nbval = L_MAX(0, L_MIN(255, nbval));
2167  composeRGBPixel(nrval, ngval, nbval, &nval);
2168  *(lined + j) = nval;
2169  }
2170  }
2171 
2172  return pixd;
2173 }
2174 
2175 
2176 /*-------------------------------------------------------------*
2177  * Half-edge by bandpass *
2178  *-------------------------------------------------------------*/
2211 PIX *
2213  l_int32 sm1h,
2214  l_int32 sm1v,
2215  l_int32 sm2h,
2216  l_int32 sm2v)
2217 {
2218 l_int32 d;
2219 PIX *pixg, *pixacc, *pixc1, *pixc2;
2220 
2221  PROCNAME("pixHalfEdgeByBandpass");
2222 
2223  if (!pixs)
2224  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2225  if (sm1h == sm2h && sm1v == sm2v)
2226  return (PIX *)ERROR_PTR("sm2 = sm1", procName, NULL);
2227  d = pixGetDepth(pixs);
2228  if (d != 8 && d != 32)
2229  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
2230  if (d == 32)
2232  else /* d == 8 */
2233  pixg = pixClone(pixs);
2234 
2235  /* Make a convolution accumulator and use it twice */
2236  if ((pixacc = pixBlockconvAccum(pixg)) == NULL) {
2237  pixDestroy(&pixg);
2238  return (PIX *)ERROR_PTR("pixacc not made", procName, NULL);
2239  }
2240  if ((pixc1 = pixBlockconvGray(pixg, pixacc, sm1h, sm1v)) == NULL) {
2241  pixDestroy(&pixg);
2242  pixDestroy(&pixacc);
2243  return (PIX *)ERROR_PTR("pixc1 not made", procName, NULL);
2244  }
2245  pixc2 = pixBlockconvGray(pixg, pixacc, sm2h, sm2v);
2246  pixDestroy(&pixg);
2247  pixDestroy(&pixacc);
2248  if (!pixc2) {
2249  pixDestroy(&pixc1);
2250  return (PIX *)ERROR_PTR("pixc2 not made", procName, NULL);
2251  }
2252 
2253  /* Compute the half-edge using pixc1 - pixc2. */
2254  pixSubtractGray(pixc1, pixc1, pixc2);
2255  pixDestroy(&pixc2);
2256  return pixc1;
2257 }
l_ok numaGetSum(NUMA *na, l_float32 *psum)
numaGetSum()
Definition: numafunc1.c:527
PIX * pixConvertRGBToLuminance(PIX *pixs)
pixConvertRGBToLuminance()
Definition: pixconv.c:733
NUMA * pixGetGrayHistogram(PIX *pixs, l_int32 factor)
pixGetGrayHistogram()
Definition: pix4.c:109
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:166
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:692
PIX * pixContrastTRCMasked(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 factor)
pixContrastTRCMasked()
Definition: enhance.c:498
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:322
l_int32 h
Definition: dewarp.h:164
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2463
Definition: pix.h:717
PIX * pixUnsharpMaskingGray2D(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMaskingGray2D()
Definition: enhance.c:1323
l_ok kernelGetParameters(L_KERNEL *kel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
kernelGetParameters()
Definition: kernel.c:270
PIX * pixContrastTRC(PIX *pixd, PIX *pixs, l_float32 factor)
pixContrastTRC()
Definition: enhance.c:436
PIX * pixBlockconvAccum(PIX *pixs)
pixBlockconvAccum()
Definition: convolve.c:455
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
PIX * pixUnsharpMaskingGrayFast(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingGrayFast()
Definition: enhance.c:1140
NUMA * numaGammaTRC(l_float32 gamma, l_int32 minval, l_int32 maxval)
numaGammaTRC()
Definition: enhance.c:366
PIX * pixModifyBrightness(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifyBrightness()
Definition: enhance.c:1657
PIX * pixGammaTRCWithAlpha(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRCWithAlpha()
Definition: enhance.c:306
l_int32 pixTRCMap(PIX *pixs, PIX *pixm, NUMA *na)
pixTRCMap()
Definition: enhance.c:781
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
NUMA * numaGetPartialSums(NUMA *na)
numaGetPartialSums()
Definition: numafunc1.c:566
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
l_ok pixaccMultConst(PIXACC *pixacc, l_float32 factor)
pixaccMultConst()
Definition: pixacc.c:297
PIX * pixCreateTemplateNoInit(PIX *pixs)
pixCreateTemplateNoInit()
Definition: pix1.c:397
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2404
Definition: bmf.h:45
PIX * pixMultConstantColor(PIX *pixs, l_float32 rfact, l_float32 gfact, l_float32 bfact)
pixMultConstantColor()
Definition: enhance.c:2001
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:820
struct Pix * pixs
Definition: dewarp.h:154
void pixaccDestroy(PIXACC **ppixacc)
pixaccDestroy()
Definition: pixacc.c:160
PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtractGray()
Definition: pixarith.c:353
PIX * pixModifyHue(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifyHue()
Definition: enhance.c:1468
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
PIX * pixUnsharpMaskingGray(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMaskingGray()
Definition: enhance.c:972
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
PIX * pixEqualizeTRC(PIX *pixd, PIX *pixs, l_float32 fract, l_int32 factor)
pixEqualizeTRC()
Definition: enhance.c:627
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:335
l_ok pixcmapContrastTRC(PIXCMAP *cmap, l_float32 factor)
pixcmapContrastTRC()
Definition: colormap.c:2178
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:751
l_int32 pixMeasureSaturation(PIX *pixs, l_int32 factor, l_float32 *psat)
pixMeasureSaturation()
Definition: enhance.c:1596
Definition: pix.h:546
#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:1832
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:459
PIX * pixGammaTRCMasked(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRCMasked()
Definition: enhance.c:242
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2348
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
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:1137
PIX * pixModifySaturation(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifySaturation()
Definition: enhance.c:1541
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:317
PIX * pixBlockconvGray(PIX *pixs, PIX *pixacc, l_int32 wc, l_int32 hc)
pixBlockconvGray()
Definition: convolve.c:210
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:750
NUMA * numaContrastTRC(l_float32 factor)
numaContrastTRC()
Definition: enhance.c:557
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:273
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
Definition: colormap.c:893
l_float32 * fpixGetData(FPIX *fpix)
fpixGetData()
Definition: fpix1.c:602
PIX * pixaccFinal(PIXACC *pixacc, l_int32 outdepth)
pixaccFinal()
Definition: pixacc.c:192
PIX * pixMosaicColorShiftRGB(PIX *pixs, l_float32 roff, l_float32 goff, l_float32 boff, l_float32 delta, l_int32 nincr)
pixMosaicColorShiftRGB()
Definition: enhance.c:1736
Definition: pix.h:454
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
PIX * pixHalfEdgeByBandpass(PIX *pixs, l_int32 sm1h, l_int32 sm1v, l_int32 sm2h, l_int32 sm2v)
pixHalfEdgeByBandpass()
Definition: enhance.c:2212
FPIX * fpixCreate(l_int32 width, l_int32 height)
fpixCreate()
Definition: fpix1.c:153
l_ok kernelGetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 *pval)
kernelGetElement()
Definition: kernel.c:211
PIX * pixUnsharpMasking(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMasking()
Definition: enhance.c:903
PIXACC * pixaccCreate(l_int32 w, l_int32 h, l_int32 negflag)
pixaccCreate()
Definition: pixacc.c:90
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:635
Definition: morph.h:89
Definition: pix.h:134
Definition: pix.h:719
l_ok pixaccSubtract(PIXACC *pixacc, PIX *pix)
pixaccSubtract()
Definition: pixacc.c:275
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
PIX * pixGammaTRC(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRC()
Definition: enhance.c:174
Definition: pix.h:201
PIX * pixUnsharpMaskingFast(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingFast()
Definition: enhance.c:1069
NUMA * numaEqualizeTRC(PIX *pix, l_float32 fract, l_int32 factor)
numaEqualizeTRC()
Definition: enhance.c:714
l_ok pixaccAdd(PIXACC *pixacc, PIX *pix)
pixaccAdd()
Definition: pixacc.c:253
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
PIX * pixUnsharpMaskingGray1D(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingGray1D()
Definition: enhance.c:1189
l_int32 w
Definition: dewarp.h:163
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:373
l_ok pixScaleAndTransferAlpha(PIX *pixd, PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleAndTransferAlpha()
Definition: scale2.c:1358
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
PIX * pixCopyBorder(PIX *pixd, PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixCopyBorder()
Definition: pix2.c:1694
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:115
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2737
l_ok pixcmapGammaTRC(PIXCMAP *cmap, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixcmapGammaTRC()
Definition: colormap.c:2123
PIX * pixDarkenGray(PIX *pixd, PIX *pixs, l_int32 thresh, l_int32 satlimit)
pixDarkenGray()
Definition: enhance.c:1929
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition: pixconv.c:3393
Definition: pix.h:582
PIX * pixMultMatrixColor(PIX *pixs, L_KERNEL *kel)
pixMultMatrixColor()
Definition: enhance.c:2103
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:114