Leptonica  1.83.1
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 
95 #ifdef HAVE_CONFIG_H
96 #include <config_auto.h>
97 #endif /* HAVE_CONFIG_H */
98 
99 #include <string.h>
100 #include "allheaders.h"
101 #include "pix_internal.h"
102 
103  /* For more than this number of c.c. in a binarized image of
104  * semi-perimeter (w + h) about 5000 or less, the O(n) binsort
105  * is faster than the O(nlogn) shellsort. */
106 static const l_int32 MinCompsForBinSort = 200;
107 
108  /* Don't rotate any angle smaller than this */
109 static const l_float32 MinAngleToRotate = 0.001; /* radians; ~0.06 deg */
110 
111 /*---------------------------------------------------------------------*
112  * Filters *
113  *---------------------------------------------------------------------*/
114 /*
115  * These filters work on the connected components of 1 bpp images.
116  * They are typically used on pixa that have been generated from a Pix
117  * using pixConnComp(), so that the corresponding Boxa is available.
118  *
119  * The filters remove or retain c.c. based on these properties:
120  * (a) size [pixaFindDimensions()]
121  * (b) area-to-perimeter ratio [pixaFindAreaPerimRatio()]
122  * (c) foreground area as a fraction of bounding box area (w * h)
123  * [pixaFindForegroundArea()]
124  * (d) number of foreground pixels [pixaCountPixels()]
125  * (e) width/height aspect ratio [pixFindWidthHeightRatio()]
126  *
127  * We provide two different high-level interfaces:
128  * (1) Functions that use one of the filters on either
129  * a pix or the pixa of components.
130  * (2) A general method that generates numas of indicator functions,
131  * logically combines them, and efficiently removes or adds
132  * the selected components.
133  *
134  * For interface (1), the filtering is performed with a single function call.
135  * This is the easiest way to do simple filtering. These functions
136  * are named pixSelectBy*() and pixaSelectBy*(), where the '*' is one of:
137  * Size
138  * PerimToAreaRatio
139  * PerimSizeRatio
140  * Area
141  * AreaFraction
142  * WidthHeightRatio
143  *
144  * For more complicated filtering, use the general method (2).
145  * The numa indicator functions for a pixa are generated by these functions:
146  * pixaFindDimensions()
147  * pixaFindPerimToAreaRatio()
148  * pixaFindPerimSizeRatio()
149  * pixaFindAreaFraction()
150  * pixaCountPixels()
151  * pixaFindWidthHeightRatio()
152  * pixaFindWidthHeightProduct()
153  *
154  * Here is an illustration using the general method. Suppose you want
155  * all 8-connected components that have a height greater than 40 pixels,
156  * a width not more than 30 pixels, between 150 and 300 fg pixels,
157  * and a perimeter-to-size ratio between 1.2 and 2.0.
158  *
159  * // Generate the pixa of 8 cc pieces.
160  * boxa = pixConnComp(pixs, &pixa, 8);
161  *
162  * // Extract the data we need about each component.
163  * pixaFindDimensions(pixa, &naw, &nah);
164  * nas = pixaCountPixels(pixa);
165  * nar = pixaFindPerimSizeRatio(pixa);
166  *
167  * // Build the indicator arrays for the set of components,
168  * // based on thresholds and selection criteria.
169  * na1 = numaMakeThresholdIndicator(nah, 40, L_SELECT_IF_GT);
170  * na2 = numaMakeThresholdIndicator(naw, 30, L_SELECT_IF_LTE);
171  * na3 = numaMakeThresholdIndicator(nas, 150, L_SELECT_IF_GTE);
172  * na4 = numaMakeThresholdIndicator(nas, 300, L_SELECT_IF_LTE);
173  * na5 = numaMakeThresholdIndicator(nar, 1.2, L_SELECT_IF_GTE);
174  * na6 = numaMakeThresholdIndicator(nar, 2.0, L_SELECT_IF_LTE);
175  *
176  * // Combine the indicator arrays logically to find
177  * // the components that will be retained.
178  * nad = numaLogicalOp(NULL, na1, na2, L_INTERSECTION);
179  * numaLogicalOp(nad, nad, na3, L_INTERSECTION);
180  * numaLogicalOp(nad, nad, na4, L_INTERSECTION);
181  * numaLogicalOp(nad, nad, na5, L_INTERSECTION);
182  * numaLogicalOp(nad, nad, na6, L_INTERSECTION);
183  *
184  * // Invert to get the components that will be removed.
185  * numaInvert(nad, nad);
186  *
187  * // Remove the components, in-place.
188  * pixRemoveWithIndicator(pixs, pixa, nad);
189  */
190 
191 
219 PIX *
221  l_int32 width,
222  l_int32 height,
223  l_int32 connectivity,
224  l_int32 type,
225  l_int32 relation,
226  l_int32 *pchanged)
227 {
228 l_int32 w, h, empty, changed, count;
229 BOXA *boxa;
230 PIX *pixd;
231 PIXA *pixas, *pixad;
232 
233  if (!pixs)
234  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
235  if (connectivity != 4 && connectivity != 8)
236  return (PIX *)ERROR_PTR("connectivity not 4 or 8", __func__, NULL);
237  if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
238  type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
239  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
240  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
241  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
242  return (PIX *)ERROR_PTR("invalid relation", __func__, NULL);
243  if (pchanged) *pchanged = FALSE;
244 
245  /* Check if any components exist */
246  pixZero(pixs, &empty);
247  if (empty)
248  return pixCopy(NULL, pixs);
249 
250  /* Identify and select the components */
251  boxa = pixConnComp(pixs, &pixas, connectivity);
252  pixad = pixaSelectBySize(pixas, width, height, type, relation, &changed);
253  boxaDestroy(&boxa);
254  pixaDestroy(&pixas);
255 
256  if (!changed) {
257  pixaDestroy(&pixad);
258  return pixCopy(NULL, pixs);
259  }
260 
261  /* Render the result */
262  if (pchanged) *pchanged = TRUE;
263  pixGetDimensions(pixs, &w, &h, NULL);
264  count = pixaGetCount(pixad);
265  if (count == 0) { /* return empty pix */
266  pixd = pixCreateTemplate(pixs);
267  } else {
268  pixd = pixaDisplay(pixad, w, h);
269  pixCopyResolution(pixd, pixs);
270  pixCopyColormap(pixd, pixs);
271  pixCopyText(pixd, pixs);
272  pixCopyInputFormat(pixd, pixs);
273  }
274  pixaDestroy(&pixad);
275  return pixd;
276 }
277 
278 
304 PIXA *
306  l_int32 width,
307  l_int32 height,
308  l_int32 type,
309  l_int32 relation,
310  l_int32 *pchanged)
311 {
312 NUMA *na;
313 PIXA *pixad;
314 
315  if (!pixas)
316  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
317  if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
318  type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
319  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
320  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
321  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
322  return (PIXA *)ERROR_PTR("invalid relation", __func__, NULL);
323 
324  /* Compute the indicator array for saving components */
325  na = pixaMakeSizeIndicator(pixas, width, height, type, relation);
326 
327  /* Filter to get output */
328  pixad = pixaSelectWithIndicator(pixas, na, pchanged);
329 
330  numaDestroy(&na);
331  return pixad;
332 }
333 
334 
358 NUMA *
360  l_int32 width,
361  l_int32 height,
362  l_int32 type,
363  l_int32 relation)
364 {
365 l_int32 i, n, w, h, ival;
366 NUMA *na;
367 
368  if (!pixa)
369  return (NUMA *)ERROR_PTR("pixa not defined", __func__, NULL);
370  if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT &&
371  type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH)
372  return (NUMA *)ERROR_PTR("invalid type", __func__, NULL);
373  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
374  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
375  return (NUMA *)ERROR_PTR("invalid relation", __func__, NULL);
376 
377  n = pixaGetCount(pixa);
378  na = numaCreate(n);
379  for (i = 0; i < n; i++) {
380  ival = 0;
381  pixaGetPixDimensions(pixa, i, &w, &h, NULL);
382  switch (type)
383  {
384  case L_SELECT_WIDTH:
385  if ((relation == L_SELECT_IF_LT && w < width) ||
386  (relation == L_SELECT_IF_GT && w > width) ||
387  (relation == L_SELECT_IF_LTE && w <= width) ||
388  (relation == L_SELECT_IF_GTE && w >= width))
389  ival = 1;
390  break;
391  case L_SELECT_HEIGHT:
392  if ((relation == L_SELECT_IF_LT && h < height) ||
393  (relation == L_SELECT_IF_GT && h > height) ||
394  (relation == L_SELECT_IF_LTE && h <= height) ||
395  (relation == L_SELECT_IF_GTE && h >= height))
396  ival = 1;
397  break;
398  case L_SELECT_IF_EITHER:
399  if (((relation == L_SELECT_IF_LT) && (w < width || h < height)) ||
400  ((relation == L_SELECT_IF_GT) && (w > width || h > height)) ||
401  ((relation == L_SELECT_IF_LTE) && (w <= width || h <= height)) ||
402  ((relation == L_SELECT_IF_GTE) && (w >= width || h >= height)))
403  ival = 1;
404  break;
405  case L_SELECT_IF_BOTH:
406  if (((relation == L_SELECT_IF_LT) && (w < width && h < height)) ||
407  ((relation == L_SELECT_IF_GT) && (w > width && h > height)) ||
408  ((relation == L_SELECT_IF_LTE) && (w <= width && h <= height)) ||
409  ((relation == L_SELECT_IF_GTE) && (w >= width && h >= height)))
410  ival = 1;
411  break;
412  default:
413  L_WARNING("can't get here!\n", __func__);
414  break;
415  }
416  numaAddNumber(na, ival);
417  }
418 
419  return na;
420 }
421 
422 
447 PIX *
449  l_float32 thresh,
450  l_int32 connectivity,
451  l_int32 type,
452  l_int32 *pchanged)
453 {
454 l_int32 w, h, empty, changed, count;
455 BOXA *boxa;
456 PIX *pixd;
457 PIXA *pixas, *pixad;
458 
459  if (!pixs)
460  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
461  if (connectivity != 4 && connectivity != 8)
462  return (PIX *)ERROR_PTR("connectivity not 4 or 8", __func__, NULL);
463  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
464  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
465  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
466  if (pchanged) *pchanged = FALSE;
467 
468  /* Check if any components exist */
469  pixZero(pixs, &empty);
470  if (empty)
471  return pixCopy(NULL, pixs);
472 
473  /* Filter thin components */
474  boxa = pixConnComp(pixs, &pixas, connectivity);
475  pixad = pixaSelectByPerimToAreaRatio(pixas, thresh, type, &changed);
476  boxaDestroy(&boxa);
477  pixaDestroy(&pixas);
478 
479  if (!changed) {
480  pixaDestroy(&pixad);
481  return pixCopy(NULL, pixs);
482  }
483 
484  /* Render the result */
485  if (pchanged) *pchanged = TRUE;
486  pixGetDimensions(pixs, &w, &h, NULL);
487  count = pixaGetCount(pixad);
488  if (count == 0) { /* return empty pix */
489  pixd = pixCreateTemplate(pixs);
490  } else {
491  pixd = pixaDisplay(pixad, w, h);
492  pixCopyResolution(pixd, pixs);
493  pixCopyColormap(pixd, pixs);
494  pixCopyText(pixd, pixs);
495  pixCopyInputFormat(pixd, pixs);
496  }
497  pixaDestroy(&pixad);
498  return pixd;
499 }
500 
501 
519 PIXA *
521  l_float32 thresh,
522  l_int32 type,
523  l_int32 *pchanged)
524 {
525 NUMA *na, *nai;
526 PIXA *pixad;
527 
528  if (!pixas)
529  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
530  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
531  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
532  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
533 
534  /* Compute component ratios. */
535  na = pixaFindPerimToAreaRatio(pixas);
536 
537  /* Generate indicator array for elements to be saved. */
538  nai = numaMakeThresholdIndicator(na, thresh, type);
539  numaDestroy(&na);
540 
541  /* Filter to get output */
542  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
543 
544  numaDestroy(&nai);
545  return pixad;
546 }
547 
548 
574 PIX *
576  l_float32 thresh,
577  l_int32 connectivity,
578  l_int32 type,
579  l_int32 *pchanged)
580 {
581 l_int32 w, h, empty, changed, count;
582 BOXA *boxa;
583 PIX *pixd;
584 PIXA *pixas, *pixad;
585 
586  if (!pixs)
587  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
588  if (connectivity != 4 && connectivity != 8)
589  return (PIX *)ERROR_PTR("connectivity not 4 or 8", __func__, NULL);
590  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
591  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
592  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
593  if (pchanged) *pchanged = FALSE;
594 
595  /* Check if any components exist */
596  pixZero(pixs, &empty);
597  if (empty)
598  return pixCopy(NULL, pixs);
599 
600  /* Filter thin components */
601  boxa = pixConnComp(pixs, &pixas, connectivity);
602  pixad = pixaSelectByPerimSizeRatio(pixas, thresh, type, &changed);
603  boxaDestroy(&boxa);
604  pixaDestroy(&pixas);
605 
606  if (!changed) {
607  pixaDestroy(&pixad);
608  return pixCopy(NULL, pixs);
609  }
610 
611  /* Render the result */
612  if (pchanged) *pchanged = TRUE;
613  pixGetDimensions(pixs, &w, &h, NULL);
614  count = pixaGetCount(pixad);
615  if (count == 0) { /* return empty pix */
616  pixd = pixCreateTemplate(pixs);
617  } else {
618  pixd = pixaDisplay(pixad, w, h);
619  pixCopyResolution(pixd, pixs);
620  pixCopyColormap(pixd, pixs);
621  pixCopyText(pixd, pixs);
622  pixCopyInputFormat(pixd, pixs);
623  }
624  pixaDestroy(&pixad);
625  return pixd;
626 }
627 
628 
646 PIXA *
648  l_float32 thresh,
649  l_int32 type,
650  l_int32 *pchanged)
651 {
652 NUMA *na, *nai;
653 PIXA *pixad;
654 
655  if (!pixas)
656  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
657  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
658  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
659  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
660 
661  /* Compute component ratios. */
662  na = pixaFindPerimSizeRatio(pixas);
663 
664  /* Generate indicator array for elements to be saved. */
665  nai = numaMakeThresholdIndicator(na, thresh, type);
666  numaDestroy(&na);
667 
668  /* Filter to get output */
669  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
670 
671  numaDestroy(&nai);
672  return pixad;
673 }
674 
675 
700 PIX *
702  l_float32 thresh,
703  l_int32 connectivity,
704  l_int32 type,
705  l_int32 *pchanged)
706 {
707 l_int32 w, h, empty, changed, count;
708 BOXA *boxa;
709 PIX *pixd;
710 PIXA *pixas, *pixad;
711 
712  if (!pixs)
713  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
714  if (connectivity != 4 && connectivity != 8)
715  return (PIX *)ERROR_PTR("connectivity not 4 or 8", __func__, 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", __func__, 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  if (!pixas)
786  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
787  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
788  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
789  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
790 
791  /* Compute component ratios. */
792  na = pixaFindAreaFraction(pixas);
793 
794  /* Generate indicator array for elements to be saved. */
795  nai = numaMakeThresholdIndicator(na, thresh, type);
796  numaDestroy(&na);
797 
798  /* Filter to get output */
799  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
800 
801  numaDestroy(&nai);
802  return pixad;
803 }
804 
805 
830 PIX *
832  l_float32 thresh,
833  l_int32 connectivity,
834  l_int32 type,
835  l_int32 *pchanged)
836 {
837 l_int32 w, h, empty, changed, count;
838 BOXA *boxa;
839 PIX *pixd;
840 PIXA *pixas, *pixad;
841 
842  if (!pixs)
843  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
844  if (connectivity != 4 && connectivity != 8)
845  return (PIX *)ERROR_PTR("connectivity not 4 or 8", __func__, NULL);
846  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
847  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
848  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
849  if (pchanged) *pchanged = FALSE;
850 
851  /* Check if any components exist */
852  pixZero(pixs, &empty);
853  if (empty)
854  return pixCopy(NULL, pixs);
855 
856  /* Filter components */
857  boxa = pixConnComp(pixs, &pixas, connectivity);
858  pixad = pixaSelectByArea(pixas, thresh, type, &changed);
859  boxaDestroy(&boxa);
860  pixaDestroy(&pixas);
861 
862  if (!changed) {
863  pixaDestroy(&pixad);
864  return pixCopy(NULL, pixs);
865  }
866 
867  /* Render the result */
868  if (pchanged) *pchanged = TRUE;
869  pixGetDimensions(pixs, &w, &h, NULL);
870  count = pixaGetCount(pixad);
871  if (count == 0) { /* return empty pix */
872  pixd = pixCreateTemplate(pixs);
873  } else {
874  pixd = pixaDisplay(pixad, w, h);
875  pixCopyResolution(pixd, pixs);
876  pixCopyColormap(pixd, pixs);
877  pixCopyText(pixd, pixs);
878  pixCopyInputFormat(pixd, pixs);
879  }
880  pixaDestroy(&pixad);
881  return pixd;
882 }
883 
884 
906 PIXA *
908  l_float32 thresh,
909  l_int32 type,
910  l_int32 *pchanged)
911 {
912 NUMA *na, *nai;
913 PIXA *pixad;
914 
915  if (!pixas)
916  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
917  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
918  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
919  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
920 
921  /* Compute area of each component */
922  na = pixaCountPixels(pixas);
923 
924  /* Generate indicator array for elements to be saved. */
925  nai = numaMakeThresholdIndicator(na, thresh, type);
926  numaDestroy(&na);
927 
928  /* Filter to get output */
929  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
930 
931  numaDestroy(&nai);
932  return pixad;
933 }
934 
935 
959 PIX *
961  l_float32 thresh,
962  l_int32 connectivity,
963  l_int32 type,
964  l_int32 *pchanged)
965 {
966 l_int32 w, h, empty, changed, count;
967 BOXA *boxa;
968 PIX *pixd;
969 PIXA *pixas, *pixad;
970 
971  if (!pixs)
972  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
973  if (connectivity != 4 && connectivity != 8)
974  return (PIX *)ERROR_PTR("connectivity not 4 or 8", __func__, NULL);
975  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
976  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
977  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
978  if (pchanged) *pchanged = FALSE;
979 
980  /* Check if any components exist */
981  pixZero(pixs, &empty);
982  if (empty)
983  return pixCopy(NULL, pixs);
984 
985  /* Filter components */
986  boxa = pixConnComp(pixs, &pixas, connectivity);
987  pixad = pixaSelectByWidthHeightRatio(pixas, thresh, type, &changed);
988  boxaDestroy(&boxa);
989  pixaDestroy(&pixas);
990 
991  if (!changed) {
992  pixaDestroy(&pixad);
993  return pixCopy(NULL, pixs);
994  }
995 
996  /* Render the result */
997  if (pchanged) *pchanged = TRUE;
998  pixGetDimensions(pixs, &w, &h, NULL);
999  count = pixaGetCount(pixad);
1000  if (count == 0) { /* return empty pix */
1001  pixd = pixCreateTemplate(pixs);
1002  } else {
1003  pixd = pixaDisplay(pixad, w, h);
1004  pixCopyResolution(pixd, pixs);
1005  pixCopyColormap(pixd, pixs);
1006  pixCopyText(pixd, pixs);
1007  pixCopyInputFormat(pixd, pixs);
1008  }
1009  pixaDestroy(&pixad);
1010  return pixd;
1011 }
1012 
1013 
1035 PIXA *
1037  l_float32 thresh,
1038  l_int32 type,
1039  l_int32 *pchanged)
1040 {
1041 NUMA *na, *nai;
1042 PIXA *pixad;
1043 
1044  if (!pixas)
1045  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1046  if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
1047  type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
1048  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
1049 
1050  /* Compute component ratios. */
1051  na = pixaFindWidthHeightRatio(pixas);
1052 
1053  /* Generate indicator array for elements to be saved. */
1054  nai = numaMakeThresholdIndicator(na, thresh, type);
1055  numaDestroy(&na);
1056 
1057  /* Filter to get output */
1058  pixad = pixaSelectWithIndicator(pixas, nai, pchanged);
1059 
1060  numaDestroy(&nai);
1061  return pixad;
1062 }
1063 
1064 
1083 PIXA *
1085  l_int32 nmin,
1086  l_int32 nmax,
1087  l_int32 connectivity,
1088  l_int32 *pchanged)
1089 {
1090 l_int32 n, i, count;
1091 NUMA *na;
1092 PIX *pix;
1093 PIXA *pixad;
1094 
1095  if (pchanged) *pchanged = 0;
1096  if (!pixas)
1097  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1098  if (nmin > nmax)
1099  return (PIXA *)ERROR_PTR("nmin > nmax", __func__, NULL);
1100  if (connectivity != 4 && connectivity != 8)
1101  return (PIXA *)ERROR_PTR("connectivity not 4 or 8", __func__, NULL);
1102 
1103  /* Get indicator array based on number of c.c. */
1104  n = pixaGetCount(pixas);
1105  na = numaCreate(n);
1106  for (i = 0; i < n; i++) {
1107  pix = pixaGetPix(pixas, i, L_CLONE);
1108  pixCountConnComp(pix, connectivity, &count);
1109  if (count >= nmin && count <= nmax)
1110  numaAddNumber(na, 1);
1111  else
1112  numaAddNumber(na, 0);
1113  pixDestroy(&pix);
1114  }
1115 
1116  /* Filter to get output */
1117  pixad = pixaSelectWithIndicator(pixas, na, pchanged);
1118  numaDestroy(&na);
1119  return pixad;
1120 }
1121 
1122 
1140 PIXA *
1142  NUMA *na,
1143  l_int32 *pchanged)
1144 {
1145 l_int32 i, n, nbox, ival, nsave;
1146 BOX *box;
1147 PIX *pix1;
1148 PIXA *pixad;
1149 
1150  if (!pixas)
1151  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1152  if (!na)
1153  return (PIXA *)ERROR_PTR("na not defined", __func__, NULL);
1154 
1155  nsave = 0;
1156  n = numaGetCount(na);
1157  for (i = 0; i < n; i++) {
1158  numaGetIValue(na, i, &ival);
1159  if (ival == 1) nsave++;
1160  }
1161 
1162  if (nsave == n) {
1163  if (pchanged) *pchanged = FALSE;
1164  return pixaCopy(pixas, L_CLONE);
1165  }
1166  if (pchanged) *pchanged = TRUE;
1167  pixad = pixaCreate(nsave);
1168  nbox = pixaGetBoxaCount(pixas);
1169  for (i = 0; i < n; i++) {
1170  numaGetIValue(na, i, &ival);
1171  if (ival == 0) continue;
1172  pix1 = pixaGetPix(pixas, i, L_CLONE);
1173  pixaAddPix(pixad, pix1, L_INSERT);
1174  if (nbox == n) { /* fully populated boxa */
1175  box = pixaGetBox(pixas, i, L_CLONE);
1176  pixaAddBox(pixad, box, L_INSERT);
1177  }
1178  }
1179 
1180  return pixad;
1181 }
1182 
1183 
1198 l_ok
1200  PIXA *pixa,
1201  NUMA *na)
1202 {
1203 l_int32 i, n, ival, x, y, w, h;
1204 BOX *box;
1205 PIX *pix;
1206 
1207  if (!pixs)
1208  return ERROR_INT("pixs not defined", __func__, 1);
1209  if (!pixa)
1210  return ERROR_INT("pixa not defined", __func__, 1);
1211  if (!na)
1212  return ERROR_INT("na not defined", __func__, 1);
1213  n = pixaGetCount(pixa);
1214  if (n != numaGetCount(na))
1215  return ERROR_INT("pixa and na sizes not equal", __func__, 1);
1216 
1217  for (i = 0; i < n; i++) {
1218  numaGetIValue(na, i, &ival);
1219  if (ival == 1) {
1220  pix = pixaGetPix(pixa, i, L_CLONE);
1221  box = pixaGetBox(pixa, i, L_CLONE);
1222  boxGetGeometry(box, &x, &y, &w, &h);
1223  pixRasterop(pixs, x, y, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1224  pix, 0, 0);
1225  boxDestroy(&box);
1226  pixDestroy(&pix);
1227  }
1228  }
1229 
1230  return 0;
1231 }
1232 
1233 
1249 l_ok
1251  PIXA *pixa,
1252  NUMA *na)
1253 {
1254 l_int32 i, n, ival, x, y, w, h;
1255 BOX *box;
1256 PIX *pix;
1257 
1258  if (!pixs)
1259  return ERROR_INT("pixs not defined", __func__, 1);
1260  if (!pixa)
1261  return ERROR_INT("pixa not defined", __func__, 1);
1262  if (!na)
1263  return ERROR_INT("na not defined", __func__, 1);
1264  n = pixaGetCount(pixa);
1265  if (n != numaGetCount(na))
1266  return ERROR_INT("pixa and na sizes not equal", __func__, 1);
1267 
1268  for (i = 0; i < n; i++) {
1269  numaGetIValue(na, i, &ival);
1270  if (ival == 1) {
1271  pix = pixaGetPix(pixa, i, L_CLONE);
1272  box = pixaGetBox(pixa, i, L_CLONE);
1273  boxGetGeometry(box, &x, &y, &w, &h);
1274  pixRasterop(pixs, x, y, w, h, PIX_SRC | PIX_DST, pix, 0, 0);
1275  boxDestroy(&box);
1276  pixDestroy(&pix);
1277  }
1278  }
1279 
1280  return 0;
1281 }
1282 
1283 
1300 PIXA *
1302  const char *str,
1303  l_int32 *perror)
1304 {
1305 l_int32 i, nval, npix, nbox, val, imaxval;
1306 l_float32 maxval;
1307 BOX *box;
1308 NUMA *na;
1309 PIX *pix1;
1310 PIXA *pixad;
1311 
1312  if (perror) *perror = 0;
1313  if (!pixas)
1314  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1315  if (!str)
1316  return (PIXA *)ERROR_PTR("str not defined", __func__, NULL);
1317 
1318  if ((na = numaCreateFromString(str)) == NULL)
1319  return (PIXA *)ERROR_PTR("na not made", __func__, NULL);
1320  if ((nval = numaGetCount(na)) == 0) {
1321  numaDestroy(&na);
1322  return (PIXA *)ERROR_PTR("no indices found", __func__, NULL);
1323  }
1324  numaGetMax(na, &maxval, NULL);
1325  imaxval = (l_int32)(maxval + 0.1);
1326  nbox = pixaGetBoxaCount(pixas);
1327  npix = pixaGetCount(pixas);
1328  if (imaxval >= npix) {
1329  if (perror) *perror = 1;
1330  L_ERROR("max index = %d, size of pixa = %d\n", __func__, imaxval, npix);
1331  }
1332 
1333  pixad = pixaCreate(nval);
1334  for (i = 0; i < nval; i++) {
1335  numaGetIValue(na, i, &val);
1336  if (val < 0 || val >= npix) {
1337  L_ERROR("index %d out of range of pix\n", __func__, val);
1338  continue;
1339  }
1340  pix1 = pixaGetPix(pixas, val, L_COPY);
1341  pixaAddPix(pixad, pix1, L_INSERT);
1342  if (nbox == npix) { /* fully populated boxa */
1343  box = pixaGetBox(pixas, val, L_COPY);
1344  pixaAddBox(pixad, box, L_INSERT);
1345  }
1346  }
1347  numaDestroy(&na);
1348  return pixad;
1349 }
1350 
1351 
1369 PIX *
1371  PIXA *pixa,
1372  l_int32 index)
1373 {
1374 l_int32 n, x, y, w, h, same, maxd;
1375 BOX *box;
1376 BOXA *boxa;
1377 PIX *pix;
1378 
1379  if (!pixa)
1380  return (PIX *)ERROR_PTR("pixa not defined", __func__, pixs);
1381  n = pixaGetCount(pixa);
1382  if (index < 0 || index >= n)
1383  return (PIX *)ERROR_PTR("invalid index", __func__, pixs);
1384  if (pixs && (pixGetDepth(pixs) != 1))
1385  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixs);
1386  pixaVerifyDepth(pixa, &same, &maxd);
1387  if (maxd > 1)
1388  return (PIX *)ERROR_PTR("not all pix with d == 1", __func__, pixs);
1389 
1390  boxa = pixaGetBoxa(pixa, L_CLONE);
1391  if (!pixs) {
1392  boxaGetExtent(boxa, &w, &h, NULL);
1393  pixs = pixCreate(w, h, 1);
1394  }
1395 
1396  pix = pixaGetPix(pixa, index, L_CLONE);
1397  box = boxaGetBox(boxa, index, L_CLONE);
1398  boxGetGeometry(box, &x, &y, &w, &h);
1399  pixRasterop(pixs, x, y, w, h, PIX_SRC | PIX_DST, pix, 0, 0);
1400  boxDestroy(&box);
1401  pixDestroy(&pix);
1402  boxaDestroy(&boxa);
1403 
1404  return pixs;
1405 }
1406 
1407 
1408 /*---------------------------------------------------------------------*
1409  * Sort functions *
1410  *---------------------------------------------------------------------*/
1437 PIXA *
1439  l_int32 sorttype,
1440  l_int32 sortorder,
1441  NUMA **pnaindex,
1442  l_int32 copyflag)
1443 {
1444 l_int32 i, n, nb, x, y, w, h;
1445 BOXA *boxa;
1446 NUMA *na, *naindex;
1447 PIXA *pixad;
1448 
1449  if (pnaindex) *pnaindex = NULL;
1450  if (!pixas)
1451  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1452  if (sorttype != L_SORT_BY_X && sorttype != L_SORT_BY_Y &&
1453  sorttype != L_SORT_BY_WIDTH && sorttype != L_SORT_BY_HEIGHT &&
1454  sorttype != L_SORT_BY_MIN_DIMENSION &&
1455  sorttype != L_SORT_BY_MAX_DIMENSION &&
1456  sorttype != L_SORT_BY_PERIMETER &&
1457  sorttype != L_SORT_BY_AREA &&
1458  sorttype != L_SORT_BY_ASPECT_RATIO)
1459  return (PIXA *)ERROR_PTR("invalid sort type", __func__, NULL);
1460  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
1461  return (PIXA *)ERROR_PTR("invalid sort order", __func__, NULL);
1462  if (copyflag != L_COPY && copyflag != L_CLONE)
1463  return (PIXA *)ERROR_PTR("invalid copy flag", __func__, NULL);
1464 
1465  /* Check the pixa and boxa counts. Make a boxa if required. */
1466  if ((n = pixaGetCount(pixas)) == 0) {
1467  L_INFO("no pix in pixa\n", __func__);
1468  return pixaCopy(pixas, copyflag);
1469  }
1470  if ((boxa = pixas->boxa) == NULL) /* not owned; do not destroy */
1471  return (PIXA *)ERROR_PTR("boxa not found!", __func__, NULL);
1472  nb = boxaGetCount(boxa);
1473  if (nb == 0) {
1474  pixaSetFullSizeBoxa(pixas);
1475  nb = n;
1476  boxa = pixas->boxa; /* not owned */
1477  if (sorttype == L_SORT_BY_X || sorttype == L_SORT_BY_Y)
1478  L_WARNING("sort by x or y where all values are 0\n", __func__);
1479  }
1480  if (nb != n)
1481  return (PIXA *)ERROR_PTR("boxa and pixa counts differ", __func__, NULL);
1482 
1483  /* Use O(n) binsort if possible */
1484  if (n > MinCompsForBinSort &&
1485  ((sorttype == L_SORT_BY_X) || (sorttype == L_SORT_BY_Y) ||
1486  (sorttype == L_SORT_BY_WIDTH) || (sorttype == L_SORT_BY_HEIGHT) ||
1487  (sorttype == L_SORT_BY_PERIMETER)))
1488  return pixaBinSort(pixas, sorttype, sortorder, pnaindex, copyflag);
1489 
1490  /* Build up numa of specific data */
1491  if ((na = numaCreate(n)) == NULL)
1492  return (PIXA *)ERROR_PTR("na not made", __func__, NULL);
1493  for (i = 0; i < n; i++) {
1494  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
1495  switch (sorttype)
1496  {
1497  case L_SORT_BY_X:
1498  numaAddNumber(na, x);
1499  break;
1500  case L_SORT_BY_Y:
1501  numaAddNumber(na, y);
1502  break;
1503  case L_SORT_BY_WIDTH:
1504  numaAddNumber(na, w);
1505  break;
1506  case L_SORT_BY_HEIGHT:
1507  numaAddNumber(na, h);
1508  break;
1510  numaAddNumber(na, L_MIN(w, h));
1511  break;
1513  numaAddNumber(na, L_MAX(w, h));
1514  break;
1515  case L_SORT_BY_PERIMETER:
1516  numaAddNumber(na, w + h);
1517  break;
1518  case L_SORT_BY_AREA:
1519  numaAddNumber(na, w * h);
1520  break;
1522  numaAddNumber(na, (l_float32)w / (l_float32)h);
1523  break;
1524  default:
1525  L_WARNING("invalid sort type\n", __func__);
1526  }
1527  }
1528 
1529  /* Get the sort index for data array */
1530  naindex = numaGetSortIndex(na, sortorder);
1531  numaDestroy(&na);
1532  if (!naindex)
1533  return (PIXA *)ERROR_PTR("naindex not made", __func__, NULL);
1534 
1535  /* Build up sorted pixa using sort index */
1536  if ((pixad = pixaSortByIndex(pixas, naindex, copyflag)) == NULL) {
1537  numaDestroy(&naindex);
1538  return (PIXA *)ERROR_PTR("pixad not made", __func__, NULL);
1539  }
1540 
1541  if (pnaindex)
1542  *pnaindex = naindex;
1543  else
1544  numaDestroy(&naindex);
1545  return pixad;
1546 }
1547 
1548 
1575 PIXA *
1577  l_int32 sorttype,
1578  l_int32 sortorder,
1579  NUMA **pnaindex,
1580  l_int32 copyflag)
1581 {
1582 l_int32 i, n, x, y, w, h;
1583 BOXA *boxa;
1584 NUMA *na, *naindex;
1585 PIXA *pixad;
1586 
1587  if (pnaindex) *pnaindex = NULL;
1588  if (!pixas)
1589  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1590  if (sorttype != L_SORT_BY_X && sorttype != L_SORT_BY_Y &&
1591  sorttype != L_SORT_BY_WIDTH && sorttype != L_SORT_BY_HEIGHT &&
1592  sorttype != L_SORT_BY_PERIMETER)
1593  return (PIXA *)ERROR_PTR("invalid sort type", __func__, NULL);
1594  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
1595  return (PIXA *)ERROR_PTR("invalid sort order", __func__, NULL);
1596  if (copyflag != L_COPY && copyflag != L_CLONE)
1597  return (PIXA *)ERROR_PTR("invalid copy flag", __func__, NULL);
1598 
1599  /* Verify that the pixa and its boxa have the same count */
1600  if ((boxa = pixas->boxa) == NULL) /* not owned; do not destroy */
1601  return (PIXA *)ERROR_PTR("boxa not found", __func__, NULL);
1602  n = pixaGetCount(pixas);
1603  if (boxaGetCount(boxa) != n)
1604  return (PIXA *)ERROR_PTR("boxa and pixa counts differ", __func__, NULL);
1605 
1606  /* Generate Numa of appropriate box dimensions */
1607  if ((na = numaCreate(n)) == NULL)
1608  return (PIXA *)ERROR_PTR("na not made", __func__, NULL);
1609  for (i = 0; i < n; i++) {
1610  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
1611  switch (sorttype)
1612  {
1613  case L_SORT_BY_X:
1614  numaAddNumber(na, x);
1615  break;
1616  case L_SORT_BY_Y:
1617  numaAddNumber(na, y);
1618  break;
1619  case L_SORT_BY_WIDTH:
1620  numaAddNumber(na, w);
1621  break;
1622  case L_SORT_BY_HEIGHT:
1623  numaAddNumber(na, h);
1624  break;
1625  case L_SORT_BY_PERIMETER:
1626  numaAddNumber(na, w + h);
1627  break;
1628  default:
1629  L_WARNING("invalid sort type\n", __func__);
1630  }
1631  }
1632 
1633  /* Get the sort index for data array */
1634  naindex = numaGetBinSortIndex(na, sortorder);
1635  numaDestroy(&na);
1636  if (!naindex)
1637  return (PIXA *)ERROR_PTR("naindex not made", __func__, NULL);
1638 
1639  /* Build up sorted pixa using sort index */
1640  if ((pixad = pixaSortByIndex(pixas, naindex, copyflag)) == NULL) {
1641  numaDestroy(&naindex);
1642  return (PIXA *)ERROR_PTR("pixad not made", __func__, NULL);
1643  }
1644 
1645  if (pnaindex)
1646  *pnaindex = naindex;
1647  else
1648  numaDestroy(&naindex);
1649  return pixad;
1650 }
1651 
1652 
1661 PIXA *
1663  NUMA *naindex,
1664  l_int32 copyflag)
1665 {
1666 l_int32 i, n, index;
1667 BOX *box;
1668 PIX *pix;
1669 PIXA *pixad;
1670 
1671  if (!pixas)
1672  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1673  if (!naindex)
1674  return (PIXA *)ERROR_PTR("naindex not defined", __func__, NULL);
1675  if (copyflag != L_CLONE && copyflag != L_COPY)
1676  return (PIXA *)ERROR_PTR("invalid copyflag", __func__, NULL);
1677 
1678  n = pixaGetCount(pixas);
1679  pixad = pixaCreate(n);
1680  for (i = 0; i < n; i++) {
1681  numaGetIValue(naindex, i, &index);
1682  pix = pixaGetPix(pixas, index, copyflag);
1683  box = pixaGetBox(pixas, index, copyflag);
1684  pixaAddPix(pixad, pix, L_INSERT);
1685  pixaAddBox(pixad, box, L_INSERT);
1686  }
1687 
1688  return pixad;
1689 }
1690 
1691 
1700 PIXAA *
1702  NUMAA *naa,
1703  l_int32 copyflag)
1704 {
1705 l_int32 pixtot, ntot, i, j, n, nn, index;
1706 BOX *box;
1707 NUMA *na;
1708 PIX *pix;
1709 PIXA *pixa;
1710 PIXAA *paa;
1711 
1712  if (!pixas)
1713  return (PIXAA *)ERROR_PTR("pixas not defined", __func__, NULL);
1714  if (!naa)
1715  return (PIXAA *)ERROR_PTR("naindex not defined", __func__, NULL);
1716 
1717  /* Check counts */
1718  ntot = numaaGetNumberCount(naa);
1719  pixtot = pixaGetCount(pixas);
1720  if (ntot != pixtot)
1721  return (PIXAA *)ERROR_PTR("element count mismatch", __func__, NULL);
1722 
1723  n = numaaGetCount(naa);
1724  paa = pixaaCreate(n);
1725  for (i = 0; i < n; i++) {
1726  na = numaaGetNuma(naa, i, L_CLONE);
1727  nn = numaGetCount(na);
1728  pixa = pixaCreate(nn);
1729  for (j = 0; j < nn; j++) {
1730  numaGetIValue(na, j, &index);
1731  pix = pixaGetPix(pixas, index, copyflag);
1732  box = pixaGetBox(pixas, index, copyflag);
1733  pixaAddPix(pixa, pix, L_INSERT);
1734  pixaAddBox(pixa, box, L_INSERT);
1735  }
1736  pixaaAddPixa(paa, pixa, L_INSERT);
1737  numaDestroy(&na);
1738  }
1739 
1740  return paa;
1741 }
1742 
1743 
1744 /*---------------------------------------------------------------------*
1745  * Pixa and Pixaa range selection *
1746  *---------------------------------------------------------------------*/
1763 PIXA *
1765  l_int32 first,
1766  l_int32 last,
1767  l_int32 copyflag)
1768 {
1769 l_int32 n, npix, i;
1770 PIX *pix;
1771 PIXA *pixad;
1772 
1773  if (!pixas)
1774  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1775  if (copyflag != L_COPY && copyflag != L_CLONE)
1776  return (PIXA *)ERROR_PTR("invalid copyflag", __func__, NULL);
1777  n = pixaGetCount(pixas);
1778  first = L_MAX(0, first);
1779  if (last < 0) last = n - 1;
1780  if (first >= n)
1781  return (PIXA *)ERROR_PTR("invalid first", __func__, NULL);
1782  if (last >= n) {
1783  L_WARNING("last = %d is beyond max index = %d; adjusting\n",
1784  __func__, last, n - 1);
1785  last = n - 1;
1786  }
1787  if (first > last)
1788  return (PIXA *)ERROR_PTR("first > last", __func__, NULL);
1789 
1790  npix = last - first + 1;
1791  pixad = pixaCreate(npix);
1792  for (i = first; i <= last; i++) {
1793  pix = pixaGetPix(pixas, i, copyflag);
1794  pixaAddPix(pixad, pix, L_INSERT);
1795  }
1796  return pixad;
1797 }
1798 
1799 
1816 PIXAA *
1818  l_int32 first,
1819  l_int32 last,
1820  l_int32 copyflag)
1821 {
1822 l_int32 n, npixa, i;
1823 PIXA *pixa;
1824 PIXAA *paad;
1825 
1826  if (!paas)
1827  return (PIXAA *)ERROR_PTR("paas not defined", __func__, NULL);
1828  if (copyflag != L_COPY && copyflag != L_CLONE)
1829  return (PIXAA *)ERROR_PTR("invalid copyflag", __func__, NULL);
1830  n = pixaaGetCount(paas, NULL);
1831  first = L_MAX(0, first);
1832  if (last < 0) last = n - 1;
1833  if (first >= n)
1834  return (PIXAA *)ERROR_PTR("invalid first", __func__, NULL);
1835  if (last >= n) {
1836  L_WARNING("last = %d is beyond max index = %d; adjusting\n",
1837  __func__, last, n - 1);
1838  last = n - 1;
1839  }
1840  if (first > last)
1841  return (PIXAA *)ERROR_PTR("first > last", __func__, NULL);
1842 
1843  npixa = last - first + 1;
1844  paad = pixaaCreate(npixa);
1845  for (i = first; i <= last; i++) {
1846  pixa = pixaaGetPixa(paas, i, copyflag);
1847  pixaaAddPixa(paad, pixa, L_INSERT);
1848  }
1849  return paad;
1850 }
1851 
1852 
1853 /*---------------------------------------------------------------------*
1854  * Pixa and Pixaa scaling *
1855  *---------------------------------------------------------------------*/
1875 PIXAA *
1877  l_int32 wd,
1878  l_int32 hd)
1879 {
1880 l_int32 n, i;
1881 PIXA *pixa1, *pixa2;
1882 PIXAA *paad;
1883 
1884  if (!paas)
1885  return (PIXAA *)ERROR_PTR("paas not defined", __func__, NULL);
1886  if (wd <= 0 && hd <= 0)
1887  return (PIXAA *)ERROR_PTR("neither wd nor hd > 0", __func__, NULL);
1888 
1889  n = pixaaGetCount(paas, NULL);
1890  paad = pixaaCreate(n);
1891  for (i = 0; i < n; i++) {
1892  pixa1 = pixaaGetPixa(paas, i, L_CLONE);
1893  pixa2 = pixaScaleToSize(pixa1, wd, hd);
1894  pixaaAddPixa(paad, pixa2, L_INSERT);
1895  pixaDestroy(&pixa1);
1896  }
1897  return paad;
1898 }
1899 
1900 
1922 PIXAA *
1924  NUMA *nawd,
1925  NUMA *nahd)
1926 {
1927 l_int32 n, i, wd, hd;
1928 PIXA *pixa1, *pixa2;
1929 PIXAA *paad;
1930 
1931  if (!paas)
1932  return (PIXAA *)ERROR_PTR("paas not defined", __func__, NULL);
1933  if (!nawd && !nahd)
1934  return (PIXAA *)ERROR_PTR("!nawd && !nahd", __func__, NULL);
1935 
1936  n = pixaaGetCount(paas, NULL);
1937  if (nawd && (n != numaGetCount(nawd)))
1938  return (PIXAA *)ERROR_PTR("nawd wrong size", __func__, NULL);
1939  if (nahd && (n != numaGetCount(nahd)))
1940  return (PIXAA *)ERROR_PTR("nahd wrong size", __func__, NULL);
1941  paad = pixaaCreate(n);
1942  for (i = 0; i < n; i++) {
1943  wd = hd = 0;
1944  if (nawd) numaGetIValue(nawd, i, &wd);
1945  if (nahd) numaGetIValue(nahd, i, &hd);
1946  pixa1 = pixaaGetPixa(paas, i, L_CLONE);
1947  pixa2 = pixaScaleToSize(pixa1, wd, hd);
1948  pixaaAddPixa(paad, pixa2, L_INSERT);
1949  pixaDestroy(&pixa1);
1950  }
1951  return paad;
1952 }
1953 
1954 
1968 PIXA *
1970  l_int32 wd,
1971  l_int32 hd)
1972 {
1973 l_int32 n, i;
1974 PIX *pix1, *pix2;
1975 PIXA *pixad;
1976 
1977  if (!pixas)
1978  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1979 
1980  if (wd <= 0 && hd <= 0) /* no scaling requested */
1981  return pixaCopy(pixas, L_CLONE);
1982 
1983  n = pixaGetCount(pixas);
1984  pixad = pixaCreate(n);
1985  for (i = 0; i < n; i++) {
1986  pix1 = pixaGetPix(pixas, i, L_CLONE);
1987  pix2 = pixScaleToSize(pix1, wd, hd);
1988  pixCopyText(pix2, pix1);
1989  pixaAddPix(pixad, pix2, L_INSERT);
1990  pixDestroy(&pix1);
1991  }
1992  return pixad;
1993 }
1994 
1995 
2011 PIXA *
2013  l_int32 delw,
2014  l_int32 delh)
2015 {
2016 l_int32 n, i;
2017 PIX *pix1, *pix2;
2018 PIXA *pixad;
2019 
2020  if (!pixas)
2021  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2022 
2023  n = pixaGetCount(pixas);
2024  pixad = pixaCreate(n);
2025  for (i = 0; i < n; i++) {
2026  pix1 = pixaGetPix(pixas, i, L_CLONE);
2027  pix2 = pixScaleToSizeRel(pix1, delw, delh);
2028  if (pix2) {
2029  pixaAddPix(pixad, pix2, L_INSERT);
2030  } else {
2031  L_WARNING("relative scale to size failed; use a copy\n", __func__);
2032  pixaAddPix(pixad, pix1, L_COPY);
2033  }
2034  pixDestroy(&pix1);
2035  }
2036  return pixad;
2037 }
2038 
2039 
2053 PIXA *
2055  l_float32 scalex,
2056  l_float32 scaley)
2057 {
2058 l_int32 i, n, nb;
2059 BOXA *boxa1, *boxa2;
2060 PIX *pix1, *pix2;
2061 PIXA *pixad;
2062 
2063  if (!pixas)
2064  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2065  if (scalex <= 0.0 || scaley <= 0.0)
2066  return (PIXA *)ERROR_PTR("invalid scaling parameters", __func__, NULL);
2067 
2068  n = pixaGetCount(pixas);
2069  pixad = pixaCreate(n);
2070  for (i = 0; i < n; i++) {
2071  pix1 = pixaGetPix(pixas, i, L_CLONE);
2072  pix2 = pixScale(pix1, scalex, scaley);
2073  pixCopyText(pix2, pix1);
2074  pixaAddPix(pixad, pix2, L_INSERT);
2075  pixDestroy(&pix1);
2076  }
2077 
2078  boxa1 = pixaGetBoxa(pixas, L_CLONE);
2079  nb = boxaGetCount(boxa1);
2080  if (nb == n) {
2081  boxa2 = boxaTransform(boxa1, 0, 0, scalex, scaley);
2082  pixaSetBoxa(pixad, boxa2, L_INSERT);
2083  }
2084  boxaDestroy(&boxa1);
2085  return pixad;
2086 }
2087 
2088 
2102 PIXA *
2104  l_float32 scalex,
2105  l_float32 scaley)
2106 {
2107 l_int32 i, n, nb;
2108 BOXA *boxa1, *boxa2;
2109 PIX *pix1, *pix2;
2110 PIXA *pixad;
2111 
2112  if (!pixas)
2113  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2114  if (scalex <= 0.0 || scaley <= 0.0)
2115  return (PIXA *)ERROR_PTR("invalid scaling parameters", __func__, NULL);
2116 
2117  n = pixaGetCount(pixas);
2118  pixad = pixaCreate(n);
2119  for (i = 0; i < n; i++) {
2120  pix1 = pixaGetPix(pixas, i, L_CLONE);
2121  pix2 = pixScaleBySampling(pix1, scalex, scaley);
2122  pixCopyText(pix2, pix1);
2123  pixaAddPix(pixad, pix2, L_INSERT);
2124  pixDestroy(&pix1);
2125  }
2126 
2127  boxa1 = pixaGetBoxa(pixas, L_CLONE);
2128  nb = boxaGetCount(boxa1);
2129  if (nb == n) {
2130  boxa2 = boxaTransform(boxa1, 0, 0, scalex, scaley);
2131  pixaSetBoxa(pixad, boxa2, L_INSERT);
2132  }
2133  boxaDestroy(&boxa1);
2134  return pixad;
2135 }
2136 
2137 
2138 /*---------------------------------------------------------------------*
2139  * Pixa rotation and translation *
2140  *---------------------------------------------------------------------*/
2165 PIXA *
2167  l_float32 angle,
2168  l_int32 type,
2169  l_int32 incolor,
2170  l_int32 width,
2171  l_int32 height)
2172 {
2173 l_int32 i, n;
2174 BOXA *boxa;
2175 PIX *pixs, *pixd;
2176 PIXA *pixad;
2177 
2178  if (!pixas)
2179  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2180  if (type != L_ROTATE_SHEAR && type != L_ROTATE_AREA_MAP &&
2181  type != L_ROTATE_SAMPLING)
2182  return (PIXA *)ERROR_PTR("invalid type", __func__, NULL);
2183  if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
2184  return (PIXA *)ERROR_PTR("invalid incolor", __func__, NULL);
2185  if (L_ABS(angle) < MinAngleToRotate)
2186  return pixaCopy(pixas, L_COPY);
2187 
2188  n = pixaGetCount(pixas);
2189  if ((pixad = pixaCreate(n)) == NULL)
2190  return (PIXA *)ERROR_PTR("pixad not made", __func__, NULL);
2191  boxa = pixaGetBoxa(pixad, L_COPY);
2192  pixaSetBoxa(pixad, boxa, L_INSERT);
2193  for (i = 0; i < n; i++) {
2194  if ((pixs = pixaGetPix(pixas, i, L_CLONE)) == NULL) {
2195  pixaDestroy(&pixad);
2196  return (PIXA *)ERROR_PTR("pixs not found", __func__, NULL);
2197  }
2198  pixd = pixRotate(pixs, angle, type, incolor, width, height);
2199  pixaAddPix(pixad, pixd, L_INSERT);
2200  pixDestroy(&pixs);
2201  }
2202 
2203  return pixad;
2204 }
2205 
2206 
2221 PIXA *
2223  l_int32 rotation)
2224 {
2225 l_int32 i, n, nb, w, h;
2226 BOX *boxs, *boxd;
2227 PIX *pixs, *pixd;
2228 PIXA *pixad;
2229 
2230  if (!pixas)
2231  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2232  if (rotation < 0 || rotation > 3)
2233  return (PIXA *)ERROR_PTR("rotation not in {0,1,2,3}", __func__, NULL);
2234  if (rotation == 0)
2235  return pixaCopy(pixas, L_COPY);
2236 
2237  n = pixaGetCount(pixas);
2238  nb = pixaGetBoxaCount(pixas);
2239  if ((pixad = pixaCreate(n)) == NULL)
2240  return (PIXA *)ERROR_PTR("pixad not made", __func__, NULL);
2241  for (i = 0; i < n; i++) {
2242  if ((pixs = pixaGetPix(pixas, i, L_CLONE)) == NULL) {
2243  pixaDestroy(&pixad);
2244  return (PIXA *)ERROR_PTR("pixs not found", __func__, NULL);
2245  }
2246  pixd = pixRotateOrth(pixs, rotation);
2247  pixaAddPix(pixad, pixd, L_INSERT);
2248  if (n == nb) {
2249  boxs = pixaGetBox(pixas, i, L_COPY);
2250  pixGetDimensions(pixs, &w, &h, NULL);
2251  boxd = boxRotateOrth(boxs, w, h, rotation);
2252  pixaAddBox(pixad, boxd, L_INSERT);
2253  boxDestroy(&boxs);
2254  }
2255  pixDestroy(&pixs);
2256  }
2257 
2258  return pixad;
2259 }
2260 
2261 
2271 PIXA *
2273  l_int32 hshift,
2274  l_int32 vshift,
2275  l_int32 incolor)
2276 {
2277 l_int32 i, n, nb;
2278 BOXA *boxas, *boxad;
2279 PIX *pixs, *pixd;
2280 PIXA *pixad;
2281 
2282  if (!pixas)
2283  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2284  if (hshift == 0 && vshift == 0)
2285  return pixaCopy(pixas, L_COPY);
2286 
2287  n = pixaGetCount(pixas);
2288  nb = pixaGetBoxaCount(pixas);
2289  if ((pixad = pixaCreate(n)) == NULL)
2290  return (PIXA *)ERROR_PTR("pixad not made", __func__, NULL);
2291  for (i = 0; i < n; i++) {
2292  if ((pixs = pixaGetPix(pixas, i, L_CLONE)) == NULL) {
2293  pixaDestroy(&pixad);
2294  return (PIXA *)ERROR_PTR("pixs not found", __func__, NULL);
2295  }
2296  pixd = pixTranslate(NULL, pixs, hshift, vshift, incolor);
2297  pixaAddPix(pixad, pixd, L_INSERT);
2298  pixDestroy(&pixs);
2299  }
2300  if (n == nb) {
2301  boxas = pixaGetBoxa(pixas, L_CLONE);
2302  boxad = boxaTransform(boxas, hshift, vshift, 1.0, 1.0);
2303  pixaSetBoxa(pixad, boxad, L_INSERT);
2304  boxaDestroy(&boxas);
2305  }
2306 
2307  return pixad;
2308 }
2309 
2310 
2311 /*---------------------------------------------------------------------*
2312  * Miscellaneous functions *
2313  *---------------------------------------------------------------------*/
2343 PIXA *
2345  PIXA *pixas,
2346  l_int32 left,
2347  l_int32 right,
2348  l_int32 top,
2349  l_int32 bot,
2350  l_uint32 val)
2351 {
2352 l_int32 i, n, nbox;
2353 BOX *box;
2354 BOXA *boxad;
2355 PIX *pixs, *pixd;
2356 
2357  if (!pixas)
2358  return (PIXA *)ERROR_PTR("pixas not defined", __func__, pixad);
2359  if (left < 0 || right < 0 || top < 0 || bot < 0)
2360  return (PIXA *)ERROR_PTR("negative border added!", __func__, pixad);
2361  if (pixad && (pixad != pixas))
2362  return (PIXA *)ERROR_PTR("pixad defined but != pixas", __func__, pixad);
2363 
2364  n = pixaGetCount(pixas);
2365  if (!pixad)
2366  pixad = pixaCreate(n);
2367  for (i = 0; i < n; i++) {
2368  pixs = pixaGetPix(pixas, i, L_CLONE);
2369  pixd = pixAddBorderGeneral(pixs, left, right, top, bot, val);
2370  if (pixad == pixas) /* replace */
2371  pixaReplacePix(pixad, i, pixd, NULL);
2372  else
2373  pixaAddPix(pixad, pixd, L_INSERT);
2374  pixDestroy(&pixs);
2375  }
2376 
2377  nbox = pixaGetBoxaCount(pixas);
2378  boxad = pixaGetBoxa(pixad, L_CLONE);
2379  for (i = 0; i < nbox; i++) {
2380  if ((box = pixaGetBox(pixas, i, L_COPY)) == NULL) {
2381  L_WARNING("box %d not found\n", __func__, i);
2382  break;
2383  }
2384  boxAdjustSides(box, box, -left, right, -top, bot);
2385  if (pixad == pixas) /* replace */
2386  boxaReplaceBox(boxad, i, box);
2387  else
2388  boxaAddBox(boxad, box, L_INSERT);
2389  }
2390  boxaDestroy(&boxad);
2391 
2392  return pixad;
2393 }
2394 
2395 
2412 PIXA *
2414  NUMA **pnaindex,
2415  l_int32 copyflag)
2416 {
2417 l_int32 i, j, m, mb, n;
2418 BOX *box;
2419 NUMA *naindex;
2420 PIX *pix;
2421 PIXA *pixa, *pixat;
2422 
2423  if (pnaindex) *pnaindex = NULL;
2424  if (!paa)
2425  return (PIXA *)ERROR_PTR("paa not defined", __func__, NULL);
2426  if (copyflag != L_COPY && copyflag != L_CLONE)
2427  return (PIXA *)ERROR_PTR("invalid copyflag", __func__, NULL);
2428 
2429  if (pnaindex) {
2430  naindex = numaCreate(0);
2431  *pnaindex = naindex;
2432  }
2433 
2434  n = pixaaGetCount(paa, NULL);
2435  pixa = pixaCreate(n);
2436  for (i = 0; i < n; i++) {
2437  pixat = pixaaGetPixa(paa, i, L_CLONE);
2438  m = pixaGetCount(pixat);
2439  mb = pixaGetBoxaCount(pixat);
2440  for (j = 0; j < m; j++) {
2441  pix = pixaGetPix(pixat, j, copyflag);
2442  pixaAddPix(pixa, pix, L_INSERT);
2443  if (j < mb) {
2444  box = pixaGetBox(pixat, j, copyflag);
2445  pixaAddBox(pixa, box, L_INSERT);
2446  }
2447  if (pnaindex)
2448  numaAddNumber(naindex, i); /* save 'row' number */
2449  }
2450  pixaDestroy(&pixat);
2451  }
2452 
2453  return pixa;
2454 }
2455 
2456 
2465 l_ok
2467  l_int32 *pminw,
2468  l_int32 *pminh,
2469  l_int32 *pmaxw,
2470  l_int32 *pmaxh)
2471 {
2472 l_int32 minw, minh, maxw, maxh, minpw, minph, maxpw, maxph, i, n;
2473 PIXA *pixa;
2474 
2475  if (pminw) *pminw = 0;
2476  if (pminh) *pminh = 0;
2477  if (pmaxw) *pmaxw = 0;
2478  if (pmaxh) *pmaxh = 0;
2479  if (!paa)
2480  return ERROR_INT("paa not defined", __func__, 1);
2481  if (!pminw && !pmaxw && !pminh && !pmaxh)
2482  return ERROR_INT("no data can be returned", __func__, 1);
2483 
2484  minw = minh = 100000000;
2485  maxw = maxh = 0;
2486  n = pixaaGetCount(paa, NULL);
2487  for (i = 0; i < n; i++) {
2488  pixa = pixaaGetPixa(paa, i, L_CLONE);
2489  pixaSizeRange(pixa, &minpw, &minph, &maxpw, &maxph);
2490  if (minpw < minw)
2491  minw = minpw;
2492  if (minph < minh)
2493  minh = minph;
2494  if (maxpw > maxw)
2495  maxw = maxpw;
2496  if (maxph > maxh)
2497  maxh = maxph;
2498  pixaDestroy(&pixa);
2499  }
2500 
2501  if (pminw) *pminw = minw;
2502  if (pminh) *pminh = minh;
2503  if (pmaxw) *pmaxw = maxw;
2504  if (pmaxh) *pmaxh = maxh;
2505  return 0;
2506 }
2507 
2508 
2517 l_ok
2519  l_int32 *pminw,
2520  l_int32 *pminh,
2521  l_int32 *pmaxw,
2522  l_int32 *pmaxh)
2523 {
2524 l_int32 minw, minh, maxw, maxh, i, n, w, h;
2525 PIX *pix;
2526 
2527  if (pminw) *pminw = 0;
2528  if (pminh) *pminh = 0;
2529  if (pmaxw) *pmaxw = 0;
2530  if (pmaxh) *pmaxh = 0;
2531  if (!pixa)
2532  return ERROR_INT("pixa not defined", __func__, 1);
2533  if (!pminw && !pmaxw && !pminh && !pmaxh)
2534  return ERROR_INT("no data can be returned", __func__, 1);
2535 
2536  minw = minh = 1000000;
2537  maxw = maxh = 0;
2538  n = pixaGetCount(pixa);
2539  for (i = 0; i < n; i++) {
2540  pix = pixaGetPix(pixa, i, L_CLONE);
2541  w = pixGetWidth(pix);
2542  h = pixGetHeight(pix);
2543  if (w < minw)
2544  minw = w;
2545  if (h < minh)
2546  minh = h;
2547  if (w > maxw)
2548  maxw = w;
2549  if (h > maxh)
2550  maxh = h;
2551  pixDestroy(&pix);
2552  }
2553 
2554  if (pminw) *pminw = minw;
2555  if (pminh) *pminh = minh;
2556  if (pmaxw) *pmaxw = maxw;
2557  if (pmaxh) *pmaxh = maxh;
2558 
2559  return 0;
2560 }
2561 
2562 
2585 PIXA *
2587  PIX *pixs)
2588 {
2589 l_int32 i, n;
2590 BOX *box;
2591 PIX *pix, *pixc;
2592 PIXA *pixad;
2593 
2594  if (!pixas)
2595  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2596  if (!pixs)
2597  return (PIXA *)ERROR_PTR("pixs not defined", __func__, NULL);
2598 
2599  n = pixaGetCount(pixas);
2600  if ((pixad = pixaCreate(n)) == NULL)
2601  return (PIXA *)ERROR_PTR("pixad not made", __func__, NULL);
2602 
2603  for (i = 0; i < n; i++) {
2604  pix = pixaGetPix(pixas, i, L_CLONE);
2605  box = pixaGetBox(pixas, i, L_COPY);
2606  pixc = pixClipRectangle(pixs, box, NULL);
2607  pixAnd(pixc, pixc, pix);
2608  pixaAddPix(pixad, pixc, L_INSERT);
2609  pixaAddBox(pixad, box, L_INSERT);
2610  pixDestroy(&pix);
2611  }
2612 
2613  return pixad;
2614 }
2615 
2616 
2632 l_ok
2634  PIXA **ppixad,
2635  BOXA **pboxa)
2636 {
2637 l_int32 i, n;
2638 BOX *box1;
2639 PIX *pix1, *pix2;
2640 
2641  if (ppixad) *ppixad = NULL;
2642  if (pboxa) *pboxa = NULL;
2643  if (!pixas)
2644  return ERROR_INT("pixas not defined", __func__, 1);
2645  if (!ppixad && !pboxa)
2646  return ERROR_INT("no output requested", __func__, 1);
2647 
2648  n = pixaGetCount(pixas);
2649  if (ppixad) *ppixad = pixaCreate(n);
2650  if (pboxa) *pboxa = boxaCreate(n);
2651  for (i = 0; i < n; i++) {
2652  pix1 = pixaGetPix(pixas, i, L_CLONE);
2653  pixClipToForeground(pix1, &pix2, &box1);
2654  pixDestroy(&pix1);
2655  if (ppixad)
2656  pixaAddPix(*ppixad, pix2, L_INSERT);
2657  else
2658  pixDestroy(&pix2);
2659  if (pboxa)
2660  boxaAddBox(*pboxa, box1, L_INSERT);
2661  else
2662  boxDestroy(&box1);
2663  }
2664 
2665  return 0;
2666 }
2667 
2668 
2687 l_ok
2689  l_int32 *pdepth)
2690 {
2691 l_int32 hascolor, maxdepth;
2692 
2693  if (!pdepth)
2694  return ERROR_INT("&depth not defined", __func__, 1);
2695  *pdepth = 0;
2696  if (!pixa)
2697  return ERROR_INT("pixa not defined", __func__, 1);
2698 
2699  pixaHasColor(pixa, &hascolor);
2700  if (hascolor) {
2701  *pdepth = 32;
2702  return 0;
2703  }
2704 
2705  pixaGetDepthInfo(pixa, &maxdepth, NULL);
2706  if (maxdepth == 1)
2707  *pdepth = 1;
2708  else /* 2, 4, 8 or 16 */
2709  *pdepth = 8;
2710  return 0;
2711 }
2712 
2713 
2722 l_ok
2724  l_int32 *phascolor)
2725 {
2726 l_int32 i, n, hascolor, d;
2727 PIX *pix;
2728 PIXCMAP *cmap;
2729 
2730  if (!phascolor)
2731  return ERROR_INT("&hascolor not defined", __func__, 1);
2732  *phascolor = 0;
2733  if (!pixa)
2734  return ERROR_INT("pixa not defined", __func__, 1);
2735 
2736  n = pixaGetCount(pixa);
2737  hascolor = 0;
2738  for (i = 0; i < n; i++) {
2739  pix = pixaGetPix(pixa, i, L_CLONE);
2740  if ((cmap = pixGetColormap(pix)) != NULL)
2741  pixcmapHasColor(cmap, &hascolor);
2742  d = pixGetDepth(pix);
2743  pixDestroy(&pix);
2744  if (d == 32 || hascolor == 1) {
2745  *phascolor = 1;
2746  break;
2747  }
2748  }
2749 
2750  return 0;
2751 }
2752 
2753 
2761 l_ok
2763  l_int32 *phascmap)
2764 {
2765 l_int32 i, n;
2766 PIX *pix;
2767 PIXCMAP *cmap;
2768 
2769  if (!phascmap)
2770  return ERROR_INT("&hascmap not defined", __func__, 1);
2771  *phascmap = 0;
2772  if (!pixa)
2773  return ERROR_INT("pixa not defined", __func__, 1);
2774 
2775  n = pixaGetCount(pixa);
2776  for (i = 0; i < n; i++) {
2777  pix = pixaGetPix(pixa, i, L_CLONE);
2778  cmap = pixGetColormap(pix);
2779  pixDestroy(&pix);
2780  if (cmap) {
2781  *phascmap = 1;
2782  return 0;
2783  }
2784  }
2785 
2786  return 0;
2787 }
2788 
2789 
2798 l_ok
2800  l_int32 *pmaxdepth,
2801  l_int32 *psame)
2802 {
2803 l_int32 i, n, d, d0;
2804 l_int32 maxd, same; /* depth info */
2805 
2806  if (pmaxdepth) *pmaxdepth = 0;
2807  if (psame) *psame = TRUE;
2808  if (!pmaxdepth && !psame) return 0;
2809  if (!pixa)
2810  return ERROR_INT("pixa not defined", __func__, 1);
2811  if ((n = pixaGetCount(pixa)) == 0)
2812  return ERROR_INT("pixa is empty", __func__, 1);
2813 
2814  same = TRUE;
2815  maxd = 0;
2816  for (i = 0; i < n; i++) {
2817  pixaGetPixDimensions(pixa, i, NULL, NULL, &d);
2818  if (i == 0)
2819  d0 = d;
2820  else if (d != d0)
2821  same = FALSE;
2822  if (d > maxd) maxd = d;
2823  }
2824 
2825  if (pmaxdepth) *pmaxdepth = maxd;
2826  if (psame) *psame = same;
2827  return 0;
2828 }
2829 
2830 
2849 PIXA *
2851 {
2852 l_int32 i, n, depth, same, hascmap, maxdepth;
2853 BOXA *boxa;
2854 PIX *pix1, *pix2;
2855 PIXA *pixa1, *pixad;
2856 
2857  if (!pixas)
2858  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2859  if ((n = pixaGetCount(pixas)) == 0)
2860  return (PIXA *)ERROR_PTR("no components", __func__, NULL);
2861 
2862 
2863  /* Remove colormaps if necessary */
2864  pixaGetRenderingDepth(pixas, &depth);
2865  pixaAnyColormaps(pixas, &hascmap);
2866  if (hascmap) {
2867  pixa1 = pixaCreate(n);
2868  for (i = 0; i < n; i++) {
2869  pix1 = pixaGetPix(pixas, i, L_CLONE);
2870  if (depth == 32)
2871  pix2 = pixConvertTo32(pix1);
2872  else /* depth = 8 */
2873  pix2 = pixConvertTo8(pix1, 0);
2874  pixaAddPix(pixa1, pix2, L_INSERT);
2875  pixDestroy(&pix1);
2876  }
2877  } else {
2878  pixa1 = pixaCopy(pixas, L_CLONE);
2879  }
2880 
2881  pixaGetDepthInfo(pixa1, &maxdepth, &same);
2882  if (!same) { /* at least one pix has depth < maxdepth */
2883  pixad = pixaCreate(n);
2884  for (i = 0; i < n; i++) {
2885  pix1 = pixaGetPix(pixa1, i, L_CLONE);
2886  if (maxdepth <= 16)
2887  pix2 = pixConvertTo8(pix1, 0);
2888  else
2889  pix2 = pixConvertTo32(pix1);
2890  pixaAddPix(pixad, pix2, L_INSERT);
2891  pixDestroy(&pix1);
2892  }
2893  } else {
2894  pixad = pixaCopy(pixa1, L_CLONE);
2895  }
2896 
2897  boxa = pixaGetBoxa(pixas, L_COPY);
2898  pixaSetBoxa(pixad, boxa, L_INSERT);
2899  pixaDestroy(&pixa1);
2900  return pixad;
2901 }
2902 
2903 
2919 PIXA *
2921  l_int32 depth)
2922 {
2923 l_int32 i, n, maxd;
2924 BOXA *boxa;
2925 PIX *pix1, *pix2;
2926 PIXA *pixad;
2927 
2928  if (!pixas)
2929  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2930  if ((n = pixaGetCount(pixas)) == 0)
2931  return (PIXA *)ERROR_PTR("no components", __func__, NULL);
2932  if (depth != 8 && depth != 32)
2933  return (PIXA *)ERROR_PTR("depth not 8 or 32", __func__, NULL);
2934 
2935  /* Warn with 1 --> {8,32} or lossy conversions */
2936  pixaGetRenderingDepth(pixas, &maxd);
2937  if (maxd == 1)
2938  L_WARNING("All pix are 1 bpp; converting to %d bpp\n", __func__, depth);
2939  if (maxd > depth)
2940  L_WARNING("Lossy conversion: max rendering depth %d > input %d\n",
2941  __func__, maxd, depth);
2942 
2943  pixad = pixaCreate(n);
2944  for (i = 0; i < n; i++) {
2945  pix1 = pixaGetPix(pixas, i, L_CLONE);
2946  if (depth == 32) {
2947  pix2 = (pixGetDepth(pix1) == 32) ? pixClone(pix1) :
2948  pixConvertTo32(pix1);
2949  } else { /* depth = 8 */
2950  pix2 = pixConvertTo8(pix1, 0);
2951  }
2952  pixaAddPix(pixad, pix2, L_INSERT);
2953  pixDestroy(&pix1);
2954  }
2955 
2956  boxa = pixaGetBoxa(pixas, L_COPY);
2957  pixaSetBoxa(pixad, boxa, L_INSERT);
2958  return pixad;
2959 }
2960 
2961 
2990 l_ok
2992  PIXA *pixa2,
2993  l_int32 maxdist,
2994  NUMA **pnaindex,
2995  l_int32 *psame)
2996 {
2997 l_int32 i, j, n, empty1, empty2, same, sameboxa;
2998 BOXA *boxa1, *boxa2;
2999 NUMA *na;
3000 PIX *pix1, *pix2;
3001 
3002  if (pnaindex) *pnaindex = NULL;
3003  if (!psame)
3004  return ERROR_INT("&same not defined", __func__, 1);
3005  *psame = 0;
3006  sameboxa = 0;
3007  na = NULL;
3008  if (!pixa1 || !pixa2)
3009  return ERROR_INT("pixa1 and pixa2 not both defined", __func__, 1);
3010  n = pixaGetCount(pixa1);
3011  if (n != pixaGetCount(pixa2))
3012  return 0;
3013 
3014  /* If there are no boxes, strict ordering of the pix in each
3015  * pixa is required. */
3016  boxa1 = pixaGetBoxa(pixa1, L_CLONE);
3017  boxa2 = pixaGetBoxa(pixa2, L_CLONE);
3018  empty1 = (boxaGetCount(boxa1) == 0) ? 1 : 0;
3019  empty2 = (boxaGetCount(boxa2) == 0) ? 1 : 0;
3020  if (!empty1 && !empty2) {
3021  boxaEqual(boxa1, boxa2, maxdist, &na, &sameboxa);
3022  if (!sameboxa) {
3023  boxaDestroy(&boxa1);
3024  boxaDestroy(&boxa2);
3025  numaDestroy(&na);
3026  return 0;
3027  }
3028  }
3029  boxaDestroy(&boxa1);
3030  boxaDestroy(&boxa2);
3031  if ((!empty1 && empty2) || (empty1 && !empty2))
3032  return 0;
3033 
3034  for (i = 0; i < n; i++) {
3035  pix1 = pixaGetPix(pixa1, i, L_CLONE);
3036  if (na)
3037  numaGetIValue(na, i, &j);
3038  else
3039  j = i;
3040  pix2 = pixaGetPix(pixa2, j, L_CLONE);
3041  pixEqual(pix1, pix2, &same);
3042  pixDestroy(&pix1);
3043  pixDestroy(&pix2);
3044  if (!same) {
3045  numaDestroy(&na);
3046  return 0;
3047  }
3048  }
3049 
3050  *psame = 1;
3051  if (pnaindex)
3052  *pnaindex = na;
3053  else
3054  numaDestroy(&na);
3055  return 0;
3056 }
3057 
3058 
3072 l_ok
3074 {
3075 l_int32 i, n, w, h;
3076 BOX *box;
3077 BOXA *boxa;
3078 PIX *pix;
3079 
3080  if (!pixa)
3081  return ERROR_INT("pixa not defined", __func__, 1);
3082  if ((n = pixaGetCount(pixa)) == 0) {
3083  L_INFO("pixa contains no pix\n", __func__);
3084  return 0;
3085  }
3086 
3087  boxa = boxaCreate(n);
3088  pixaSetBoxa(pixa, boxa, L_INSERT);
3089  for (i = 0; i < n; i++) {
3090  pix = pixaGetPix(pixa, i, L_CLONE);
3091  pixGetDimensions(pix, &w, &h, NULL);
3092  box = boxCreate(0, 0, w, h);
3093  boxaAddBox(boxa, box, L_INSERT);
3094  pixDestroy(&pix);
3095  }
3096  return 0;
3097 }
3098 
l_ok boxGetGeometry(const BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:301
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:273
l_ok boxaReplaceBox(BOXA *boxa, l_int32 index, BOX *box)
boxaReplaceBox()
Definition: boxbasic.c:875
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:796
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:553
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:519
l_int32 boxaGetCount(const BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:661
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:702
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:171
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:442
l_ok boxaEqual(BOXA *boxa1, BOXA *boxa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame)
boxaEqual()
Definition: boxfunc1.c:2254
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1932
BOX * boxRotateOrth(BOX *box, l_int32 w, l_int32 h, l_int32 rotation)
boxRotateOrth()
Definition: boxfunc2.c:513
BOXA * boxaTransform(BOXA *boxas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
boxaTransform()
Definition: boxfunc2.c:103
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:922
l_ok pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:1026
l_ok pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame)
pixEqual()
Definition: compare.c:156
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:152
l_ok pixCountConnComp(PIX *pixs, l_int32 connectivity, l_int32 *pcount)
pixCountConnComp()
Definition: conncomp.c:389
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
l_int32 numaaGetNumberCount(NUMAA *naa)
numaaGetNumberCount()
Definition: numabasic.c:1551
NUMA * numaCreateFromString(const char *str)
numaCreateFromString()
Definition: numabasic.c:308
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
l_int32 numaaGetCount(NUMAA *naa)
numaaGetCount()
Definition: numabasic.c:1516
NUMA * numaaGetNuma(NUMAA *naa, l_int32 index, l_int32 accessflag)
numaaGetNuma()
Definition: numabasic.c:1617
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:720
NUMA * numaMakeThresholdIndicator(NUMA *nas, l_float32 thresh, l_int32 type)
numaMakeThresholdIndicator()
Definition: numafunc1.c:1184
NUMA * numaGetSortIndex(NUMA *na, l_int32 sortorder)
numaGetSortIndex()
Definition: numafunc1.c:2664
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:485
NUMA * numaGetBinSortIndex(NUMA *nas, l_int32 sortorder)
numaGetBinSortIndex()
Definition: numafunc1.c:2744
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition: pix1.c:795
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1863
l_ok pixZero(PIX *pix, l_int32 *pempty)
pixZero()
Definition: pix3.c:1777
NUMA * pixaCountPixels(PIXA *pixa)
pixaCountPixels()
Definition: pix3.c:1850
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1592
NUMA * pixaFindAreaFraction(PIXA *pixa)
pixaFindAreaFraction()
Definition: pix5.c:429
NUMA * pixaFindPerimSizeRatio(PIXA *pixa)
pixaFindPerimSizeRatio()
Definition: pix5.c:337
NUMA * pixaFindPerimToAreaRatio(PIXA *pixa)
pixaFindPerimToAreaRatio()
Definition: pix5.c:237
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:994
NUMA * pixaFindWidthHeightRatio(PIXA *pixa)
pixaFindWidthHeightRatio()
Definition: pix5.c:650
l_ok pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
pixClipToForeground()
Definition: pix5.c:1728
#define PIX_DST
Definition: pix.h:445
@ L_SELECT_IF_LTE
Definition: pix.h:577
@ L_SELECT_IF_LT
Definition: pix.h:575
@ L_SELECT_IF_GT
Definition: pix.h:576
@ L_SELECT_IF_GTE
Definition: pix.h:578
@ L_SELECT_IF_BOTH
Definition: pix.h:599
@ L_SELECT_IF_EITHER
Definition: pix.h:597
@ L_SELECT_WIDTH
Definition: pix.h:593
@ L_SELECT_HEIGHT
Definition: pix.h:594
@ L_SORT_BY_AREA
Definition: pix.h:537
@ L_SORT_BY_MIN_DIMENSION
Definition: pix.h:534
@ L_SORT_BY_PERIMETER
Definition: pix.h:536
@ L_SORT_BY_WIDTH
Definition: pix.h:532
@ L_SORT_BY_ASPECT_RATIO
Definition: pix.h:538
@ L_SORT_BY_HEIGHT
Definition: pix.h:533
@ L_SORT_BY_MAX_DIMENSION
Definition: pix.h:535
@ L_SORT_BY_Y
Definition: pix.h:529
@ L_SORT_BY_X
Definition: pix.h:528
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_INSERT
Definition: pix.h:504
#define PIX_SRC
Definition: pix.h:444
@ L_SORT_DECREASING
Definition: pix.h:523
@ L_SORT_INCREASING
Definition: pix.h:522
#define PIX_NOT(op)
Definition: pix.h:446
@ L_BRING_IN_BLACK
Definition: pix.h:663
@ L_BRING_IN_WHITE
Definition: pix.h:662
@ L_ROTATE_SAMPLING
Definition: pix.h:657
@ L_ROTATE_SHEAR
Definition: pix.h:656
@ L_ROTATE_AREA_MAP
Definition: pix.h:655
PIXAA * pixaaCreate(l_int32 n)
pixaaCreate()
Definition: pixabasic.c:1758
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:404
l_ok pixaVerifyDepth(PIXA *pixa, l_int32 *psame, l_int32 *pmaxd)
pixaVerifyDepth()
Definition: pixabasic.c:900
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:764
l_int32 pixaGetBoxaCount(PIXA *pixa)
pixaGetBoxaCount()
Definition: pixabasic.c:734
l_ok pixaaAddPixa(PIXAA *paa, PIXA *pixa, l_int32 copyflag)
pixaaAddPixa()
Definition: pixabasic.c:1898
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:680
PIXA * pixaCopy(PIXA *pixa, l_int32 copyflag)
pixaCopy()
Definition: pixabasic.c:442
l_ok pixaReplacePix(PIXA *pixa, l_int32 index, PIX *pix, BOX *box)
pixaReplacePix()
Definition: pixabasic.c:1246
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:629
l_ok pixaAddBox(PIXA *pixa, BOX *box, l_int32 copyflag)
pixaAddBox()
Definition: pixabasic.c:540
BOXA * pixaGetBoxa(PIXA *pixa, l_int32 accesstype)
pixaGetBoxa()
Definition: pixabasic.c:712
l_int32 pixaaGetCount(PIXAA *paa, NUMA **pna)
pixaaGetCount()
Definition: pixabasic.c:2049
PIXA * pixaaGetPixa(PIXAA *paa, l_int32 index, l_int32 accesstype)
pixaaGetPixa()
Definition: pixabasic.c:2096
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:647
l_ok pixaSetBoxa(PIXA *pixa, BOXA *boxa, l_int32 accesstype)
pixaSetBoxa()
Definition: pixabasic.c:840
PIXA * pixaSelectRange(PIXA *pixas, l_int32 first, l_int32 last, l_int32 copyflag)
pixaSelectRange()
Definition: pixafunc1.c:1764
l_ok pixaGetRenderingDepth(PIXA *pixa, l_int32 *pdepth)
pixaGetRenderingDepth()
Definition: pixafunc1.c:2688
PIXA * pixaSelectByWidthHeightRatio(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByWidthHeightRatio()
Definition: pixafunc1.c:1036
PIXA * pixaRotateOrth(PIXA *pixas, l_int32 rotation)
pixaRotateOrth()
Definition: pixafunc1.c:2222
l_ok pixaHasColor(PIXA *pixa, l_int32 *phascolor)
pixaHasColor()
Definition: pixafunc1.c:2723
PIXA * pixaSelectByAreaFraction(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByAreaFraction()
Definition: pixafunc1.c:777
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:220
PIXA * pixaSelectByNumConnComp(PIXA *pixas, l_int32 nmin, l_int32 nmax, l_int32 connectivity, l_int32 *pchanged)
pixaSelectByNumConnComp()
Definition: pixafunc1.c:1084
PIX * pixaRenderComponent(PIX *pixs, PIXA *pixa, l_int32 index)
pixaRenderComponent()
Definition: pixafunc1.c:1370
l_ok pixaSizeRange(PIXA *pixa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
pixaSizeRange()
Definition: pixafunc1.c:2518
PIXAA * pixaSort2dByIndex(PIXA *pixas, NUMAA *naa, l_int32 copyflag)
pixaSort2dByIndex()
Definition: pixafunc1.c:1701
PIXA * pixaSelectByPerimSizeRatio(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByPerimSizeRatio()
Definition: pixafunc1.c:647
PIXAA * pixaaScaleToSize(PIXAA *paas, l_int32 wd, l_int32 hd)
pixaaScaleToSize()
Definition: pixafunc1.c:1876
l_ok pixaaSizeRange(PIXAA *paa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
pixaaSizeRange()
Definition: pixafunc1.c:2466
l_ok pixaSetFullSizeBoxa(PIXA *pixa)
pixaSetFullSizeBoxa()
Definition: pixafunc1.c:3073
PIXA * pixaSelectByPerimToAreaRatio(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByPerimToAreaRatio()
Definition: pixafunc1.c:520
PIXA * pixaSelectWithString(PIXA *pixas, const char *str, l_int32 *perror)
pixaSelectWithString()
Definition: pixafunc1.c:1301
PIX * pixSelectByAreaFraction(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByAreaFraction()
Definition: pixafunc1.c:701
PIXA * pixaTranslate(PIXA *pixas, l_int32 hshift, l_int32 vshift, l_int32 incolor)
pixaTranslate()
Definition: pixafunc1.c:2272
PIXAA * pixaaSelectRange(PIXAA *paas, l_int32 first, l_int32 last, l_int32 copyflag)
pixaaSelectRange()
Definition: pixafunc1.c:1817
l_ok pixaAnyColormaps(PIXA *pixa, l_int32 *phascmap)
pixaAnyColormaps()
Definition: pixafunc1.c:2762
PIX * pixSelectByPerimToAreaRatio(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByPerimToAreaRatio()
Definition: pixafunc1.c:448
PIXA * pixaScale(PIXA *pixas, l_float32 scalex, l_float32 scaley)
pixaScale()
Definition: pixafunc1.c:2054
l_ok pixRemoveWithIndicator(PIX *pixs, PIXA *pixa, NUMA *na)
pixRemoveWithIndicator()
Definition: pixafunc1.c:1199
PIXA * pixaConvertToGivenDepth(PIXA *pixas, l_int32 depth)
pixaConvertToGivenDepth()
Definition: pixafunc1.c:2920
PIXA * pixaScaleBySampling(PIXA *pixas, l_float32 scalex, l_float32 scaley)
pixaScaleBySampling()
Definition: pixafunc1.c:2103
l_ok pixAddWithIndicator(PIX *pixs, PIXA *pixa, NUMA *na)
pixAddWithIndicator()
Definition: pixafunc1.c:1250
PIX * pixSelectByWidthHeightRatio(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByWidthHeightRatio()
Definition: pixafunc1.c:960
l_ok pixaClipToForeground(PIXA *pixas, PIXA **ppixad, BOXA **pboxa)
pixaClipToForeground()
Definition: pixafunc1.c:2633
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:2344
l_ok pixaGetDepthInfo(PIXA *pixa, l_int32 *pmaxdepth, l_int32 *psame)
pixaGetDepthInfo()
Definition: pixafunc1.c:2799
PIXA * pixaRotate(PIXA *pixas, l_float32 angle, l_int32 type, l_int32 incolor, l_int32 width, l_int32 height)
pixaRotate()
Definition: pixafunc1.c:2166
PIXA * pixaSortByIndex(PIXA *pixas, NUMA *naindex, l_int32 copyflag)
pixaSortByIndex()
Definition: pixafunc1.c:1662
PIXA * pixaSort(PIXA *pixas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex, l_int32 copyflag)
pixaSort()
Definition: pixafunc1.c:1438
PIXA * pixaBinSort(PIXA *pixas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex, l_int32 copyflag)
pixaBinSort()
Definition: pixafunc1.c:1576
PIXA * pixaSelectBySize(PIXA *pixas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
pixaSelectBySize()
Definition: pixafunc1.c:305
PIXAA * pixaaScaleToSizeVar(PIXAA *paas, NUMA *nawd, NUMA *nahd)
pixaaScaleToSizeVar()
Definition: pixafunc1.c:1923
l_ok pixaEqual(PIXA *pixa1, PIXA *pixa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame)
pixaEqual()
Definition: pixafunc1.c:2991
PIXA * pixaClipToPix(PIXA *pixas, PIX *pixs)
pixaClipToPix()
Definition: pixafunc1.c:2586
PIXA * pixaSelectByArea(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged)
pixaSelectByArea()
Definition: pixafunc1.c:907
PIXA * pixaScaleToSize(PIXA *pixas, l_int32 wd, l_int32 hd)
pixaScaleToSize()
Definition: pixafunc1.c:1969
PIXA * pixaaFlattenToPixa(PIXAA *paa, NUMA **pnaindex, l_int32 copyflag)
pixaaFlattenToPixa()
Definition: pixafunc1.c:2413
PIXA * pixaScaleToSizeRel(PIXA *pixas, l_int32 delw, l_int32 delh)
pixaScaleToSizeRel()
Definition: pixafunc1.c:2012
PIXA * pixaSelectWithIndicator(PIXA *pixas, NUMA *na, l_int32 *pchanged)
pixaSelectWithIndicator()
Definition: pixafunc1.c:1141
PIXA * pixaConvertToSameDepth(PIXA *pixas)
pixaConvertToSameDepth()
Definition: pixafunc1.c:2850
NUMA * pixaMakeSizeIndicator(PIXA *pixa, l_int32 width, l_int32 height, l_int32 type, l_int32 relation)
pixaMakeSizeIndicator()
Definition: pixafunc1.c:359
PIX * pixSelectByPerimSizeRatio(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByPerimSizeRatio()
Definition: pixafunc1.c:575
PIX * pixSelectByArea(PIX *pixs, l_float32 thresh, l_int32 connectivity, l_int32 type, l_int32 *pchanged)
pixSelectByArea()
Definition: pixafunc1.c:831
PIX * pixaDisplay(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplay()
Definition: pixafunc2.c:191
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3055
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3246
PIX * pixTranslate(PIX *pixd, PIX *pixs, l_int32 hshift, l_int32 vshift, l_int32 incolor)
pixTranslate()
Definition: rop.c:439
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
PIX * pixRotate(PIX *pixs, l_float32 angle, l_int32 type, l_int32 incolor, l_int32 width, l_int32 height)
pixRotate()
Definition: rotate.c:101
PIX * pixRotateOrth(PIX *pixs, l_int32 quads)
pixRotateOrth()
Definition: rotateorth.c:75
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
PIX * pixScaleToSizeRel(PIX *pixs, l_int32 delw, l_int32 delh)
pixScaleToSizeRel()
Definition: scale1.c:278
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:319
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1306
struct Boxa * boxa
Definition: pix_internal.h:238