Leptonica  1.77.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 #include <math.h>
68 #include "allheaders.h"
69 
70 
71 /*---------------------------------------------------------------------*
72  * Boxa and boxaa range selection *
73  *---------------------------------------------------------------------*/
90 BOXA *
92  l_int32 first,
93  l_int32 last,
94  l_int32 copyflag)
95 {
96 l_int32 n, nbox, i;
97 BOX *box;
98 BOXA *boxad;
99 
100  PROCNAME("boxaSelectRange");
101 
102  if (!boxas)
103  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
104  if (copyflag != L_COPY && copyflag != L_CLONE)
105  return (BOXA *)ERROR_PTR("invalid copyflag", procName, NULL);
106  if ((n = boxaGetCount(boxas)) == 0) {
107  L_WARNING("boxas is empty\n", procName);
108  return boxaCopy(boxas, copyflag);
109  }
110  first = L_MAX(0, first);
111  if (last < 0) last = n - 1;
112  if (first >= n)
113  return (BOXA *)ERROR_PTR("invalid first", procName, NULL);
114  if (last >= n) {
115  L_WARNING("last = %d is beyond max index = %d; adjusting\n",
116  procName, last, n - 1);
117  last = n - 1;
118  }
119  if (first > last)
120  return (BOXA *)ERROR_PTR("first > last", procName, NULL);
121 
122  nbox = last - first + 1;
123  boxad = boxaCreate(nbox);
124  for (i = first; i <= last; i++) {
125  box = boxaGetBox(boxas, i, copyflag);
126  boxaAddBox(boxad, box, L_INSERT);
127  }
128  return boxad;
129 }
130 
131 
148 BOXAA *
150  l_int32 first,
151  l_int32 last,
152  l_int32 copyflag)
153 {
154 l_int32 n, nboxa, i;
155 BOXA *boxa;
156 BOXAA *baad;
157 
158  PROCNAME("boxaaSelectRange");
159 
160  if (!baas)
161  return (BOXAA *)ERROR_PTR("baas not defined", procName, NULL);
162  if (copyflag != L_COPY && copyflag != L_CLONE)
163  return (BOXAA *)ERROR_PTR("invalid copyflag", procName, NULL);
164  if ((n = boxaaGetCount(baas)) == 0)
165  return (BOXAA *)ERROR_PTR("empty baas", procName, 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", procName, NULL);
170  if (last >= n) {
171  L_WARNING("last = %d is beyond max index = %d; adjusting\n",
172  procName, last, n - 1);
173  last = n - 1;
174  }
175  if (first > last)
176  return (BOXAA *)ERROR_PTR("first > last", procName, 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  *---------------------------------------------------------------------*/
216 BOXA *
218  l_int32 width,
219  l_int32 height,
220  l_int32 type,
221  l_int32 relation,
222  l_int32 *pchanged)
223 {
224 BOXA *boxad;
225 NUMA *na;
226 
227  PROCNAME("boxaSelectBySize");
228 
229  if (pchanged) *pchanged = FALSE;
230  if (!boxas)
231  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
232  if (boxaGetCount(boxas) == 0) {
233  L_WARNING("boxas is empty\n", procName);
234  return boxaCopy(boxas, L_COPY);
235  }
236  if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
237  type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
238  return (BOXA *)ERROR_PTR("invalid type", procName, NULL);
239  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
240  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
241  return (BOXA *)ERROR_PTR("invalid relation", procName, NULL);
242 
243  /* Compute the indicator array for saving components */
244  if ((na =
245  boxaMakeSizeIndicator(boxas, width, height, type, relation)) == NULL)
246  return (BOXA *)ERROR_PTR("na not made", procName, NULL);
247 
248  /* Filter to get output */
249  boxad = boxaSelectWithIndicator(boxas, na, pchanged);
250 
251  numaDestroy(&na);
252  return boxad;
253 }
254 
255 
279 NUMA *
281  l_int32 width,
282  l_int32 height,
283  l_int32 type,
284  l_int32 relation)
285 {
286 l_int32 i, n, w, h, ival;
287 NUMA *na;
288 
289  PROCNAME("boxaMakeSizeIndicator");
290 
291  if (!boxa)
292  return (NUMA *)ERROR_PTR("boxa not defined", procName, NULL);
293  if ((n = boxaGetCount(boxa)) == 0)
294  return (NUMA *)ERROR_PTR("boxa is empty", procName, NULL);
295  if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
296  type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
297  return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
298  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
299  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
300  return (NUMA *)ERROR_PTR("invalid relation", procName, NULL);
301 
302  na = numaCreate(n);
303  for (i = 0; i < n; i++) {
304  ival = 0;
305  boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
306  switch (type)
307  {
308  case L_SELECT_WIDTH:
309  if ((relation == L_SELECT_IF_LT && w < width) ||
310  (relation == L_SELECT_IF_GT && w > width) ||
311  (relation == L_SELECT_IF_LTE && w <= width) ||
312  (relation == L_SELECT_IF_GTE && w >= width))
313  ival = 1;
314  break;
315  case L_SELECT_HEIGHT:
316  if ((relation == L_SELECT_IF_LT && h < height) ||
317  (relation == L_SELECT_IF_GT && h > height) ||
318  (relation == L_SELECT_IF_LTE && h <= height) ||
319  (relation == L_SELECT_IF_GTE && h >= height))
320  ival = 1;
321  break;
322  case L_SELECT_IF_EITHER:
323  if (((relation == L_SELECT_IF_LT) && (w < width || h < height)) ||
324  ((relation == L_SELECT_IF_GT) && (w > width || h > height)) ||
325  ((relation == L_SELECT_IF_LTE) && (w <= width || h <= height)) ||
326  ((relation == L_SELECT_IF_GTE) && (w >= width || h >= height)))
327  ival = 1;
328  break;
329  case L_SELECT_IF_BOTH:
330  if (((relation == L_SELECT_IF_LT) && (w < width && h < height)) ||
331  ((relation == L_SELECT_IF_GT) && (w > width && h > height)) ||
332  ((relation == L_SELECT_IF_LTE) && (w <= width && h <= height)) ||
333  ((relation == L_SELECT_IF_GTE) && (w >= width && h >= height)))
334  ival = 1;
335  break;
336  default:
337  L_WARNING("can't get here!\n", procName);
338  break;
339  }
340  numaAddNumber(na, ival);
341  }
342 
343  return na;
344 }
345 
346 
366 BOXA *
368  l_int32 area,
369  l_int32 relation,
370  l_int32 *pchanged)
371 {
372 BOXA *boxad;
373 NUMA *na;
374 
375  PROCNAME("boxaSelectByArea");
376 
377  if (pchanged) *pchanged = FALSE;
378  if (!boxas)
379  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
380  if (boxaGetCount(boxas) == 0) {
381  L_WARNING("boxas is empty\n", procName);
382  return boxaCopy(boxas, L_COPY);
383  }
384  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
385  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
386  return (BOXA *)ERROR_PTR("invalid relation", procName, NULL);
387 
388  /* Compute the indicator array for saving components */
389  na = boxaMakeAreaIndicator(boxas, area, relation);
390 
391  /* Filter to get output */
392  boxad = boxaSelectWithIndicator(boxas, na, pchanged);
393 
394  numaDestroy(&na);
395  return boxad;
396 }
397 
398 
416 NUMA *
418  l_int32 area,
419  l_int32 relation)
420 {
421 l_int32 i, n, w, h, ival;
422 NUMA *na;
423 
424  PROCNAME("boxaMakeAreaIndicator");
425 
426  if (!boxa)
427  return (NUMA *)ERROR_PTR("boxa not defined", procName, NULL);
428  if ((n = boxaGetCount(boxa)) == 0)
429  return (NUMA *)ERROR_PTR("boxa is empty", procName, NULL);
430  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
431  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
432  return (NUMA *)ERROR_PTR("invalid relation", procName, NULL);
433 
434  na = numaCreate(n);
435  for (i = 0; i < n; i++) {
436  ival = 0;
437  boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
438 
439  if ((relation == L_SELECT_IF_LT && w * h < area) ||
440  (relation == L_SELECT_IF_GT && w * h > area) ||
441  (relation == L_SELECT_IF_LTE && w * h <= area) ||
442  (relation == L_SELECT_IF_GTE && w * h >= area))
443  ival = 1;
444  numaAddNumber(na, ival);
445  }
446 
447  return na;
448 }
449 
450 
470 BOXA *
472  l_float32 ratio,
473  l_int32 relation,
474  l_int32 *pchanged)
475 {
476 BOXA *boxad;
477 NUMA *na;
478 
479  PROCNAME("boxaSelectByWHRatio");
480 
481  if (pchanged) *pchanged = FALSE;
482  if (!boxas)
483  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
484  if (boxaGetCount(boxas) == 0) {
485  L_WARNING("boxas is empty\n", procName);
486  return boxaCopy(boxas, L_COPY);
487  }
488  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
489  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
490  return (BOXA *)ERROR_PTR("invalid relation", procName, NULL);
491 
492  /* Compute the indicator array for saving components */
493  na = boxaMakeWHRatioIndicator(boxas, ratio, relation);
494 
495  /* Filter to get output */
496  boxad = boxaSelectWithIndicator(boxas, na, pchanged);
497 
498  numaDestroy(&na);
499  return boxad;
500 }
501 
502 
520 NUMA *
522  l_float32 ratio,
523  l_int32 relation)
524 {
525 l_int32 i, n, w, h, ival;
526 l_float32 whratio;
527 NUMA *na;
528 
529  PROCNAME("boxaMakeWHRatioIndicator");
530 
531  if (!boxa)
532  return (NUMA *)ERROR_PTR("boxa not defined", procName, NULL);
533  if ((n = boxaGetCount(boxa)) == 0)
534  return (NUMA *)ERROR_PTR("boxa is empty", procName, NULL);
535  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
536  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
537  return (NUMA *)ERROR_PTR("invalid relation", procName, NULL);
538 
539  na = numaCreate(n);
540  for (i = 0; i < n; i++) {
541  ival = 0;
542  boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
543  whratio = (l_float32)w / (l_float32)h;
544 
545  if ((relation == L_SELECT_IF_LT && whratio < ratio) ||
546  (relation == L_SELECT_IF_GT && whratio > ratio) ||
547  (relation == L_SELECT_IF_LTE && whratio <= ratio) ||
548  (relation == L_SELECT_IF_GTE && whratio >= ratio))
549  ival = 1;
550  numaAddNumber(na, ival);
551  }
552 
553  return na;
554 }
555 
556 
572 BOXA *
574  NUMA *na,
575  l_int32 *pchanged)
576 {
577 l_int32 i, n, ival, nsave;
578 BOX *box;
579 BOXA *boxad;
580 
581  PROCNAME("boxaSelectWithIndicator");
582 
583  if (pchanged) *pchanged = FALSE;
584  if (!boxas)
585  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
586  if (!na)
587  return (BOXA *)ERROR_PTR("na not defined", procName, NULL);
588 
589  nsave = 0;
590  n = numaGetCount(na);
591  for (i = 0; i < n; i++) {
592  numaGetIValue(na, i, &ival);
593  if (ival == 1) nsave++;
594  }
595 
596  if (nsave == n) {
597  if (pchanged) *pchanged = FALSE;
598  return boxaCopy(boxas, L_COPY);
599  }
600  if (pchanged) *pchanged = TRUE;
601  boxad = boxaCreate(nsave);
602  for (i = 0; i < n; i++) {
603  numaGetIValue(na, i, &ival);
604  if (ival == 0) continue;
605  box = boxaGetBox(boxas, i, L_COPY);
606  boxaAddBox(boxad, box, L_INSERT);
607  }
608 
609  return boxad;
610 }
611 
612 
613 /*---------------------------------------------------------------------*
614  * Boxa Permutation *
615  *---------------------------------------------------------------------*/
630 BOXA *
632 {
633 l_int32 n;
634 NUMA *na;
635 BOXA *boxad;
636 
637  PROCNAME("boxaPermutePseudorandom");
638 
639  if (!boxas)
640  return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
641 
642  n = boxaGetCount(boxas);
643  na = numaPseudorandomSequence(n, 0);
644  boxad = boxaSortByIndex(boxas, na);
645  numaDestroy(&na);
646  return boxad;
647 }
648 
649 
671 BOXA *
673  BOXA *boxas)
674 {
675 l_int32 i, n, index;
676 
677  PROCNAME("boxaPermuteRandom");
678 
679  if (!boxas)
680  return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
681  if (boxad && (boxad != boxas))
682  return (BOXA *)ERROR_PTR("boxad defined but in-place", procName, NULL);
683 
684  if (!boxad)
685  boxad = boxaCopy(boxas, L_COPY);
686  if ((n = boxaGetCount(boxad)) == 0)
687  return boxad;
688  index = (l_uint32)rand() % n;
689  index = L_MAX(1, index);
690  boxaSwapBoxes(boxad, 0, index);
691  for (i = 1; i < n; i++) {
692  index = (l_uint32)rand() % n;
693  if (index == i) index--;
694  boxaSwapBoxes(boxad, i, index);
695  }
696 
697  return boxad;
698 }
699 
700 
708 l_ok
710  l_int32 i,
711  l_int32 j)
712 {
713 l_int32 n;
714 BOX *box;
715 
716  PROCNAME("boxaSwapBoxes");
717 
718  if (!boxa)
719  return ERROR_INT("boxa not defined", procName, 1);
720  n = boxaGetCount(boxa);
721  if (i < 0 || i >= n)
722  return ERROR_INT("i invalid", procName, 1);
723  if (j < 0 || j >= n)
724  return ERROR_INT("j invalid", procName, 1);
725  if (i == j)
726  return ERROR_INT("i == j", procName, 1);
727 
728  box = boxa->box[i];
729  boxa->box[i] = boxa->box[j];
730  boxa->box[j] = box;
731  return 0;
732 }
733 
734 
735 /*---------------------------------------------------------------------*
736  * Boxa and Box Conversions *
737  *---------------------------------------------------------------------*/
752 PTA *
754  l_int32 ncorners)
755 {
756 l_int32 i, n;
757 BOX *box;
758 PTA *pta, *pta1;
759 
760  PROCNAME("boxaConvertToPta");
761 
762  if (!boxa)
763  return (PTA *)ERROR_PTR("boxa not defined", procName, NULL);
764  if (ncorners != 2 && ncorners != 4)
765  return (PTA *)ERROR_PTR("ncorners not 2 or 4", procName, NULL);
766 
767  n = boxaGetCount(boxa);
768  if ((pta = ptaCreate(n)) == NULL)
769  return (PTA *)ERROR_PTR("pta not made", procName, NULL);
770  for (i = 0; i < n; i++) {
771  box = boxaGetBox(boxa, i, L_COPY);
772  pta1 = boxConvertToPta(box, ncorners);
773  ptaJoin(pta, pta1, 0, -1);
774  boxDestroy(&box);
775  ptaDestroy(&pta1);
776  }
777 
778  return pta;
779 }
780 
781 
797 BOXA *
799  l_int32 ncorners)
800 {
801 l_int32 i, n, nbox, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
802 BOX *box;
803 BOXA *boxa;
804 
805  PROCNAME("ptaConvertToBoxa");
806 
807  if (!pta)
808  return (BOXA *)ERROR_PTR("pta not defined", procName, NULL);
809  if (ncorners != 2 && ncorners != 4)
810  return (BOXA *)ERROR_PTR("ncorners not 2 or 4", procName, NULL);
811  n = ptaGetCount(pta);
812  if (n % ncorners != 0)
813  return (BOXA *)ERROR_PTR("size % ncorners != 0", procName, NULL);
814  nbox = n / ncorners;
815  if ((boxa = boxaCreate(nbox)) == NULL)
816  return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
817  for (i = 0; i < n; i += ncorners) {
818  ptaGetIPt(pta, i, &x1, &y1);
819  ptaGetIPt(pta, i + 1, &x2, &y2);
820  if (ncorners == 2) {
821  box = boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
822  boxaAddBox(boxa, box, L_INSERT);
823  continue;
824  }
825  ptaGetIPt(pta, i + 2, &x3, &y3);
826  ptaGetIPt(pta, i + 3, &x4, &y4);
827  x = L_MIN(x1, x3);
828  y = L_MIN(y1, y2);
829  xmax = L_MAX(x2, x4);
830  ymax = L_MAX(y3, y4);
831  box = boxCreate(x, y, xmax - x + 1, ymax - y + 1);
832  boxaAddBox(boxa, box, L_INSERT);
833  }
834 
835  return boxa;
836 }
837 
838 
852 PTA *
854  l_int32 ncorners)
855 {
856 l_int32 x, y, w, h;
857 PTA *pta;
858 
859  PROCNAME("boxConvertToPta");
860 
861  if (!box)
862  return (PTA *)ERROR_PTR("box not defined", procName, NULL);
863  if (ncorners != 2 && ncorners != 4)
864  return (PTA *)ERROR_PTR("ncorners not 2 or 4", procName, NULL);
865 
866  if ((pta = ptaCreate(ncorners)) == NULL)
867  return (PTA *)ERROR_PTR("pta not made", procName, NULL);
868  boxGetGeometry(box, &x, &y, &w, &h);
869  ptaAddPt(pta, x, y);
870  if (ncorners == 2) {
871  ptaAddPt(pta, x + w - 1, y + h - 1);
872  } else {
873  ptaAddPt(pta, x + w - 1, y);
874  ptaAddPt(pta, x, y + h - 1);
875  ptaAddPt(pta, x + w - 1, y + h - 1);
876  }
877 
878  return pta;
879 }
880 
881 
894 BOX *
896 {
897 l_int32 n, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
898 
899  PROCNAME("ptaConvertToBox");
900 
901  if (!pta)
902  return (BOX *)ERROR_PTR("pta not defined", procName, NULL);
903  n = ptaGetCount(pta);
904  ptaGetIPt(pta, 0, &x1, &y1);
905  ptaGetIPt(pta, 1, &x2, &y2);
906  if (n == 2)
907  return boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
908 
909  /* 4 corners */
910  ptaGetIPt(pta, 2, &x3, &y3);
911  ptaGetIPt(pta, 3, &x4, &y4);
912  x = L_MIN(x1, x3);
913  y = L_MIN(y1, y2);
914  xmax = L_MAX(x2, x4);
915  ymax = L_MAX(y3, y4);
916  return boxCreate(x, y, xmax - x + 1, ymax - y + 1);
917 }
918 
919 
920 /*---------------------------------------------------------------------*
921  * Miscellaneous Boxa functions *
922  *---------------------------------------------------------------------*/
942 l_ok
944  l_int32 *pw,
945  l_int32 *ph,
946  BOX **pbox)
947 {
948 l_int32 i, n, x, y, w, h, xmax, ymax, xmin, ymin, found;
949 
950  PROCNAME("boxaGetExtent");
951 
952  if (!pw && !ph && !pbox)
953  return ERROR_INT("no ptrs defined", procName, 1);
954  if (pw) *pw = 0;
955  if (ph) *ph = 0;
956  if (pbox) *pbox = NULL;
957  if (!boxa)
958  return ERROR_INT("boxa not defined", procName, 1);
959 
960  n = boxaGetCount(boxa);
961  xmax = ymax = 0;
962  xmin = ymin = 100000000;
963  found = FALSE;
964  for (i = 0; i < n; i++) {
965  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
966  if (w <= 0 || h <= 0)
967  continue;
968  found = TRUE;
969  xmin = L_MIN(xmin, x);
970  ymin = L_MIN(ymin, y);
971  xmax = L_MAX(xmax, x + w);
972  ymax = L_MAX(ymax, y + h);
973  }
974  if (found == FALSE) /* no valid boxes in boxa */
975  xmin = ymin = 0;
976  if (pw) *pw = xmax;
977  if (ph) *ph = ymax;
978  if (pbox)
979  *pbox = boxCreate(xmin, ymin, xmax - xmin, ymax - ymin);
980 
981  return 0;
982 }
983 
984 
1008 l_ok
1010  l_int32 wc,
1011  l_int32 hc,
1012  l_int32 exactflag,
1013  l_float32 *pfract)
1014 {
1015 l_int32 i, n, x, y, w, h, sum;
1016 BOX *box, *boxc;
1017 PIX *pixt;
1018 
1019  PROCNAME("boxaGetCoverage");
1020 
1021  if (!pfract)
1022  return ERROR_INT("&fract not defined", procName, 1);
1023  *pfract = 0.0;
1024  if (!boxa)
1025  return ERROR_INT("boxa not defined", procName, 1);
1026 
1027  n = boxaGetCount(boxa);
1028  if (n == 0)
1029  return ERROR_INT("no boxes in boxa", procName, 1);
1030 
1031  if (exactflag == 0) { /* quick and dirty */
1032  sum = 0;
1033  for (i = 0; i < n; i++) {
1034  box = boxaGetBox(boxa, i, L_CLONE);
1035  if ((boxc = boxClipToRectangle(box, wc, hc)) != NULL) {
1036  boxGetGeometry(boxc, NULL, NULL, &w, &h);
1037  sum += w * h;
1038  boxDestroy(&boxc);
1039  }
1040  boxDestroy(&box);
1041  }
1042  } else { /* slower and exact */
1043  pixt = pixCreate(wc, hc, 1);
1044  for (i = 0; i < n; i++) {
1045  box = boxaGetBox(boxa, i, L_CLONE);
1046  boxGetGeometry(box, &x, &y, &w, &h);
1047  pixRasterop(pixt, x, y, w, h, PIX_SET, NULL, 0, 0);
1048  boxDestroy(&box);
1049  }
1050  pixCountPixels(pixt, &sum, NULL);
1051  pixDestroy(&pixt);
1052  }
1053 
1054  *pfract = (l_float32)sum / (l_float32)(wc * hc);
1055  return 0;
1056 }
1057 
1058 
1069 l_ok
1071  l_int32 *pminw,
1072  l_int32 *pminh,
1073  l_int32 *pmaxw,
1074  l_int32 *pmaxh)
1075 {
1076 l_int32 minw, minh, maxw, maxh, minbw, minbh, maxbw, maxbh, i, n;
1077 BOXA *boxa;
1078 
1079  PROCNAME("boxaaSizeRange");
1080 
1081  if (!pminw && !pmaxw && !pminh && !pmaxh)
1082  return ERROR_INT("no data can be returned", procName, 1);
1083  if (pminw) *pminw = 0;
1084  if (pminh) *pminh = 0;
1085  if (pmaxw) *pmaxw = 0;
1086  if (pmaxh) *pmaxh = 0;
1087  if (!baa)
1088  return ERROR_INT("baa not defined", procName, 1);
1089 
1090  minw = minh = 100000000;
1091  maxw = maxh = 0;
1092  n = boxaaGetCount(baa);
1093  for (i = 0; i < n; i++) {
1094  boxa = boxaaGetBoxa(baa, i, L_CLONE);
1095  boxaSizeRange(boxa, &minbw, &minbh, &maxbw, &maxbh);
1096  if (minbw < minw)
1097  minw = minbw;
1098  if (minbh < minh)
1099  minh = minbh;
1100  if (maxbw > maxw)
1101  maxw = maxbw;
1102  if (maxbh > maxh)
1103  maxh = maxbh;
1104  boxaDestroy(&boxa);
1105  }
1106 
1107  if (pminw) *pminw = minw;
1108  if (pminh) *pminh = minh;
1109  if (pmaxw) *pmaxw = maxw;
1110  if (pmaxh) *pmaxh = maxh;
1111  return 0;
1112 }
1113 
1114 
1125 l_ok
1127  l_int32 *pminw,
1128  l_int32 *pminh,
1129  l_int32 *pmaxw,
1130  l_int32 *pmaxh)
1131 {
1132 l_int32 minw, minh, maxw, maxh, i, n, w, h;
1133 
1134  PROCNAME("boxaSizeRange");
1135 
1136  if (!pminw && !pmaxw && !pminh && !pmaxh)
1137  return ERROR_INT("no data can be returned", procName, 1);
1138  if (pminw) *pminw = 0;
1139  if (pminh) *pminh = 0;
1140  if (pmaxw) *pmaxw = 0;
1141  if (pmaxh) *pmaxh = 0;
1142  if (!boxa)
1143  return ERROR_INT("boxa not defined", procName, 1);
1144 
1145  minw = minh = 100000000;
1146  maxw = maxh = 0;
1147  n = boxaGetCount(boxa);
1148  for (i = 0; i < n; i++) {
1149  boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
1150  if (w < minw)
1151  minw = w;
1152  if (h < minh)
1153  minh = h;
1154  if (w > maxw)
1155  maxw = w;
1156  if (h > maxh)
1157  maxh = h;
1158  }
1159 
1160  if (pminw) *pminw = minw;
1161  if (pminh) *pminh = minh;
1162  if (pmaxw) *pmaxw = maxw;
1163  if (pmaxh) *pmaxh = maxh;
1164  return 0;
1165 }
1166 
1167 
1178 l_ok
1180  l_int32 *pminx,
1181  l_int32 *pminy,
1182  l_int32 *pmaxx,
1183  l_int32 *pmaxy)
1184 {
1185 l_int32 minx, miny, maxx, maxy, i, n, x, y;
1186 
1187  PROCNAME("boxaLocationRange");
1188 
1189  if (!pminx && !pminy && !pmaxx && !pmaxy)
1190  return ERROR_INT("no data can be returned", procName, 1);
1191  if (pminx) *pminx = 0;
1192  if (pminy) *pminy = 0;
1193  if (pmaxx) *pmaxx = 0;
1194  if (pmaxy) *pmaxy = 0;
1195  if (!boxa)
1196  return ERROR_INT("boxa not defined", procName, 1);
1197 
1198  minx = miny = 100000000;
1199  maxx = maxy = 0;
1200  n = boxaGetCount(boxa);
1201  for (i = 0; i < n; i++) {
1202  boxaGetBoxGeometry(boxa, i, &x, &y, NULL, NULL);
1203  if (x < minx)
1204  minx = x;
1205  if (y < miny)
1206  miny = y;
1207  if (x > maxx)
1208  maxx = x;
1209  if (y > maxy)
1210  maxy = y;
1211  }
1212 
1213  if (pminx) *pminx = minx;
1214  if (pminy) *pminy = miny;
1215  if (pmaxx) *pmaxx = maxx;
1216  if (pmaxy) *pmaxy = maxy;
1217 
1218  return 0;
1219 }
1220 
1221 
1230 l_ok
1232  NUMA **pnaw,
1233  NUMA **pnah)
1234 {
1235 l_int32 i, n, w, h;
1236 BOX *box;
1237 
1238  PROCNAME("boxaGetSizes");
1239 
1240  if (pnaw) *pnaw = NULL;
1241  if (pnah) *pnah = NULL;
1242  if (!pnaw && !pnah)
1243  return ERROR_INT("no output requested", procName, 1);
1244  if (!boxa)
1245  return ERROR_INT("boxa not defined", procName, 1);
1246 
1247  n = boxaGetValidCount(boxa);
1248  if (pnaw) *pnaw = numaCreate(n);
1249  if (pnah) *pnah = numaCreate(n);
1250  for (i = 0; i < n; i++) {
1251  box = boxaGetValidBox(boxa, i, L_COPY);
1252  if (box) {
1253  boxGetGeometry(box, NULL, NULL, &w, &h);
1254  if (pnaw) numaAddNumber(*pnaw, w);
1255  if (pnah) numaAddNumber(*pnah, h);
1256  boxDestroy(&box);
1257  }
1258  }
1259 
1260  return 0;
1261 }
1262 
1263 
1276 l_ok
1278  l_int32 *parea)
1279 {
1280 l_int32 i, n, w, h;
1281 
1282  PROCNAME("boxaGetArea");
1283 
1284  if (!parea)
1285  return ERROR_INT("&area not defined", procName, 1);
1286  *parea = 0;
1287  if (!boxa)
1288  return ERROR_INT("boxa not defined", procName, 1);
1289 
1290  n = boxaGetCount(boxa);
1291  for (i = 0; i < n; i++) {
1292  boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
1293  *parea += w * h;
1294  }
1295  return 0;
1296 }
1297 
1298 
1326 PIX *
1328  PIXA *pixa,
1329  l_int32 first,
1330  l_int32 last,
1331  l_int32 maxwidth,
1332  l_int32 linewidth,
1333  l_float32 scalefactor,
1334  l_int32 background,
1335  l_int32 spacing,
1336  l_int32 border)
1337 {
1338 char buf[32];
1339 l_int32 i, n, npix, w, h, fontsize;
1340 L_BMF *bmf;
1341 BOX *box;
1342 BOXA *boxa;
1343 PIX *pix1, *pix2, *pixd;
1344 PIXA *pixat;
1345 
1346  PROCNAME("boxaDisplayTiled");
1347 
1348  if (!boxas)
1349  return (PIX *)ERROR_PTR("boxas not defined", procName, NULL);
1350 
1351  boxa = boxaSaveValid(boxas, L_COPY);
1352  n = boxaGetCount(boxa);
1353  if (pixa) {
1354  npix = pixaGetCount(pixa);
1355  if (n != npix) {
1356  boxaDestroy(&boxa);
1357  return (PIX *)ERROR_PTR("boxa and pixa counts differ",
1358  procName, NULL);
1359  }
1360  }
1361  first = L_MAX(0, first);
1362  if (last < 0) last = n - 1;
1363  if (first >= n)
1364  return (PIX *)ERROR_PTR("invalid first", procName, NULL);
1365  if (last >= n) {
1366  L_WARNING("last = %d is beyond max index = %d; adjusting\n",
1367  procName, last, n - 1);
1368  last = n - 1;
1369  }
1370  if (first > last)
1371  return (PIX *)ERROR_PTR("first > last", procName, NULL);
1372 
1373  /* Because the bitmap font will be reduced when tiled, choose the
1374  * font size inversely with the scale factor. */
1375  if (scalefactor > 0.8)
1376  fontsize = 6;
1377  else if (scalefactor > 0.6)
1378  fontsize = 10;
1379  else if (scalefactor > 0.4)
1380  fontsize = 14;
1381  else if (scalefactor > 0.3)
1382  fontsize = 18;
1383  else fontsize = 20;
1384  bmf = bmfCreate(NULL, fontsize);
1385 
1386  pixat = pixaCreate(n);
1387  boxaGetExtent(boxa, &w, &h, NULL);
1388  for (i = first; i <= last; i++) {
1389  box = boxaGetBox(boxa, i, L_CLONE);
1390  if (!pixa) {
1391  pix1 = pixCreate(w, h, 32);
1392  pixSetAll(pix1);
1393  } else {
1394  pix1 = pixaGetPix(pixa, i, L_COPY);
1395  }
1396  pixSetBorderVal(pix1, 0, 0, 0, 2, 0x0000ff00);
1397  snprintf(buf, sizeof(buf), "%d", i);
1398  pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0x00ff0000,
1399  L_ADD_BELOW, NULL);
1400  pixDestroy(&pix1);
1401  pixRenderBoxArb(pix2, box, linewidth, 255, 0, 0);
1402  pixaAddPix(pixat, pix2, L_INSERT);
1403  boxDestroy(&box);
1404  }
1405  bmfDestroy(&bmf);
1406  boxaDestroy(&boxa);
1407 
1408  pixd = pixaDisplayTiledInRows(pixat, 32, maxwidth, scalefactor, background,
1409  spacing, border);
1410  pixaDestroy(&pixat);
1411  return pixd;
1412 }
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:166
BOX * boxaGetValidBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetValidBox()
Definition: boxbasic.c:802
Definition: pix.h:717
l_ok boxaSwapBoxes(BOXA *boxa, l_int32 i, l_int32 j)
boxaSwapBoxes()
Definition: boxfunc4.c:709
PTA * boxaConvertToPta(BOXA *boxa, l_int32 ncorners)
boxaConvertToPta()
Definition: boxfunc4.c:753
BOXA * boxaSelectRange(BOXA *boxas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaSelectRange()
Definition: boxfunc4.c:91
l_ok boxaSizeRange(BOXA *boxa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
boxaSizeRange()
Definition: boxfunc4.c:1126
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:342
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
l_ok boxaGetSizes(BOXA *boxa, NUMA **pnaw, NUMA **pnah)
boxaGetSizes()
Definition: boxfunc4.c:1231
l_int32 boxaaGetCount(BOXAA *baa)
boxaaGetCount()
Definition: boxbasic.c:1424
l_ok boxaaSizeRange(BOXAA *baa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
boxaaSizeRange()
Definition: boxfunc4.c:1070
BOXA * boxaSelectBySize(BOXA *boxas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
boxaSelectBySize()
Definition: boxfunc4.c:217
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:193
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:116
NUMA * boxaMakeSizeIndicator(BOXA *boxa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation)
boxaMakeSizeIndicator()
Definition: boxfunc4.c:280
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1587
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:741
BOXA * ptaConvertToBoxa(PTA *pta, l_int32 ncorners)
ptaConvertToBoxa()
Definition: boxfunc4.c:798
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:534
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:504
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:580
Definition: pix.h:492
Definition: bmf.h:45
l_ok ptaJoin(PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend)
ptaJoin()
Definition: ptafunc1.c:164
Definition: pix.h:502
l_ok pixSetBorderVal(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixSetBorderVal()
Definition: pix2.c:1488
BOXAA * boxaaSelectRange(BOXAA *baas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaaSelectRange()
Definition: boxfunc4.c:149
l_ok boxaaAddBoxa(BOXAA *baa, BOXA *ba, l_int32 copyflag)
boxaaAddBoxa()
Definition: boxbasic.c:1327
NUMA * numaPseudorandomSequence(l_int32 size, l_int32 seed)
numaPseudorandomSequence()
Definition: numafunc1.c:2985
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
#define PIX_SET
Definition: pix.h:331
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:863
BOXA * boxaSaveValid(BOXA *boxas, l_int32 copyflag)
boxaSaveValid()
Definition: boxbasic.c:1095
l_ok boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition: boxfunc4.c:1277
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:836
BOXA * boxaPermuteRandom(BOXA *boxad, BOXA *boxas)
boxaPermuteRandom()
Definition: boxfunc4.c:672
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1823
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:618
BOXA * boxaSelectByWHRatio(BOXA *boxas, l_float32 ratio, l_int32 relation, l_int32 *pchanged)
boxaSelectByWHRatio()
Definition: boxfunc4.c:471
BOXA * boxaSelectByArea(BOXA *boxas, l_int32 area, l_int32 relation, l_int32 *pchanged)
boxaSelectByArea()
Definition: boxfunc4.c:367
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:763
l_ok boxaLocationRange(BOXA *boxa, l_int32 *pminx, l_int32 *pminy, l_int32 *pmaxx, l_int32 *pmaxy)
boxaLocationRange()
Definition: boxfunc4.c:1179
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:1327
Definition: pix.h:454
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:943
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
NUMA * boxaMakeAreaIndicator(BOXA *boxa, l_int32 area, l_int32 relation)
boxaMakeAreaIndicator()
Definition: boxfunc4.c:417
BOXAA * boxaaCreate(l_int32 n)
boxaaCreate()
Definition: boxbasic.c:1223
BOXA * boxaSelectWithIndicator(BOXA *boxas, NUMA *na, l_int32 *pchanged)
boxaSelectWithIndicator()
Definition: boxfunc4.c:573
l_int32 boxaGetValidCount(BOXA *boxa)
boxaGetValidCount()
Definition: boxbasic.c:735
PTA * boxConvertToPta(BOX *box, l_int32 ncorners)
boxConvertToPta()
Definition: boxfunc4.c:853
BOXA * boxaPermutePseudorandom(BOXA *boxas)
boxaPermutePseudorandom()
Definition: boxfunc4.c:631
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:672
Definition: pix.h:718
l_ok pixRenderBoxArb(PIX *pix, BOX *box, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxArb()
Definition: graphics.c:1642
Definition: pix.h:134
Definition: pix.h:719
l_ok boxaGetCoverage(BOXA *boxa, l_int32 wc, l_int32 hc, l_int32 exactflag, l_float32 *pfract)
boxaGetCoverage()
Definition: boxfunc4.c:1009
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:192
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:499
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:718
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:555
struct Box ** box
Definition: pix.h:497
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:310
Definition: pix.h:480
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:115
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
NUMA * boxaMakeWHRatioIndicator(BOXA *boxa, l_float32 ratio, l_int32 relation)
boxaMakeWHRatioIndicator()
Definition: boxfunc4.c:521
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:631
BOX * ptaConvertToBox(PTA *pta)
ptaConvertToBox()
Definition: boxfunc4.c:895
Definition: pix.h:517
BOXA * boxaaGetBoxa(BOXAA *baa, l_int32 index, l_int32 accessflag)
boxaaGetBoxa()
Definition: boxbasic.c:1471
BOXA * boxaSortByIndex(BOXA *boxas, NUMA *naindex)
boxaSortByIndex()
Definition: boxfunc2.c:769
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:114