Leptonica  1.77.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 
103 #include <string.h>
104 #include <math.h>
105 #include "allheaders.h"
106 
107 static const l_uint32 rmask32[] = {0x0,
108  0x00000001, 0x00000003, 0x00000007, 0x0000000f,
109  0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
110  0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
111  0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
112  0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
113  0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
114  0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
115  0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};
116 
117 #ifndef NO_CONSOLE_IO
118 #define DEBUG_EDGES 0
119 #endif /* ~NO_CONSOLE_IO */
120 
121 
122 /*-------------------------------------------------------------*
123  * Measurement of properties *
124  *-------------------------------------------------------------*/
133 l_ok
135  NUMA **pnaw,
136  NUMA **pnah)
137 {
138 l_int32 i, n, w, h;
139 PIX *pixt;
140 
141  PROCNAME("pixaFindDimensions");
142 
143  if (pnaw) *pnaw = NULL;
144  if (pnah) *pnah = NULL;
145  if (!pnaw && !pnah)
146  return ERROR_INT("no output requested", procName, 1);
147  if (!pixa)
148  return ERROR_INT("pixa not defined", procName, 1);
149 
150  n = pixaGetCount(pixa);
151  if (pnaw) *pnaw = numaCreate(n);
152  if (pnah) *pnah = numaCreate(n);
153  for (i = 0; i < n; i++) {
154  pixt = pixaGetPix(pixa, i, L_CLONE);
155  pixGetDimensions(pixt, &w, &h, NULL);
156  if (pnaw)
157  numaAddNumber(*pnaw, w);
158  if (pnah)
159  numaAddNumber(*pnah, h);
160  pixDestroy(&pixt);
161  }
162  return 0;
163 }
164 
165 
183 l_ok
185  l_int32 *tab,
186  l_float32 *pfract)
187 {
188 l_int32 *tab8;
189 l_int32 nfg, nbound;
190 PIX *pixt;
191 
192  PROCNAME("pixFindAreaPerimRatio");
193 
194  if (!pfract)
195  return ERROR_INT("&fract not defined", procName, 1);
196  *pfract = 0.0;
197  if (!pixs || pixGetDepth(pixs) != 1)
198  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
199 
200  if (!tab)
201  tab8 = makePixelSumTab8();
202  else
203  tab8 = tab;
204 
205  pixt = pixErodeBrick(NULL, pixs, 3, 3);
206  pixCountPixels(pixt, &nfg, tab8);
207  if (nfg == 0) {
208  pixDestroy(&pixt);
209  if (!tab) LEPT_FREE(tab8);
210  return 0;
211  }
212  pixXor(pixt, pixt, pixs);
213  pixCountPixels(pixt, &nbound, tab8);
214  *pfract = (l_float32)nfg / (l_float32)nbound;
215  pixDestroy(&pixt);
216 
217  if (!tab) LEPT_FREE(tab8);
218  return 0;
219 }
220 
221 
234 NUMA *
236 {
237 l_int32 i, n;
238 l_int32 *tab;
239 l_float32 fract;
240 NUMA *na;
241 PIX *pixt;
242 
243  PROCNAME("pixaFindPerimToAreaRatio");
244 
245  if (!pixa)
246  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
247 
248  n = pixaGetCount(pixa);
249  na = numaCreate(n);
250  tab = makePixelSumTab8();
251  for (i = 0; i < n; i++) {
252  pixt = pixaGetPix(pixa, i, L_CLONE);
253  pixFindPerimToAreaRatio(pixt, tab, &fract);
254  numaAddNumber(na, fract);
255  pixDestroy(&pixt);
256  }
257  LEPT_FREE(tab);
258  return na;
259 }
260 
261 
284 l_ok
286  l_int32 *tab,
287  l_float32 *pfract)
288 {
289 l_int32 *tab8;
290 l_int32 nfg, nbound;
291 PIX *pixt;
292 
293  PROCNAME("pixFindPerimToAreaRatio");
294 
295  if (!pfract)
296  return ERROR_INT("&fract not defined", procName, 1);
297  *pfract = 0.0;
298  if (!pixs || pixGetDepth(pixs) != 1)
299  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
300 
301  if (!tab)
302  tab8 = makePixelSumTab8();
303  else
304  tab8 = tab;
305 
306  pixCountPixels(pixs, &nfg, tab8);
307  if (nfg == 0) {
308  if (!tab) LEPT_FREE(tab8);
309  return 0;
310  }
311  pixt = pixErodeBrick(NULL, pixs, 3, 3);
312  pixXor(pixt, pixt, pixs);
313  pixCountPixels(pixt, &nbound, tab8);
314  *pfract = (l_float32)nbound / (l_float32)nfg;
315  pixDestroy(&pixt);
316 
317  if (!tab) LEPT_FREE(tab8);
318  return 0;
319 }
320 
321 
338 NUMA *
340 {
341 l_int32 i, n;
342 l_int32 *tab;
343 l_float32 ratio;
344 NUMA *na;
345 PIX *pixt;
346 
347  PROCNAME("pixaFindPerimSizeRatio");
348 
349  if (!pixa)
350  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
351 
352  n = pixaGetCount(pixa);
353  na = numaCreate(n);
354  tab = makePixelSumTab8();
355  for (i = 0; i < n; i++) {
356  pixt = pixaGetPix(pixa, i, L_CLONE);
357  pixFindPerimSizeRatio(pixt, tab, &ratio);
358  numaAddNumber(na, ratio);
359  pixDestroy(&pixt);
360  }
361  LEPT_FREE(tab);
362  return na;
363 }
364 
365 
388 l_ok
390  l_int32 *tab,
391  l_float32 *pratio)
392 {
393 l_int32 *tab8;
394 l_int32 w, h, nbound;
395 PIX *pixt;
396 
397  PROCNAME("pixFindPerimSizeRatio");
398 
399  if (!pratio)
400  return ERROR_INT("&ratio not defined", procName, 1);
401  *pratio = 0.0;
402  if (!pixs || pixGetDepth(pixs) != 1)
403  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
404 
405  if (!tab)
406  tab8 = makePixelSumTab8();
407  else
408  tab8 = tab;
409 
410  pixt = pixErodeBrick(NULL, pixs, 3, 3);
411  pixXor(pixt, pixt, pixs);
412  pixCountPixels(pixt, &nbound, tab8);
413  pixGetDimensions(pixs, &w, &h, NULL);
414  *pratio = (0.5 * nbound) / (l_float32)(w + h);
415  pixDestroy(&pixt);
416 
417  if (!tab) LEPT_FREE(tab8);
418  return 0;
419 }
420 
421 
434 NUMA *
436 {
437 l_int32 i, n;
438 l_int32 *tab;
439 l_float32 fract;
440 NUMA *na;
441 PIX *pixt;
442 
443  PROCNAME("pixaFindAreaFraction");
444 
445  if (!pixa)
446  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
447 
448  n = pixaGetCount(pixa);
449  na = numaCreate(n);
450  tab = makePixelSumTab8();
451  for (i = 0; i < n; i++) {
452  pixt = pixaGetPix(pixa, i, L_CLONE);
453  pixFindAreaFraction(pixt, tab, &fract);
454  numaAddNumber(na, fract);
455  pixDestroy(&pixt);
456  }
457  LEPT_FREE(tab);
458  return na;
459 }
460 
461 
477 l_ok
479  l_int32 *tab,
480  l_float32 *pfract)
481 {
482 l_int32 w, h, sum;
483 l_int32 *tab8;
484 
485  PROCNAME("pixFindAreaFraction");
486 
487  if (!pfract)
488  return ERROR_INT("&fract not defined", procName, 1);
489  *pfract = 0.0;
490  if (!pixs || pixGetDepth(pixs) != 1)
491  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
492 
493  if (!tab)
494  tab8 = makePixelSumTab8();
495  else
496  tab8 = tab;
497  pixGetDimensions(pixs, &w, &h, NULL);
498  pixCountPixels(pixs, &sum, tab8);
499  *pfract = (l_float32)sum / (l_float32)(w * h);
500 
501  if (!tab) LEPT_FREE(tab8);
502  return 0;
503 }
504 
505 
525 NUMA *
527  PIX *pixm,
528  l_int32 debug)
529 {
530 l_int32 i, n, full;
531 l_int32 *tab;
532 l_float32 fract;
533 BOX *box;
534 NUMA *na;
535 PIX *pix;
536 
537  PROCNAME("pixaFindAreaFractionMasked");
538 
539  if (!pixa)
540  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
541  if (!pixm || pixGetDepth(pixm) != 1)
542  return (NUMA *)ERROR_PTR("pixm undefined or not 1 bpp", procName, NULL);
543 
544  n = pixaGetCount(pixa);
545  na = numaCreate(n);
546  tab = makePixelSumTab8();
547  pixaIsFull(pixa, NULL, &full); /* check boxa */
548  box = NULL;
549  for (i = 0; i < n; i++) {
550  pix = pixaGetPix(pixa, i, L_CLONE);
551  if (full)
552  box = pixaGetBox(pixa, i, L_CLONE);
553  pixFindAreaFractionMasked(pix, box, pixm, tab, &fract);
554  numaAddNumber(na, fract);
555  boxDestroy(&box);
556  pixDestroy(&pix);
557  }
558  LEPT_FREE(tab);
559 
560  if (debug) {
561  l_int32 w, h;
562  PIX *pix1, *pix2;
563  pixGetDimensions(pixm, &w, &h, NULL);
564  pix1 = pixaDisplay(pixa, w, h); /* recover original image */
565  pix2 = pixCreate(w, h, 8); /* make an 8 bpp white image ... */
566  pixSetColormap(pix2, pixcmapCreate(8)); /* that's cmapped ... */
567  pixSetBlackOrWhite(pix2, L_SET_WHITE); /* and init to white */
568  pixSetMaskedCmap(pix2, pix1, 0, 0, 255, 0, 0); /* color all fg red */
569  pixRasterop(pix1, 0, 0, w, h, PIX_MASK, pixm, 0, 0);
570  pixSetMaskedCmap(pix2, pix1, 0, 0, 0, 255, 0); /* turn masked green */
571  pixDisplay(pix2, 100, 100);
572  pixDestroy(&pix1);
573  pixDestroy(&pix2);
574  }
575 
576  return na;
577 }
578 
579 
604 l_ok
606  BOX *box,
607  PIX *pixm,
608  l_int32 *tab,
609  l_float32 *pfract)
610 {
611 l_int32 x, y, w, h, sum, masksum;
612 l_int32 *tab8;
613 PIX *pix1;
614 
615  PROCNAME("pixFindAreaFractionMasked");
616 
617  if (!pfract)
618  return ERROR_INT("&fract not defined", procName, 1);
619  *pfract = 0.0;
620  if (!pixs || pixGetDepth(pixs) != 1)
621  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
622  if (!pixm || pixGetDepth(pixm) != 1)
623  return ERROR_INT("pixm not defined or not 1 bpp", procName, 1);
624 
625  if (!tab)
626  tab8 = makePixelSumTab8();
627  else
628  tab8 = tab;
629  x = y = 0;
630  if (box)
631  boxGetGeometry(box, &x, &y, NULL, NULL);
632  pixGetDimensions(pixs, &w, &h, NULL);
633 
634  pix1 = pixCopy(NULL, pixs);
635  pixRasterop(pix1, 0, 0, w, h, PIX_MASK, pixm, x, y);
636  pixCountPixels(pixs, &sum, tab8);
637  if (sum == 0) {
638  pixDestroy(&pix1);
639  if (!tab) LEPT_FREE(tab8);
640  return 0;
641  }
642  pixCountPixels(pix1, &masksum, tab8);
643  *pfract = (l_float32)masksum / (l_float32)sum;
644 
645  if (!tab) LEPT_FREE(tab8);
646  pixDestroy(&pix1);
647  return 0;
648 }
649 
650 
663 NUMA *
665 {
666 l_int32 i, n, w, h;
667 NUMA *na;
668 PIX *pixt;
669 
670  PROCNAME("pixaFindWidthHeightRatio");
671 
672  if (!pixa)
673  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
674 
675  n = pixaGetCount(pixa);
676  na = numaCreate(n);
677  for (i = 0; i < n; i++) {
678  pixt = pixaGetPix(pixa, i, L_CLONE);
679  pixGetDimensions(pixt, &w, &h, NULL);
680  numaAddNumber(na, (l_float32)w / (l_float32)h);
681  pixDestroy(&pixt);
682  }
683  return na;
684 }
685 
686 
699 NUMA *
701 {
702 l_int32 i, n, w, h;
703 NUMA *na;
704 PIX *pixt;
705 
706  PROCNAME("pixaFindWidthHeightProduct");
707 
708  if (!pixa)
709  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
710 
711  n = pixaGetCount(pixa);
712  na = numaCreate(n);
713  for (i = 0; i < n; i++) {
714  pixt = pixaGetPix(pixa, i, L_CLONE);
715  pixGetDimensions(pixt, &w, &h, NULL);
716  numaAddNumber(na, w * h);
717  pixDestroy(&pixt);
718  }
719  return na;
720 }
721 
722 
739 l_ok
741  PIX *pixs2,
742  l_int32 x2,
743  l_int32 y2,
744  l_int32 *tab,
745  l_float32 *pratio,
746  l_int32 *pnoverlap)
747 {
748 l_int32 *tab8;
749 l_int32 w, h, nintersect, nunion;
750 PIX *pixt;
751 
752  PROCNAME("pixFindOverlapFraction");
753 
754  if (pnoverlap) *pnoverlap = 0;
755  if (!pratio)
756  return ERROR_INT("&ratio not defined", procName, 1);
757  *pratio = 0.0;
758  if (!pixs1 || pixGetDepth(pixs1) != 1)
759  return ERROR_INT("pixs1 not defined or not 1 bpp", procName, 1);
760  if (!pixs2 || pixGetDepth(pixs2) != 1)
761  return ERROR_INT("pixs2 not defined or not 1 bpp", procName, 1);
762 
763  if (!tab)
764  tab8 = makePixelSumTab8();
765  else
766  tab8 = tab;
767 
768  pixGetDimensions(pixs2, &w, &h, NULL);
769  pixt = pixCopy(NULL, pixs1);
770  pixRasterop(pixt, x2, y2, w, h, PIX_MASK, pixs2, 0, 0); /* AND */
771  pixCountPixels(pixt, &nintersect, tab8);
772  if (pnoverlap)
773  *pnoverlap = nintersect;
774  pixCopy(pixt, pixs1);
775  pixRasterop(pixt, x2, y2, w, h, PIX_PAINT, pixs2, 0, 0); /* OR */
776  pixCountPixels(pixt, &nunion, tab8);
777  if (!tab) LEPT_FREE(tab8);
778  pixDestroy(&pixt);
779 
780  if (nunion > 0)
781  *pratio = (l_float32)nintersect / (l_float32)nunion;
782  return 0;
783 }
784 
785 
806 BOXA *
808  l_int32 dist,
809  l_int32 minw,
810  l_int32 minh)
811 {
812 l_int32 w, h, i, n, conforms;
813 BOX *box;
814 BOXA *boxa, *boxad;
815 PIX *pix;
816 PIXA *pixa;
817 
818  PROCNAME("pixFindRectangleComps");
819 
820  if (!pixs || pixGetDepth(pixs) != 1)
821  return (BOXA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
822  if (dist < 0)
823  return (BOXA *)ERROR_PTR("dist must be >= 0", procName, NULL);
824  if (minw <= 2 * dist && minh <= 2 * dist)
825  return (BOXA *)ERROR_PTR("invalid parameters", procName, NULL);
826 
827  boxa = pixConnComp(pixs, &pixa, 8);
828  boxad = boxaCreate(0);
829  n = pixaGetCount(pixa);
830  for (i = 0; i < n; i++) {
831  pix = pixaGetPix(pixa, i, L_CLONE);
832  pixGetDimensions(pix, &w, &h, NULL);
833  if (w < minw || h < minh) {
834  pixDestroy(&pix);
835  continue;
836  }
837  pixConformsToRectangle(pix, NULL, dist, &conforms);
838  if (conforms) {
839  box = boxaGetBox(boxa, i, L_COPY);
840  boxaAddBox(boxad, box, L_INSERT);
841  }
842  pixDestroy(&pix);
843  }
844  boxaDestroy(&boxa);
845  pixaDestroy(&pixa);
846  return boxad;
847 }
848 
849 
886 l_ok
888  BOX *box,
889  l_int32 dist,
890  l_int32 *pconforms)
891 {
892 l_int32 w, h, empty;
893 PIX *pix1, *pix2;
894 
895  PROCNAME("pixConformsToRectangle");
896 
897  if (!pconforms)
898  return ERROR_INT("&conforms not defined", procName, 1);
899  *pconforms = 0;
900  if (!pixs || pixGetDepth(pixs) != 1)
901  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
902  if (dist < 0)
903  return ERROR_INT("dist must be >= 0", procName, 1);
904  pixGetDimensions(pixs, &w, &h, NULL);
905  if (w <= 2 * dist || h <= 2 * dist) {
906  L_WARNING("automatic conformation: distance too large\n", procName);
907  *pconforms = 1;
908  return 0;
909  }
910 
911  /* Extract the region, if necessary */
912  if (box)
913  pix1 = pixClipRectangle(pixs, box, NULL);
914  else
915  pix1 = pixCopy(NULL, pixs);
916 
917  /* Invert and fill from the boundary into the interior.
918  * Because we're considering the connected component in an
919  * 8-connected sense, we do the background filling as 4 c.c. */
920  pixInvert(pix1, pix1);
921  pix2 = pixExtractBorderConnComps(pix1, 4);
922 
923  /* Mask out all pixels within a distance %dist from the box
924  * boundary. Any remaining pixels are from filling that goes
925  * more than %dist from the boundary. If no pixels remain,
926  * the component conforms to the bounding rectangle within
927  * a distance %dist. */
928  pixSetOrClearBorder(pix2, dist, dist, dist, dist, PIX_CLR);
929  pixZero(pix2, &empty);
930  pixDestroy(&pix1);
931  pixDestroy(&pix2);
932  *pconforms = (empty) ? 1 : 0;
933  return 0;
934 }
935 
936 
937 /*-----------------------------------------------------------------------*
938  * Extract rectangular region *
939  *-----------------------------------------------------------------------*/
953 PIXA *
955  BOXA *boxa)
956 {
957 l_int32 i, n;
958 BOX *box, *boxc;
959 PIX *pix;
960 PIXA *pixa;
961 
962  PROCNAME("pixClipRectangles");
963 
964  if (!pixs)
965  return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
966  if (!boxa)
967  return (PIXA *)ERROR_PTR("boxa not defined", procName, NULL);
968 
969  n = boxaGetCount(boxa);
970  pixa = pixaCreate(n);
971  for (i = 0; i < n; i++) {
972  box = boxaGetBox(boxa, i, L_CLONE);
973  pix = pixClipRectangle(pixs, box, &boxc);
974  pixaAddPix(pixa, pix, L_INSERT);
975  pixaAddBox(pixa, boxc, L_INSERT);
976  boxDestroy(&box);
977  }
978 
979  return pixa;
980 }
981 
982 
1019 PIX *
1021  BOX *box,
1022  BOX **pboxc)
1023 {
1024 l_int32 w, h, d, bx, by, bw, bh;
1025 BOX *boxc;
1026 PIX *pixd;
1027 
1028  PROCNAME("pixClipRectangle");
1029 
1030  if (pboxc) *pboxc = NULL;
1031  if (!pixs)
1032  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1033  if (!box)
1034  return (PIX *)ERROR_PTR("box not defined", procName, NULL);
1035 
1036  /* Clip the input box to the pix */
1037  pixGetDimensions(pixs, &w, &h, &d);
1038  if ((boxc = boxClipToRectangle(box, w, h)) == NULL) {
1039  L_WARNING("box doesn't overlap pix\n", procName);
1040  return NULL;
1041  }
1042  boxGetGeometry(boxc, &bx, &by, &bw, &bh);
1043 
1044  /* Extract the block */
1045  if ((pixd = pixCreate(bw, bh, d)) == NULL) {
1046  boxDestroy(&boxc);
1047  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1048  }
1049  pixCopyResolution(pixd, pixs);
1050  pixCopyColormap(pixd, pixs);
1051  pixCopyText(pixd, pixs);
1052  pixRasterop(pixd, 0, 0, bw, bh, PIX_SRC, pixs, bx, by);
1053 
1054  if (pboxc)
1055  *pboxc = boxc;
1056  else
1057  boxDestroy(&boxc);
1058 
1059  return pixd;
1060 }
1061 
1062 
1092 PIX *
1094  PIX *pixm,
1095  l_int32 x,
1096  l_int32 y,
1097  l_uint32 outval)
1098 {
1099 l_int32 wm, hm, index, rval, gval, bval;
1100 l_uint32 pixel;
1101 BOX *box;
1102 PIX *pixmi, *pixd;
1103 PIXCMAP *cmap;
1104 
1105  PROCNAME("pixClipMasked");
1106 
1107  if (!pixs)
1108  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1109  if (!pixm || pixGetDepth(pixm) != 1)
1110  return (PIX *)ERROR_PTR("pixm undefined or not 1 bpp", procName, NULL);
1111 
1112  /* Clip out the region specified by pixm and (x,y) */
1113  pixGetDimensions(pixm, &wm, &hm, NULL);
1114  box = boxCreate(x, y, wm, hm);
1115  pixd = pixClipRectangle(pixs, box, NULL);
1116 
1117  /* Paint 'outval' (or something close to it if cmapped) through
1118  * the pixels not masked by pixm */
1119  cmap = pixGetColormap(pixd);
1120  pixmi = pixInvert(NULL, pixm);
1121  if (cmap) {
1122  extractRGBValues(outval, &rval, &gval, &bval);
1123  pixcmapGetNearestIndex(cmap, rval, gval, bval, &index);
1124  pixcmapGetColor(cmap, index, &rval, &gval, &bval);
1125  composeRGBPixel(rval, gval, bval, &pixel);
1126  pixPaintThroughMask(pixd, pixmi, 0, 0, pixel);
1127  } else {
1128  pixPaintThroughMask(pixd, pixmi, 0, 0, outval);
1129  }
1130 
1131  boxDestroy(&box);
1132  pixDestroy(&pixmi);
1133  return pixd;
1134 }
1135 
1136 
1154 l_ok
1156  PIX *pixs2,
1157  PIX **ppixd1,
1158  PIX **ppixd2)
1159 {
1160 l_int32 w1, h1, w2, h2, w, h;
1161 
1162  PROCNAME("pixCropToMatch");
1163 
1164  if (!ppixd1 || !ppixd2)
1165  return ERROR_INT("&pixd1 and &pixd2 not both defined", procName, 1);
1166  *ppixd1 = *ppixd2 = NULL;
1167  if (!pixs1 || !pixs2)
1168  return ERROR_INT("pixs1 and pixs2 not defined", procName, 1);
1169 
1170  pixGetDimensions(pixs1, &w1, &h1, NULL);
1171  pixGetDimensions(pixs2, &w2, &h2, NULL);
1172  w = L_MIN(w1, w2);
1173  h = L_MIN(h1, h2);
1174 
1175  *ppixd1 = pixCropToSize(pixs1, w, h);
1176  *ppixd2 = pixCropToSize(pixs2, w, h);
1177  if (*ppixd1 == NULL || *ppixd2 == NULL)
1178  return ERROR_INT("cropped image failure", procName, 1);
1179  return 0;
1180 }
1181 
1182 
1197 PIX *
1199  l_int32 w,
1200  l_int32 h)
1201 {
1202 l_int32 ws, hs, wd, hd, d;
1203 PIX *pixd;
1204 
1205  PROCNAME("pixCropToSize");
1206 
1207  if (!pixs)
1208  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1209 
1210  pixGetDimensions(pixs, &ws, &hs, &d);
1211  if (ws <= w && hs <= h) /* no cropping necessary */
1212  return pixClone(pixs);
1213 
1214  wd = L_MIN(ws, w);
1215  hd = L_MIN(hs, h);
1216  if ((pixd = pixCreate(wd, hd, d)) == NULL)
1217  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1218  pixCopyResolution(pixd, pixs);
1219  pixCopyColormap(pixd, pixs);
1220  pixCopyText(pixd, pixs);
1221  pixCopyInputFormat(pixd, pixs);
1222  pixRasterop(pixd, 0, 0, wd, hd, PIX_SRC, pixs, 0, 0);
1223  return pixd;
1224 }
1225 
1226 
1251 PIX *
1253  PIX *pixt,
1254  l_int32 w,
1255  l_int32 h)
1256 {
1257 l_int32 i, j, ws, hs, d;
1258 PIX *pixd;
1259 
1260  PROCNAME("pixResizeToMatch");
1261 
1262  if (!pixs)
1263  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1264  if (!pixt && (w <= 0 || h <= 0))
1265  return (PIX *)ERROR_PTR("both w and h not > 0", procName, NULL);
1266 
1267  if (pixt) /* redefine w, h */
1268  pixGetDimensions(pixt, &w, &h, NULL);
1269  pixGetDimensions(pixs, &ws, &hs, &d);
1270  if (ws == w && hs == h)
1271  return pixCopy(NULL, pixs);
1272 
1273  if ((pixd = pixCreate(w, h, d)) == NULL)
1274  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1275  pixCopyResolution(pixd, pixs);
1276  pixCopyColormap(pixd, pixs);
1277  pixCopyText(pixd, pixs);
1278  pixCopyInputFormat(pixd, pixs);
1279  pixRasterop(pixd, 0, 0, ws, hs, PIX_SRC, pixs, 0, 0);
1280  if (ws >= w && hs >= h)
1281  return pixd;
1282 
1283  /* Replicate the last column and then the last row */
1284  if (ws < w) {
1285  for (j = ws; j < w; j++)
1286  pixRasterop(pixd, j, 0, 1, h, PIX_SRC, pixd, ws - 1, 0);
1287  }
1288  if (hs < h) {
1289  for (i = hs; i < h; i++)
1290  pixRasterop(pixd, 0, i, w, 1, PIX_SRC, pixd, 0, hs - 1);
1291  }
1292 
1293  return pixd;
1294 }
1295 
1296 
1297 /*---------------------------------------------------------------------*
1298  * Select a connected component by size *
1299  *---------------------------------------------------------------------*/
1320 PIX *
1321 pixSelectComponentBySize(PIX *pixs,
1322  l_int32 rankorder,
1323  l_int32 type,
1324  l_int32 connectivity,
1325  BOX **pbox)
1326 {
1327 l_int32 n, empty, sorttype, index;
1328 BOXA *boxa1;
1329 NUMA *naindex;
1330 PIX *pixd;
1331 PIXA *pixa1, *pixa2;
1332 
1333  PROCNAME("pixSelectComponentBySize");
1334 
1335  if (pbox) *pbox = NULL;
1336  if (!pixs || pixGetDepth(pixs) != 1)
1337  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1338  if (type == L_SELECT_BY_WIDTH)
1339  sorttype = L_SORT_BY_WIDTH;
1340  else if (type == L_SELECT_BY_HEIGHT)
1341  sorttype = L_SORT_BY_HEIGHT;
1342  else if (type == L_SELECT_BY_MAX_DIMENSION)
1343  sorttype = L_SORT_BY_MAX_DIMENSION;
1344  else if (type == L_SELECT_BY_AREA)
1345  sorttype = L_SORT_BY_AREA;
1346  else if (type == L_SELECT_BY_PERIMETER)
1347  sorttype = L_SORT_BY_PERIMETER;
1348  else
1349  return (PIX *)ERROR_PTR("invalid selection type", procName, NULL);
1350  if (connectivity != 4 && connectivity != 8)
1351  return (PIX *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
1352  pixZero(pixs, &empty);
1353  if (empty)
1354  return (PIX *)ERROR_PTR("no foreground pixels", procName, NULL);
1355 
1356  boxa1 = pixConnComp(pixs, &pixa1, connectivity);
1357  n = boxaGetCount(boxa1);
1358  if (rankorder < 0 || rankorder >= n)
1359  rankorder = n - 1; /* smallest */
1360  pixa2 = pixaSort(pixa1, sorttype, L_SORT_DECREASING, &naindex, L_CLONE);
1361  pixd = pixaGetPix(pixa2, rankorder, L_COPY);
1362  if (pbox) {
1363  numaGetIValue(naindex, rankorder, &index);
1364  *pbox = boxaGetBox(boxa1, index, L_COPY);
1365  }
1366 
1367  numaDestroy(&naindex);
1368  boxaDestroy(&boxa1);
1369  pixaDestroy(&pixa1);
1370  pixaDestroy(&pixa2);
1371  return pixd;
1372 }
1373 
1374 
1393 PIX *
1394 pixFilterComponentBySize(PIX *pixs,
1395  l_int32 rankorder,
1396  l_int32 type,
1397  l_int32 connectivity,
1398  BOX **pbox)
1399 {
1400 l_int32 x, y, w, h;
1401 BOX *box;
1402 PIX *pix1, *pix2;
1403 
1404  PROCNAME("pixFilterComponentBySize");
1405 
1406  if (!pixs || pixGetDepth(pixs) != 1)
1407  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1408 
1409  pix1 = pixSelectComponentBySize(pixs, rankorder, type, connectivity, &box);
1410  if (!pix1) {
1411  boxDestroy(&box);
1412  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1413  }
1414 
1415  /* Put the selected component in a new pix at the same
1416  * location as it had in %pixs */
1417  boxGetGeometry(box, &x, &y, &w, &h);
1418  pix2 = pixCreateTemplate(pixs);
1419  pixRasterop(pix2, x, y, w, h, PIX_SRC, pix1, 0, 0);
1420  if (pbox)
1421  *pbox = box;
1422  else
1423  boxDestroy(&box);
1424  pixDestroy(&pix1);
1425  return pix2;
1426 }
1427 
1428 
1429 /*---------------------------------------------------------------------*
1430  * Make a frame mask *
1431  *---------------------------------------------------------------------*/
1464 PIX *
1466  l_int32 h,
1467  l_float32 hf1,
1468  l_float32 hf2,
1469  l_float32 vf1,
1470  l_float32 vf2)
1471 {
1472 l_int32 h1, h2, v1, v2;
1473 PIX *pixd;
1474 
1475  PROCNAME("pixMakeFrameMask");
1476 
1477  if (w <= 0 || h <= 0)
1478  return (PIX *)ERROR_PTR("mask size 0", procName, NULL);
1479  if (hf1 < 0.0 || hf1 > 1.0 || hf2 < 0.0 || hf2 > 1.0)
1480  return (PIX *)ERROR_PTR("invalid horiz fractions", procName, NULL);
1481  if (vf1 < 0.0 || vf1 > 1.0 || vf2 < 0.0 || vf2 > 1.0)
1482  return (PIX *)ERROR_PTR("invalid vert fractions", procName, NULL);
1483  if (hf1 > hf2 || vf1 > vf2)
1484  return (PIX *)ERROR_PTR("invalid relative sizes", procName, NULL);
1485 
1486  pixd = pixCreate(w, h, 1);
1487 
1488  /* Special cases */
1489  if (hf1 == 0.0 && vf1 == 0.0 && hf2 == 1.0 && vf2 == 1.0) { /* full */
1490  pixSetAll(pixd);
1491  return pixd;
1492  }
1493  if (hf1 == hf2 && vf1 == vf2) { /* empty */
1494  return pixd;
1495  }
1496 
1497  /* General case */
1498  h1 = 0.5 * hf1 * w;
1499  h2 = 0.5 * hf2 * w;
1500  v1 = 0.5 * vf1 * h;
1501  v2 = 0.5 * vf2 * h;
1502  pixRasterop(pixd, h1, v1, w - 2 * h1, h - 2 * v1, PIX_SET, NULL, 0, 0);
1503  if (hf2 < 1.0 && vf2 < 1.0)
1504  pixRasterop(pixd, h2, v2, w - 2 * h2, h - 2 * v2, PIX_CLR, NULL, 0, 0);
1505  return pixd;
1506 }
1507 
1508 
1509 /*---------------------------------------------------------------------*
1510  * Generate a covering of rectangles over connected components *
1511  *---------------------------------------------------------------------*/
1530 PIX *
1532  l_int32 maxiters)
1533 {
1534 l_int32 empty, same, niters;
1535 BOXA *boxa;
1536 PIX *pix1, *pix2;
1537 
1538  PROCNAME("pixMakeCoveringOfRectangles");
1539 
1540  if (!pixs || pixGetDepth(pixs) != 1)
1541  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1542  if (maxiters < 0)
1543  return (PIX *)ERROR_PTR("maxiters must be >= 0", procName, NULL);
1544  if (maxiters == 0) maxiters = 50; /* ridiculously large number */
1545 
1546  pixZero(pixs, &empty);
1547  pix1 = pixCreateTemplate(pixs);
1548  if (empty) return pix1;
1549 
1550  /* Do first iteration */
1551  boxa = pixConnCompBB(pixs, 8);
1552  pixMaskBoxa(pix1, pix1, boxa, L_SET_PIXELS);
1553  boxaDestroy(&boxa);
1554  if (maxiters == 1) return pix1;
1555 
1556  niters = 1;
1557  while (niters < maxiters) { /* continue to add pixels to pix1 */
1558  niters++;
1559  boxa = pixConnCompBB(pix1, 8);
1560  pix2 = pixCopy(NULL, pix1);
1561  pixMaskBoxa(pix1, pix1, boxa, L_SET_PIXELS);
1562  boxaDestroy(&boxa);
1563  pixEqual(pix1, pix2, &same);
1564  pixDestroy(&pix2);
1565  if (same) {
1566  L_INFO("%d iterations\n", procName, niters - 1);
1567  return pix1;
1568  }
1569  }
1570  L_INFO("maxiters = %d reached\n", procName, niters);
1571  return pix1;
1572 }
1573 
1574 
1575 /*---------------------------------------------------------------------*
1576  * Fraction of Fg pixels under a mask *
1577  *---------------------------------------------------------------------*/
1603 l_ok
1605  PIX *pix2,
1606  l_float32 *pfract)
1607 {
1608 l_int32 w1, h1, w2, h2, empty, count1, count3;
1609 PIX *pix3;
1610 
1611  PROCNAME("pixFractionFgInMask");
1612 
1613  if (!pfract)
1614  return ERROR_INT("&fract not defined", procName, 1);
1615  *pfract = 0.0;
1616  if (!pix1 || pixGetDepth(pix1) != 1)
1617  return ERROR_INT("pix1 not defined or not 1 bpp", procName, 1);
1618  if (!pix2 || pixGetDepth(pix2) != 1)
1619  return ERROR_INT("pix2 not defined or not 1 bpp", procName, 1);
1620 
1621  pixGetDimensions(pix1, &w1, &h1, NULL);
1622  pixGetDimensions(pix2, &w2, &h2, NULL);
1623  if (w1 != w2 || h1 != h2) {
1624  L_INFO("sizes unequal: (w1,w2) = (%d,%d), (h1,h2) = (%d,%d)\n",
1625  procName, w1, w2, h1, h2);
1626  }
1627  pixZero(pix1, &empty);
1628  if (empty) return 0;
1629  pixZero(pix2, &empty);
1630  if (empty) return 0;
1631 
1632  pix3 = pixCopy(NULL, pix1);
1633  pixAnd(pix3, pix3, pix2);
1634  pixCountPixels(pix1, &count1, NULL); /* |1| */
1635  pixCountPixels(pix3, &count3, NULL); /* |1 & 2| */
1636  *pfract = (l_float32)count3 / (l_float32)count1;
1637  pixDestroy(&pix3);
1638  return 0;
1639 }
1640 
1641 
1642 /*---------------------------------------------------------------------*
1643  * Clip to Foreground *
1644  *---------------------------------------------------------------------*/
1659 l_ok
1661  PIX **ppixd,
1662  BOX **pbox)
1663 {
1664 l_int32 w, h, wpl, nfullwords, extra, i, j;
1665 l_int32 minx, miny, maxx, maxy;
1666 l_uint32 result, mask;
1667 l_uint32 *data, *line;
1668 BOX *box;
1669 
1670  PROCNAME("pixClipToForeground");
1671 
1672  if (ppixd) *ppixd = NULL;
1673  if (pbox) *pbox = NULL;
1674  if (!ppixd && !pbox)
1675  return ERROR_INT("no output requested", procName, 1);
1676  if (!pixs || (pixGetDepth(pixs) != 1))
1677  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1678 
1679  pixGetDimensions(pixs, &w, &h, NULL);
1680  nfullwords = w / 32;
1681  extra = w & 31;
1682  mask = ~rmask32[32 - extra];
1683  wpl = pixGetWpl(pixs);
1684  data = pixGetData(pixs);
1685 
1686  result = 0;
1687  for (i = 0, miny = 0; i < h; i++, miny++) {
1688  line = data + i * wpl;
1689  for (j = 0; j < nfullwords; j++)
1690  result |= line[j];
1691  if (extra)
1692  result |= (line[j] & mask);
1693  if (result)
1694  break;
1695  }
1696  if (miny == h) /* no ON pixels */
1697  return 1;
1698 
1699  result = 0;
1700  for (i = h - 1, maxy = h - 1; i >= 0; i--, maxy--) {
1701  line = data + i * wpl;
1702  for (j = 0; j < nfullwords; j++)
1703  result |= line[j];
1704  if (extra)
1705  result |= (line[j] & mask);
1706  if (result)
1707  break;
1708  }
1709 
1710  minx = 0;
1711  for (j = 0, minx = 0; j < w; j++, minx++) {
1712  for (i = 0; i < h; i++) {
1713  line = data + i * wpl;
1714  if (GET_DATA_BIT(line, j))
1715  goto minx_found;
1716  }
1717  }
1718 
1719 minx_found:
1720  for (j = w - 1, maxx = w - 1; j >= 0; j--, maxx--) {
1721  for (i = 0; i < h; i++) {
1722  line = data + i * wpl;
1723  if (GET_DATA_BIT(line, j))
1724  goto maxx_found;
1725  }
1726  }
1727 
1728 maxx_found:
1729  box = boxCreate(minx, miny, maxx - minx + 1, maxy - miny + 1);
1730 
1731  if (ppixd)
1732  *ppixd = pixClipRectangle(pixs, box, NULL);
1733  if (pbox)
1734  *pbox = box;
1735  else
1736  boxDestroy(&box);
1737 
1738  return 0;
1739 }
1740 
1741 
1759 l_ok
1761  l_int32 *pcanclip)
1762 {
1763 l_int32 i, j, w, h, wpl, found;
1764 l_uint32 *data, *line;
1765 
1766  PROCNAME("pixTestClipToForeground");
1767 
1768  if (!pcanclip)
1769  return ERROR_INT("&canclip not defined", procName, 1);
1770  *pcanclip = 0;
1771  if (!pixs || (pixGetDepth(pixs) != 1))
1772  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1773 
1774  /* Check top and bottom raster lines */
1775  pixGetDimensions(pixs, &w, &h, NULL);
1776  data = pixGetData(pixs);
1777  wpl = pixGetWpl(pixs);
1778  found = FALSE;
1779  for (j = 0; found == FALSE && j < w; j++)
1780  found = GET_DATA_BIT(data, j);
1781  if (!found) {
1782  *pcanclip = 1;
1783  return 0;
1784  }
1785 
1786  line = data + (h - 1) * wpl;
1787  found = FALSE;
1788  for (j = 0; found == FALSE && j < w; j++)
1789  found = GET_DATA_BIT(data, j);
1790  if (!found) {
1791  *pcanclip = 1;
1792  return 0;
1793  }
1794 
1795  /* Check left and right edges */
1796  found = FALSE;
1797  for (i = 0, line = data; found == FALSE && i < h; line += wpl, i++)
1798  found = GET_DATA_BIT(line, 0);
1799  if (!found) {
1800  *pcanclip = 1;
1801  return 0;
1802  }
1803 
1804  found = FALSE;
1805  for (i = 0, line = data; found == FALSE && i < h; line += wpl, i++)
1806  found = GET_DATA_BIT(line, w - 1);
1807  if (!found)
1808  *pcanclip = 1;
1809 
1810  return 0; /* fg pixels found on all edges */
1811 }
1812 
1813 
1831 l_ok
1833  BOX *boxs,
1834  PIX **ppixd,
1835  BOX **pboxd)
1836 {
1837 l_int32 w, h, bx, by, bw, bh, cbw, cbh, left, right, top, bottom;
1838 BOX *boxt, *boxd;
1839 
1840  PROCNAME("pixClipBoxToForeground");
1841 
1842  if (ppixd) *ppixd = NULL;
1843  if (pboxd) *pboxd = NULL;
1844  if (!ppixd && !pboxd)
1845  return ERROR_INT("no output requested", procName, 1);
1846  if (!pixs || (pixGetDepth(pixs) != 1))
1847  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1848 
1849  if (!boxs)
1850  return pixClipToForeground(pixs, ppixd, pboxd);
1851 
1852  pixGetDimensions(pixs, &w, &h, NULL);
1853  boxGetGeometry(boxs, &bx, &by, &bw, &bh);
1854  cbw = L_MIN(bw, w - bx);
1855  cbh = L_MIN(bh, h - by);
1856  if (cbw < 0 || cbh < 0)
1857  return ERROR_INT("box not within image", procName, 1);
1858  boxt = boxCreate(bx, by, cbw, cbh);
1859 
1860  if (pixScanForForeground(pixs, boxt, L_FROM_LEFT, &left)) {
1861  boxDestroy(&boxt);
1862  return 1;
1863  }
1864  pixScanForForeground(pixs, boxt, L_FROM_RIGHT, &right);
1865  pixScanForForeground(pixs, boxt, L_FROM_TOP, &top);
1866  pixScanForForeground(pixs, boxt, L_FROM_BOT, &bottom);
1867 
1868  boxd = boxCreate(left, top, right - left + 1, bottom - top + 1);
1869  if (ppixd)
1870  *ppixd = pixClipRectangle(pixs, boxd, NULL);
1871  if (pboxd)
1872  *pboxd = boxd;
1873  else
1874  boxDestroy(&boxd);
1875 
1876  boxDestroy(&boxt);
1877  return 0;
1878 }
1879 
1880 
1897 l_ok
1899  BOX *box,
1900  l_int32 scanflag,
1901  l_int32 *ploc)
1902 {
1903 l_int32 bx, by, bw, bh, x, xstart, xend, y, ystart, yend, wpl;
1904 l_uint32 *data, *line;
1905 BOX *boxt;
1906 
1907  PROCNAME("pixScanForForeground");
1908 
1909  if (!ploc)
1910  return ERROR_INT("&loc not defined", procName, 1);
1911  *ploc = 0;
1912  if (!pixs || (pixGetDepth(pixs) != 1))
1913  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1914 
1915  /* Clip box to pixs if it exists */
1916  pixGetDimensions(pixs, &bw, &bh, NULL);
1917  if (box) {
1918  if ((boxt = boxClipToRectangle(box, bw, bh)) == NULL)
1919  return ERROR_INT("invalid box", procName, 1);
1920  boxGetGeometry(boxt, &bx, &by, &bw, &bh);
1921  boxDestroy(&boxt);
1922  } else {
1923  bx = by = 0;
1924  }
1925  xstart = bx;
1926  ystart = by;
1927  xend = bx + bw - 1;
1928  yend = by + bh - 1;
1929 
1930  data = pixGetData(pixs);
1931  wpl = pixGetWpl(pixs);
1932  if (scanflag == L_FROM_LEFT) {
1933  for (x = xstart; x <= xend; x++) {
1934  for (y = ystart; y <= yend; y++) {
1935  line = data + y * wpl;
1936  if (GET_DATA_BIT(line, x)) {
1937  *ploc = x;
1938  return 0;
1939  }
1940  }
1941  }
1942  } else if (scanflag == L_FROM_RIGHT) {
1943  for (x = xend; x >= xstart; x--) {
1944  for (y = ystart; y <= yend; y++) {
1945  line = data + y * wpl;
1946  if (GET_DATA_BIT(line, x)) {
1947  *ploc = x;
1948  return 0;
1949  }
1950  }
1951  }
1952  } else if (scanflag == L_FROM_TOP) {
1953  for (y = ystart; y <= yend; y++) {
1954  line = data + y * wpl;
1955  for (x = xstart; x <= xend; x++) {
1956  if (GET_DATA_BIT(line, x)) {
1957  *ploc = y;
1958  return 0;
1959  }
1960  }
1961  }
1962  } else if (scanflag == L_FROM_BOT) {
1963  for (y = yend; y >= ystart; y--) {
1964  line = data + y * wpl;
1965  for (x = xstart; x <= xend; x++) {
1966  if (GET_DATA_BIT(line, x)) {
1967  *ploc = y;
1968  return 0;
1969  }
1970  }
1971  }
1972  } else {
1973  return ERROR_INT("invalid scanflag", procName, 1);
1974  }
1975 
1976  return 1; /* no fg found */
1977 }
1978 
1979 
2013 l_ok
2015  BOX *boxs,
2016  l_int32 lowthresh,
2017  l_int32 highthresh,
2018  l_int32 maxwidth,
2019  l_int32 factor,
2020  PIX **ppixd,
2021  BOX **pboxd)
2022 {
2023 l_int32 w, h, bx, by, bw, bh, cbw, cbh, left, right, top, bottom;
2024 l_int32 lfound, rfound, tfound, bfound, change;
2025 BOX *boxt, *boxd;
2026 
2027  PROCNAME("pixClipBoxToEdges");
2028 
2029  if (ppixd) *ppixd = NULL;
2030  if (pboxd) *pboxd = NULL;
2031  if (!ppixd && !pboxd)
2032  return ERROR_INT("no output requested", procName, 1);
2033  if (!pixs || (pixGetDepth(pixs) != 1))
2034  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
2035  if (lowthresh < 1 || highthresh < 1 ||
2036  lowthresh > highthresh || maxwidth < 1)
2037  return ERROR_INT("invalid thresholds", procName, 1);
2038  factor = L_MIN(1, factor);
2039 
2040  if (lowthresh == 1 && highthresh == 1)
2041  return pixClipBoxToForeground(pixs, boxs, ppixd, pboxd);
2042 
2043  pixGetDimensions(pixs, &w, &h, NULL);
2044  if (boxs) {
2045  boxGetGeometry(boxs, &bx, &by, &bw, &bh);
2046  cbw = L_MIN(bw, w - bx);
2047  cbh = L_MIN(bh, h - by);
2048  if (cbw < 0 || cbh < 0)
2049  return ERROR_INT("box not within image", procName, 1);
2050  boxt = boxCreate(bx, by, cbw, cbh);
2051  } else {
2052  boxt = boxCreate(0, 0, w, h);
2053  }
2054 
2055  lfound = rfound = tfound = bfound = 0;
2056  while (!lfound || !rfound || !tfound || !bfound) {
2057  change = 0;
2058  if (!lfound) {
2059  if (!pixScanForEdge(pixs, boxt, lowthresh, highthresh, maxwidth,
2060  factor, L_FROM_LEFT, &left)) {
2061  lfound = 1;
2062  change = 1;
2063  boxRelocateOneSide(boxt, boxt, left, L_FROM_LEFT);
2064  }
2065  }
2066  if (!rfound) {
2067  if (!pixScanForEdge(pixs, boxt, lowthresh, highthresh, maxwidth,
2068  factor, L_FROM_RIGHT, &right)) {
2069  rfound = 1;
2070  change = 1;
2071  boxRelocateOneSide(boxt, boxt, right, L_FROM_RIGHT);
2072  }
2073  }
2074  if (!tfound) {
2075  if (!pixScanForEdge(pixs, boxt, lowthresh, highthresh, maxwidth,
2076  factor, L_FROM_TOP, &top)) {
2077  tfound = 1;
2078  change = 1;
2079  boxRelocateOneSide(boxt, boxt, top, L_FROM_TOP);
2080  }
2081  }
2082  if (!bfound) {
2083  if (!pixScanForEdge(pixs, boxt, lowthresh, highthresh, maxwidth,
2084  factor, L_FROM_BOT, &bottom)) {
2085  bfound = 1;
2086  change = 1;
2087  boxRelocateOneSide(boxt, boxt, bottom, L_FROM_BOT);
2088  }
2089  }
2090 
2091 #if DEBUG_EDGES
2092  fprintf(stderr, "iter: %d %d %d %d\n", lfound, rfound, tfound, bfound);
2093 #endif /* DEBUG_EDGES */
2094 
2095  if (change == 0) break;
2096  }
2097  boxDestroy(&boxt);
2098 
2099  if (change == 0)
2100  return ERROR_INT("not all edges found", procName, 1);
2101 
2102  boxd = boxCreate(left, top, right - left + 1, bottom - top + 1);
2103  if (ppixd)
2104  *ppixd = pixClipRectangle(pixs, boxd, NULL);
2105  if (pboxd)
2106  *pboxd = boxd;
2107  else
2108  boxDestroy(&boxd);
2109 
2110  return 0;
2111 }
2112 
2113 
2143 l_ok
2145  BOX *box,
2146  l_int32 lowthresh,
2147  l_int32 highthresh,
2148  l_int32 maxwidth,
2149  l_int32 factor,
2150  l_int32 scanflag,
2151  l_int32 *ploc)
2152 {
2153 l_int32 bx, by, bw, bh, foundmin, loc, sum, wpl;
2154 l_int32 x, xstart, xend, y, ystart, yend;
2155 l_uint32 *data, *line;
2156 BOX *boxt;
2157 
2158  PROCNAME("pixScanForEdge");
2159 
2160  if (!ploc)
2161  return ERROR_INT("&ploc not defined", procName, 1);
2162  *ploc = 0;
2163  if (!pixs || (pixGetDepth(pixs) != 1))
2164  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
2165  if (lowthresh < 1 || highthresh < 1 ||
2166  lowthresh > highthresh || maxwidth < 1)
2167  return ERROR_INT("invalid thresholds", procName, 1);
2168  factor = L_MIN(1, factor);
2169 
2170  /* Clip box to pixs if it exists */
2171  pixGetDimensions(pixs, &bw, &bh, NULL);
2172  if (box) {
2173  if ((boxt = boxClipToRectangle(box, bw, bh)) == NULL)
2174  return ERROR_INT("invalid box", procName, 1);
2175  boxGetGeometry(boxt, &bx, &by, &bw, &bh);
2176  boxDestroy(&boxt);
2177  } else {
2178  bx = by = 0;
2179  }
2180  xstart = bx;
2181  ystart = by;
2182  xend = bx + bw - 1;
2183  yend = by + bh - 1;
2184 
2185  data = pixGetData(pixs);
2186  wpl = pixGetWpl(pixs);
2187  foundmin = 0;
2188  if (scanflag == L_FROM_LEFT) {
2189  for (x = xstart; x <= xend; x++) {
2190  sum = 0;
2191  for (y = ystart; y <= yend; y += factor) {
2192  line = data + y * wpl;
2193  if (GET_DATA_BIT(line, x))
2194  sum++;
2195  }
2196  if (!foundmin && sum < lowthresh)
2197  continue;
2198  if (!foundmin) { /* save the loc of the beginning of the edge */
2199  foundmin = 1;
2200  loc = x;
2201  }
2202  if (sum >= highthresh) {
2203 #if DEBUG_EDGES
2204  fprintf(stderr, "Left: x = %d, loc = %d\n", x, loc);
2205 #endif /* DEBUG_EDGES */
2206  if (x - loc < maxwidth) {
2207  *ploc = loc;
2208  return 0;
2209  } else {
2210  return 1;
2211  }
2212  }
2213  }
2214  } else if (scanflag == L_FROM_RIGHT) {
2215  for (x = xend; x >= xstart; x--) {
2216  sum = 0;
2217  for (y = ystart; y <= yend; y += factor) {
2218  line = data + y * wpl;
2219  if (GET_DATA_BIT(line, x))
2220  sum++;
2221  }
2222  if (!foundmin && sum < lowthresh)
2223  continue;
2224  if (!foundmin) {
2225  foundmin = 1;
2226  loc = x;
2227  }
2228  if (sum >= highthresh) {
2229 #if DEBUG_EDGES
2230  fprintf(stderr, "Right: x = %d, loc = %d\n", x, loc);
2231 #endif /* DEBUG_EDGES */
2232  if (loc - x < maxwidth) {
2233  *ploc = loc;
2234  return 0;
2235  } else {
2236  return 1;
2237  }
2238  }
2239  }
2240  } else if (scanflag == L_FROM_TOP) {
2241  for (y = ystart; y <= yend; y++) {
2242  sum = 0;
2243  line = data + y * wpl;
2244  for (x = xstart; x <= xend; x += factor) {
2245  if (GET_DATA_BIT(line, x))
2246  sum++;
2247  }
2248  if (!foundmin && sum < lowthresh)
2249  continue;
2250  if (!foundmin) {
2251  foundmin = 1;
2252  loc = y;
2253  }
2254  if (sum >= highthresh) {
2255 #if DEBUG_EDGES
2256  fprintf(stderr, "Top: y = %d, loc = %d\n", y, loc);
2257 #endif /* DEBUG_EDGES */
2258  if (y - loc < maxwidth) {
2259  *ploc = loc;
2260  return 0;
2261  } else {
2262  return 1;
2263  }
2264  }
2265  }
2266  } else if (scanflag == L_FROM_BOT) {
2267  for (y = yend; y >= ystart; y--) {
2268  sum = 0;
2269  line = data + y * wpl;
2270  for (x = xstart; x <= xend; x += factor) {
2271  if (GET_DATA_BIT(line, x))
2272  sum++;
2273  }
2274  if (!foundmin && sum < lowthresh)
2275  continue;
2276  if (!foundmin) {
2277  foundmin = 1;
2278  loc = y;
2279  }
2280  if (sum >= highthresh) {
2281 #if DEBUG_EDGES
2282  fprintf(stderr, "Bottom: y = %d, loc = %d\n", y, loc);
2283 #endif /* DEBUG_EDGES */
2284  if (loc - y < maxwidth) {
2285  *ploc = loc;
2286  return 0;
2287  } else {
2288  return 1;
2289  }
2290  }
2291  }
2292  } else {
2293  return ERROR_INT("invalid scanflag", procName, 1);
2294  }
2295 
2296  return 1; /* edge not found */
2297 }
2298 
2299 
2300 /*---------------------------------------------------------------------*
2301  * Extract pixel averages and reversals along lines *
2302  *---------------------------------------------------------------------*/
2324 NUMA *
2326  l_int32 x1,
2327  l_int32 y1,
2328  l_int32 x2,
2329  l_int32 y2,
2330  l_int32 factor)
2331 {
2332 l_int32 i, w, h, d, xmin, ymin, xmax, ymax, npts, direction;
2333 l_uint32 val;
2334 l_float32 x, y;
2335 l_float64 slope;
2336 NUMA *na;
2337 PTA *pta;
2338 
2339  PROCNAME("pixExtractOnLine");
2340 
2341  if (!pixs)
2342  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
2343  pixGetDimensions(pixs, &w, &h, &d);
2344  if (d != 1 && d != 8)
2345  return (NUMA *)ERROR_PTR("d not 1 or 8 bpp", procName, NULL);
2346  if (pixGetColormap(pixs))
2347  return (NUMA *)ERROR_PTR("pixs has a colormap", procName, NULL);
2348  if (factor < 1) {
2349  L_WARNING("factor must be >= 1; setting to 1\n", procName);
2350  factor = 1;
2351  }
2352 
2353  /* Clip line to the image */
2354  x1 = L_MAX(0, L_MIN(x1, w - 1));
2355  x2 = L_MAX(0, L_MIN(x2, w - 1));
2356  y1 = L_MAX(0, L_MIN(y1, h - 1));
2357  y2 = L_MAX(0, L_MIN(y2, h - 1));
2358 
2359  if (x1 == x2 && y1 == y2) {
2360  pixGetPixel(pixs, x1, y1, &val);
2361  na = numaCreate(1);
2362  numaAddNumber(na, val);
2363  return na;
2364  }
2365 
2366  if (y1 == y2)
2367  direction = L_HORIZONTAL_LINE;
2368  else if (x1 == x2)
2369  direction = L_VERTICAL_LINE;
2370  else
2371  direction = L_OBLIQUE_LINE;
2372 
2373  na = numaCreate(0);
2374  if (direction == L_HORIZONTAL_LINE) { /* plot against x */
2375  xmin = L_MIN(x1, x2);
2376  xmax = L_MAX(x1, x2);
2377  numaSetParameters(na, xmin, factor);
2378  for (i = xmin; i <= xmax; i += factor) {
2379  pixGetPixel(pixs, i, y1, &val);
2380  numaAddNumber(na, val);
2381  }
2382  } else if (direction == L_VERTICAL_LINE) { /* plot against y */
2383  ymin = L_MIN(y1, y2);
2384  ymax = L_MAX(y1, y2);
2385  numaSetParameters(na, ymin, factor);
2386  for (i = ymin; i <= ymax; i += factor) {
2387  pixGetPixel(pixs, x1, i, &val);
2388  numaAddNumber(na, val);
2389  }
2390  } else { /* direction == L_OBLIQUE_LINE */
2391  slope = (l_float64)((y2 - y1) / (x2 - x1));
2392  if (L_ABS(slope) < 1.0) { /* quasi-horizontal */
2393  xmin = L_MIN(x1, x2);
2394  xmax = L_MAX(x1, x2);
2395  ymin = (xmin == x1) ? y1 : y2; /* pt that goes with xmin */
2396  ymax = (ymin == y1) ? y2 : y1; /* pt that goes with xmax */
2397  pta = generatePtaLine(xmin, ymin, xmax, ymax);
2398  numaSetParameters(na, xmin, (l_float32)factor);
2399  } else { /* quasi-vertical */
2400  ymin = L_MIN(y1, y2);
2401  ymax = L_MAX(y1, y2);
2402  xmin = (ymin == y1) ? x1 : x2; /* pt that goes with ymin */
2403  xmax = (xmin == x1) ? x2 : x1; /* pt that goes with ymax */
2404  pta = generatePtaLine(xmin, ymin, xmax, ymax);
2405  numaSetParameters(na, ymin, (l_float32)factor);
2406  }
2407  npts = ptaGetCount(pta);
2408  for (i = 0; i < npts; i += factor) {
2409  ptaGetPt(pta, i, &x, &y);
2410  pixGetPixel(pixs, (l_int32)x, (l_int32)y, &val);
2411  numaAddNumber(na, val);
2412  }
2413 
2414 #if 0 /* debugging */
2415  pixPlotAlongPta(pixs, pta, GPLOT_PNG, NULL);
2416 #endif
2417 
2418  ptaDestroy(&pta);
2419  }
2420 
2421  return na;
2422 }
2423 
2424 
2444 l_float32
2446  l_int32 x1,
2447  l_int32 y1,
2448  l_int32 x2,
2449  l_int32 y2,
2450  l_int32 factor)
2451 {
2452 l_int32 i, j, w, h, d, direction, count, wpl;
2453 l_uint32 *data, *line;
2454 l_float32 sum;
2455 
2456  PROCNAME("pixAverageOnLine");
2457 
2458  if (!pixs)
2459  return ERROR_INT("pixs not defined", procName, 1);
2460  pixGetDimensions(pixs, &w, &h, &d);
2461  if (d != 1 && d != 8)
2462  return ERROR_INT("d not 1 or 8 bpp", procName, 1);
2463  if (pixGetColormap(pixs))
2464  return ERROR_INT("pixs has a colormap", procName, 1);
2465  if (x1 > x2 || y1 > y2)
2466  return ERROR_INT("x1 > x2 or y1 > y2", procName, 1);
2467 
2468  if (y1 == y2) {
2469  x1 = L_MAX(0, x1);
2470  x2 = L_MIN(w - 1, x2);
2471  y1 = L_MAX(0, L_MIN(y1, h - 1));
2472  direction = L_HORIZONTAL_LINE;
2473  } else if (x1 == x2) {
2474  y1 = L_MAX(0, y1);
2475  y2 = L_MIN(h - 1, y2);
2476  x1 = L_MAX(0, L_MIN(x1, w - 1));
2477  direction = L_VERTICAL_LINE;
2478  } else {
2479  return ERROR_INT("line neither horiz nor vert", procName, 1);
2480  }
2481 
2482  if (factor < 1) {
2483  L_WARNING("factor must be >= 1; setting to 1\n", procName);
2484  factor = 1;
2485  }
2486 
2487  data = pixGetData(pixs);
2488  wpl = pixGetWpl(pixs);
2489  sum = 0;
2490  count = 0;
2491  if (direction == L_HORIZONTAL_LINE) {
2492  line = data + y1 * wpl;
2493  for (j = x1, count = 0; j <= x2; count++, j += factor) {
2494  if (d == 1)
2495  sum += GET_DATA_BIT(line, j);
2496  else /* d == 8 */
2497  sum += GET_DATA_BYTE(line, j);
2498  }
2499  } else if (direction == L_VERTICAL_LINE) {
2500  for (i = y1, count = 0; i <= y2; count++, i += factor) {
2501  line = data + i * wpl;
2502  if (d == 1)
2503  sum += GET_DATA_BIT(line, x1);
2504  else /* d == 8 */
2505  sum += GET_DATA_BYTE(line, x1);
2506  }
2507  }
2508 
2509  return sum / (l_float32)count;
2510 }
2511 
2512 
2543 NUMA *
2545  l_float32 fract,
2546  l_int32 dir,
2547  l_int32 first,
2548  l_int32 last,
2549  l_int32 factor1,
2550  l_int32 factor2)
2551 {
2552 l_int32 i, j, w, h, d, start, end;
2553 l_float32 ave;
2554 NUMA *nad;
2555 PIX *pixr, *pixg;
2556 
2557  PROCNAME("pixAverageIntensityProfile");
2558 
2559  if (!pixs)
2560  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
2561  if (fract < 0.0 || fract > 1.0)
2562  return (NUMA *)ERROR_PTR("fract < 0.0 or > 1.0", procName, NULL);
2563  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
2564  return (NUMA *)ERROR_PTR("invalid direction", procName, NULL);
2565  if (first < 0) first = 0;
2566  if (last < first)
2567  return (NUMA *)ERROR_PTR("last must be >= first", procName, NULL);
2568  if (factor1 < 1) {
2569  L_WARNING("factor1 must be >= 1; setting to 1\n", procName);
2570  factor1 = 1;
2571  }
2572  if (factor2 < 1) {
2573  L_WARNING("factor2 must be >= 1; setting to 1\n", procName);
2574  factor2 = 1;
2575  }
2576 
2577  /* Use 1 or 8 bpp, without colormap */
2578  if (pixGetColormap(pixs))
2580  else
2581  pixr = pixClone(pixs);
2582  pixGetDimensions(pixr, &w, &h, &d);
2583  if (d == 1)
2584  pixg = pixClone(pixr);
2585  else
2586  pixg = pixConvertTo8(pixr, 0);
2587 
2588  nad = numaCreate(0); /* output: samples in slow scan direction */
2589  numaSetParameters(nad, 0, factor2);
2590  if (dir == L_HORIZONTAL_LINE) {
2591  start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)w);
2592  end = w - start;
2593  if (last > h - 1) {
2594  L_WARNING("last > h - 1; clipping\n", procName);
2595  last = h - 1;
2596  }
2597  for (i = first; i <= last; i += factor2) {
2598  ave = pixAverageOnLine(pixg, start, i, end, i, factor1);
2599  numaAddNumber(nad, ave);
2600  }
2601  } else if (dir == L_VERTICAL_LINE) {
2602  start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)h);
2603  end = h - start;
2604  if (last > w - 1) {
2605  L_WARNING("last > w - 1; clipping\n", procName);
2606  last = w - 1;
2607  }
2608  for (j = first; j <= last; j += factor2) {
2609  ave = pixAverageOnLine(pixg, j, start, j, end, factor1);
2610  numaAddNumber(nad, ave);
2611  }
2612  }
2613 
2614  pixDestroy(&pixr);
2615  pixDestroy(&pixg);
2616  return nad;
2617 }
2618 
2619 
2658 NUMA *
2660  l_float32 fract,
2661  l_int32 dir,
2662  l_int32 first,
2663  l_int32 last,
2664  l_int32 minreversal,
2665  l_int32 factor1,
2666  l_int32 factor2)
2667 {
2668 l_int32 i, j, w, h, d, start, end, nr;
2669 NUMA *naline, *nad;
2670 PIX *pixr, *pixg;
2671 
2672  PROCNAME("pixReversalProfile");
2673 
2674  if (!pixs)
2675  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
2676  if (fract < 0.0 || fract > 1.0)
2677  return (NUMA *)ERROR_PTR("fract < 0.0 or > 1.0", procName, NULL);
2678  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
2679  return (NUMA *)ERROR_PTR("invalid direction", procName, NULL);
2680  if (first < 0) first = 0;
2681  if (last < first)
2682  return (NUMA *)ERROR_PTR("last must be >= first", procName, NULL);
2683  if (factor1 < 1) {
2684  L_WARNING("factor1 must be >= 1; setting to 1\n", procName);
2685  factor1 = 1;
2686  }
2687  if (factor2 < 1) {
2688  L_WARNING("factor2 must be >= 1; setting to 1\n", procName);
2689  factor2 = 1;
2690  }
2691 
2692  /* Use 1 or 8 bpp, without colormap */
2693  if (pixGetColormap(pixs))
2695  else
2696  pixr = pixClone(pixs);
2697  pixGetDimensions(pixr, &w, &h, &d);
2698  if (d == 1) {
2699  pixg = pixClone(pixr);
2700  minreversal = 1; /* enforce this */
2701  } else {
2702  pixg = pixConvertTo8(pixr, 0);
2703  }
2704 
2705  nad = numaCreate(0); /* output: samples in slow scan direction */
2706  numaSetParameters(nad, 0, factor2);
2707  if (dir == L_HORIZONTAL_LINE) {
2708  start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)w);
2709  end = w - start;
2710  if (last > h - 1) {
2711  L_WARNING("last > h - 1; clipping\n", procName);
2712  last = h - 1;
2713  }
2714  for (i = first; i <= last; i += factor2) {
2715  naline = pixExtractOnLine(pixg, start, i, end, i, factor1);
2716  numaCountReversals(naline, minreversal, &nr, NULL);
2717  numaAddNumber(nad, nr);
2718  numaDestroy(&naline);
2719  }
2720  } else if (dir == L_VERTICAL_LINE) {
2721  start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)h);
2722  end = h - start;
2723  if (last > w - 1) {
2724  L_WARNING("last > w - 1; clipping\n", procName);
2725  last = w - 1;
2726  }
2727  for (j = first; j <= last; j += factor2) {
2728  naline = pixExtractOnLine(pixg, j, start, j, end, factor1);
2729  numaCountReversals(naline, minreversal, &nr, NULL);
2730  numaAddNumber(nad, nr);
2731  numaDestroy(&naline);
2732  }
2733  }
2734 
2735  pixDestroy(&pixr);
2736  pixDestroy(&pixg);
2737  return nad;
2738 }
2739 
2740 
2741 /*---------------------------------------------------------------------*
2742  * Extract windowed variance along a line *
2743  *---------------------------------------------------------------------*/
2767 l_ok
2769  l_int32 dir,
2770  l_int32 loc,
2771  l_int32 c1,
2772  l_int32 c2,
2773  l_int32 size,
2774  NUMA **pnad)
2775 {
2776 l_int32 i, j, w, h, cmin, cmax, maxloc, n, x, y;
2777 l_uint32 val;
2778 l_float32 norm, rootvar;
2779 l_float32 *array;
2780 l_float64 sum1, sum2, ave, var;
2781 NUMA *na1, *nad;
2782 PTA *pta;
2783 
2784  PROCNAME("pixWindowedVarianceOnLine");
2785 
2786  if (!pnad)
2787  return ERROR_INT("&nad not defined", procName, 1);
2788  *pnad = NULL;
2789  if (!pixs || pixGetDepth(pixs) != 8)
2790  return ERROR_INT("pixs not defined or not 8bpp", procName, 1);
2791  if (size < 2)
2792  return ERROR_INT("window size must be > 1", procName, 1);
2793  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
2794  return ERROR_INT("invalid direction", procName, 1);
2795  pixGetDimensions(pixs, &w, &h, NULL);
2796  maxloc = (dir == L_HORIZONTAL_LINE) ? h - 1 : w - 1;
2797  if (loc < 0 || loc > maxloc)
2798  return ERROR_INT("invalid line position", procName, 1);
2799 
2800  /* Clip line to the image */
2801  cmin = L_MIN(c1, c2);
2802  cmax = L_MAX(c1, c2);
2803  maxloc = (dir == L_HORIZONTAL_LINE) ? w - 1 : h - 1;
2804  cmin = L_MAX(0, L_MIN(cmin, maxloc));
2805  cmax = L_MAX(0, L_MIN(cmax, maxloc));
2806  n = cmax - cmin + 1;
2807 
2808  /* Generate pta along the line */
2809  pta = ptaCreate(n);
2810  if (dir == L_HORIZONTAL_LINE) {
2811  for (i = cmin; i <= cmax; i++)
2812  ptaAddPt(pta, i, loc);
2813  } else { /* vertical line */
2814  for (i = cmin; i <= cmax; i++)
2815  ptaAddPt(pta, loc, i);
2816  }
2817 
2818  /* Get numa of pixel values on the line */
2819  na1 = numaCreate(n);
2820  numaSetParameters(na1, cmin, 1);
2821  for (i = 0; i < n; i++) {
2822  ptaGetIPt(pta, i, &x, &y);
2823  pixGetPixel(pixs, x, y, &val);
2824  numaAddNumber(na1, val);
2825  }
2826  array = numaGetFArray(na1, L_NOCOPY);
2827  ptaDestroy(&pta);
2828 
2829  /* Compute root variance on overlapping windows */
2830  nad = numaCreate(n);
2831  *pnad = nad;
2832  numaSetParameters(nad, cmin + size / 2, 1);
2833  norm = 1.0 / (l_float32)size;
2834  for (i = 0; i < n - size; i++) { /* along the line */
2835  sum1 = sum2 = 0;
2836  for (j = 0; j < size; j++) { /* over the window */
2837  val = array[i + j];
2838  sum1 += val;
2839  sum2 += (l_float64)(val) * val;
2840  }
2841  ave = norm * sum1;
2842  var = norm * sum2 - ave * ave;
2843  rootvar = (l_float32)sqrt(var);
2844  numaAddNumber(nad, rootvar);
2845  }
2846 
2847  numaDestroy(&na1);
2848  return 0;
2849 }
2850 
2851 
2852 /*---------------------------------------------------------------------*
2853  * Extract min/max of pixel values near lines *
2854  *---------------------------------------------------------------------*/
2885 l_ok
2887  l_int32 x1,
2888  l_int32 y1,
2889  l_int32 x2,
2890  l_int32 y2,
2891  l_int32 dist,
2892  l_int32 direction,
2893  NUMA **pnamin,
2894  NUMA **pnamax,
2895  l_float32 *pminave,
2896  l_float32 *pmaxave)
2897 {
2898 l_int32 i, j, w, h, d, x, y, n, dir, found, minval, maxval, negloc, posloc;
2899 l_uint32 val;
2900 l_float32 sum;
2901 NUMA *namin, *namax;
2902 PTA *pta;
2903 
2904  PROCNAME("pixMinMaxNearLine");
2905 
2906  if (pnamin) *pnamin = NULL;
2907  if (pnamax) *pnamax = NULL;
2908  if (pminave) *pminave = UNDEF;
2909  if (pmaxave) *pmaxave = UNDEF;
2910  if (!pnamin && !pnamax && !pminave && !pmaxave)
2911  return ERROR_INT("no output requested", procName, 1);
2912  if (!pixs)
2913  return ERROR_INT("pixs not defined", procName, 1);
2914  pixGetDimensions(pixs, &w, &h, &d);
2915  if (d != 8 || pixGetColormap(pixs))
2916  return ERROR_INT("pixs not 8 bpp or has colormap", procName, 1);
2917  dist = L_ABS(dist);
2918  if (direction != L_SCAN_NEGATIVE && direction != L_SCAN_POSITIVE &&
2919  direction != L_SCAN_BOTH)
2920  return ERROR_INT("invalid direction", procName, 1);
2921 
2922  pta = generatePtaLine(x1, y1, x2, y2);
2923  n = ptaGetCount(pta);
2924  dir = (L_ABS(x1 - x2) == n - 1) ? L_HORIZ : L_VERT;
2925  namin = numaCreate(n);
2926  namax = numaCreate(n);
2927  negloc = -dist;
2928  posloc = dist;
2929  if (direction == L_SCAN_NEGATIVE)
2930  posloc = 0;
2931  else if (direction == L_SCAN_POSITIVE)
2932  negloc = 0;
2933  for (i = 0; i < n; i++) {
2934  ptaGetIPt(pta, i, &x, &y);
2935  minval = 255;
2936  maxval = 0;
2937  found = FALSE;
2938  if (dir == L_HORIZ) {
2939  if (x < 0 || x >= w) continue;
2940  for (j = negloc; j <= posloc; j++) {
2941  if (y + j < 0 || y + j >= h) continue;
2942  pixGetPixel(pixs, x, y + j, &val);
2943  found = TRUE;
2944  if (val < minval) minval = val;
2945  if (val > maxval) maxval = val;
2946  }
2947  } else { /* dir == L_VERT */
2948  if (y < 0 || y >= h) continue;
2949  for (j = negloc; j <= posloc; j++) {
2950  if (x + j < 0 || x + j >= w) continue;
2951  pixGetPixel(pixs, x + j, y, &val);
2952  found = TRUE;
2953  if (val < minval) minval = val;
2954  if (val > maxval) maxval = val;
2955  }
2956  }
2957  if (found) {
2958  numaAddNumber(namin, minval);
2959  numaAddNumber(namax, maxval);
2960  }
2961  }
2962 
2963  n = numaGetCount(namin);
2964  if (n == 0) {
2965  numaDestroy(&namin);
2966  numaDestroy(&namax);
2967  ptaDestroy(&pta);
2968  return ERROR_INT("no output from this line", procName, 1);
2969  }
2970 
2971  if (pminave) {
2972  numaGetSum(namin, &sum);
2973  *pminave = sum / n;
2974  }
2975  if (pmaxave) {
2976  numaGetSum(namax, &sum);
2977  *pmaxave = sum / n;
2978  }
2979  if (pnamin)
2980  *pnamin = namin;
2981  else
2982  numaDestroy(&namin);
2983  if (pnamax)
2984  *pnamax = namax;
2985  else
2986  numaDestroy(&namax);
2987  ptaDestroy(&pta);
2988  return 0;
2989 }
2990 
2991 
2992 /*---------------------------------------------------------------------*
2993  * Rank row and column transforms *
2994  *---------------------------------------------------------------------*/
3008 PIX *
3010 {
3011 l_int32 i, j, k, m, w, h, wpl, val;
3012 l_int32 histo[256];
3013 l_uint32 *datas, *datad, *lines, *lined;
3014 PIX *pixd;
3015 
3016  PROCNAME("pixRankRowTransform");
3017 
3018  if (!pixs)
3019  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3020  if (pixGetDepth(pixs) != 8)
3021  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
3022  if (pixGetColormap(pixs))
3023  return (PIX *)ERROR_PTR("pixs has a colormap", procName, NULL);
3024 
3025  pixGetDimensions(pixs, &w, &h, NULL);
3026  pixd = pixCreateTemplate(pixs);
3027  datas = pixGetData(pixs);
3028  datad = pixGetData(pixd);
3029  wpl = pixGetWpl(pixs);
3030  for (i = 0; i < h; i++) {
3031  memset(histo, 0, 1024);
3032  lines = datas + i * wpl;
3033  lined = datad + i * wpl;
3034  for (j = 0; j < w; j++) {
3035  val = GET_DATA_BYTE(lines, j);
3036  histo[val]++;
3037  }
3038  for (m = 0, j = 0; m < 256; m++) {
3039  for (k = 0; k < histo[m]; k++, j++)
3040  SET_DATA_BYTE(lined, j, m);
3041  }
3042  }
3043 
3044  return pixd;
3045 }
3046 
3047 
3061 PIX *
3063 {
3064 l_int32 i, j, k, m, w, h, val;
3065 l_int32 histo[256];
3066 void **lines8, **lined8;
3067 PIX *pixd;
3068 
3069  PROCNAME("pixRankColumnTransform");
3070 
3071  if (!pixs)
3072  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3073  if (pixGetDepth(pixs) != 8)
3074  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
3075  if (pixGetColormap(pixs))
3076  return (PIX *)ERROR_PTR("pixs has a colormap", procName, NULL);
3077 
3078  pixGetDimensions(pixs, &w, &h, NULL);
3079  pixd = pixCreateTemplate(pixs);
3080  lines8 = pixGetLinePtrs(pixs, NULL);
3081  lined8 = pixGetLinePtrs(pixd, NULL);
3082  for (j = 0; j < w; j++) {
3083  memset(histo, 0, 1024);
3084  for (i = 0; i < h; i++) {
3085  val = GET_DATA_BYTE(lines8[i], j);
3086  histo[val]++;
3087  }
3088  for (m = 0, i = 0; m < 256; m++) {
3089  for (k = 0; k < histo[m]; k++, i++)
3090  SET_DATA_BYTE(lined8[i], j, m);
3091  }
3092  }
3093 
3094  LEPT_FREE(lines8);
3095  LEPT_FREE(lined8);
3096  return pixd;
3097 }
l_ok numaGetSum(NUMA *na, l_float32 *psum)
numaGetSum()
Definition: numafunc1.c:527
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:322
Definition: pix.h:717
l_ok pixPlotAlongPta(PIX *pixs, PTA *pta, l_int32 outformat, const char *title)
pixPlotAlongPta()
Definition: ptafunc1.c:1807
NUMA * pixaFindAreaFraction(PIXA *pixa)
pixaFindAreaFraction()
Definition: pix5.c:435
#define PIX_CLR
Definition: pix.h:330
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:2886
NUMA * pixExtractOnLine(PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor)
pixExtractOnLine()
Definition: pix5.c:2325
BOXA * pixFindRectangleComps(PIX *pixs, l_int32 dist, l_int32 minw, l_int32 minh)
pixFindRectangleComps()
Definition: pix5.c:807
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:342
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
Definition: pix.h:716
l_ok pixcmapGetNearestIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetNearestIndex()
Definition: colormap.c:1209
PIX * pixExtractBorderConnComps(PIX *pixs, l_int32 connectivity)
pixExtractBorderConnComps()
Definition: seedfill.c:694
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:193
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:116
PIX * pixMakeFrameMask(l_int32 w, l_int32 h, l_float32 hf1, l_float32 hf2, l_float32 vf1, l_float32 vf2)
pixSelectComponentBySize()
Definition: pix5.c:1465
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1810
NUMA * pixaFindAreaFractionMasked(PIXA *pixa, PIX *pixm, l_int32 debug)
pixaFindAreaFractionMasked()
Definition: pix5.c:526
l_float32 pixAverageOnLine(PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor)
pixAverageOnLine()
Definition: pix5.c:2445
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1587
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
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:2768
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:741
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1395
NUMA * pixaFindWidthHeightRatio(PIXA *pixa)
pixaFindWidthHeightRatio()
Definition: pix5.c:664
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:504
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:580
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:797
NUMA * pixaFindPerimSizeRatio(PIXA *pixa)
pixaFindPerimSizeRatio()
Definition: pix5.c:339
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:2014
PIX * pixaDisplay(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplay()
Definition: pixafunc2.c:184
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1020
Definition: pix.h:492
NUMA * pixaFindPerimToAreaRatio(PIXA *pixa)
pixaFindPerimToAreaRatio()
Definition: pix5.c:235
PIX * pixClipMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_uint32 outval)
pixClipMasked()
Definition: pix5.c:1093
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1573
l_ok pixSetOrClearBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_int32 op)
pixSetOrClearBorder()
Definition: pix2.c:1439
NUMA * pixaFindWidthHeightProduct(PIXA *pixa)
pixaFindWidthHeightProduct()
Definition: pix5.c:700
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:618
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:111
PIX * pixMakeCoveringOfRectangles(PIX *pixs, l_int32 maxiters)
pixMakeCoveringOfRectangles()
Definition: pix5.c:1531
l_ok pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
pixClipToForeground()
Definition: pix5.c:1660
#define PIX_MASK
Definition: pix.h:334
l_ok pixaFindDimensions(PIXA *pixa, NUMA **pnaw, NUMA **pnah)
pixaFindDimensions()
Definition: pix5.c:134
l_ok numaCountReversals(NUMA *nas, l_float32 minreversal, l_int32 *pnr, l_float32 *prd)
numaCountReversals()
Definition: numafunc2.c:2577
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:147
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:2144
l_ok pixFindPerimToAreaRatio(PIX *pixs, l_int32 *tab, l_float32 *pfract)
pixFindPerimToAreaRatio()
Definition: pix5.c:285
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1574
PTA * generatePtaLine(l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2)
generatePtaLine()
Definition: graphics.c:138
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
BOXA * pixConnCompBB(PIX *pixs, l_int32 connectivity)
pixConnCompBB()
Definition: conncomp.c:306
#define PIX_SET
Definition: pix.h:331
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1510
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:751
PIX * pixCropToSize(PIX *pixs, l_int32 w, l_int32 h)
pixCropToSize()
Definition: pix5.c:1198
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1823
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:618
l_ok ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:525
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2297
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
PIXA * pixClipRectangles(PIX *pixs, BOXA *boxa)
pixClipRectangles()
Definition: pix5.c:954
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:2544
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:946
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:693
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define PIX_PAINT
Definition: pix.h:333
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:966
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
l_ok pixClipBoxToForeground(PIX *pixs, BOX *boxs, PIX **ppixd, BOX **pboxd)
pixClipBoxToForeground()
Definition: pix5.c:1832
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
l_ok pixCopyColormap(PIX *pixd, PIX *pixs)
pixCopyColormap()
Definition: pix1.c:745
PIX * pixMaskBoxa(PIX *pixd, PIX *pixs, BOXA *boxa, l_int32 op)
pixMaskBoxa()
Definition: boxfunc3.c:148
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:763
PIXA * pixaSort(PIXA *pixas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex, l_int32 copyflag)
pixaSort()
Definition: pixafunc1.c:1334
Definition: pix.h:454
PIX * pixRankColumnTransform(PIX *pixs)
pixRankColumnTransform()
Definition: pix5.c:3062
l_ok pixFindAreaFractionMasked(PIX *pixs, BOX *box, PIX *pixm, l_int32 *tab, l_float32 *pfract)
pixFindAreaFractionMasked()
Definition: pix5.c:605
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
l_ok pixFindAreaPerimRatio(PIX *pixs, l_int32 *tab, l_float32 *pfract)
pixFindAreaPerimRatio()
Definition: pix5.c:184
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:180
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
BOX * boxRelocateOneSide(BOX *boxd, BOX *boxs, l_int32 loc, l_int32 sideflag)
boxRelocateOneSide()
Definition: boxfunc1.c:1706
l_ok pixFindPerimSizeRatio(PIX *pixs, l_int32 *tab, l_float32 *pratio)
pixFindPerimSizeRatio()
Definition: pix5.c:389
l_ok pixaIsFull(PIXA *pixa, l_int32 *pfullpa, l_int32 *pfullba)
pixaIsFull()
Definition: pixabasic.c:1038
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:865
l_ok pixScanForForeground(PIX *pixs, BOX *box, l_int32 scanflag, l_int32 *ploc)
pixScanForForeground()
Definition: pix5.c:1898
l_ok pixFractionFgInMask(PIX *pix1, PIX *pix2, l_float32 *pfract)
pixFractionFgInMask()
Definition: pix5.c:1604
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:672
Definition: pix.h:718
l_ok pixCropToMatch(PIX *pixs1, PIX *pixs2, PIX **ppixd1, PIX **ppixd2)
pixCropToMatch()
Definition: pix5.c:1155
Definition: pix.h:134
Definition: pix.h:719
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:192
l_ok pixZero(PIX *pix, l_int32 *pempty)
pixZero()
Definition: pix3.c:1701
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:499
#define PIX_SRC
Definition: pix.h:327
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
l_ok pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame)
pixEqual()
Definition: compare.c:150
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:740
PIX * pixResizeToMatch(PIX *pixs, PIX *pixt, l_int32 w, l_int32 h)
pixResizeToMatch()
Definition: pix5.c:1252
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:718
l_ok pixFindAreaFraction(PIX *pixs, l_int32 *tab, l_float32 *pfract)
pixFindAreaFraction()
Definition: pix5.c:478
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:555
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:2659
l_ok pixTestClipToForeground(PIX *pixs, l_int32 *pcanclip)
pixTestClipToForeground()
Definition: pix5.c:1760
PIX * pixRankRowTransform(PIX *pixs)
pixRankRowTransform()
Definition: pix5.c:3009
PIX * pixErodeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrick()
Definition: morph.c:748
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
l_ok pixaAddBox(PIXA *pixa, BOX *box, l_int32 copyflag)
pixaAddBox()
Definition: pixabasic.c:547
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:310
Definition: pix.h:480
l_ok pixConformsToRectangle(PIX *pixs, BOX *box, l_int32 dist, l_int32 *pconforms)
pixConformsToRectangle()
Definition: pix5.c:887
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2737
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:631
Definition: pix.h:517