Leptonica  1.83.1
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 #include "pix_internal.h"
74 
75 /*---------------------------------------------------------------------*
76  * Boxa and boxaa range selection *
77  *---------------------------------------------------------------------*/
94 BOXA *
96  l_int32 first,
97  l_int32 last,
98  l_int32 copyflag)
99 {
100 l_int32 n, nbox, i;
101 BOX *box;
102 BOXA *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 
150 BOXAA *
152  l_int32 first,
153  l_int32 last,
154  l_int32 copyflag)
155 {
156 l_int32 n, nboxa, i;
157 BOXA *boxa;
158 BOXAA *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  *---------------------------------------------------------------------*/
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  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 
277 NUMA *
279  l_int32 width,
280  l_int32 height,
281  l_int32 type,
282  l_int32 relation)
283 {
284 l_int32 i, n, w, h, ival;
285 NUMA *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;
318  case L_SELECT_IF_EITHER:
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 
362 BOXA *
364  l_int32 area,
365  l_int32 relation,
366  l_int32 *pchanged)
367 {
368 BOXA *boxad;
369 NUMA *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 
410 NUMA *
412  l_int32 area,
413  l_int32 relation)
414 {
415 l_int32 i, n, w, h, ival;
416 NUMA *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 
462 BOXA *
464  l_float32 ratio,
465  l_int32 relation,
466  l_int32 *pchanged)
467 {
468 BOXA *boxad;
469 NUMA *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 
510 NUMA *
512  l_float32 ratio,
513  l_int32 relation)
514 {
515 l_int32 i, n, w, h, ival;
516 l_float32 whratio;
517 NUMA *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 
561 BOXA *
563  NUMA *na,
564  l_int32 *pchanged)
565 {
566 l_int32 i, n, ival, nsave;
567 BOX *box;
568 BOXA *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  *---------------------------------------------------------------------*/
617 BOXA *
619 {
620 l_int32 n;
621 NUMA *na;
622 BOXA *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 
656 BOXA *
658  BOXA *boxas)
659 {
660 l_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 
691 l_ok
693  l_int32 i,
694  l_int32 j)
695 {
696 l_int32 n;
697 BOX *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  *---------------------------------------------------------------------*/
737 PTA *
739  l_int32 ncorners)
740 {
741 l_int32 i, n;
742 BOX *box;
743 PTA *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 
780 BOXA *
782  l_int32 ncorners)
783 {
784 l_int32 i, n, nbox, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
785 BOX *box;
786 BOXA *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 
833 PTA *
835  l_int32 ncorners)
836 {
837 l_int32 x, y, w, h;
838 PTA *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 
873 BOX *
875 {
876 l_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  *---------------------------------------------------------------------*/
921 l_ok
923  l_int32 *pw,
924  l_int32 *ph,
925  BOX **pbox)
926 {
927 l_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 
985 l_ok
987  l_int32 wc,
988  l_int32 hc,
989  l_int32 exactflag,
990  l_float32 *pfract)
991 {
992 l_int32 i, n, x, y, w, h, sum;
993 BOX *box, *boxc;
994 PIX *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 
1044 l_ok
1046  l_int32 *pminw,
1047  l_int32 *pminh,
1048  l_int32 *pmaxw,
1049  l_int32 *pmaxh)
1050 {
1051 l_int32 minw, minh, maxw, maxh, minbw, minbh, maxbw, maxbh, i, n;
1052 BOXA *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 
1098 l_ok
1100  l_int32 *pminw,
1101  l_int32 *pminh,
1102  l_int32 *pmaxw,
1103  l_int32 *pmaxh)
1104 {
1105 l_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 
1149 l_ok
1151  l_int32 *pminx,
1152  l_int32 *pminy,
1153  l_int32 *pmaxx,
1154  l_int32 *pmaxy)
1155 {
1156 l_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 
1199 l_ok
1201  NUMA **pnaw,
1202  NUMA **pnah)
1203 {
1204 l_int32 i, n, w, h;
1205 BOX *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 
1243 l_ok
1245  l_int32 *parea)
1246 {
1247 l_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 
1291 PIX *
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 {
1303 char buf[32];
1304 l_int32 i, n, npix, w, h, fontsize;
1305 L_BMF *bmf;
1306 BOX *box;
1307 BOXA *boxa;
1308 PIX *pix1, *pix2, *pixd;
1309 PIXA *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 }
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:168
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:118
l_int32 boxaGetValidCount(BOXA *boxa)
boxaGetValidCount()
Definition: boxbasic.c:676
BOXA * boxaSaveValid(BOXA *boxas, l_int32 copyflag)
boxaSaveValid()
Definition: boxbasic.c:1023
l_ok boxGetGeometry(const BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:301
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:475
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:273
BOXAA * boxaaCreate(l_int32 n)
boxaaCreate()
Definition: boxbasic.c:1145
l_int32 boxaaGetCount(BOXAA *baa)
boxaaGetCount()
Definition: boxbasic.c:1343
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:796
l_ok boxaaAddBoxa(BOXAA *baa, BOXA *ba, l_int32 copyflag)
boxaaAddBoxa()
Definition: boxbasic.c:1241
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:553
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:519
l_int32 boxaGetCount(const BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:661
BOX * boxaGetValidBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetValidBox()
Definition: boxbasic.c:739
BOXA * boxaaGetBoxa(BOXAA *baa, l_int32 index, l_int32 accessflag)
boxaaGetBoxa()
Definition: boxbasic.c:1386
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:702
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:171
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:442
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1679
BOXA * boxaSortByIndex(BOXA *boxas, NUMA *naindex)
boxaSortByIndex()
Definition: boxfunc2.c:821
l_ok boxaSwapBoxes(BOXA *boxa, l_int32 i, l_int32 j)
boxaSwapBoxes()
Definition: boxfunc4.c:692
l_ok boxaaSizeRange(BOXAA *baa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
boxaaSizeRange()
Definition: boxfunc4.c:1045
BOXAA * boxaaSelectRange(BOXAA *baas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaaSelectRange()
Definition: boxfunc4.c:151
BOXA * boxaSelectByWHRatio(BOXA *boxas, l_float32 ratio, l_int32 relation, l_int32 *pchanged)
boxaSelectByWHRatio()
Definition: boxfunc4.c:463
l_ok boxaGetSizes(BOXA *boxa, NUMA **pnaw, NUMA **pnah)
boxaGetSizes()
Definition: boxfunc4.c:1200
BOXA * boxaSelectBySize(BOXA *boxas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
boxaSelectBySize()
Definition: boxfunc4.c:217
BOXA * ptaConvertToBoxa(PTA *pta, l_int32 ncorners)
ptaConvertToBoxa()
Definition: boxfunc4.c:781
BOXA * boxaSelectByArea(BOXA *boxas, l_int32 area, l_int32 relation, l_int32 *pchanged)
boxaSelectByArea()
Definition: boxfunc4.c:363
l_ok boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition: boxfunc4.c:1244
NUMA * boxaMakeAreaIndicator(BOXA *boxa, l_int32 area, l_int32 relation)
boxaMakeAreaIndicator()
Definition: boxfunc4.c:411
NUMA * boxaMakeWHRatioIndicator(BOXA *boxa, l_float32 ratio, l_int32 relation)
boxaMakeWHRatioIndicator()
Definition: boxfunc4.c:511
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
PTA * boxConvertToPta(BOX *box, l_int32 ncorners)
boxConvertToPta()
Definition: boxfunc4.c:834
BOX * ptaConvertToBox(PTA *pta)
ptaConvertToBox()
Definition: boxfunc4.c:874
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
NUMA * boxaMakeSizeIndicator(BOXA *boxa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation)
boxaMakeSizeIndicator()
Definition: boxfunc4.c:278
PTA * boxaConvertToPta(BOXA *boxa, l_int32 ncorners)
boxaConvertToPta()
Definition: boxfunc4.c:738
BOXA * boxaSelectRange(BOXA *boxas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaSelectRange()
Definition: boxfunc4.c:95
BOXA * boxaPermuteRandom(BOXA *boxad, BOXA *boxas)
boxaPermuteRandom()
Definition: boxfunc4.c:657
BOXA * boxaPermutePseudorandom(BOXA *boxas)
boxaPermutePseudorandom()
Definition: boxfunc4.c:618
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
l_ok pixRenderBoxArb(PIX *pix, BOX *box, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxArb()
Definition: graphics.c:1606
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:720
NUMA * numaPseudorandomSequence(l_int32 size, l_int32 seed)
numaPseudorandomSequence()
Definition: numafunc1.c:3151
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
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:1521
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:799
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1893
@ 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
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:404
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:629
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:647
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:730
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:527
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:328
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:480
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
l_ok ptaJoin(PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend)
ptaJoin()
Definition: ptafunc1.c:166
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
struct Box ** box
Definition: pix_internal.h:270
Definition: bmf.h:47
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120