Leptonica 1.82.0
Image processing and image analysis suite
boxfunc1.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
82#ifdef HAVE_CONFIG_H
83#include <config_auto.h>
84#endif /* HAVE_CONFIG_H */
85
86#include "allheaders.h"
87
88static l_int32 boxHasOverlapInXorY(l_int32 c1, l_int32 s1, l_int32 c2,
89 l_int32 s2);
90static l_int32 boxGetDistanceInXorY(l_int32 c1, l_int32 s1, l_int32 c2,
91 l_int32 s2);
92
93
94/*---------------------------------------------------------------------*
95 * Box geometry *
96 *---------------------------------------------------------------------*/
105l_ok
107 BOX *box2,
108 l_int32 *presult)
109{
110l_int32 x1, y1, w1, h1, x2, y2, w2, h2, valid1, valid2;
111
112 PROCNAME("boxContains");
113
114 if (!presult)
115 return ERROR_INT("&result not defined", procName, 1);
116 *presult = 0;
117 if (!box1 || !box2)
118 return ERROR_INT("boxes not both defined", procName, 1);
119 boxIsValid(box1, &valid1);
120 boxIsValid(box2, &valid2);
121 if (!valid1 || !valid2)
122 return ERROR_INT("boxes not both valid", procName, 1);
123
124 boxGetGeometry(box1, &x1, &y1, &w1, &h1);
125 boxGetGeometry(box2, &x2, &y2, &w2, &h2);
126 if (x1 <= x2 && y1 <= y2 && (x1 + w1 >= x2 + w2) && (y1 + h1 >= y2 + h2))
127 *presult = 1;
128 return 0;
129}
130
131
140l_ok
142 BOX *box2,
143 l_int32 *presult)
144{
145l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, valid1, valid2;
146
147 PROCNAME("boxIntersects");
148
149 if (!presult)
150 return ERROR_INT("&result not defined", procName, 1);
151 *presult = 0;
152 if (!box1 || !box2)
153 return ERROR_INT("boxes not both defined", procName, 1);
154 boxIsValid(box1, &valid1);
155 boxIsValid(box2, &valid2);
156 if (!valid1 || !valid2)
157 return ERROR_INT("boxes not both valid", procName, 1);
158
159 boxGetGeometry(box1, &l1, &t1, &w1, &h1);
160 boxGetGeometry(box2, &l2, &t2, &w2, &h2);
161 r1 = l1 + w1 - 1;
162 r2 = l2 + w2 - 1;
163 b1 = t1 + h1 - 1;
164 b2 = t2 + h2 - 1;
165 if (b2 < t1 || b1 < t2 || r1 < l2 || r2 < l1)
166 *presult = 0;
167 else
168 *presult = 1;
169 return 0;
170}
171
172
187BOXA *
189 BOX *box)
190{
191l_int32 i, n, val, valid;
192BOX *box1;
193BOXA *boxad;
194
195 PROCNAME("boxaContainedInBox");
196
197 if (!boxas)
198 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
199 if (!box)
200 return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
201 n = boxaGetCount(boxas);
202 boxIsValid(box, &valid);
203 if (n == 0 || !valid)
204 return boxaCreate(1); /* empty */
205
206 boxad = boxaCreate(0);
207 for (i = 0; i < n; i++) {
208 if ((box1 = boxaGetValidBox(boxas, i, L_CLONE)) == NULL)
209 continue;
210 boxContains(box, box1, &val);
211 if (val == 1)
212 boxaAddBox(boxad, box1, L_COPY);
213 boxDestroy(&box1); /* destroy the clone */
214 }
215
216 return boxad;
217}
218
219
233l_ok
235 BOX *box,
236 l_int32 *pcount)
237{
238l_int32 i, n, val, valid;
239BOX *box1;
240
241 PROCNAME("boxaContainedInBoxCount");
242
243 if (!pcount)
244 return ERROR_INT("&count not defined", procName, 1);
245 *pcount = 0;
246 if (!boxa)
247 return ERROR_INT("boxa not defined", procName, 1);
248 if (!box)
249 return ERROR_INT("box not defined", procName, 1);
250 n = boxaGetCount(boxa);
251 boxIsValid(box, &valid);
252 if (n == 0 || !valid)
253 return 0;
254
255 for (i = 0; i < n; i++) {
256 if ((box1 = boxaGetValidBox(boxa, i, L_CLONE)) == NULL)
257 continue;
258 boxContains(box, box1, &val);
259 if (val == 1)
260 (*pcount)++;
261 boxDestroy(&box1);
262 }
263 return 0;
264}
265
266
275l_ok
277 BOXA *boxa2,
278 l_int32 *pcontained)
279{
280l_int32 i, j, n1, n2, cont, result;
281BOX *box1, *box2;
282
283 PROCNAME("boxaContainedInBoxa");
284
285 if (!pcontained)
286 return ERROR_INT("&contained not defined", procName, 1);
287 *pcontained = 0;
288 if (!boxa1 || !boxa2)
289 return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
290
291 n1 = boxaGetCount(boxa1);
292 n2 = boxaGetCount(boxa2);
293 for (i = 0; i < n2; i++) {
294 if ((box2 = boxaGetValidBox(boxa2, i, L_CLONE)) == NULL)
295 continue;
296 cont = 0;
297 for (j = 0; j < n1; j++) {
298 if ((box1 = boxaGetValidBox(boxa1, j, L_CLONE)) == NULL)
299 continue;
300 boxContains(box1, box2, &result);
301 boxDestroy(&box1);
302 if (result) {
303 cont = 1;
304 break;
305 }
306 }
307 boxDestroy(&box2);
308 if (!cont) return 0;
309 }
310
311 *pcontained = 1;
312 return 0;
313}
314
315
330BOXA *
332 BOX *box)
333{
334l_int32 i, n, val, valid;
335BOX *box1;
336BOXA *boxad;
337
338 PROCNAME("boxaIntersectsBox");
339
340 if (!boxas)
341 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
342 if (!box)
343 return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
344 n = boxaGetCount(boxas);
345 boxIsValid(box, &valid);
346 if (n == 0 || !valid)
347 return boxaCreate(1); /* empty */
348
349 boxad = boxaCreate(0);
350 for (i = 0; i < n; i++) {
351 if ((box1 = boxaGetValidBox(boxas, i, L_CLONE)) == NULL)
352 continue;
353 boxIntersects(box, box1, &val);
354 if (val == 1)
355 boxaAddBox(boxad, box1, L_COPY);
356 boxDestroy(&box1); /* destroy the clone */
357 }
358
359 return boxad;
360}
361
362
371l_ok
373 BOX *box,
374 l_int32 *pcount)
375{
376l_int32 i, n, val, valid;
377BOX *box1;
378
379 PROCNAME("boxaIntersectsBoxCount");
380
381 if (!pcount)
382 return ERROR_INT("&count not defined", procName, 1);
383 *pcount = 0;
384 if (!boxa)
385 return ERROR_INT("boxa not defined", procName, 1);
386 if (!box)
387 return ERROR_INT("box not defined", procName, 1);
388 n = boxaGetCount(boxa);
389 boxIsValid(box, &valid);
390 if (n == 0 || !valid)
391 return 0;
392
393 for (i = 0; i < n; i++) {
394 if ((box1 = boxaGetValidBox(boxa, i, L_CLONE)) == NULL)
395 continue;
396 boxIntersects(box, box1, &val);
397 if (val == 1)
398 (*pcount)++;
399 boxDestroy(&box1);
400 }
401 return 0;
402}
403
404
418BOXA *
420 BOX *box)
421{
422l_int32 i, n, valid;
423BOX *box1, *boxo;
424BOXA *boxad;
425
426 PROCNAME("boxaClipToBox");
427
428 if (!boxas)
429 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
430 if (!box)
431 return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
432 n = boxaGetCount(boxas);
433 boxIsValid(box, &valid);
434 if (n == 0 || !valid)
435 return boxaCreate(1); /* empty */
436
437 boxad = boxaCreate(0);
438 for (i = 0; i < n; i++) {
439 if ((box1 = boxaGetValidBox(boxas, i, L_CLONE)) == NULL)
440 continue;
441 if ((boxo = boxOverlapRegion(box, box1)) != NULL)
442 boxaAddBox(boxad, boxo, L_INSERT);
443 boxDestroy(&box1);
444 }
445
446 return boxad;
447}
448
449
477BOXA *
479 PIXA *pixadb)
480{
481l_int32 i, j, w, h, n1, n2, overlap, niters;
482BOX *box1, *box2, *box3;
483BOXA *boxa1, *boxa2;
484PIX *pix1;
485
486 PROCNAME("boxaCombineOverlaps");
487
488 if (!boxas)
489 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
490
491 if (pixadb) boxaGetExtent(boxas, &w, &h, NULL);
492
493 boxa1 = boxaCopy(boxas, L_COPY);
494 n1 = boxaGetCount(boxa1);
495 niters = 0;
496 while (1) { /* loop until no change from previous iteration */
497 niters++;
498 if (pixadb) {
499 pix1 = pixCreate(w + 5, h + 5, 32);
500 pixSetAll(pix1);
501 pixRenderBoxaArb(pix1, boxa1, 2, 255, 0, 0);
502 pixaAddPix(pixadb, pix1, L_COPY);
503 }
504
505 /* Combine overlaps for this iteration */
506 for (i = 0; i < n1; i++) {
507 if ((box1 = boxaGetValidBox(boxa1, i, L_COPY)) == NULL)
508 continue;
509 for (j = i + 1; j < n1; j++) {
510 if ((box2 = boxaGetValidBox(boxa1, j, L_COPY)) == NULL)
511 continue;
512 boxIntersects(box1, box2, &overlap);
513 if (overlap) {
514 box3 = boxBoundingRegion(box1, box2);
515 boxaReplaceBox(boxa1, i, box3);
516 boxaReplaceBox(boxa1, j, boxCreate(0, 0, 0, 0));
517 boxDestroy(&box1);
518 box1 = boxCopy(box3);
519 }
520 boxDestroy(&box2);
521 }
522 boxDestroy(&box1);
523 }
524 boxa2 = boxaSaveValid(boxa1, L_COPY);
525 n2 = boxaGetCount(boxa2);
526 boxaDestroy(&boxa1);
527 boxa1 = boxa2;
528 if (n1 == n2) {
529 if (pixadb) pixDestroy(&pix1);
530 break;
531 }
532 n1 = n2;
533 if (pixadb) {
534 pixRenderBoxaArb(pix1, boxa1, 2, 0, 255, 0);
535 pixaAddPix(pixadb, pix1, L_INSERT);
536 }
537 }
538
539 if (pixadb)
540 L_INFO("number of iterations: %d\n", procName, niters);
541 return boxa1;
542}
543
544
571l_ok
573 BOXA *boxas2,
574 BOXA **pboxad1,
575 BOXA **pboxad2,
576 PIXA *pixadb)
577{
578l_int32 i, j, w, h, w2, h2, n1, n2, n1i, n2i, niters;
579l_int32 overlap, bigger, area1, area2;
580BOX *box1, *box2, *box3;
581BOXA *boxa1, *boxa2, *boxac1, *boxac2;
582PIX *pix1;
583
584 PROCNAME("boxaCombineOverlapsInPair");
585
586 if (pboxad1) *pboxad1 = NULL;
587 if (pboxad2) *pboxad2 = NULL;
588 if (!boxas1 || !boxas2)
589 return ERROR_INT("boxas1 and boxas2 not both defined", procName, 1);
590 if (!pboxad1 || !pboxad2)
591 return ERROR_INT("&boxad1 and &boxad2 not both defined", procName, 1);
592
593 if (pixadb) {
594 boxaGetExtent(boxas1, &w, &h, NULL);
595 boxaGetExtent(boxas2, &w2, &h2, NULL);
596 w = L_MAX(w, w2);
597 h = L_MAX(h, w2);
598 }
599
600 /* Let the boxa with the largest area have first crack at the other */
601 boxaGetArea(boxas1, &area1);
602 boxaGetArea(boxas2, &area2);
603 if (area1 >= area2) {
604 boxac1 = boxaCopy(boxas1, L_COPY);
605 boxac2 = boxaCopy(boxas2, L_COPY);
606 } else {
607 boxac1 = boxaCopy(boxas2, L_COPY);
608 boxac2 = boxaCopy(boxas1, L_COPY);
609 }
610
611 n1i = boxaGetCount(boxac1);
612 n2i = boxaGetCount(boxac2);
613 niters = 0;
614 while (1) {
615 niters++;
616 if (pixadb) {
617 pix1 = pixCreate(w + 5, h + 5, 32);
618 pixSetAll(pix1);
619 pixRenderBoxaArb(pix1, boxac1, 2, 255, 0, 0);
620 pixRenderBoxaArb(pix1, boxac2, 2, 0, 255, 0);
621 pixaAddPix(pixadb, pix1, L_INSERT);
622 }
623
624 /* First combine boxes in each set */
625 boxa1 = boxaCombineOverlaps(boxac1, NULL);
626 boxa2 = boxaCombineOverlaps(boxac2, NULL);
627
628 /* Now combine boxes between sets */
629 n1 = boxaGetCount(boxa1);
630 n2 = boxaGetCount(boxa2);
631 for (i = 0; i < n1; i++) { /* 1 eats 2 */
632 if ((box1 = boxaGetValidBox(boxa1, i, L_COPY)) == NULL)
633 continue;
634 for (j = 0; j < n2; j++) {
635 if ((box2 = boxaGetValidBox(boxa2, j, L_COPY)) == NULL)
636 continue;
637 boxIntersects(box1, box2, &overlap);
638 boxCompareSize(box1, box2, L_SORT_BY_AREA, &bigger);
639 if (overlap && (bigger == 1)) {
640 box3 = boxBoundingRegion(box1, box2);
641 boxaReplaceBox(boxa1, i, box3);
642 boxaReplaceBox(boxa2, j, boxCreate(0, 0, 0, 0));
643 boxDestroy(&box1);
644 box1 = boxCopy(box3);
645 }
646 boxDestroy(&box2);
647 }
648 boxDestroy(&box1);
649 }
650 for (i = 0; i < n2; i++) { /* 2 eats 1 */
651 if ((box2 = boxaGetValidBox(boxa2, i, L_COPY)) == NULL)
652 continue;
653 for (j = 0; j < n1; j++) {
654 if ((box1 = boxaGetValidBox(boxa1, j, L_COPY)) == NULL)
655 continue;
656 boxIntersects(box1, box2, &overlap);
657 boxCompareSize(box2, box1, L_SORT_BY_AREA, &bigger);
658 if (overlap && (bigger == 1)) {
659 box3 = boxBoundingRegion(box1, box2);
660 boxaReplaceBox(boxa2, i, box3);
661 boxaReplaceBox(boxa1, j, boxCreate(0, 0, 0, 0));
662 boxDestroy(&box2);
663 box2 = boxCopy(box3);
664 }
665 boxDestroy(&box1);
666 }
667 boxDestroy(&box2);
668 }
669 boxaDestroy(&boxac1);
670 boxaDestroy(&boxac2);
671 boxac1 = boxaSaveValid(boxa1, L_COPY); /* remove invalid boxes */
672 boxac2 = boxaSaveValid(boxa2, L_COPY);
673 boxaDestroy(&boxa1);
674 boxaDestroy(&boxa2);
675 n1 = boxaGetCount(boxac1);
676 n2 = boxaGetCount(boxac2);
677 if (n1 == n1i && n2 == n2i) break;
678 n1i = n1;
679 n2i = n2;
680 if (pixadb) {
681 pix1 = pixCreate(w + 5, h + 5, 32);
682 pixSetAll(pix1);
683 pixRenderBoxaArb(pix1, boxac1, 2, 255, 0, 0);
684 pixRenderBoxaArb(pix1, boxac2, 2, 0, 255, 0);
685 pixaAddPix(pixadb, pix1, L_INSERT);
686 }
687 }
688
689 if (pixadb)
690 L_INFO("number of iterations: %d\n", procName, niters);
691 *pboxad1 = boxac1;
692 *pboxad2 = boxac2;
693 return 0;
694}
695
696
709BOX *
711 BOX *box2)
712{
713l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, ld, td, rd, bd;
714l_int32 valid1, valid2;
715
716 PROCNAME("boxOverlapRegion");
717
718 if (!box1 || !box2)
719 return (BOX *)ERROR_PTR("boxes not both defined", procName, NULL);
720 boxIsValid(box1, &valid1);
721 boxIsValid(box2, &valid2);
722 if (!valid1 || !valid2) {
723 L_WARNING("at least one box is invalid\n", procName);
724 return NULL;
725 }
726
727 boxGetGeometry(box1, &l1, &t1, &w1, &h1);
728 boxGetGeometry(box2, &l2, &t2, &w2, &h2);
729 r1 = l1 + w1 - 1;
730 r2 = l2 + w2 - 1;
731 b1 = t1 + h1 - 1;
732 b2 = t2 + h2 - 1;
733 if (b2 < t1 || b1 < t2 || r1 < l2 || r2 < l1)
734 return NULL;
735
736 ld = L_MAX(l1, l2);
737 td = L_MAX(t1, t2);
738 rd = L_MIN(r1, r2);
739 bd = L_MIN(b1, b2);
740 return boxCreate(ld, td, rd - ld + 1, bd - td + 1);
741}
742
743
759BOX *
761 BOX *box2)
762{
763l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, ld, td, rd, bd;
764l_int32 valid1, valid2;
765
766 PROCNAME("boxBoundingRegion");
767
768 if (!box1 || !box2)
769 return (BOX *)ERROR_PTR("boxes not both defined", procName, NULL);
770 boxIsValid(box1, &valid1);
771 boxIsValid(box2, &valid2);
772 if (!valid1 && !valid2) {
773 L_WARNING("both boxes are invalid\n", procName);
774 return boxCreate(0, 0, 0, 0);
775 }
776 if (valid1 && !valid2)
777 return boxCopy(box1);
778 if (!valid1 && valid2)
779 return boxCopy(box2);
780
781 boxGetGeometry(box1, &l1, &t1, &w1, &h1);
782 boxGetGeometry(box2, &l2, &t2, &w2, &h2);
783 r1 = l1 + w1 - 1;
784 r2 = l2 + w2 - 1;
785 b1 = t1 + h1 - 1;
786 b2 = t2 + h2 - 1;
787 ld = L_MIN(l1, l2);
788 td = L_MIN(t1, t2);
789 rd = L_MAX(r1, r2);
790 bd = L_MAX(b1, b2);
791 return boxCreate(ld, td, rd - ld + 1, bd - td + 1);
792}
793
794
809l_ok
811 BOX *box2,
812 l_float32 *pfract)
813{
814l_int32 w2, h2, w, h, valid1, valid2;
815BOX *boxo;
816
817 PROCNAME("boxOverlapFraction");
818
819 if (!pfract)
820 return ERROR_INT("&fract not defined", procName, 1);
821 *pfract = 0.0;
822 if (!box1 || !box2)
823 return ERROR_INT("boxes not both defined", procName, 1);
824 boxIsValid(box1, &valid1);
825 boxIsValid(box2, &valid2);
826 if (!valid1 || !valid2) {
827 L_WARNING("boxes not both valid\n", procName);
828 return 0;
829 }
830
831 if ((boxo = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */
832 return 0;
833
834 boxGetGeometry(box2, NULL, NULL, &w2, &h2);
835 boxGetGeometry(boxo, NULL, NULL, &w, &h);
836 *pfract = (l_float32)(w * h) / (l_float32)(w2 * h2);
837 boxDestroy(&boxo);
838 return 0;
839}
840
841
849l_ok
851 BOX *box2,
852 l_int32 *parea)
853{
854l_int32 w, h, valid1, valid2;
855BOX *box;
856
857 PROCNAME("boxOverlapArea");
858
859 if (!parea)
860 return ERROR_INT("&area not defined", procName, 1);
861 *parea = 0;
862 if (!box1 || !box2)
863 return ERROR_INT("boxes not both defined", procName, 1);
864 boxIsValid(box1, &valid1);
865 boxIsValid(box2, &valid2);
866 if (!valid1 || !valid2)
867 return ERROR_INT("boxes not both valid", procName, 1);
868
869 if ((box = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */
870 return 0;
871
872 boxGetGeometry(box, NULL, NULL, &w, &h);
873 *parea = w * h;
874 boxDestroy(&box);
875 return 0;
876}
877
878
913BOXA *
915 l_int32 op,
916 l_int32 range,
917 l_float32 min_overlap,
918 l_float32 max_ratio,
919 NUMA **pnamap)
920{
921l_int32 i, j, n, w, h, area1, area2, val;
922l_int32 overlap_area;
923l_float32 overlap_ratio, area_ratio;
924BOX *box1, *box2, *box3;
925BOXA *boxat, *boxad;
926NUMA *namap;
927
928 PROCNAME("boxaHandleOverlaps");
929
930 if (pnamap) *pnamap = NULL;
931 if (!boxas)
932 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
933 if (op != L_COMBINE && op != L_REMOVE_SMALL)
934 return (BOXA *)ERROR_PTR("invalid op", procName, NULL);
935
936 n = boxaGetCount(boxas);
937 if (n == 0)
938 return boxaCreate(1); /* empty */
939 if (range == 0) {
940 L_WARNING("range is 0\n", procName);
941 return boxaCopy(boxas, L_COPY);
942 }
943
944 /* Identify smaller boxes in overlap pairs, and mark to eliminate. */
945 namap = numaMakeConstant(-1, n);
946 for (i = 0; i < n; i++) {
947 if ((box1 = boxaGetValidBox(boxas, i, L_CLONE)) == NULL)
948 continue;
949 boxGetGeometry(box1, NULL, NULL, &w, &h);
950 area1 = w * h;
951 if (area1 == 0) {
952 boxDestroy(&box1);
953 continue;
954 }
955 for (j = i + 1; j < i + 1 + range && j < n; j++) {
956 if ((box2 = boxaGetValidBox(boxas, j, L_CLONE)) == NULL)
957 continue;
958 boxOverlapArea(box1, box2, &overlap_area);
959 if (overlap_area > 0) {
960 boxGetGeometry(box2, NULL, NULL, &w, &h);
961 area2 = w * h;
962 if (area2 == 0) {
963 /* do nothing */
964 } else if (area1 >= area2) {
965 overlap_ratio = (l_float32)overlap_area / (l_float32)area2;
966 area_ratio = (l_float32)area2 / (l_float32)area1;
967 if (overlap_ratio >= min_overlap &&
968 area_ratio <= max_ratio) {
969 numaSetValue(namap, j, i);
970 }
971 } else {
972 overlap_ratio = (l_float32)overlap_area / (l_float32)area1;
973 area_ratio = (l_float32)area1 / (l_float32)area2;
974 if (overlap_ratio >= min_overlap &&
975 area_ratio <= max_ratio) {
976 numaSetValue(namap, i, j);
977 }
978 }
979 }
980 boxDestroy(&box2);
981 }
982 boxDestroy(&box1);
983 }
984
985 boxat = boxaCopy(boxas, L_COPY);
986 if (op == L_COMBINE) {
987 /* Resize the larger of the pair to the bounding region */
988 for (i = 0; i < n; i++) {
989 numaGetIValue(namap, i, &val);
990 if (val >= 0) {
991 box1 = boxaGetBox(boxas, i, L_CLONE); /* smaller */
992 box2 = boxaGetBox(boxas, val, L_CLONE); /* larger */
993 box3 = boxBoundingRegion(box1, box2);
994 boxaReplaceBox(boxat, val, box3);
995 boxDestroy(&box1);
996 boxDestroy(&box2);
997 }
998 }
999 }
1000
1001 /* Remove the smaller of the pairs */
1002 boxad = boxaCreate(n);
1003 for (i = 0; i < n; i++) {
1004 numaGetIValue(namap, i, &val);
1005 if (val == -1) {
1006 box1 = boxaGetBox(boxat, i, L_COPY);
1007 boxaAddBox(boxad, box1, L_INSERT);
1008 }
1009 }
1010 boxaDestroy(&boxat);
1011 if (pnamap)
1012 *pnamap = namap;
1013 else
1014 numaDestroy(&namap);
1015 return boxad;
1016}
1017
1018
1043l_ok
1045 BOX *box2,
1046 l_int32 *ph_ovl,
1047 l_int32 *pv_ovl)
1048{
1049l_int32 l1, t1, w1, h1, r1, b1, l2, t2, w2, h2, r2, b2, valid1, valid2;
1050
1051 PROCNAME("boxOverlapDistance");
1052
1053 if (!ph_ovl && !pv_ovl)
1054 return ERROR_INT("nothing to do", procName, 1);
1055 if (ph_ovl) *ph_ovl = 0;
1056 if (pv_ovl) *pv_ovl = 0;
1057 if (!box1 || !box2)
1058 return ERROR_INT("boxes not both defined", procName, 1);
1059 boxIsValid(box1, &valid1);
1060 boxIsValid(box2, &valid2);
1061 if (!valid1 || !valid2)
1062 return ERROR_INT("boxes not both valid", procName, 1);
1063
1064 if (ph_ovl) {
1065 boxGetGeometry(box1, &l1, NULL, &w1, NULL);
1066 boxGetGeometry(box2, &l2, NULL, &w2, NULL);
1067 r1 = l1 + w1; /* 1 pixel to the right of box 1 */
1068 r2 = l2 + w2;
1069 if (l2 >= l1)
1070 *ph_ovl = r1 - l2;
1071 else
1072 *ph_ovl = r2 - l1;
1073 }
1074 if (pv_ovl) {
1075 boxGetGeometry(box1, NULL, &t1, NULL, &h1);
1076 boxGetGeometry(box2, NULL, &t2, NULL, &h2);
1077 b1 = t1 + h1; /* 1 pixel below box 1 */
1078 b2 = t2 + h2;
1079 if (t2 >= t1)
1080 *pv_ovl = b1 - t2;
1081 else
1082 *pv_ovl = b2 - t1;
1083 }
1084 return 0;
1085}
1086
1087
1116l_ok
1118 BOX *box2,
1119 l_int32 *ph_sep,
1120 l_int32 *pv_sep)
1121{
1122l_int32 h_ovl, v_ovl, valid1, valid2;
1123
1124 PROCNAME("boxSeparationDistance");
1125
1126 if (ph_sep) *ph_sep = 0;
1127 if (pv_sep) *pv_sep = 0;
1128 if (!ph_sep || !pv_sep)
1129 return ERROR_INT("&h_sep and &v_sep not both defined", procName, 1);
1130 if (!box1 || !box2)
1131 return ERROR_INT("boxes not both defined", procName, 1);
1132 boxIsValid(box1, &valid1);
1133 boxIsValid(box2, &valid2);
1134 if (!valid1 || !valid2)
1135 return ERROR_INT("boxes not both valid", procName, 1);
1136
1137 boxOverlapDistance(box1, box2, &h_ovl, &v_ovl);
1138 if (h_ovl <= 0)
1139 *ph_sep = -h_ovl + 1;
1140 if (v_ovl <= 0)
1141 *pv_sep = -v_ovl + 1;
1142 return 0;
1143}
1144
1145
1161l_ok
1163 BOX *box2,
1164 l_int32 type,
1165 l_int32 *prel)
1166{
1167l_int32 w1, h1, w2, h2, size1, size2, valid1, valid2;
1168
1169 PROCNAME("boxCompareSize");
1170
1171 if (!prel)
1172 return ERROR_INT("&rel not defined", procName, 1);
1173 *prel = 0;
1174 if (!box1 || !box2)
1175 return ERROR_INT("boxes not both defined", procName, 1);
1176 boxIsValid(box1, &valid1);
1177 boxIsValid(box2, &valid2);
1178 if (!valid1 || !valid2)
1179 return ERROR_INT("boxes not both valid", procName, 1);
1180 if (type != L_SORT_BY_WIDTH && type != L_SORT_BY_HEIGHT &&
1181 type != L_SORT_BY_MAX_DIMENSION && type != L_SORT_BY_PERIMETER &&
1182 type != L_SORT_BY_AREA)
1183 return ERROR_INT("invalid compare type", procName, 1);
1184
1185 boxGetGeometry(box1, NULL, NULL, &w1, &h1);
1186 boxGetGeometry(box2, NULL, NULL, &w2, &h2);
1187 if (type == L_SORT_BY_WIDTH) {
1188 *prel = (w1 > w2) ? 1 : ((w1 == w2) ? 0 : -1);
1189 } else if (type == L_SORT_BY_HEIGHT) {
1190 *prel = (h1 > h2) ? 1 : ((h1 == h2) ? 0 : -1);
1191 } else if (type == L_SORT_BY_MAX_DIMENSION) {
1192 size1 = L_MAX(w1, h1);
1193 size2 = L_MAX(w2, h2);
1194 *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1195 } else if (type == L_SORT_BY_PERIMETER) {
1196 size1 = w1 + h1;
1197 size2 = w2 + h2;
1198 *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1199 } else if (type == L_SORT_BY_AREA) {
1200 size1 = w1 * h1;
1201 size2 = w2 * h2;
1202 *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1203 }
1204 return 0;
1205}
1206
1207
1216l_ok
1218 l_float32 x,
1219 l_float32 y,
1220 l_int32 *pcontains)
1221{
1222l_int32 bx, by, bw, bh;
1223
1224 PROCNAME("boxContainsPt");
1225
1226 if (!pcontains)
1227 return ERROR_INT("&contains not defined", procName, 1);
1228 *pcontains = 0;
1229 if (!box)
1230 return ERROR_INT("&box not defined", procName, 1);
1231 boxGetGeometry(box, &bx, &by, &bw, &bh);
1232 if (x >= bx && x < bx + bw && y >= by && y < by + bh)
1233 *pcontains = 1;
1234 return 0;
1235}
1236
1237
1251BOX *
1253 l_int32 x,
1254 l_int32 y)
1255{
1256l_int32 i, n, minindex;
1257l_float32 delx, dely, dist, mindist, cx, cy;
1258BOX *box;
1259
1260 PROCNAME("boxaGetNearestToPt");
1261
1262 if (!boxa)
1263 return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
1264 if ((n = boxaGetCount(boxa)) == 0)
1265 return (BOX *)ERROR_PTR("n = 0", procName, NULL);
1266
1267 mindist = 1000000000.;
1268 minindex = 0;
1269 for (i = 0; i < n; i++) {
1270 if ((box = boxaGetValidBox(boxa, i, L_CLONE)) == NULL)
1271 continue;
1272 boxGetCenter(box, &cx, &cy);
1273 delx = (l_float32)(cx - x);
1274 dely = (l_float32)(cy - y);
1275 dist = delx * delx + dely * dely;
1276 if (dist < mindist) {
1277 minindex = i;
1278 mindist = dist;
1279 }
1280 boxDestroy(&box);
1281 }
1282
1283 return boxaGetBox(boxa, minindex, L_COPY);
1284}
1285
1286
1304BOX *
1306 l_int32 x,
1307 l_int32 y)
1308{
1309l_int32 i, n, minindex;
1310l_float32 dist, mindist, cx, cy;
1311BOX *box;
1312
1313 PROCNAME("boxaGetNearestToLine");
1314
1315 if (!boxa)
1316 return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
1317 if ((n = boxaGetCount(boxa)) == 0)
1318 return (BOX *)ERROR_PTR("n = 0", procName, NULL);
1319 if (y >= 0 && x >= 0)
1320 return (BOX *)ERROR_PTR("either x or y must be < 0", procName, NULL);
1321 if (y < 0 && x < 0)
1322 return (BOX *)ERROR_PTR("either x or y must be >= 0", procName, NULL);
1323
1324 mindist = 1000000000.;
1325 minindex = 0;
1326 for (i = 0; i < n; i++) {
1327 if ((box = boxaGetValidBox(boxa, i, L_CLONE)) == NULL)
1328 continue;
1329 boxGetCenter(box, &cx, &cy);
1330 if (x >= 0)
1331 dist = L_ABS(cx - (l_float32)x);
1332 else /* y >= 0 */
1333 dist = L_ABS(cy - (l_float32)y);
1334 if (dist < mindist) {
1335 minindex = i;
1336 mindist = dist;
1337 }
1338 boxDestroy(&box);
1339 }
1340
1341 return boxaGetBox(boxa, minindex, L_COPY);
1342}
1343
1344
1362l_ok
1364 l_int32 dist_select,
1365 l_int32 range,
1366 NUMAA **pnaaindex,
1367 NUMAA **pnaadist)
1368{
1369l_int32 i, n, index, dist;
1370NUMA *nai, *nad;
1371NUMAA *naai, *naad;
1372
1373 PROCNAME("boxaFindNearestBoxes");
1374
1375 if (pnaaindex) *pnaaindex = NULL;
1376 if (pnaadist) *pnaadist = NULL;
1377 if (!pnaaindex)
1378 return ERROR_INT("&naaindex not defined", procName, 1);
1379 if (!pnaadist)
1380 return ERROR_INT("&naadist not defined", procName, 1);
1381 if (!boxa)
1382 return ERROR_INT("boxa not defined", procName, 1);
1383
1384 n = boxaGetCount(boxa);
1385 naai = numaaCreate(n);
1386 naad = numaaCreate(n);
1387 *pnaaindex = naai;
1388 *pnaadist = naad;
1389 for (i = 0; i < n; i++) {
1390 nai = numaCreate(4);
1391 nad = numaCreate(4);
1392 boxaGetNearestByDirection(boxa, i, L_FROM_LEFT, dist_select,
1393 range, &index, &dist);
1394 numaAddNumber(nai, index);
1395 numaAddNumber(nad, dist);
1396 boxaGetNearestByDirection(boxa, i, L_FROM_RIGHT, dist_select,
1397 range, &index, &dist);
1398 numaAddNumber(nai, index);
1399 numaAddNumber(nad, dist);
1400 boxaGetNearestByDirection(boxa, i, L_FROM_TOP, dist_select,
1401 range, &index, &dist);
1402 numaAddNumber(nai, index);
1403 numaAddNumber(nad, dist);
1404 boxaGetNearestByDirection(boxa, i, L_FROM_BOT, dist_select,
1405 range, &index, &dist);
1406 numaAddNumber(nai, index);
1407 numaAddNumber(nad, dist);
1408 numaaAddNuma(naai, nai, L_INSERT);
1409 numaaAddNuma(naad, nad, L_INSERT);
1410 }
1411 return 0;
1412}
1413
1414
1443l_ok
1445 l_int32 i,
1446 l_int32 dir,
1447 l_int32 dist_select,
1448 l_int32 range,
1449 l_int32 *pindex,
1450 l_int32 *pdist)
1451{
1452l_int32 j, jmin, jmax, n, mindist, dist, index;
1453l_int32 x, y, w, h, bx, by, bw, bh;
1454
1455 PROCNAME("boxaGetNearestByDirection");
1456
1457 if (pindex) *pindex = -1;
1458 if (pdist) *pdist = 100000;
1459 if (!pindex)
1460 return ERROR_INT("&index not defined", procName, 1);
1461 if (!pdist)
1462 return ERROR_INT("&dist not defined", procName, 1);
1463 if (!boxa)
1464 return ERROR_INT("boxa not defined", procName, 1);
1465 if (dir != L_FROM_LEFT && dir != L_FROM_RIGHT &&
1466 dir != L_FROM_TOP && dir != L_FROM_BOT)
1467 return ERROR_INT("invalid dir", procName, 1);
1468 if (dist_select != L_NON_NEGATIVE && dist_select != L_ALL)
1469 return ERROR_INT("invalid dist_select", procName, 1);
1470 n = boxaGetCount(boxa);
1471 if (i < 0 || i >= n)
1472 return ERROR_INT("invalid box index", procName, 1);
1473
1474 jmin = (range <= 0) ? 0 : L_MAX(0, i - range);
1475 jmax = (range <= 0) ? n - 1 : L_MIN(n -1, i + range);
1476 boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
1477 mindist = 100000;
1478 index = -1;
1479 if (dir == L_FROM_LEFT || dir == L_FROM_RIGHT) {
1480 for (j = jmin; j <= jmax; j++) {
1481 if (j == i) continue;
1482 boxaGetBoxGeometry(boxa, j, &bx, &by, &bw, &bh);
1483 if ((bx >= x && dir == L_FROM_LEFT) || /* not to the left */
1484 (x >= bx && dir == L_FROM_RIGHT)) /* not to the right */
1485 continue;
1486 if (boxHasOverlapInXorY(y, h, by, bh) == 1) {
1487 dist = boxGetDistanceInXorY(x, w, bx, bw);
1488 if (dist_select == L_NON_NEGATIVE && dist < 0) continue;
1489 if (dist < mindist) {
1490 mindist = dist;
1491 index = j;
1492 }
1493 }
1494 }
1495 } else if (dir == L_FROM_TOP || dir == L_FROM_BOT) {
1496 for (j = jmin; j <= jmax; j++) {
1497 if (j == i) continue;
1498 boxaGetBoxGeometry(boxa, j, &bx, &by, &bw, &bh);
1499 if ((by >= y && dir == L_FROM_TOP) || /* not above */
1500 (y >= by && dir == L_FROM_BOT)) /* not below */
1501 continue;
1502 if (boxHasOverlapInXorY(x, w, bx, bw) == 1) {
1503 dist = boxGetDistanceInXorY(y, h, by, bh);
1504 if (dist_select == L_NON_NEGATIVE && dist < 0) continue;
1505 if (dist < mindist) {
1506 mindist = dist;
1507 index = j;
1508 }
1509 }
1510 }
1511 }
1512 *pindex = index;
1513 *pdist = mindist;
1514 return 0;
1515}
1516
1517
1533static l_int32
1535 l_int32 s1,
1536 l_int32 c2,
1537 l_int32 s2)
1538{
1539l_int32 ovlp;
1540
1541 if (c1 > c2)
1542 ovlp = c2 + s2 - 1 - c1;
1543 else
1544 ovlp = c1 + s1 - 1 - c2;
1545 return (ovlp < 0) ? 0 : 1;
1546}
1547
1548
1559static l_int32
1561 l_int32 s1,
1562 l_int32 c2,
1563 l_int32 s2)
1564{
1565l_int32 dist;
1566
1567 if (c1 > c2)
1568 dist = c1 - (c2 + s2 - 1);
1569 else
1570 dist = c2 - (c1 + s1 - 1);
1571 return dist;
1572}
1573
1574
1582l_ok
1584 l_float32 *pcx,
1585 l_float32 *pcy)
1586{
1587l_int32 x, y, w, h;
1588
1589 PROCNAME("boxGetCenter");
1590
1591 if (pcx) *pcx = 0;
1592 if (pcy) *pcy = 0;
1593 if (!pcx || !pcy)
1594 return ERROR_INT("&cx, &cy not both defined", procName, 1);
1595 if (!box)
1596 return ERROR_INT("box not defined", procName, 1);
1597 boxGetGeometry(box, &x, &y, &w, &h);
1598 if (w == 0 || h == 0) return 1;
1599 *pcx = (l_float32)(x + 0.5 * w);
1600 *pcy = (l_float32)(y + 0.5 * h);
1601
1602 return 0;
1603}
1604
1605
1624l_ok
1626 l_int32 x,
1627 l_int32 y,
1628 l_float32 slope,
1629 l_int32 *px1,
1630 l_int32 *py1,
1631 l_int32 *px2,
1632 l_int32 *py2,
1633 l_int32 *pn)
1634{
1635l_int32 bx, by, bw, bh, xp, yp, xt, yt, i, n;
1636l_float32 invslope;
1637PTA *pta;
1638
1639 PROCNAME("boxIntersectByLine");
1640
1641 if (px1) *px1 = 0;
1642 if (px2) *px2 = 0;
1643 if (py1) *py1 = 0;
1644 if (py2) *py2 = 0;
1645 if (pn) *pn = 0;
1646 if (!px1 || !py1 || !px2 || !py2)
1647 return ERROR_INT("&x1, &y1, &x2, &y2 not all defined", procName, 1);
1648 if (!pn)
1649 return ERROR_INT("&n not defined", procName, 1);
1650 if (!box)
1651 return ERROR_INT("box not defined", procName, 1);
1652 boxGetGeometry(box, &bx, &by, &bw, &bh);
1653 if (bw == 0 || bh == 0) return 1;
1654
1655 if (slope == 0.0) {
1656 if (y >= by && y < by + bh) {
1657 *py1 = *py2 = y;
1658 *px1 = bx;
1659 *px2 = bx + bw - 1;
1660 }
1661 return 0;
1662 }
1663
1664 if (slope > 1000000.0) {
1665 if (x >= bx && x < bx + bw) {
1666 *px1 = *px2 = x;
1667 *py1 = by;
1668 *py2 = by + bh - 1;
1669 }
1670 return 0;
1671 }
1672
1673 /* Intersection with top and bottom lines of box */
1674 pta = ptaCreate(2);
1675 invslope = 1.0 / slope;
1676 xp = (l_int32)(x + invslope * (y - by));
1677 if (xp >= bx && xp < bx + bw)
1678 ptaAddPt(pta, xp, by);
1679 xp = (l_int32)(x + invslope * (y - by - bh + 1));
1680 if (xp >= bx && xp < bx + bw)
1681 ptaAddPt(pta, xp, by + bh - 1);
1682
1683 /* Intersection with left and right lines of box */
1684 yp = (l_int32)(y + slope * (x - bx));
1685 if (yp >= by && yp < by + bh)
1686 ptaAddPt(pta, bx, yp);
1687 yp = (l_int32)(y + slope * (x - bx - bw + 1));
1688 if (yp >= by && yp < by + bh)
1689 ptaAddPt(pta, bx + bw - 1, yp);
1690
1691 /* There is a maximum of 2 unique points; remove duplicates. */
1692 n = ptaGetCount(pta);
1693 if (n > 0) {
1694 ptaGetIPt(pta, 0, px1, py1); /* accept the first one */
1695 *pn = 1;
1696 }
1697 for (i = 1; i < n; i++) {
1698 ptaGetIPt(pta, i, &xt, &yt);
1699 if ((*px1 != xt) || (*py1 != yt)) {
1700 *px2 = xt;
1701 *py2 = yt;
1702 *pn = 2;
1703 break;
1704 }
1705 }
1706
1707 ptaDestroy(&pta);
1708 return 0;
1709}
1710
1711
1727BOX *
1729 l_int32 wi,
1730 l_int32 hi)
1731{
1732BOX *boxd;
1733
1734 PROCNAME("boxClipToRectangle");
1735
1736 if (!box)
1737 return (BOX *)ERROR_PTR("box not defined", procName, NULL);
1738 if (box->x >= wi || box->y >= hi ||
1739 box->x + box->w <= 0 || box->y + box->h <= 0)
1740 return (BOX *)ERROR_PTR("box outside rectangle", procName, NULL);
1741
1742 boxd = boxCopy(box);
1743 if (boxd->x < 0) {
1744 boxd->w += boxd->x;
1745 boxd->x = 0;
1746 }
1747 if (boxd->y < 0) {
1748 boxd->h += boxd->y;
1749 boxd->y = 0;
1750 }
1751 if (boxd->x + boxd->w > wi)
1752 boxd->w = wi - boxd->x;
1753 if (boxd->y + boxd->h > hi)
1754 boxd->h = hi - boxd->y;
1755 return boxd;
1756}
1757
1758
1784l_ok
1786 l_int32 w,
1787 l_int32 h,
1788 l_int32 *pxstart,
1789 l_int32 *pystart,
1790 l_int32 *pxend,
1791 l_int32 *pyend,
1792 l_int32 *pbw,
1793 l_int32 *pbh)
1794{
1795l_int32 bw, bh;
1796BOX *boxc;
1797
1798 PROCNAME("boxClipToRectangleParams");
1799
1800 if (pxstart) *pxstart = 0;
1801 if (pystart) *pystart = 0;
1802 if (pxend) *pxend = w;
1803 if (pyend) *pyend = h;
1804 if (pbw) *pbw = w;
1805 if (pbh) *pbh = h;
1806 if (!pxstart || !pystart || !pxend || !pyend)
1807 return ERROR_INT("invalid ptr input", procName, 1);
1808 if (!box) return 0;
1809
1810 if ((boxc = boxClipToRectangle(box, w, h)) == NULL)
1811 return ERROR_INT("box outside image", procName, 1);
1812 boxGetGeometry(boxc, pxstart, pystart, &bw, &bh);
1813 boxDestroy(&boxc);
1814
1815 if (pbw) *pbw = bw;
1816 if (pbh) *pbh = bh;
1817 if (bw == 0 || bh == 0)
1818 return ERROR_INT("invalid clipping box", procName, 1);
1819 *pxend = *pxstart + bw; /* 1 past the end */
1820 *pyend = *pystart + bh; /* 1 past the end */
1821 return 0;
1822}
1823
1824
1846BOX *
1848 BOX *boxs,
1849 l_int32 loc,
1850 l_int32 sideflag)
1851{
1852l_int32 x, y, w, h;
1853
1854 PROCNAME("boxRelocateOneSide");
1855
1856 if (!boxs)
1857 return (BOX *)ERROR_PTR("boxs not defined", procName, NULL);
1858 if (!boxd)
1859 boxd = boxCopy(boxs);
1860
1861 boxGetGeometry(boxs, &x, &y, &w, &h);
1862 if (w == 0 || h == 0)
1863 return boxd;
1864 if (sideflag == L_FROM_LEFT)
1865 boxSetGeometry(boxd, loc, -1, w + x - loc, -1);
1866 else if (sideflag == L_FROM_RIGHT)
1867 boxSetGeometry(boxd, -1, -1, loc - x + 1, -1);
1868 else if (sideflag == L_FROM_TOP)
1869 boxSetGeometry(boxd, -1, loc, -1, h + y - loc);
1870 else if (sideflag == L_FROM_BOT)
1871 boxSetGeometry(boxd, -1, -1, -1, loc - y + 1);
1872 return boxd;
1873}
1874
1875
1892BOXA *
1894 l_int32 delleft,
1895 l_int32 delright,
1896 l_int32 deltop,
1897 l_int32 delbot)
1898{
1899l_int32 n, i, x, y;
1900BOX *box1, *box2;
1901BOXA *boxad;
1902
1903 PROCNAME("boxaAdjustSides");
1904
1905 if (!boxas)
1906 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
1907
1908 n = boxaGetCount(boxas);
1909 boxad = boxaCreate(n);
1910 for (i = 0; i < n; i++) {
1911 box1 = boxaGetBox(boxas, i, L_COPY);
1912 box2 = boxAdjustSides(NULL, box1, delleft, delright, deltop, delbot);
1913 if (!box2) {
1914 boxGetGeometry(box1, &x, &y, NULL, NULL);
1915 box2 = boxCreate(x, y, 1, 1);
1916 }
1917 boxaAddBox(boxad, box2, L_INSERT);
1918 boxDestroy(&box1);
1919 }
1920
1921 return boxad;
1922}
1923
1924
1942l_ok
1944 l_int32 index,
1945 l_int32 delleft,
1946 l_int32 delright,
1947 l_int32 deltop,
1948 l_int32 delbot)
1949{
1950BOX *box;
1951
1952 PROCNAME("boxaAdjustBoxSides");
1953
1954 if (!boxa)
1955 return ERROR_INT("boxa not defined", procName, 1);
1956
1957 if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL)
1958 return ERROR_INT("invalid index", procName, 1);
1959
1960 boxAdjustSides(box, box, delleft, delright, deltop, delbot);
1961 boxDestroy(&box); /* the clone */
1962 return 0;
1963}
1964
1965
1990BOX *
1992 BOX *boxs,
1993 l_int32 delleft,
1994 l_int32 delright,
1995 l_int32 deltop,
1996 l_int32 delbot)
1997{
1998l_int32 x, y, w, h, xl, xr, yt, yb, wnew, hnew;
1999
2000 PROCNAME("boxAdjustSides");
2001
2002 if (!boxs)
2003 return (BOX *)ERROR_PTR("boxs not defined", procName, NULL);
2004
2005 boxGetGeometry(boxs, &x, &y, &w, &h);
2006 xl = L_MAX(0, x + delleft);
2007 yt = L_MAX(0, y + deltop);
2008 xr = x + w + delright; /* one pixel beyond right edge */
2009 yb = y + h + delbot; /* one pixel below bottom edge */
2010 wnew = xr - xl;
2011 hnew = yb - yt;
2012
2013 if (wnew < 1 || hnew < 1)
2014 return (BOX *)ERROR_PTR("boxd has 0 area", procName, NULL);
2015 if (!boxd)
2016 return boxCreate(xl, yt, wnew, hnew);
2017
2018 boxSetGeometry(boxd, xl, yt, wnew, hnew);
2019 return boxd;
2020}
2021
2022
2042BOXA *
2044 BOXA *boxas,
2045 l_int32 side,
2046 l_int32 val,
2047 l_int32 thresh)
2048{
2049l_int32 n, i;
2050BOX *box;
2051
2052 PROCNAME("boxaSetSide");
2053
2054 if (!boxas)
2055 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
2056 if (boxad && (boxas != boxad))
2057 return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
2058 if (side != L_SET_LEFT && side != L_SET_RIGHT &&
2059 side != L_SET_TOP && side != L_SET_BOT)
2060 return (BOXA *)ERROR_PTR("invalid side", procName, NULL);
2061 if (val < 0)
2062 return (BOXA *)ERROR_PTR("val < 0", procName, NULL);
2063
2064 if (!boxad)
2065 boxad = boxaCopy(boxas, L_COPY);
2066 n = boxaGetCount(boxad);
2067 for (i = 0; i < n; i++) {
2068 box = boxaGetBox(boxad, i, L_CLONE);
2069 boxSetSide(box, side, val, thresh);
2070 boxDestroy(&box); /* the clone */
2071 }
2072
2073 return boxad;
2074}
2075
2076
2092l_ok
2094 l_int32 side,
2095 l_int32 val,
2096 l_int32 thresh)
2097{
2098l_int32 x, y, w, h, diff;
2099
2100 PROCNAME("boxSetSide");
2101
2102 if (!boxs)
2103 return ERROR_INT("box not defined", procName, 1);
2104 if (side != L_SET_LEFT && side != L_SET_RIGHT &&
2105 side != L_SET_TOP && side != L_SET_BOT)
2106 return ERROR_INT("invalid side", procName, 1);
2107 if (val < 0)
2108 return ERROR_INT("val < 0", procName, 1);
2109
2110 boxGetGeometry(boxs, &x, &y, &w, &h);
2111 if (side == L_SET_LEFT) {
2112 diff = x - val;
2113 if (L_ABS(diff) >= thresh)
2114 boxSetGeometry(boxs, val, y, w + diff, h);
2115 } else if (side == L_SET_RIGHT) {
2116 diff = x + w -1 - val;
2117 if (L_ABS(diff) >= thresh)
2118 boxSetGeometry(boxs, x, y, val - x + 1, h);
2119 } else if (side == L_SET_TOP) {
2120 diff = y - val;
2121 if (L_ABS(diff) >= thresh)
2122 boxSetGeometry(boxs, x, val, w, h + diff);
2123 } else { /* side == L_SET_BOT */
2124 diff = y + h - 1 - val;
2125 if (L_ABS(diff) >= thresh)
2126 boxSetGeometry(boxs, x, y, w, val - y + 1);
2127 }
2128
2129 return 0;
2130}
2131
2132
2154BOXA *
2156 BOXA *boxas,
2157 l_int32 sides,
2158 l_int32 target,
2159 l_int32 thresh)
2160{
2161l_int32 x, y, w, h, n, i, diff;
2162BOX *box;
2163
2164 PROCNAME("boxaAdjustWidthToTarget");
2165
2166 if (!boxas)
2167 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
2168 if (boxad && (boxas != boxad))
2169 return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
2170 if (sides != L_ADJUST_LEFT && sides != L_ADJUST_RIGHT &&
2171 sides != L_ADJUST_LEFT_AND_RIGHT)
2172 return (BOXA *)ERROR_PTR("invalid sides", procName, NULL);
2173 if (target < 1)
2174 return (BOXA *)ERROR_PTR("target < 1", procName, NULL);
2175
2176 if (!boxad)
2177 boxad = boxaCopy(boxas, L_COPY);
2178 n = boxaGetCount(boxad);
2179 for (i = 0; i < n; i++) {
2180 if ((box = boxaGetValidBox(boxad, i, L_CLONE)) == NULL)
2181 continue;
2182 boxGetGeometry(box, &x, &y, &w, &h);
2183 diff = w - target;
2184 if (sides == L_ADJUST_LEFT) {
2185 if (L_ABS(diff) >= thresh)
2186 boxSetGeometry(box, L_MAX(0, x + diff), y, target, h);
2187 } else if (sides == L_ADJUST_RIGHT) {
2188 if (L_ABS(diff) >= thresh)
2189 boxSetGeometry(box, x, y, target, h);
2190 } else { /* sides == L_ADJUST_LEFT_AND_RIGHT */
2191 if (L_ABS(diff) >= thresh)
2192 boxSetGeometry(box, L_MAX(0, x + diff/2), y, target, h);
2193 }
2194 boxDestroy(&box);
2195 }
2196
2197 return boxad;
2198}
2199
2200
2222BOXA *
2224 BOXA *boxas,
2225 l_int32 sides,
2226 l_int32 target,
2227 l_int32 thresh)
2228{
2229l_int32 x, y, w, h, n, i, diff;
2230BOX *box;
2231
2232 PROCNAME("boxaAdjustHeightToTarget");
2233
2234 if (!boxas)
2235 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
2236 if (boxad && (boxas != boxad))
2237 return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
2238 if (sides != L_ADJUST_TOP && sides != L_ADJUST_BOT &&
2239 sides != L_ADJUST_TOP_AND_BOT)
2240 return (BOXA *)ERROR_PTR("invalid sides", procName, NULL);
2241 if (target < 1)
2242 return (BOXA *)ERROR_PTR("target < 1", procName, NULL);
2243
2244 if (!boxad)
2245 boxad = boxaCopy(boxas, L_COPY);
2246 n = boxaGetCount(boxad);
2247 for (i = 0; i < n; i++) {
2248 if ((box = boxaGetValidBox(boxad, i, L_CLONE)) == NULL)
2249 continue;
2250 boxGetGeometry(box, &x, &y, &w, &h);
2251 diff = h - target;
2252 if (sides == L_ADJUST_TOP) {
2253 if (L_ABS(diff) >= thresh)
2254 boxSetGeometry(box, x, L_MAX(0, y + diff), w, target);
2255 } else if (sides == L_ADJUST_BOT) {
2256 if (L_ABS(diff) >= thresh)
2257 boxSetGeometry(box, x, y, w, target);
2258 } else { /* sides == L_ADJUST_TOP_AND_BOT */
2259 if (L_ABS(diff) >= thresh)
2260 boxSetGeometry(box, x, L_MAX(0, y + diff/2), w, target);
2261 }
2262 boxDestroy(&box);
2263 }
2264
2265 return boxad;
2266}
2267
2268
2277l_ok
2279 BOX *box2,
2280 l_int32 *psame)
2281{
2282 PROCNAME("boxEqual");
2283
2284 if (!psame)
2285 return ERROR_INT("&same not defined", procName, 1);
2286 *psame = 0;
2287 if (!box1 || !box2)
2288 return ERROR_INT("boxes not both defined", procName, 1);
2289 if (box1->x == box2->x && box1->y == box2->y &&
2290 box1->w == box2->w && box1->h == box2->h)
2291 *psame = 1;
2292 return 0;
2293}
2294
2295
2324l_ok
2326 BOXA *boxa2,
2327 l_int32 maxdist,
2328 NUMA **pnaindex,
2329 l_int32 *psame)
2330{
2331l_int32 i, j, n, jstart, jend, found, samebox;
2332l_int32 *countarray;
2333BOX *box1, *box2;
2334NUMA *na;
2335
2336 PROCNAME("boxaEqual");
2337
2338 if (pnaindex) *pnaindex = NULL;
2339 if (!psame)
2340 return ERROR_INT("&same not defined", procName, 1);
2341 *psame = 0;
2342 if (!boxa1 || !boxa2)
2343 return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
2344 n = boxaGetCount(boxa1);
2345 if (n != boxaGetCount(boxa2))
2346 return 0;
2347
2348 if ((countarray = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32))) == NULL)
2349 return ERROR_INT("calloc fail for countarray", procName, 1);
2350 na = numaMakeConstant(0.0, n);
2351
2352 for (i = 0; i < n; i++) {
2353 box1 = boxaGetBox(boxa1, i, L_CLONE);
2354 jstart = L_MAX(0, i - maxdist);
2355 jend = L_MIN(n-1, i + maxdist);
2356 found = FALSE;
2357 for (j = jstart; j <= jend; j++) {
2358 box2 = boxaGetBox(boxa2, j, L_CLONE);
2359 boxEqual(box1, box2, &samebox);
2360 if (samebox && countarray[j] == 0) {
2361 countarray[j] = 1;
2362 numaReplaceNumber(na, i, j);
2363 found = TRUE;
2364 boxDestroy(&box2);
2365 break;
2366 }
2367 boxDestroy(&box2);
2368 }
2369 boxDestroy(&box1);
2370 if (!found) {
2371 numaDestroy(&na);
2372 LEPT_FREE(countarray);
2373 return 0;
2374 }
2375 }
2376
2377 *psame = 1;
2378 if (pnaindex)
2379 *pnaindex = na;
2380 else
2381 numaDestroy(&na);
2382 LEPT_FREE(countarray);
2383 return 0;
2384}
2385
2386
2403l_ok
2405 BOX *box2,
2406 l_int32 leftdiff,
2407 l_int32 rightdiff,
2408 l_int32 topdiff,
2409 l_int32 botdiff,
2410 l_int32 *psimilar)
2411{
2412l_int32 l1, l2, r1, r2, t1, t2, b1, b2, valid1, valid2;
2413
2414 PROCNAME("boxSimilar");
2415
2416 if (!psimilar)
2417 return ERROR_INT("&similar not defined", procName, 1);
2418 *psimilar = 0;
2419 if (!box1 || !box2)
2420 return ERROR_INT("boxes not both defined", procName, 1);
2421 boxIsValid(box1, &valid1);
2422 boxIsValid(box2, &valid2);
2423 if (!valid1 || !valid2)
2424 return ERROR_INT("boxes not both valid", procName, 1);
2425
2426 boxGetSideLocations(box1, &l1, &r1, &t1, &b1);
2427 boxGetSideLocations(box2, &l2, &r2, &t2, &b2);
2428 if (L_ABS(l1 - l2) > leftdiff)
2429 return 0;
2430 if (L_ABS(r1 - r2) > rightdiff)
2431 return 0;
2432 if (L_ABS(t1 - t2) > topdiff)
2433 return 0;
2434 if (L_ABS(b1 - b2) > botdiff)
2435 return 0;
2436
2437 *psimilar = 1;
2438 return 0;
2439}
2440
2441
2462l_ok
2464 BOXA *boxa2,
2465 l_int32 leftdiff,
2466 l_int32 rightdiff,
2467 l_int32 topdiff,
2468 l_int32 botdiff,
2469 l_int32 debug,
2470 l_int32 *psimilar,
2471 NUMA **pnasim)
2472{
2473l_int32 i, n1, n2, match, mismatch;
2474BOX *box1, *box2;
2475
2476 PROCNAME("boxaSimilar");
2477
2478 if (psimilar) *psimilar = 0;
2479 if (pnasim) *pnasim = NULL;
2480 if (!boxa1 || !boxa2)
2481 return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
2482 if (!psimilar)
2483 return ERROR_INT("&similar not defined", procName, 1);
2484 n1 = boxaGetCount(boxa1);
2485 n2 = boxaGetCount(boxa2);
2486 if (n1 != n2) {
2487 L_ERROR("boxa counts differ: %d vs %d\n", procName, n1, n2);
2488 return 1;
2489 }
2490 if (pnasim) *pnasim = numaCreate(n1);
2491
2492 mismatch = FALSE;
2493 for (i = 0; i < n1; i++) {
2494 box1 = boxaGetBox(boxa1, i, L_CLONE);
2495 box2 = boxaGetBox(boxa2, i, L_CLONE);
2496 boxSimilar(box1, box2, leftdiff, rightdiff, topdiff, botdiff,
2497 &match);
2498 boxDestroy(&box1);
2499 boxDestroy(&box2);
2500 if (pnasim)
2501 numaAddNumber(*pnasim, match);
2502 if (!match) {
2503 mismatch = TRUE;
2504 if (!debug && pnasim == NULL)
2505 return 0;
2506 else if (debug)
2507 L_INFO("box %d not similar\n", procName, i);
2508 }
2509 }
2510
2511 if (!mismatch) *psimilar = 1;
2512 return 0;
2513}
2514
2515
2516/*----------------------------------------------------------------------*
2517 * Boxa combine and split *
2518 *----------------------------------------------------------------------*/
2536l_ok
2538 BOXA *boxas,
2539 l_int32 istart,
2540 l_int32 iend)
2541{
2542l_int32 n, i;
2543BOX *box;
2544
2545 PROCNAME("boxaJoin");
2546
2547 if (!boxad)
2548 return ERROR_INT("boxad not defined", procName, 1);
2549 if (!boxas || ((n = boxaGetCount(boxas)) == 0))
2550 return 0;
2551
2552 if (istart < 0)
2553 istart = 0;
2554 if (iend < 0 || iend >= n)
2555 iend = n - 1;
2556 if (istart > iend)
2557 return ERROR_INT("istart > iend; nothing to add", procName, 1);
2558
2559 for (i = istart; i <= iend; i++) {
2560 box = boxaGetBox(boxas, i, L_CLONE);
2561 boxaAddBox(boxad, box, L_INSERT);
2562 }
2563
2564 return 0;
2565}
2566
2567
2585l_ok
2587 BOXAA *baas,
2588 l_int32 istart,
2589 l_int32 iend)
2590{
2591l_int32 n, i;
2592BOXA *boxa;
2593
2594 PROCNAME("boxaaJoin");
2595
2596 if (!baad)
2597 return ERROR_INT("baad not defined", procName, 1);
2598 if (!baas)
2599 return 0;
2600
2601 if (istart < 0)
2602 istart = 0;
2603 n = boxaaGetCount(baas);
2604 if (iend < 0 || iend >= n)
2605 iend = n - 1;
2606 if (istart > iend)
2607 return ERROR_INT("istart > iend; nothing to add", procName, 1);
2608
2609 for (i = istart; i <= iend; i++) {
2610 boxa = boxaaGetBoxa(baas, i, L_CLONE);
2611 boxaaAddBoxa(baad, boxa, L_INSERT);
2612 }
2613
2614 return 0;
2615}
2616
2617
2635l_ok
2637 l_int32 fillflag,
2638 BOXA **pboxae,
2639 BOXA **pboxao)
2640{
2641l_int32 i, n;
2642BOX *box, *box1;
2643
2644 PROCNAME("boxaSplitEvenOdd");
2645
2646 if (pboxae) *pboxae = NULL;
2647 if (pboxao) *pboxao = NULL;
2648 if (!pboxae || !pboxao)
2649 return ERROR_INT("&boxae and &boxao not both defined", procName, 1);
2650 if (!boxa)
2651 return ERROR_INT("boxa not defined", procName, 1);
2652
2653 n = boxaGetCount(boxa);
2654 *pboxae = boxaCreate(n);
2655 *pboxao = boxaCreate(n);
2656 if (fillflag == 0) {
2657 /* don't fill with invalid boxes; end up with half-size boxa */
2658 for (i = 0; i < n; i++) {
2659 box = boxaGetBox(boxa, i, L_COPY);
2660 if ((i & 1) == 0)
2661 boxaAddBox(*pboxae, box, L_INSERT);
2662 else
2663 boxaAddBox(*pboxao, box, L_INSERT);
2664 }
2665 } else {
2666 for (i = 0; i < n; i++) {
2667 box = boxaGetBox(boxa, i, L_COPY);
2668 box1 = boxCreate(0, 0, 0, 0); /* empty placeholder */
2669 if ((i & 1) == 0) {
2670 boxaAddBox(*pboxae, box, L_INSERT);
2671 boxaAddBox(*pboxao, box1, L_INSERT);
2672 } else {
2673 boxaAddBox(*pboxae, box1, L_INSERT);
2674 boxaAddBox(*pboxao, box, L_INSERT);
2675 }
2676 }
2677 }
2678 return 0;
2679}
2680
2681
2699BOXA *
2701 BOXA *boxao,
2702 l_int32 fillflag)
2703{
2704l_int32 i, n, ne, no;
2705BOX *box;
2706BOXA *boxad;
2707
2708 PROCNAME("boxaMergeEvenOdd");
2709
2710 if (!boxae || !boxao)
2711 return (BOXA *)ERROR_PTR("boxae and boxao not defined", procName, NULL);
2712 ne = boxaGetCount(boxae);
2713 no = boxaGetCount(boxao);
2714 if (ne < no || ne > no + 1)
2715 return (BOXA *)ERROR_PTR("boxa sizes invalid", procName, NULL);
2716
2717 boxad = boxaCreate(ne);
2718 if (fillflag == 0) { /* both are approx. half-sized; all valid boxes */
2719 n = ne + no;
2720 for (i = 0; i < n; i++) {
2721 if ((i & 1) == 0)
2722 box = boxaGetBox(boxae, i / 2, L_COPY);
2723 else
2724 box = boxaGetBox(boxao, i / 2, L_COPY);
2725 boxaAddBox(boxad, box, L_INSERT);
2726 }
2727 } else { /* both are full size and have invalid placeholders */
2728 for (i = 0; i < ne; i++) {
2729 if ((i & 1) == 0)
2730 box = boxaGetBox(boxae, i, L_COPY);
2731 else
2732 box = boxaGetBox(boxao, i, L_COPY);
2733 boxaAddBox(boxad, box, L_INSERT);
2734 }
2735 }
2736 return boxad;
2737}
BOX * boxaGetValidBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetValidBox()
Definition: boxbasic.c:818
BOX * boxCopy(BOX *box)
boxCopy()
Definition: boxbasic.c:235
BOXA * boxaaGetBoxa(BOXAA *baa, l_int32 index, l_int32 accessflag)
boxaaGetBoxa()
Definition: boxbasic.c:1501
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:537
BOXA * boxaSaveValid(BOXA *boxas, l_int32 copyflag)
boxaSaveValid()
Definition: boxbasic.c:1116
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_ok boxGetSideLocations(BOX *box, l_int32 *pl, l_int32 *pr, l_int32 *pt, l_int32 *pb)
boxGetSideLocations()
Definition: boxbasic.c:374
l_ok boxaReplaceBox(BOXA *boxa, l_int32 index, BOX *box)
boxaReplaceBox()
Definition: boxbasic.c:962
l_int32 boxaaGetCount(BOXAA *baa)
boxaaGetCount()
Definition: boxbasic.c:1454
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:879
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
l_ok boxaaAddBoxa(BOXAA *baa, BOXA *ba, l_int32 copyflag)
boxaaAddBoxa()
Definition: boxbasic.c:1346
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
l_ok boxIsValid(BOX *box, l_int32 *pvalid)
boxIsValid()
Definition: boxbasic.c:475
l_ok boxSetGeometry(BOX *box, l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxSetGeometry()
Definition: boxbasic.c:343
BOX * boxaGetNearestToLine(BOXA *boxa, l_int32 x, l_int32 y)
boxaGetNearestToLine()
Definition: boxfunc1.c:1305
BOXA * boxaContainedInBox(BOXA *boxas, BOX *box)
boxaContainedInBox()
Definition: boxfunc1.c:188
l_ok boxEqual(BOX *box1, BOX *box2, l_int32 *psame)
boxEqual()
Definition: boxfunc1.c:2278
l_ok boxCompareSize(BOX *box1, BOX *box2, l_int32 type, l_int32 *prel)
boxCompareSize()
Definition: boxfunc1.c:1162
BOXA * boxaIntersectsBox(BOXA *boxas, BOX *box)
boxaIntersectsBox()
Definition: boxfunc1.c:331
BOX * boxOverlapRegion(BOX *box1, BOX *box2)
boxOverlapRegion()
Definition: boxfunc1.c:710
BOXA * boxaAdjustWidthToTarget(BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh)
boxaAdjustWidthToTarget()
Definition: boxfunc1.c:2155
l_ok boxGetCenter(BOX *box, l_float32 *pcx, l_float32 *pcy)
boxGetCenter()
Definition: boxfunc1.c:1583
l_ok boxaGetNearestByDirection(BOXA *boxa, l_int32 i, l_int32 dir, l_int32 dist_select, l_int32 range, l_int32 *pindex, l_int32 *pdist)
boxaGetNearestByDirection()
Definition: boxfunc1.c:1444
l_ok boxaEqual(BOXA *boxa1, BOXA *boxa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame)
boxaEqual()
Definition: boxfunc1.c:2325
l_ok boxaAdjustBoxSides(BOXA *boxa, l_int32 index, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxaAdjustBoxSides()
Definition: boxfunc1.c:1943
l_ok boxaJoin(BOXA *boxad, BOXA *boxas, l_int32 istart, l_int32 iend)
boxaJoin()
Definition: boxfunc1.c:2537
l_ok boxaCombineOverlapsInPair(BOXA *boxas1, BOXA *boxas2, BOXA **pboxad1, BOXA **pboxad2, PIXA *pixadb)
boxaCombineOverlapsInPair()
Definition: boxfunc1.c:572
l_ok boxOverlapDistance(BOX *box1, BOX *box2, l_int32 *ph_ovl, l_int32 *pv_ovl)
boxOverlapDistance()
Definition: boxfunc1.c:1044
l_ok boxSimilar(BOX *box1, BOX *box2, l_int32 leftdiff, l_int32 rightdiff, l_int32 topdiff, l_int32 botdiff, l_int32 *psimilar)
boxSimilar()
Definition: boxfunc1.c:2404
l_ok boxIntersects(BOX *box1, BOX *box2, l_int32 *presult)
boxIntersects()
Definition: boxfunc1.c:141
BOXA * boxaCombineOverlaps(BOXA *boxas, PIXA *pixadb)
boxaCombineOverlaps()
Definition: boxfunc1.c:478
l_ok boxaContainedInBoxa(BOXA *boxa1, BOXA *boxa2, l_int32 *pcontained)
boxaContainedInBoxa()
Definition: boxfunc1.c:276
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1991
BOXA * boxaClipToBox(BOXA *boxas, BOX *box)
boxaClipToBox()
Definition: boxfunc1.c:419
l_ok boxaFindNearestBoxes(BOXA *boxa, l_int32 dist_select, l_int32 range, NUMAA **pnaaindex, NUMAA **pnaadist)
boxaFindNearestBoxes()
Definition: boxfunc1.c:1363
BOXA * boxaAdjustSides(BOXA *boxas, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxaAdjustSides()
Definition: boxfunc1.c:1893
l_ok boxaSimilar(BOXA *boxa1, BOXA *boxa2, l_int32 leftdiff, l_int32 rightdiff, l_int32 topdiff, l_int32 botdiff, l_int32 debug, l_int32 *psimilar, NUMA **pnasim)
boxaSimilar()
Definition: boxfunc1.c:2463
BOXA * boxaHandleOverlaps(BOXA *boxas, l_int32 op, l_int32 range, l_float32 min_overlap, l_float32 max_ratio, NUMA **pnamap)
boxaHandleOverlaps()
Definition: boxfunc1.c:914
BOX * boxRelocateOneSide(BOX *boxd, BOX *boxs, l_int32 loc, l_int32 sideflag)
boxRelocateOneSide()
Definition: boxfunc1.c:1847
BOX * boxBoundingRegion(BOX *box1, BOX *box2)
boxBoundingRegion()
Definition: boxfunc1.c:760
l_ok boxaContainedInBoxCount(BOXA *boxa, BOX *box, l_int32 *pcount)
boxaContainedInBoxCount()
Definition: boxfunc1.c:234
l_ok boxOverlapArea(BOX *box1, BOX *box2, l_int32 *parea)
boxOverlapArea()
Definition: boxfunc1.c:850
l_ok boxaIntersectsBoxCount(BOXA *boxa, BOX *box, l_int32 *pcount)
boxaIntersectsBoxCount()
Definition: boxfunc1.c:372
BOX * boxaGetNearestToPt(BOXA *boxa, l_int32 x, l_int32 y)
boxaGetNearestToPt()
Definition: boxfunc1.c:1252
l_ok boxContains(BOX *box1, BOX *box2, l_int32 *presult)
boxContains()
Definition: boxfunc1.c:106
l_ok boxSetSide(BOX *boxs, l_int32 side, l_int32 val, l_int32 thresh)
boxSetSide()
Definition: boxfunc1.c:2093
static l_int32 boxHasOverlapInXorY(l_int32 c1, l_int32 s1, l_int32 c2, l_int32 s2)
boxHasOverlapInXorY()
Definition: boxfunc1.c:1534
l_ok boxIntersectByLine(BOX *box, l_int32 x, l_int32 y, l_float32 slope, l_int32 *px1, l_int32 *py1, l_int32 *px2, l_int32 *py2, l_int32 *pn)
boxIntersectByLine()
Definition: boxfunc1.c:1625
l_ok boxContainsPt(BOX *box, l_float32 x, l_float32 y, l_int32 *pcontains)
boxContainsPt()
Definition: boxfunc1.c:1217
BOXA * boxaMergeEvenOdd(BOXA *boxae, BOXA *boxao, l_int32 fillflag)
boxaMergeEvenOdd()
Definition: boxfunc1.c:2700
BOXA * boxaAdjustHeightToTarget(BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh)
boxaAdjustHeightToTarget()
Definition: boxfunc1.c:2223
l_ok boxSeparationDistance(BOX *box1, BOX *box2, l_int32 *ph_sep, l_int32 *pv_sep)
boxSeparationDistance()
Definition: boxfunc1.c:1117
l_ok boxaaJoin(BOXAA *baad, BOXAA *baas, l_int32 istart, l_int32 iend)
boxaaJoin()
Definition: boxfunc1.c:2586
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1728
static l_int32 boxGetDistanceInXorY(l_int32 c1, l_int32 s1, l_int32 c2, l_int32 s2)
boxGetDistanceInXorY()
Definition: boxfunc1.c:1560
l_ok boxClipToRectangleParams(BOX *box, l_int32 w, l_int32 h, l_int32 *pxstart, l_int32 *pystart, l_int32 *pxend, l_int32 *pyend, l_int32 *pbw, l_int32 *pbh)
boxClipToRectangleParams()
Definition: boxfunc1.c:1785
l_ok boxOverlapFraction(BOX *box1, BOX *box2, l_float32 *pfract)
boxOverlapFraction()
Definition: boxfunc1.c:810
l_ok boxaSplitEvenOdd(BOXA *boxa, l_int32 fillflag, BOXA **pboxae, BOXA **pboxao)
boxaSplitEvenOdd()
Definition: boxfunc1.c:2636
BOXA * boxaSetSide(BOXA *boxad, BOXA *boxas, l_int32 side, l_int32 val, l_int32 thresh)
boxaSetSide()
Definition: boxfunc1.c:2043
l_ok boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition: boxfunc4.c:1287
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:953
l_ok pixRenderBoxaArb(PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxaArb()
Definition: graphics.c:1772
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:627
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:786
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 numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1546
NUMAA * numaaCreate(l_int32 n)
numaaCreate()
Definition: numabasic.c:1407
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:851
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
@ 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
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
@ L_SET_RIGHT
Definition: pix.h:1060
@ L_SET_LEFT
Definition: pix.h:1059
@ L_ADJUST_LEFT
Definition: pix.h:1051
@ L_SET_BOT
Definition: pix.h:1062
@ L_ADJUST_LEFT_AND_RIGHT
Definition: pix.h:1053
@ L_ADJUST_RIGHT
Definition: pix.h:1052
@ L_ADJUST_BOT
Definition: pix.h:1055
@ L_ADJUST_TOP
Definition: pix.h:1054
@ L_SET_TOP
Definition: pix.h:1061
@ L_ADJUST_TOP_AND_BOT
Definition: pix.h:1056
@ L_FROM_BOT
Definition: pix.h:1037
@ L_FROM_LEFT
Definition: pix.h:1034
@ L_FROM_RIGHT
Definition: pix.h:1035
@ L_FROM_TOP
Definition: pix.h:1036
@ L_REMOVE_SMALL
Definition: pix.h:1088
@ L_COMBINE
Definition: pix.h:1087
@ L_NON_NEGATIVE
Definition: pix.h:956
@ L_ALL
Definition: pix.h:960
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
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_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:527
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
Definition: pix.h:481
l_int32 y
Definition: pix.h:483
l_int32 x
Definition: pix.h:482
l_int32 w
Definition: pix.h:484
l_int32 h
Definition: pix.h:485
Definition: pix.h:492
Definition: pix.h:502
Definition: array.h:71
Definition: array.h:83
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517