Leptonica  1.83.1
Image processing and image analysis suite
pixafunc2.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 
159 #ifdef HAVE_CONFIG_H
160 #include <config_auto.h>
161 #endif /* HAVE_CONFIG_H */
162 
163 #include <string.h>
164 #include <math.h> /* for sqrt() */
165 #include "allheaders.h"
166 
167 /*---------------------------------------------------------------------*
168  * Pixa Display *
169  *---------------------------------------------------------------------*/
190 PIX *
192  l_int32 w,
193  l_int32 h)
194 {
195 l_int32 i, n, d, xb, yb, wb, hb, res;
196 BOXA *boxa;
197 PIX *pix1, *pixd;
198 
199  if (!pixa)
200  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
201 
202  n = pixaGetCount(pixa);
203  if (n == 0 && w == 0 && h == 0)
204  return (PIX *)ERROR_PTR("no components; no size", __func__, NULL);
205  if (n == 0) {
206  L_WARNING("no components; returning empty 1 bpp pix\n", __func__);
207  return pixCreate(w, h, 1);
208  }
209 
210  /* If w and h not input, determine the minimum size required
211  * to contain the origin and all c.c. */
212  if (w == 0 || h == 0) {
213  boxa = pixaGetBoxa(pixa, L_CLONE);
214  boxaGetExtent(boxa, &w, &h, NULL);
215  boxaDestroy(&boxa);
216  if (w == 0 || h == 0)
217  return (PIX *)ERROR_PTR("no associated boxa", __func__, NULL);
218  }
219 
220  /* Use the first pix in pixa to determine depth and resolution */
221  pix1 = pixaGetPix(pixa, 0, L_CLONE);
222  d = pixGetDepth(pix1);
223  res = pixGetXRes(pix1);
224  pixDestroy(&pix1);
225 
226  if ((pixd = pixCreate(w, h, d)) == NULL)
227  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
228  pixSetResolution(pixd, res, res);
229  if (d > 1)
230  pixSetAll(pixd);
231  for (i = 0; i < n; i++) {
232  if (pixaGetBoxGeometry(pixa, i, &xb, &yb, &wb, &hb)) {
233  L_WARNING("no box found!\n", __func__);
234  continue;
235  }
236  pix1 = pixaGetPix(pixa, i, L_CLONE);
237  if (d == 1)
238  pixRasterop(pixd, xb, yb, wb, hb, PIX_PAINT, pix1, 0, 0);
239  else
240  pixRasterop(pixd, xb, yb, wb, hb, PIX_SRC, pix1, 0, 0);
241  pixDestroy(&pix1);
242  }
243 
244  return pixd;
245 }
246 
247 
266 PIX *
268  l_int32 w,
269  l_int32 h)
270 {
271 l_int32 i, n, same, maxd, index, xb, yb, wb, hb, res;
272 BOXA *boxa;
273 PIX *pixs, *pix1, *pixd;
274 PIXCMAP *cmap;
275 
276  if (!pixa)
277  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
278 
279  if ((n = pixaGetCount(pixa)) == 0)
280  return (PIX *)ERROR_PTR("no components", __func__, NULL);
281  pixaVerifyDepth(pixa, &same, &maxd);
282  if (maxd > 1)
283  return (PIX *)ERROR_PTR("not all components are 1 bpp", __func__, NULL);
284 
285  /* If w and h are not input, determine the minimum size required
286  * to contain the origin and all c.c. */
287  if (w == 0 || h == 0) {
288  boxa = pixaGetBoxa(pixa, L_CLONE);
289  boxaGetExtent(boxa, &w, &h, NULL);
290  boxaDestroy(&boxa);
291  }
292 
293  /* Set up an 8 bpp dest pix, with a colormap with 254 random colors */
294  if ((pixd = pixCreate(w, h, 8)) == NULL)
295  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
296  cmap = pixcmapCreateRandom(8, 1, 1);
297  pixSetColormap(pixd, cmap);
298 
299  /* Color each component and blit it in */
300  for (i = 0; i < n; i++) {
301  index = 1 + (i % 254);
302  pixaGetBoxGeometry(pixa, i, &xb, &yb, &wb, &hb);
303  pixs = pixaGetPix(pixa, i, L_CLONE);
304  if (i == 0) res = pixGetXRes(pixs);
305  pix1 = pixConvert1To8(NULL, pixs, 0, index);
306  pixRasterop(pixd, xb, yb, wb, hb, PIX_PAINT, pix1, 0, 0);
307  pixDestroy(&pixs);
308  pixDestroy(&pix1);
309  }
310 
311  pixSetResolution(pixd, res, res);
312  return pixd;
313 }
314 
315 
338 PIX *
340  l_int32 direction,
341  l_float32 scalefactor,
342  l_int32 background, /* not used */
343  l_int32 spacing,
344  l_int32 border,
345  BOXA **pboxa)
346 {
347 l_int32 i, n, x, y, w, h, depth, bordval;
348 BOX *box;
349 PIX *pix1, *pix2, *pix3, *pixd;
350 PIXA *pixa1, *pixa2;
351 
352  if (pboxa) *pboxa = NULL;
353  if (!pixas)
354  return (PIX *)ERROR_PTR("pixas not defined", __func__, NULL);
355  if (direction != L_HORIZ && direction != L_VERT)
356  return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
357 
358  /* Make sure all pix are at the same depth */
359  pixa1 = pixaConvertToSameDepth(pixas);
360  pixaGetDepthInfo(pixa1, &depth, NULL);
361 
362  /* Scale and add border if requested */
363  n = pixaGetCount(pixa1);
364  pixa2 = pixaCreate(n);
365  bordval = (depth == 1) ? 1 : 0;
366  x = y = 0;
367  for (i = 0; i < n; i++) {
368  if ((pix1 = pixaGetPix(pixa1, i, L_CLONE)) == NULL) {
369  L_WARNING("missing pix at index %d\n", __func__, i);
370  continue;
371  }
372 
373  if (scalefactor != 1.0)
374  pix2 = pixScale(pix1, scalefactor, scalefactor);
375  else
376  pix2 = pixClone(pix1);
377  if (border)
378  pix3 = pixAddBorder(pix2, border, bordval);
379  else
380  pix3 = pixClone(pix2);
381 
382  pixGetDimensions(pix3, &w, &h, NULL);
383  box = boxCreate(x, y, w, h);
384  if (direction == L_HORIZ)
385  x += w + spacing;
386  else /* vertical */
387  y += h + spacing;
388  pixaAddPix(pixa2, pix3, L_INSERT);
389  pixaAddBox(pixa2, box, L_INSERT);
390  pixDestroy(&pix1);
391  pixDestroy(&pix2);
392  }
393  pixd = pixaDisplay(pixa2, 0, 0);
394 
395  if (pboxa)
396  *pboxa = pixaGetBoxa(pixa2, L_COPY);
397  pixaDestroy(&pixa1);
398  pixaDestroy(&pixa2);
399  return pixd;
400 }
401 
402 
429 PIX *
431  l_int32 cellw,
432  l_int32 cellh,
433  l_int32 *pncols,
434  BOXA **pboxa)
435 {
436 char buf[16];
437 l_int32 n, nw, nh, w, h, d, wt, ht, res, samedepth;
438 l_int32 index, i, j, hascmap;
439 BOX *box;
440 BOXA *boxa;
441 PIX *pix1, *pix2, *pixd;
442 PIXA *pixa1;
443 
444  if (pncols) *pncols = 0;
445  if (pboxa) *pboxa = NULL;
446  if (!pixa)
447  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
448 
449  /* If any pix have colormaps, or if the depths differ, generate rgb */
450  if ((n = pixaGetCount(pixa)) == 0)
451  return (PIX *)ERROR_PTR("no components", __func__, NULL);
452  pixaAnyColormaps(pixa, &hascmap);
453  pixaVerifyDepth(pixa, &samedepth, NULL);
454  if (hascmap || !samedepth) {
455  pixa1 = pixaCreate(n);
456  for (i = 0; i < n; i++) {
457  pix1 = pixaGetPix(pixa, i, L_CLONE);
458  pix2 = pixConvertTo32(pix1);
459  pixaAddPix(pixa1, pix2, L_INSERT);
460  pixDestroy(&pix1);
461  }
462  } else {
463  pixa1 = pixaCopy(pixa, L_CLONE);
464  }
465 
466  /* Have number of rows and columns approximately equal */
467  nw = (l_int32)sqrt((l_float64)n);
468  nh = (n + nw - 1) / nw;
469  w = cellw * nw;
470  h = cellh * nh;
471 
472  /* Use the first pix to determine output depth and resolution */
473  pix1 = pixaGetPix(pixa1, 0, L_CLONE);
474  d = pixGetDepth(pix1);
475  res = pixGetXRes(pix1);
476  pixDestroy(&pix1);
477  if ((pixd = pixCreate(w, h, d)) == NULL) {
478  pixaDestroy(&pixa1);
479  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
480  }
482  pixSetResolution(pixd, res, res);
483  boxa = boxaCreate(n);
484 
485  /* Tile the output */
486  index = 0;
487  for (i = 0; i < nh; i++) {
488  for (j = 0; j < nw && index < n; j++, index++) {
489  pix1 = pixaGetPix(pixa1, index, L_CLONE);
490  pixGetDimensions(pix1, &wt, &ht, NULL);
491  if (wt > cellw || ht > cellh) {
492  L_INFO("pix(%d) omitted; size %dx%x\n", __func__, index,
493  wt, ht);
494  box = boxCreate(0, 0, 0, 0);
495  boxaAddBox(boxa, box, L_INSERT);
496  pixDestroy(&pix1);
497  continue;
498  }
499  pixRasterop(pixd, j * cellw, i * cellh, wt, ht,
500  PIX_SRC, pix1, 0, 0);
501  box = boxCreate(j * cellw, i * cellh, wt, ht);
502  boxaAddBox(boxa, box, L_INSERT);
503  pixDestroy(&pix1);
504  }
505  }
506 
507  /* Save the number of tiles in the text field */
508  snprintf(buf, sizeof(buf), "n = %d", boxaGetCount(boxa));
509  pixSetText(pixd, buf);
510 
511  if (pncols) *pncols = nw;
512  if (pboxa)
513  *pboxa = boxa;
514  else
515  boxaDestroy(&boxa);
516  pixaDestroy(&pixa1);
517  return pixd;
518 }
519 
520 
544 PIX *
546  l_int32 nx,
547  l_int32 ny,
548  l_int32 borderwidth,
549  l_uint32 bordercolor)
550 {
551 l_int32 w, h, d, wt, ht;
552 l_int32 i, j, k, x, y, n;
553 PIX *pix1, *pixd;
554 
555  if (!pixa)
556  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
557  if (nx <= 0 || ny <= 0)
558  return (PIX *)ERROR_PTR("nx and ny must be > 0", __func__, NULL);
559  if ((n = pixaGetCount(pixa)) == 0)
560  return (PIX *)ERROR_PTR("no components", __func__, NULL);
561  if (n != nx * ny)
562  return (PIX *)ERROR_PTR("n != nx * ny", __func__, NULL);
563  borderwidth = L_MAX(0, borderwidth);
564 
565  pixaGetPixDimensions(pixa, 0, &wt, &ht, &d);
566  w = nx * (wt + 2 * borderwidth);
567  h = ny * (ht + 2 * borderwidth);
568 
569  if ((pixd = pixCreate(w, h, d)) == NULL)
570  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
571  pix1 = pixaGetPix(pixa, 0, L_CLONE);
572  pixCopyColormap(pixd, pix1);
573  pixDestroy(&pix1);
574  if (borderwidth > 0)
575  pixSetAllArbitrary(pixd, bordercolor);
576 
577  y = borderwidth;
578  for (i = 0, k = 0; i < ny; i++) {
579  x = borderwidth;
580  for (j = 0; j < nx; j++, k++) {
581  pix1 = pixaGetPix(pixa, k, L_CLONE);
582  pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pix1, 0, 0);
583  pixDestroy(&pix1);
584  x += wt + 2 * borderwidth;
585  }
586  y += ht + 2 * borderwidth;
587  }
588 
589  return pixd;
590 }
591 
592 
617 PIX *
619  l_int32 maxwidth,
620  l_int32 background,
621  l_int32 spacing)
622 {
623 l_int32 wmax, hmax, wd, hd, d, hascmap, res, same;
624 l_int32 i, j, n, ni, ncols, nrows;
625 l_int32 ystart, xstart, wt, ht;
626 PIX *pix1, *pix2, *pixd;
627 PIXA *pixa1;
628 
629  if (!pixa)
630  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
631  spacing = L_MAX(spacing, 0);
632  if ((n = pixaGetCount(pixa)) == 0)
633  return (PIX *)ERROR_PTR("no components", __func__, NULL);
634 
635  /* If any pix have colormaps, generate rgb */
636  pixaAnyColormaps(pixa, &hascmap);
637  if (hascmap) {
638  pixa1 = pixaCreate(n);
639  for (i = 0; i < n; i++) {
640  pix1 = pixaGetPix(pixa, i, L_CLONE);
641  pix2 = pixConvertTo32(pix1);
642  pixaAddPix(pixa1, pix2, L_INSERT);
643  pixDestroy(&pix1);
644  }
645  } else {
646  pixa1 = pixaCopy(pixa, L_CLONE);
647  }
648 
649  /* Find the max dimensions and depth subimages */
650  pixaGetDepthInfo(pixa1, &d, &same);
651  if (!same) {
652  pixaDestroy(&pixa1);
653  return (PIX *)ERROR_PTR("depths not equal", __func__, NULL);
654  }
655  pixaSizeRange(pixa1, NULL, NULL, &wmax, &hmax);
656 
657  /* Get the number of rows and columns and the output image size */
658  ncols = (l_int32)((l_float32)(maxwidth - spacing) /
659  (l_float32)(wmax + spacing));
660  ncols = L_MAX(ncols, 1);
661  nrows = (n + ncols - 1) / ncols;
662  wd = wmax * ncols + spacing * (ncols + 1);
663  hd = hmax * nrows + spacing * (nrows + 1);
664  if ((pixd = pixCreate(wd, hd, d)) == NULL) {
665  pixaDestroy(&pixa1);
666  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
667  }
668 
669  /* Reset the background color if necessary */
670  if ((background == 1 && d == 1) || (background == 0 && d != 1))
671  pixSetAll(pixd);
672 
673  /* Blit the images to the dest */
674  for (i = 0, ni = 0; i < nrows; i++) {
675  ystart = spacing + i * (hmax + spacing);
676  for (j = 0; j < ncols && ni < n; j++, ni++) {
677  xstart = spacing + j * (wmax + spacing);
678  pix1 = pixaGetPix(pixa1, ni, L_CLONE);
679  if (ni == 0) res = pixGetXRes(pix1);
680  pixGetDimensions(pix1, &wt, &ht, NULL);
681  pixRasterop(pixd, xstart, ystart, wt, ht, PIX_SRC, pix1, 0, 0);
682  pixDestroy(&pix1);
683  }
684  }
685  pixSetResolution(pixd, res, res);
686 
687  pixaDestroy(&pixa1);
688  return pixd;
689 }
690 
691 
729 PIX *
731  l_int32 outdepth,
732  l_int32 maxwidth,
733  l_float32 scalefactor,
734  l_int32 background,
735  l_int32 spacing,
736  l_int32 border)
737 {
738 l_int32 h; /* cumulative height over all the rows */
739 l_int32 w; /* cumulative height in the current row */
740 l_int32 bordval, wtry, wt, ht;
741 l_int32 irow; /* index of current pix in current row */
742 l_int32 wmaxrow; /* width of the largest row */
743 l_int32 maxh; /* max height in row */
744 l_int32 i, j, index, n, x, y, nrows, ninrow, res;
745 size_t size;
746 l_uint8 *data;
747 BOXA *boxa;
748 NUMA *nainrow; /* number of pix in the row */
749 NUMA *namaxh; /* height of max pix in the row */
750 PIX *pix, *pixn, *pix1, *pixd;
751 PIXA *pixan;
752 
753  if (!pixa)
754  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
755  if (outdepth != 1 && outdepth != 8 && outdepth != 32)
756  return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", __func__, NULL);
757  spacing = L_MAX(spacing, 0);
758  border = L_MAX(border, 0);
759  if (scalefactor <= 0.0) scalefactor = 1.0;
760 
761  if ((n = pixaGetCount(pixa)) == 0)
762  return (PIX *)ERROR_PTR("no components", __func__, NULL);
763 
764  /* Normalize depths, scale, remove colormaps; optionally add border */
765  pixan = pixaCreate(n);
766  bordval = (outdepth == 1) ? 1 : 0;
767  for (i = 0; i < n; i++) {
768  if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
769  continue;
770 
771  if (outdepth == 1)
772  pixn = pixConvertTo1(pix, 128);
773  else if (outdepth == 8)
774  pixn = pixConvertTo8(pix, FALSE);
775  else /* outdepth == 32 */
776  pixn = pixConvertTo32(pix);
777  pixDestroy(&pix);
778 
779  if (scalefactor != 1.0)
780  pix1 = pixScale(pixn, scalefactor, scalefactor);
781  else
782  pix1 = pixClone(pixn);
783  if (border)
784  pixd = pixAddBorder(pix1, border, bordval);
785  else
786  pixd = pixClone(pix1);
787  pixDestroy(&pixn);
788  pixDestroy(&pix1);
789 
790  pixaAddPix(pixan, pixd, L_INSERT);
791  }
792  if (pixaGetCount(pixan) != n) {
793  n = pixaGetCount(pixan);
794  L_WARNING("only got %d components\n", __func__, n);
795  if (n == 0) {
796  pixaDestroy(&pixan);
797  return (PIX *)ERROR_PTR("no components", __func__, NULL);
798  }
799  }
800 
801  /* Compute parameters for layout */
802  nainrow = numaCreate(0);
803  namaxh = numaCreate(0);
804  wmaxrow = 0;
805  w = h = spacing;
806  maxh = 0; /* max height in row */
807  for (i = 0, irow = 0; i < n; i++, irow++) {
808  pixaGetPixDimensions(pixan, i, &wt, &ht, NULL);
809  wtry = w + wt + spacing;
810  if (wtry > maxwidth) { /* end the current row and start next one */
811  numaAddNumber(nainrow, irow);
812  numaAddNumber(namaxh, maxh);
813  wmaxrow = L_MAX(wmaxrow, w);
814  h += maxh + spacing;
815  irow = 0;
816  w = wt + 2 * spacing;
817  maxh = ht;
818  } else {
819  w = wtry;
820  maxh = L_MAX(maxh, ht);
821  }
822  }
823 
824  /* Enter the parameters for the last row */
825  numaAddNumber(nainrow, irow);
826  numaAddNumber(namaxh, maxh);
827  wmaxrow = L_MAX(wmaxrow, w);
828  h += maxh + spacing;
829 
830  if ((pixd = pixCreate(wmaxrow, h, outdepth)) == NULL) {
831  numaDestroy(&nainrow);
832  numaDestroy(&namaxh);
833  pixaDestroy(&pixan);
834  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
835  }
836 
837  /* Reset the background color if necessary */
838  if ((background == 1 && outdepth == 1) ||
839  (background == 0 && outdepth != 1))
840  pixSetAll(pixd);
841 
842  /* Blit the images to the dest, and save the boxa identifying
843  * the image regions that do not include the borders. */
844  nrows = numaGetCount(nainrow);
845  y = spacing;
846  boxa = boxaCreate(n);
847  for (i = 0, index = 0; i < nrows; i++) { /* over rows */
848  numaGetIValue(nainrow, i, &ninrow);
849  numaGetIValue(namaxh, i, &maxh);
850  x = spacing;
851  for (j = 0; j < ninrow; j++, index++) { /* over pix in row */
852  pix = pixaGetPix(pixan, index, L_CLONE);
853  if (index == 0) {
854  res = pixGetXRes(pix);
855  pixSetResolution(pixd, res, res);
856  }
857  pixGetDimensions(pix, &wt, &ht, NULL);
858  boxaAddBox(boxa, boxCreate(x + border, y + border,
859  wt - 2 * border, ht - 2 *border), L_INSERT);
860  pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pix, 0, 0);
861  pixDestroy(&pix);
862  x += wt + spacing;
863  }
864  y += maxh + spacing;
865  }
866  if (boxaWriteMem(&data, &size, boxa) == 0)
867  pixSetText(pixd, (char *)data); /* data is ascii */
868  LEPT_FREE(data);
869  boxaDestroy(&boxa);
870 
871  numaDestroy(&nainrow);
872  numaDestroy(&namaxh);
873  pixaDestroy(&pixan);
874  return pixd;
875 }
876 
877 
911 PIX *
913  l_int32 nx,
914  l_float32 scalefactor,
915  l_int32 spacing,
916  l_int32 border)
917 {
918 l_int32 i, j, index, n, x, y, nrows, wb, hb, w, h, maxd, maxh, bordval, res;
919 size_t size;
920 l_uint8 *data;
921 BOX *box;
922 BOXA *boxa;
923 PIX *pix1, *pix2, *pix3, *pixd;
924 PIXA *pixa1, *pixa2;
925 
926  if (!pixas)
927  return (PIX *)ERROR_PTR("pixas not defined", __func__, NULL);
928  border = L_MAX(border, 0);
929  if (scalefactor <= 0.0) scalefactor = 1.0;
930  if ((n = pixaGetCount(pixas)) == 0)
931  return (PIX *)ERROR_PTR("no components", __func__, NULL);
932 
933  /* Convert to same depth, if necessary */
934  pixa1 = pixaConvertToSameDepth(pixas);
935  pixaGetDepthInfo(pixa1, &maxd, NULL);
936 
937  /* Scale and optionally add border */
938  pixa2 = pixaCreate(n);
939  bordval = (maxd == 1) ? 1 : 0;
940  for (i = 0; i < n; i++) {
941  if ((pix1 = pixaGetPix(pixa1, i, L_CLONE)) == NULL)
942  continue;
943  if (scalefactor != 1.0)
944  pix2 = pixScale(pix1, scalefactor, scalefactor);
945  else
946  pix2 = pixClone(pix1);
947  if (border)
948  pix3 = pixAddBorder(pix2, border, bordval);
949  else
950  pix3 = pixClone(pix2);
951  if (i == 0) res = pixGetXRes(pix3);
952  pixaAddPix(pixa2, pix3, L_INSERT);
953  pixDestroy(&pix1);
954  pixDestroy(&pix2);
955  }
956  pixaDestroy(&pixa1);
957  if (pixaGetCount(pixa2) != n) {
958  n = pixaGetCount(pixa2);
959  L_WARNING("only got %d components\n", __func__, n);
960  if (n == 0) {
961  pixaDestroy(&pixa2);
962  return (PIX *)ERROR_PTR("no components", __func__, NULL);
963  }
964  }
965 
966  /* Compute layout parameters and save as a boxa */
967  boxa = boxaCreate(n);
968  nrows = (n + nx - 1) / nx;
969  y = spacing;
970  for (i = 0, index = 0; i < nrows; i++) {
971  x = spacing;
972  maxh = 0;
973  for (j = 0; j < nx && index < n; j++) {
974  pixaGetPixDimensions(pixa2, index, &wb, &hb, NULL);
975  box = boxCreate(x, y, wb, hb);
976  boxaAddBox(boxa, box, L_INSERT);
977  maxh = L_MAX(maxh, hb + spacing);
978  x += wb + spacing;
979  index++;
980  }
981  y += maxh;
982  }
983  pixaSetBoxa(pixa2, boxa, L_INSERT);
984 
985  /* Render the output pix */
986  boxaGetExtent(boxa, &w, &h, NULL);
987  pixd = pixaDisplay(pixa2, w + spacing, h + spacing);
988  pixSetResolution(pixd, res, res);
989 
990  /* Save the boxa in the text field of the output pix */
991  if (boxaWriteMem(&data, &size, boxa) == 0)
992  pixSetText(pixd, (char *)data); /* data is ascii */
993  LEPT_FREE(data);
994 
995  pixaDestroy(&pixa2);
996  return pixd;
997 }
998 
999 
1024 PIX *
1026  l_int32 outdepth,
1027  l_int32 tilewidth,
1028  l_int32 ncols,
1029  l_int32 background,
1030  l_int32 spacing,
1031  l_int32 border)
1032 {
1033 l_int32 x, y, w, h, wd, hd, d, res;
1034 l_int32 i, n, nrows, maxht, ninrow, irow, bordval;
1035 l_int32 *rowht;
1036 l_float32 scalefact;
1037 PIX *pix, *pixn, *pix1, *pixb, *pixd;
1038 PIXA *pixan;
1039 
1040  if (!pixa)
1041  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
1042  if (outdepth != 1 && outdepth != 8 && outdepth != 32)
1043  return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", __func__, NULL);
1044  if (ncols <= 0)
1045  return (PIX *)ERROR_PTR("ncols must be > 0", __func__, NULL);
1046  spacing = L_MAX(spacing, 0);
1047  if (border < 0 || border > tilewidth / 5)
1048  border = 0;
1049  if ((n = pixaGetCount(pixa)) == 0)
1050  return (PIX *)ERROR_PTR("no components", __func__, NULL);
1051 
1052  /* Normalize scale and depth for each pix; optionally add border */
1053  pixan = pixaCreate(n);
1054  bordval = (outdepth == 1) ? 1 : 0;
1055  for (i = 0; i < n; i++) {
1056  if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
1057  continue;
1058 
1059  pixGetDimensions(pix, &w, &h, &d);
1060  scalefact = (l_float32)(tilewidth - 2 * border) / (l_float32)w;
1061  if (d == 1 && outdepth > 1 && scalefact < 1.0)
1062  pix1 = pixScaleToGray(pix, scalefact);
1063  else
1064  pix1 = pixScale(pix, scalefact, scalefact);
1065 
1066  if (outdepth == 1)
1067  pixn = pixConvertTo1(pix1, 128);
1068  else if (outdepth == 8)
1069  pixn = pixConvertTo8(pix1, FALSE);
1070  else /* outdepth == 32 */
1071  pixn = pixConvertTo32(pix1);
1072  pixDestroy(&pix1);
1073 
1074  if (border)
1075  pixb = pixAddBorder(pixn, border, bordval);
1076  else
1077  pixb = pixClone(pixn);
1078 
1079  pixaAddPix(pixan, pixb, L_INSERT);
1080  pixDestroy(&pix);
1081  pixDestroy(&pixn);
1082  }
1083  if ((n = pixaGetCount(pixan)) == 0) { /* should not have changed! */
1084  pixaDestroy(&pixan);
1085  return (PIX *)ERROR_PTR("no components", __func__, NULL);
1086  }
1087 
1088  /* Determine the size of each row and of pixd */
1089  wd = tilewidth * ncols + spacing * (ncols + 1);
1090  nrows = (n + ncols - 1) / ncols;
1091  if ((rowht = (l_int32 *)LEPT_CALLOC(nrows, sizeof(l_int32))) == NULL) {
1092  pixaDestroy(&pixan);
1093  return (PIX *)ERROR_PTR("rowht array not made", __func__, NULL);
1094  }
1095  maxht = 0;
1096  ninrow = 0;
1097  irow = 0;
1098  for (i = 0; i < n; i++) {
1099  pix = pixaGetPix(pixan, i, L_CLONE);
1100  ninrow++;
1101  pixGetDimensions(pix, &w, &h, NULL);
1102  maxht = L_MAX(h, maxht);
1103  if (ninrow == ncols) {
1104  rowht[irow] = maxht;
1105  maxht = ninrow = 0; /* reset */
1106  irow++;
1107  }
1108  pixDestroy(&pix);
1109  }
1110  if (ninrow > 0) { /* last fencepost */
1111  rowht[irow] = maxht;
1112  irow++; /* total number of rows */
1113  }
1114  nrows = irow;
1115  hd = spacing * (nrows + 1);
1116  for (i = 0; i < nrows; i++)
1117  hd += rowht[i];
1118 
1119  pixd = pixCreate(wd, hd, outdepth);
1120  if ((background == 1 && outdepth == 1) ||
1121  (background == 0 && outdepth != 1))
1122  pixSetAll(pixd);
1123 
1124  /* Now blit images to pixd */
1125  x = y = spacing;
1126  irow = 0;
1127  for (i = 0; i < n; i++) {
1128  pix = pixaGetPix(pixan, i, L_CLONE);
1129  if (i == 0) {
1130  res = pixGetXRes(pix);
1131  pixSetResolution(pixd, res, res);
1132  }
1133  pixGetDimensions(pix, &w, &h, NULL);
1134  if (i && ((i % ncols) == 0)) { /* start new row */
1135  x = spacing;
1136  y += spacing + rowht[irow];
1137  irow++;
1138  }
1139  pixRasterop(pixd, x, y, w, h, PIX_SRC, pix, 0, 0);
1140  x += tilewidth + spacing;
1141  pixDestroy(&pix);
1142  }
1143 
1144  pixaDestroy(&pixan);
1145  LEPT_FREE(rowht);
1146  return pixd;
1147 }
1148 
1149 
1177 PIX *
1179  l_int32 maxwidth,
1180  l_float32 scalefactor,
1181  l_int32 spacing,
1182  l_int32 border,
1183  l_int32 fontsize,
1184  l_uint32 textcolor)
1185 {
1186 char buf[128];
1187 char *textstr;
1188 l_int32 i, n, maxw;
1189 L_BMF *bmf;
1190 PIX *pix1, *pix2, *pix3, *pix4, *pixd;
1191 PIXA *pixad;
1192 
1193  if (!pixa)
1194  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
1195  if ((n = pixaGetCount(pixa)) == 0)
1196  return (PIX *)ERROR_PTR("no components", __func__, NULL);
1197  if (maxwidth <= 0)
1198  return (PIX *)ERROR_PTR("invalid maxwidth", __func__, NULL);
1199  spacing = L_MAX(spacing, 0);
1200  border = L_MAX(border, 0);
1201  if (scalefactor <= 0.0) scalefactor = 1.0;
1202  if (fontsize < 4 || fontsize > 20 || (fontsize & 1)) {
1203  l_int32 fsize = L_MAX(L_MIN(fontsize, 20), 4);
1204  if (fsize & 1) fsize--;
1205  L_WARNING("changed fontsize from %d to %d\n", __func__,
1206  fontsize, fsize);
1207  fontsize = fsize;
1208  }
1209 
1210  /* Be sure the width can accommodate a single column of images */
1211  pixaSizeRange(pixa, NULL, NULL, &maxw, NULL);
1212  maxwidth = L_MAX(maxwidth, scalefactor * (maxw + 2 * spacing + 2 * border));
1213 
1214  bmf = bmfCreate(NULL, fontsize);
1215  pixad = pixaCreate(n);
1216  for (i = 0; i < n; i++) {
1217  pix1 = pixaGetPix(pixa, i, L_CLONE);
1218  pix2 = pixConvertTo32(pix1);
1219  pix3 = pixAddBorderGeneral(pix2, spacing / 2, spacing / 2, spacing / 2,
1220  spacing / 2, 0xffffff00);
1221  textstr = pixGetText(pix1);
1222  if (textstr && strlen(textstr) > 0) {
1223  snprintf(buf, sizeof(buf), "%s", textstr);
1224  pix4 = pixAddSingleTextblock(pix3, bmf, buf, textcolor,
1225  L_ADD_BELOW, NULL);
1226  } else {
1227  pix4 = pixClone(pix3);
1228  }
1229  pixaAddPix(pixad, pix4, L_INSERT);
1230  pixDestroy(&pix1);
1231  pixDestroy(&pix2);
1232  pixDestroy(&pix3);
1233  }
1234  bmfDestroy(&bmf);
1235 
1236  pixd = pixaDisplayTiledInRows(pixad, 32, maxwidth, scalefactor,
1237  0, spacing, border);
1238  pixaDestroy(&pixad);
1239  return pixd;
1240 }
1241 
1242 
1271 PIX *
1273  NUMA *na,
1274  l_int32 width,
1275  l_int32 spacing,
1276  l_int32 border,
1277  l_int32 fontsize,
1278  l_uint32 textcolor)
1279 {
1280 char buf[128];
1281 char *textstr;
1282 l_int32 i, n, x, y, w, h, yval, index;
1283 l_float32 maxindex;
1284 L_BMF *bmf;
1285 BOX *box;
1286 NUMA *nay; /* top of the next pix to add in that column */
1287 PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pixd;
1288 PIXA *pixad;
1289 
1290  if (!pixa)
1291  return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
1292  if (!na)
1293  return (PIX *)ERROR_PTR("na not defined", __func__, NULL);
1294  if ((n = pixaGetCount(pixa)) == 0)
1295  return (PIX *)ERROR_PTR("no pixa components", __func__, NULL);
1296  if (n != numaGetCount(na))
1297  return (PIX *)ERROR_PTR("pixa and na counts differ", __func__, NULL);
1298  if (width <= 0)
1299  return (PIX *)ERROR_PTR("invalid width", __func__, NULL);
1300  if (width < 20)
1301  L_WARNING("very small width: %d\n", __func__, width);
1302  spacing = L_MAX(spacing, 0);
1303  border = L_MAX(border, 0);
1304  if (fontsize < 4 || fontsize > 20 || (fontsize & 1)) {
1305  l_int32 fsize = L_MAX(L_MIN(fontsize, 20), 4);
1306  if (fsize & 1) fsize--;
1307  L_WARNING("changed fontsize from %d to %d\n", __func__,
1308  fontsize, fsize);
1309  fontsize = fsize;
1310  }
1311 
1312  /* The pix will be rendered in the order they occupy in pixa. */
1313  bmf = bmfCreate(NULL, fontsize);
1314  pixad = pixaCreate(n);
1315  numaGetMax(na, &maxindex, NULL);
1316  nay = numaMakeConstant(spacing, lept_roundftoi(maxindex) + 1);
1317  for (i = 0; i < n; i++) {
1318  numaGetIValue(na, i, &index);
1319  numaGetIValue(nay, index, &yval);
1320  pix1 = pixaGetPix(pixa, i, L_CLONE);
1321  pix2 = pixConvertTo32(pix1);
1322  pix3 = pixScaleToSize(pix2, width, 0);
1323  pix4 = pixAddBorderGeneral(pix3, border, border, border, border, 0);
1324  textstr = pixGetText(pix1);
1325  if (textstr && strlen(textstr) > 0) {
1326  snprintf(buf, sizeof(buf), "%s", textstr);
1327  pix5 = pixAddTextlines(pix4, bmf, textstr, textcolor, L_ADD_BELOW);
1328  } else {
1329  pix5 = pixClone(pix4);
1330  }
1331  pixaAddPix(pixad, pix5, L_INSERT);
1332  x = spacing + border + index * (2 * border + width + spacing);
1333  y = yval;
1334  pixGetDimensions(pix5, &w, &h, NULL);
1335  yval += h + spacing;
1336  numaSetValue(nay, index, yval);
1337  box = boxCreate(x, y, w, h);
1338  pixaAddBox(pixad, box, L_INSERT);
1339  pixDestroy(&pix1);
1340  pixDestroy(&pix2);
1341  pixDestroy(&pix3);
1342  pixDestroy(&pix4);
1343  }
1344  numaDestroy(&nay);
1345  bmfDestroy(&bmf);
1346 
1347  pixd = pixaDisplay(pixad, 0, 0);
1348  pixaDestroy(&pixad);
1349  return pixd;
1350 }
1351 
1352 
1353 /*---------------------------------------------------------------------*
1354  * Pixa pair display *
1355  *---------------------------------------------------------------------*/
1393 PIX *
1395  PIXA *pixas2,
1396  l_int32 nx,
1397  l_float32 scalefactor,
1398  l_int32 spacing1,
1399  l_int32 spacing2,
1400  l_int32 border1,
1401  l_int32 border2,
1402  l_int32 fontsize,
1403  l_int32 startindex,
1404  SARRAY *sa)
1405 {
1406 l_int32 i, n, w, maxd, maxd1, maxd2, text;
1407 NUMA *na;
1408 PIX *pixs1, *pixs2, *pix1, *pix2, *pix3, *pix4;
1409 PIX *pix5, *pix6, *pix7, *pix8, *pix9;
1410 PIXA *pixa1, *pixa2;
1411 SARRAY *sa1;
1412 
1413  if (!pixas1)
1414  return (PIX *)ERROR_PTR("pixas1 not defined", __func__, NULL);
1415  if (!pixas2)
1416  return (PIX *)ERROR_PTR("pixas2 not defined", __func__, NULL);
1417  spacing1 = L_MAX(spacing1, 0);
1418  spacing2 = L_MAX(spacing2, 0);
1419  border1 = L_MAX(border1, 0);
1420  border2 = L_MAX(border2, 0);
1421  if (scalefactor <= 0.0) scalefactor = 1.0;
1422  if ((n = pixaGetCount(pixas1)) == 0)
1423  return (PIX *)ERROR_PTR("no components", __func__, NULL);
1424  if (n != pixaGetCount(pixas2))
1425  return (PIX *)ERROR_PTR("pixa sizes differ", __func__, NULL);
1426  text = (fontsize <= 0) ? 0 : 1;
1427  if (text && (fontsize < 4 || fontsize > 20 || (fontsize & 1))) {
1428  l_int32 fsize = L_MAX(L_MIN(fontsize, 20), 4);
1429  if (fsize & 1) fsize--;
1430  L_WARNING("changed fontsize from %d to %d\n", __func__,
1431  fontsize, fsize);
1432  fontsize = fsize;
1433  }
1434 
1435  /* Convert to same depth, if necessary */
1436  if (text) { /* adding color text; convert to 32 bpp */
1437  maxd = 32;
1438  } else {
1439  pixaGetRenderingDepth(pixas1, &maxd1);
1440  pixaGetRenderingDepth(pixas2, &maxd2);
1441  maxd = L_MAX(maxd1, maxd2);
1442  }
1443 
1444  /* Optionally scale and add borders to each pair;
1445  then combine the pairs and add outer border. */
1446  pixa1 = pixaCreate(n);
1447  for (i = 0; i < n; i++) {
1448  pixs1 = pixaGetPix(pixas1, i, L_CLONE);
1449  pixs2 = pixaGetPix(pixas2, i, L_CLONE);
1450  if (!pixs1 || !pixs2) continue;
1451  if (maxd == 1) {
1452  pix1 = pixClone(pixs1);
1453  pix2 = pixClone(pixs2);
1454  } else if (maxd == 8) {
1455  pix1 = pixConvertTo8(pixs1, 0);
1456  pix2 = pixConvertTo8(pixs2, 0);
1457  } else { /* maxd == 32 */
1458  pix1 = pixConvertTo32(pixs1);
1459  pix2 = pixConvertTo32(pixs2);
1460  }
1461  pixDestroy(&pixs1);
1462  pixDestroy(&pixs2);
1463  if (scalefactor != 1.0) {
1464  pix3 = pixScale(pix1, scalefactor, scalefactor);
1465  pix4 = pixScale(pix2, scalefactor, scalefactor);
1466  } else {
1467  pix3 = pixClone(pix1);
1468  pix4 = pixClone(pix2);
1469  }
1470  pixDestroy(&pix1);
1471  pixDestroy(&pix2);
1472  if (border1) {
1473  pix5 = pixAddBlackOrWhiteBorder(pix3, border1, border1, border1,
1474  border1, L_GET_BLACK_VAL);
1475  pix6 = pixAddBlackOrWhiteBorder(pix4, border1, border1, border1,
1476  border1, L_GET_BLACK_VAL);
1477  } else {
1478  pix5 = pixClone(pix3);
1479  pix6 = pixClone(pix4);
1480  }
1481  pixDestroy(&pix3);
1482  pixDestroy(&pix4);
1483  if (spacing1) { /* white border */
1484  pix7 = pixAddBlackOrWhiteBorder(pix5, spacing1 / 2, spacing1 / 2,
1485  spacing1 / 2, spacing1 / 2, L_GET_WHITE_VAL);
1486  pix8 = pixAddBlackOrWhiteBorder(pix6, spacing1 / 2, spacing1 / 2,
1487  spacing1 / 2, spacing1 / 2, L_GET_WHITE_VAL);
1488  } else {
1489  pix7 = pixClone(pix5);
1490  pix8 = pixClone(pix6);
1491  }
1492  pixDestroy(&pix5);
1493  pixDestroy(&pix6);
1494  pixa2 = pixaCreate(2);
1495  pixaAddPix(pixa2, pix7, L_INSERT);
1496  pixaAddPix(pixa2, pix8, L_INSERT);
1497  pix9 = pixaDisplayTiledInColumns(pixa2, 2, 1.0, 0, 0);
1498  pixaAddPix(pixa1, pix9, L_INSERT);
1499  pixaDestroy(&pixa2);
1500  }
1501 
1502  if (!text) {
1503  pix1 = pixaDisplayTiledInColumns(pixa1, nx, 1.0, spacing2, border2);
1504  } else {
1505  if (sa) {
1506  pixaSetText(pixa1, NULL, sa);
1507  } else {
1508  n = pixaGetCount(pixa1);
1509  na = numaMakeSequence(startindex, 1, n);
1510  sa1 = numaConvertToSarray(na, 4, 0, 0, L_INTEGER_VALUE);
1511  pixaSetText(pixa1, NULL, sa1);
1512  numaDestroy(&na);
1513  sarrayDestroy(&sa1);
1514  }
1515  pixaSizeRange(pixa1, NULL, NULL, &w, NULL);
1516  pix1 = pixaDisplayTiledWithText(pixa1, w * (nx + 1), 1.0, spacing2,
1517  border2, fontsize, 0xff000000);
1518  }
1519  pixaDestroy(&pixa1);
1520  return pix1;
1521 }
1522 
1523 
1524 /*---------------------------------------------------------------------*
1525  * Pixaa Display *
1526  *---------------------------------------------------------------------*/
1542 PIX *
1544  l_int32 w,
1545  l_int32 h)
1546 {
1547 l_int32 i, j, n, nbox, na, d, wmax, hmax, x, y, xb, yb, wb, hb;
1548 BOXA *boxa1; /* top-level boxa */
1549 BOXA *boxa;
1550 PIX *pix1, *pixd;
1551 PIXA *pixa;
1552 
1553  if (!paa)
1554  return (PIX *)ERROR_PTR("paa not defined", __func__, NULL);
1555 
1556  n = pixaaGetCount(paa, NULL);
1557  if (n == 0)
1558  return (PIX *)ERROR_PTR("no components", __func__, NULL);
1559 
1560  /* If w and h not input, determine the minimum size required
1561  * to contain the origin and all c.c. */
1562  boxa1 = pixaaGetBoxa(paa, L_CLONE);
1563  nbox = boxaGetCount(boxa1);
1564  if (w == 0 || h == 0) {
1565  if (nbox == n) {
1566  boxaGetExtent(boxa1, &w, &h, NULL);
1567  } else { /* have to use the lower-level boxa for each pixa */
1568  wmax = hmax = 0;
1569  for (i = 0; i < n; i++) {
1570  pixa = pixaaGetPixa(paa, i, L_CLONE);
1571  boxa = pixaGetBoxa(pixa, L_CLONE);
1572  boxaGetExtent(boxa, &w, &h, NULL);
1573  wmax = L_MAX(wmax, w);
1574  hmax = L_MAX(hmax, h);
1575  pixaDestroy(&pixa);
1576  boxaDestroy(&boxa);
1577  }
1578  w = wmax;
1579  h = hmax;
1580  }
1581  }
1582 
1583  /* Get depth from first pix */
1584  pixa = pixaaGetPixa(paa, 0, L_CLONE);
1585  pix1 = pixaGetPix(pixa, 0, L_CLONE);
1586  d = pixGetDepth(pix1);
1587  pixaDestroy(&pixa);
1588  pixDestroy(&pix1);
1589 
1590  if ((pixd = pixCreate(w, h, d)) == NULL) {
1591  boxaDestroy(&boxa1);
1592  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
1593  }
1594 
1595  x = y = 0;
1596  for (i = 0; i < n; i++) {
1597  pixa = pixaaGetPixa(paa, i, L_CLONE);
1598  if (nbox == n)
1599  boxaGetBoxGeometry(boxa1, i, &x, &y, NULL, NULL);
1600  na = pixaGetCount(pixa);
1601  for (j = 0; j < na; j++) {
1602  pixaGetBoxGeometry(pixa, j, &xb, &yb, &wb, &hb);
1603  pix1 = pixaGetPix(pixa, j, L_CLONE);
1604  pixRasterop(pixd, x + xb, y + yb, wb, hb, PIX_PAINT, pix1, 0, 0);
1605  pixDestroy(&pix1);
1606  }
1607  pixaDestroy(&pixa);
1608  }
1609  boxaDestroy(&boxa1);
1610 
1611  return pixd;
1612 }
1613 
1614 
1643 PIX *
1645  l_int32 maxnx,
1646  l_float32 scalefactor,
1647  l_int32 hspacing,
1648  l_int32 vspacing,
1649  l_int32 border)
1650 {
1651 l_int32 i, n, vs;
1652 PIX *pix1, *pix2;
1653 PIXA *pixa1, *pixa2;
1654 
1655  if (!paa)
1656  return (PIX *)ERROR_PTR("paa not defined", __func__, NULL);
1657  if (scalefactor <= 0.0) scalefactor = 1.0;
1658  if (hspacing < 0) hspacing = 0;
1659  if (vspacing < 0) vspacing = 0;
1660  if (border < 0) border = 0;
1661 
1662  if ((n = pixaaGetCount(paa, NULL)) == 0)
1663  return (PIX *)ERROR_PTR("no components", __func__, NULL);
1664 
1665  /* Vertical spacing of amount %hspacing is also added at this step */
1666  pixa2 = pixaCreate(0);
1667  for (i = 0; i < n; i++) {
1668  pixa1 = pixaaGetPixa(paa, i, L_CLONE);
1669  pix1 = pixaDisplayTiledInColumns(pixa1, maxnx, scalefactor,
1670  hspacing, border);
1671  pixaAddPix(pixa2, pix1, L_INSERT);
1672  pixaDestroy(&pixa1);
1673  }
1674 
1675  vs = vspacing - 2 * hspacing;
1676  pix2 = pixaDisplayTiledInColumns(pixa2, 1, scalefactor, vs, 0);
1677  pixaDestroy(&pixa2);
1678  return pix2;
1679 }
1680 
1681 
1704 PIXA *
1706  l_int32 outdepth,
1707  l_int32 tilewidth,
1708  l_int32 ncols,
1709  l_int32 background,
1710  l_int32 spacing,
1711  l_int32 border)
1712 {
1713 l_int32 i, n;
1714 PIX *pix;
1715 PIXA *pixa, *pixad;
1716 
1717  if (!paa)
1718  return (PIXA *)ERROR_PTR("paa not defined", __func__, NULL);
1719  if (outdepth != 1 && outdepth != 8 && outdepth != 32)
1720  return (PIXA *)ERROR_PTR("outdepth not in {1, 8, 32}", __func__, NULL);
1721  if (ncols <= 0)
1722  return (PIXA *)ERROR_PTR("ncols must be > 0", __func__, NULL);
1723  if (border < 0 || border > tilewidth / 5)
1724  border = 0;
1725 
1726  if ((n = pixaaGetCount(paa, NULL)) == 0)
1727  return (PIXA *)ERROR_PTR("no components", __func__, NULL);
1728 
1729  pixad = pixaCreate(n);
1730  for (i = 0; i < n; i++) {
1731  pixa = pixaaGetPixa(paa, i, L_CLONE);
1732  pix = pixaDisplayTiledAndScaled(pixa, outdepth, tilewidth, ncols,
1733  background, spacing, border);
1734  pixaAddPix(pixad, pix, L_INSERT);
1735  pixaDestroy(&pixa);
1736  }
1737 
1738  return pixad;
1739 }
1740 
1741 
1742 /*---------------------------------------------------------------------*
1743  * Conversion of all pix to specified type (e.g., depth) *
1744  *---------------------------------------------------------------------*/
1752 PIXA *
1754  l_int32 thresh)
1755 {
1756 l_int32 i, n;
1757 BOXA *boxa;
1758 PIX *pix1, *pix2;
1759 PIXA *pixad;
1760 
1761  if (!pixas)
1762  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1763 
1764  n = pixaGetCount(pixas);
1765  pixad = pixaCreate(n);
1766  for (i = 0; i < n; i++) {
1767  pix1 = pixaGetPix(pixas, i, L_CLONE);
1768  pix2 = pixConvertTo1(pix1, thresh);
1769  pixaAddPix(pixad, pix2, L_INSERT);
1770  pixDestroy(&pix1);
1771  }
1772 
1773  boxa = pixaGetBoxa(pixas, L_COPY);
1774  pixaSetBoxa(pixad, boxa, L_INSERT);
1775  return pixad;
1776 }
1777 
1778 
1791 PIXA *
1793  l_int32 cmapflag)
1794 {
1795 l_int32 i, n;
1796 BOXA *boxa;
1797 PIX *pix1, *pix2;
1798 PIXA *pixad;
1799 
1800  if (!pixas)
1801  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1802 
1803  n = pixaGetCount(pixas);
1804  pixad = pixaCreate(n);
1805  for (i = 0; i < n; i++) {
1806  pix1 = pixaGetPix(pixas, i, L_CLONE);
1807  pix2 = pixConvertTo8(pix1, cmapflag);
1808  pixaAddPix(pixad, pix2, L_INSERT);
1809  pixDestroy(&pix1);
1810  }
1811 
1812  boxa = pixaGetBoxa(pixas, L_COPY);
1813  pixaSetBoxa(pixad, boxa, L_INSERT);
1814  return pixad;
1815 }
1816 
1817 
1830 PIXA *
1832  l_int32 dither)
1833 {
1834 l_int32 i, n;
1835 BOXA *boxa;
1836 PIX *pix1, *pix2;
1837 PIXA *pixad;
1838 
1839  if (!pixas)
1840  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1841 
1842  n = pixaGetCount(pixas);
1843  pixad = pixaCreate(n);
1844  for (i = 0; i < n; i++) {
1845  pix1 = pixaGetPix(pixas, i, L_CLONE);
1846  pix2 = pixConvertTo8Colormap(pix1, dither);
1847  pixaAddPix(pixad, pix2, L_INSERT);
1848  pixDestroy(&pix1);
1849  }
1850 
1851  boxa = pixaGetBoxa(pixas, L_COPY);
1852  pixaSetBoxa(pixad, boxa, L_INSERT);
1853  return pixad;
1854 }
1855 
1856 
1870 PIXA *
1872 {
1873 l_int32 i, n;
1874 BOXA *boxa;
1875 PIX *pix1, *pix2;
1876 PIXA *pixad;
1877 
1878  if (!pixas)
1879  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1880 
1881  n = pixaGetCount(pixas);
1882  pixad = pixaCreate(n);
1883  for (i = 0; i < n; i++) {
1884  pix1 = pixaGetPix(pixas, i, L_CLONE);
1885  pix2 = pixConvertTo32(pix1);
1886  pixaAddPix(pixad, pix2, L_INSERT);
1887  pixDestroy(&pix1);
1888  }
1889 
1890  boxa = pixaGetBoxa(pixas, L_COPY);
1891  pixaSetBoxa(pixad, boxa, L_INSERT);
1892  return pixad;
1893 }
1894 
1895 
1896 /*---------------------------------------------------------------------*
1897  * Pixa constrained selection *
1898  *---------------------------------------------------------------------*/
1921 PIXA *
1923  l_int32 first,
1924  l_int32 last,
1925  l_int32 nmax,
1926  l_int32 use_pairs,
1927  l_int32 copyflag)
1928 {
1929 l_int32 i, n, nselect, index;
1930 NUMA *na;
1931 PIX *pix1;
1932 PIXA *pixad;
1933 
1934  if (!pixas)
1935  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
1936  n = pixaGetCount(pixas);
1937  first = L_MAX(0, first);
1938  last = (last < 0) ? n - 1 : L_MIN(n - 1, last);
1939  if (last < first)
1940  return (PIXA *)ERROR_PTR("last < first!", __func__, NULL);
1941  if (nmax < 1)
1942  return (PIXA *)ERROR_PTR("nmax < 1!", __func__, NULL);
1943 
1944  na = genConstrainedNumaInRange(first, last, nmax, use_pairs);
1945  nselect = numaGetCount(na);
1946  pixad = pixaCreate(nselect);
1947  for (i = 0; i < nselect; i++) {
1948  numaGetIValue(na, i, &index);
1949  pix1 = pixaGetPix(pixas, index, copyflag);
1950  pixaAddPix(pixad, pix1, L_INSERT);
1951  }
1952  numaDestroy(&na);
1953  return pixad;
1954 }
1955 
1956 
1987 l_ok
1989  l_int32 first,
1990  l_int32 last,
1991  l_int32 res,
1992  l_float32 scalefactor,
1993  l_int32 type,
1994  l_int32 quality,
1995  l_uint32 color,
1996  l_int32 fontsize,
1997  const char *fileout)
1998 {
1999 l_int32 n;
2000 L_BMF *bmf;
2001 NUMA *na;
2002 PIXA *pixa1, *pixa2;
2003 
2004  if (!pixas)
2005  return ERROR_INT("pixas not defined", __func__, 1);
2006  if (type < 0 || type > L_FLATE_ENCODE) {
2007  L_WARNING("invalid compression type; using default\n", __func__);
2008  type = 0;
2009  }
2010  if (!fileout)
2011  return ERROR_INT("fileout not defined", __func__, 1);
2012 
2013  /* Select from given range */
2014  n = pixaGetCount(pixas);
2015  first = L_MAX(0, first);
2016  last = (last < 0) ? n - 1 : L_MIN(n - 1, last);
2017  if (first > last) {
2018  L_ERROR("first = %d > last = %d\n", __func__, first, last);
2019  return 1;
2020  }
2021  pixa1 = pixaSelectRange(pixas, first, last, L_CLONE);
2022 
2023  /* Optionally add index numbers */
2024  bmf = (fontsize <= 0) ? NULL : bmfCreate(NULL, fontsize);
2025  if (bmf) {
2026  na = numaMakeSequence(first, 1.0, last - first + 1);
2027  pixa2 = pixaAddTextNumber(pixa1, bmf, na, color, L_ADD_LEFT);
2028  numaDestroy(&na);
2029  } else {
2030  pixa2 = pixaCopy(pixa1, L_CLONE);
2031  }
2032  pixaDestroy(&pixa1);
2033  bmfDestroy(&bmf);
2034 
2035  pixaConvertToPdf(pixa2, res, scalefactor, type, quality, NULL, fileout);
2036  pixaDestroy(&pixa2);
2037  return 0;
2038 }
2039 
2040 
2041 /*---------------------------------------------------------------------*
2042  * Generate pixa from tiled images *
2043  *---------------------------------------------------------------------*/
2064 PIXA *
2066  l_int32 w,
2067  l_int32 h,
2068  l_int32 nsamp)
2069 {
2070 char buf[8];
2071 l_int32 ntiles, i;
2072 PIX *pix1;
2073 PIXA *pixad, *pixa1;
2074 
2075  if (!pixas)
2076  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2077  if (nsamp > 1000)
2078  return (PIXA *)ERROR_PTR("nsamp too large; typ. 100", __func__, NULL);
2079 
2080  if (w <= 0) w = 20;
2081  if (h <= 0) h = 30;
2082  if (nsamp <= 0) nsamp = 100;
2083 
2084  /* pixas has 10 pix of mosaic'd digits. Each of these images
2085  * must be extracted into a pixa of templates, where each template
2086  * is labeled with the digit value, and then selectively
2087  * concatenated into an output pixa. */
2088  pixad = pixaCreate(10 * nsamp);
2089  for (i = 0; i < 10; i++) {
2090  pix1 = pixaGetPix(pixas, i, L_CLONE);
2091  pixGetTileCount(pix1, &ntiles);
2092  if (nsamp > ntiles)
2093  L_WARNING("requested %d; only %d tiles\n", __func__, nsamp, ntiles);
2094  pixa1 = pixaMakeFromTiledPix(pix1, w, h, 0, nsamp, NULL);
2095  snprintf(buf, sizeof(buf), "%d", i);
2096  pixaSetText(pixa1, buf, NULL);
2097  pixaJoin(pixad, pixa1, 0, -1);
2098  pixaDestroy(&pixa1);
2099  pixDestroy(&pix1);
2100  }
2101  return pixad;
2102 }
2103 
2104 
2142 PIXA *
2144  l_int32 w,
2145  l_int32 h,
2146  l_int32 start,
2147  l_int32 num,
2148  BOXA *boxa)
2149 {
2150 l_int32 i, j, k, ws, hs, d, nx, ny, n, n_isvalid, ntiles, nmax;
2151 PIX *pix1;
2152 PIXA *pixa1;
2153 PIXCMAP *cmap;
2154 
2155  if (!pixs)
2156  return (PIXA *)ERROR_PTR("pixs not defined", __func__, NULL);
2157  if (!boxa && (w <= 0 || h <= 0))
2158  return (PIXA *)ERROR_PTR("w and h must be > 0", __func__, NULL);
2159 
2160  if (boxa) /* general case */
2161  return pixaCreateFromBoxa(pixs, boxa, start, num, NULL);
2162 
2163  /* All tiles are the same size */
2164  pixGetDimensions(pixs, &ws, &hs, &d);
2165  nx = ws / w;
2166  ny = hs / h;
2167  if (nx < 1 || ny < 1)
2168  return (PIXA *)ERROR_PTR("invalid dimensions", __func__, NULL);
2169  if (nx * w != ws || ny * h != hs)
2170  L_WARNING("some tiles will be clipped\n", __func__);
2171 
2172  /* Check the text field of the pix. It may tell how many
2173  * tiles hold valid data. If a valid value is not found,
2174  * assume all (nx * ny) tiles are valid. */
2175  pixGetTileCount(pixs, &n);
2176  n_isvalid = (n <= nx * ny && n > nx * (ny - 1)) ? TRUE : FALSE;
2177  ntiles = (n_isvalid) ? n : nx * ny;
2178  nmax = ntiles - start; /* max available from start */
2179  num = (num == 0) ? nmax : L_MIN(num, nmax);
2180 
2181  /* Extract the tiles */
2182  if ((pixa1 = pixaCreate(num)) == NULL) {
2183  return (PIXA *)ERROR_PTR("pixa1 not made", __func__, NULL);
2184  }
2185  cmap = pixGetColormap(pixs);
2186  for (i = 0, k = 0; i < ny; i++) {
2187  for (j = 0; j < nx; j++, k++) {
2188  if (k < start) continue;
2189  if (k >= start + num) break;
2190  pix1 = pixCreate(w, h, d);
2191  if (cmap) pixSetColormap(pix1, pixcmapCopy(cmap));
2192  pixRasterop(pix1, 0, 0, w, h, PIX_SRC, pixs, j * w, i * h);
2193  pixaAddPix(pixa1, pix1, L_INSERT);
2194  }
2195  }
2196  return pixa1;
2197 }
2198 
2199 
2215 l_ok
2217  l_int32 *pn)
2218 {
2219 char *text;
2220 l_int32 n;
2221 
2222  if (!pn)
2223  return ERROR_INT("&n not defined", __func__, 1);
2224  *pn = 0;
2225  if (!pix)
2226  return ERROR_INT("pix not defined", __func__, 1);
2227 
2228  text = pixGetText(pix);
2229  if (text && strlen(text) > 4) {
2230  if (sscanf(text, "n = %d", &n) == 1)
2231  *pn = n;
2232  }
2233  return 0;
2234 }
2235 
2236 
2237 /*---------------------------------------------------------------------*
2238  * Pixa display into multiple tiles *
2239  *---------------------------------------------------------------------*/
2261 PIXA *
2263  l_int32 nx,
2264  l_int32 ny,
2265  l_int32 maxw,
2266  l_int32 maxh,
2267  l_float32 scalefactor,
2268  l_int32 spacing,
2269  l_int32 border)
2270 {
2271 l_int32 n, i, j, ntile, nout, index;
2272 PIX *pix1, *pix2;
2273 PIXA *pixa1, *pixa2, *pixad;
2274 
2275  if (!pixas)
2276  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2277  if (nx < 1 || ny < 1 || nx > 50 || ny > 50)
2278  return (PIXA *)ERROR_PTR("invalid tiling factor(s)", __func__, NULL);
2279  if ((n = pixaGetCount(pixas)) == 0)
2280  return (PIXA *)ERROR_PTR("pixas is empty", __func__, NULL);
2281 
2282  /* Filter out large ones if requested */
2283  if (maxw == 0 && maxh == 0) {
2284  pixa1 = pixaCopy(pixas, L_CLONE);
2285  } else {
2286  maxw = (maxw == 0) ? 1000000 : maxw;
2287  maxh = (maxh == 0) ? 1000000 : maxh;
2288  pixa1 = pixaSelectBySize(pixas, maxw, maxh, L_SELECT_IF_BOTH,
2289  L_SELECT_IF_LTE, NULL);
2290  n = pixaGetCount(pixa1);
2291  }
2292 
2293  ntile = nx * ny;
2294  nout = L_MAX(1, (n + ntile - 1) / ntile);
2295  pixad = pixaCreate(nout);
2296  for (i = 0, index = 0; i < nout; i++) { /* over tiles */
2297  pixa2 = pixaCreate(ntile);
2298  for (j = 0; j < ntile && index < n; j++, index++) {
2299  pix1 = pixaGetPix(pixa1, index, L_COPY);
2300  pixaAddPix(pixa2, pix1, L_INSERT);
2301  }
2302  pix2 = pixaDisplayTiledInColumns(pixa2, nx, scalefactor, spacing,
2303  border);
2304  pixaAddPix(pixad, pix2, L_INSERT);
2305  pixaDestroy(&pixa2);
2306  }
2307  pixaDestroy(&pixa1);
2308 
2309  return pixad;
2310 }
2311 
2312 
2313 /*---------------------------------------------------------------------*
2314  * Split pixa into files *
2315  *---------------------------------------------------------------------*/
2338 l_ok
2340  l_int32 nsplit,
2341  l_float32 scale,
2342  l_int32 outwidth,
2343  l_int32 write_pixa,
2344  l_int32 write_pix,
2345  l_int32 write_pdf)
2346 {
2347 char buf[64];
2348 l_int32 i, j, index, n, nt;
2349 PIX *pix1, *pix2;
2350 PIXA *pixa1;
2351 
2352  if (!pixas)
2353  return ERROR_INT("pixas not defined", __func__, 1);
2354  if (nsplit <= 1)
2355  return ERROR_INT("nsplit must be >= 2", __func__, 1);
2356  if ((nt = pixaGetCount(pixas)) == 0)
2357  return ERROR_INT("pixas is empty", __func__, 1);
2358  if (!write_pixa && !write_pix && !write_pdf)
2359  return ERROR_INT("no output is requested", __func__, 1);
2360 
2361  lept_mkdir("lept/split");
2362  n = (nt + nsplit - 1) / nsplit;
2363  lept_stderr("nt = %d, n = %d, nsplit = %d\n", nt, n, nsplit);
2364  for (i = 0, index = 0; i < nsplit; i++) {
2365  pixa1 = pixaCreate(n);
2366  for (j = 0; j < n && index < nt; j++, index++) {
2367  pix1 = pixaGetPix(pixas, index, L_CLONE);
2368  pix2 = pixScale(pix1, scale, scale);
2369  pixaAddPix(pixa1, pix2, L_INSERT);
2370  pixDestroy(&pix1);
2371  }
2372  if (write_pixa) {
2373  snprintf(buf, sizeof(buf), "/tmp/lept/split/split%d.pa", i + 1);
2374  pixaWriteDebug(buf, pixa1);
2375  }
2376  if (write_pix) {
2377  snprintf(buf, sizeof(buf), "/tmp/lept/split/split%d.tif", i + 1);
2378  pix1 = pixaDisplayTiledInRows(pixa1, 1, outwidth, 1.0, 0, 20, 2);
2379  pixWriteDebug(buf, pix1, IFF_TIFF_G4);
2380  pixDestroy(&pix1);
2381  }
2382  if (write_pdf) {
2383  snprintf(buf, sizeof(buf), "/tmp/lept/split/split%d.pdf", i + 1);
2384  pixaConvertToPdf(pixa1, 0, 1.0, L_G4_ENCODE, 0, buf, buf);
2385  }
2386  pixaDestroy(&pixa1);
2387  }
2388 
2389  return 0;
2390 }
2391 
2392 
2393 /*---------------------------------------------------------------------*
2394  * Tile N-Up *
2395  *---------------------------------------------------------------------*/
2425 l_ok
2426 convertToNUpFiles(const char *dir,
2427  const char *substr,
2428  l_int32 nx,
2429  l_int32 ny,
2430  l_int32 tw,
2431  l_int32 spacing,
2432  l_int32 border,
2433  l_int32 fontsize,
2434  const char *outdir)
2435 {
2436 l_int32 d, format;
2437 char rootpath[256];
2438 PIXA *pixa;
2439 
2440  if (!dir)
2441  return ERROR_INT("dir not defined", __func__, 1);
2442  if (nx < 1 || ny < 1 || nx > 50 || ny > 50)
2443  return ERROR_INT("invalid tiling N-factor", __func__, 1);
2444  if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2445  return ERROR_INT("invalid fontsize", __func__, 1);
2446  if (!outdir)
2447  return ERROR_INT("outdir not defined", __func__, 1);
2448 
2449  pixa = convertToNUpPixa(dir, substr, nx, ny, tw, spacing, border,
2450  fontsize);
2451  if (!pixa)
2452  return ERROR_INT("pixa not made", __func__, 1);
2453 
2454  lept_rmdir(outdir);
2455  lept_mkdir(outdir);
2456  pixaGetRenderingDepth(pixa, &d);
2457  format = (d == 1) ? IFF_TIFF_G4 : IFF_JFIF_JPEG;
2458  makeTempDirname(rootpath, 256, outdir);
2459  modifyTrailingSlash(rootpath, 256, L_ADD_TRAIL_SLASH);
2460  pixaWriteFiles(rootpath, pixa, format);
2461  pixaDestroy(&pixa);
2462  return 0;
2463 }
2464 
2465 
2485 PIXA *
2486 convertToNUpPixa(const char *dir,
2487  const char *substr,
2488  l_int32 nx,
2489  l_int32 ny,
2490  l_int32 tw,
2491  l_int32 spacing,
2492  l_int32 border,
2493  l_int32 fontsize)
2494 {
2495 l_int32 i, n;
2496 char *fname, *tail;
2497 PIXA *pixa1, *pixa2;
2498 SARRAY *sa1, *sa2;
2499 
2500  if (!dir)
2501  return (PIXA *)ERROR_PTR("dir not defined", __func__, NULL);
2502  if (nx < 1 || ny < 1 || nx > 50 || ny > 50)
2503  return (PIXA *)ERROR_PTR("invalid tiling N-factor", __func__, NULL);
2504  if (tw < 20)
2505  return (PIXA *)ERROR_PTR("tw must be >= 20", __func__, NULL);
2506  if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2507  return (PIXA *)ERROR_PTR("invalid fontsize", __func__, NULL);
2508 
2509  sa1 = getSortedPathnamesInDirectory(dir, substr, 0, 0);
2510  pixa1 = pixaReadFilesSA(sa1);
2511  n = sarrayGetCount(sa1);
2512  sa2 = sarrayCreate(n);
2513  for (i = 0; i < n; i++) {
2514  fname = sarrayGetString(sa1, i, L_NOCOPY);
2515  splitPathAtDirectory(fname, NULL, &tail);
2516  sarrayAddString(sa2, tail, L_INSERT);
2517  }
2518  sarrayDestroy(&sa1);
2519  pixa2 = pixaConvertToNUpPixa(pixa1, sa2, nx, ny, tw, spacing,
2520  border, fontsize);
2521  pixaDestroy(&pixa1);
2522  sarrayDestroy(&sa2);
2523  return pixa2;
2524 }
2525 
2526 
2549 PIXA *
2551  SARRAY *sa,
2552  l_int32 nx,
2553  l_int32 ny,
2554  l_int32 tw,
2555  l_int32 spacing,
2556  l_int32 border,
2557  l_int32 fontsize)
2558 {
2559 l_int32 i, j, k, nt, n2, nout, d;
2560 char *str;
2561 L_BMF *bmf;
2562 PIX *pix1, *pix2, *pix3, *pix4;
2563 PIXA *pixa1, *pixad;
2564 
2565  if (!pixas)
2566  return (PIXA *)ERROR_PTR("pixas not defined", __func__, NULL);
2567  if (nx < 1 || ny < 1 || nx > 50 || ny > 50)
2568  return (PIXA *)ERROR_PTR("invalid tiling N-factor", __func__, NULL);
2569  if (tw < 20)
2570  return (PIXA *)ERROR_PTR("tw must be >= 20", __func__, NULL);
2571  if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2572  return (PIXA *)ERROR_PTR("invalid fontsize", __func__, NULL);
2573 
2574  nt = pixaGetCount(pixas);
2575  if (sa && (sarrayGetCount(sa) != nt)) {
2576  L_WARNING("pixa size %d not equal to sarray size %d\n", __func__,
2577  nt, sarrayGetCount(sa));
2578  }
2579 
2580  n2 = nx * ny;
2581  nout = (nt + n2 - 1) / n2;
2582  pixad = pixaCreate(nout);
2583  bmf = (fontsize == 0) ? NULL : bmfCreate(NULL, fontsize);
2584  for (i = 0, j = 0; i < nout; i++) {
2585  pixa1 = pixaCreate(n2);
2586  for (k = 0; k < n2 && j < nt; j++, k++) {
2587  pix1 = pixaGetPix(pixas, j, L_CLONE);
2588  pix2 = pixScaleToSize(pix1, tw, 0); /* all images have width tw */
2589  if (bmf && sa) {
2590  str = sarrayGetString(sa, j, L_NOCOPY);
2591  pix3 = pixAddTextlines(pix2, bmf, str, 0xff000000,
2592  L_ADD_BELOW);
2593  } else {
2594  pix3 = pixClone(pix2);
2595  }
2596  pixaAddPix(pixa1, pix3, L_INSERT);
2597  pixDestroy(&pix1);
2598  pixDestroy(&pix2);
2599  }
2600  if (pixaGetCount(pixa1) == 0) { /* probably won't happen */
2601  pixaDestroy(&pixa1);
2602  continue;
2603  }
2604 
2605  /* Add 2 * border to image width to prevent scaling */
2606  pixaGetRenderingDepth(pixa1, &d);
2607  pix4 = pixaDisplayTiledAndScaled(pixa1, d, tw + 2 * border, nx, 0,
2608  spacing, border);
2609  pixaAddPix(pixad, pix4, L_INSERT);
2610  pixaDestroy(&pixa1);
2611  }
2612 
2613  bmfDestroy(&bmf);
2614  return pixad;
2615 }
2616 
2617 
2618 /*---------------------------------------------------------------------*
2619  * Render two pixa side-by-side for comparison *
2620  *---------------------------------------------------------------------*/
2660 l_ok
2662  PIXA *pixa2,
2663  l_int32 nx,
2664  l_int32 ny,
2665  l_int32 tw,
2666  l_int32 spacing,
2667  l_int32 border,
2668  l_int32 fontsize,
2669  const char *fileout)
2670 {
2671 l_int32 n1, n2, npairs;
2672 PIXA *pixa3, *pixa4, *pixa5;
2673 SARRAY *sa;
2674 
2675  if (!pixa1 || !pixa2)
2676  return ERROR_INT("pixa1 and pixa2 not both defined", __func__, 1);
2677  if (nx < 1 || ny < 1 || nx > 20 || ny > 20)
2678  return ERROR_INT("invalid tiling factors", __func__, 1);
2679  if (tw < 20)
2680  return ERROR_INT("invalid tw; tw must be >= 20", __func__, 1);
2681  if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2682  return ERROR_INT("invalid fontsize", __func__, 1);
2683  if (!fileout)
2684  return ERROR_INT("fileout not defined", __func__, 1);
2685  n1 = pixaGetCount(pixa1);
2686  n2 = pixaGetCount(pixa2);
2687  if (n1 == 0 || n2 == 0)
2688  return ERROR_INT("at least one pixa is empty", __func__, 1);
2689  if (n1 != n2)
2690  L_WARNING("sizes (%d, %d) differ; using the minimum in interleave\n",
2691  __func__, n1, n2);
2692 
2693  /* Interleave the input pixa */
2694  if ((pixa3 = pixaInterleave(pixa1, pixa2, L_CLONE)) == NULL)
2695  return ERROR_INT("pixa3 not made", __func__, 1);
2696 
2697  /* Scale the images if necessary and pair them up side/by/side */
2698  pixa4 = pixaConvertToNUpPixa(pixa3, NULL, 2, 1, tw, spacing, border, 0);
2699  pixaDestroy(&pixa3);
2700 
2701  /* Label the pairs and mosaic into pages without further scaling */
2702  npairs = pixaGetCount(pixa4);
2703  sa = (fontsize > 0) ? sarrayGenerateIntegers(npairs) : NULL;
2704  pixa5 = pixaConvertToNUpPixa(pixa4, sa, nx, ny,
2705  2 * tw + 4 * border + spacing,
2706  spacing, border, fontsize);
2707  pixaDestroy(&pixa4);
2708  sarrayDestroy(&sa);
2709 
2710  /* Output as pdf without scaling */
2711  pixaConvertToPdf(pixa5, 0, 1.0, 0, 0, NULL, fileout);
2712  pixaDestroy(&pixa5);
2713  return 0;
2714 }
2715 
2716 
@ L_INTEGER_VALUE
Definition: array.h:105
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:168
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:118
l_ok boxaWriteMem(l_uint8 **pdata, size_t *psize, BOXA *boxa)
boxaWriteMem()
Definition: boxbasic.c:2212
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 * 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 boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:922
PIXCMAP * pixcmapCreateRandom(l_int32 depth, l_int32 hasblack, l_int32 haswhite)
pixcmapCreateRandom()
Definition: colormap.c:171
PIXCMAP * pixcmapCopy(const PIXCMAP *cmaps)
pixcmapCopy()
Definition: colormap.c:243
@ L_FLATE_ENCODE
Definition: imageio.h:161
@ L_G4_ENCODE
Definition: imageio.h:160
SARRAY * numaConvertToSarray(NUMA *na, l_int32 size1, l_int32 size2, l_int32 addzeros, l_int32 type)
numaConvertToSarray()
Definition: numabasic.c:967
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:750
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 * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:820
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:485
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:792
NUMA * genConstrainedNumaInRange(l_int32 first, l_int32 last, l_int32 nmax, l_int32 use_pairs)
genConstrainedNumaInRange()
Definition: numafunc2.c:3215
l_ok pixaConvertToPdf(PIXA *pixa, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, const char *title, const char *fileout)
pixaConvertToPdf()
Definition: pdfio1.c:756
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1582
l_ok pixSetResolution(PIX *pix, l_int32 xres, l_int32 yres)
pixSetResolution()
Definition: pix1.c:1297
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
char * pixGetText(PIX *pix)
pixGetText()
Definition: pix1.c:1408
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
Definition: pix1.c:1430
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 * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1773
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 pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:799
PIX * pixAddBlackOrWhiteBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_int32 op)
pixAddBlackOrWhiteBorder()
Definition: pix2.c:1811
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:997
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:929
@ L_SELECT_IF_LTE
Definition: pix.h:577
@ L_SELECT_IF_BOTH
Definition: pix.h:599
@ L_ADD_LEFT
Definition: pix.h:1004
@ L_ADD_BELOW
Definition: pix.h:1003
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_NOCOPY
Definition: pix.h:503
@ L_INSERT
Definition: pix.h:504
#define PIX_PAINT
Definition: pix.h:450
@ L_SET_WHITE
Definition: pix.h:699
@ L_ADD_TRAIL_SLASH
Definition: pix.h:1081
#define PIX_SRC
Definition: pix.h:444
@ L_GET_BLACK_VAL
Definition: pix.h:709
@ L_GET_WHITE_VAL
Definition: pix.h:708
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
PIXA * pixaInterleave(PIXA *pixa1, PIXA *pixa2, l_int32 copyflag)
pixaInterleave()
Definition: pixabasic.c:1639
l_ok pixaSetText(PIXA *pixa, const char *text, SARRAY *sa)
pixaSetText()
Definition: pixabasic.c:1087
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_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
BOXA * pixaaGetBoxa(PIXAA *paa, l_int32 accesstype)
pixaaGetBoxa()
Definition: pixabasic.c:2132
l_ok pixaGetBoxGeometry(PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
pixaGetBoxGeometry()
Definition: pixabasic.c:800
l_ok pixaWriteDebug(const char *fname, PIXA *pixa)
pixaWriteDebug()
Definition: pixabasic.c:2613
PIXA * pixaCreateFromBoxa(PIX *pixs, BOXA *boxa, l_int32 start, l_int32 num, l_int32 *pcropwarn)
pixaCreateFromBoxa()
Definition: pixabasic.c:268
l_int32 pixaaGetCount(PIXAA *paa, NUMA **pna)
pixaaGetCount()
Definition: pixabasic.c:2049
l_ok pixaJoin(PIXA *pixad, PIXA *pixas, l_int32 istart, l_int32 iend)
pixaJoin()
Definition: pixabasic.c:1585
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
l_ok pixaSizeRange(PIXA *pixa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
pixaSizeRange()
Definition: pixafunc1.c:2518
l_ok pixaAnyColormaps(PIXA *pixa, l_int32 *phascmap)
pixaAnyColormaps()
Definition: pixafunc1.c:2762
l_ok pixaGetDepthInfo(PIXA *pixa, l_int32 *pmaxdepth, l_int32 *psame)
pixaGetDepthInfo()
Definition: pixafunc1.c:2799
PIXA * pixaSelectBySize(PIXA *pixas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
pixaSelectBySize()
Definition: pixafunc1.c:305
PIXA * pixaConvertToSameDepth(PIXA *pixas)
pixaConvertToSameDepth()
Definition: pixafunc1.c:2850
PIX * pixaDisplayTiled(PIXA *pixa, l_int32 maxwidth, l_int32 background, l_int32 spacing)
pixaDisplayTiled()
Definition: pixafunc2.c:618
PIX * pixaDisplay(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplay()
Definition: pixafunc2.c:191
PIXA * convertToNUpPixa(const char *dir, const char *substr, l_int32 nx, l_int32 ny, l_int32 tw, l_int32 spacing, l_int32 border, l_int32 fontsize)
convertToNUpPixa()
Definition: pixafunc2.c:2486
PIXA * pixaConvertTo1(PIXA *pixas, l_int32 thresh)
pixaConvertTo1()
Definition: pixafunc2.c:1753
PIX * pixaDisplayUnsplit(PIXA *pixa, l_int32 nx, l_int32 ny, l_int32 borderwidth, l_uint32 bordercolor)
pixaDisplayUnsplit()
Definition: pixafunc2.c:545
PIX * pixaDisplayLinearly(PIXA *pixas, l_int32 direction, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border, BOXA **pboxa)
pixaDisplayLinearly()
Definition: pixafunc2.c:339
l_ok pixGetTileCount(PIX *pix, l_int32 *pn)
pixGetTileCount()
Definition: pixafunc2.c:2216
PIXA * pixaMakeFromTiledPixa(PIXA *pixas, l_int32 w, l_int32 h, l_int32 nsamp)
pixaMakeFromTiledPixa()
Definition: pixafunc2.c:2065
PIXA * pixaConstrainedSelect(PIXA *pixas, l_int32 first, l_int32 last, l_int32 nmax, l_int32 use_pairs, l_int32 copyflag)
pixaConstrainedSelect()
Definition: pixafunc2.c:1922
PIX * pixaDisplayRandomCmap(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplayRandomCmap()
Definition: pixafunc2.c:267
PIXA * pixaConvertTo8Colormap(PIXA *pixas, l_int32 dither)
pixaConvertTo8Colormap()
Definition: pixafunc2.c:1831
PIX * pixaDisplayOnLattice(PIXA *pixa, l_int32 cellw, l_int32 cellh, l_int32 *pncols, BOXA **pboxa)
pixaDisplayOnLattice()
Definition: pixafunc2.c:430
PIX * pixaDisplayTiledInRows(PIXA *pixa, l_int32 outdepth, l_int32 maxwidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledInRows()
Definition: pixafunc2.c:730
PIXA * pixaConvertTo32(PIXA *pixas)
pixaConvertTo32()
Definition: pixafunc2.c:1871
l_ok pixaSplitIntoFiles(PIXA *pixas, l_int32 nsplit, l_float32 scale, l_int32 outwidth, l_int32 write_pixa, l_int32 write_pix, l_int32 write_pdf)
pixaSplitIntoFiles()
Definition: pixafunc2.c:2339
PIX * pixaDisplayTiledWithText(PIXA *pixa, l_int32 maxwidth, l_float32 scalefactor, l_int32 spacing, l_int32 border, l_int32 fontsize, l_uint32 textcolor)
pixaDisplayTiledWithText()
Definition: pixafunc2.c:1178
l_ok pixaCompareInPdf(PIXA *pixa1, PIXA *pixa2, l_int32 nx, l_int32 ny, l_int32 tw, l_int32 spacing, l_int32 border, l_int32 fontsize, const char *fileout)
pixaCompareInPdf()
Definition: pixafunc2.c:2661
l_ok convertToNUpFiles(const char *dir, const char *substr, l_int32 nx, l_int32 ny, l_int32 tw, l_int32 spacing, l_int32 border, l_int32 fontsize, const char *outdir)
convertToNUpFiles()
Definition: pixafunc2.c:2426
PIXA * pixaDisplayMultiTiled(PIXA *pixas, l_int32 nx, l_int32 ny, l_int32 maxw, l_int32 maxh, l_float32 scalefactor, l_int32 spacing, l_int32 border)
pixaDisplayMultiTiled()
Definition: pixafunc2.c:2262
PIXA * pixaConvertToNUpPixa(PIXA *pixas, SARRAY *sa, l_int32 nx, l_int32 ny, l_int32 tw, l_int32 spacing, l_int32 border, l_int32 fontsize)
pixaConvertToNUpPixa()
Definition: pixafunc2.c:2550
PIX * pixaaDisplay(PIXAA *paa, l_int32 w, l_int32 h)
pixaaDisplay()
Definition: pixafunc2.c:1543
PIX * pixaDisplayPairTiledInColumns(PIXA *pixas1, PIXA *pixas2, l_int32 nx, l_float32 scalefactor, l_int32 spacing1, l_int32 spacing2, l_int32 border1, l_int32 border2, l_int32 fontsize, l_int32 startindex, SARRAY *sa)
pixaDisplayPairTiledInColumns()
Definition: pixafunc2.c:1394
PIXA * pixaaDisplayTiledAndScaled(PIXAA *paa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border)
pixaaDisplayTiledAndScaled()
Definition: pixafunc2.c:1705
PIX * pixaDisplayTiledAndScaled(PIXA *pixa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledAndScaled()
Definition: pixafunc2.c:1025
PIXA * pixaConvertTo8(PIXA *pixas, l_int32 cmapflag)
pixaConvertTo8()
Definition: pixafunc2.c:1792
PIXA * pixaMakeFromTiledPix(PIX *pixs, l_int32 w, l_int32 h, l_int32 start, l_int32 num, BOXA *boxa)
pixaMakeFromTiledPix()
Definition: pixafunc2.c:2143
PIX * pixaaDisplayByPixa(PIXAA *paa, l_int32 maxnx, l_float32 scalefactor, l_int32 hspacing, l_int32 vspacing, l_int32 border)
pixaaDisplayByPixa()
Definition: pixafunc2.c:1644
PIX * pixaDisplayTiledInColumns(PIXA *pixas, l_int32 nx, l_float32 scalefactor, l_int32 spacing, l_int32 border)
pixaDisplayTiledInColumns()
Definition: pixafunc2.c:912
PIX * pixaDisplayTiledByIndex(PIXA *pixa, NUMA *na, l_int32 width, l_int32 spacing, l_int32 border, l_int32 fontsize, l_uint32 textcolor)
pixaDisplayTiledByIndex()
Definition: pixafunc2.c:1272
l_ok pixaSelectToPdf(PIXA *pixas, l_int32 first, l_int32 last, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, l_uint32 color, l_int32 fontsize, const char *fileout)
pixaSelectToPdf()
Definition: pixafunc2.c:1988
PIX * pixConvertTo8Colormap(PIX *pixs, l_int32 dither)
pixConvertTo8Colormap()
Definition: pixconv.c:3166
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
Definition: pixconv.c:2952
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2345
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3055
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3246
PIXA * pixaReadFilesSA(SARRAY *sa)
pixaReadFilesSA()
Definition: readfile.c:152
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
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:169
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:673
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:617
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:353
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:435
SARRAY * getSortedPathnamesInDirectory(const char *dirname, const char *substr, l_int32 first, l_int32 nfiles)
getSortedPathnamesInDirectory()
Definition: sarray1.c:1739
SARRAY * sarrayGenerateIntegers(l_int32 n)
sarrayGenerateIntegers()
Definition: sarray2.c:603
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:319
PIX * pixScaleToGray(PIX *pixs, l_float32 scalefactor)
pixScaleToGray()
Definition: scale2.c:208
Definition: bmf.h:47
PIX * pixAddTextlines(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location)
pixAddTextlines()
Definition: textops.c:274
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120
PIXA * pixaAddTextNumber(PIXA *pixas, L_BMF *bmf, NUMA *na, l_uint32 val, l_int32 location)
pixaAddTextNumber()
Definition: textops.c:641
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_roundftoi(l_float32 fval)
lept_roundftoi()
Definition: utils1.c:690
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2213
l_ok modifyTrailingSlash(char *path, size_t nbytes, l_int32 flag)
modifyTrailingSlash()
Definition: utils2.c:3238
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2728
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2138
l_ok makeTempDirname(char *result, size_t nbytes, const char *subdir)
makeTempDirname()
Definition: utils2.c:3175