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  *---------------------------------------------------------------------*/
93 BOXA *
95  l_int32 first,
96  l_int32 last,
97  l_int32 copyflag)
98 {
99 l_int32 n, nbox, i;
100 BOX *box;
101 BOXA *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 
151 BOXAA *
153  l_int32 first,
154  l_int32 last,
155  l_int32 copyflag)
156 {
157 l_int32 n, nboxa, i;
158 BOXA *boxa;
159 BOXAA *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  *---------------------------------------------------------------------*/
219 BOXA *
221  l_int32 width,
222  l_int32 height,
223  l_int32 type,
224  l_int32 relation,
225  l_int32 *pchanged)
226 {
227 BOXA *boxad;
228 NUMA *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 
282 NUMA *
284  l_int32 width,
285  l_int32 height,
286  l_int32 type,
287  l_int32 relation)
288 {
289 l_int32 i, n, w, h, ival;
290 NUMA *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;
325  case L_SELECT_IF_EITHER:
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 
369 BOXA *
371  l_int32 area,
372  l_int32 relation,
373  l_int32 *pchanged)
374 {
375 BOXA *boxad;
376 NUMA *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 
419 NUMA *
421  l_int32 area,
422  l_int32 relation)
423 {
424 l_int32 i, n, w, h, ival;
425 NUMA *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 
473 BOXA *
475  l_float32 ratio,
476  l_int32 relation,
477  l_int32 *pchanged)
478 {
479 BOXA *boxad;
480 NUMA *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 
523 NUMA *
525  l_float32 ratio,
526  l_int32 relation)
527 {
528 l_int32 i, n, w, h, ival;
529 l_float32 whratio;
530 NUMA *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 
576 BOXA *
578  NUMA *na,
579  l_int32 *pchanged)
580 {
581 l_int32 i, n, ival, nsave;
582 BOX *box;
583 BOXA *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  *---------------------------------------------------------------------*/
634 BOXA *
636 {
637 l_int32 n;
638 NUMA *na;
639 BOXA *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 
675 BOXA *
677  BOXA *boxas)
678 {
679 l_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 
712 l_ok
714  l_int32 i,
715  l_int32 j)
716 {
717 l_int32 n;
718 BOX *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  *---------------------------------------------------------------------*/
760 PTA *
762  l_int32 ncorners)
763 {
764 l_int32 i, n;
765 BOX *box;
766 PTA *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 
805 BOXA *
807  l_int32 ncorners)
808 {
809 l_int32 i, n, nbox, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
810 BOX *box;
811 BOXA *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 
860 PTA *
862  l_int32 ncorners)
863 {
864 l_int32 x, y, w, h;
865 PTA *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 
902 BOX *
904 {
905 l_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  *---------------------------------------------------------------------*/
952 l_ok
954  l_int32 *pw,
955  l_int32 *ph,
956  BOX **pbox)
957 {
958 l_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 
1018 l_ok
1020  l_int32 wc,
1021  l_int32 hc,
1022  l_int32 exactflag,
1023  l_float32 *pfract)
1024 {
1025 l_int32 i, n, x, y, w, h, sum;
1026 BOX *box, *boxc;
1027 PIX *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 
1079 l_ok
1081  l_int32 *pminw,
1082  l_int32 *pminh,
1083  l_int32 *pmaxw,
1084  l_int32 *pmaxh)
1085 {
1086 l_int32 minw, minh, maxw, maxh, minbw, minbh, maxbw, maxbh, i, n;
1087 BOXA *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 
1135 l_ok
1137  l_int32 *pminw,
1138  l_int32 *pminh,
1139  l_int32 *pmaxw,
1140  l_int32 *pmaxh)
1141 {
1142 l_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 
1188 l_ok
1190  l_int32 *pminx,
1191  l_int32 *pminy,
1192  l_int32 *pmaxx,
1193  l_int32 *pmaxy)
1194 {
1195 l_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 
1240 l_ok
1242  NUMA **pnaw,
1243  NUMA **pnah)
1244 {
1245 l_int32 i, n, w, h;
1246 BOX *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 
1286 l_ok
1288  l_int32 *parea)
1289 {
1290 l_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 
1336 PIX *
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 {
1348 char buf[32];
1349 l_int32 i, n, npix, w, h, fontsize;
1350 L_BMF *bmf;
1351 BOX *box;
1352 BOXA *boxa;
1353 PIX *pix1, *pix2, *pixd;
1354 PIXA *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
l_int32 boxaGetValidCount(BOXA *boxa)
boxaGetValidCount()
Definition: boxbasic.c:751
BOXA * boxaSaveValid(BOXA *boxas, l_int32 copyflag)
boxaSaveValid()
Definition: boxbasic.c:1116
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:537
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
BOXAA * boxaaCreate(l_int32 n)
boxaaCreate()
Definition: boxbasic.c:1244
l_int32 boxaaGetCount(BOXAA *baa)
boxaaGetCount()
Definition: boxbasic.c:1454
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
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 * boxaGetValidBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetValidBox()
Definition: boxbasic.c:818
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
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
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
l_ok boxaSwapBoxes(BOXA *boxa, l_int32 i, l_int32 j)
boxaSwapBoxes()
Definition: boxfunc4.c:713
l_ok boxaaSizeRange(BOXAA *baa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
boxaaSizeRange()
Definition: boxfunc4.c:1080
BOXAA * boxaaSelectRange(BOXAA *baas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaaSelectRange()
Definition: boxfunc4.c:152
BOXA * boxaSelectByWHRatio(BOXA *boxas, l_float32 ratio, l_int32 relation, l_int32 *pchanged)
boxaSelectByWHRatio()
Definition: boxfunc4.c:474
l_ok boxaGetSizes(BOXA *boxa, NUMA **pnaw, NUMA **pnah)
boxaGetSizes()
Definition: boxfunc4.c:1241
BOXA * boxaSelectBySize(BOXA *boxas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
boxaSelectBySize()
Definition: boxfunc4.c:220
BOXA * ptaConvertToBoxa(PTA *pta, l_int32 ncorners)
ptaConvertToBoxa()
Definition: boxfunc4.c:806
BOXA * boxaSelectByArea(BOXA *boxas, l_int32 area, l_int32 relation, l_int32 *pchanged)
boxaSelectByArea()
Definition: boxfunc4.c:370
l_ok boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition: boxfunc4.c:1287
NUMA * boxaMakeAreaIndicator(BOXA *boxa, l_int32 area, l_int32 relation)
boxaMakeAreaIndicator()
Definition: boxfunc4.c:420
NUMA * boxaMakeWHRatioIndicator(BOXA *boxa, l_float32 ratio, l_int32 relation)
boxaMakeWHRatioIndicator()
Definition: boxfunc4.c:524
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
PTA * boxConvertToPta(BOX *box, l_int32 ncorners)
boxConvertToPta()
Definition: boxfunc4.c:861
BOX * ptaConvertToBox(PTA *pta)
ptaConvertToBox()
Definition: boxfunc4.c:903
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
NUMA * boxaMakeSizeIndicator(BOXA *boxa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation)
boxaMakeSizeIndicator()
Definition: boxfunc4.c:283
PTA * boxaConvertToPta(BOXA *boxa, l_int32 ncorners)
boxaConvertToPta()
Definition: boxfunc4.c:761
BOXA * boxaSelectRange(BOXA *boxas, l_int32 first, l_int32 last, l_int32 copyflag)
boxaSelectRange()
Definition: boxfunc4.c:94
BOXA * boxaPermuteRandom(BOXA *boxad, BOXA *boxas)
boxaPermuteRandom()
Definition: boxfunc4.c:676
BOXA * boxaPermutePseudorandom(BOXA *boxas)
boxaPermutePseudorandom()
Definition: boxfunc4.c:635
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
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
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
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 * 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
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
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
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