Leptonica  1.73
Image processing and image analysis suite
pixafunc1.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 
87 #include <string.h>
88 #include "allheaders.h"
89 
90  /* For more than this number of c.c. in a binarized image of
91  * semi-perimeter (w + h) about 5000 or less, the O(n) binsort
92  * is faster than the O(nlogn) shellsort. */
93 static const l_int32 MIN_COMPS_FOR_BIN_SORT = 200;
94 
95 
96 /*---------------------------------------------------------------------*
97  * Filters *
98  *---------------------------------------------------------------------*/
99 /*
100  * These filters work on the connected components of 1 bpp images.
101  * They are typically used on pixa that have been generated from a Pix
102  * using pixConnComp(), so that the corresponding Boxa is available.
103  *
104  * The filters remove or retain c.c. based on these properties:
105  * (a) size [pixaFindDimensions()]
106  * (b) area-to-perimeter ratio [pixaFindAreaPerimRatio()]
107  * (c) foreground area as a fraction of bounding box area (w * h)
108  * [pixaFindForegroundArea()]
109  * (d) number of foreground pixels [pixaCountPixels()]
110  * (e) width/height aspect ratio [pixFindWidthHeightRatio()]
111  *
112  * We provide two different high-level interfaces:
113  * (1) Functions that use one of the filters on either
114  * a pix or the pixa of components.
115  * (2) A general method that generates numas of indicator functions,
116  * logically combines them, and efficiently removes or adds
117  * the selected components.
118  *
119  * For interface (1), the filtering is performed with a single function call.
120  * This is the easiest way to do simple filtering. These functions
121  * are named pixSelectBy*() and pixaSelectBy*(), where the '*' is one of:
122  * Size
123  * PerimToAreaRatio
124  * PerimSizeRatio
125  * AreaFraction
126  * WidthHeightRatio
127  *
128  * For more complicated filtering, use the general method (2).
129  * The numa indicator functions for a pixa are generated by these functions:
130  * pixaFindDimensions()
131  * pixaFindPerimToAreaRatio()
132  * pixaFindPerimSizeRatio()
133  * pixaFindAreaFraction()
134  * pixaCountPixels()
135  * pixaFindWidthHeightRatio()
136  * pixaFindWidthHeightProduct()
137  *
138  * Here is an illustration using the general method. Suppose you want
139  * all 8-connected components that have a height greater than 40 pixels,
140  * a width not more than 30 pixels, between 150 and 300 fg pixels,
141  * and a perimeter-to-size ratio between 1.2 and 2.0.
142  *
143  * // Generate the pixa of 8 cc pieces.
144  * boxa = pixConnComp(pixs, &pixa, 8);
145  *
146  * // Extract the data we need about each component.
147  * pixaFindDimensions(pixa, &naw, &nah);
148  * nas = pixaCountPixels(pixa);
149  * nar = pixaFindPerimSizeRatio(pixa);
150  *
151  * // Build the indicator arrays for the set of components,
152  * // based on thresholds and selection criteria.
153  * na1 = numaMakeThresholdIndicator(nah, 40, L_SELECT_IF_GT);
154  * na2 = numaMakeThresholdIndicator(naw, 30, L_SELECT_IF_LTE);
155  * na3 = numaMakeThresholdIndicator(nas, 150, L_SELECT_IF_GTE);
156  * na4 = numaMakeThresholdIndicator(nas, 300, L_SELECT_IF_LTE);
157  * na5 = numaMakeThresholdIndicator(nar, 1.2, L_SELECT_IF_GTE);
158  * na6 = numaMakeThresholdIndicator(nar, 2.0, L_SELECT_IF_LTE);
159  *
160  * // Combine the indicator arrays logically to find
161  * // the components that will be retained.
162  * nad = numaLogicalOp(NULL, na1, na2, L_INTERSECTION);
163  * numaLogicalOp(nad, nad, na3, L_INTERSECTION);
164  * numaLogicalOp(nad, nad, na4, L_INTERSECTION);
165  * numaLogicalOp(nad, nad, na5, L_INTERSECTION);
166  * numaLogicalOp(nad, nad, na6, L_INTERSECTION);
167  *
168  * // Invert to get the components that will be removed.
169  * numaInvert(nad, nad);
170  *
171  * // Remove the components, in-place.
172  * pixRemoveWithIndicator(pixs, pixa, nad);
173  */
174 
175 
203 PIX *
205  l_int32 width,
206  l_int32 height,
207  l_int32 connectivity,
208  l_int32 type,
209  l_int32 relation,
210  l_int32 *pchanged)
211 {
212 l_int32 w, h, empty, changed, count;
213 BOXA *boxa;
214 PIX *pixd;
215 PIXA *pixas, *pixad;
216 
217  PROCNAME("pixSelectBySize");
218 
219  if (!pixs)
220  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
221  if (connectivity != 4 && connectivity != 8)
222  return (PIX *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
223  if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
224  type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
225  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
226  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
227  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
228  return (PIX *)ERROR_PTR("invalid relation", procName, NULL);
229  if (pchanged) *pchanged = FALSE;
230 
231  /* Check if any components exist */
232  pixZero(pixs, &empty);
233  if (empty)
234  return pixCopy(NULL, pixs);
235 
236  /* Identify and select the components */
237  boxa = pixConnComp(pixs, &pixas, connectivity);
238  pixad = pixaSelectBySize(pixas, width, height, type, relation, &changed);
239  boxaDestroy(&boxa);
240  pixaDestroy(&pixas);
241 
242  if (!changed) {
243  pixaDestroy(&pixad);
244  return pixCopy(NULL, pixs);
245  }
246 
247  /* Render the result */
248  if (pchanged) *pchanged = TRUE;
249  pixGetDimensions(pixs, &w, &h, NULL);
250  count = pixaGetCount(pixad);
251  if (count == 0) { /* return empty pix */
252  pixd = pixCreateTemplate(pixs);
253  } else {
254  pixd = pixaDisplay(pixad, w, h);
255  pixCopyResolution(pixd, pixs);
256  pixCopyColormap(pixd, pixs);
257  pixCopyText(pixd, pixs);
258  pixCopyInputFormat(pixd, pixs);
259  }
260  pixaDestroy(&pixad);
261  return pixd;
262 }
263 
264 
290 PIXA *
292  l_int32 width,
293  l_int32 height,
294  l_int32 type,
295  l_int32 relation,
296  l_int32 *pchanged)
297 {
298 NUMA *na;
299 PIXA *pixad;
300 
301  PROCNAME("pixaSelectBySize");
302 
303  if (!pixas)
304  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
305  if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
306  type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
307  return (PIXA *)ERROR_PTR("invalid type", procName, NULL);
308  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
309  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
310  return (PIXA *)ERROR_PTR("invalid relation", procName, NULL);
311 
312  /* Compute the indicator array for saving components */
313  na = pixaMakeSizeIndicator(pixas, width, height, type, relation);
314 
315  /* Filter to get output */
316  pixad = pixaSelectWithIndicator(pixas, na, pchanged);
317 
318  numaDestroy(&na);
319  return pixad;
320 }
321 
322 
346 NUMA *
348  l_int32 width,
349  l_int32 height,
350  l_int32 type,
351  l_int32 relation)
352 {
353 l_int32 i, n, w, h, ival;
354 NUMA *na;
355 
356  PROCNAME("pixaMakeSizeIndicator");
357 
358  if (!pixa)
359  return (NUMA *)ERROR_PTR("pixa not defined", procName, NULL);
360  if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
361  type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
362  return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
363  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
364  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
365  return (NUMA *)ERROR_PTR("invalid relation", procName, NULL);
366 
367  n = pixaGetCount(pixa);
368  na = numaCreate(n);
369  for (i = 0; i < n; i++) {
370  ival = 0;
371  pixaGetPixDimensions(pixa, i, &w, &h, NULL);
372  switch (type)
373  {
374  case L_SELECT_WIDTH:
375  if ((relation == L_SELECT_IF_LT && w < width) ||
376  (relation == L_SELECT_IF_GT && w > width) ||
377  (relation == L_SELECT_IF_LTE && w <= width) ||
378  (relation == L_SELECT_IF_GTE && w >= width))
379  ival = 1;
380  break;
381  case L_SELECT_HEIGHT:
382  if ((relation == L_SELECT_IF_LT && h < height) ||
383  (relation == L_SELECT_IF_GT && h > height) ||
384  (relation == L_SELECT_IF_LTE && h <= height) ||
385  (relation == L_SELECT_IF_GTE && h >= height))
386  ival = 1;
387  break;
388  case L_SELECT_IF_EITHER:
389  if (((relation == L_SELECT_IF_LT) && (w < width || h < height)) ||
390  ((relation == L_SELECT_IF_GT) && (w > width || h > height)) ||
391  ((relation == L_SELECT_IF_LTE) && (w <= width || h <= height)) ||
392  ((relation == L_SELECT_IF_GTE) && (w >= width || h >= height)))
393  ival = 1;
394  break;
395  case L_SELECT_IF_BOTH:
396  if (((relation == L_SELECT_IF_LT) && (w < width && h < height)) ||
397  ((relation == L_SELECT_IF_GT) && (w > width && h > height)) ||
398  ((relation == L_SELECT_IF_LTE) && (w <= width && h <= height)) ||
399  ((relation == L_SELECT_IF_GTE) && (w >= width && h >= height)))
400  ival = 1;
401  break;
402  default:
403  L_WARNING("can't get here!\n", procName);
404  break;
405  }
406  numaAddNumber(na, ival);
407  }
408 
409  return na;
410 }
411 
412 
437 PIX *
439  l_float32 thresh,
440  l_int32 connectivity,
441  l_int32 type,
442  l_int32 *pchanged)
443 {
444 l_int32 w, h, empty, changed, count;
445 BOXA *boxa;
446 PIX *pixd;
447 PIXA *pixas, *pixad;
448 
449  PROCNAME("pixSelectByPerimToAreaRatio");
450 
451  if (!pixs)
452  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
453  if (connectivity != 4 && connectivity != 8)
454  return (PIX *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
455  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
456  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
457  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
458  if (pchanged) *pchanged = FALSE;
459 
460  /* Check if any components exist */
461  pixZero(pixs, &empty);
462  if (empty)
463  return pixCopy(NULL, pixs);
464 
465  /* Filter thin components */
466  boxa = pixConnComp(pixs, &pixas, connectivity);
467  pixad = pixaSelectByPerimToAreaRatio(pixas, thresh, type, &changed);
468  boxaDestroy(&boxa);
469  pixaDestroy(&pixas);
470 
471  if (!changed) {
472  pixaDestroy(&pixad);
473  return pixCopy(NULL, pixs);
474  }
475 
476  /* Render the result */
477  if (pchanged) *pchanged = TRUE;
478  pixGetDimensions(pixs, &w, &h, NULL);
479  count = pixaGetCount(pixad);
480  if (count == 0) { /* return empty pix */
481  pixd = pixCreateTemplate(pixs);
482  } else {
483  pixd = pixaDisplay(pixad, w, h);
484  pixCopyResolution(pixd, pixs);
485  pixCopyColormap(pixd, pixs);
486  pixCopyText(pixd, pixs);
487  pixCopyInputFormat(pixd, pixs);
488  }
489  pixaDestroy(&pixad);
490  return pixd;
491 }
492 
493 
511 PIXA *
513  l_float32 thresh,
514  l_int32 type,
515  l_int32 *pchanged)
516 {
517 NUMA *na, *nai;
518 PIXA *pixad;
519 
520  PROCNAME("pixaSelectByPerimToAreaRatio");
521 
522  if (!pixas)
523  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
524  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
525  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
526  return (PIXA *)ERROR_PTR("invalid type", procName, NULL);
527 
528  /* Compute component ratios. */
529  na = pixaFindPerimToAreaRatio(pixas);
530 
531  /* Generate indicator array for elements to be saved. */
532  nai = numaMakeThresholdIndicator(na, thresh, type);
533  numaDestroy(&na);
534 
535  /* Filter to get output */
536  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
537 
538  numaDestroy(&nai);
539  return pixad;
540 }
541 
542 
568 PIX *
570  l_float32 thresh,
571  l_int32 connectivity,
572  l_int32 type,
573  l_int32 *pchanged)
574 {
575 l_int32 w, h, empty, changed, count;
576 BOXA *boxa;
577 PIX *pixd;
578 PIXA *pixas, *pixad;
579 
580  PROCNAME("pixSelectByPerimSizeRatio");
581 
582  if (!pixs)
583  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
584  if (connectivity != 4 && connectivity != 8)
585  return (PIX *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
586  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
587  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
588  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
589  if (pchanged) *pchanged = FALSE;
590 
591  /* Check if any components exist */
592  pixZero(pixs, &empty);
593  if (empty)
594  return pixCopy(NULL, pixs);
595 
596  /* Filter thin components */
597  boxa = pixConnComp(pixs, &pixas, connectivity);
598  pixad = pixaSelectByPerimSizeRatio(pixas, thresh, type, &changed);
599  boxaDestroy(&boxa);
600  pixaDestroy(&pixas);
601 
602  if (!changed) {
603  pixaDestroy(&pixad);
604  return pixCopy(NULL, pixs);
605  }
606 
607  /* Render the result */
608  if (pchanged) *pchanged = TRUE;
609  pixGetDimensions(pixs, &w, &h, NULL);
610  count = pixaGetCount(pixad);
611  if (count == 0) { /* return empty pix */
612  pixd = pixCreateTemplate(pixs);
613  } else {
614  pixd = pixaDisplay(pixad, w, h);
615  pixCopyResolution(pixd, pixs);
616  pixCopyColormap(pixd, pixs);
617  pixCopyText(pixd, pixs);
618  pixCopyInputFormat(pixd, pixs);
619  }
620  pixaDestroy(&pixad);
621  return pixd;
622 }
623 
624 
642 PIXA *
644  l_float32 thresh,
645  l_int32 type,
646  l_int32 *pchanged)
647 {
648 NUMA *na, *nai;
649 PIXA *pixad;
650 
651  PROCNAME("pixaSelectByPerimSizeRatio");
652 
653  if (!pixas)
654  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
655  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
656  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
657  return (PIXA *)ERROR_PTR("invalid type", procName, NULL);
658 
659  /* Compute component ratios. */
660  na = pixaFindPerimSizeRatio(pixas);
661 
662  /* Generate indicator array for elements to be saved. */
663  nai = numaMakeThresholdIndicator(na, thresh, type);
664  numaDestroy(&na);
665 
666  /* Filter to get output */
667  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
668 
669  numaDestroy(&nai);
670  return pixad;
671 }
672 
673 
698 PIX *
700  l_float32 thresh,
701  l_int32 connectivity,
702  l_int32 type,
703  l_int32 *pchanged)
704 {
705 l_int32 w, h, empty, changed, count;
706 BOXA *boxa;
707 PIX *pixd;
708 PIXA *pixas, *pixad;
709 
710  PROCNAME("pixSelectByAreaFraction");
711 
712  if (!pixs)
713  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
714  if (connectivity != 4 && connectivity != 8)
715  return (PIX *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
716  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
717  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
718  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
719  if (pchanged) *pchanged = FALSE;
720 
721  /* Check if any components exist */
722  pixZero(pixs, &empty);
723  if (empty)
724  return pixCopy(NULL, pixs);
725 
726  /* Filter components */
727  boxa = pixConnComp(pixs, &pixas, connectivity);
728  pixad = pixaSelectByAreaFraction(pixas, thresh, type, &changed);
729  boxaDestroy(&boxa);
730  pixaDestroy(&pixas);
731 
732  if (!changed) {
733  pixaDestroy(&pixad);
734  return pixCopy(NULL, pixs);
735  }
736 
737  /* Render the result */
738  if (pchanged) *pchanged = TRUE;
739  pixGetDimensions(pixs, &w, &h, NULL);
740  count = pixaGetCount(pixad);
741  if (count == 0) { /* return empty pix */
742  pixd = pixCreateTemplate(pixs);
743  } else {
744  pixd = pixaDisplay(pixad, w, h);
745  pixCopyResolution(pixd, pixs);
746  pixCopyColormap(pixd, pixs);
747  pixCopyText(pixd, pixs);
748  pixCopyInputFormat(pixd, pixs);
749  }
750  pixaDestroy(&pixad);
751  return pixd;
752 }
753 
754 
776 PIXA *
778  l_float32 thresh,
779  l_int32 type,
780  l_int32 *pchanged)
781 {
782 NUMA *na, *nai;
783 PIXA *pixad;
784 
785  PROCNAME("pixaSelectByAreaFraction");
786 
787  if (!pixas)
788  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
789  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
790  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
791  return (PIXA *)ERROR_PTR("invalid type", procName, NULL);
792 
793  /* Compute component ratios. */
794  na = pixaFindAreaFraction(pixas);
795 
796  /* Generate indicator array for elements to be saved. */
797  nai = numaMakeThresholdIndicator(na, thresh, type);
798  numaDestroy(&na);
799 
800  /* Filter to get output */
801  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
802 
803  numaDestroy(&nai);
804  return pixad;
805 }
806 
807 
831 PIX *
833  l_float32 thresh,
834  l_int32 connectivity,
835  l_int32 type,
836  l_int32 *pchanged)
837 {
838 l_int32 w, h, empty, changed, count;
839 BOXA *boxa;
840 PIX *pixd;
841 PIXA *pixas, *pixad;
842 
843  PROCNAME("pixSelectByWidthHeightRatio");
844 
845  if (!pixs)
846  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
847  if (connectivity != 4 && connectivity != 8)
848  return (PIX *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
849  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
850  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
851  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
852  if (pchanged) *pchanged = FALSE;
853 
854  /* Check if any components exist */
855  pixZero(pixs, &empty);
856  if (empty)
857  return pixCopy(NULL, pixs);
858 
859  /* Filter components */
860  boxa = pixConnComp(pixs, &pixas, connectivity);
861  pixad = pixaSelectByWidthHeightRatio(pixas, thresh, type, &changed);
862  boxaDestroy(&boxa);
863  pixaDestroy(&pixas);
864 
865  if (!changed) {
866  pixaDestroy(&pixad);
867  return pixCopy(NULL, pixs);
868  }
869 
870  /* Render the result */
871  if (pchanged) *pchanged = TRUE;
872  pixGetDimensions(pixs, &w, &h, NULL);
873  count = pixaGetCount(pixad);
874  if (count == 0) { /* return empty pix */
875  pixd = pixCreateTemplate(pixs);
876  } else {
877  pixd = pixaDisplay(pixad, w, h);
878  pixCopyResolution(pixd, pixs);
879  pixCopyColormap(pixd, pixs);
880  pixCopyText(pixd, pixs);
881  pixCopyInputFormat(pixd, pixs);
882  }
883  pixaDestroy(&pixad);
884  return pixd;
885 }
886 
887 
909 PIXA *
911  l_float32 thresh,
912  l_int32 type,
913  l_int32 *pchanged)
914 {
915 NUMA *na, *nai;
916 PIXA *pixad;
917 
918  PROCNAME("pixaSelectByWidthHeightRatio");
919 
920  if (!pixas)
921  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
922  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
923  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
924  return (PIXA *)ERROR_PTR("invalid type", procName, NULL);
925 
926  /* Compute component ratios. */
927  na = pixaFindWidthHeightRatio(pixas);
928 
929  /* Generate indicator array for elements to be saved. */
930  nai = numaMakeThresholdIndicator(na, thresh, type);
931  numaDestroy(&na);
932 
933  /* Filter to get output */
934  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
935 
936  numaDestroy(&nai);
937  return pixad;
938 }
939 
940 
959 PIXA *
961  l_int32 nmin,
962  l_int32 nmax,
963  l_int32 connectivity,
964  l_int32 *pchanged)
965 {
966 l_int32 n, i, count;
967 NUMA *na;
968 PIX *pix;
969 PIXA *pixad;
970 
971  PROCNAME("pixaSelectByNumConnComp");
972 
973  if (pchanged) *pchanged = 0;
974  if (!pixas)
975  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
976  if (nmin > nmax)
977  return (PIXA *)ERROR_PTR("nmin > nmax", procName, NULL);
978  if (connectivity != 4 && connectivity != 8)
979  return (PIXA *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
980 
981  /* Get indicator array based on number of c.c. */
982  n = pixaGetCount(pixas);
983  na = numaCreate(n);
984  for (i = 0; i < n; i++) {
985  pix = pixaGetPix(pixas, i, L_CLONE);
986  pixCountConnComp(pix, connectivity, &count);
987  if (count >= nmin && count <= nmax)
988  numaAddNumber(na, 1);
989  else
990  numaAddNumber(na, 0);
991  pixDestroy(&pix);
992  }
993 
994  /* Filter to get output */
995  pixad = pixaSelectWithIndicator(pixas, na, pchanged);
996  numaDestroy(&na);
997  return pixad;
998 }
999 
1000 
1018 PIXA *
1020  NUMA *na,
1021  l_int32 *pchanged)
1022 {
1023 l_int32 i, n, nbox, ival, nsave;
1024 BOX *box;
1025 PIX *pix1;
1026 PIXA *pixad;
1027 
1028  PROCNAME("pixaSelectWithIndicator");
1029 
1030  if (!pixas)
1031  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1032  if (!na)
1033  return (PIXA *)ERROR_PTR("na not defined", procName, NULL);
1034 
1035  nsave = 0;
1036  n = numaGetCount(na);
1037  for (i = 0; i < n; i++) {
1038  numaGetIValue(na, i, &ival);
1039  if (ival == 1) nsave++;
1040  }
1041 
1042  if (nsave == n) {
1043  if (pchanged) *pchanged = FALSE;
1044  return pixaCopy(pixas, L_CLONE);
1045  }
1046  if (pchanged) *pchanged = TRUE;
1047  pixad = pixaCreate(nsave);
1048  nbox = pixaGetBoxaCount(pixas);
1049  for (i = 0; i < n; i++) {
1050  numaGetIValue(na, i, &ival);
1051  if (ival == 0) continue;
1052  pix1 = pixaGetPix(pixas, i, L_CLONE);
1053  pixaAddPix(pixad, pix1, L_INSERT);
1054  if (nbox == n) { /* fully populated boxa */
1055  box = pixaGetBox(pixas, i, L_CLONE);
1056  pixaAddBox(pixad, box, L_INSERT);
1057  }
1058  }
1059 
1060  return pixad;
1061 }
1062 
1063 
1078 l_int32
1080  PIXA *pixa,
1081  NUMA *na)
1082 {
1083 l_int32 i, n, ival, x, y, w, h;
1084 BOX *box;
1085 PIX *pix;
1086 
1087  PROCNAME("pixRemoveWithIndicator");
1088 
1089  if (!pixs)
1090  return ERROR_INT("pixs not defined", procName, 1);
1091  if (!pixa)
1092  return ERROR_INT("pixa not defined", procName, 1);
1093  if (!na)
1094  return ERROR_INT("na not defined", procName, 1);
1095  n = pixaGetCount(pixa);
1096  if (n != numaGetCount(na))
1097  return ERROR_INT("pixa and na sizes not equal", procName, 1);
1098 
1099  for (i = 0; i < n; i++) {
1100  numaGetIValue(na, i, &ival);
1101  if (ival == 1) {
1102  pix = pixaGetPix(pixa, i, L_CLONE);
1103  box = pixaGetBox(pixa, i, L_CLONE);
1104  boxGetGeometry(box, &x, &y, &w, &h);
1105  pixRasterop(pixs, x, y, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1106  pix, 0, 0);
1107  boxDestroy(&box);
1108  pixDestroy(&pix);
1109  }
1110  }
1111 
1112  return 0;
1113 }
1114 
1115 
1131 l_int32
1133  PIXA *pixa,
1134  NUMA *na)
1135 {
1136 l_int32 i, n, ival, x, y, w, h;
1137 BOX *box;
1138 PIX *pix;
1139 
1140  PROCNAME("pixAddWithIndicator");
1141 
1142  if (!pixs)
1143  return ERROR_INT("pixs not defined", procName, 1);
1144  if (!pixa)
1145  return ERROR_INT("pixa not defined", procName, 1);
1146  if (!na)
1147  return ERROR_INT("na not defined", procName, 1);
1148  n = pixaGetCount(pixa);
1149  if (n != numaGetCount(na))
1150  return ERROR_INT("pixa and na sizes not equal", procName, 1);
1151 
1152  for (i = 0; i < n; i++) {
1153  numaGetIValue(na, i, &ival);
1154  if (ival == 1) {
1155  pix = pixaGetPix(pixa, i, L_CLONE);
1156  box = pixaGetBox(pixa, i, L_CLONE);
1157  boxGetGeometry(box, &x, &y, &w, &h);
1158  pixRasterop(pixs, x, y, w, h, PIX_SRC | PIX_DST, pix, 0, 0);
1159  boxDestroy(&box);
1160  pixDestroy(&pix);
1161  }
1162  }
1163 
1164  return 0;
1165 }
1166 
1167 
1184 PIXA *
1186  const char *str,
1187  l_int32 *perror)
1188 {
1189 l_int32 i, nval, npix, nbox, val, imaxval;
1190 l_float32 maxval;
1191 BOX *box;
1192 NUMA *na;
1193 PIX *pix1;
1194 PIXA *pixad;
1195 
1196  PROCNAME("pixaSelectWithString");
1197 
1198  if (perror) *perror = 0;
1199  if (!pixas)
1200  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1201  if (!str)
1202  return (PIXA *)ERROR_PTR("str not defined", procName, NULL);
1203 
1204  if ((na = numaCreateFromString(str)) == NULL)
1205  return (PIXA *)ERROR_PTR("na not made", procName, NULL);
1206  if ((nval = numaGetCount(na)) == 0) {
1207  numaDestroy(&na);
1208  return (PIXA *)ERROR_PTR("no indices found", procName, NULL);
1209  }
1210  numaGetMax(na, &maxval, NULL);
1211  imaxval = (l_int32)(maxval + 0.1);
1212  nbox = pixaGetBoxaCount(pixas);
1213  npix = pixaGetCount(pixas);
1214  if (imaxval >= npix) {
1215  if (perror) *perror = 1;
1216  L_ERROR("max index = %d, size of pixa = %d\n", procName, imaxval, npix);
1217  }
1218 
1219  pixad = pixaCreate(nval);
1220  for (i = 0; i < nval; i++) {
1221  numaGetIValue(na, i, &val);
1222  if (val < 0 || val >= npix) {
1223  L_ERROR("index %d out of range of pix\n", procName, val);
1224  continue;
1225  }
1226  pix1 = pixaGetPix(pixas, val, L_COPY);
1227  pixaAddPix(pixad, pix1, L_INSERT);
1228  if (nbox == npix) { /* fully populated boxa */
1229  box = pixaGetBox(pixas, val, L_COPY);
1230  pixaAddBox(pixad, box, L_INSERT);
1231  }
1232  }
1233  numaDestroy(&na);
1234  return pixad;
1235 }
1236 
1237 
1255 PIX *
1257  PIXA *pixa,
1258  l_int32 index)
1259 {
1260 l_int32 n, x, y, w, h, same, maxd;
1261 BOX *box;
1262 BOXA *boxa;
1263 PIX *pix;
1264 
1265  PROCNAME("pixaRenderComponent");
1266 
1267  if (!pixa)
1268  return (PIX *)ERROR_PTR("pixa not defined", procName, pixs);
1269  n = pixaGetCount(pixa);
1270  if (index < 0 || index >= n)
1271  return (PIX *)ERROR_PTR("invalid index", procName, pixs);
1272  if (pixs && (pixGetDepth(pixs) != 1))
1273  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixs);
1274  pixaVerifyDepth(pixa, &same, &maxd);
1275  if (maxd > 1)
1276  return (PIX *)ERROR_PTR("not all pix with d == 1", procName, pixs);
1277 
1278  boxa = pixaGetBoxa(pixa, L_CLONE);
1279  if (!pixs) {
1280  boxaGetExtent(boxa, &w, &h, NULL);
1281  pixs = pixCreate(w, h, 1);
1282  }
1283 
1284  pix = pixaGetPix(pixa, index, L_CLONE);
1285  box = boxaGetBox(boxa, index, L_CLONE);
1286  boxGetGeometry(box, &x, &y, &w, &h);
1287  pixRasterop(pixs, x, y, w, h, PIX_SRC | PIX_DST, pix, 0, 0);
1288  boxDestroy(&box);
1289  pixDestroy(&pix);
1290  boxaDestroy(&boxa);
1291 
1292  return pixs;
1293 }
1294 
1295 
1296 /*---------------------------------------------------------------------*
1297  * Sort functions *
1298  *---------------------------------------------------------------------*/
1325 PIXA *
1327  l_int32 sorttype,
1328  l_int32 sortorder,
1329  NUMA **pnaindex,
1330  l_int32 copyflag)
1331 {
1332 l_int32 i, n, nb, x, y, w, h;
1333 BOXA *boxa;
1334 NUMA *na, *naindex;
1335 PIXA *pixad;
1336 
1337  PROCNAME("pixaSort");
1338 
1339  if (pnaindex) *pnaindex = NULL;
1340  if (!pixas)
1341  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1342  if (sorttype != L_SORT_BY_X && sorttype != L_SORT_BY_Y &&
1343  sorttype != L_SORT_BY_WIDTH && sorttype != L_SORT_BY_HEIGHT &&
1344  sorttype != L_SORT_BY_MIN_DIMENSION &&
1345  sorttype != L_SORT_BY_MAX_DIMENSION &&
1346  sorttype != L_SORT_BY_PERIMETER &&
1347  sorttype != L_SORT_BY_AREA &&
1348  sorttype != L_SORT_BY_ASPECT_RATIO)
1349  return (PIXA *)ERROR_PTR("invalid sort type", procName, NULL);
1350  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
1351  return (PIXA *)ERROR_PTR("invalid sort order", procName, NULL);
1352  if (copyflag != L_COPY && copyflag != L_CLONE)
1353  return (PIXA *)ERROR_PTR("invalid copy flag", procName, NULL);
1354 
1355  /* Check the pixa and boxa counts. Make a boxa if required. */
1356  if ((n = pixaGetCount(pixas)) == 0) {
1357  L_INFO("no pix in pixa\n", procName);
1358  return pixaCopy(pixas, copyflag);
1359  }
1360  if ((boxa = pixas->boxa) == NULL) /* not owned; do not destroy */
1361  return (PIXA *)ERROR_PTR("boxa not found!", procName, NULL);
1362  nb = boxaGetCount(boxa);
1363  if (nb == 0) {
1364  pixaSetFullSizeBoxa(pixas);
1365  nb = n;
1366  boxa = pixas->boxa; /* not owned */
1367  if (sorttype == L_SORT_BY_X || sorttype == L_SORT_BY_Y)
1368  L_WARNING("sort by x or y where all values are 0\n", procName);
1369  }
1370  if (nb != n)
1371  return (PIXA *)ERROR_PTR("boxa and pixa counts differ", procName, NULL);
1372 
1373  /* Use O(n) binsort if possible */
1374  if (n > MIN_COMPS_FOR_BIN_SORT &&
1375  ((sorttype == L_SORT_BY_X) || (sorttype == L_SORT_BY_Y) ||
1376  (sorttype == L_SORT_BY_WIDTH) || (sorttype == L_SORT_BY_HEIGHT) ||
1377  (sorttype == L_SORT_BY_PERIMETER)))
1378  return pixaBinSort(pixas, sorttype, sortorder, pnaindex, copyflag);
1379 
1380  /* Build up numa of specific data */
1381  if ((na = numaCreate(n)) == NULL)
1382  return (PIXA *)ERROR_PTR("na not made", procName, NULL);
1383  for (i = 0; i < n; i++) {
1384  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
1385  switch (sorttype)
1386  {
1387  case L_SORT_BY_X:
1388  numaAddNumber(na, x);
1389  break;
1390  case L_SORT_BY_Y:
1391  numaAddNumber(na, y);
1392  break;
1393  case L_SORT_BY_WIDTH:
1394  numaAddNumber(na, w);
1395  break;
1396  case L_SORT_BY_HEIGHT:
1397  numaAddNumber(na, h);
1398  break;
1400  numaAddNumber(na, L_MIN(w, h));
1401  break;
1403  numaAddNumber(na, L_MAX(w, h));
1404  break;
1405  case L_SORT_BY_PERIMETER:
1406  numaAddNumber(na, w + h);
1407  break;
1408  case L_SORT_BY_AREA:
1409  numaAddNumber(na, w * h);
1410  break;
1412  numaAddNumber(na, (l_float32)w / (l_float32)h);
1413  break;
1414  default:
1415  L_WARNING("invalid sort type\n", procName);
1416  }
1417  }
1418 
1419  /* Get the sort index for data array */
1420  naindex = numaGetSortIndex(na, sortorder);
1421  numaDestroy(&na);
1422  if (!naindex)
1423  return (PIXA *)ERROR_PTR("naindex not made", procName, NULL);
1424 
1425  /* Build up sorted pixa using sort index */
1426  if ((pixad = pixaSortByIndex(pixas, naindex, copyflag)) == NULL) {
1427  numaDestroy(&naindex);
1428  return (PIXA *)ERROR_PTR("pixad not made", procName, NULL);
1429  }
1430 
1431  if (pnaindex)
1432  *pnaindex = naindex;
1433  else
1434  numaDestroy(&naindex);
1435  return pixad;
1436 }
1437 
1438 
1465 PIXA *
1467  l_int32 sorttype,
1468  l_int32 sortorder,
1469  NUMA **pnaindex,
1470  l_int32 copyflag)
1471 {
1472 l_int32 i, n, x, y, w, h;
1473 BOXA *boxa;
1474 NUMA *na, *naindex;
1475 PIXA *pixad;
1476 
1477  PROCNAME("pixaBinSort");
1478 
1479  if (pnaindex) *pnaindex = NULL;
1480  if (!pixas)
1481  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1482  if (sorttype != L_SORT_BY_X && sorttype != L_SORT_BY_Y &&
1483  sorttype != L_SORT_BY_WIDTH && sorttype != L_SORT_BY_HEIGHT &&
1484  sorttype != L_SORT_BY_PERIMETER)
1485  return (PIXA *)ERROR_PTR("invalid sort type", procName, NULL);
1486  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
1487  return (PIXA *)ERROR_PTR("invalid sort order", procName, NULL);
1488  if (copyflag != L_COPY && copyflag != L_CLONE)
1489  return (PIXA *)ERROR_PTR("invalid copy flag", procName, NULL);
1490 
1491  /* Verify that the pixa and its boxa have the same count */
1492  if ((boxa = pixas->boxa) == NULL) /* not owned; do not destroy */
1493  return (PIXA *)ERROR_PTR("boxa not found", procName, NULL);
1494  n = pixaGetCount(pixas);
1495  if (boxaGetCount(boxa) != n)
1496  return (PIXA *)ERROR_PTR("boxa and pixa counts differ", procName, NULL);
1497 
1498  /* Generate Numa of appropriate box dimensions */
1499  if ((na = numaCreate(n)) == NULL)
1500  return (PIXA *)ERROR_PTR("na not made", procName, NULL);
1501  for (i = 0; i < n; i++) {
1502  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
1503  switch (sorttype)
1504  {
1505  case L_SORT_BY_X:
1506  numaAddNumber(na, x);
1507  break;
1508  case L_SORT_BY_Y:
1509  numaAddNumber(na, y);
1510  break;
1511  case L_SORT_BY_WIDTH:
1512  numaAddNumber(na, w);
1513  break;
1514  case L_SORT_BY_HEIGHT:
1515  numaAddNumber(na, h);
1516  break;
1517  case L_SORT_BY_PERIMETER:
1518  numaAddNumber(na, w + h);
1519  break;
1520  default:
1521  L_WARNING("invalid sort type\n", procName);
1522  }
1523  }
1524 
1525  /* Get the sort index for data array */
1526  naindex = numaGetBinSortIndex(na, sortorder);
1527  numaDestroy(&na);
1528  if (!naindex)
1529  return (PIXA *)ERROR_PTR("naindex not made", procName, NULL);
1530 
1531  /* Build up sorted pixa using sort index */
1532  if ((pixad = pixaSortByIndex(pixas, naindex, copyflag)) == NULL) {
1533  numaDestroy(&naindex);
1534  return (PIXA *)ERROR_PTR("pixad not made", procName, NULL);
1535  }
1536 
1537  if (pnaindex)
1538  *pnaindex = naindex;
1539  else
1540  numaDestroy(&naindex);
1541  return pixad;
1542 }
1543 
1544 
1553 PIXA *
1555  NUMA *naindex,
1556  l_int32 copyflag)
1557 {
1558 l_int32 i, n, index;
1559 BOX *box;
1560 PIX *pix;
1561 PIXA *pixad;
1562 
1563  PROCNAME("pixaSortByIndex");
1564 
1565  if (!pixas)
1566  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1567  if (!naindex)
1568  return (PIXA *)ERROR_PTR("naindex not defined", procName, NULL);
1569  if (copyflag != L_CLONE && copyflag != L_COPY)
1570  return (PIXA *)ERROR_PTR("invalid copyflag", procName, NULL);
1571 
1572  n = pixaGetCount(pixas);
1573  pixad = pixaCreate(n);
1574  for (i = 0; i < n; i++) {
1575  numaGetIValue(naindex, i, &index);
1576  pix = pixaGetPix(pixas, index, copyflag);
1577  box = pixaGetBox(pixas, index, copyflag);
1578  pixaAddPix(pixad, pix, L_INSERT);
1579  pixaAddBox(pixad, box, L_INSERT);
1580  }
1581 
1582  return pixad;
1583 }
1584 
1585 
1594 PIXAA *
1596  NUMAA *naa,
1597  l_int32 copyflag)
1598 {
1599 l_int32 pixtot, ntot, i, j, n, nn, index;
1600 BOX *box;
1601 NUMA *na;
1602 PIX *pix;
1603 PIXA *pixa;
1604 PIXAA *paa;
1605 
1606  PROCNAME("pixaSort2dByIndex");
1607 
1608  if (!pixas)
1609  return (PIXAA *)ERROR_PTR("pixas not defined", procName, NULL);
1610  if (!naa)
1611  return (PIXAA *)ERROR_PTR("naindex not defined", procName, NULL);
1612 
1613  /* Check counts */
1614  ntot = numaaGetNumberCount(naa);
1615  pixtot = pixaGetCount(pixas);
1616  if (ntot != pixtot)
1617  return (PIXAA *)ERROR_PTR("element count mismatch", procName, NULL);
1618 
1619  n = numaaGetCount(naa);
1620  paa = pixaaCreate(n);
1621  for (i = 0; i < n; i++) {
1622  na = numaaGetNuma(naa, i, L_CLONE);
1623  nn = numaGetCount(na);
1624  pixa = pixaCreate(nn);
1625  for (j = 0; j < nn; j++) {
1626  numaGetIValue(na, j, &index);
1627  pix = pixaGetPix(pixas, index, copyflag);
1628  box = pixaGetBox(pixas, index, copyflag);
1629  pixaAddPix(pixa, pix, L_INSERT);
1630  pixaAddBox(pixa, box, L_INSERT);
1631  }
1632  pixaaAddPixa(paa, pixa, L_INSERT);
1633  numaDestroy(&na);
1634  }
1635 
1636  return paa;
1637 }
1638 
1639 
1640 /*---------------------------------------------------------------------*
1641  * Pixa and Pixaa range selection *
1642  *---------------------------------------------------------------------*/
1659 PIXA *
1661  l_int32 first,
1662  l_int32 last,
1663  l_int32 copyflag)
1664 {
1665 l_int32 n, npix, i;
1666 PIX *pix;
1667 PIXA *pixad;
1668 
1669  PROCNAME("pixaSelectRange");
1670 
1671  if (!pixas)
1672  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1673  if (copyflag != L_COPY && copyflag != L_CLONE)
1674  return (PIXA *)ERROR_PTR("invalid copyflag", procName, NULL);
1675  n = pixaGetCount(pixas);
1676  first = L_MAX(0, first);
1677  if (last <= 0) last = n - 1;
1678  if (first >= n)
1679  return (PIXA *)ERROR_PTR("invalid first", procName, NULL);
1680  if (first > last)
1681  return (PIXA *)ERROR_PTR("first > last", procName, NULL);
1682 
1683  npix = last - first + 1;
1684  pixad = pixaCreate(npix);
1685  for (i = first; i <= last; i++) {
1686  pix = pixaGetPix(pixas, i, copyflag);
1687  pixaAddPix(pixad, pix, L_INSERT);
1688  }
1689  return pixad;
1690 }
1691 
1692 
1709 PIXAA *
1711  l_int32 first,
1712  l_int32 last,
1713  l_int32 copyflag)
1714 {
1715 l_int32 n, npixa, i;
1716 PIXA *pixa;
1717 PIXAA *paad;
1718 
1719  PROCNAME("pixaaSelectRange");
1720 
1721  if (!paas)
1722  return (PIXAA *)ERROR_PTR("paas not defined", procName, NULL);
1723  if (copyflag != L_COPY && copyflag != L_CLONE)
1724  return (PIXAA *)ERROR_PTR("invalid copyflag", procName, NULL);
1725  n = pixaaGetCount(paas, NULL);
1726  first = L_MAX(0, first);
1727  if (last <= 0) last = n - 1;
1728  if (first >= n)
1729  return (PIXAA *)ERROR_PTR("invalid first", procName, NULL);
1730  if (first > last)
1731  return (PIXAA *)ERROR_PTR("first > last", procName, NULL);
1732 
1733  npixa = last - first + 1;
1734  paad = pixaaCreate(npixa);
1735  for (i = first; i <= last; i++) {
1736  pixa = pixaaGetPixa(paas, i, copyflag);
1737  pixaaAddPixa(paad, pixa, L_INSERT);
1738  }
1739  return paad;
1740 }
1741 
1742 
1743 /*---------------------------------------------------------------------*
1744  * Pixa and Pixaa scaling *
1745  *---------------------------------------------------------------------*/
1765 PIXAA *
1767  l_int32 wd,
1768  l_int32 hd)
1769 {
1770 l_int32 n, i;
1771 PIXA *pixa1, *pixa2;
1772 PIXAA *paad;
1773 
1774  PROCNAME("pixaaScaleToSize");
1775 
1776  if (!paas)
1777  return (PIXAA *)ERROR_PTR("paas not defined", procName, NULL);
1778  if (wd <= 0 && hd <= 0)
1779  return (PIXAA *)ERROR_PTR("neither wd nor hd > 0", procName, NULL);
1780 
1781  n = pixaaGetCount(paas, NULL);
1782  paad = pixaaCreate(n);
1783  for (i = 0; i < n; i++) {
1784  pixa1 = pixaaGetPixa(paas, i, L_CLONE);
1785  pixa2 = pixaScaleToSize(pixa1, wd, hd);
1786  pixaaAddPixa(paad, pixa2, L_INSERT);
1787  pixaDestroy(&pixa1);
1788  }
1789  return paad;
1790 }
1791 
1792 
1814 PIXAA *
1816  NUMA *nawd,
1817  NUMA *nahd)
1818 {
1819 l_int32 n, i, wd, hd;
1820 PIXA *pixa1, *pixa2;
1821 PIXAA *paad;
1822 
1823  PROCNAME("pixaaScaleToSizeVar");
1824 
1825  if (!paas)
1826  return (PIXAA *)ERROR_PTR("paas not defined", procName, NULL);
1827  if (!nawd && !nahd)
1828  return (PIXAA *)ERROR_PTR("!nawd && !nahd", procName, NULL);
1829 
1830  n = pixaaGetCount(paas, NULL);
1831  if (nawd && (n != numaGetCount(nawd)))
1832  return (PIXAA *)ERROR_PTR("nawd wrong size", procName, NULL);
1833  if (nahd && (n != numaGetCount(nahd)))
1834  return (PIXAA *)ERROR_PTR("nahd wrong size", procName, NULL);
1835  paad = pixaaCreate(n);
1836  for (i = 0; i < n; i++) {
1837  wd = hd = 0;
1838  if (nawd) numaGetIValue(nawd, i, &wd);
1839  if (nahd) numaGetIValue(nahd, i, &hd);
1840  pixa1 = pixaaGetPixa(paas, i, L_CLONE);
1841  pixa2 = pixaScaleToSize(pixa1, wd, hd);
1842  pixaaAddPixa(paad, pixa2, L_INSERT);
1843  pixaDestroy(&pixa1);
1844  }
1845  return paad;
1846 }
1847 
1848 
1862 PIXA *
1864  l_int32 wd,
1865  l_int32 hd)
1866 {
1867 l_int32 n, i;
1868 PIX *pix1, *pix2;
1869 PIXA *pixad;
1870 
1871  PROCNAME("pixaScaleToSize");
1872 
1873  if (!pixas)
1874  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1875 
1876  if (wd <= 0 && hd <= 0) /* no scaling requested */
1877  return pixaCopy(pixas, L_CLONE);
1878 
1879  n = pixaGetCount(pixas);
1880  pixad = pixaCreate(n);
1881  for (i = 0; i < n; i++) {
1882  pix1 = pixaGetPix(pixas, i, L_CLONE);
1883  pix2 = pixScaleToSize(pix1, wd, hd);
1884  pixCopyText(pix2, pix1);
1885  pixaAddPix(pixad, pix2, L_INSERT);
1886  pixDestroy(&pix1);
1887  }
1888  return pixad;
1889 }
1890 
1891 
1907 PIXA *
1909  l_int32 delw,
1910  l_int32 delh)
1911 {
1912 l_int32 n, i;
1913 PIX *pix1, *pix2;
1914 PIXA *pixad;
1915 
1916  PROCNAME("pixaScaleToSizeRel");
1917 
1918  if (!pixas)
1919  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1920 
1921  n = pixaGetCount(pixas);
1922  pixad = pixaCreate(n);
1923  for (i = 0; i < n; i++) {
1924  pix1 = pixaGetPix(pixas, i, L_CLONE);
1925  pix2 = pixScaleToSizeRel(pix1, delw, delh);
1926  if (pix2) {
1927  pixaAddPix(pixad, pix2, L_INSERT);
1928  } else {
1929  L_WARNING("relative scale to size failed; use a copy\n", procName);
1930  pixaAddPix(pixad, pix1, L_COPY);
1931  }
1932  pixDestroy(&pix1);
1933  }
1934  return pixad;
1935 }
1936 
1937 
1951 PIXA *
1953  l_float32 scalex,
1954  l_float32 scaley)
1955 {
1956 l_int32 i, n, nb;
1957 BOXA *boxa1, *boxa2;
1958 PIX *pix1, *pix2;
1959 PIXA *pixad;
1960 
1961  PROCNAME("pixaScale");
1962 
1963  if (!pixas)
1964  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1965  if (scalex <= 0.0 || scaley <= 0.0)
1966  return (PIXA *)ERROR_PTR("invalid scaling parameters", procName, NULL);
1967 
1968  n = pixaGetCount(pixas);
1969  pixad = pixaCreate(n);
1970  for (i = 0; i < n; i++) {
1971  pix1 = pixaGetPix(pixas, i, L_CLONE);
1972  pix2 = pixScale(pix1, scalex, scaley);
1973  pixCopyText(pix2, pix1);
1974  pixaAddPix(pixad, pix2, L_INSERT);
1975  pixDestroy(&pix1);
1976  }
1977 
1978  boxa1 = pixaGetBoxa(pixas, L_CLONE);
1979  nb = boxaGetCount(boxa1);
1980  if (nb == n) {
1981  boxa2 = boxaTransform(boxa1, 0, 0, scalex, scaley);
1982  pixaSetBoxa(pixad, boxa2, L_INSERT);
1983  }
1984  boxaDestroy(&boxa1);
1985  return pixad;
1986 }
1987 
1988 
1989 /*---------------------------------------------------------------------*
1990  * Miscellaneous functions *
1991  *---------------------------------------------------------------------*/
2021 PIXA *
2023  PIXA *pixas,
2024  l_int32 left,
2025  l_int32 right,
2026  l_int32 top,
2027  l_int32 bot,
2028  l_uint32 val)
2029 {
2030 l_int32 i, n, nbox;
2031 BOX *box;
2032 BOXA *boxad;
2033 PIX *pixs, *pixd;
2034 
2035  PROCNAME("pixaAddBorderGeneral");
2036 
2037  if (!pixas)
2038  return (PIXA *)ERROR_PTR("pixas not defined", procName, pixad);
2039  if (left < 0 || right < 0 || top < 0 || bot < 0)
2040  return (PIXA *)ERROR_PTR("negative border added!", procName, pixad);
2041  if (pixad && (pixad != pixas))
2042  return (PIXA *)ERROR_PTR("pixad defined but != pixas", procName, pixad);
2043 
2044  n = pixaGetCount(pixas);
2045  if (!pixad)
2046  pixad = pixaCreate(n);
2047  for (i = 0; i < n; i++) {
2048  pixs = pixaGetPix(pixas, i, L_CLONE);
2049  pixd = pixAddBorderGeneral(pixs, left, right, top, bot, val);
2050  if (pixad == pixas) /* replace */
2051  pixaReplacePix(pixad, i, pixd, NULL);
2052  else
2053  pixaAddPix(pixad, pixd, L_INSERT);
2054  pixDestroy(&pixs);
2055  }
2056 
2057  nbox = pixaGetBoxaCount(pixas);
2058  boxad = pixaGetBoxa(pixad, L_CLONE);
2059  for (i = 0; i < nbox; i++) {
2060  if ((box = pixaGetBox(pixas, i, L_COPY)) == NULL) {
2061  L_WARNING("box %d not found\n", procName, i);
2062  break;
2063  }
2064  boxAdjustSides(box, box, -left, right, -top, bot);
2065  if (pixad == pixas) /* replace */
2066  boxaReplaceBox(boxad, i, box);
2067  else
2068  boxaAddBox(boxad, box, L_INSERT);
2069  }
2070  boxaDestroy(&boxad);
2071 
2072  return pixad;
2073 }
2074 
2075 
2092 PIXA *
2094  NUMA **pnaindex,
2095  l_int32 copyflag)
2096 {
2097 l_int32 i, j, m, mb, n;
2098 BOX *box;
2099 NUMA *naindex;
2100 PIX *pix;
2101 PIXA *pixa, *pixat;
2102 
2103  PROCNAME("pixaaFlattenToPixa");
2104 
2105  if (pnaindex) *pnaindex = NULL;
2106  if (!paa)
2107  return (PIXA *)ERROR_PTR("paa not defined", procName, NULL);
2108  if (copyflag != L_COPY && copyflag != L_CLONE)
2109  return (PIXA *)ERROR_PTR("invalid copyflag", procName, NULL);
2110 
2111  if (pnaindex) {
2112  naindex = numaCreate(0);
2113  *pnaindex = naindex;
2114  }
2115 
2116  n = pixaaGetCount(paa, NULL);
2117  pixa = pixaCreate(n);
2118  for (i = 0; i < n; i++) {
2119  pixat = pixaaGetPixa(paa, i, L_CLONE);
2120  m = pixaGetCount(pixat);
2121  mb = pixaGetBoxaCount(pixat);
2122  for (j = 0; j < m; j++) {
2123  pix = pixaGetPix(pixat, j, copyflag);
2124  pixaAddPix(pixa, pix, L_INSERT);
2125  if (j < mb) {
2126  box = pixaGetBox(pixat, j, copyflag);
2127  pixaAddBox(pixa, box, L_INSERT);
2128  }
2129  if (pnaindex)
2130  numaAddNumber(naindex, i); /* save 'row' number */
2131  }
2132  pixaDestroy(&pixat);
2133  }
2134 
2135  return pixa;
2136 }
2137 
2138 
2147 l_int32
2149  l_int32 *pminw,
2150  l_int32 *pminh,
2151  l_int32 *pmaxw,
2152  l_int32 *pmaxh)
2153 {
2154 l_int32 minw, minh, maxw, maxh, minpw, minph, maxpw, maxph, i, n;
2155 PIXA *pixa;
2156 
2157  PROCNAME("pixaaSizeRange");
2158 
2159  if (pminw) *pminw = 0;
2160  if (pminh) *pminh = 0;
2161  if (pmaxw) *pmaxw = 0;
2162  if (pmaxh) *pmaxh = 0;
2163  if (!paa)
2164  return ERROR_INT("paa not defined", procName, 1);
2165  if (!pminw && !pmaxw && !pminh && !pmaxh)
2166  return ERROR_INT("no data can be returned", procName, 1);
2167 
2168  minw = minh = 100000000;
2169  maxw = maxh = 0;
2170  n = pixaaGetCount(paa, NULL);
2171  for (i = 0; i < n; i++) {
2172  pixa = pixaaGetPixa(paa, i, L_CLONE);
2173  pixaSizeRange(pixa, &minpw, &minph, &maxpw, &maxph);
2174  if (minpw < minw)
2175  minw = minpw;
2176  if (minph < minh)
2177  minh = minph;
2178  if (maxpw > maxw)
2179  maxw = maxpw;
2180  if (maxph > maxh)
2181  maxh = maxph;
2182  pixaDestroy(&pixa);
2183  }
2184 
2185  if (pminw) *pminw = minw;
2186  if (pminh) *pminh = minh;
2187  if (pmaxw) *pmaxw = maxw;
2188  if (pmaxh) *pmaxh = maxh;
2189  return 0;
2190 }
2191 
2192 
2201 l_int32
2203  l_int32 *pminw,
2204  l_int32 *pminh,
2205  l_int32 *pmaxw,
2206  l_int32 *pmaxh)
2207 {
2208 l_int32 minw, minh, maxw, maxh, i, n, w, h;
2209 PIX *pix;
2210 
2211  PROCNAME("pixaSizeRange");
2212 
2213  if (pminw) *pminw = 0;
2214  if (pminh) *pminh = 0;
2215  if (pmaxw) *pmaxw = 0;
2216  if (pmaxh) *pmaxh = 0;
2217  if (!pixa)
2218  return ERROR_INT("pixa not defined", procName, 1);
2219  if (!pminw && !pmaxw && !pminh && !pmaxh)
2220  return ERROR_INT("no data can be returned", procName, 1);
2221 
2222  minw = minh = 1000000;
2223  maxw = maxh = 0;
2224  n = pixaGetCount(pixa);
2225  for (i = 0; i < n; i++) {
2226  pix = pixaGetPix(pixa, i, L_CLONE);
2227  w = pixGetWidth(pix);
2228  h = pixGetHeight(pix);
2229  if (w < minw)
2230  minw = w;
2231  if (h < minh)
2232  minh = h;
2233  if (w > maxw)
2234  maxw = w;
2235  if (h > maxh)
2236  maxh = h;
2237  pixDestroy(&pix);
2238  }
2239 
2240  if (pminw) *pminw = minw;
2241  if (pminh) *pminh = minh;
2242  if (pmaxw) *pmaxw = maxw;
2243  if (pmaxh) *pmaxh = maxh;
2244 
2245  return 0;
2246 }
2247 
2248 
2271 PIXA *
2273  PIX *pixs)
2274 {
2275 l_int32 i, n;
2276 BOX *box;
2277 PIX *pix, *pixc;
2278 PIXA *pixad;
2279 
2280  PROCNAME("pixaClipToPix");
2281 
2282  if (!pixas)
2283  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
2284  if (!pixs)
2285  return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
2286 
2287  n = pixaGetCount(pixas);
2288  if ((pixad = pixaCreate(n)) == NULL)
2289  return (PIXA *)ERROR_PTR("pixad not made", procName, NULL);
2290 
2291  for (i = 0; i < n; i++) {
2292  pix = pixaGetPix(pixas, i, L_CLONE);
2293  box = pixaGetBox(pixas, i, L_COPY);
2294  pixc = pixClipRectangle(pixs, box, NULL);
2295  pixAnd(pixc, pixc, pix);
2296  pixaAddPix(pixad, pixc, L_INSERT);
2297  pixaAddBox(pixad, box, L_INSERT);
2298  pixDestroy(&pix);
2299  }
2300 
2301  return pixad;
2302 }
2303 
2304 
2320 l_int32
2322  PIXA **ppixad,
2323  BOXA **pboxa)
2324 {
2325 l_int32 i, n;
2326 BOX *box1;
2327 PIX *pix1, *pix2;
2328 
2329  PROCNAME("pixaClipToForeground");
2330 
2331  if (ppixad) *ppixad = NULL;
2332  if (pboxa) *pboxa = NULL;
2333  if (!pixas)
2334  return ERROR_INT("pixas not defined", procName, 1);
2335  if (!ppixad && !pboxa)
2336  return ERROR_INT("no output requested", procName, 1);
2337 
2338  n = pixaGetCount(pixas);
2339  if (ppixad) *ppixad = pixaCreate(n);
2340  if (pboxa) *pboxa = boxaCreate(n);
2341  for (i = 0; i < n; i++) {
2342  pix1 = pixaGetPix(pixas, i, L_CLONE);
2343  pixClipToForeground(pix1, &pix2, &box1);
2344  pixDestroy(&pix1);
2345  if (ppixad)
2346  pixaAddPix(*ppixad, pix2, L_INSERT);
2347  else
2348  pixDestroy(&pix2);
2349  if (pboxa)
2350  boxaAddBox(*pboxa, box1, L_INSERT);
2351  else
2352  boxDestroy(&box1);
2353  }
2354 
2355  return 0;
2356 }
2357 
2358 
2366 l_int32
2368  l_int32 *pdepth)
2369 {
2370 l_int32 hascolor, maxdepth;
2371 
2372  PROCNAME("pixaGetRenderingDepth");
2373 
2374  if (!pdepth)
2375  return ERROR_INT("&depth not defined", procName, 1);
2376  *pdepth = 0;
2377  if (!pixa)
2378  return ERROR_INT("pixa not defined", procName, 1);
2379 
2380  pixaHasColor(pixa, &hascolor);
2381  if (hascolor) {
2382  *pdepth = 32;
2383  return 0;
2384  }
2385 
2386  pixaGetDepthInfo(pixa, &maxdepth, NULL);
2387  if (maxdepth == 1)
2388  *pdepth = 1;
2389  else /* 2, 4, 8 or 16 */
2390  *pdepth = 8;
2391  return 0;
2392 }
2393 
2394 
2403 l_int32
2405  l_int32 *phascolor)
2406 {
2407 l_int32 i, n, hascolor, d;
2408 PIX *pix;
2409 PIXCMAP *cmap;
2410 
2411  PROCNAME("pixaHasColor");
2412 
2413  if (!phascolor)
2414  return ERROR_INT("&hascolor not defined", procName, 1);
2415  *phascolor = 0;
2416  if (!pixa)
2417  return ERROR_INT("pixa not defined", procName, 1);
2418 
2419  n = pixaGetCount(pixa);
2420  hascolor = 0;
2421  for (i = 0; i < n; i++) {
2422  pix = pixaGetPix(pixa, i, L_CLONE);
2423  if ((cmap = pixGetColormap(pix)) != NULL)
2424  pixcmapHasColor(cmap, &hascolor);
2425  d = pixGetDepth(pix);
2426  pixDestroy(&pix);
2427  if (d == 32 || hascolor == 1) {
2428  *phascolor = 1;
2429  break;
2430  }
2431  }
2432 
2433  return 0;
2434 }
2435 
2436 
2444 l_int32
2446  l_int32 *phascmap)
2447 {
2448 l_int32 i, n;
2449 PIX *pix;
2450 PIXCMAP *cmap;
2451 
2452  PROCNAME("pixaAnyColormaps");
2453 
2454  if (!phascmap)
2455  return ERROR_INT("&hascmap not defined", procName, 1);
2456  *phascmap = 0;
2457  if (!pixa)
2458  return ERROR_INT("pixa not defined", procName, 1);
2459 
2460  n = pixaGetCount(pixa);
2461  for (i = 0; i < n; i++) {
2462  pix = pixaGetPix(pixa, i, L_CLONE);
2463  cmap = pixGetColormap(pix);
2464  pixDestroy(&pix);
2465  if (cmap) {
2466  *phascmap = 1;
2467  return 0;
2468  }
2469  }
2470 
2471  return 0;
2472 }
2473 
2474 
2483 l_int32
2485  l_int32 *pmaxdepth,
2486  l_int32 *psame)
2487 {
2488 l_int32 i, n, d, d0;
2489 l_int32 maxd, same; /* depth info */
2490 
2491  PROCNAME("pixaGetDepthInfo");
2492 
2493  if (pmaxdepth) *pmaxdepth = 0;
2494  if (psame) *psame = TRUE;
2495  if (!pmaxdepth && !psame) return 0;
2496  if (!pixa)
2497  return ERROR_INT("pixa not defined", procName, 1);
2498  if ((n = pixaGetCount(pixa)) == 0)
2499  return ERROR_INT("pixa is empty", procName, 1);
2500 
2501  same = TRUE;
2502  maxd = 0;
2503  for (i = 0; i < n; i++) {
2504  pixaGetPixDimensions(pixa, i, NULL, NULL, &d);
2505  if (i == 0)
2506  d0 = d;
2507  else if (d != d0)
2508  same = FALSE;
2509  if (d > maxd) maxd = d;
2510  }
2511 
2512  if (pmaxdepth) *pmaxdepth = maxd;
2513  if (psame) *psame = same;
2514  return 0;
2515 }
2516 
2517 
2532 PIXA *
2534 {
2535 l_int32 i, n, same, hascmap, maxdepth;
2536 BOXA *boxa;
2537 PIX *pix1, *pix2;
2538 PIXA *pixa1, *pixad;
2539 
2540  PROCNAME("pixaConvertToSameDepth");
2541 
2542  if (!pixas)
2543  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
2544 
2545  /* Remove colormaps to rgb */
2546  if ((n = pixaGetCount(pixas)) == 0)
2547  return (PIXA *)ERROR_PTR("no components", procName, NULL);
2548  pixaAnyColormaps(pixas, &hascmap);
2549  if (hascmap) {
2550  pixa1 = pixaCreate(n);
2551  for (i = 0; i < n; i++) {
2552  pix1 = pixaGetPix(pixas, i, L_CLONE);
2553  pix2 = pixConvertTo32(pix1);
2554  pixaAddPix(pixa1, pix2, L_INSERT);
2555  pixDestroy(&pix1);
2556  }
2557  } else {
2558  pixa1 = pixaCopy(pixas, L_CLONE);
2559  }
2560 
2561  pixaGetDepthInfo(pixa1, &maxdepth, &same);
2562  if (!same) { /* at least one pix has depth < maxdepth */
2563  pixad = pixaCreate(n);
2564  for (i = 0; i < n; i++) {
2565  pix1 = pixaGetPix(pixa1, i, L_CLONE);
2566  if (maxdepth <= 8)
2567  pix2 = pixConvertTo8(pix1, 0);
2568  else
2569  pix2 = pixConvertTo32(pix1);
2570  pixaAddPix(pixad, pix2, L_INSERT);
2571  pixDestroy(&pix1);
2572  }
2573  } else {
2574  pixad = pixaCopy(pixa1, L_CLONE);
2575  }
2576 
2577  boxa = pixaGetBoxa(pixas, L_COPY);
2578  pixaSetBoxa(pixad, boxa, L_INSERT);
2579  pixaDestroy(&pixa1);
2580  return pixad;
2581 }
2582 
2583 
2612 l_int32
2614  PIXA *pixa2,
2615  l_int32 maxdist,
2616  NUMA **pnaindex,
2617  l_int32 *psame)
2618 {
2619 l_int32 i, j, n, same, sameboxa;
2620 BOXA *boxa1, *boxa2;
2621 NUMA *na;
2622 PIX *pix1, *pix2;
2623 
2624  PROCNAME("pixaEqual");
2625 
2626  if (pnaindex) *pnaindex = NULL;
2627  if (!psame)
2628  return ERROR_INT("&same not defined", procName, 1);
2629  *psame = 0;
2630  sameboxa = 0;
2631  na = NULL;
2632  if (!pixa1 || !pixa2)
2633  return ERROR_INT("pixa1 and pixa2 not both defined", procName, 1);
2634  n = pixaGetCount(pixa1);
2635  if (n != pixaGetCount(pixa2))
2636  return 0;
2637  boxa1 = pixaGetBoxa(pixa1, L_CLONE);
2638  boxa2 = pixaGetBoxa(pixa2, L_CLONE);
2639  if (!boxa1 && !boxa2)
2640  maxdist = 0; /* exact ordering required */
2641  if (boxa1 && !boxa2) {
2642  boxaDestroy(&boxa1);
2643  return 0;
2644  }
2645  if (!boxa1 && boxa2) {
2646  boxaDestroy(&boxa2);
2647  return 0;
2648  }
2649  if (boxa1 && boxa2) {
2650  boxaEqual(boxa1, boxa2, maxdist, &na, &sameboxa);
2651  boxaDestroy(&boxa1);
2652  boxaDestroy(&boxa2);
2653  if (!sameboxa) {
2654  numaDestroy(&na);
2655  return 0;
2656  }
2657  }
2658 
2659  for (i = 0; i < n; i++) {
2660  pix1 = pixaGetPix(pixa1, i, L_CLONE);
2661  if (na)
2662  numaGetIValue(na, i, &j);
2663  else
2664  j = i;
2665  pix2 = pixaGetPix(pixa2, j, L_CLONE);
2666  pixEqual(pix1, pix2, &same);
2667  pixDestroy(&pix1);
2668  pixDestroy(&pix2);
2669  if (!same) {
2670  numaDestroy(&na);
2671  return 0;
2672  }
2673  }
2674 
2675  *psame = 1;
2676  if (pnaindex)
2677  *pnaindex = na;
2678  else
2679  numaDestroy(&na);
2680  return 0;
2681 }
2682 
2683 
2698 PIXA *
2700  l_int32 rotation)
2701 {
2702 l_int32 i, n, nb, w, h;
2703 BOX *boxs, *boxd;
2704 PIX *pixs, *pixd;
2705 PIXA *pixad;
2706 
2707  PROCNAME("pixaRotateOrth");
2708 
2709  if (!pixas)
2710  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
2711  if (rotation < 0 || rotation > 3)
2712  return (PIXA *)ERROR_PTR("rotation not in {0,1,2,3}", procName, NULL);
2713  if (rotation == 0)
2714  return pixaCopy(pixas, L_COPY);
2715 
2716  n = pixaGetCount(pixas);
2717  nb = pixaGetBoxaCount(pixas);
2718  if ((pixad = pixaCreate(n)) == NULL)
2719  return (PIXA *)ERROR_PTR("pixad not made", procName, NULL);
2720  for (i = 0; i < n; i++) {
2721  if ((pixs = pixaGetPix(pixas, i, L_CLONE)) == NULL) {
2722  pixaDestroy(&pixad);
2723  return (PIXA *)ERROR_PTR("pixs not found", procName, NULL);
2724  }
2725  pixd = pixRotateOrth(pixs, rotation);
2726  pixaAddPix(pixad, pixd, L_INSERT);
2727  if (n == nb) {
2728  boxs = pixaGetBox(pixas, i, L_COPY);
2729  pixGetDimensions(pixs, &w, &h, NULL);
2730  boxd = boxRotateOrth(boxs, w, h, rotation);
2731  pixaAddBox(pixad, boxd, L_INSERT);
2732  boxDestroy(&boxs);
2733  }
2734  pixDestroy(&pixs);
2735  }
2736 
2737  return pixad;
2738 }
2739 
2740 
2754 l_int32
2756 {
2757 l_int32 i, n, w, h;
2758 BOX *box;
2759 BOXA *boxa;
2760 PIX *pix;
2761 
2762  PROCNAME("pixaSetFullSizeBoxa");
2763 
2764  if (!pixa)
2765  return ERROR_INT("pixa not defined", procName, 1);
2766  if ((n = pixaGetCount(pixa)) == 0) {
2767  L_INFO("pixa contains no pix\n", procName);
2768  return 0;
2769  }
2770 
2771  boxa = boxaCreate(n);
2772  pixaSetBoxa(pixa, boxa, L_INSERT);
2773  for (i = 0; i < n; i++) {
2774  pix = pixaGetPix(pixa, i, L_CLONE);
2775  pixGetDimensions(pix, &w, &h, NULL);
2776  box = boxCreate(0, 0, w, h);
2777  boxaAddBox(boxa, box, L_INSERT);
2778  pixDestroy(&pix);
2779  }
2780  return 0;
2781 }
2782 
PIXA * pixaSelectByPerimToAreaRatio(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByPerimToAreaRatio()
Definition: pixafunc1.c:512
l_int32 pixRemoveWithIndicator(PIX *pixs, PIXA *pixa, NUMA *na)
pixRemoveWithIndicator()
Definition: pixafunc1.c:1079
PIXA * pixaSortByIndex(PIXA *pixas, NUMA *naindex, l_int32 copyflag)
pixaSortByIndex()
Definition: pixafunc1.c:1554
l_int32 pixCopyColormap(PIX *pixd, PIX *pixs)
pixCopyColormap()
Definition: pix1.c:735
l_int32 pixaReplacePix(PIXA *pixa, l_int32 index, PIX *pix, BOX *box)
pixaReplacePix()
Definition: pixabasic.c:1283
PIXAA * pixaaCreate(l_int32 n)
pixaaCreate()
Definition: pixabasic.c:1769
BOX * boxRotateOrth(BOX *box, l_int32 w, l_int32 h, l_int32 rotation)
boxRotateOrth()
Definition: boxfunc2.c:506
l_int32 numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:472
PIXAA * pixaSort2dByIndex(PIXA *pixas, NUMAA *naa, l_int32 copyflag)
pixaSort2dByIndex()
Definition: pixafunc1.c:1595
NUMA * numaGetSortIndex(NUMA *na, l_int32 sortorder)
numaGetSortIndex()
Definition: numafunc1.c:2621
NUMA * pixaFindAreaFraction(PIXA *pixa)
pixaFindAreaFraction()
Definition: pix5.c:428
PIX * pixScaleToSizeRel(PIX *pixs, l_int32 delw, l_int32 delh)
pixScaleToSizeRel()
Definition: scale1.c:273
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3233
struct Boxa * boxa
Definition: pix.h:460
PIXA * pixaSelectWithIndicator(PIXA *pixas, NUMA *na, l_int32 *pchanged)
pixaSelectWithIndicator()
Definition: pixafunc1.c:1019
l_int32 pixaaAddPixa(PIXAA *paa, PIXA *pixa, l_int32 copyflag)
pixaaAddPixa()
Definition: pixabasic.c:1920
l_int32 pixaGetDepthInfo(PIXA *pixa, l_int32 *pmaxdepth, l_int32 *psame)
pixaGetDepthInfo()
Definition: pixafunc1.c:2484
l_int32 numaaGetNumberCount(NUMAA *naa)
numaaGetNumberCount()
Definition: numabasic.c:1555
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:161
l_int32 pixZero(PIX *pix, l_int32 *pempty)
pixZero()
Definition: pix3.c:1702
NUMA * numaGetBinSortIndex(NUMA *nas, l_int32 sortorder)
numaGetBinSortIndex()
Definition: numafunc1.c:2697
l_int32 boxaEqual(BOXA *boxa1, BOXA *boxa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame)
boxaEqual()
Definition: boxfunc1.c:2104
l_int32 numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:473
PIXA * pixaaGetPixa(PIXAA *paa, l_int32 index, l_int32 accesstype)
pixaaGetPixa()
Definition: pixabasic.c:2112
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
l_int32 pixaaGetCount(PIXAA *paa, NUMA **pna)
pixaaGetCount()
Definition: pixabasic.c:2063
PIXA * pixaRotateOrth(PIXA *pixas, l_int32 rotation)
pixaRotateOrth()
Definition: pixafunc1.c:2699
PIXA * pixaaFlattenToPixa(PIXAA *paa, NUMA **pnaindex, l_int32 copyflag)
pixaaFlattenToPixa()
Definition: pixafunc1.c:2093
l_int32 boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:615
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
PIX * pixSelectBySize(PIX *pixs, l_int32 width, l_int32 height, l_int32 connectivity, l_int32 type, l_int32 relation, l_int32 *pchanged)
pixSelectBySize()
Definition: pixafunc1.c:204
PIXA * pixaConvertToSameDepth(PIXA *pixas)
pixaConvertToSameDepth()
Definition: pixafunc1.c:2533
NUMA * pixaFindWidthHeightRatio(PIXA *pixa)
pixaFindWidthHeightRatio()
Definition: pix5.c:657
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:186
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:577
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:785
l_int32 pixaAnyColormaps(PIXA *pixa, l_int32 *phascmap)
pixaAnyColormaps()
Definition: pixafunc1.c:2445
NUMA * pixaFindPerimSizeRatio(PIXA *pixa)
pixaFindPerimSizeRatio()
Definition: pix5.c:332
l_int32 boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:860
PIX * pixaDisplay(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplay()
Definition: pixafunc2.c:179
PIXA * pixaScaleToSize(PIXA *pixas, l_int32 wd, l_int32 hd)
pixaScaleToSize()
Definition: pixafunc1.c:1863
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1013
Definition: pix.h:492
NUMA * pixaFindPerimToAreaRatio(PIXA *pixa)
pixaFindPerimToAreaRatio()
Definition: pix5.c:228
l_int32 pixaGetBoxaCount(PIXA *pixa)
pixaGetBoxaCount()
Definition: pixabasic.c:753
l_int32 pixaVerifyDepth(PIXA *pixa, l_int32 *psame, l_int32 *pmaxd)
pixaVerifyDepth()
Definition: pixabasic.c:929
PIX * pixaRenderComponent(PIX *pixs, PIXA *pixa, l_int32 index)
pixaRenderComponent()
Definition: pixafunc1.c:1256
l_int32 pixaSizeRange(PIXA *pixa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
pixaSizeRange()
Definition: pixafunc1.c:2202
l_int32 pixaEqual(PIXA *pixa1, PIXA *pixa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame)
pixaEqual()
Definition: pixafunc1.c:2613
l_int32 pixAddWithIndicator(PIX *pixs, PIXA *pixa, NUMA *na)
pixAddWithIndicator()
Definition: pixafunc1.c:1132
PIXA * pixaCopy(PIXA *pixa, l_int32 copyflag)
pixaCopy()
Definition: pixabasic.c:440
PIXA * pixaSelectByNumConnComp(PIXA *pixas, l_int32 nmin, l_int32 nmax, l_int32 connectivity, l_int32 *pchanged)
pixaSelectByNumConnComp()
Definition: pixafunc1.c:960
l_int32 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
PIXAA * pixaaScaleToSize(PIXAA *paas, l_int32 wd, l_int32 hd)
pixaaScaleToSize()
Definition: pixafunc1.c:1766
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:144
NUMA * numaaGetNuma(NUMAA *naa, l_int32 index, l_int32 accessflag)
numaaGetNuma()
Definition: numabasic.c:1625
l_int32 pixaSetFullSizeBoxa(PIXA *pixa)
pixaSetFullSizeBoxa()
Definition: pixafunc1.c:2755
Definition: array.h:59
static const l_int32 L_INSERT
Definition: pix.h:710
PIX * pixSelectByAreaFraction(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByAreaFraction()
Definition: pixafunc1.c:699
PIXAA * pixaaSelectRange(PIXAA *paas, l_int32 first, l_int32 last, l_int32 copyflag)
pixaaSelectRange()
Definition: pixafunc1.c:1710
PIXA * pixaSelectByWidthHeightRatio(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByWidthHeightRatio()
Definition: pixafunc1.c:910
BOXA * boxaTransform(BOXA *boxas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
boxaTransform()
Definition: boxfunc2.c:91
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_int32 pixaHasColor(PIXA *pixa, l_int32 *phascolor)
pixaHasColor()
Definition: pixafunc1.c:2404
l_int32 pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:695
l_int32 pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
l_int32 pixaGetRenderingDepth(PIXA *pixa, l_int32 *pdepth)
pixaGetRenderingDepth()
Definition: pixafunc1.c:2367
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1510
l_int32 pixCountConnComp(PIX *pixs, l_int32 connectivity, l_int32 *pcount)
pixCountConnComp()
Definition: conncomp.c:385
PIXA * pixaSelectBySize(PIXA *pixas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
pixaSelectBySize()
Definition: pixafunc1.c:291
PIXA * pixaSelectByPerimSizeRatio(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByPerimSizeRatio()
Definition: pixafunc1.c:643
PIX * pixSelectByPerimToAreaRatio(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByPerimToAreaRatio()
Definition: pixafunc1.c:438
PIXAA * pixaaScaleToSizeVar(PIXAA *paas, NUMA *nawd, NUMA *nahd)
pixaaScaleToSizeVar()
Definition: pixafunc1.c:1815
l_int32 boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:309
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1807
l_int32 pixaClipToForeground(PIXA *pixas, PIXA **ppixad, BOXA **pboxa)
pixaClipToForeground()
Definition: pixafunc1.c:2321
NUMA * numaMakeThresholdIndicator(NUMA *nas, l_float32 thresh, l_int32 type)
numaMakeThresholdIndicator()
Definition: numafunc1.c:1137
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:316
Definition: array.h:71
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:545
PIX * pixSelectByWidthHeightRatio(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByWidthHeightRatio()
Definition: pixafunc1.c:832
PIX * pixRotateOrth(PIX *pixs, l_int32 quads)
pixRotateOrth()
Definition: rotateorth.c:72
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:760
PIXA * pixaScaleToSizeRel(PIXA *pixas, l_int32 delw, l_int32 delh)
pixaScaleToSizeRel()
Definition: pixafunc1.c:1908
PIXA * pixaSort(PIXA *pixas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex, l_int32 copyflag)
pixaSort()
Definition: pixafunc1.c:1326
NUMA * numaCreateFromString(const char *str)
numaCreateFromString()
Definition: numabasic.c:308
Definition: pix.h:454
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:359
Definition: pix.h:465
PIXA * pixaSelectByAreaFraction(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByAreaFraction()
Definition: pixafunc1.c:777
NUMA * pixaMakeSizeIndicator(PIXA *pixa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation)
pixaMakeSizeIndicator()
Definition: pixafunc1.c:347
l_int32 pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame)
pixEqual()
Definition: compare.c:150
PIXA * pixaAddBorderGeneral(PIXA *pixad, PIXA *pixas, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixaAddBorderGeneral()
Definition: pixafunc1.c:2022
l_int32 numaaGetCount(NUMAA *naa)
numaaGetCount()
Definition: numabasic.c:1516
PIXA * pixaScale(PIXA *pixas, l_float32 scalex, l_float32 scaley)
pixaScale()
Definition: pixafunc1.c:1952
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:660
PIX * pixSelectByPerimSizeRatio(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByPerimSizeRatio()
Definition: pixafunc1.c:569
Definition: pix.h:705
#define PIX_NOT(op)
Definition: pix.h:329
l_int32 pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
pixClipToForeground()
Definition: pix5.c:1455
Definition: pix.h:134
PIXA * pixaBinSort(PIXA *pixas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex, l_int32 copyflag)
pixaBinSort()
Definition: pixafunc1.c:1466
Definition: pix.h:706
l_int32 pixaAddBox(PIXA *pixa, BOX *box, l_int32 copyflag)
pixaAddBox()
Definition: pixabasic.c:537
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:496
#define PIX_SRC
Definition: pix.h:327
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:630
PIXA * pixaSelectWithString(PIXA *pixas, const char *str, l_int32 *perror)
pixaSelectWithString()
Definition: pixafunc1.c:1185
PIXA * pixaClipToPix(PIXA *pixas, PIX *pixs)
pixaClipToPix()
Definition: pixafunc1.c:2272
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:277
l_int32 boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:2321
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:715
l_int32 numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:726
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1052
PIXA * pixaSelectRange(PIXA *pixas, l_int32 first, l_int32 last, l_int32 copyflag)
pixaSelectRange()
Definition: pixafunc1.c:1660
l_int32 pixaaSizeRange(PIXAA *paa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
pixaaSizeRange()
Definition: pixafunc1.c:2148
Definition: pix.h:480
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:243
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:398
l_int32 pixaSetBoxa(PIXA *pixa, BOXA *boxa, l_int32 accesstype)
pixaSetBoxa()
Definition: pixabasic.c:865
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:164
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:620
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1830
l_int32 boxaReplaceBox(BOXA *boxa, l_int32 index, BOX *box)
boxaReplaceBox()
Definition: boxbasic.c:942
#define PIX_DST
Definition: pix.h:328
l_int32 pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:960
BOXA * pixaGetBoxa(PIXA *pixa, l_int32 accesstype)
pixaGetBoxa()
Definition: pixabasic.c:729