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
113static 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 *-------------------------------------------------------------*/
139l_ok
141 NUMA **pnaw,
142 NUMA **pnah)
143{
144l_int32 i, n, w, h;
145PIX *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
189l_ok
191 l_int32 *tab,
192 l_float32 *pfract)
193{
194l_int32 *tab8;
195l_int32 nfg, nbound;
196PIX *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
240NUMA *
242{
243l_int32 i, n;
244l_int32 *tab;
245l_float32 fract;
246NUMA *na;
247PIX *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
290l_ok
292 l_int32 *tab,
293 l_float32 *pfract)
294{
295l_int32 *tab8;
296l_int32 nfg, nbound;
297PIX *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
344NUMA *
346{
347l_int32 i, n;
348l_int32 *tab;
349l_float32 ratio;
350NUMA *na;
351PIX *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
394l_ok
396 l_int32 *tab,
397 l_float32 *pratio)
398{
399l_int32 *tab8;
400l_int32 w, h, nbound;
401PIX *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
440NUMA *
442{
443l_int32 i, n;
444l_int32 *tab;
445l_float32 fract;
446NUMA *na;
447PIX *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
483l_ok
485 l_int32 *tab,
486 l_float32 *pfract)
487{
488l_int32 w, h, sum;
489l_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
531NUMA *
533 PIX *pixm,
534 l_int32 debug)
535{
536l_int32 i, n, full;
537l_int32 *tab;
538l_float32 fract;
539BOX *box;
540NUMA *na;
541PIX *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
610l_ok
612 BOX *box,
613 PIX *pixm,
614 l_int32 *tab,
615 l_float32 *pfract)
616{
617l_int32 x, y, w, h, sum, masksum;
618l_int32 *tab8;
619PIX *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
669NUMA *
671{
672l_int32 i, n, w, h;
673NUMA *na;
674PIX *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
705NUMA *
707{
708l_int32 i, n, w, h;
709NUMA *na;
710PIX *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
745l_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{
754l_int32 *tab8;
755l_int32 w, h, nintersect, nunion;
756PIX *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
812BOXA *
814 l_int32 dist,
815 l_int32 minw,
816 l_int32 minh)
817{
818l_int32 w, h, i, n, conforms;
819BOX *box;
820BOXA *boxa, *boxad;
821PIX *pix;
822PIXA *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
892l_ok
894 BOX *box,
895 l_int32 dist,
896 l_int32 *pconforms)
897{
898l_int32 w, h, empty;
899PIX *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 *-----------------------------------------------------------------------*/
959PIXA *
961 BOXA *boxa)
962{
963l_int32 i, n;
964BOX *box, *boxc;
965PIX *pix;
966PIXA *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
1025PIX *
1027 BOX *box,
1028 BOX **pboxc)
1029{
1030l_int32 w, h, d, bx, by, bw, bh;
1031BOX *boxc;
1032PIX *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
1088PIX *
1090 BOX *box,
1091 l_int32 maxbord,
1092 BOX **pboxn)
1093{
1094l_int32 w, h, bx, by, bw, bh, bord;
1095BOX *box1;
1096PIX *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
1161PIX *
1163 PIX *pixm,
1164 l_int32 x,
1165 l_int32 y,
1166 l_uint32 outval)
1167{
1168l_int32 wm, hm, index, rval, gval, bval;
1169l_uint32 pixel;
1170BOX *box;
1171PIX *pixmi, *pixd;
1172PIXCMAP *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
1223l_ok
1225 PIX *pixs2,
1226 PIX **ppixd1,
1227 PIX **ppixd2)
1228{
1229l_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
1266PIX *
1268 l_int32 w,
1269 l_int32 h)
1270{
1271l_int32 ws, hs, wd, hd, d;
1272PIX *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
1320PIX *
1322 PIX *pixt,
1323 l_int32 w,
1324 l_int32 h)
1325{
1326l_int32 i, j, ws, hs, d;
1327PIX *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 *---------------------------------------------------------------------*/
1389PIX *
1390pixSelectComponentBySize(PIX *pixs,
1391 l_int32 rankorder,
1392 l_int32 type,
1393 l_int32 connectivity,
1394 BOX **pbox)
1395{
1396l_int32 n, empty, sorttype, index;
1397BOXA *boxa1;
1398NUMA *naindex;
1399PIX *pixd;
1400PIXA *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
1462PIX *
1463pixFilterComponentBySize(PIX *pixs,
1464 l_int32 rankorder,
1465 l_int32 type,
1466 l_int32 connectivity,
1467 BOX **pbox)
1468{
1469l_int32 x, y, w, h;
1470BOX *box;
1471PIX *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 *---------------------------------------------------------------------*/
1531PIX *
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
1588PIX *
1590 l_int32 h,
1591 l_float32 hf1,
1592 l_float32 hf2,
1593 l_float32 vf1,
1594 l_float32 vf2)
1595{
1596l_int32 h1, h2, v1, v2;
1597PIX *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 *---------------------------------------------------------------------*/
1654PIX *
1656 l_int32 maxiters)
1657{
1658l_int32 empty, same, niters;
1659BOXA *boxa;
1660PIX *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 *---------------------------------------------------------------------*/
1727l_ok
1729 PIX *pix2,
1730 l_float32 *pfract)
1731{
1732l_int32 w1, h1, w2, h2, empty, count1, count3;
1733PIX *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 *---------------------------------------------------------------------*/
1783l_ok
1785 PIX **ppixd,
1786 BOX **pbox)
1787{
1788l_int32 w, h, wpl, nfullwords, extra, i, j;
1789l_int32 minx, miny, maxx, maxy;
1790l_uint32 result, mask;
1791l_uint32 *data, *line;
1792BOX *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
1843minx_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
1852maxx_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
1883l_ok
1885 l_int32 *pcanclip)
1886{
1887l_int32 i, j, w, h, wpl, found;
1888l_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
1955l_ok
1957 BOX *boxs,
1958 PIX **ppixd,
1959 BOX **pboxd)
1960{
1961l_int32 w, h, bx, by, bw, bh, cbw, cbh, left, right, top, bottom;
1962BOX *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
2021l_ok
2023 BOX *box,
2024 l_int32 scanflag,
2025 l_int32 *ploc)
2026{
2027l_int32 bx, by, bw, bh, x, xstart, xend, y, ystart, yend, wpl;
2028l_uint32 *data, *line;
2029BOX *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
2137l_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{
2147l_int32 w, h, bx, by, bw, bh, cbw, cbh, left, right, top, bottom;
2148l_int32 lfound, rfound, tfound, bfound, change;
2149BOX *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
2267l_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{
2277l_int32 bx, by, bw, bh, foundmin, loc, sum, wpl;
2278l_int32 x, xstart, xend, y, ystart, yend;
2279l_uint32 *data, *line;
2280BOX *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 *---------------------------------------------------------------------*/
2448NUMA *
2450 l_int32 x1,
2451 l_int32 y1,
2452 l_int32 x2,
2453 l_int32 y2,
2454 l_int32 factor)
2455{
2456l_int32 i, w, h, d, xmin, ymin, xmax, ymax, npts, direction;
2457l_uint32 val;
2458l_float32 x, y;
2459l_float64 slope;
2460NUMA *na;
2461PTA *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
2568l_float32
2570 l_int32 x1,
2571 l_int32 y1,
2572 l_int32 x2,
2573 l_int32 y2,
2574 l_int32 factor)
2575{
2576l_int32 i, j, w, h, d, direction, count, wpl;
2577l_uint32 *data, *line;
2578l_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
2667NUMA *
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{
2676l_int32 i, j, w, h, d, start, end;
2677l_float32 ave;
2678NUMA *nad;
2679PIX *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
2782NUMA *
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{
2792l_int32 i, j, w, h, d, start, end, nr;
2793NUMA *naline, *nad;
2794PIX *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 *---------------------------------------------------------------------*/
2891l_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{
2900l_int32 i, j, w, h, cmin, cmax, maxloc, n, x, y;
2901l_uint32 val;
2902l_float32 norm, rootvar;
2903l_float32 *array;
2904l_float64 sum1, sum2, ave, var;
2905NUMA *na1, *nad;
2906PTA *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 *---------------------------------------------------------------------*/
3009l_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{
3022l_int32 i, j, w, h, d, x, y, n, dir, found, minval, maxval, negloc, posloc;
3023l_uint32 val;
3024l_float32 sum;
3025NUMA *namin, *namax;
3026PTA *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 *---------------------------------------------------------------------*/
3132PIX *
3134{
3135l_int32 i, j, k, m, w, h, wpl, val;
3136l_int32 histo[256];
3137l_uint32 *datas, *datad, *lines, *lined;
3138PIX *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
3185PIX *
3187{
3188l_int32 i, j, k, m, w, h, val;
3189l_int32 histo[256];
3190void **lines8, **lined8;
3191PIX *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
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
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
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
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 * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1991
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
PIX * pixMaskBoxa(PIX *pixd, PIX *pixs, BOXA *boxa, l_int32 op)
pixMaskBoxa()
Definition: boxfunc3.c:151
l_ok pixcmapGetNearestIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetNearestIndex()
Definition: colormap.c:1353
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
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 * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:151
BOXA * pixConnCompBB(PIX *pixs, l_int32 connectivity)
pixConnCompBB()
Definition: conncomp.c:310
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
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:892
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
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:993
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
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1949
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 * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition: pix1.c:816
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2411
l_ok pixZero(PIX *pix, l_int32 *pempty)
pixZero()
Definition: pix3.c:1815
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
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1688
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
PIX * pixClipRectangleWithBorder(PIX *pixs, BOX *box, l_int32 maxbord, BOX **pboxn)
pixClipRectangleWithBorder()
Definition: pix5.c:1089
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
l_ok pixFindPerimToAreaRatio(PIX *pixs, l_int32 *tab, l_float32 *pfract)
pixFindPerimToAreaRatio()
Definition: pix5.c:291
NUMA * pixaFindWidthHeightRatio(PIXA *pixa)
pixaFindWidthHeightRatio()
Definition: pix5.c:670
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
PIX * pixClipMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_uint32 outval)
pixClipMasked()
Definition: pix5.c:1162
NUMA * pixaFindPerimToAreaRatio(PIXA *pixa)
pixaFindPerimToAreaRatio()
Definition: pix5.c:241
PIX * pixRankColumnTransform(PIX *pixs)
pixRankColumnTransform()
Definition: pix5.c:3186
l_ok pixFindPerimSizeRatio(PIX *pixs, l_int32 *tab, l_float32 *pratio)
pixFindPerimSizeRatio()
Definition: pix5.c:395
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
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 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
NUMA * pixaFindAreaFraction(PIXA *pixa)
pixaFindAreaFraction()
Definition: pix5.c:441
PIXA * pixClipRectangles(PIX *pixs, BOXA *boxa)
pixClipRectangles()
Definition: pix5.c:960
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
PIX * pixResizeToMatch(PIX *pixs, PIX *pixt, l_int32 w, l_int32 h)
pixResizeToMatch()
Definition: pix5.c:1321
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
l_ok pixTestClipToForeground(PIX *pixs, l_int32 *pcanclip)
pixTestClipToForeground()
Definition: pix5.c:1884
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
PIX * pixMakeCoveringOfRectangles(PIX *pixs, l_int32 maxiters)
pixMakeCoveringOfRectangles()
Definition: pix5.c:1655
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
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 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
BOXA * pixFindRectangleComps(PIX *pixs, l_int32 dist, l_int32 minw, l_int32 minh)
pixFindRectangleComps()
Definition: pix5.c:813
PIX * pixCropToSize(PIX *pixs, l_int32 w, l_int32 h)
pixCropToSize()
Definition: pix5.c:1267
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
NUMA * pixaFindAreaFractionMasked(PIXA *pixa, PIX *pixm, l_int32 debug)
pixaFindAreaFractionMasked()
Definition: pix5.c:532
PIX * pixRankRowTransform(PIX *pixs)
pixRankRowTransform()
Definition: pix5.c:3133
l_ok pixConformsToRectangle(PIX *pixs, BOX *box, l_int32 dist, l_int32 *pconforms)
pixConformsToRectangle()
Definition: pix5.c:893
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
PIX * pixMakeSymmetricMask(l_int32 w, l_int32 h, l_float32 hf, l_float32 vf, l_int32 type)
pixSelectComponentBySize()
Definition: pix5.c:1532
NUMA * pixaFindPerimSizeRatio(PIXA *pixa)
pixaFindPerimSizeRatio()
Definition: pix5.c:345
NUMA * pixaFindWidthHeightProduct(PIXA *pixa)
pixaFindWidthHeightProduct()
Definition: pix5.c:706
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
#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
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
l_ok pixaIsFull(PIXA *pixa, l_int32 *pfullpa, l_int32 *pfullba)
pixaIsFull()
Definition: pixabasic.c:1057
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 * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
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
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