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