Leptonica  1.82.0
Image processing and image analysis suite
pix5.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 
105 #ifdef HAVE_CONFIG_H
106 #include <config_auto.h>
107 #endif /* HAVE_CONFIG_H */
108 
109 #include <string.h>
110 #include <math.h>
111 #include "allheaders.h"
112 
113 static const l_uint32 rmask32[] = {0x0,
114  0x00000001, 0x00000003, 0x00000007, 0x0000000f,
115  0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
116  0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
117  0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
118  0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
119  0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
120  0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
121  0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};
122 
123 #ifndef NO_CONSOLE_IO
124 #define DEBUG_EDGES 0
125 #endif /* ~NO_CONSOLE_IO */
126 
127 
128 /*-------------------------------------------------------------*
129  * Measurement of properties *
130  *-------------------------------------------------------------*/
139 l_ok
141  NUMA **pnaw,
142  NUMA **pnah)
143 {
144 l_int32 i, n, w, h;
145 PIX *pixt;
146 
147  PROCNAME("pixaFindDimensions");
148 
149  if (pnaw) *pnaw = NULL;
150  if (pnah) *pnah = NULL;
151  if (!pnaw && !pnah)
152  return ERROR_INT("no output requested", procName, 1);
153  if (!pixa)
154  return ERROR_INT("pixa not defined", procName, 1);
155 
156  n = pixaGetCount(pixa);
157  if (pnaw) *pnaw = numaCreate(n);
158  if (pnah) *pnah = numaCreate(n);
159  for (i = 0; i < n; i++) {
160  pixt = pixaGetPix(pixa, i, L_CLONE);
161  pixGetDimensions(pixt, &w, &h, NULL);
162  if (pnaw)
163  numaAddNumber(*pnaw, w);
164  if (pnah)
165  numaAddNumber(*pnah, h);
166  pixDestroy(&pixt);
167  }
168  return 0;
169 }
170 
171 
189 l_ok
191  l_int32 *tab,
192  l_float32 *pfract)
193 {
194 l_int32 *tab8;
195 l_int32 nfg, nbound;
196 PIX *pixt;
197 
198  PROCNAME("pixFindAreaPerimRatio");
199 
200  if (!pfract)
201  return ERROR_INT("&fract not defined", procName, 1);
202  *pfract = 0.0;
203  if (!pixs || pixGetDepth(pixs) != 1)
204  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
205 
206  if (!tab)
207  tab8 = makePixelSumTab8();
208  else
209  tab8 = tab;
210 
211  pixt = pixErodeBrick(NULL, pixs, 3, 3);
212  pixCountPixels(pixt, &nfg, tab8);
213  if (nfg == 0) {
214  pixDestroy(&pixt);
215  if (!tab) LEPT_FREE(tab8);
216  return 0;
217  }
218  pixXor(pixt, pixt, pixs);
219  pixCountPixels(pixt, &nbound, tab8);
220  *pfract = (l_float32)nfg / (l_float32)nbound;
221  pixDestroy(&pixt);
222 
223  if (!tab) LEPT_FREE(tab8);
224  return 0;
225 }
226 
227 
240 NUMA *
242 {
243 l_int32 i, n;
244 l_int32 *tab;
245 l_float32 fract;
246 NUMA *na;
247 PIX *pixt;
248 
249  PROCNAME("pixaFindPerimToAreaRatio");
250 
251  if (!pixa)
252  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
253 
254  n = pixaGetCount(pixa);
255  na = numaCreate(n);
256  tab = makePixelSumTab8();
257  for (i = 0; i < n; i++) {
258  pixt = pixaGetPix(pixa, i, L_CLONE);
259  pixFindPerimToAreaRatio(pixt, tab, &fract);
260  numaAddNumber(na, fract);
261  pixDestroy(&pixt);
262  }
263  LEPT_FREE(tab);
264  return na;
265 }
266 
267 
290 l_ok
292  l_int32 *tab,
293  l_float32 *pfract)
294 {
295 l_int32 *tab8;
296 l_int32 nfg, nbound;
297 PIX *pixt;
298 
299  PROCNAME("pixFindPerimToAreaRatio");
300 
301  if (!pfract)
302  return ERROR_INT("&fract not defined", procName, 1);
303  *pfract = 0.0;
304  if (!pixs || pixGetDepth(pixs) != 1)
305  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
306 
307  if (!tab)
308  tab8 = makePixelSumTab8();
309  else
310  tab8 = tab;
311 
312  pixCountPixels(pixs, &nfg, tab8);
313  if (nfg == 0) {
314  if (!tab) LEPT_FREE(tab8);
315  return 0;
316  }
317  pixt = pixErodeBrick(NULL, pixs, 3, 3);
318  pixXor(pixt, pixt, pixs);
319  pixCountPixels(pixt, &nbound, tab8);
320  *pfract = (l_float32)nbound / (l_float32)nfg;
321  pixDestroy(&pixt);
322 
323  if (!tab) LEPT_FREE(tab8);
324  return 0;
325 }
326 
327 
344 NUMA *
346 {
347 l_int32 i, n;
348 l_int32 *tab;
349 l_float32 ratio;
350 NUMA *na;
351 PIX *pixt;
352 
353  PROCNAME("pixaFindPerimSizeRatio");
354 
355  if (!pixa)
356  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
357 
358  n = pixaGetCount(pixa);
359  na = numaCreate(n);
360  tab = makePixelSumTab8();
361  for (i = 0; i < n; i++) {
362  pixt = pixaGetPix(pixa, i, L_CLONE);
363  pixFindPerimSizeRatio(pixt, tab, &ratio);
364  numaAddNumber(na, ratio);
365  pixDestroy(&pixt);
366  }
367  LEPT_FREE(tab);
368  return na;
369 }
370 
371 
394 l_ok
396  l_int32 *tab,
397  l_float32 *pratio)
398 {
399 l_int32 *tab8;
400 l_int32 w, h, nbound;
401 PIX *pixt;
402 
403  PROCNAME("pixFindPerimSizeRatio");
404 
405  if (!pratio)
406  return ERROR_INT("&ratio not defined", procName, 1);
407  *pratio = 0.0;
408  if (!pixs || pixGetDepth(pixs) != 1)
409  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
410 
411  if (!tab)
412  tab8 = makePixelSumTab8();
413  else
414  tab8 = tab;
415 
416  pixt = pixErodeBrick(NULL, pixs, 3, 3);
417  pixXor(pixt, pixt, pixs);
418  pixCountPixels(pixt, &nbound, tab8);
419  pixGetDimensions(pixs, &w, &h, NULL);
420  *pratio = (0.5 * nbound) / (l_float32)(w + h);
421  pixDestroy(&pixt);
422 
423  if (!tab) LEPT_FREE(tab8);
424  return 0;
425 }
426 
427 
440 NUMA *
442 {
443 l_int32 i, n;
444 l_int32 *tab;
445 l_float32 fract;
446 NUMA *na;
447 PIX *pixt;
448 
449  PROCNAME("pixaFindAreaFraction");
450 
451  if (!pixa)
452  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
453 
454  n = pixaGetCount(pixa);
455  na = numaCreate(n);
456  tab = makePixelSumTab8();
457  for (i = 0; i < n; i++) {
458  pixt = pixaGetPix(pixa, i, L_CLONE);
459  pixFindAreaFraction(pixt, tab, &fract);
460  numaAddNumber(na, fract);
461  pixDestroy(&pixt);
462  }
463  LEPT_FREE(tab);
464  return na;
465 }
466 
467 
483 l_ok
485  l_int32 *tab,
486  l_float32 *pfract)
487 {
488 l_int32 w, h, sum;
489 l_int32 *tab8;
490 
491  PROCNAME("pixFindAreaFraction");
492 
493  if (!pfract)
494  return ERROR_INT("&fract not defined", procName, 1);
495  *pfract = 0.0;
496  if (!pixs || pixGetDepth(pixs) != 1)
497  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
498 
499  if (!tab)
500  tab8 = makePixelSumTab8();
501  else
502  tab8 = tab;
503  pixGetDimensions(pixs, &w, &h, NULL);
504  pixCountPixels(pixs, &sum, tab8);
505  *pfract = (l_float32)sum / (l_float32)(w * h);
506 
507  if (!tab) LEPT_FREE(tab8);
508  return 0;
509 }
510 
511 
531 NUMA *
533  PIX *pixm,
534  l_int32 debug)
535 {
536 l_int32 i, n, full;
537 l_int32 *tab;
538 l_float32 fract;
539 BOX *box;
540 NUMA *na;
541 PIX *pix;
542 
543  PROCNAME("pixaFindAreaFractionMasked");
544 
545  if (!pixa)
546  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
547  if (!pixm || pixGetDepth(pixm) != 1)
548  return (NUMA *)ERROR_PTR("pixm undefined or not 1 bpp", procName, NULL);
549 
550  n = pixaGetCount(pixa);
551  na = numaCreate(n);
552  tab = makePixelSumTab8();
553  pixaIsFull(pixa, NULL, &full); /* check boxa */
554  box = NULL;
555  for (i = 0; i < n; i++) {
556  pix = pixaGetPix(pixa, i, L_CLONE);
557  if (full)
558  box = pixaGetBox(pixa, i, L_CLONE);
559  pixFindAreaFractionMasked(pix, box, pixm, tab, &fract);
560  numaAddNumber(na, fract);
561  boxDestroy(&box);
562  pixDestroy(&pix);
563  }
564  LEPT_FREE(tab);
565 
566  if (debug) {
567  l_int32 w, h;
568  PIX *pix1, *pix2;
569  pixGetDimensions(pixm, &w, &h, NULL);
570  pix1 = pixaDisplay(pixa, w, h); /* recover original image */
571  pix2 = pixCreate(w, h, 8); /* make an 8 bpp white image ... */
572  pixSetColormap(pix2, pixcmapCreate(8)); /* that's cmapped ... */
573  pixSetBlackOrWhite(pix2, L_SET_WHITE); /* and init to white */
574  pixSetMaskedCmap(pix2, pix1, 0, 0, 255, 0, 0); /* color all fg red */
575  pixRasterop(pix1, 0, 0, w, h, PIX_MASK, pixm, 0, 0);
576  pixSetMaskedCmap(pix2, pix1, 0, 0, 0, 255, 0); /* turn masked green */
577  pixDisplay(pix2, 100, 100);
578  pixDestroy(&pix1);
579  pixDestroy(&pix2);
580  }
581 
582  return na;
583 }
584 
585 
610 l_ok
612  BOX *box,
613  PIX *pixm,
614  l_int32 *tab,
615  l_float32 *pfract)
616 {
617 l_int32 x, y, w, h, sum, masksum;
618 l_int32 *tab8;
619 PIX *pix1;
620 
621  PROCNAME("pixFindAreaFractionMasked");
622 
623  if (!pfract)
624  return ERROR_INT("&fract not defined", procName, 1);
625  *pfract = 0.0;
626  if (!pixs || pixGetDepth(pixs) != 1)
627  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
628  if (!pixm || pixGetDepth(pixm) != 1)
629  return ERROR_INT("pixm not defined or not 1 bpp", procName, 1);
630 
631  if (!tab)
632  tab8 = makePixelSumTab8();
633  else
634  tab8 = tab;
635  x = y = 0;
636  if (box)
637  boxGetGeometry(box, &x, &y, NULL, NULL);
638  pixGetDimensions(pixs, &w, &h, NULL);
639 
640  pix1 = pixCopy(NULL, pixs);
641  pixRasterop(pix1, 0, 0, w, h, PIX_MASK, pixm, x, y);
642  pixCountPixels(pixs, &sum, tab8);
643  if (sum == 0) {
644  pixDestroy(&pix1);
645  if (!tab) LEPT_FREE(tab8);
646  return 0;
647  }
648  pixCountPixels(pix1, &masksum, tab8);
649  *pfract = (l_float32)masksum / (l_float32)sum;
650 
651  if (!tab) LEPT_FREE(tab8);
652  pixDestroy(&pix1);
653  return 0;
654 }
655 
656 
669 NUMA *
671 {
672 l_int32 i, n, w, h;
673 NUMA *na;
674 PIX *pixt;
675 
676  PROCNAME("pixaFindWidthHeightRatio");
677 
678  if (!pixa)
679  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
680 
681  n = pixaGetCount(pixa);
682  na = numaCreate(n);
683  for (i = 0; i < n; i++) {
684  pixt = pixaGetPix(pixa, i, L_CLONE);
685  pixGetDimensions(pixt, &w, &h, NULL);
686  numaAddNumber(na, (l_float32)w / (l_float32)h);
687  pixDestroy(&pixt);
688  }
689  return na;
690 }
691 
692 
705 NUMA *
707 {
708 l_int32 i, n, w, h;
709 NUMA *na;
710 PIX *pixt;
711 
712  PROCNAME("pixaFindWidthHeightProduct");
713 
714  if (!pixa)
715  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
716 
717  n = pixaGetCount(pixa);
718  na = numaCreate(n);
719  for (i = 0; i < n; i++) {
720  pixt = pixaGetPix(pixa, i, L_CLONE);
721  pixGetDimensions(pixt, &w, &h, NULL);
722  numaAddNumber(na, w * h);
723  pixDestroy(&pixt);
724  }
725  return na;
726 }
727 
728 
745 l_ok
747  PIX *pixs2,
748  l_int32 x2,
749  l_int32 y2,
750  l_int32 *tab,
751  l_float32 *pratio,
752  l_int32 *pnoverlap)
753 {
754 l_int32 *tab8;
755 l_int32 w, h, nintersect, nunion;
756 PIX *pixt;
757 
758  PROCNAME("pixFindOverlapFraction");
759 
760  if (pnoverlap) *pnoverlap = 0;
761  if (!pratio)
762  return ERROR_INT("&ratio not defined", procName, 1);
763  *pratio = 0.0;
764  if (!pixs1 || pixGetDepth(pixs1) != 1)
765  return ERROR_INT("pixs1 not defined or not 1 bpp", procName, 1);
766  if (!pixs2 || pixGetDepth(pixs2) != 1)
767  return ERROR_INT("pixs2 not defined or not 1 bpp", procName, 1);
768 
769  if (!tab)
770  tab8 = makePixelSumTab8();
771  else
772  tab8 = tab;
773 
774  pixGetDimensions(pixs2, &w, &h, NULL);
775  pixt = pixCopy(NULL, pixs1);
776  pixRasterop(pixt, x2, y2, w, h, PIX_MASK, pixs2, 0, 0); /* AND */
777  pixCountPixels(pixt, &nintersect, tab8);
778  if (pnoverlap)
779  *pnoverlap = nintersect;
780  pixCopy(pixt, pixs1);
781  pixRasterop(pixt, x2, y2, w, h, PIX_PAINT, pixs2, 0, 0); /* OR */
782  pixCountPixels(pixt, &nunion, tab8);
783  if (!tab) LEPT_FREE(tab8);
784  pixDestroy(&pixt);
785 
786  if (nunion > 0)
787  *pratio = (l_float32)nintersect / (l_float32)nunion;
788  return 0;
789 }
790 
791 
812 BOXA *
814  l_int32 dist,
815  l_int32 minw,
816  l_int32 minh)
817 {
818 l_int32 w, h, i, n, conforms;
819 BOX *box;
820 BOXA *boxa, *boxad;
821 PIX *pix;
822 PIXA *pixa;
823 
824  PROCNAME("pixFindRectangleComps");
825 
826  if (!pixs || pixGetDepth(pixs) != 1)
827  return (BOXA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
828  if (dist < 0)
829  return (BOXA *)ERROR_PTR("dist must be >= 0", procName, NULL);
830  if (minw <= 2 * dist && minh <= 2 * dist)
831  return (BOXA *)ERROR_PTR("invalid parameters", procName, NULL);
832 
833  boxa = pixConnComp(pixs, &pixa, 8);
834  boxad = boxaCreate(0);
835  n = pixaGetCount(pixa);
836  for (i = 0; i < n; i++) {
837  pix = pixaGetPix(pixa, i, L_CLONE);
838  pixGetDimensions(pix, &w, &h, NULL);
839  if (w < minw || h < minh) {
840  pixDestroy(&pix);
841  continue;
842  }
843  pixConformsToRectangle(pix, NULL, dist, &conforms);
844  if (conforms) {
845  box = boxaGetBox(boxa, i, L_COPY);
846  boxaAddBox(boxad, box, L_INSERT);
847  }
848  pixDestroy(&pix);
849  }
850  boxaDestroy(&boxa);
851  pixaDestroy(&pixa);
852  return boxad;
853 }
854 
855 
892 l_ok
894  BOX *box,
895  l_int32 dist,
896  l_int32 *pconforms)
897 {
898 l_int32 w, h, empty;
899 PIX *pix1, *pix2;
900 
901  PROCNAME("pixConformsToRectangle");
902 
903  if (!pconforms)
904  return ERROR_INT("&conforms not defined", procName, 1);
905  *pconforms = 0;
906  if (!pixs || pixGetDepth(pixs) != 1)
907  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
908  if (dist < 0)
909  return ERROR_INT("dist must be >= 0", procName, 1);
910  pixGetDimensions(pixs, &w, &h, NULL);
911  if (w <= 2 * dist || h <= 2 * dist) {
912  L_WARNING("automatic conformation: distance too large\n", procName);
913  *pconforms = 1;
914  return 0;
915  }
916 
917  /* Extract the region, if necessary */
918  if (box)
919  pix1 = pixClipRectangle(pixs, box, NULL);
920  else
921  pix1 = pixCopy(NULL, pixs);
922 
923  /* Invert and fill from the boundary into the interior.
924  * Because we're considering the connected component in an
925  * 8-connected sense, we do the background filling as 4 c.c. */
926  pixInvert(pix1, pix1);
927  pix2 = pixExtractBorderConnComps(pix1, 4);
928 
929  /* Mask out all pixels within a distance %dist from the box
930  * boundary. Any remaining pixels are from filling that goes
931  * more than %dist from the boundary. If no pixels remain,
932  * the component conforms to the bounding rectangle within
933  * a distance %dist. */
934  pixSetOrClearBorder(pix2, dist, dist, dist, dist, PIX_CLR);
935  pixZero(pix2, &empty);
936  pixDestroy(&pix1);
937  pixDestroy(&pix2);
938  *pconforms = (empty) ? 1 : 0;
939  return 0;
940 }
941 
942 
943 /*-----------------------------------------------------------------------*
944  * Extract rectangular region *
945  *-----------------------------------------------------------------------*/
959 PIXA *
961  BOXA *boxa)
962 {
963 l_int32 i, n;
964 BOX *box, *boxc;
965 PIX *pix;
966 PIXA *pixa;
967 
968  PROCNAME("pixClipRectangles");
969 
970  if (!pixs)
971  return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
972  if (!boxa)
973  return (PIXA *)ERROR_PTR("boxa not defined", procName, NULL);
974 
975  n = boxaGetCount(boxa);
976  pixa = pixaCreate(n);
977  for (i = 0; i < n; i++) {
978  box = boxaGetBox(boxa, i, L_CLONE);
979  pix = pixClipRectangle(pixs, box, &boxc);
980  pixaAddPix(pixa, pix, L_INSERT);
981  pixaAddBox(pixa, boxc, L_INSERT);
982  boxDestroy(&box);
983  }
984 
985  return pixa;
986 }
987 
988 
1025 PIX *
1027  BOX *box,
1028  BOX **pboxc)
1029 {
1030 l_int32 w, h, d, bx, by, bw, bh;
1031 BOX *boxc;
1032 PIX *pixd;
1033 
1034  PROCNAME("pixClipRectangle");
1035 
1036  if (pboxc) *pboxc = NULL;
1037  if (!pixs)
1038  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1039  if (!box)
1040  return (PIX *)ERROR_PTR("box not defined", procName, NULL);
1041 
1042  /* Clip the input box to the pix */
1043  pixGetDimensions(pixs, &w, &h, &d);
1044  if ((boxc = boxClipToRectangle(box, w, h)) == NULL) {
1045  L_WARNING("box doesn't overlap pix\n", procName);
1046  return NULL;
1047  }
1048  boxGetGeometry(boxc, &bx, &by, &bw, &bh);
1049 
1050  /* Extract the block */
1051  if ((pixd = pixCreate(bw, bh, d)) == NULL) {
1052  boxDestroy(&boxc);
1053  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1054  }
1055  pixCopyResolution(pixd, pixs);
1056  pixCopyColormap(pixd, pixs);
1057  pixCopyText(pixd, pixs);
1058  pixRasterop(pixd, 0, 0, bw, bh, PIX_SRC, pixs, bx, by);
1059 
1060  if (pboxc)
1061  *pboxc = boxc;
1062  else
1063  boxDestroy(&boxc);
1064 
1065  return pixd;
1066 }
1067 
1068 
1088 PIX *
1090  BOX *box,
1091  l_int32 maxbord,
1092  BOX **pboxn)
1093 {
1094 l_int32 w, h, bx, by, bw, bh, bord;
1095 BOX *box1;
1096 PIX *pix1;
1097 
1098  PROCNAME("pixClipRectangleWithBorder");
1099 
1100  if (!pboxn)
1101  return (PIX *)ERROR_PTR("&boxn not defined", procName, NULL);
1102  *pboxn = NULL;
1103  if (!pixs)
1104  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1105  if (!box)
1106  return (PIX *)ERROR_PTR("box not defined", procName, NULL);
1107 
1108  /* Determine the border width */
1109  pixGetDimensions(pixs, &w, &h, NULL);
1110  boxGetGeometry(box, &bx, &by, &bw, &bh);
1111  bord = L_MIN(bx, by);
1112  bord = L_MIN(bord, w - bx - bw);
1113  bord = L_MIN(bord, h - by - bh);
1114  bord = L_MIN(bord, maxbord);
1115 
1116  if (bord <= 0) { /* standard clipping */
1117  pix1 = pixClipRectangle(pixs, box, NULL);
1118  pixGetDimensions(pix1, &w, &h, NULL);
1119  *pboxn = boxCreate(0, 0, w, h);
1120  return pix1;
1121  }
1122 
1123  /* There is a positive border */
1124  box1 = boxAdjustSides(NULL, box, -bord, bord, -bord, bord);
1125  pix1 = pixClipRectangle(pixs, box1, NULL);
1126  boxDestroy(&box1);
1127  *pboxn = boxCreate(bord, bord, bw, bh);
1128  return pix1;
1129 }
1130 
1131 
1161 PIX *
1163  PIX *pixm,
1164  l_int32 x,
1165  l_int32 y,
1166  l_uint32 outval)
1167 {
1168 l_int32 wm, hm, index, rval, gval, bval;
1169 l_uint32 pixel;
1170 BOX *box;
1171 PIX *pixmi, *pixd;
1172 PIXCMAP *cmap;
1173 
1174  PROCNAME("pixClipMasked");
1175 
1176  if (!pixs)
1177  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1178  if (!pixm || pixGetDepth(pixm) != 1)
1179  return (PIX *)ERROR_PTR("pixm undefined or not 1 bpp", procName, NULL);
1180 
1181  /* Clip out the region specified by pixm and (x,y) */
1182  pixGetDimensions(pixm, &wm, &hm, NULL);
1183  box = boxCreate(x, y, wm, hm);
1184  pixd = pixClipRectangle(pixs, box, NULL);
1185 
1186  /* Paint 'outval' (or something close to it if cmapped) through
1187  * the pixels not masked by pixm */
1188  cmap = pixGetColormap(pixd);
1189  pixmi = pixInvert(NULL, pixm);
1190  if (cmap) {
1191  extractRGBValues(outval, &rval, &gval, &bval);
1192  pixcmapGetNearestIndex(cmap, rval, gval, bval, &index);
1193  pixcmapGetColor(cmap, index, &rval, &gval, &bval);
1194  composeRGBPixel(rval, gval, bval, &pixel);
1195  pixPaintThroughMask(pixd, pixmi, 0, 0, pixel);
1196  } else {
1197  pixPaintThroughMask(pixd, pixmi, 0, 0, outval);
1198  }
1199 
1200  boxDestroy(&box);
1201  pixDestroy(&pixmi);
1202  return pixd;
1203 }
1204 
1205 
1223 l_ok
1225  PIX *pixs2,
1226  PIX **ppixd1,
1227  PIX **ppixd2)
1228 {
1229 l_int32 w1, h1, w2, h2, w, h;
1230 
1231  PROCNAME("pixCropToMatch");
1232 
1233  if (!ppixd1 || !ppixd2)
1234  return ERROR_INT("&pixd1 and &pixd2 not both defined", procName, 1);
1235  *ppixd1 = *ppixd2 = NULL;
1236  if (!pixs1 || !pixs2)
1237  return ERROR_INT("pixs1 and pixs2 not defined", procName, 1);
1238 
1239  pixGetDimensions(pixs1, &w1, &h1, NULL);
1240  pixGetDimensions(pixs2, &w2, &h2, NULL);
1241  w = L_MIN(w1, w2);
1242  h = L_MIN(h1, h2);
1243 
1244  *ppixd1 = pixCropToSize(pixs1, w, h);
1245  *ppixd2 = pixCropToSize(pixs2, w, h);
1246  if (*ppixd1 == NULL || *ppixd2 == NULL)
1247  return ERROR_INT("cropped image failure", procName, 1);
1248  return 0;
1249 }
1250 
1251 
1266 PIX *
1268  l_int32 w,
1269  l_int32 h)
1270 {
1271 l_int32 ws, hs, wd, hd, d;
1272 PIX *pixd;
1273 
1274  PROCNAME("pixCropToSize");
1275 
1276  if (!pixs)
1277  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1278 
1279  pixGetDimensions(pixs, &ws, &hs, &d);
1280  if (ws <= w && hs <= h) /* no cropping necessary */
1281  return pixClone(pixs);
1282 
1283  wd = L_MIN(ws, w);
1284  hd = L_MIN(hs, h);
1285  if ((pixd = pixCreate(wd, hd, d)) == NULL)
1286  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1287  pixCopyResolution(pixd, pixs);
1288  pixCopyColormap(pixd, pixs);
1289  pixCopyText(pixd, pixs);
1290  pixCopyInputFormat(pixd, pixs);
1291  pixRasterop(pixd, 0, 0, wd, hd, PIX_SRC, pixs, 0, 0);
1292  return pixd;
1293 }
1294 
1295 
1320 PIX *
1322  PIX *pixt,
1323  l_int32 w,
1324  l_int32 h)
1325 {
1326 l_int32 i, j, ws, hs, d;
1327 PIX *pixd;
1328 
1329  PROCNAME("pixResizeToMatch");
1330 
1331  if (!pixs)
1332  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1333  if (!pixt && (w <= 0 || h <= 0))
1334  return (PIX *)ERROR_PTR("both w and h not > 0", procName, NULL);
1335 
1336  if (pixt) /* redefine w, h */
1337  pixGetDimensions(pixt, &w, &h, NULL);
1338  pixGetDimensions(pixs, &ws, &hs, &d);
1339  if (ws == w && hs == h)
1340  return pixCopy(NULL, pixs);
1341 
1342  if ((pixd = pixCreate(w, h, d)) == NULL)
1343  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1344  pixCopyResolution(pixd, pixs);
1345  pixCopyColormap(pixd, pixs);
1346  pixCopyText(pixd, pixs);
1347  pixCopyInputFormat(pixd, pixs);
1348  pixRasterop(pixd, 0, 0, ws, hs, PIX_SRC, pixs, 0, 0);
1349  if (ws >= w && hs >= h)
1350  return pixd;
1351 
1352  /* Replicate the last column and then the last row */
1353  if (ws < w) {
1354  for (j = ws; j < w; j++)
1355  pixRasterop(pixd, j, 0, 1, h, PIX_SRC, pixd, ws - 1, 0);
1356  }
1357  if (hs < h) {
1358  for (i = hs; i < h; i++)
1359  pixRasterop(pixd, 0, i, w, 1, PIX_SRC, pixd, 0, hs - 1);
1360  }
1361 
1362  return pixd;
1363 }
1364 
1365 
1366 /*---------------------------------------------------------------------*
1367  * Select a connected component by size *
1368  *---------------------------------------------------------------------*/
1389 PIX *
1390 pixSelectComponentBySize(PIX *pixs,
1391  l_int32 rankorder,
1392  l_int32 type,
1393  l_int32 connectivity,
1394  BOX **pbox)
1395 {
1396 l_int32 n, empty, sorttype, index;
1397 BOXA *boxa1;
1398 NUMA *naindex;
1399 PIX *pixd;
1400 PIXA *pixa1, *pixa2;
1401 
1402  PROCNAME("pixSelectComponentBySize");
1403 
1404  if (pbox) *pbox = NULL;
1405  if (!pixs || pixGetDepth(pixs) != 1)
1406  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1407  if (type == L_SELECT_BY_WIDTH)
1408  sorttype = L_SORT_BY_WIDTH;
1409  else if (type == L_SELECT_BY_HEIGHT)
1410  sorttype = L_SORT_BY_HEIGHT;
1411  else if (type == L_SELECT_BY_MAX_DIMENSION)
1412  sorttype = L_SORT_BY_MAX_DIMENSION;
1413  else if (type == L_SELECT_BY_AREA)
1414  sorttype = L_SORT_BY_AREA;
1415  else if (type == L_SELECT_BY_PERIMETER)
1416  sorttype = L_SORT_BY_PERIMETER;
1417  else
1418  return (PIX *)ERROR_PTR("invalid selection type", procName, NULL);
1419  if (connectivity != 4 && connectivity != 8)
1420  return (PIX *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
1421  pixZero(pixs, &empty);
1422  if (empty)
1423  return (PIX *)ERROR_PTR("no foreground pixels", procName, NULL);
1424 
1425  boxa1 = pixConnComp(pixs, &pixa1, connectivity);
1426  n = boxaGetCount(boxa1);
1427  if (rankorder < 0 || rankorder >= n)
1428  rankorder = n - 1; /* smallest */
1429  pixa2 = pixaSort(pixa1, sorttype, L_SORT_DECREASING, &naindex, L_CLONE);
1430  pixd = pixaGetPix(pixa2, rankorder, L_COPY);
1431  if (pbox) {
1432  numaGetIValue(naindex, rankorder, &index);
1433  *pbox = boxaGetBox(boxa1, index, L_COPY);
1434  }
1435 
1436  numaDestroy(&naindex);
1437  boxaDestroy(&boxa1);
1438  pixaDestroy(&pixa1);
1439  pixaDestroy(&pixa2);
1440  return pixd;
1441 }
1442 
1443 
1462 PIX *
1463 pixFilterComponentBySize(PIX *pixs,
1464  l_int32 rankorder,
1465  l_int32 type,
1466  l_int32 connectivity,
1467  BOX **pbox)
1468 {
1469 l_int32 x, y, w, h;
1470 BOX *box;
1471 PIX *pix1, *pix2;
1472 
1473  PROCNAME("pixFilterComponentBySize");
1474 
1475  if (!pixs || pixGetDepth(pixs) != 1)
1476  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1477 
1478  pix1 = pixSelectComponentBySize(pixs, rankorder, type, connectivity, &box);
1479  if (!pix1) {
1480  boxDestroy(&box);
1481  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1482  }
1483 
1484  /* Put the selected component in a new pix at the same
1485  * location as it had in %pixs */
1486  boxGetGeometry(box, &x, &y, &w, &h);
1487  pix2 = pixCreateTemplate(pixs);
1488  pixRasterop(pix2, x, y, w, h, PIX_SRC, pix1, 0, 0);
1489  if (pbox)
1490  *pbox = box;
1491  else
1492  boxDestroy(&box);
1493  pixDestroy(&pix1);
1494  return pix2;
1495 }
1496 
1497 
1498 /*---------------------------------------------------------------------*
1499  * Make special masks *
1500  *---------------------------------------------------------------------*/
1531 PIX *
1533  l_int32 h,
1534  l_float32 hf,
1535  l_float32 vf,
1536  l_int32 type)
1537 {
1538  PROCNAME("pixMakeSymmetricMask");
1539 
1540  if (w <= 0 || h <= 0)
1541  return (PIX *)ERROR_PTR("mask size 0", procName, NULL);
1542  if (hf < 0.0 || hf > 1.0)
1543  return (PIX *)ERROR_PTR("invalid horiz fractions", procName, NULL);
1544  if (vf < 0.0 || vf > 1.0)
1545  return (PIX *)ERROR_PTR("invalid vert fractions", procName, NULL);
1546 
1547  if (type == L_USE_INNER)
1548  return pixMakeFrameMask(w, h, hf, 1.0, vf, 1.0);
1549  else if (type == L_USE_OUTER)
1550  return pixMakeFrameMask(w, h, 0.0, hf, 0.0, vf);
1551  else
1552  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1553 }
1554 
1555 
1588 PIX *
1590  l_int32 h,
1591  l_float32 hf1,
1592  l_float32 hf2,
1593  l_float32 vf1,
1594  l_float32 vf2)
1595 {
1596 l_int32 h1, h2, v1, v2;
1597 PIX *pixd;
1598 
1599  PROCNAME("pixMakeFrameMask");
1600 
1601  if (w <= 0 || h <= 0)
1602  return (PIX *)ERROR_PTR("mask size 0", procName, NULL);
1603  if (hf1 < 0.0 || hf1 > 1.0 || hf2 < 0.0 || hf2 > 1.0)
1604  return (PIX *)ERROR_PTR("invalid horiz fractions", procName, NULL);
1605  if (vf1 < 0.0 || vf1 > 1.0 || vf2 < 0.0 || vf2 > 1.0)
1606  return (PIX *)ERROR_PTR("invalid vert fractions", procName, NULL);
1607  if (hf1 > hf2 || vf1 > vf2)
1608  return (PIX *)ERROR_PTR("invalid relative sizes", procName, NULL);
1609 
1610  pixd = pixCreate(w, h, 1);
1611 
1612  /* Special cases */
1613  if (hf1 == 0.0 && vf1 == 0.0 && hf2 == 1.0 && vf2 == 1.0) { /* full */
1614  pixSetAll(pixd);
1615  return pixd;
1616  }
1617  if (hf1 == hf2 && vf1 == vf2) { /* empty */
1618  return pixd;
1619  }
1620 
1621  /* General case */
1622  h1 = 0.5 * hf1 * w;
1623  h2 = 0.5 * hf2 * w;
1624  v1 = 0.5 * vf1 * h;
1625  v2 = 0.5 * vf2 * h;
1626  pixRasterop(pixd, h1, v1, w - 2 * h1, h - 2 * v1, PIX_SET, NULL, 0, 0);
1627  if (hf2 < 1.0 && vf2 < 1.0)
1628  pixRasterop(pixd, h2, v2, w - 2 * h2, h - 2 * v2, PIX_CLR, NULL, 0, 0);
1629  return pixd;
1630 }
1631 
1632 
1633 /*---------------------------------------------------------------------*
1634  * Generate a covering of rectangles over connected components *
1635  *---------------------------------------------------------------------*/
1654 PIX *
1656  l_int32 maxiters)
1657 {
1658 l_int32 empty, same, niters;
1659 BOXA *boxa;
1660 PIX *pix1, *pix2;
1661 
1662  PROCNAME("pixMakeCoveringOfRectangles");
1663 
1664  if (!pixs || pixGetDepth(pixs) != 1)
1665  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1666  if (maxiters < 0)
1667  return (PIX *)ERROR_PTR("maxiters must be >= 0", procName, NULL);
1668  if (maxiters == 0) maxiters = 50; /* ridiculously large number */
1669 
1670  pixZero(pixs, &empty);
1671  pix1 = pixCreateTemplate(pixs);
1672  if (empty) return pix1;
1673 
1674  /* Do first iteration */
1675  boxa = pixConnCompBB(pixs, 8);
1676  pixMaskBoxa(pix1, pix1, boxa, L_SET_PIXELS);
1677  boxaDestroy(&boxa);
1678  if (maxiters == 1) return pix1;
1679 
1680  niters = 1;
1681  while (niters < maxiters) { /* continue to add pixels to pix1 */
1682  niters++;
1683  boxa = pixConnCompBB(pix1, 8);
1684  pix2 = pixCopy(NULL, pix1);
1685  pixMaskBoxa(pix1, pix1, boxa, L_SET_PIXELS);
1686  boxaDestroy(&boxa);
1687  pixEqual(pix1, pix2, &same);
1688  pixDestroy(&pix2);
1689  if (same) {
1690  L_INFO("%d iterations\n", procName, niters - 1);
1691  return pix1;
1692  }
1693  }
1694  L_INFO("maxiters = %d reached\n", procName, niters);
1695  return pix1;
1696 }
1697 
1698 
1699 /*---------------------------------------------------------------------*
1700  * Fraction of Fg pixels under a mask *
1701  *---------------------------------------------------------------------*/
1727 l_ok
1729  PIX *pix2,
1730  l_float32 *pfract)
1731 {
1732 l_int32 w1, h1, w2, h2, empty, count1, count3;
1733 PIX *pix3;
1734 
1735  PROCNAME("pixFractionFgInMask");
1736 
1737  if (!pfract)
1738  return ERROR_INT("&fract not defined", procName, 1);
1739  *pfract = 0.0;
1740  if (!pix1 || pixGetDepth(pix1) != 1)
1741  return ERROR_INT("pix1 not defined or not 1 bpp", procName, 1);
1742  if (!pix2 || pixGetDepth(pix2) != 1)
1743  return ERROR_INT("pix2 not defined or not 1 bpp", procName, 1);
1744 
1745  pixGetDimensions(pix1, &w1, &h1, NULL);
1746  pixGetDimensions(pix2, &w2, &h2, NULL);
1747  if (w1 != w2 || h1 != h2) {
1748  L_INFO("sizes unequal: (w1,w2) = (%d,%d), (h1,h2) = (%d,%d)\n",
1749  procName, w1, w2, h1, h2);
1750  }
1751  pixZero(pix1, &empty);
1752  if (empty) return 0;
1753  pixZero(pix2, &empty);
1754  if (empty) return 0;
1755 
1756  pix3 = pixCopy(NULL, pix1);
1757  pixAnd(pix3, pix3, pix2);
1758  pixCountPixels(pix1, &count1, NULL); /* |1| */
1759  pixCountPixels(pix3, &count3, NULL); /* |1 & 2| */
1760  *pfract = (l_float32)count3 / (l_float32)count1;
1761  pixDestroy(&pix3);
1762  return 0;
1763 }
1764 
1765 
1766 /*---------------------------------------------------------------------*
1767  * Clip to Foreground *
1768  *---------------------------------------------------------------------*/
1783 l_ok
1785  PIX **ppixd,
1786  BOX **pbox)
1787 {
1788 l_int32 w, h, wpl, nfullwords, extra, i, j;
1789 l_int32 minx, miny, maxx, maxy;
1790 l_uint32 result, mask;
1791 l_uint32 *data, *line;
1792 BOX *box;
1793 
1794  PROCNAME("pixClipToForeground");
1795 
1796  if (ppixd) *ppixd = NULL;
1797  if (pbox) *pbox = NULL;
1798  if (!ppixd && !pbox)
1799  return ERROR_INT("no output requested", procName, 1);
1800  if (!pixs || (pixGetDepth(pixs) != 1))
1801  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1802 
1803  pixGetDimensions(pixs, &w, &h, NULL);
1804  nfullwords = w / 32;
1805  extra = w & 31;
1806  mask = ~rmask32[32 - extra];
1807  wpl = pixGetWpl(pixs);
1808  data = pixGetData(pixs);
1809 
1810  result = 0;
1811  for (i = 0, miny = 0; i < h; i++, miny++) {
1812  line = data + i * wpl;
1813  for (j = 0; j < nfullwords; j++)
1814  result |= line[j];
1815  if (extra)
1816  result |= (line[j] & mask);
1817  if (result)
1818  break;
1819  }
1820  if (miny == h) /* no ON pixels */
1821  return 1;
1822 
1823  result = 0;
1824  for (i = h - 1, maxy = h - 1; i >= 0; i--, maxy--) {
1825  line = data + i * wpl;
1826  for (j = 0; j < nfullwords; j++)
1827  result |= line[j];
1828  if (extra)
1829  result |= (line[j] & mask);
1830  if (result)
1831  break;
1832  }
1833 
1834  minx = 0;
1835  for (j = 0, minx = 0; j < w; j++, minx++) {
1836  for (i = 0; i < h; i++) {
1837  line = data + i * wpl;
1838  if (GET_DATA_BIT(line, j))
1839  goto minx_found;
1840  }
1841  }
1842 
1843 minx_found:
1844  for (j = w - 1, maxx = w - 1; j >= 0; j--, maxx--) {
1845  for (i = 0; i < h; i++) {
1846  line = data + i * wpl;
1847  if (GET_DATA_BIT(line, j))
1848  goto maxx_found;
1849  }
1850  }
1851 
1852 maxx_found:
1853  box = boxCreate(minx, miny, maxx - minx + 1, maxy - miny + 1);
1854 
1855  if (ppixd)
1856  *ppixd = pixClipRectangle(pixs, box, NULL);
1857  if (pbox)
1858  *pbox = box;
1859  else
1860  boxDestroy(&box);
1861 
1862  return 0;
1863 }
1864 
1865 
1883 l_ok
1885  l_int32 *pcanclip)
1886 {
1887 l_int32 i, j, w, h, wpl, found;
1888 l_uint32 *data, *line;
1889 
1890  PROCNAME("pixTestClipToForeground");
1891 
1892  if (!pcanclip)
1893  return ERROR_INT("&canclip not defined", procName, 1);
1894  *pcanclip = 0;
1895  if (!pixs || (pixGetDepth(pixs) != 1))
1896  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1897 
1898  /* Check top and bottom raster lines */
1899  pixGetDimensions(pixs, &w, &h, NULL);
1900  data = pixGetData(pixs);
1901  wpl = pixGetWpl(pixs);
1902  found = FALSE;
1903  for (j = 0; found == FALSE && j < w; j++)
1904  found = GET_DATA_BIT(data, j);
1905  if (!found) {
1906  *pcanclip = 1;
1907  return 0;
1908  }
1909 
1910  line = data + (h - 1) * wpl;
1911  found = FALSE;
1912  for (j = 0; found == FALSE && j < w; j++)
1913  found = GET_DATA_BIT(data, j);
1914  if (!found) {
1915  *pcanclip = 1;
1916  return 0;
1917  }
1918 
1919  /* Check left and right edges */
1920  found = FALSE;
1921  for (i = 0, line = data; found == FALSE && i < h; line += wpl, i++)
1922  found = GET_DATA_BIT(line, 0);
1923  if (!found) {
1924  *pcanclip = 1;
1925  return 0;
1926  }
1927 
1928  found = FALSE;
1929  for (i = 0, line = data; found == FALSE && i < h; line += wpl, i++)
1930  found = GET_DATA_BIT(line, w - 1);
1931  if (!found)
1932  *pcanclip = 1;
1933 
1934  return 0; /* fg pixels found on all edges */
1935 }
1936 
1937 
1955 l_ok
1957  BOX *boxs,
1958  PIX **ppixd,
1959  BOX **pboxd)
1960 {
1961 l_int32 w, h, bx, by, bw, bh, cbw, cbh, left, right, top, bottom;
1962 BOX *boxt, *boxd;
1963 
1964  PROCNAME("pixClipBoxToForeground");
1965 
1966  if (ppixd) *ppixd = NULL;
1967  if (pboxd) *pboxd = NULL;
1968  if (!ppixd && !pboxd)
1969  return ERROR_INT("no output requested", procName, 1);
1970  if (!pixs || (pixGetDepth(pixs) != 1))
1971  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1972 
1973  if (!boxs)
1974  return pixClipToForeground(pixs, ppixd, pboxd);
1975 
1976  pixGetDimensions(pixs, &w, &h, NULL);
1977  boxGetGeometry(boxs, &bx, &by, &bw, &bh);
1978  cbw = L_MIN(bw, w - bx);
1979  cbh = L_MIN(bh, h - by);
1980  if (cbw < 0 || cbh < 0)
1981  return ERROR_INT("box not within image", procName, 1);
1982  boxt = boxCreate(bx, by, cbw, cbh);
1983 
1984  if (pixScanForForeground(pixs, boxt, L_FROM_LEFT, &left)) {
1985  boxDestroy(&boxt);
1986  return 1;
1987  }
1988  pixScanForForeground(pixs, boxt, L_FROM_RIGHT, &right);
1989  pixScanForForeground(pixs, boxt, L_FROM_TOP, &top);
1990  pixScanForForeground(pixs, boxt, L_FROM_BOT, &bottom);
1991 
1992  boxd = boxCreate(left, top, right - left + 1, bottom - top + 1);
1993  if (ppixd)
1994  *ppixd = pixClipRectangle(pixs, boxd, NULL);
1995  if (pboxd)
1996  *pboxd = boxd;
1997  else
1998  boxDestroy(&boxd);
1999 
2000  boxDestroy(&boxt);
2001  return 0;
2002 }
2003 
2004 
2021 l_ok
2023  BOX *box,
2024  l_int32 scanflag,
2025  l_int32 *ploc)
2026 {
2027 l_int32 bx, by, bw, bh, x, xstart, xend, y, ystart, yend, wpl;
2028 l_uint32 *data, *line;
2029 BOX *boxt;
2030 
2031  PROCNAME("pixScanForForeground");
2032 
2033  if (!ploc)
2034  return ERROR_INT("&loc not defined", procName, 1);
2035  *ploc = 0;
2036  if (!pixs || (pixGetDepth(pixs) != 1))
2037  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
2038 
2039  /* Clip box to pixs if it exists */
2040  pixGetDimensions(pixs, &bw, &bh, NULL);
2041  if (box) {
2042  if ((boxt = boxClipToRectangle(box, bw, bh)) == NULL)
2043  return ERROR_INT("invalid box", procName, 1);
2044  boxGetGeometry(boxt, &bx, &by, &bw, &bh);
2045  boxDestroy(&boxt);
2046  } else {
2047  bx = by = 0;
2048  }
2049  xstart = bx;
2050  ystart = by;
2051  xend = bx + bw - 1;
2052  yend = by + bh - 1;
2053 
2054  data = pixGetData(pixs);
2055  wpl = pixGetWpl(pixs);
2056  if (scanflag == L_FROM_LEFT) {
2057  for (x = xstart; x <= xend; x++) {
2058  for (y = ystart; y <= yend; y++) {
2059  line = data + y * wpl;
2060  if (GET_DATA_BIT(line, x)) {
2061  *ploc = x;
2062  return 0;
2063  }
2064  }
2065  }
2066  } else if (scanflag == L_FROM_RIGHT) {
2067  for (x = xend; x >= xstart; x--) {
2068  for (y = ystart; y <= yend; y++) {
2069  line = data + y * wpl;
2070  if (GET_DATA_BIT(line, x)) {
2071  *ploc = x;
2072  return 0;
2073  }
2074  }
2075  }
2076  } else if (scanflag == L_FROM_TOP) {
2077  for (y = ystart; y <= yend; y++) {
2078  line = data + y * wpl;
2079  for (x = xstart; x <= xend; x++) {
2080  if (GET_DATA_BIT(line, x)) {
2081  *ploc = y;
2082  return 0;
2083  }
2084  }
2085  }
2086  } else if (scanflag == L_FROM_BOT) {
2087  for (y = yend; y >= ystart; y--) {
2088  line = data + y * wpl;
2089  for (x = xstart; x <= xend; x++) {
2090  if (GET_DATA_BIT(line, x)) {
2091  *ploc = y;
2092  return 0;
2093  }
2094  }
2095  }
2096  } else {
2097  return ERROR_INT("invalid scanflag", procName, 1);
2098  }
2099 
2100  return 1; /* no fg found */
2101 }
2102 
2103 
2137 l_ok
2139  BOX *boxs,
2140  l_int32 lowthresh,
2141  l_int32 highthresh,
2142  l_int32 maxwidth,
2143  l_int32 factor,
2144  PIX **ppixd,
2145  BOX **pboxd)
2146 {
2147 l_int32 w, h, bx, by, bw, bh, cbw, cbh, left, right, top, bottom;
2148 l_int32 lfound, rfound, tfound, bfound, change;
2149 BOX *boxt, *boxd;
2150 
2151  PROCNAME("pixClipBoxToEdges");
2152 
2153  if (ppixd) *ppixd = NULL;
2154  if (pboxd) *pboxd = NULL;
2155  if (!ppixd && !pboxd)
2156  return ERROR_INT("no output requested", procName, 1);
2157  if (!pixs || (pixGetDepth(pixs) != 1))
2158  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
2159  if (lowthresh < 1 || highthresh < 1 ||
2160  lowthresh > highthresh || maxwidth < 1)
2161  return ERROR_INT("invalid thresholds", procName, 1);
2162  factor = L_MIN(1, factor);
2163 
2164  if (lowthresh == 1 && highthresh == 1)
2165  return pixClipBoxToForeground(pixs, boxs, ppixd, pboxd);
2166 
2167  pixGetDimensions(pixs, &w, &h, NULL);
2168  if (boxs) {
2169  boxGetGeometry(boxs, &bx, &by, &bw, &bh);
2170  cbw = L_MIN(bw, w - bx);
2171  cbh = L_MIN(bh, h - by);
2172  if (cbw < 0 || cbh < 0)
2173  return ERROR_INT("box not within image", procName, 1);
2174  boxt = boxCreate(bx, by, cbw, cbh);
2175  } else {
2176  boxt = boxCreate(0, 0, w, h);
2177  }
2178 
2179  lfound = rfound = tfound = bfound = 0;
2180  while (!lfound || !rfound || !tfound || !bfound) {
2181  change = 0;
2182  if (!lfound) {
2183  if (!pixScanForEdge(pixs, boxt, lowthresh, highthresh, maxwidth,
2184  factor, L_FROM_LEFT, &left)) {
2185  lfound = 1;
2186  change = 1;
2187  boxRelocateOneSide(boxt, boxt, left, L_FROM_LEFT);
2188  }
2189  }
2190  if (!rfound) {
2191  if (!pixScanForEdge(pixs, boxt, lowthresh, highthresh, maxwidth,
2192  factor, L_FROM_RIGHT, &right)) {
2193  rfound = 1;
2194  change = 1;
2195  boxRelocateOneSide(boxt, boxt, right, L_FROM_RIGHT);
2196  }
2197  }
2198  if (!tfound) {
2199  if (!pixScanForEdge(pixs, boxt, lowthresh, highthresh, maxwidth,
2200  factor, L_FROM_TOP, &top)) {
2201  tfound = 1;
2202  change = 1;
2203  boxRelocateOneSide(boxt, boxt, top, L_FROM_TOP);
2204  }
2205  }
2206  if (!bfound) {
2207  if (!pixScanForEdge(pixs, boxt, lowthresh, highthresh, maxwidth,
2208  factor, L_FROM_BOT, &bottom)) {
2209  bfound = 1;
2210  change = 1;
2211  boxRelocateOneSide(boxt, boxt, bottom, L_FROM_BOT);
2212  }
2213  }
2214 
2215 #if DEBUG_EDGES
2216  lept_stderr("iter: %d %d %d %d\n", lfound, rfound, tfound, bfound);
2217 #endif /* DEBUG_EDGES */
2218 
2219  if (change == 0) break;
2220  }
2221  boxDestroy(&boxt);
2222 
2223  if (change == 0)
2224  return ERROR_INT("not all edges found", procName, 1);
2225 
2226  boxd = boxCreate(left, top, right - left + 1, bottom - top + 1);
2227  if (ppixd)
2228  *ppixd = pixClipRectangle(pixs, boxd, NULL);
2229  if (pboxd)
2230  *pboxd = boxd;
2231  else
2232  boxDestroy(&boxd);
2233 
2234  return 0;
2235 }
2236 
2237 
2267 l_ok
2269  BOX *box,
2270  l_int32 lowthresh,
2271  l_int32 highthresh,
2272  l_int32 maxwidth,
2273  l_int32 factor,
2274  l_int32 scanflag,
2275  l_int32 *ploc)
2276 {
2277 l_int32 bx, by, bw, bh, foundmin, loc, sum, wpl;
2278 l_int32 x, xstart, xend, y, ystart, yend;
2279 l_uint32 *data, *line;
2280 BOX *boxt;
2281 
2282  PROCNAME("pixScanForEdge");
2283 
2284  if (!ploc)
2285  return ERROR_INT("&ploc not defined", procName, 1);
2286  *ploc = 0;
2287  if (!pixs || (pixGetDepth(pixs) != 1))
2288  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
2289  if (lowthresh < 1 || highthresh < 1 ||
2290  lowthresh > highthresh || maxwidth < 1)
2291  return ERROR_INT("invalid thresholds", procName, 1);
2292  factor = L_MIN(1, factor);
2293 
2294  /* Clip box to pixs if it exists */
2295  pixGetDimensions(pixs, &bw, &bh, NULL);
2296  if (box) {
2297  if ((boxt = boxClipToRectangle(box, bw, bh)) == NULL)
2298  return ERROR_INT("invalid box", procName, 1);
2299  boxGetGeometry(boxt, &bx, &by, &bw, &bh);
2300  boxDestroy(&boxt);
2301  } else {
2302  bx = by = 0;
2303  }
2304  xstart = bx;
2305  ystart = by;
2306  xend = bx + bw - 1;
2307  yend = by + bh - 1;
2308 
2309  data = pixGetData(pixs);
2310  wpl = pixGetWpl(pixs);
2311  foundmin = 0;
2312  if (scanflag == L_FROM_LEFT) {
2313  for (x = xstart; x <= xend; x++) {
2314  sum = 0;
2315  for (y = ystart; y <= yend; y += factor) {
2316  line = data + y * wpl;
2317  if (GET_DATA_BIT(line, x))
2318  sum++;
2319  }
2320  if (!foundmin && sum < lowthresh)
2321  continue;
2322  if (!foundmin) { /* save the loc of the beginning of the edge */
2323  foundmin = 1;
2324  loc = x;
2325  }
2326  if (sum >= highthresh) {
2327 #if DEBUG_EDGES
2328  lept_stderr("Left: x = %d, loc = %d\n", x, loc);
2329 #endif /* DEBUG_EDGES */
2330  if (x - loc < maxwidth) {
2331  *ploc = loc;
2332  return 0;
2333  } else {
2334  return 1;
2335  }
2336  }
2337  }
2338  } else if (scanflag == L_FROM_RIGHT) {
2339  for (x = xend; x >= xstart; x--) {
2340  sum = 0;
2341  for (y = ystart; y <= yend; y += factor) {
2342  line = data + y * wpl;
2343  if (GET_DATA_BIT(line, x))
2344  sum++;
2345  }
2346  if (!foundmin && sum < lowthresh)
2347  continue;
2348  if (!foundmin) {
2349  foundmin = 1;
2350  loc = x;
2351  }
2352  if (sum >= highthresh) {
2353 #if DEBUG_EDGES
2354  lept_stderr("Right: x = %d, loc = %d\n", x, loc);
2355 #endif /* DEBUG_EDGES */
2356  if (loc - x < maxwidth) {
2357  *ploc = loc;
2358  return 0;
2359  } else {
2360  return 1;
2361  }
2362  }
2363  }
2364  } else if (scanflag == L_FROM_TOP) {
2365  for (y = ystart; y <= yend; y++) {
2366  sum = 0;
2367  line = data + y * wpl;
2368  for (x = xstart; x <= xend; x += factor) {
2369  if (GET_DATA_BIT(line, x))
2370  sum++;
2371  }
2372  if (!foundmin && sum < lowthresh)
2373  continue;
2374  if (!foundmin) {
2375  foundmin = 1;
2376  loc = y;
2377  }
2378  if (sum >= highthresh) {
2379 #if DEBUG_EDGES
2380  lept_stderr("Top: y = %d, loc = %d\n", y, loc);
2381 #endif /* DEBUG_EDGES */
2382  if (y - loc < maxwidth) {
2383  *ploc = loc;
2384  return 0;
2385  } else {
2386  return 1;
2387  }
2388  }
2389  }
2390  } else if (scanflag == L_FROM_BOT) {
2391  for (y = yend; y >= ystart; y--) {
2392  sum = 0;
2393  line = data + y * wpl;
2394  for (x = xstart; x <= xend; x += factor) {
2395  if (GET_DATA_BIT(line, x))
2396  sum++;
2397  }
2398  if (!foundmin && sum < lowthresh)
2399  continue;
2400  if (!foundmin) {
2401  foundmin = 1;
2402  loc = y;
2403  }
2404  if (sum >= highthresh) {
2405 #if DEBUG_EDGES
2406  lept_stderr("Bottom: y = %d, loc = %d\n", y, loc);
2407 #endif /* DEBUG_EDGES */
2408  if (loc - y < maxwidth) {
2409  *ploc = loc;
2410  return 0;
2411  } else {
2412  return 1;
2413  }
2414  }
2415  }
2416  } else {
2417  return ERROR_INT("invalid scanflag", procName, 1);
2418  }
2419 
2420  return 1; /* edge not found */
2421 }
2422 
2423 
2424 /*---------------------------------------------------------------------*
2425  * Extract pixel averages and reversals along lines *
2426  *---------------------------------------------------------------------*/
2448 NUMA *
2450  l_int32 x1,
2451  l_int32 y1,
2452  l_int32 x2,
2453  l_int32 y2,
2454  l_int32 factor)
2455 {
2456 l_int32 i, w, h, d, xmin, ymin, xmax, ymax, npts, direction;
2457 l_uint32 val;
2458 l_float32 x, y;
2459 l_float64 slope;
2460 NUMA *na;
2461 PTA *pta;
2462 
2463  PROCNAME("pixExtractOnLine");
2464 
2465  if (!pixs)
2466  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
2467  pixGetDimensions(pixs, &w, &h, &d);
2468  if (d != 1 && d != 8)
2469  return (NUMA *)ERROR_PTR("d not 1 or 8 bpp", procName, NULL);
2470  if (pixGetColormap(pixs))
2471  return (NUMA *)ERROR_PTR("pixs has a colormap", procName, NULL);
2472  if (factor < 1) {
2473  L_WARNING("factor must be >= 1; setting to 1\n", procName);
2474  factor = 1;
2475  }
2476 
2477  /* Clip line to the image */
2478  x1 = L_MAX(0, L_MIN(x1, w - 1));
2479  x2 = L_MAX(0, L_MIN(x2, w - 1));
2480  y1 = L_MAX(0, L_MIN(y1, h - 1));
2481  y2 = L_MAX(0, L_MIN(y2, h - 1));
2482 
2483  if (x1 == x2 && y1 == y2) {
2484  pixGetPixel(pixs, x1, y1, &val);
2485  na = numaCreate(1);
2486  numaAddNumber(na, val);
2487  return na;
2488  }
2489 
2490  if (y1 == y2)
2491  direction = L_HORIZONTAL_LINE;
2492  else if (x1 == x2)
2493  direction = L_VERTICAL_LINE;
2494  else
2495  direction = L_OBLIQUE_LINE;
2496 
2497  na = numaCreate(0);
2498  if (direction == L_HORIZONTAL_LINE) { /* plot against x */
2499  xmin = L_MIN(x1, x2);
2500  xmax = L_MAX(x1, x2);
2501  numaSetParameters(na, xmin, factor);
2502  for (i = xmin; i <= xmax; i += factor) {
2503  pixGetPixel(pixs, i, y1, &val);
2504  numaAddNumber(na, val);
2505  }
2506  } else if (direction == L_VERTICAL_LINE) { /* plot against y */
2507  ymin = L_MIN(y1, y2);
2508  ymax = L_MAX(y1, y2);
2509  numaSetParameters(na, ymin, factor);
2510  for (i = ymin; i <= ymax; i += factor) {
2511  pixGetPixel(pixs, x1, i, &val);
2512  numaAddNumber(na, val);
2513  }
2514  } else { /* direction == L_OBLIQUE_LINE */
2515  slope = (l_float64)((y2 - y1) / (x2 - x1));
2516  if (L_ABS(slope) < 1.0) { /* quasi-horizontal */
2517  xmin = L_MIN(x1, x2);
2518  xmax = L_MAX(x1, x2);
2519  ymin = (xmin == x1) ? y1 : y2; /* pt that goes with xmin */
2520  ymax = (ymin == y1) ? y2 : y1; /* pt that goes with xmax */
2521  pta = generatePtaLine(xmin, ymin, xmax, ymax);
2522  numaSetParameters(na, xmin, (l_float32)factor);
2523  } else { /* quasi-vertical */
2524  ymin = L_MIN(y1, y2);
2525  ymax = L_MAX(y1, y2);
2526  xmin = (ymin == y1) ? x1 : x2; /* pt that goes with ymin */
2527  xmax = (xmin == x1) ? x2 : x1; /* pt that goes with ymax */
2528  pta = generatePtaLine(xmin, ymin, xmax, ymax);
2529  numaSetParameters(na, ymin, (l_float32)factor);
2530  }
2531  npts = ptaGetCount(pta);
2532  for (i = 0; i < npts; i += factor) {
2533  ptaGetPt(pta, i, &x, &y);
2534  pixGetPixel(pixs, (l_int32)x, (l_int32)y, &val);
2535  numaAddNumber(na, val);
2536  }
2537 
2538 #if 0 /* debugging */
2539  pixPlotAlongPta(pixs, pta, GPLOT_PNG, NULL);
2540 #endif
2541 
2542  ptaDestroy(&pta);
2543  }
2544 
2545  return na;
2546 }
2547 
2548 
2568 l_float32
2570  l_int32 x1,
2571  l_int32 y1,
2572  l_int32 x2,
2573  l_int32 y2,
2574  l_int32 factor)
2575 {
2576 l_int32 i, j, w, h, d, direction, count, wpl;
2577 l_uint32 *data, *line;
2578 l_float32 sum;
2579 
2580  PROCNAME("pixAverageOnLine");
2581 
2582  if (!pixs)
2583  return ERROR_INT("pixs not defined", procName, 1);
2584  pixGetDimensions(pixs, &w, &h, &d);
2585  if (d != 1 && d != 8)
2586  return ERROR_INT("d not 1 or 8 bpp", procName, 1);
2587  if (pixGetColormap(pixs))
2588  return ERROR_INT("pixs has a colormap", procName, 1);
2589  if (x1 > x2 || y1 > y2)
2590  return ERROR_INT("x1 > x2 or y1 > y2", procName, 1);
2591 
2592  if (y1 == y2) {
2593  x1 = L_MAX(0, x1);
2594  x2 = L_MIN(w - 1, x2);
2595  y1 = L_MAX(0, L_MIN(y1, h - 1));
2596  direction = L_HORIZONTAL_LINE;
2597  } else if (x1 == x2) {
2598  y1 = L_MAX(0, y1);
2599  y2 = L_MIN(h - 1, y2);
2600  x1 = L_MAX(0, L_MIN(x1, w - 1));
2601  direction = L_VERTICAL_LINE;
2602  } else {
2603  return ERROR_INT("line neither horiz nor vert", procName, 1);
2604  }
2605 
2606  if (factor < 1) {
2607  L_WARNING("factor must be >= 1; setting to 1\n", procName);
2608  factor = 1;
2609  }
2610 
2611  data = pixGetData(pixs);
2612  wpl = pixGetWpl(pixs);
2613  sum = 0;
2614  count = 0;
2615  if (direction == L_HORIZONTAL_LINE) {
2616  line = data + y1 * wpl;
2617  for (j = x1, count = 0; j <= x2; count++, j += factor) {
2618  if (d == 1)
2619  sum += GET_DATA_BIT(line, j);
2620  else /* d == 8 */
2621  sum += GET_DATA_BYTE(line, j);
2622  }
2623  } else if (direction == L_VERTICAL_LINE) {
2624  for (i = y1, count = 0; i <= y2; count++, i += factor) {
2625  line = data + i * wpl;
2626  if (d == 1)
2627  sum += GET_DATA_BIT(line, x1);
2628  else /* d == 8 */
2629  sum += GET_DATA_BYTE(line, x1);
2630  }
2631  }
2632 
2633  return sum / (l_float32)count;
2634 }
2635 
2636 
2667 NUMA *
2669  l_float32 fract,
2670  l_int32 dir,
2671  l_int32 first,
2672  l_int32 last,
2673  l_int32 factor1,
2674  l_int32 factor2)
2675 {
2676 l_int32 i, j, w, h, d, start, end;
2677 l_float32 ave;
2678 NUMA *nad;
2679 PIX *pixr, *pixg;
2680 
2681  PROCNAME("pixAverageIntensityProfile");
2682 
2683  if (!pixs)
2684  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
2685  if (fract < 0.0 || fract > 1.0)
2686  return (NUMA *)ERROR_PTR("fract < 0.0 or > 1.0", procName, NULL);
2687  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
2688  return (NUMA *)ERROR_PTR("invalid direction", procName, NULL);
2689  if (first < 0) first = 0;
2690  if (last < first)
2691  return (NUMA *)ERROR_PTR("last must be >= first", procName, NULL);
2692  if (factor1 < 1) {
2693  L_WARNING("factor1 must be >= 1; setting to 1\n", procName);
2694  factor1 = 1;
2695  }
2696  if (factor2 < 1) {
2697  L_WARNING("factor2 must be >= 1; setting to 1\n", procName);
2698  factor2 = 1;
2699  }
2700 
2701  /* Use 1 or 8 bpp, without colormap */
2702  if (pixGetColormap(pixs))
2704  else
2705  pixr = pixClone(pixs);
2706  pixGetDimensions(pixr, &w, &h, &d);
2707  if (d == 1)
2708  pixg = pixClone(pixr);
2709  else
2710  pixg = pixConvertTo8(pixr, 0);
2711 
2712  nad = numaCreate(0); /* output: samples in slow scan direction */
2713  numaSetParameters(nad, 0, factor2);
2714  if (dir == L_HORIZONTAL_LINE) {
2715  start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)w);
2716  end = w - start;
2717  if (last > h - 1) {
2718  L_WARNING("last > h - 1; clipping\n", procName);
2719  last = h - 1;
2720  }
2721  for (i = first; i <= last; i += factor2) {
2722  ave = pixAverageOnLine(pixg, start, i, end, i, factor1);
2723  numaAddNumber(nad, ave);
2724  }
2725  } else if (dir == L_VERTICAL_LINE) {
2726  start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)h);
2727  end = h - start;
2728  if (last > w - 1) {
2729  L_WARNING("last > w - 1; clipping\n", procName);
2730  last = w - 1;
2731  }
2732  for (j = first; j <= last; j += factor2) {
2733  ave = pixAverageOnLine(pixg, j, start, j, end, factor1);
2734  numaAddNumber(nad, ave);
2735  }
2736  }
2737 
2738  pixDestroy(&pixr);
2739  pixDestroy(&pixg);
2740  return nad;
2741 }
2742 
2743 
2782 NUMA *
2784  l_float32 fract,
2785  l_int32 dir,
2786  l_int32 first,
2787  l_int32 last,
2788  l_int32 minreversal,
2789  l_int32 factor1,
2790  l_int32 factor2)
2791 {
2792 l_int32 i, j, w, h, d, start, end, nr;
2793 NUMA *naline, *nad;
2794 PIX *pixr, *pixg;
2795 
2796  PROCNAME("pixReversalProfile");
2797 
2798  if (!pixs)
2799  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
2800  if (fract < 0.0 || fract > 1.0)
2801  return (NUMA *)ERROR_PTR("fract < 0.0 or > 1.0", procName, NULL);
2802  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
2803  return (NUMA *)ERROR_PTR("invalid direction", procName, NULL);
2804  if (first < 0) first = 0;
2805  if (last < first)
2806  return (NUMA *)ERROR_PTR("last must be >= first", procName, NULL);
2807  if (factor1 < 1) {
2808  L_WARNING("factor1 must be >= 1; setting to 1\n", procName);
2809  factor1 = 1;
2810  }
2811  if (factor2 < 1) {
2812  L_WARNING("factor2 must be >= 1; setting to 1\n", procName);
2813  factor2 = 1;
2814  }
2815 
2816  /* Use 1 or 8 bpp, without colormap */
2817  if (pixGetColormap(pixs))
2819  else
2820  pixr = pixClone(pixs);
2821  pixGetDimensions(pixr, &w, &h, &d);
2822  if (d == 1) {
2823  pixg = pixClone(pixr);
2824  minreversal = 1; /* enforce this */
2825  } else {
2826  pixg = pixConvertTo8(pixr, 0);
2827  }
2828 
2829  nad = numaCreate(0); /* output: samples in slow scan direction */
2830  numaSetParameters(nad, 0, factor2);
2831  if (dir == L_HORIZONTAL_LINE) {
2832  start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)w);
2833  end = w - start;
2834  if (last > h - 1) {
2835  L_WARNING("last > h - 1; clipping\n", procName);
2836  last = h - 1;
2837  }
2838  for (i = first; i <= last; i += factor2) {
2839  naline = pixExtractOnLine(pixg, start, i, end, i, factor1);
2840  numaCountReversals(naline, minreversal, &nr, NULL);
2841  numaAddNumber(nad, nr);
2842  numaDestroy(&naline);
2843  }
2844  } else if (dir == L_VERTICAL_LINE) {
2845  start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)h);
2846  end = h - start;
2847  if (last > w - 1) {
2848  L_WARNING("last > w - 1; clipping\n", procName);
2849  last = w - 1;
2850  }
2851  for (j = first; j <= last; j += factor2) {
2852  naline = pixExtractOnLine(pixg, j, start, j, end, factor1);
2853  numaCountReversals(naline, minreversal, &nr, NULL);
2854  numaAddNumber(nad, nr);
2855  numaDestroy(&naline);
2856  }
2857  }
2858 
2859  pixDestroy(&pixr);
2860  pixDestroy(&pixg);
2861  return nad;
2862 }
2863 
2864 
2865 /*---------------------------------------------------------------------*
2866  * Extract windowed variance along a line *
2867  *---------------------------------------------------------------------*/
2891 l_ok
2893  l_int32 dir,
2894  l_int32 loc,
2895  l_int32 c1,
2896  l_int32 c2,
2897  l_int32 size,
2898  NUMA **pnad)
2899 {
2900 l_int32 i, j, w, h, cmin, cmax, maxloc, n, x, y;
2901 l_uint32 val;
2902 l_float32 norm, rootvar;
2903 l_float32 *array;
2904 l_float64 sum1, sum2, ave, var;
2905 NUMA *na1, *nad;
2906 PTA *pta;
2907 
2908  PROCNAME("pixWindowedVarianceOnLine");
2909 
2910  if (!pnad)
2911  return ERROR_INT("&nad not defined", procName, 1);
2912  *pnad = NULL;
2913  if (!pixs || pixGetDepth(pixs) != 8)
2914  return ERROR_INT("pixs not defined or not 8bpp", procName, 1);
2915  if (size < 2)
2916  return ERROR_INT("window size must be > 1", procName, 1);
2917  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
2918  return ERROR_INT("invalid direction", procName, 1);
2919  pixGetDimensions(pixs, &w, &h, NULL);
2920  maxloc = (dir == L_HORIZONTAL_LINE) ? h - 1 : w - 1;
2921  if (loc < 0 || loc > maxloc)
2922  return ERROR_INT("invalid line position", procName, 1);
2923 
2924  /* Clip line to the image */
2925  cmin = L_MIN(c1, c2);
2926  cmax = L_MAX(c1, c2);
2927  maxloc = (dir == L_HORIZONTAL_LINE) ? w - 1 : h - 1;
2928  cmin = L_MAX(0, L_MIN(cmin, maxloc));
2929  cmax = L_MAX(0, L_MIN(cmax, maxloc));
2930  n = cmax - cmin + 1;
2931 
2932  /* Generate pta along the line */
2933  pta = ptaCreate(n);
2934  if (dir == L_HORIZONTAL_LINE) {
2935  for (i = cmin; i <= cmax; i++)
2936  ptaAddPt(pta, i, loc);
2937  } else { /* vertical line */
2938  for (i = cmin; i <= cmax; i++)
2939  ptaAddPt(pta, loc, i);
2940  }
2941 
2942  /* Get numa of pixel values on the line */
2943  na1 = numaCreate(n);
2944  numaSetParameters(na1, cmin, 1);
2945  for (i = 0; i < n; i++) {
2946  ptaGetIPt(pta, i, &x, &y);
2947  pixGetPixel(pixs, x, y, &val);
2948  numaAddNumber(na1, val);
2949  }
2950  array = numaGetFArray(na1, L_NOCOPY);
2951  ptaDestroy(&pta);
2952 
2953  /* Compute root variance on overlapping windows */
2954  nad = numaCreate(n);
2955  *pnad = nad;
2956  numaSetParameters(nad, cmin + size / 2, 1);
2957  norm = 1.0 / (l_float32)size;
2958  for (i = 0; i < n - size; i++) { /* along the line */
2959  sum1 = sum2 = 0;
2960  for (j = 0; j < size; j++) { /* over the window */
2961  val = array[i + j];
2962  sum1 += val;
2963  sum2 += (l_float64)(val) * val;
2964  }
2965  ave = norm * sum1;
2966  var = norm * sum2 - ave * ave;
2967  rootvar = (l_float32)sqrt(var);
2968  numaAddNumber(nad, rootvar);
2969  }
2970 
2971  numaDestroy(&na1);
2972  return 0;
2973 }
2974 
2975 
2976 /*---------------------------------------------------------------------*
2977  * Extract min/max of pixel values near lines *
2978  *---------------------------------------------------------------------*/
3009 l_ok
3011  l_int32 x1,
3012  l_int32 y1,
3013  l_int32 x2,
3014  l_int32 y2,
3015  l_int32 dist,
3016  l_int32 direction,
3017  NUMA **pnamin,
3018  NUMA **pnamax,
3019  l_float32 *pminave,
3020  l_float32 *pmaxave)
3021 {
3022 l_int32 i, j, w, h, d, x, y, n, dir, found, minval, maxval, negloc, posloc;
3023 l_uint32 val;
3024 l_float32 sum;
3025 NUMA *namin, *namax;
3026 PTA *pta;
3027 
3028  PROCNAME("pixMinMaxNearLine");
3029 
3030  if (pnamin) *pnamin = NULL;
3031  if (pnamax) *pnamax = NULL;
3032  if (pminave) *pminave = UNDEF;
3033  if (pmaxave) *pmaxave = UNDEF;
3034  if (!pnamin && !pnamax && !pminave && !pmaxave)
3035  return ERROR_INT("no output requested", procName, 1);
3036  if (!pixs)
3037  return ERROR_INT("pixs not defined", procName, 1);
3038  pixGetDimensions(pixs, &w, &h, &d);
3039  if (d != 8 || pixGetColormap(pixs))
3040  return ERROR_INT("pixs not 8 bpp or has colormap", procName, 1);
3041  dist = L_ABS(dist);
3042  if (direction != L_SCAN_NEGATIVE && direction != L_SCAN_POSITIVE &&
3043  direction != L_SCAN_BOTH)
3044  return ERROR_INT("invalid direction", procName, 1);
3045 
3046  pta = generatePtaLine(x1, y1, x2, y2);
3047  n = ptaGetCount(pta);
3048  dir = (L_ABS(x1 - x2) == n - 1) ? L_HORIZ : L_VERT;
3049  namin = numaCreate(n);
3050  namax = numaCreate(n);
3051  negloc = -dist;
3052  posloc = dist;
3053  if (direction == L_SCAN_NEGATIVE)
3054  posloc = 0;
3055  else if (direction == L_SCAN_POSITIVE)
3056  negloc = 0;
3057  for (i = 0; i < n; i++) {
3058  ptaGetIPt(pta, i, &x, &y);
3059  minval = 255;
3060  maxval = 0;
3061  found = FALSE;
3062  if (dir == L_HORIZ) {
3063  if (x < 0 || x >= w) continue;
3064  for (j = negloc; j <= posloc; j++) {
3065  if (y + j < 0 || y + j >= h) continue;
3066  pixGetPixel(pixs, x, y + j, &val);
3067  found = TRUE;
3068  if (val < minval) minval = val;
3069  if (val > maxval) maxval = val;
3070  }
3071  } else { /* dir == L_VERT */
3072  if (y < 0 || y >= h) continue;
3073  for (j = negloc; j <= posloc; j++) {
3074  if (x + j < 0 || x + j >= w) continue;
3075  pixGetPixel(pixs, x + j, y, &val);
3076  found = TRUE;
3077  if (val < minval) minval = val;
3078  if (val > maxval) maxval = val;
3079  }
3080  }
3081  if (found) {
3082  numaAddNumber(namin, minval);
3083  numaAddNumber(namax, maxval);
3084  }
3085  }
3086 
3087  n = numaGetCount(namin);
3088  if (n == 0) {
3089  numaDestroy(&namin);
3090  numaDestroy(&namax);
3091  ptaDestroy(&pta);
3092  return ERROR_INT("no output from this line", procName, 1);
3093  }
3094 
3095  if (pminave) {
3096  numaGetSum(namin, &sum);
3097  *pminave = sum / n;
3098  }
3099  if (pmaxave) {
3100  numaGetSum(namax, &sum);
3101  *pmaxave = sum / n;
3102  }
3103  if (pnamin)
3104  *pnamin = namin;
3105  else
3106  numaDestroy(&namin);
3107  if (pnamax)
3108  *pnamax = namax;
3109  else
3110  numaDestroy(&namax);
3111  ptaDestroy(&pta);
3112  return 0;
3113 }
3114 
3115 
3116 /*---------------------------------------------------------------------*
3117  * Rank row and column transforms *
3118  *---------------------------------------------------------------------*/
3132 PIX *
3134 {
3135 l_int32 i, j, k, m, w, h, wpl, val;
3136 l_int32 histo[256];
3137 l_uint32 *datas, *datad, *lines, *lined;
3138 PIX *pixd;
3139 
3140  PROCNAME("pixRankRowTransform");
3141 
3142  if (!pixs)
3143  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3144  if (pixGetDepth(pixs) != 8)
3145  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
3146  if (pixGetColormap(pixs))
3147  return (PIX *)ERROR_PTR("pixs has a colormap", procName, NULL);
3148 
3149  pixGetDimensions(pixs, &w, &h, NULL);
3150  pixd = pixCreateTemplate(pixs);
3151  datas = pixGetData(pixs);
3152  datad = pixGetData(pixd);
3153  wpl = pixGetWpl(pixs);
3154  for (i = 0; i < h; i++) {
3155  memset(histo, 0, 1024);
3156  lines = datas + i * wpl;
3157  lined = datad + i * wpl;
3158  for (j = 0; j < w; j++) {
3159  val = GET_DATA_BYTE(lines, j);
3160  histo[val]++;
3161  }
3162  for (m = 0, j = 0; m < 256; m++) {
3163  for (k = 0; k < histo[m]; k++, j++)
3164  SET_DATA_BYTE(lined, j, m);
3165  }
3166  }
3167 
3168  return pixd;
3169 }
3170 
3171 
3185 PIX *
3187 {
3188 l_int32 i, j, k, m, w, h, val;
3189 l_int32 histo[256];
3190 void **lines8, **lined8;
3191 PIX *pixd;
3192 
3193  PROCNAME("pixRankColumnTransform");
3194 
3195  if (!pixs)
3196  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3197  if (pixGetDepth(pixs) != 8)
3198  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
3199  if (pixGetColormap(pixs))
3200  return (PIX *)ERROR_PTR("pixs has a colormap", procName, NULL);
3201 
3202  pixGetDimensions(pixs, &w, &h, NULL);
3203  pixd = pixCreateTemplate(pixs);
3204  lines8 = pixGetLinePtrs(pixs, NULL);
3205  lined8 = pixGetLinePtrs(pixd, NULL);
3206  for (j = 0; j < w; j++) {
3207  memset(histo, 0, 1024);
3208  for (i = 0; i < h; i++) {
3209  val = GET_DATA_BYTE(lines8[i], j);
3210  histo[val]++;
3211  }
3212  for (m = 0, i = 0; m < 256; m++) {
3213  for (k = 0; k < histo[m]; k++, i++)
3214  SET_DATA_BYTE(lined8[i], j, m);
3215  }
3216  }
3217 
3218  LEPT_FREE(lines8);
3219  LEPT_FREE(lined8);
3220  return pixd;
3221 }
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:620
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
BOX * boxRelocateOneSide(BOX *boxd, BOX *boxs, l_int32 loc, l_int32 sideflag)
boxRelocateOneSide()
Definition: boxfunc1.c:1847
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1728
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1991
PIX * pixMaskBoxa(PIX *pixd, PIX *pixs, BOXA *boxa, l_int32 op)
pixMaskBoxa()
Definition: boxfunc3.c:151
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
l_ok pixcmapGetNearestIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetNearestIndex()
Definition: colormap.c:1353
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:824
l_ok pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame)
pixEqual()
Definition: compare.c:156
BOXA * pixConnCompBB(PIX *pixs, l_int32 connectivity)
pixConnCompBB()
Definition: conncomp.c:310
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:151
PTA * generatePtaLine(l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2)
generatePtaLine()
Definition: graphics.c:141
PIX * pixErodeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrick()
Definition: morph.c:758
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:993
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:892
l_ok numaGetSum(NUMA *na, l_float32 *psum)
numaGetSum()
Definition: numafunc1.c:538
l_ok numaCountReversals(NUMA *nas, l_float32 minreversal, l_int32 *pnr, l_float32 *prd)
numaCountReversals()
Definition: numafunc2.c:2752
l_ok pixSetMaskedCmap(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 rval, l_int32 gval, l_int32 bval)
pixSetMaskedCmap()
Definition: paintcmap.c:698
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition: pix1.c:816
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1949
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:190
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
l_ok pixSetOrClearBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_int32 op)
pixSetOrClearBorder()
Definition: pix2.c:1514
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:1021
l_ok pixZero(PIX *pix, l_int32 *pempty)
pixZero()
Definition: pix3.c:1815
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:626
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1937
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1624
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2411
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1688
PIX * pixResizeToMatch(PIX *pixs, PIX *pixt, l_int32 w, l_int32 h)
pixResizeToMatch()
Definition: pix5.c:1321
l_ok pixWindowedVarianceOnLine(PIX *pixs, l_int32 dir, l_int32 loc, l_int32 c1, l_int32 c2, l_int32 size, NUMA **pnad)
pixWindowedVarianceOnLine()
Definition: pix5.c:2892
l_ok pixFractionFgInMask(PIX *pix1, PIX *pix2, l_float32 *pfract)
pixFractionFgInMask()
Definition: pix5.c:1728
l_ok pixFindAreaPerimRatio(PIX *pixs, l_int32 *tab, l_float32 *pfract)
pixFindAreaPerimRatio()
Definition: pix5.c:190
NUMA * pixAverageIntensityProfile(PIX *pixs, l_float32 fract, l_int32 dir, l_int32 first, l_int32 last, l_int32 factor1, l_int32 factor2)
pixAverageIntensityProfile()
Definition: pix5.c:2668
l_ok pixFindPerimToAreaRatio(PIX *pixs, l_int32 *tab, l_float32 *pfract)
pixFindPerimToAreaRatio()
Definition: pix5.c:291
NUMA * pixaFindAreaFraction(PIXA *pixa)
pixaFindAreaFraction()
Definition: pix5.c:441
PIX * pixCropToSize(PIX *pixs, l_int32 w, l_int32 h)
pixCropToSize()
Definition: pix5.c:1267
NUMA * pixaFindPerimSizeRatio(PIXA *pixa)
pixaFindPerimSizeRatio()
Definition: pix5.c:345
PIX * pixMakeSymmetricMask(l_int32 w, l_int32 h, l_float32 hf, l_float32 vf, l_int32 type)
pixSelectComponentBySize()
Definition: pix5.c:1532
NUMA * pixaFindPerimToAreaRatio(PIXA *pixa)
pixaFindPerimToAreaRatio()
Definition: pix5.c:241
PIX * pixRankRowTransform(PIX *pixs)
pixRankRowTransform()
Definition: pix5.c:3133
l_ok pixFindPerimSizeRatio(PIX *pixs, l_int32 *tab, l_float32 *pratio)
pixFindPerimSizeRatio()
Definition: pix5.c:395
NUMA * pixaFindWidthHeightProduct(PIXA *pixa)
pixaFindWidthHeightProduct()
Definition: pix5.c:706
l_ok pixFindAreaFraction(PIX *pixs, l_int32 *tab, l_float32 *pfract)
pixFindAreaFraction()
Definition: pix5.c:484
l_ok pixScanForForeground(PIX *pixs, BOX *box, l_int32 scanflag, l_int32 *ploc)
pixScanForForeground()
Definition: pix5.c:2022
BOXA * pixFindRectangleComps(PIX *pixs, l_int32 dist, l_int32 minw, l_int32 minh)
pixFindRectangleComps()
Definition: pix5.c:813
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
l_ok pixClipBoxToEdges(PIX *pixs, BOX *boxs, l_int32 lowthresh, l_int32 highthresh, l_int32 maxwidth, l_int32 factor, PIX **ppixd, BOX **pboxd)
pixClipBoxToEdges()
Definition: pix5.c:2138
l_float32 pixAverageOnLine(PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor)
pixAverageOnLine()
Definition: pix5.c:2569
PIX * pixClipRectangleWithBorder(PIX *pixs, BOX *box, l_int32 maxbord, BOX **pboxn)
pixClipRectangleWithBorder()
Definition: pix5.c:1089
l_ok pixTestClipToForeground(PIX *pixs, l_int32 *pcanclip)
pixTestClipToForeground()
Definition: pix5.c:1884
PIX * pixRankColumnTransform(PIX *pixs)
pixRankColumnTransform()
Definition: pix5.c:3186
l_ok pixClipBoxToForeground(PIX *pixs, BOX *boxs, PIX **ppixd, BOX **pboxd)
pixClipBoxToForeground()
Definition: pix5.c:1956
l_ok pixFindAreaFractionMasked(PIX *pixs, BOX *box, PIX *pixm, l_int32 *tab, l_float32 *pfract)
pixFindAreaFractionMasked()
Definition: pix5.c:611
NUMA * pixExtractOnLine(PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor)
pixExtractOnLine()
Definition: pix5.c:2449
l_ok pixScanForEdge(PIX *pixs, BOX *box, l_int32 lowthresh, l_int32 highthresh, l_int32 maxwidth, l_int32 factor, l_int32 scanflag, l_int32 *ploc)
pixScanForEdge()
Definition: pix5.c:2268
l_ok pixMinMaxNearLine(PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 dist, l_int32 direction, NUMA **pnamin, NUMA **pnamax, l_float32 *pminave, l_float32 *pmaxave)
pixMinMaxNearLine()
Definition: pix5.c:3010
PIX * pixMakeCoveringOfRectangles(PIX *pixs, l_int32 maxiters)
pixMakeCoveringOfRectangles()
Definition: pix5.c:1655
NUMA * pixaFindWidthHeightRatio(PIXA *pixa)
pixaFindWidthHeightRatio()
Definition: pix5.c:670
l_ok pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
pixClipToForeground()
Definition: pix5.c:1784
l_ok pixaFindDimensions(PIXA *pixa, NUMA **pnaw, NUMA **pnah)
pixaFindDimensions()
Definition: pix5.c:140
l_ok pixConformsToRectangle(PIX *pixs, BOX *box, l_int32 dist, l_int32 *pconforms)
pixConformsToRectangle()
Definition: pix5.c:893
NUMA * pixaFindAreaFractionMasked(PIXA *pixa, PIX *pixm, l_int32 debug)
pixaFindAreaFractionMasked()
Definition: pix5.c:532
PIX * pixClipMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_uint32 outval)
pixClipMasked()
Definition: pix5.c:1162
l_ok pixFindOverlapFraction(PIX *pixs1, PIX *pixs2, l_int32 x2, l_int32 y2, l_int32 *tab, l_float32 *pratio, l_int32 *pnoverlap)
pixFindOverlapFraction()
Definition: pix5.c:746
l_ok pixCropToMatch(PIX *pixs1, PIX *pixs2, PIX **ppixd1, PIX **ppixd2)
pixCropToMatch()
Definition: pix5.c:1224
NUMA * pixReversalProfile(PIX *pixs, l_float32 fract, l_int32 dir, l_int32 first, l_int32 last, l_int32 minreversal, l_int32 factor1, l_int32 factor2)
pixReversalProfile()
Definition: pix5.c:2783
PIXA * pixClipRectangles(PIX *pixs, BOXA *boxa)
pixClipRectangles()
Definition: pix5.c:960
PIX * pixMakeFrameMask(l_int32 w, l_int32 h, l_float32 hf1, l_float32 hf2, l_float32 vf1, l_float32 vf2)
pixMakeFrameMask()
Definition: pix5.c:1589
#define PIX_MASK
Definition: pix.h:337
@ L_SET_PIXELS
Definition: pix.h:772
@ L_HORIZONTAL_LINE
Definition: pix.h:1013
@ L_OBLIQUE_LINE
Definition: pix.h:1017
@ L_VERTICAL_LINE
Definition: pix.h:1015
@ L_USE_INNER
Definition: pix.h:1237
@ L_USE_OUTER
Definition: pix.h:1238
@ L_SORT_BY_AREA
Definition: pix.h:744
@ L_SORT_BY_PERIMETER
Definition: pix.h:743
@ L_SORT_BY_WIDTH
Definition: pix.h:739
@ L_SORT_BY_HEIGHT
Definition: pix.h:740
@ L_SORT_BY_MAX_DIMENSION
Definition: pix.h:742
@ REMOVE_CMAP_TO_GRAYSCALE
Definition: pix.h:257
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_NOCOPY
Definition: pix.h:710
@ L_INSERT
Definition: pix.h:711
#define PIX_PAINT
Definition: pix.h:336
@ L_SET_WHITE
Definition: pix.h:906
@ L_FROM_BOT
Definition: pix.h:1037
@ L_FROM_LEFT
Definition: pix.h:1034
@ L_SCAN_NEGATIVE
Definition: pix.h:1038
@ L_SCAN_BOTH
Definition: pix.h:1040
@ L_FROM_RIGHT
Definition: pix.h:1035
@ L_SCAN_POSITIVE
Definition: pix.h:1039
@ L_FROM_TOP
Definition: pix.h:1036
#define PIX_SRC
Definition: pix.h:330
#define PIX_CLR
Definition: pix.h:333
@ L_SORT_DECREASING
Definition: pix.h:730
#define PIX_SET
Definition: pix.h:334
@ L_SELECT_BY_HEIGHT
Definition: pix.h:791
@ L_SELECT_BY_AREA
Definition: pix.h:794
@ L_SELECT_BY_PERIMETER
Definition: pix.h:795
@ L_SELECT_BY_WIDTH
Definition: pix.h:790
@ L_SELECT_BY_MAX_DIMENSION
Definition: pix.h:792
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:816
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
l_ok pixaAddBox(PIXA *pixa, BOX *box, l_int32 copyflag)
pixaAddBox()
Definition: pixabasic.c:555
l_ok pixaIsFull(PIXA *pixa, l_int32 *pfullpa, l_int32 *pfullba)
pixaIsFull()
Definition: pixabasic.c:1057
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
PIXA * pixaSort(PIXA *pixas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex, l_int32 copyflag)
pixaSort()
Definition: pixafunc1.c:1475
PIX * pixaDisplay(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplay()
Definition: pixafunc2.c:191
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:343
l_ok ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:548
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:527
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
l_ok pixPlotAlongPta(PIX *pixs, PTA *pta, l_int32 outformat, const char *title)
pixPlotAlongPta()
Definition: ptafunc1.c:1869
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:204
PIX * pixExtractBorderConnComps(PIX *pixs, l_int32 connectivity)
pixExtractBorderConnComps()
Definition: seedfill.c:698
Definition: pix.h:481
Definition: pix.h:492
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306