Leptonica 1.82.0
Image processing and image analysis suite
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
74/*---------------------------------------------------------------------*
75 * Boxa and boxaa range selection *
76 *---------------------------------------------------------------------*/
93BOXA *
95 l_int32 first,
96 l_int32 last,
97 l_int32 copyflag)
98{
99l_int32 n, nbox, i;
100BOX *box;
101BOXA *boxad;
102
103 PROCNAME("boxaSelectRange");
104
105 if (!boxas)
106 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
107 if (copyflag != L_COPY && copyflag != L_CLONE)
108 return (BOXA *)ERROR_PTR("invalid copyflag", procName, NULL);
109 if ((n = boxaGetCount(boxas)) == 0) {
110 L_WARNING("boxas is empty\n", procName);
111 return boxaCopy(boxas, copyflag);
112 }
113 first = L_MAX(0, first);
114 if (last < 0) last = n - 1;
115 if (first >= n)
116 return (BOXA *)ERROR_PTR("invalid first", procName, NULL);
117 if (last >= n) {
118 L_WARNING("last = %d is beyond max index = %d; adjusting\n",
119 procName, last, n - 1);
120 last = n - 1;
121 }
122 if (first > last)
123 return (BOXA *)ERROR_PTR("first > last", procName, NULL);
124
125 nbox = last - first + 1;
126 boxad = boxaCreate(nbox);
127 for (i = first; i <= last; i++) {
128 box = boxaGetBox(boxas, i, copyflag);
129 boxaAddBox(boxad, box, L_INSERT);
130 }
131 return boxad;
132}
133
134
151BOXAA *
153 l_int32 first,
154 l_int32 last,
155 l_int32 copyflag)
156{
157l_int32 n, nboxa, i;
158BOXA *boxa;
159BOXAA *baad;
160
161 PROCNAME("boxaaSelectRange");
162
163 if (!baas)
164 return (BOXAA *)ERROR_PTR("baas not defined", procName, NULL);
165 if (copyflag != L_COPY && copyflag != L_CLONE)
166 return (BOXAA *)ERROR_PTR("invalid copyflag", procName, NULL);
167 if ((n = boxaaGetCount(baas)) == 0)
168 return (BOXAA *)ERROR_PTR("empty baas", procName, NULL);
169 first = L_MAX(0, first);
170 if (last < 0) last = n - 1;
171 if (first >= n)
172 return (BOXAA *)ERROR_PTR("invalid first", procName, NULL);
173 if (last >= n) {
174 L_WARNING("last = %d is beyond max index = %d; adjusting\n",
175 procName, last, n - 1);
176 last = n - 1;
177 }
178 if (first > last)
179 return (BOXAA *)ERROR_PTR("first > last", procName, NULL);
180
181 nboxa = last - first + 1;
182 baad = boxaaCreate(nboxa);
183 for (i = first; i <= last; i++) {
184 boxa = boxaaGetBoxa(baas, i, copyflag);
185 boxaaAddBoxa(baad, boxa, L_INSERT);
186 }
187 return baad;
188}
189
190
191/*---------------------------------------------------------------------*
192 * Boxa size selection *
193 *---------------------------------------------------------------------*/
219BOXA *
221 l_int32 width,
222 l_int32 height,
223 l_int32 type,
224 l_int32 relation,
225 l_int32 *pchanged)
226{
227BOXA *boxad;
228NUMA *na;
229
230 PROCNAME("boxaSelectBySize");
231
232 if (pchanged) *pchanged = FALSE;
233 if (!boxas)
234 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
235 if (boxaGetCount(boxas) == 0) {
236 L_WARNING("boxas is empty\n", procName);
237 return boxaCopy(boxas, L_COPY);
238 }
239 if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
240 type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
241 return (BOXA *)ERROR_PTR("invalid type", procName, NULL);
242 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
243 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
244 return (BOXA *)ERROR_PTR("invalid relation", procName, NULL);
245
246 /* Compute the indicator array for saving components */
247 if ((na =
248 boxaMakeSizeIndicator(boxas, width, height, type, relation)) == NULL)
249 return (BOXA *)ERROR_PTR("na not made", procName, NULL);
250
251 /* Filter to get output */
252 boxad = boxaSelectWithIndicator(boxas, na, pchanged);
253
254 numaDestroy(&na);
255 return boxad;
256}
257
258
282NUMA *
284 l_int32 width,
285 l_int32 height,
286 l_int32 type,
287 l_int32 relation)
288{
289l_int32 i, n, w, h, ival;
290NUMA *na;
291
292 PROCNAME("boxaMakeSizeIndicator");
293
294 if (!boxa)
295 return (NUMA *)ERROR_PTR("boxa not defined", procName, NULL);
296 if ((n = boxaGetCount(boxa)) == 0)
297 return (NUMA *)ERROR_PTR("boxa is empty", procName, NULL);
298 if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
299 type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
300 return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
301 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
302 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
303 return (NUMA *)ERROR_PTR("invalid relation", procName, NULL);
304
305 na = numaCreate(n);
306 for (i = 0; i < n; i++) {
307 ival = 0;
308 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
309 switch (type)
310 {
311 case L_SELECT_WIDTH:
312 if ((relation == L_SELECT_IF_LT && w < width) ||
313 (relation == L_SELECT_IF_GT && w > width) ||
314 (relation == L_SELECT_IF_LTE && w <= width) ||
315 (relation == L_SELECT_IF_GTE && w >= width))
316 ival = 1;
317 break;
318 case L_SELECT_HEIGHT:
319 if ((relation == L_SELECT_IF_LT && h < height) ||
320 (relation == L_SELECT_IF_GT && h > height) ||
321 (relation == L_SELECT_IF_LTE && h <= height) ||
322 (relation == L_SELECT_IF_GTE && h >= height))
323 ival = 1;
324 break;
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 case L_SELECT_IF_BOTH:
333 if (((relation == L_SELECT_IF_LT) && (w < width && h < height)) ||
334 ((relation == L_SELECT_IF_GT) && (w > width && h > height)) ||
335 ((relation == L_SELECT_IF_LTE) && (w <= width && h <= height)) ||
336 ((relation == L_SELECT_IF_GTE) && (w >= width && h >= height)))
337 ival = 1;
338 break;
339 default:
340 L_WARNING("can't get here!\n", procName);
341 break;
342 }
343 numaAddNumber(na, ival);
344 }
345
346 return na;
347}
348
349
369BOXA *
371 l_int32 area,
372 l_int32 relation,
373 l_int32 *pchanged)
374{
375BOXA *boxad;
376NUMA *na;
377
378 PROCNAME("boxaSelectByArea");
379
380 if (pchanged) *pchanged = FALSE;
381 if (!boxas)
382 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
383 if (boxaGetCount(boxas) == 0) {
384 L_WARNING("boxas is empty\n", procName);
385 return boxaCopy(boxas, L_COPY);
386 }
387 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
388 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
389 return (BOXA *)ERROR_PTR("invalid relation", procName, NULL);
390
391 /* Compute the indicator array for saving components */
392 na = boxaMakeAreaIndicator(boxas, area, relation);
393
394 /* Filter to get output */
395 boxad = boxaSelectWithIndicator(boxas, na, pchanged);
396
397 numaDestroy(&na);
398 return boxad;
399}
400
401
419NUMA *
421 l_int32 area,
422 l_int32 relation)
423{
424l_int32 i, n, w, h, ival;
425NUMA *na;
426
427 PROCNAME("boxaMakeAreaIndicator");
428
429 if (!boxa)
430 return (NUMA *)ERROR_PTR("boxa not defined", procName, NULL);
431 if ((n = boxaGetCount(boxa)) == 0)
432 return (NUMA *)ERROR_PTR("boxa is empty", procName, NULL);
433 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
434 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
435 return (NUMA *)ERROR_PTR("invalid relation", procName, NULL);
436
437 na = numaCreate(n);
438 for (i = 0; i < n; i++) {
439 ival = 0;
440 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
441
442 if ((relation == L_SELECT_IF_LT && w * h < area) ||
443 (relation == L_SELECT_IF_GT && w * h > area) ||
444 (relation == L_SELECT_IF_LTE && w * h <= area) ||
445 (relation == L_SELECT_IF_GTE && w * h >= area))
446 ival = 1;
447 numaAddNumber(na, ival);
448 }
449
450 return na;
451}
452
453
473BOXA *
475 l_float32 ratio,
476 l_int32 relation,
477 l_int32 *pchanged)
478{
479BOXA *boxad;
480NUMA *na;
481
482 PROCNAME("boxaSelectByWHRatio");
483
484 if (pchanged) *pchanged = FALSE;
485 if (!boxas)
486 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
487 if (boxaGetCount(boxas) == 0) {
488 L_WARNING("boxas is empty\n", procName);
489 return boxaCopy(boxas, L_COPY);
490 }
491 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
492 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
493 return (BOXA *)ERROR_PTR("invalid relation", procName, NULL);
494
495 /* Compute the indicator array for saving components */
496 na = boxaMakeWHRatioIndicator(boxas, ratio, relation);
497
498 /* Filter to get output */
499 boxad = boxaSelectWithIndicator(boxas, na, pchanged);
500
501 numaDestroy(&na);
502 return boxad;
503}
504
505
523NUMA *
525 l_float32 ratio,
526 l_int32 relation)
527{
528l_int32 i, n, w, h, ival;
529l_float32 whratio;
530NUMA *na;
531
532 PROCNAME("boxaMakeWHRatioIndicator");
533
534 if (!boxa)
535 return (NUMA *)ERROR_PTR("boxa not defined", procName, NULL);
536 if ((n = boxaGetCount(boxa)) == 0)
537 return (NUMA *)ERROR_PTR("boxa is empty", procName, NULL);
538 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
539 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
540 return (NUMA *)ERROR_PTR("invalid relation", procName, NULL);
541
542 na = numaCreate(n);
543 for (i = 0; i < n; i++) {
544 ival = 0;
545 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
546 whratio = (l_float32)w / (l_float32)h;
547
548 if ((relation == L_SELECT_IF_LT && whratio < ratio) ||
549 (relation == L_SELECT_IF_GT && whratio > ratio) ||
550 (relation == L_SELECT_IF_LTE && whratio <= ratio) ||
551 (relation == L_SELECT_IF_GTE && whratio >= ratio))
552 ival = 1;
553 numaAddNumber(na, ival);
554 }
555
556 return na;
557}
558
559
576BOXA *
578 NUMA *na,
579 l_int32 *pchanged)
580{
581l_int32 i, n, ival, nsave;
582BOX *box;
583BOXA *boxad;
584
585 PROCNAME("boxaSelectWithIndicator");
586
587 if (pchanged) *pchanged = FALSE;
588 if (!boxas)
589 return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
590 if (!na)
591 return (BOXA *)ERROR_PTR("na not defined", procName, NULL);
592
593 nsave = 0;
594 n = numaGetCount(na);
595 for (i = 0; i < n; i++) {
596 numaGetIValue(na, i, &ival);
597 if (ival == 1) nsave++;
598 }
599
600 if (nsave == n) {
601 if (pchanged) *pchanged = FALSE;
602 return boxaCopy(boxas, L_COPY);
603 }
604 if (pchanged) *pchanged = TRUE;
605 boxad = boxaCreate(nsave);
606 for (i = 0; i < n; i++) {
607 numaGetIValue(na, i, &ival);
608 if (ival == 0) continue;
609 box = boxaGetBox(boxas, i, L_COPY);
610 boxaAddBox(boxad, box, L_INSERT);
611 }
612
613 return boxad;
614}
615
616
617/*---------------------------------------------------------------------*
618 * Boxa Permutation *
619 *---------------------------------------------------------------------*/
634BOXA *
636{
637l_int32 n;
638NUMA *na;
639BOXA *boxad;
640
641 PROCNAME("boxaPermutePseudorandom");
642
643 if (!boxas)
644 return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
645
646 n = boxaGetCount(boxas);
647 na = numaPseudorandomSequence(n, 0);
648 boxad = boxaSortByIndex(boxas, na);
649 numaDestroy(&na);
650 return boxad;
651}
652
653
675BOXA *
677 BOXA *boxas)
678{
679l_int32 i, n, index;
680
681 PROCNAME("boxaPermuteRandom");
682
683 if (!boxas)
684 return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
685 if (boxad && (boxad != boxas))
686 return (BOXA *)ERROR_PTR("boxad defined but in-place", procName, NULL);
687
688 if (!boxad)
689 boxad = boxaCopy(boxas, L_COPY);
690 if ((n = boxaGetCount(boxad)) == 0)
691 return boxad;
692 index = (l_uint32)rand() % n;
693 index = L_MAX(1, index);
694 boxaSwapBoxes(boxad, 0, index);
695 for (i = 1; i < n; i++) {
696 index = (l_uint32)rand() % n;
697 if (index == i) index--;
698 boxaSwapBoxes(boxad, i, index);
699 }
700
701 return boxad;
702}
703
704
712l_ok
714 l_int32 i,
715 l_int32 j)
716{
717l_int32 n;
718BOX *box;
719
720 PROCNAME("boxaSwapBoxes");
721
722 if (!boxa)
723 return ERROR_INT("boxa not defined", procName, 1);
724 n = boxaGetCount(boxa);
725 if (i < 0 || i >= n)
726 return ERROR_INT("i invalid", procName, 1);
727 if (j < 0 || j >= n)
728 return ERROR_INT("j invalid", procName, 1);
729 if (i == j)
730 return ERROR_INT("i == j", procName, 1);
731
732 box = boxa->box[i];
733 boxa->box[i] = boxa->box[j];
734 boxa->box[j] = box;
735 return 0;
736}
737
738
739/*---------------------------------------------------------------------*
740 * Boxa and Box Conversions *
741 *---------------------------------------------------------------------*/
760PTA *
762 l_int32 ncorners)
763{
764l_int32 i, n;
765BOX *box;
766PTA *pta, *pta1;
767
768 PROCNAME("boxaConvertToPta");
769
770 if (!boxa)
771 return (PTA *)ERROR_PTR("boxa not defined", procName, NULL);
772 if (ncorners != 2 && ncorners != 4)
773 return (PTA *)ERROR_PTR("ncorners not 2 or 4", procName, NULL);
774
775 n = boxaGetCount(boxa);
776 if ((pta = ptaCreate(n)) == NULL)
777 return (PTA *)ERROR_PTR("pta not made", procName, NULL);
778 for (i = 0; i < n; i++) {
779 box = boxaGetBox(boxa, i, L_COPY);
780 pta1 = boxConvertToPta(box, ncorners);
781 ptaJoin(pta, pta1, 0, -1);
782 boxDestroy(&box);
783 ptaDestroy(&pta1);
784 }
785
786 return pta;
787}
788
789
805BOXA *
807 l_int32 ncorners)
808{
809l_int32 i, n, nbox, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
810BOX *box;
811BOXA *boxa;
812
813 PROCNAME("ptaConvertToBoxa");
814
815 if (!pta)
816 return (BOXA *)ERROR_PTR("pta not defined", procName, NULL);
817 if (ncorners != 2 && ncorners != 4)
818 return (BOXA *)ERROR_PTR("ncorners not 2 or 4", procName, NULL);
819 n = ptaGetCount(pta);
820 if (n % ncorners != 0)
821 return (BOXA *)ERROR_PTR("size % ncorners != 0", procName, NULL);
822 nbox = n / ncorners;
823 if ((boxa = boxaCreate(nbox)) == NULL)
824 return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
825 for (i = 0; i < n; i += ncorners) {
826 ptaGetIPt(pta, i, &x1, &y1);
827 ptaGetIPt(pta, i + 1, &x2, &y2);
828 if (ncorners == 2) {
829 box = boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
830 boxaAddBox(boxa, box, L_INSERT);
831 continue;
832 }
833 ptaGetIPt(pta, i + 2, &x3, &y3);
834 ptaGetIPt(pta, i + 3, &x4, &y4);
835 x = L_MIN(x1, x3);
836 y = L_MIN(y1, y2);
837 xmax = L_MAX(x2, x4);
838 ymax = L_MAX(y3, y4);
839 box = boxCreate(x, y, xmax - x + 1, ymax - y + 1);
840 boxaAddBox(boxa, box, L_INSERT);
841 }
842
843 return boxa;
844}
845
846
860PTA *
862 l_int32 ncorners)
863{
864l_int32 x, y, w, h;
865PTA *pta;
866
867 PROCNAME("boxConvertToPta");
868
869 if (!box)
870 return (PTA *)ERROR_PTR("box not defined", procName, NULL);
871 if (ncorners != 2 && ncorners != 4)
872 return (PTA *)ERROR_PTR("ncorners not 2 or 4", procName, NULL);
873
874 if ((pta = ptaCreate(ncorners)) == NULL)
875 return (PTA *)ERROR_PTR("pta not made", procName, NULL);
876 boxGetGeometry(box, &x, &y, &w, &h);
877 ptaAddPt(pta, x, y);
878 if (ncorners == 2) {
879 ptaAddPt(pta, x + w - 1, y + h - 1);
880 } else {
881 ptaAddPt(pta, x + w - 1, y);
882 ptaAddPt(pta, x, y + h - 1);
883 ptaAddPt(pta, x + w - 1, y + h - 1);
884 }
885
886 return pta;
887}
888
889
902BOX *
904{
905l_int32 n, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
906
907 PROCNAME("ptaConvertToBox");
908
909 if (!pta)
910 return (BOX *)ERROR_PTR("pta not defined", procName, NULL);
911 n = ptaGetCount(pta);
912 ptaGetIPt(pta, 0, &x1, &y1);
913 ptaGetIPt(pta, 1, &x2, &y2);
914 if (n == 2)
915 return boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
916
917 /* 4 corners */
918 ptaGetIPt(pta, 2, &x3, &y3);
919 ptaGetIPt(pta, 3, &x4, &y4);
920 x = L_MIN(x1, x3);
921 y = L_MIN(y1, y2);
922 xmax = L_MAX(x2, x4);
923 ymax = L_MAX(y3, y4);
924 return boxCreate(x, y, xmax - x + 1, ymax - y + 1);
925}
926
927
928/*---------------------------------------------------------------------*
929 * Miscellaneous Boxa functions *
930 *---------------------------------------------------------------------*/
952l_ok
954 l_int32 *pw,
955 l_int32 *ph,
956 BOX **pbox)
957{
958l_int32 i, n, x, y, w, h, xmax, ymax, xmin, ymin, found;
959
960 PROCNAME("boxaGetExtent");
961
962 if (!pw && !ph && !pbox)
963 return ERROR_INT("no ptrs defined", procName, 1);
964 if (pw) *pw = 0;
965 if (ph) *ph = 0;
966 if (pbox) *pbox = NULL;
967 if (!boxa)
968 return ERROR_INT("boxa not defined", procName, 1);
969
970 n = boxaGetCount(boxa);
971 xmax = ymax = 0;
972 xmin = ymin = 100000000;
973 found = FALSE;
974 for (i = 0; i < n; i++) {
975 boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
976 if (w <= 0 || h <= 0)
977 continue;
978 found = TRUE;
979 xmin = L_MIN(xmin, x);
980 ymin = L_MIN(ymin, y);
981 xmax = L_MAX(xmax, x + w);
982 ymax = L_MAX(ymax, y + h);
983 }
984 if (found == FALSE) /* no valid boxes in boxa */
985 xmin = ymin = 0;
986 if (pw) *pw = xmax;
987 if (ph) *ph = ymax;
988 if (pbox)
989 *pbox = boxCreate(xmin, ymin, xmax - xmin, ymax - ymin);
990
991 return 0;
992}
993
994
1018l_ok
1020 l_int32 wc,
1021 l_int32 hc,
1022 l_int32 exactflag,
1023 l_float32 *pfract)
1024{
1025l_int32 i, n, x, y, w, h, sum;
1026BOX *box, *boxc;
1027PIX *pixt;
1028
1029 PROCNAME("boxaGetCoverage");
1030
1031 if (!pfract)
1032 return ERROR_INT("&fract not defined", procName, 1);
1033 *pfract = 0.0;
1034 if (!boxa)
1035 return ERROR_INT("boxa not defined", procName, 1);
1036
1037 n = boxaGetCount(boxa);
1038 if (n == 0)
1039 return ERROR_INT("no boxes in boxa", procName, 1);
1040
1041 if (exactflag == 0) { /* quick and dirty */
1042 sum = 0;
1043 for (i = 0; i < n; i++) {
1044 box = boxaGetBox(boxa, i, L_CLONE);
1045 if ((boxc = boxClipToRectangle(box, wc, hc)) != NULL) {
1046 boxGetGeometry(boxc, NULL, NULL, &w, &h);
1047 sum += w * h;
1048 boxDestroy(&boxc);
1049 }
1050 boxDestroy(&box);
1051 }
1052 } else { /* slower and exact */
1053 pixt = pixCreate(wc, hc, 1);
1054 for (i = 0; i < n; i++) {
1055 box = boxaGetBox(boxa, i, L_CLONE);
1056 boxGetGeometry(box, &x, &y, &w, &h);
1057 pixRasterop(pixt, x, y, w, h, PIX_SET, NULL, 0, 0);
1058 boxDestroy(&box);
1059 }
1060 pixCountPixels(pixt, &sum, NULL);
1061 pixDestroy(&pixt);
1062 }
1063
1064 *pfract = (l_float32)sum / (l_float32)(wc * hc);
1065 return 0;
1066}
1067
1068
1079l_ok
1081 l_int32 *pminw,
1082 l_int32 *pminh,
1083 l_int32 *pmaxw,
1084 l_int32 *pmaxh)
1085{
1086l_int32 minw, minh, maxw, maxh, minbw, minbh, maxbw, maxbh, i, n;
1087BOXA *boxa;
1088
1089 PROCNAME("boxaaSizeRange");
1090
1091 if (!pminw && !pmaxw && !pminh && !pmaxh)
1092 return ERROR_INT("no data can be returned", procName, 1);
1093 if (pminw) *pminw = 0;
1094 if (pminh) *pminh = 0;
1095 if (pmaxw) *pmaxw = 0;
1096 if (pmaxh) *pmaxh = 0;
1097 if (!baa)
1098 return ERROR_INT("baa not defined", procName, 1);
1099
1100 minw = minh = 100000000;
1101 maxw = maxh = 0;
1102 n = boxaaGetCount(baa);
1103 for (i = 0; i < n; i++) {
1104 boxa = boxaaGetBoxa(baa, i, L_CLONE);
1105 boxaSizeRange(boxa, &minbw, &minbh, &maxbw, &maxbh);
1106 if (minbw < minw)
1107 minw = minbw;
1108 if (minbh < minh)
1109 minh = minbh;
1110 if (maxbw > maxw)
1111 maxw = maxbw;
1112 if (maxbh > maxh)
1113 maxh = maxbh;
1114 boxaDestroy(&boxa);
1115 }
1116
1117 if (pminw) *pminw = minw;
1118 if (pminh) *pminh = minh;
1119 if (pmaxw) *pmaxw = maxw;
1120 if (pmaxh) *pmaxh = maxh;
1121 return 0;
1122}
1123
1124
1135l_ok
1137 l_int32 *pminw,
1138 l_int32 *pminh,
1139 l_int32 *pmaxw,
1140 l_int32 *pmaxh)
1141{
1142l_int32 minw, minh, maxw, maxh, i, n, w, h;
1143
1144 PROCNAME("boxaSizeRange");
1145
1146 if (!pminw && !pmaxw && !pminh && !pmaxh)
1147 return ERROR_INT("no data can be returned", procName, 1);
1148 if (pminw) *pminw = 0;
1149 if (pminh) *pminh = 0;
1150 if (pmaxw) *pmaxw = 0;
1151 if (pmaxh) *pmaxh = 0;
1152 if (!boxa)
1153 return ERROR_INT("boxa not defined", procName, 1);
1154
1155 minw = minh = 100000000;
1156 maxw = maxh = 0;
1157 n = boxaGetCount(boxa);
1158 for (i = 0; i < n; i++) {
1159 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
1160 if (w < minw)
1161 minw = w;
1162 if (h < minh)
1163 minh = h;
1164 if (w > maxw)
1165 maxw = w;
1166 if (h > maxh)
1167 maxh = h;
1168 }
1169
1170 if (pminw) *pminw = minw;
1171 if (pminh) *pminh = minh;
1172 if (pmaxw) *pmaxw = maxw;
1173 if (pmaxh) *pmaxh = maxh;
1174 return 0;
1175}
1176
1177
1188l_ok
1190 l_int32 *pminx,
1191 l_int32 *pminy,
1192 l_int32 *pmaxx,
1193 l_int32 *pmaxy)
1194{
1195l_int32 minx, miny, maxx, maxy, i, n, x, y;
1196
1197 PROCNAME("boxaLocationRange");
1198
1199 if (!pminx && !pminy && !pmaxx && !pmaxy)
1200 return ERROR_INT("no data can be returned", procName, 1);
1201 if (pminx) *pminx = 0;
1202 if (pminy) *pminy = 0;
1203 if (pmaxx) *pmaxx = 0;
1204 if (pmaxy) *pmaxy = 0;
1205 if (!boxa)
1206 return ERROR_INT("boxa not defined", procName, 1);
1207
1208 minx = miny = 100000000;
1209 maxx = maxy = 0;
1210 n = boxaGetCount(boxa);
1211 for (i = 0; i < n; i++) {
1212 boxaGetBoxGeometry(boxa, i, &x, &y, NULL, NULL);
1213 if (x < minx)
1214 minx = x;
1215 if (y < miny)
1216 miny = y;
1217 if (x > maxx)
1218 maxx = x;
1219 if (y > maxy)
1220 maxy = y;
1221 }
1222
1223 if (pminx) *pminx = minx;
1224 if (pminy) *pminy = miny;
1225 if (pmaxx) *pmaxx = maxx;
1226 if (pmaxy) *pmaxy = maxy;
1227
1228 return 0;
1229}
1230
1231
1240l_ok
1242 NUMA **pnaw,
1243 NUMA **pnah)
1244{
1245l_int32 i, n, w, h;
1246BOX *box;
1247
1248 PROCNAME("boxaGetSizes");
1249
1250 if (pnaw) *pnaw = NULL;
1251 if (pnah) *pnah = NULL;
1252 if (!pnaw && !pnah)
1253 return ERROR_INT("no output requested", procName, 1);
1254 if (!boxa)
1255 return ERROR_INT("boxa not defined", procName, 1);
1256
1257 n = boxaGetValidCount(boxa);
1258 if (pnaw) *pnaw = numaCreate(n);
1259 if (pnah) *pnah = numaCreate(n);
1260 for (i = 0; i < n; i++) {
1261 box = boxaGetValidBox(boxa, i, L_COPY);
1262 if (box) {
1263 boxGetGeometry(box, NULL, NULL, &w, &h);
1264 if (pnaw) numaAddNumber(*pnaw, w);
1265 if (pnah) numaAddNumber(*pnah, h);
1266 boxDestroy(&box);
1267 }
1268 }
1269
1270 return 0;
1271}
1272
1273
1286l_ok
1288 l_int32 *parea)
1289{
1290l_int32 i, n, w, h;
1291
1292 PROCNAME("boxaGetArea");
1293
1294 if (!parea)
1295 return ERROR_INT("&area not defined", procName, 1);
1296 *parea = 0;
1297 if (!boxa)
1298 return ERROR_INT("boxa not defined", procName, 1);
1299
1300 n = boxaGetCount(boxa);
1301 for (i = 0; i < n; i++) {
1302 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
1303 *parea += w * h;
1304 }
1305 return 0;
1306}
1307
1308
1336PIX *
1338 PIXA *pixa,
1339 l_int32 first,
1340 l_int32 last,
1341 l_int32 maxwidth,
1342 l_int32 linewidth,
1343 l_float32 scalefactor,
1344 l_int32 background,
1345 l_int32 spacing,
1346 l_int32 border)
1347{
1348char buf[32];
1349l_int32 i, n, npix, w, h, fontsize;
1350L_BMF *bmf;
1351BOX *box;
1352BOXA *boxa;
1353PIX *pix1, *pix2, *pixd;
1354PIXA *pixat;
1355
1356 PROCNAME("boxaDisplayTiled");
1357
1358 if (!boxas)
1359 return (PIX *)ERROR_PTR("boxas not defined", procName, NULL);
1360
1361 boxa = boxaSaveValid(boxas, L_COPY);
1362 n = boxaGetCount(boxa);
1363 if (pixa) {
1364 npix = pixaGetCount(pixa);
1365 if (n != npix) {
1366 boxaDestroy(&boxa);
1367 return (PIX *)ERROR_PTR("boxa and pixa counts differ",
1368 procName, NULL);
1369 }
1370 }
1371 first = L_MAX(0, first);
1372 if (last < 0) last = n - 1;
1373 if (first >= n) {
1374 boxaDestroy(&boxa);
1375 return (PIX *)ERROR_PTR("invalid first", procName, NULL);
1376 }
1377 if (last >= n) {
1378 L_WARNING("last = %d is beyond max index = %d; adjusting\n",
1379 procName, last, n - 1);
1380 last = n - 1;
1381 }
1382 if (first > last) {
1383 boxaDestroy(&boxa);
1384 return (PIX *)ERROR_PTR("first > last", procName, NULL);
1385 }
1386
1387 /* Because the bitmap font will be reduced when tiled, choose the
1388 * font size inversely with the scale factor. */
1389 if (scalefactor > 0.8)
1390 fontsize = 6;
1391 else if (scalefactor > 0.6)
1392 fontsize = 10;
1393 else if (scalefactor > 0.4)
1394 fontsize = 14;
1395 else if (scalefactor > 0.3)
1396 fontsize = 18;
1397 else fontsize = 20;
1398 bmf = bmfCreate(NULL, fontsize);
1399
1400 pixat = pixaCreate(n);
1401 boxaGetExtent(boxa, &w, &h, NULL);
1402 for (i = first; i <= last; i++) {
1403 box = boxaGetBox(boxa, i, L_CLONE);
1404 if (!pixa) {
1405 pix1 = pixCreate(w, h, 32);
1406 pixSetAll(pix1);
1407 } else {
1408 pix1 = pixaGetPix(pixa, i, L_COPY);
1409 }
1410 pixSetBorderVal(pix1, 0, 0, 0, 2, 0x0000ff00);
1411 snprintf(buf, sizeof(buf), "%d", i);
1412 pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0x00ff0000,
1413 L_ADD_BELOW, NULL);
1414 pixDestroy(&pix1);
1415 pixRenderBoxArb(pix2, box, linewidth, 255, 0, 0);
1416 pixaAddPix(pixat, pix2, L_INSERT);
1417 boxDestroy(&box);
1418 }
1419 bmfDestroy(&bmf);
1420 boxaDestroy(&boxa);
1421
1422 pixd = pixaDisplayTiledInRows(pixat, 32, maxwidth, scalefactor, background,
1423 spacing, border);
1424 pixaDestroy(&pixat);
1425 return pixd;
1426}
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:169
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:117
BOX * boxaGetValidBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetValidBox()
Definition: boxbasic.c:818
l_int32 boxaGetValidCount(BOXA *boxa)
boxaGetValidCount()
Definition: boxbasic.c:751
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_int32 boxaaGetCount(BOXAA *baa)
boxaaGetCount()
Definition: boxbasic.c:1454
BOXAA * boxaaCreate(l_int32 n)
boxaaCreate()
Definition: boxbasic.c:1244
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
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1728
BOXA * boxaSortByIndex(BOXA *boxas, NUMA *naindex)
boxaSortByIndex()
Definition: boxfunc2.c:838
BOXA * boxaPermutePseudorandom(BOXA *boxas)
boxaPermutePseudorandom()
Definition: boxfunc4.c:635
l_ok boxaSwapBoxes(BOXA *boxa, l_int32 i, l_int32 j)
boxaSwapBoxes()
Definition: boxfunc4.c:713
NUMA * boxaMakeWHRatioIndicator(BOXA *boxa, l_float32 ratio, l_int32 relation)
boxaMakeWHRatioIndicator()
Definition: boxfunc4.c:524
l_ok boxaaSizeRange(BOXAA *baa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
boxaaSizeRange()
Definition: boxfunc4.c:1080
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:1337
l_ok boxaGetSizes(BOXA *boxa, NUMA **pnaw, NUMA **pnah)
boxaGetSizes()
Definition: boxfunc4.c:1241
NUMA * boxaMakeSizeIndicator(BOXA *boxa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation)
boxaMakeSizeIndicator()
Definition: boxfunc4.c:283
BOXA * boxaSelectRange(BOXA *boxas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaSelectRange()
Definition: boxfunc4.c:94
l_ok boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition: boxfunc4.c:1287
BOXA * boxaSelectBySize(BOXA *boxas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
boxaSelectBySize()
Definition: boxfunc4.c:220
PTA * boxConvertToPta(BOX *box, l_int32 ncorners)
boxConvertToPta()
Definition: boxfunc4.c:861
BOXA * boxaPermuteRandom(BOXA *boxad, BOXA *boxas)
boxaPermuteRandom()
Definition: boxfunc4.c:676
NUMA * boxaMakeAreaIndicator(BOXA *boxa, l_int32 area, l_int32 relation)
boxaMakeAreaIndicator()
Definition: boxfunc4.c:420
BOXA * boxaSelectByWHRatio(BOXA *boxas, l_float32 ratio, l_int32 relation, l_int32 *pchanged)
boxaSelectByWHRatio()
Definition: boxfunc4.c:474
l_ok boxaSizeRange(BOXA *boxa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
boxaSizeRange()
Definition: boxfunc4.c:1136
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:953
PTA * boxaConvertToPta(BOXA *boxa, l_int32 ncorners)
boxaConvertToPta()
Definition: boxfunc4.c:761
BOXA * boxaSelectByArea(BOXA *boxas, l_int32 area, l_int32 relation, l_int32 *pchanged)
boxaSelectByArea()
Definition: boxfunc4.c:370
BOX * ptaConvertToBox(PTA *pta)
ptaConvertToBox()
Definition: boxfunc4.c:903
BOXA * ptaConvertToBoxa(PTA *pta, l_int32 ncorners)
ptaConvertToBoxa()
Definition: boxfunc4.c:806
l_ok boxaGetCoverage(BOXA *boxa, l_int32 wc, l_int32 hc, l_int32 exactflag, l_float32 *pfract)
boxaGetCoverage()
Definition: boxfunc4.c:1019
BOXA * boxaSelectWithIndicator(BOXA *boxas, NUMA *na, l_int32 *pchanged)
boxaSelectWithIndicator()
Definition: boxfunc4.c:577
l_ok boxaLocationRange(BOXA *boxa, l_int32 *pminx, l_int32 *pminy, l_int32 *pmaxx, l_int32 *pmaxy)
boxaLocationRange()
Definition: boxfunc4.c:1189
BOXAA * boxaaSelectRange(BOXAA *baas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaaSelectRange()
Definition: boxfunc4.c:152
l_ok pixRenderBoxArb(PIX *pix, BOX *box, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxArb()
Definition: graphics.c:1655
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
NUMA * numaPseudorandomSequence(l_int32 size, l_int32 seed)
numaPseudorandomSequence()
Definition: numafunc1.c:3254
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 pixSetBorderVal(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixSetBorderVal()
Definition: pix2.c:1563
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1937
@ L_SELECT_IF_LTE
Definition: pix.h:784
@ L_SELECT_IF_LT
Definition: pix.h:782
@ L_SELECT_IF_GT
Definition: pix.h:783
@ L_SELECT_IF_GTE
Definition: pix.h:785
@ L_SELECT_IF_BOTH
Definition: pix.h:806
@ L_SELECT_IF_EITHER
Definition: pix.h:804
@ L_SELECT_WIDTH
Definition: pix.h:800
@ L_SELECT_HEIGHT
Definition: pix.h:801
@ L_ADD_BELOW
Definition: pix.h:1210
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
#define PIX_SET
Definition: pix.h:334
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
PIX * pixaDisplayTiledInRows(PIXA *pixa, l_int32 outdepth, l_int32 maxwidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledInRows()
Definition: pixafunc2.c:746
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
l_ok ptaJoin(PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend)
ptaJoin()
Definition: ptafunc1.c:167
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:204
Definition: pix.h:481
Definition: pix.h:492
struct Box ** box
Definition: pix.h:496
Definition: pix.h:502
Definition: bmf.h:47
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120