Leptonica 1.84.1
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 ptaGetIPt(pta, 0, &x1, &y1);
882 ptaGetIPt(pta, 1, &x2, &y2);
883 if (n == 2)
884 return boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
885
886 /* 4 corners */
887 ptaGetIPt(pta, 2, &x3, &y3);
888 ptaGetIPt(pta, 3, &x4, &y4);
889 x = L_MIN(x1, x3);
890 y = L_MIN(y1, y2);
891 xmax = L_MAX(x2, x4);
892 ymax = L_MAX(y3, y4);
893 return boxCreate(x, y, xmax - x + 1, ymax - y + 1);
894}
895
896
897/*---------------------------------------------------------------------*
898 * Miscellaneous Boxa functions *
899 *---------------------------------------------------------------------*/
921l_ok
923 l_int32 *pw,
924 l_int32 *ph,
925 BOX **pbox)
926{
927l_int32 i, n, x, y, w, h, xmax, ymax, xmin, ymin, found;
928
929 if (!pw && !ph && !pbox)
930 return ERROR_INT("no ptrs defined", __func__, 1);
931 if (pw) *pw = 0;
932 if (ph) *ph = 0;
933 if (pbox) *pbox = NULL;
934 if (!boxa)
935 return ERROR_INT("boxa not defined", __func__, 1);
936
937 n = boxaGetCount(boxa);
938 xmax = ymax = 0;
939 xmin = ymin = 100000000;
940 found = FALSE;
941 for (i = 0; i < n; i++) {
942 boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
943 if (w <= 0 || h <= 0)
944 continue;
945 found = TRUE;
946 xmin = L_MIN(xmin, x);
947 ymin = L_MIN(ymin, y);
948 xmax = L_MAX(xmax, x + w);
949 ymax = L_MAX(ymax, y + h);
950 }
951 if (found == FALSE) /* no valid boxes in boxa */
952 xmin = ymin = 0;
953 if (pw) *pw = xmax;
954 if (ph) *ph = ymax;
955 if (pbox)
956 *pbox = boxCreate(xmin, ymin, xmax - xmin, ymax - ymin);
957
958 return 0;
959}
960
961
985l_ok
987 l_int32 wc,
988 l_int32 hc,
989 l_int32 exactflag,
990 l_float32 *pfract)
991{
992l_int32 i, n, x, y, w, h, sum;
993BOX *box, *boxc;
994PIX *pixt;
995
996 if (!pfract)
997 return ERROR_INT("&fract not defined", __func__, 1);
998 *pfract = 0.0;
999 if (!boxa)
1000 return ERROR_INT("boxa not defined", __func__, 1);
1001
1002 n = boxaGetCount(boxa);
1003 if (n == 0)
1004 return ERROR_INT("no boxes in boxa", __func__, 1);
1005
1006 if (exactflag == 0) { /* quick and dirty */
1007 sum = 0;
1008 for (i = 0; i < n; i++) {
1009 box = boxaGetBox(boxa, i, L_CLONE);
1010 if ((boxc = boxClipToRectangle(box, wc, hc)) != NULL) {
1011 boxGetGeometry(boxc, NULL, NULL, &w, &h);
1012 sum += w * h;
1013 boxDestroy(&boxc);
1014 }
1015 boxDestroy(&box);
1016 }
1017 } else { /* slower and exact */
1018 pixt = pixCreate(wc, hc, 1);
1019 for (i = 0; i < n; i++) {
1020 box = boxaGetBox(boxa, i, L_CLONE);
1021 boxGetGeometry(box, &x, &y, &w, &h);
1022 pixRasterop(pixt, x, y, w, h, PIX_SET, NULL, 0, 0);
1023 boxDestroy(&box);
1024 }
1025 pixCountPixels(pixt, &sum, NULL);
1026 pixDestroy(&pixt);
1027 }
1028
1029 *pfract = (l_float32)sum / (l_float32)(wc * hc);
1030 return 0;
1031}
1032
1033
1044l_ok
1046 l_int32 *pminw,
1047 l_int32 *pminh,
1048 l_int32 *pmaxw,
1049 l_int32 *pmaxh)
1050{
1051l_int32 minw, minh, maxw, maxh, minbw, minbh, maxbw, maxbh, i, n;
1052BOXA *boxa;
1053
1054 if (!pminw && !pmaxw && !pminh && !pmaxh)
1055 return ERROR_INT("no data can be returned", __func__, 1);
1056 if (pminw) *pminw = 0;
1057 if (pminh) *pminh = 0;
1058 if (pmaxw) *pmaxw = 0;
1059 if (pmaxh) *pmaxh = 0;
1060 if (!baa)
1061 return ERROR_INT("baa not defined", __func__, 1);
1062
1063 minw = minh = 100000000;
1064 maxw = maxh = 0;
1065 n = boxaaGetCount(baa);
1066 for (i = 0; i < n; i++) {
1067 boxa = boxaaGetBoxa(baa, i, L_CLONE);
1068 boxaSizeRange(boxa, &minbw, &minbh, &maxbw, &maxbh);
1069 if (minbw < minw)
1070 minw = minbw;
1071 if (minbh < minh)
1072 minh = minbh;
1073 if (maxbw > maxw)
1074 maxw = maxbw;
1075 if (maxbh > maxh)
1076 maxh = maxbh;
1077 boxaDestroy(&boxa);
1078 }
1079
1080 if (pminw) *pminw = minw;
1081 if (pminh) *pminh = minh;
1082 if (pmaxw) *pmaxw = maxw;
1083 if (pmaxh) *pmaxh = maxh;
1084 return 0;
1085}
1086
1087
1098l_ok
1100 l_int32 *pminw,
1101 l_int32 *pminh,
1102 l_int32 *pmaxw,
1103 l_int32 *pmaxh)
1104{
1105l_int32 minw, minh, maxw, maxh, i, n, w, h;
1106
1107 if (!pminw && !pmaxw && !pminh && !pmaxh)
1108 return ERROR_INT("no data can be returned", __func__, 1);
1109 if (pminw) *pminw = 0;
1110 if (pminh) *pminh = 0;
1111 if (pmaxw) *pmaxw = 0;
1112 if (pmaxh) *pmaxh = 0;
1113 if (!boxa)
1114 return ERROR_INT("boxa not defined", __func__, 1);
1115
1116 minw = minh = 100000000;
1117 maxw = maxh = 0;
1118 n = boxaGetCount(boxa);
1119 for (i = 0; i < n; i++) {
1120 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
1121 if (w < minw)
1122 minw = w;
1123 if (h < minh)
1124 minh = h;
1125 if (w > maxw)
1126 maxw = w;
1127 if (h > maxh)
1128 maxh = h;
1129 }
1130
1131 if (pminw) *pminw = minw;
1132 if (pminh) *pminh = minh;
1133 if (pmaxw) *pmaxw = maxw;
1134 if (pmaxh) *pmaxh = maxh;
1135 return 0;
1136}
1137
1138
1149l_ok
1151 l_int32 *pminx,
1152 l_int32 *pminy,
1153 l_int32 *pmaxx,
1154 l_int32 *pmaxy)
1155{
1156l_int32 minx, miny, maxx, maxy, i, n, x, y;
1157
1158 if (!pminx && !pminy && !pmaxx && !pmaxy)
1159 return ERROR_INT("no data can be returned", __func__, 1);
1160 if (pminx) *pminx = 0;
1161 if (pminy) *pminy = 0;
1162 if (pmaxx) *pmaxx = 0;
1163 if (pmaxy) *pmaxy = 0;
1164 if (!boxa)
1165 return ERROR_INT("boxa not defined", __func__, 1);
1166
1167 minx = miny = 100000000;
1168 maxx = maxy = 0;
1169 n = boxaGetCount(boxa);
1170 for (i = 0; i < n; i++) {
1171 boxaGetBoxGeometry(boxa, i, &x, &y, NULL, NULL);
1172 if (x < minx)
1173 minx = x;
1174 if (y < miny)
1175 miny = y;
1176 if (x > maxx)
1177 maxx = x;
1178 if (y > maxy)
1179 maxy = y;
1180 }
1181
1182 if (pminx) *pminx = minx;
1183 if (pminy) *pminy = miny;
1184 if (pmaxx) *pmaxx = maxx;
1185 if (pmaxy) *pmaxy = maxy;
1186
1187 return 0;
1188}
1189
1190
1199l_ok
1201 NUMA **pnaw,
1202 NUMA **pnah)
1203{
1204l_int32 i, n, w, h;
1205BOX *box;
1206
1207 if (pnaw) *pnaw = NULL;
1208 if (pnah) *pnah = NULL;
1209 if (!pnaw && !pnah)
1210 return ERROR_INT("no output requested", __func__, 1);
1211 if (!boxa)
1212 return ERROR_INT("boxa not defined", __func__, 1);
1213
1214 n = boxaGetValidCount(boxa);
1215 if (pnaw) *pnaw = numaCreate(n);
1216 if (pnah) *pnah = numaCreate(n);
1217 for (i = 0; i < n; i++) {
1218 box = boxaGetValidBox(boxa, i, L_COPY);
1219 if (box) {
1220 boxGetGeometry(box, NULL, NULL, &w, &h);
1221 if (pnaw) numaAddNumber(*pnaw, w);
1222 if (pnah) numaAddNumber(*pnah, h);
1223 boxDestroy(&box);
1224 }
1225 }
1226
1227 return 0;
1228}
1229
1230
1243l_ok
1245 l_int32 *parea)
1246{
1247l_int32 i, n, w, h;
1248
1249 if (!parea)
1250 return ERROR_INT("&area not defined", __func__, 1);
1251 *parea = 0;
1252 if (!boxa)
1253 return ERROR_INT("boxa not defined", __func__, 1);
1254
1255 n = boxaGetCount(boxa);
1256 for (i = 0; i < n; i++) {
1257 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
1258 *parea += w * h;
1259 }
1260 return 0;
1261}
1262
1263
1291PIX *
1293 PIXA *pixa,
1294 l_int32 first,
1295 l_int32 last,
1296 l_int32 maxwidth,
1297 l_int32 linewidth,
1298 l_float32 scalefactor,
1299 l_int32 background,
1300 l_int32 spacing,
1301 l_int32 border)
1302{
1303char buf[32];
1304l_int32 i, n, npix, w, h, fontsize;
1305L_BMF *bmf;
1306BOX *box;
1307BOXA *boxa;
1308PIX *pix1, *pix2, *pixd;
1309PIXA *pixat;
1310
1311 if (!boxas)
1312 return (PIX *)ERROR_PTR("boxas not defined", __func__, NULL);
1313
1314 boxa = boxaSaveValid(boxas, L_COPY);
1315 n = boxaGetCount(boxa);
1316 if (pixa) {
1317 npix = pixaGetCount(pixa);
1318 if (n != npix) {
1319 boxaDestroy(&boxa);
1320 return (PIX *)ERROR_PTR("boxa and pixa counts differ",
1321 __func__, NULL);
1322 }
1323 }
1324 first = L_MAX(0, first);
1325 if (last < 0) last = n - 1;
1326 if (first >= n) {
1327 boxaDestroy(&boxa);
1328 return (PIX *)ERROR_PTR("invalid first", __func__, NULL);
1329 }
1330 if (last >= n) {
1331 L_WARNING("last = %d is beyond max index = %d; adjusting\n",
1332 __func__, last, n - 1);
1333 last = n - 1;
1334 }
1335 if (first > last) {
1336 boxaDestroy(&boxa);
1337 return (PIX *)ERROR_PTR("first > last", __func__, NULL);
1338 }
1339
1340 /* Because the bitmap font will be reduced when tiled, choose the
1341 * font size inversely with the scale factor. */
1342 if (scalefactor > 0.8)
1343 fontsize = 6;
1344 else if (scalefactor > 0.6)
1345 fontsize = 10;
1346 else if (scalefactor > 0.4)
1347 fontsize = 14;
1348 else if (scalefactor > 0.3)
1349 fontsize = 18;
1350 else fontsize = 20;
1351 bmf = bmfCreate(NULL, fontsize);
1352
1353 pixat = pixaCreate(n);
1354 boxaGetExtent(boxa, &w, &h, NULL);
1355 for (i = first; i <= last; i++) {
1356 box = boxaGetBox(boxa, i, L_CLONE);
1357 if (!pixa) {
1358 pix1 = pixCreate(w, h, 32);
1359 pixSetAll(pix1);
1360 } else {
1361 pix1 = pixaGetPix(pixa, i, L_COPY);
1362 }
1363 pixSetBorderVal(pix1, 0, 0, 0, 2, 0x0000ff00);
1364 snprintf(buf, sizeof(buf), "%d", i);
1365 pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0x00ff0000,
1366 L_ADD_BELOW, NULL);
1367 pixDestroy(&pix1);
1368 pixRenderBoxArb(pix2, box, linewidth, 255, 0, 0);
1369 pixaAddPix(pixat, pix2, L_INSERT);
1370 boxDestroy(&box);
1371 }
1372 bmfDestroy(&bmf);
1373 boxaDestroy(&boxa);
1374
1375 pixd = pixaDisplayTiledInRows(pixat, 32, maxwidth, scalefactor, background,
1376 spacing, border);
1377 pixaDestroy(&pixat);
1378 return pixd;
1379}
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:1045
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:1292
l_ok boxaGetSizes(BOXA *boxa, NUMA **pnaw, NUMA **pnah)
boxaGetSizes()
Definition boxfunc4.c:1200
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:1244
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:1099
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition boxfunc4.c:922
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:986
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:1150
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