Leptonica 1.85.0
Image processing and image analysis suite
Loading...
Searching...
No Matches
boxfunc4.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
67#ifdef HAVE_CONFIG_H
68#include <config_auto.h>
69#endif /* HAVE_CONFIG_H */
70
71#include <math.h>
72#include "allheaders.h"
73#include "pix_internal.h"
74
75/*---------------------------------------------------------------------*
76 * Boxa and boxaa range selection *
77 *---------------------------------------------------------------------*/
94BOXA *
96 l_int32 first,
97 l_int32 last,
98 l_int32 copyflag)
99{
100l_int32 n, nbox, i;
101BOX *box;
102BOXA *boxad;
103
104 if (!boxas)
105 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
106 if (copyflag != L_COPY && copyflag != L_CLONE)
107 return (BOXA *)ERROR_PTR("invalid copyflag", __func__, NULL);
108 if ((n = boxaGetCount(boxas)) == 0) {
109 L_WARNING("boxas is empty\n", __func__);
110 return boxaCopy(boxas, copyflag);
111 }
112 first = L_MAX(0, first);
113 if (last < 0) last = n - 1;
114 if (first >= n)
115 return (BOXA *)ERROR_PTR("invalid first", __func__, NULL);
116 if (last >= n) {
117 L_WARNING("last = %d is beyond max index = %d; adjusting\n",
118 __func__, last, n - 1);
119 last = n - 1;
120 }
121 if (first > last)
122 return (BOXA *)ERROR_PTR("first > last", __func__, NULL);
123
124 nbox = last - first + 1;
125 boxad = boxaCreate(nbox);
126 for (i = first; i <= last; i++) {
127 box = boxaGetBox(boxas, i, copyflag);
128 boxaAddBox(boxad, box, L_INSERT);
129 }
130 return boxad;
131}
132
133
150BOXAA *
152 l_int32 first,
153 l_int32 last,
154 l_int32 copyflag)
155{
156l_int32 n, nboxa, i;
157BOXA *boxa;
158BOXAA *baad;
159
160 if (!baas)
161 return (BOXAA *)ERROR_PTR("baas not defined", __func__, NULL);
162 if (copyflag != L_COPY && copyflag != L_CLONE)
163 return (BOXAA *)ERROR_PTR("invalid copyflag", __func__, NULL);
164 if ((n = boxaaGetCount(baas)) == 0)
165 return (BOXAA *)ERROR_PTR("empty baas", __func__, NULL);
166 first = L_MAX(0, first);
167 if (last < 0) last = n - 1;
168 if (first >= n)
169 return (BOXAA *)ERROR_PTR("invalid first", __func__, NULL);
170 if (last >= n) {
171 L_WARNING("last = %d is beyond max index = %d; adjusting\n",
172 __func__, last, n - 1);
173 last = n - 1;
174 }
175 if (first > last)
176 return (BOXAA *)ERROR_PTR("first > last", __func__, NULL);
177
178 nboxa = last - first + 1;
179 baad = boxaaCreate(nboxa);
180 for (i = first; i <= last; i++) {
181 boxa = boxaaGetBoxa(baas, i, copyflag);
182 boxaaAddBoxa(baad, boxa, L_INSERT);
183 }
184 return baad;
185}
186
187
188/*---------------------------------------------------------------------*
189 * Boxa size selection *
190 *---------------------------------------------------------------------*/
216BOXA *
218 l_int32 width,
219 l_int32 height,
220 l_int32 type,
221 l_int32 relation,
222 l_int32 *pchanged)
223{
224BOXA *boxad;
225NUMA *na;
226
227 if (pchanged) *pchanged = FALSE;
228 if (!boxas)
229 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
230 if (boxaGetCount(boxas) == 0) {
231 L_WARNING("boxas is empty\n", __func__);
232 return boxaCopy(boxas, L_COPY);
233 }
234 if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
235 type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
236 return (BOXA *)ERROR_PTR("invalid type", __func__, NULL);
237 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
238 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
239 return (BOXA *)ERROR_PTR("invalid relation", __func__, NULL);
240
241 /* Compute the indicator array for saving components */
242 if ((na =
243 boxaMakeSizeIndicator(boxas, width, height, type, relation)) == NULL)
244 return (BOXA *)ERROR_PTR("na not made", __func__, NULL);
245
246 /* Filter to get output */
247 boxad = boxaSelectWithIndicator(boxas, na, pchanged);
248
249 numaDestroy(&na);
250 return boxad;
251}
252
253
277NUMA *
279 l_int32 width,
280 l_int32 height,
281 l_int32 type,
282 l_int32 relation)
283{
284l_int32 i, n, w, h, ival;
285NUMA *na;
286
287 if (!boxa)
288 return (NUMA *)ERROR_PTR("boxa not defined", __func__, NULL);
289 if ((n = boxaGetCount(boxa)) == 0)
290 return (NUMA *)ERROR_PTR("boxa is empty", __func__, NULL);
291 if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
292 type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
293 return (NUMA *)ERROR_PTR("invalid type", __func__, NULL);
294 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
295 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
296 return (NUMA *)ERROR_PTR("invalid relation", __func__, NULL);
297
298 na = numaCreate(n);
299 for (i = 0; i < n; i++) {
300 ival = 0;
301 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
302 switch (type)
303 {
304 case L_SELECT_WIDTH:
305 if ((relation == L_SELECT_IF_LT && w < width) ||
306 (relation == L_SELECT_IF_GT && w > width) ||
307 (relation == L_SELECT_IF_LTE && w <= width) ||
308 (relation == L_SELECT_IF_GTE && w >= width))
309 ival = 1;
310 break;
311 case L_SELECT_HEIGHT:
312 if ((relation == L_SELECT_IF_LT && h < height) ||
313 (relation == L_SELECT_IF_GT && h > height) ||
314 (relation == L_SELECT_IF_LTE && h <= height) ||
315 (relation == L_SELECT_IF_GTE && h >= height))
316 ival = 1;
317 break;
319 if (((relation == L_SELECT_IF_LT) && (w < width || h < height)) ||
320 ((relation == L_SELECT_IF_GT) && (w > width || h > height)) ||
321 ((relation == L_SELECT_IF_LTE) && (w <= width || h <= height)) ||
322 ((relation == L_SELECT_IF_GTE) && (w >= width || h >= height)))
323 ival = 1;
324 break;
325 case L_SELECT_IF_BOTH:
326 if (((relation == L_SELECT_IF_LT) && (w < width && h < height)) ||
327 ((relation == L_SELECT_IF_GT) && (w > width && h > height)) ||
328 ((relation == L_SELECT_IF_LTE) && (w <= width && h <= height)) ||
329 ((relation == L_SELECT_IF_GTE) && (w >= width && h >= height)))
330 ival = 1;
331 break;
332 default:
333 L_WARNING("can't get here!\n", __func__);
334 break;
335 }
336 numaAddNumber(na, ival);
337 }
338
339 return na;
340}
341
342
362BOXA *
364 l_int32 area,
365 l_int32 relation,
366 l_int32 *pchanged)
367{
368BOXA *boxad;
369NUMA *na;
370
371 if (pchanged) *pchanged = FALSE;
372 if (!boxas)
373 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
374 if (boxaGetCount(boxas) == 0) {
375 L_WARNING("boxas is empty\n", __func__);
376 return boxaCopy(boxas, L_COPY);
377 }
378 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
379 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
380 return (BOXA *)ERROR_PTR("invalid relation", __func__, NULL);
381
382 /* Compute the indicator array for saving components */
383 na = boxaMakeAreaIndicator(boxas, area, relation);
384
385 /* Filter to get output */
386 boxad = boxaSelectWithIndicator(boxas, na, pchanged);
387
388 numaDestroy(&na);
389 return boxad;
390}
391
392
410NUMA *
412 l_int32 area,
413 l_int32 relation)
414{
415l_int32 i, n, w, h, ival;
416NUMA *na;
417
418 if (!boxa)
419 return (NUMA *)ERROR_PTR("boxa not defined", __func__, NULL);
420 if ((n = boxaGetCount(boxa)) == 0)
421 return (NUMA *)ERROR_PTR("boxa is empty", __func__, NULL);
422 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
423 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
424 return (NUMA *)ERROR_PTR("invalid relation", __func__, NULL);
425
426 na = numaCreate(n);
427 for (i = 0; i < n; i++) {
428 ival = 0;
429 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
430
431 if ((relation == L_SELECT_IF_LT && w * h < area) ||
432 (relation == L_SELECT_IF_GT && w * h > area) ||
433 (relation == L_SELECT_IF_LTE && w * h <= area) ||
434 (relation == L_SELECT_IF_GTE && w * h >= area))
435 ival = 1;
436 numaAddNumber(na, ival);
437 }
438
439 return na;
440}
441
442
462BOXA *
464 l_float32 ratio,
465 l_int32 relation,
466 l_int32 *pchanged)
467{
468BOXA *boxad;
469NUMA *na;
470
471 if (pchanged) *pchanged = FALSE;
472 if (!boxas)
473 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
474 if (boxaGetCount(boxas) == 0) {
475 L_WARNING("boxas is empty\n", __func__);
476 return boxaCopy(boxas, L_COPY);
477 }
478 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
479 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
480 return (BOXA *)ERROR_PTR("invalid relation", __func__, NULL);
481
482 /* Compute the indicator array for saving components */
483 na = boxaMakeWHRatioIndicator(boxas, ratio, relation);
484
485 /* Filter to get output */
486 boxad = boxaSelectWithIndicator(boxas, na, pchanged);
487
488 numaDestroy(&na);
489 return boxad;
490}
491
492
510NUMA *
512 l_float32 ratio,
513 l_int32 relation)
514{
515l_int32 i, n, w, h, ival;
516l_float32 whratio;
517NUMA *na;
518
519 if (!boxa)
520 return (NUMA *)ERROR_PTR("boxa not defined", __func__, NULL);
521 if ((n = boxaGetCount(boxa)) == 0)
522 return (NUMA *)ERROR_PTR("boxa is empty", __func__, NULL);
523 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
524 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
525 return (NUMA *)ERROR_PTR("invalid relation", __func__, NULL);
526
527 na = numaCreate(n);
528 for (i = 0; i < n; i++) {
529 ival = 0;
530 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
531 whratio = (l_float32)w / (l_float32)h;
532
533 if ((relation == L_SELECT_IF_LT && whratio < ratio) ||
534 (relation == L_SELECT_IF_GT && whratio > ratio) ||
535 (relation == L_SELECT_IF_LTE && whratio <= ratio) ||
536 (relation == L_SELECT_IF_GTE && whratio >= ratio))
537 ival = 1;
538 numaAddNumber(na, ival);
539 }
540
541 return na;
542}
543
544
561BOXA *
563 NUMA *na,
564 l_int32 *pchanged)
565{
566l_int32 i, n, ival, nsave;
567BOX *box;
568BOXA *boxad;
569
570 if (pchanged) *pchanged = FALSE;
571 if (!boxas)
572 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
573 if (!na)
574 return (BOXA *)ERROR_PTR("na not defined", __func__, NULL);
575
576 nsave = 0;
577 n = numaGetCount(na);
578 for (i = 0; i < n; i++) {
579 numaGetIValue(na, i, &ival);
580 if (ival == 1) nsave++;
581 }
582
583 if (nsave == n) {
584 if (pchanged) *pchanged = FALSE;
585 return boxaCopy(boxas, L_COPY);
586 }
587 if (pchanged) *pchanged = TRUE;
588 boxad = boxaCreate(nsave);
589 for (i = 0; i < n; i++) {
590 numaGetIValue(na, i, &ival);
591 if (ival == 0) continue;
592 box = boxaGetBox(boxas, i, L_COPY);
593 boxaAddBox(boxad, box, L_INSERT);
594 }
595
596 return boxad;
597}
598
599
600/*---------------------------------------------------------------------*
601 * Boxa Permutation *
602 *---------------------------------------------------------------------*/
617BOXA *
619{
620l_int32 n;
621NUMA *na;
622BOXA *boxad;
623
624 if (!boxas)
625 return (BOXA *)ERROR_PTR("boxa not defined", __func__, NULL);
626
627 n = boxaGetCount(boxas);
628 na = numaPseudorandomSequence(n, 0);
629 boxad = boxaSortByIndex(boxas, na);
630 numaDestroy(&na);
631 return boxad;
632}
633
634
656BOXA *
658 BOXA *boxas)
659{
660l_int32 i, n, index;
661
662 if (!boxas)
663 return (BOXA *)ERROR_PTR("boxa not defined", __func__, NULL);
664 if (boxad && (boxad != boxas))
665 return (BOXA *)ERROR_PTR("boxad defined but in-place", __func__, NULL);
666
667 if (!boxad)
668 boxad = boxaCopy(boxas, L_COPY);
669 if ((n = boxaGetCount(boxad)) == 0)
670 return boxad;
671 index = (l_uint32)rand() % n;
672 index = L_MAX(1, index);
673 boxaSwapBoxes(boxad, 0, index);
674 for (i = 1; i < n; i++) {
675 index = (l_uint32)rand() % n;
676 if (index == i) index--;
677 boxaSwapBoxes(boxad, i, index);
678 }
679
680 return boxad;
681}
682
683
691l_ok
693 l_int32 i,
694 l_int32 j)
695{
696l_int32 n;
697BOX *box;
698
699 if (!boxa)
700 return ERROR_INT("boxa not defined", __func__, 1);
701 n = boxaGetCount(boxa);
702 if (i < 0 || i >= n)
703 return ERROR_INT("i invalid", __func__, 1);
704 if (j < 0 || j >= n)
705 return ERROR_INT("j invalid", __func__, 1);
706 if (i == j)
707 return ERROR_INT("i == j", __func__, 1);
708
709 box = boxa->box[i];
710 boxa->box[i] = boxa->box[j];
711 boxa->box[j] = box;
712 return 0;
713}
714
715
716/*---------------------------------------------------------------------*
717 * Boxa and Box Conversions *
718 *---------------------------------------------------------------------*/
737PTA *
739 l_int32 ncorners)
740{
741l_int32 i, n;
742BOX *box;
743PTA *pta, *pta1;
744
745 if (!boxa)
746 return (PTA *)ERROR_PTR("boxa not defined", __func__, NULL);
747 if (ncorners != 2 && ncorners != 4)
748 return (PTA *)ERROR_PTR("ncorners not 2 or 4", __func__, NULL);
749
750 n = boxaGetCount(boxa);
751 if ((pta = ptaCreate(n)) == NULL)
752 return (PTA *)ERROR_PTR("pta not made", __func__, NULL);
753 for (i = 0; i < n; i++) {
754 box = boxaGetBox(boxa, i, L_COPY);
755 pta1 = boxConvertToPta(box, ncorners);
756 ptaJoin(pta, pta1, 0, -1);
757 boxDestroy(&box);
758 ptaDestroy(&pta1);
759 }
760
761 return pta;
762}
763
764
780BOXA *
782 l_int32 ncorners)
783{
784l_int32 i, n, nbox, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
785BOX *box;
786BOXA *boxa;
787
788 if (!pta)
789 return (BOXA *)ERROR_PTR("pta not defined", __func__, NULL);
790 if (ncorners != 2 && ncorners != 4)
791 return (BOXA *)ERROR_PTR("ncorners not 2 or 4", __func__, NULL);
792 n = ptaGetCount(pta);
793 if (n % ncorners != 0)
794 return (BOXA *)ERROR_PTR("size % ncorners != 0", __func__, NULL);
795 nbox = n / ncorners;
796 if ((boxa = boxaCreate(nbox)) == NULL)
797 return (BOXA *)ERROR_PTR("boxa not made", __func__, NULL);
798 for (i = 0; i < n; i += ncorners) {
799 ptaGetIPt(pta, i, &x1, &y1);
800 ptaGetIPt(pta, i + 1, &x2, &y2);
801 if (ncorners == 2) {
802 box = boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
803 boxaAddBox(boxa, box, L_INSERT);
804 continue;
805 }
806 ptaGetIPt(pta, i + 2, &x3, &y3);
807 ptaGetIPt(pta, i + 3, &x4, &y4);
808 x = L_MIN(x1, x3);
809 y = L_MIN(y1, y2);
810 xmax = L_MAX(x2, x4);
811 ymax = L_MAX(y3, y4);
812 box = boxCreate(x, y, xmax - x + 1, ymax - y + 1);
813 boxaAddBox(boxa, box, L_INSERT);
814 }
815
816 return boxa;
817}
818
819
833PTA *
835 l_int32 ncorners)
836{
837l_int32 x, y, w, h;
838PTA *pta;
839
840 if (!box)
841 return (PTA *)ERROR_PTR("box not defined", __func__, NULL);
842 if (ncorners != 2 && ncorners != 4)
843 return (PTA *)ERROR_PTR("ncorners not 2 or 4", __func__, NULL);
844
845 if ((pta = ptaCreate(ncorners)) == NULL)
846 return (PTA *)ERROR_PTR("pta not made", __func__, NULL);
847 boxGetGeometry(box, &x, &y, &w, &h);
848 ptaAddPt(pta, x, y);
849 if (ncorners == 2) {
850 ptaAddPt(pta, x + w - 1, y + h - 1);
851 } else {
852 ptaAddPt(pta, x + w - 1, y);
853 ptaAddPt(pta, x, y + h - 1);
854 ptaAddPt(pta, x + w - 1, y + h - 1);
855 }
856
857 return pta;
858}
859
860
873BOX *
875{
876l_int32 n, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
877
878 if (!pta)
879 return (BOX *)ERROR_PTR("pta not defined", __func__, NULL);
880 n = ptaGetCount(pta);
881 if (n != 2 && n != 4)
882 return (BOX *)ERROR_PTR("n must be 2 or 4", __func__, NULL);
883 ptaGetIPt(pta, 0, &x1, &y1);
884 ptaGetIPt(pta, 1, &x2, &y2);
885 if (n == 2)
886 return boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
887
888 /* 4 corners */
889 ptaGetIPt(pta, 2, &x3, &y3);
890 ptaGetIPt(pta, 3, &x4, &y4);
891 x = L_MIN(x1, x3);
892 y = L_MIN(y1, y2);
893 xmax = L_MAX(x2, x4);
894 ymax = L_MAX(y3, y4);
895 return boxCreate(x, y, xmax - x + 1, ymax - y + 1);
896}
897
898
899/*---------------------------------------------------------------------*
900 * Miscellaneous Boxa functions *
901 *---------------------------------------------------------------------*/
923l_ok
925 l_int32 *pw,
926 l_int32 *ph,
927 BOX **pbox)
928{
929l_int32 i, n, x, y, w, h, xmax, ymax, xmin, ymin, found;
930
931 if (!pw && !ph && !pbox)
932 return ERROR_INT("no ptrs defined", __func__, 1);
933 if (pw) *pw = 0;
934 if (ph) *ph = 0;
935 if (pbox) *pbox = NULL;
936 if (!boxa)
937 return ERROR_INT("boxa not defined", __func__, 1);
938
939 n = boxaGetCount(boxa);
940 xmax = ymax = 0;
941 xmin = ymin = 100000000;
942 found = FALSE;
943 for (i = 0; i < n; i++) {
944 boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
945 if (w <= 0 || h <= 0)
946 continue;
947 found = TRUE;
948 xmin = L_MIN(xmin, x);
949 ymin = L_MIN(ymin, y);
950 xmax = L_MAX(xmax, x + w);
951 ymax = L_MAX(ymax, y + h);
952 }
953 if (found == FALSE) /* no valid boxes in boxa */
954 xmin = ymin = 0;
955 if (pw) *pw = xmax;
956 if (ph) *ph = ymax;
957 if (pbox)
958 *pbox = boxCreate(xmin, ymin, xmax - xmin, ymax - ymin);
959
960 return 0;
961}
962
963
987l_ok
989 l_int32 wc,
990 l_int32 hc,
991 l_int32 exactflag,
992 l_float32 *pfract)
993{
994l_int32 i, n, x, y, w, h, sum;
995BOX *box, *boxc;
996PIX *pixt;
997
998 if (!pfract)
999 return ERROR_INT("&fract not defined", __func__, 1);
1000 *pfract = 0.0;
1001 if (!boxa)
1002 return ERROR_INT("boxa not defined", __func__, 1);
1003
1004 n = boxaGetCount(boxa);
1005 if (n == 0)
1006 return ERROR_INT("no boxes in boxa", __func__, 1);
1007
1008 if (exactflag == 0) { /* quick and dirty */
1009 sum = 0;
1010 for (i = 0; i < n; i++) {
1011 box = boxaGetBox(boxa, i, L_CLONE);
1012 if ((boxc = boxClipToRectangle(box, wc, hc)) != NULL) {
1013 boxGetGeometry(boxc, NULL, NULL, &w, &h);
1014 sum += w * h;
1015 boxDestroy(&boxc);
1016 }
1017 boxDestroy(&box);
1018 }
1019 } else { /* slower and exact */
1020 pixt = pixCreate(wc, hc, 1);
1021 for (i = 0; i < n; i++) {
1022 box = boxaGetBox(boxa, i, L_CLONE);
1023 boxGetGeometry(box, &x, &y, &w, &h);
1024 pixRasterop(pixt, x, y, w, h, PIX_SET, NULL, 0, 0);
1025 boxDestroy(&box);
1026 }
1027 pixCountPixels(pixt, &sum, NULL);
1028 pixDestroy(&pixt);
1029 }
1030
1031 *pfract = (l_float32)sum / (l_float32)(wc * hc);
1032 return 0;
1033}
1034
1035
1046l_ok
1048 l_int32 *pminw,
1049 l_int32 *pminh,
1050 l_int32 *pmaxw,
1051 l_int32 *pmaxh)
1052{
1053l_int32 minw, minh, maxw, maxh, minbw, minbh, maxbw, maxbh, i, n;
1054BOXA *boxa;
1055
1056 if (!pminw && !pmaxw && !pminh && !pmaxh)
1057 return ERROR_INT("no data can be returned", __func__, 1);
1058 if (pminw) *pminw = 0;
1059 if (pminh) *pminh = 0;
1060 if (pmaxw) *pmaxw = 0;
1061 if (pmaxh) *pmaxh = 0;
1062 if (!baa)
1063 return ERROR_INT("baa not defined", __func__, 1);
1064
1065 minw = minh = 100000000;
1066 maxw = maxh = 0;
1067 n = boxaaGetCount(baa);
1068 for (i = 0; i < n; i++) {
1069 boxa = boxaaGetBoxa(baa, i, L_CLONE);
1070 boxaSizeRange(boxa, &minbw, &minbh, &maxbw, &maxbh);
1071 if (minbw < minw)
1072 minw = minbw;
1073 if (minbh < minh)
1074 minh = minbh;
1075 if (maxbw > maxw)
1076 maxw = maxbw;
1077 if (maxbh > maxh)
1078 maxh = maxbh;
1079 boxaDestroy(&boxa);
1080 }
1081
1082 if (pminw) *pminw = minw;
1083 if (pminh) *pminh = minh;
1084 if (pmaxw) *pmaxw = maxw;
1085 if (pmaxh) *pmaxh = maxh;
1086 return 0;
1087}
1088
1089
1100l_ok
1102 l_int32 *pminw,
1103 l_int32 *pminh,
1104 l_int32 *pmaxw,
1105 l_int32 *pmaxh)
1106{
1107l_int32 minw, minh, maxw, maxh, i, n, w, h;
1108
1109 if (!pminw && !pmaxw && !pminh && !pmaxh)
1110 return ERROR_INT("no data can be returned", __func__, 1);
1111 if (pminw) *pminw = 0;
1112 if (pminh) *pminh = 0;
1113 if (pmaxw) *pmaxw = 0;
1114 if (pmaxh) *pmaxh = 0;
1115 if (!boxa)
1116 return ERROR_INT("boxa not defined", __func__, 1);
1117
1118 minw = minh = 100000000;
1119 maxw = maxh = 0;
1120 n = boxaGetCount(boxa);
1121 for (i = 0; i < n; i++) {
1122 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
1123 if (w < minw)
1124 minw = w;
1125 if (h < minh)
1126 minh = h;
1127 if (w > maxw)
1128 maxw = w;
1129 if (h > maxh)
1130 maxh = h;
1131 }
1132
1133 if (pminw) *pminw = minw;
1134 if (pminh) *pminh = minh;
1135 if (pmaxw) *pmaxw = maxw;
1136 if (pmaxh) *pmaxh = maxh;
1137 return 0;
1138}
1139
1140
1151l_ok
1153 l_int32 *pminx,
1154 l_int32 *pminy,
1155 l_int32 *pmaxx,
1156 l_int32 *pmaxy)
1157{
1158l_int32 minx, miny, maxx, maxy, i, n, x, y;
1159
1160 if (!pminx && !pminy && !pmaxx && !pmaxy)
1161 return ERROR_INT("no data can be returned", __func__, 1);
1162 if (pminx) *pminx = 0;
1163 if (pminy) *pminy = 0;
1164 if (pmaxx) *pmaxx = 0;
1165 if (pmaxy) *pmaxy = 0;
1166 if (!boxa)
1167 return ERROR_INT("boxa not defined", __func__, 1);
1168
1169 minx = miny = 100000000;
1170 maxx = maxy = 0;
1171 n = boxaGetCount(boxa);
1172 for (i = 0; i < n; i++) {
1173 boxaGetBoxGeometry(boxa, i, &x, &y, NULL, NULL);
1174 if (x < minx)
1175 minx = x;
1176 if (y < miny)
1177 miny = y;
1178 if (x > maxx)
1179 maxx = x;
1180 if (y > maxy)
1181 maxy = y;
1182 }
1183
1184 if (pminx) *pminx = minx;
1185 if (pminy) *pminy = miny;
1186 if (pmaxx) *pmaxx = maxx;
1187 if (pmaxy) *pmaxy = maxy;
1188
1189 return 0;
1190}
1191
1192
1201l_ok
1203 NUMA **pnaw,
1204 NUMA **pnah)
1205{
1206l_int32 i, n, w, h;
1207BOX *box;
1208
1209 if (pnaw) *pnaw = NULL;
1210 if (pnah) *pnah = NULL;
1211 if (!pnaw && !pnah)
1212 return ERROR_INT("no output requested", __func__, 1);
1213 if (!boxa)
1214 return ERROR_INT("boxa not defined", __func__, 1);
1215
1216 n = boxaGetValidCount(boxa);
1217 if (pnaw) *pnaw = numaCreate(n);
1218 if (pnah) *pnah = numaCreate(n);
1219 for (i = 0; i < n; i++) {
1220 box = boxaGetValidBox(boxa, i, L_COPY);
1221 if (box) {
1222 boxGetGeometry(box, NULL, NULL, &w, &h);
1223 if (pnaw) numaAddNumber(*pnaw, w);
1224 if (pnah) numaAddNumber(*pnah, h);
1225 boxDestroy(&box);
1226 }
1227 }
1228
1229 return 0;
1230}
1231
1232
1245l_ok
1247 l_int32 *parea)
1248{
1249l_int32 i, n, w, h;
1250
1251 if (!parea)
1252 return ERROR_INT("&area not defined", __func__, 1);
1253 *parea = 0;
1254 if (!boxa)
1255 return ERROR_INT("boxa not defined", __func__, 1);
1256
1257 n = boxaGetCount(boxa);
1258 for (i = 0; i < n; i++) {
1259 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
1260 *parea += w * h;
1261 }
1262 return 0;
1263}
1264
1265
1293PIX *
1295 PIXA *pixa,
1296 l_int32 first,
1297 l_int32 last,
1298 l_int32 maxwidth,
1299 l_int32 linewidth,
1300 l_float32 scalefactor,
1301 l_int32 background,
1302 l_int32 spacing,
1303 l_int32 border)
1304{
1305char buf[32];
1306l_int32 i, n, npix, w, h, fontsize;
1307L_BMF *bmf;
1308BOX *box;
1309BOXA *boxa;
1310PIX *pix1, *pix2, *pixd;
1311PIXA *pixat;
1312
1313 if (!boxas)
1314 return (PIX *)ERROR_PTR("boxas not defined", __func__, NULL);
1315
1316 boxa = boxaSaveValid(boxas, L_COPY);
1317 n = boxaGetCount(boxa);
1318 if (pixa) {
1319 npix = pixaGetCount(pixa);
1320 if (n != npix) {
1321 boxaDestroy(&boxa);
1322 return (PIX *)ERROR_PTR("boxa and pixa counts differ",
1323 __func__, NULL);
1324 }
1325 }
1326 first = L_MAX(0, first);
1327 if (last < 0) last = n - 1;
1328 if (first >= n) {
1329 boxaDestroy(&boxa);
1330 return (PIX *)ERROR_PTR("invalid first", __func__, NULL);
1331 }
1332 if (last >= n) {
1333 L_WARNING("last = %d is beyond max index = %d; adjusting\n",
1334 __func__, last, n - 1);
1335 last = n - 1;
1336 }
1337 if (first > last) {
1338 boxaDestroy(&boxa);
1339 return (PIX *)ERROR_PTR("first > last", __func__, NULL);
1340 }
1341
1342 /* Because the bitmap font will be reduced when tiled, choose the
1343 * font size inversely with the scale factor. */
1344 if (scalefactor > 0.8)
1345 fontsize = 6;
1346 else if (scalefactor > 0.6)
1347 fontsize = 10;
1348 else if (scalefactor > 0.4)
1349 fontsize = 14;
1350 else if (scalefactor > 0.3)
1351 fontsize = 18;
1352 else fontsize = 20;
1353 bmf = bmfCreate(NULL, fontsize);
1354
1355 pixat = pixaCreate(n);
1356 boxaGetExtent(boxa, &w, &h, NULL);
1357 for (i = first; i <= last; i++) {
1358 box = boxaGetBox(boxa, i, L_CLONE);
1359 if (!pixa) {
1360 pix1 = pixCreate(w, h, 32);
1361 pixSetAll(pix1);
1362 } else {
1363 pix1 = pixaGetPix(pixa, i, L_COPY);
1364 }
1365 pixSetBorderVal(pix1, 0, 0, 0, 2, 0x0000ff00);
1366 snprintf(buf, sizeof(buf), "%d", i);
1367 pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0x00ff0000,
1368 L_ADD_BELOW, NULL);
1369 pixDestroy(&pix1);
1370 pixRenderBoxArb(pix2, box, linewidth, 255, 0, 0);
1371 pixaAddPix(pixat, pix2, L_INSERT);
1372 boxDestroy(&box);
1373 }
1374 bmfDestroy(&bmf);
1375 boxaDestroy(&boxa);
1376
1377 pixd = pixaDisplayTiledInRows(pixat, 32, maxwidth, scalefactor, background,
1378 spacing, border);
1379 pixaDestroy(&pixat);
1380 return pixd;
1381}
BOXA * boxaPermutePseudorandom(BOXA *boxas)
boxaPermutePseudorandom()
Definition boxfunc4.c:618
l_ok boxaSwapBoxes(BOXA *boxa, l_int32 i, l_int32 j)
boxaSwapBoxes()
Definition boxfunc4.c:692
NUMA * boxaMakeWHRatioIndicator(BOXA *boxa, l_float32 ratio, l_int32 relation)
boxaMakeWHRatioIndicator()
Definition boxfunc4.c:511
l_ok boxaaSizeRange(BOXAA *baa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
boxaaSizeRange()
Definition boxfunc4.c:1047
PIX * boxaDisplayTiled(BOXA *boxas, PIXA *pixa, l_int32 first, l_int32 last, l_int32 maxwidth, l_int32 linewidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border)
boxaDisplayTiled()
Definition boxfunc4.c:1294
l_ok boxaGetSizes(BOXA *boxa, NUMA **pnaw, NUMA **pnah)
boxaGetSizes()
Definition boxfunc4.c:1202
NUMA * boxaMakeSizeIndicator(BOXA *boxa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation)
boxaMakeSizeIndicator()
Definition boxfunc4.c:278
BOXA * boxaSelectRange(BOXA *boxas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaSelectRange()
Definition boxfunc4.c:95
l_ok boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition boxfunc4.c:1246
BOXA * boxaSelectBySize(BOXA *boxas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
boxaSelectBySize()
Definition boxfunc4.c:217
PTA * boxConvertToPta(BOX *box, l_int32 ncorners)
boxConvertToPta()
Definition boxfunc4.c:834
BOXA * boxaPermuteRandom(BOXA *boxad, BOXA *boxas)
boxaPermuteRandom()
Definition boxfunc4.c:657
NUMA * boxaMakeAreaIndicator(BOXA *boxa, l_int32 area, l_int32 relation)
boxaMakeAreaIndicator()
Definition boxfunc4.c:411
BOXA * boxaSelectByWHRatio(BOXA *boxas, l_float32 ratio, l_int32 relation, l_int32 *pchanged)
boxaSelectByWHRatio()
Definition boxfunc4.c:463
l_ok boxaSizeRange(BOXA *boxa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
boxaSizeRange()
Definition boxfunc4.c:1101
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition boxfunc4.c:924
PTA * boxaConvertToPta(BOXA *boxa, l_int32 ncorners)
boxaConvertToPta()
Definition boxfunc4.c:738
BOXA * boxaSelectByArea(BOXA *boxas, l_int32 area, l_int32 relation, l_int32 *pchanged)
boxaSelectByArea()
Definition boxfunc4.c:363
BOX * ptaConvertToBox(PTA *pta)
ptaConvertToBox()
Definition boxfunc4.c:874
BOXA * ptaConvertToBoxa(PTA *pta, l_int32 ncorners)
ptaConvertToBoxa()
Definition boxfunc4.c:781
l_ok boxaGetCoverage(BOXA *boxa, l_int32 wc, l_int32 hc, l_int32 exactflag, l_float32 *pfract)
boxaGetCoverage()
Definition boxfunc4.c:988
BOXA * boxaSelectWithIndicator(BOXA *boxas, NUMA *na, l_int32 *pchanged)
boxaSelectWithIndicator()
Definition boxfunc4.c:562
l_ok boxaLocationRange(BOXA *boxa, l_int32 *pminx, l_int32 *pminy, l_int32 *pmaxx, l_int32 *pmaxy)
boxaLocationRange()
Definition boxfunc4.c:1152
BOXAA * boxaaSelectRange(BOXAA *baas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaaSelectRange()
Definition boxfunc4.c:151
@ L_SELECT_IF_LTE
Definition pix.h:577
@ L_SELECT_IF_LT
Definition pix.h:575
@ L_SELECT_IF_GT
Definition pix.h:576
@ L_SELECT_IF_GTE
Definition pix.h:578
@ L_SELECT_IF_BOTH
Definition pix.h:599
@ L_SELECT_IF_EITHER
Definition pix.h:597
@ L_SELECT_WIDTH
Definition pix.h:593
@ L_SELECT_HEIGHT
Definition pix.h:594
@ L_ADD_BELOW
Definition pix.h:1003
@ L_COPY
Definition pix.h:505
@ L_CLONE
Definition pix.h:506
@ L_INSERT
Definition pix.h:504
#define PIX_SET
Definition pix.h:448
struct Box ** box
Definition bmf.h:47