Leptonica  1.77.0
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 
155 #include <string.h>
156 #include <math.h> /* for sqrt() */
157 #include "allheaders.h"
158 
159 
160 /*---------------------------------------------------------------------*
161  * Pixa Display *
162  *---------------------------------------------------------------------*/
183 PIX *
185  l_int32 w,
186  l_int32 h)
187 {
188 l_int32 i, n, d, xb, yb, wb, hb, res;
189 BOXA *boxa;
190 PIX *pix1, *pixd;
191 
192  PROCNAME("pixaDisplay");
193 
194  if (!pixa)
195  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
196 
197  n = pixaGetCount(pixa);
198  if (n == 0 && w == 0 && h == 0)
199  return (PIX *)ERROR_PTR("no components; no size", procName, NULL);
200  if (n == 0) {
201  L_WARNING("no components; returning empty 1 bpp pix\n", procName);
202  return pixCreate(w, h, 1);
203  }
204 
205  /* If w and h not input, determine the minimum size required
206  * to contain the origin and all c.c. */
207  if (w == 0 || h == 0) {
208  boxa = pixaGetBoxa(pixa, L_CLONE);
209  boxaGetExtent(boxa, &w, &h, NULL);
210  boxaDestroy(&boxa);
211  if (w == 0 || h == 0)
212  return (PIX *)ERROR_PTR("no associated boxa", procName, NULL);
213  }
214 
215  /* Use the first pix in pixa to determine depth and resolution */
216  pix1 = pixaGetPix(pixa, 0, L_CLONE);
217  d = pixGetDepth(pix1);
218  res = pixGetXRes(pix1);
219  pixDestroy(&pix1);
220 
221  if ((pixd = pixCreate(w, h, d)) == NULL)
222  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
223  pixSetResolution(pixd, res, res);
224  if (d > 1)
225  pixSetAll(pixd);
226  for (i = 0; i < n; i++) {
227  if (pixaGetBoxGeometry(pixa, i, &xb, &yb, &wb, &hb)) {
228  L_WARNING("no box found!\n", procName);
229  continue;
230  }
231  pix1 = pixaGetPix(pixa, i, L_CLONE);
232  if (d == 1)
233  pixRasterop(pixd, xb, yb, wb, hb, PIX_PAINT, pix1, 0, 0);
234  else
235  pixRasterop(pixd, xb, yb, wb, hb, PIX_SRC, pix1, 0, 0);
236  pixDestroy(&pix1);
237  }
238 
239  return pixd;
240 }
241 
242 
263 PIX *
265  l_int32 w,
266  l_int32 h,
267  l_uint32 bgcolor)
268 {
269 l_int32 i, n, xb, yb, wb, hb, hascmap, maxdepth, same, res;
270 BOXA *boxa;
271 PIX *pix1, *pix2, *pixd;
272 PIXA *pixat;
273 
274  PROCNAME("pixaDisplayOnColor");
275 
276  if (!pixa)
277  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
278  if ((n = pixaGetCount(pixa)) == 0)
279  return (PIX *)ERROR_PTR("no components", procName, NULL);
280 
281  /* If w and h are not input, determine the minimum size
282  * required to contain the origin and all c.c. */
283  if (w == 0 || h == 0) {
284  boxa = pixaGetBoxa(pixa, L_CLONE);
285  boxaGetExtent(boxa, &w, &h, NULL);
286  boxaDestroy(&boxa);
287  }
288 
289  /* If any pix have colormaps, or if they have different depths,
290  * generate rgb */
291  pixaAnyColormaps(pixa, &hascmap);
292  pixaGetDepthInfo(pixa, &maxdepth, &same);
293  if (hascmap || !same) {
294  maxdepth = 32;
295  pixat = pixaCreate(n);
296  for (i = 0; i < n; i++) {
297  pix1 = pixaGetPix(pixa, i, L_CLONE);
298  pix2 = pixConvertTo32(pix1);
299  pixaAddPix(pixat, pix2, L_INSERT);
300  pixDestroy(&pix1);
301  }
302  } else {
303  pixat = pixaCopy(pixa, L_CLONE);
304  }
305 
306  /* Make the output pix and set the background color */
307  if ((pixd = pixCreate(w, h, maxdepth)) == NULL) {
308  pixaDestroy(&pixat);
309  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
310  }
311  if ((maxdepth == 1 && bgcolor > 0) ||
312  (maxdepth == 2 && bgcolor >= 0x3) ||
313  (maxdepth == 4 && bgcolor >= 0xf) ||
314  (maxdepth == 8 && bgcolor >= 0xff) ||
315  (maxdepth == 16 && bgcolor >= 0xffff) ||
316  (maxdepth == 32 && bgcolor >= 0xffffff00)) {
317  pixSetAll(pixd);
318  } else if (bgcolor > 0) {
319  pixSetAllArbitrary(pixd, bgcolor);
320  }
321 
322  /* Blit each pix into its place */
323  for (i = 0; i < n; i++) {
324  if (pixaGetBoxGeometry(pixat, i, &xb, &yb, &wb, &hb)) {
325  L_WARNING("no box found!\n", procName);
326  continue;
327  }
328  pix1 = pixaGetPix(pixat, i, L_CLONE);
329  if (i == 0) res = pixGetXRes(pix1);
330  pixRasterop(pixd, xb, yb, wb, hb, PIX_SRC, pix1, 0, 0);
331  pixDestroy(&pix1);
332  }
333  pixSetResolution(pixd, res, res);
334 
335  pixaDestroy(&pixat);
336  return pixd;
337 }
338 
339 
358 PIX *
360  l_int32 w,
361  l_int32 h)
362 {
363 l_int32 i, n, same, maxd, index, xb, yb, wb, hb, res;
364 BOXA *boxa;
365 PIX *pixs, *pix1, *pixd;
366 PIXCMAP *cmap;
367 
368  PROCNAME("pixaDisplayRandomCmap");
369 
370  if (!pixa)
371  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
372 
373  if ((n = pixaGetCount(pixa)) == 0)
374  return (PIX *)ERROR_PTR("no components", procName, NULL);
375  pixaVerifyDepth(pixa, &same, &maxd);
376  if (maxd > 1)
377  return (PIX *)ERROR_PTR("not all components are 1 bpp", procName, NULL);
378 
379  /* If w and h are not input, determine the minimum size required
380  * to contain the origin and all c.c. */
381  if (w == 0 || h == 0) {
382  boxa = pixaGetBoxa(pixa, L_CLONE);
383  boxaGetExtent(boxa, &w, &h, NULL);
384  boxaDestroy(&boxa);
385  }
386 
387  /* Set up an 8 bpp dest pix, with a colormap with 254 random colors */
388  if ((pixd = pixCreate(w, h, 8)) == NULL)
389  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
390  cmap = pixcmapCreateRandom(8, 1, 1);
391  pixSetColormap(pixd, cmap);
392 
393  /* Color each component and blit it in */
394  for (i = 0; i < n; i++) {
395  index = 1 + (i % 254);
396  pixaGetBoxGeometry(pixa, i, &xb, &yb, &wb, &hb);
397  pixs = pixaGetPix(pixa, i, L_CLONE);
398  if (i == 0) res = pixGetXRes(pixs);
399  pix1 = pixConvert1To8(NULL, pixs, 0, index);
400  pixRasterop(pixd, xb, yb, wb, hb, PIX_PAINT, pix1, 0, 0);
401  pixDestroy(&pixs);
402  pixDestroy(&pix1);
403  }
404 
405  pixSetResolution(pixd, res, res);
406  return pixd;
407 }
408 
409 
432 PIX *
434  l_int32 direction,
435  l_float32 scalefactor,
436  l_int32 background, /* not used */
437  l_int32 spacing,
438  l_int32 border,
439  BOXA **pboxa)
440 {
441 l_int32 i, n, x, y, w, h, size, depth, bordval;
442 BOX *box;
443 PIX *pix1, *pix2, *pix3, *pixd;
444 PIXA *pixa1, *pixa2;
445 
446  PROCNAME("pixaDisplayLinearly");
447 
448  if (pboxa) *pboxa = NULL;
449  if (!pixas)
450  return (PIX *)ERROR_PTR("pixas not defined", procName, NULL);
451  if (direction != L_HORIZ && direction != L_VERT)
452  return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
453 
454  /* Make sure all pix are at the same depth */
455  pixa1 = pixaConvertToSameDepth(pixas);
456  pixaGetDepthInfo(pixa1, &depth, NULL);
457 
458  /* Scale and add border if requested */
459  n = pixaGetCount(pixa1);
460  pixa2 = pixaCreate(n);
461  bordval = (depth == 1) ? 1 : 0;
462  size = (n - 1) * spacing;
463  x = y = 0;
464  for (i = 0; i < n; i++) {
465  if ((pix1 = pixaGetPix(pixa1, i, L_CLONE)) == NULL) {
466  L_WARNING("missing pix at index %d\n", procName, i);
467  continue;
468  }
469 
470  if (scalefactor != 1.0)
471  pix2 = pixScale(pix1, scalefactor, scalefactor);
472  else
473  pix2 = pixClone(pix1);
474  if (border)
475  pix3 = pixAddBorder(pix2, border, bordval);
476  else
477  pix3 = pixClone(pix2);
478 
479  pixGetDimensions(pix3, &w, &h, NULL);
480  box = boxCreate(x, y, w, h);
481  if (direction == L_HORIZ) {
482  size += w;
483  x += w + spacing;
484  } else { /* vertical */
485  size += h;
486  y += h + spacing;
487  }
488  pixaAddPix(pixa2, pix3, L_INSERT);
489  pixaAddBox(pixa2, box, L_INSERT);
490  pixDestroy(&pix1);
491  pixDestroy(&pix2);
492  }
493  pixd = pixaDisplay(pixa2, 0, 0);
494 
495  if (pboxa)
496  *pboxa = pixaGetBoxa(pixa2, L_COPY);
497  pixaDestroy(&pixa1);
498  pixaDestroy(&pixa2);
499  return pixd;
500 }
501 
502 
529 PIX *
531  l_int32 cellw,
532  l_int32 cellh,
533  l_int32 *pncols,
534  BOXA **pboxa)
535 {
536 char buf[16];
537 l_int32 n, nw, nh, w, h, d, wt, ht, res, samedepth;
538 l_int32 index, i, j, hascmap;
539 BOX *box;
540 BOXA *boxa;
541 PIX *pix1, *pix2, *pixd;
542 PIXA *pixa1;
543 
544  PROCNAME("pixaDisplayOnLattice");
545 
546  if (pncols) *pncols = 0;
547  if (pboxa) *pboxa = NULL;
548  if (!pixa)
549  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
550 
551  /* If any pix have colormaps, or if the depths differ, generate rgb */
552  if ((n = pixaGetCount(pixa)) == 0)
553  return (PIX *)ERROR_PTR("no components", procName, NULL);
554  pixaAnyColormaps(pixa, &hascmap);
555  pixaVerifyDepth(pixa, &samedepth, NULL);
556  if (hascmap || !samedepth) {
557  pixa1 = pixaCreate(n);
558  for (i = 0; i < n; i++) {
559  pix1 = pixaGetPix(pixa, i, L_CLONE);
560  pix2 = pixConvertTo32(pix1);
561  pixaAddPix(pixa1, pix2, L_INSERT);
562  pixDestroy(&pix1);
563  }
564  } else {
565  pixa1 = pixaCopy(pixa, L_CLONE);
566  }
567  boxa = boxaCreate(n);
568 
569  /* Have number of rows and columns approximately equal */
570  nw = (l_int32)sqrt((l_float64)n);
571  nh = (n + nw - 1) / nw;
572  w = cellw * nw;
573  h = cellh * nh;
574 
575  /* Use the first pix to determine output depth and resolution */
576  pix1 = pixaGetPix(pixa1, 0, L_CLONE);
577  d = pixGetDepth(pix1);
578  res = pixGetXRes(pix1);
579  pixDestroy(&pix1);
580  if ((pixd = pixCreate(w, h, d)) == NULL) {
581  pixaDestroy(&pixa1);
582  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
583  }
585  pixSetResolution(pixd, res, res);
586 
587  /* Tile the output */
588  index = 0;
589  for (i = 0; i < nh; i++) {
590  for (j = 0; j < nw && index < n; j++, index++) {
591  pix1 = pixaGetPix(pixa1, index, L_CLONE);
592  pixGetDimensions(pix1, &wt, &ht, NULL);
593  if (wt > cellw || ht > cellh) {
594  L_INFO("pix(%d) omitted; size %dx%x\n", procName, index,
595  wt, ht);
596  box = boxCreate(0, 0, 0, 0);
597  boxaAddBox(boxa, box, L_INSERT);
598  pixDestroy(&pix1);
599  continue;
600  }
601  pixRasterop(pixd, j * cellw, i * cellh, wt, ht,
602  PIX_SRC, pix1, 0, 0);
603  box = boxCreate(j * cellw, i * cellh, wt, ht);
604  boxaAddBox(boxa, box, L_INSERT);
605  pixDestroy(&pix1);
606  }
607  }
608 
609  /* Save the number of tiles in the text field */
610  snprintf(buf, sizeof(buf), "n = %d", boxaGetCount(boxa));
611  pixSetText(pixd, buf);
612 
613  if (pncols) *pncols = nw;
614  if (pboxa)
615  *pboxa = boxa;
616  else
617  boxaDestroy(&boxa);
618  pixaDestroy(&pixa1);
619  return pixd;
620 }
621 
622 
646 PIX *
648  l_int32 nx,
649  l_int32 ny,
650  l_int32 borderwidth,
651  l_uint32 bordercolor)
652 {
653 l_int32 w, h, d, wt, ht;
654 l_int32 i, j, k, x, y, n;
655 PIX *pix1, *pixd;
656 
657  PROCNAME("pixaDisplayUnsplit");
658 
659  if (!pixa)
660  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
661  if (nx <= 0 || ny <= 0)
662  return (PIX *)ERROR_PTR("nx and ny must be > 0", procName, NULL);
663  if ((n = pixaGetCount(pixa)) == 0)
664  return (PIX *)ERROR_PTR("no components", procName, NULL);
665  if (n != nx * ny)
666  return (PIX *)ERROR_PTR("n != nx * ny", procName, NULL);
667  borderwidth = L_MAX(0, borderwidth);
668 
669  pixaGetPixDimensions(pixa, 0, &wt, &ht, &d);
670  w = nx * (wt + 2 * borderwidth);
671  h = ny * (ht + 2 * borderwidth);
672 
673  if ((pixd = pixCreate(w, h, d)) == NULL)
674  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
675  pix1 = pixaGetPix(pixa, 0, L_CLONE);
676  pixCopyColormap(pixd, pix1);
677  pixDestroy(&pix1);
678  if (borderwidth > 0)
679  pixSetAllArbitrary(pixd, bordercolor);
680 
681  y = borderwidth;
682  for (i = 0, k = 0; i < ny; i++) {
683  x = borderwidth;
684  for (j = 0; j < nx; j++, k++) {
685  pix1 = pixaGetPix(pixa, k, L_CLONE);
686  pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pix1, 0, 0);
687  pixDestroy(&pix1);
688  x += wt + 2 * borderwidth;
689  }
690  y += ht + 2 * borderwidth;
691  }
692 
693  return pixd;
694 }
695 
696 
721 PIX *
723  l_int32 maxwidth,
724  l_int32 background,
725  l_int32 spacing)
726 {
727 l_int32 wmax, hmax, wd, hd, d, hascmap, res, same;
728 l_int32 i, j, n, ni, ncols, nrows;
729 l_int32 ystart, xstart, wt, ht;
730 PIX *pix1, *pix2, *pixd;
731 PIXA *pixa1;
732 
733  PROCNAME("pixaDisplayTiled");
734 
735  if (!pixa)
736  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
737 
738  /* If any pix have colormaps, generate rgb */
739  if ((n = pixaGetCount(pixa)) == 0)
740  return (PIX *)ERROR_PTR("no components", procName, NULL);
741  pixaAnyColormaps(pixa, &hascmap);
742  if (hascmap) {
743  pixa1 = pixaCreate(n);
744  for (i = 0; i < n; i++) {
745  pix1 = pixaGetPix(pixa, i, L_CLONE);
746  pix2 = pixConvertTo32(pix1);
747  pixaAddPix(pixa1, pix2, L_INSERT);
748  pixDestroy(&pix1);
749  }
750  } else {
751  pixa1 = pixaCopy(pixa, L_CLONE);
752  }
753 
754  /* Find the max dimensions and depth subimages */
755  pixaGetDepthInfo(pixa1, &d, &same);
756  if (!same) {
757  pixaDestroy(&pixa1);
758  return (PIX *)ERROR_PTR("depths not equal", procName, NULL);
759  }
760  pixaSizeRange(pixa1, NULL, NULL, &wmax, &hmax);
761 
762  /* Get the number of rows and columns and the output image size */
763  spacing = L_MAX(spacing, 0);
764  ncols = (l_int32)((l_float32)(maxwidth - spacing) /
765  (l_float32)(wmax + spacing));
766  ncols = L_MAX(ncols, 1);
767  nrows = (n + ncols - 1) / ncols;
768  wd = wmax * ncols + spacing * (ncols + 1);
769  hd = hmax * nrows + spacing * (nrows + 1);
770  if ((pixd = pixCreate(wd, hd, d)) == NULL) {
771  pixaDestroy(&pixa1);
772  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
773  }
774 
775  /* Reset the background color if necessary */
776  if ((background == 1 && d == 1) || (background == 0 && d != 1))
777  pixSetAll(pixd);
778 
779  /* Blit the images to the dest */
780  for (i = 0, ni = 0; i < nrows; i++) {
781  ystart = spacing + i * (hmax + spacing);
782  for (j = 0; j < ncols && ni < n; j++, ni++) {
783  xstart = spacing + j * (wmax + spacing);
784  pix1 = pixaGetPix(pixa1, ni, L_CLONE);
785  if (ni == 0) res = pixGetXRes(pix1);
786  pixGetDimensions(pix1, &wt, &ht, NULL);
787  pixRasterop(pixd, xstart, ystart, wt, ht, PIX_SRC, pix1, 0, 0);
788  pixDestroy(&pix1);
789  }
790  }
791  pixSetResolution(pixd, res, res);
792 
793  pixaDestroy(&pixa1);
794  return pixd;
795 }
796 
797 
835 PIX *
837  l_int32 outdepth,
838  l_int32 maxwidth,
839  l_float32 scalefactor,
840  l_int32 background,
841  l_int32 spacing,
842  l_int32 border)
843 {
844 l_int32 h; /* cumulative height over all the rows */
845 l_int32 w; /* cumulative height in the current row */
846 l_int32 bordval, wtry, wt, ht;
847 l_int32 irow; /* index of current pix in current row */
848 l_int32 wmaxrow; /* width of the largest row */
849 l_int32 maxh; /* max height in row */
850 l_int32 i, j, index, n, x, y, nrows, ninrow, res;
851 size_t size;
852 l_uint8 *data;
853 BOXA *boxa;
854 NUMA *nainrow; /* number of pix in the row */
855 NUMA *namaxh; /* height of max pix in the row */
856 PIX *pix, *pixn, *pix1, *pixd;
857 PIXA *pixan;
858 
859  PROCNAME("pixaDisplayTiledInRows");
860 
861  if (!pixa)
862  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
863  if (outdepth != 1 && outdepth != 8 && outdepth != 32)
864  return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL);
865  if (border < 0)
866  border = 0;
867  if (scalefactor <= 0.0) scalefactor = 1.0;
868 
869  if ((n = pixaGetCount(pixa)) == 0)
870  return (PIX *)ERROR_PTR("no components", procName, NULL);
871 
872  /* Normalize depths, scale, remove colormaps; optionally add border */
873  pixan = pixaCreate(n);
874  bordval = (outdepth == 1) ? 1 : 0;
875  for (i = 0; i < n; i++) {
876  if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
877  continue;
878 
879  if (outdepth == 1)
880  pixn = pixConvertTo1(pix, 128);
881  else if (outdepth == 8)
882  pixn = pixConvertTo8(pix, FALSE);
883  else /* outdepth == 32 */
884  pixn = pixConvertTo32(pix);
885  pixDestroy(&pix);
886 
887  if (scalefactor != 1.0)
888  pix1 = pixScale(pixn, scalefactor, scalefactor);
889  else
890  pix1 = pixClone(pixn);
891  if (border)
892  pixd = pixAddBorder(pix1, border, bordval);
893  else
894  pixd = pixClone(pix1);
895  pixDestroy(&pixn);
896  pixDestroy(&pix1);
897 
898  pixaAddPix(pixan, pixd, L_INSERT);
899  }
900  if (pixaGetCount(pixan) != n) {
901  n = pixaGetCount(pixan);
902  L_WARNING("only got %d components\n", procName, n);
903  if (n == 0) {
904  pixaDestroy(&pixan);
905  return (PIX *)ERROR_PTR("no components", procName, NULL);
906  }
907  }
908 
909  /* Compute parameters for layout */
910  nainrow = numaCreate(0);
911  namaxh = numaCreate(0);
912  wmaxrow = 0;
913  w = h = spacing;
914  maxh = 0; /* max height in row */
915  for (i = 0, irow = 0; i < n; i++, irow++) {
916  pixaGetPixDimensions(pixan, i, &wt, &ht, NULL);
917  wtry = w + wt + spacing;
918  if (wtry > maxwidth) { /* end the current row and start next one */
919  numaAddNumber(nainrow, irow);
920  numaAddNumber(namaxh, maxh);
921  wmaxrow = L_MAX(wmaxrow, w);
922  h += maxh + spacing;
923  irow = 0;
924  w = wt + 2 * spacing;
925  maxh = ht;
926  } else {
927  w = wtry;
928  maxh = L_MAX(maxh, ht);
929  }
930  }
931 
932  /* Enter the parameters for the last row */
933  numaAddNumber(nainrow, irow);
934  numaAddNumber(namaxh, maxh);
935  wmaxrow = L_MAX(wmaxrow, w);
936  h += maxh + spacing;
937 
938  if ((pixd = pixCreate(wmaxrow, h, outdepth)) == NULL) {
939  numaDestroy(&nainrow);
940  numaDestroy(&namaxh);
941  pixaDestroy(&pixan);
942  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
943  }
944 
945  /* Reset the background color if necessary */
946  if ((background == 1 && outdepth == 1) ||
947  (background == 0 && outdepth != 1))
948  pixSetAll(pixd);
949 
950  /* Blit the images to the dest, and save the boxa identifying
951  * the image regions that do not include the borders. */
952  nrows = numaGetCount(nainrow);
953  y = spacing;
954  boxa = boxaCreate(n);
955  for (i = 0, index = 0; i < nrows; i++) { /* over rows */
956  numaGetIValue(nainrow, i, &ninrow);
957  numaGetIValue(namaxh, i, &maxh);
958  x = spacing;
959  for (j = 0; j < ninrow; j++, index++) { /* over pix in row */
960  pix = pixaGetPix(pixan, index, L_CLONE);
961  if (index == 0) {
962  res = pixGetXRes(pix);
963  pixSetResolution(pixd, res, res);
964  }
965  pixGetDimensions(pix, &wt, &ht, NULL);
966  boxaAddBox(boxa, boxCreate(x + border, y + border,
967  wt - 2 * border, ht - 2 *border), L_INSERT);
968  pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pix, 0, 0);
969  pixDestroy(&pix);
970  x += wt + spacing;
971  }
972  y += maxh + spacing;
973  }
974  boxaWriteMem(&data, &size, boxa);
975  pixSetText(pixd, (char *)data); /* data is ascii */
976  LEPT_FREE(data);
977  boxaDestroy(&boxa);
978 
979  numaDestroy(&nainrow);
980  numaDestroy(&namaxh);
981  pixaDestroy(&pixan);
982  return pixd;
983 }
984 
985 
1019 PIX *
1021  l_int32 nx,
1022  l_float32 scalefactor,
1023  l_int32 spacing,
1024  l_int32 border)
1025 {
1026 l_int32 i, j, index, n, x, y, nrows, wb, hb, w, h, maxd, maxh, bordval, res;
1027 size_t size;
1028 l_uint8 *data;
1029 BOX *box;
1030 BOXA *boxa;
1031 PIX *pix1, *pix2, *pix3, *pixd;
1032 PIXA *pixa1, *pixa2;
1033 
1034  PROCNAME("pixaDisplayTiledInColumns");
1035 
1036  if (!pixas)
1037  return (PIX *)ERROR_PTR("pixas not defined", procName, NULL);
1038  if (border < 0)
1039  border = 0;
1040  if (scalefactor <= 0.0) scalefactor = 1.0;
1041 
1042  if ((n = pixaGetCount(pixas)) == 0)
1043  return (PIX *)ERROR_PTR("no components", procName, NULL);
1044 
1045  /* Convert to same depth, if necessary */
1046  pixa1 = pixaConvertToSameDepth(pixas);
1047  pixaGetDepthInfo(pixa1, &maxd, NULL);
1048 
1049  /* Scale and optionally add border */
1050  pixa2 = pixaCreate(n);
1051  bordval = (maxd == 1) ? 1 : 0;
1052  for (i = 0; i < n; i++) {
1053  if ((pix1 = pixaGetPix(pixa1, i, L_CLONE)) == NULL)
1054  continue;
1055  if (scalefactor != 1.0)
1056  pix2 = pixScale(pix1, scalefactor, scalefactor);
1057  else
1058  pix2 = pixClone(pix1);
1059  if (border)
1060  pix3 = pixAddBorder(pix2, border, bordval);
1061  else
1062  pix3 = pixClone(pix2);
1063  if (i == 0) res = pixGetXRes(pix3);
1064  pixaAddPix(pixa2, pix3, L_INSERT);
1065  pixDestroy(&pix1);
1066  pixDestroy(&pix2);
1067  }
1068  pixaDestroy(&pixa1);
1069  if (pixaGetCount(pixa2) != n) {
1070  n = pixaGetCount(pixa2);
1071  L_WARNING("only got %d components\n", procName, n);
1072  if (n == 0) {
1073  pixaDestroy(&pixa2);
1074  return (PIX *)ERROR_PTR("no components", procName, NULL);
1075  }
1076  }
1077 
1078  /* Compute layout parameters and save as a boxa */
1079  boxa = boxaCreate(n);
1080  nrows = (n + nx - 1) / nx;
1081  y = spacing;
1082  for (i = 0, index = 0; i < nrows; i++) {
1083  x = spacing;
1084  maxh = 0;
1085  for (j = 0; j < nx && index < n; j++) {
1086  pixaGetPixDimensions(pixa2, index, &wb, &hb, NULL);
1087  box = boxCreate(x, y, wb, hb);
1088  boxaAddBox(boxa, box, L_INSERT);
1089  maxh = L_MAX(maxh, hb + spacing);
1090  x += wb + spacing;
1091  index++;
1092  }
1093  y += maxh;
1094  }
1095  pixaSetBoxa(pixa2, boxa, L_INSERT);
1096 
1097  /* Render the output pix */
1098  boxaGetExtent(boxa, &w, &h, NULL);
1099  pixd = pixaDisplay(pixa2, w + spacing, h + spacing);
1100  pixSetResolution(pixd, res, res);
1101 
1102  /* Save the boxa in the text field of the output pix */
1103  boxaWriteMem(&data, &size, boxa);
1104  pixSetText(pixd, (char *)data); /* data is ascii */
1105  LEPT_FREE(data);
1106 
1107  pixaDestroy(&pixa2);
1108  return pixd;
1109 }
1110 
1111 
1136 PIX *
1138  l_int32 outdepth,
1139  l_int32 tilewidth,
1140  l_int32 ncols,
1141  l_int32 background,
1142  l_int32 spacing,
1143  l_int32 border)
1144 {
1145 l_int32 x, y, w, h, wd, hd, d, res;
1146 l_int32 i, n, nrows, maxht, ninrow, irow, bordval;
1147 l_int32 *rowht;
1148 l_float32 scalefact;
1149 PIX *pix, *pixn, *pix1, *pixb, *pixd;
1150 PIXA *pixan;
1151 
1152  PROCNAME("pixaDisplayTiledAndScaled");
1153 
1154  if (!pixa)
1155  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
1156  if (outdepth != 1 && outdepth != 8 && outdepth != 32)
1157  return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL);
1158  if (ncols <= 0)
1159  return (PIX *)ERROR_PTR("ncols must be > 0", procName, NULL);
1160  if (border < 0 || border > tilewidth / 5)
1161  border = 0;
1162 
1163  if ((n = pixaGetCount(pixa)) == 0)
1164  return (PIX *)ERROR_PTR("no components", procName, NULL);
1165 
1166  /* Normalize scale and depth for each pix; optionally add border */
1167  pixan = pixaCreate(n);
1168  bordval = (outdepth == 1) ? 1 : 0;
1169  for (i = 0; i < n; i++) {
1170  if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
1171  continue;
1172 
1173  pixGetDimensions(pix, &w, &h, &d);
1174  scalefact = (l_float32)(tilewidth - 2 * border) / (l_float32)w;
1175  if (d == 1 && outdepth > 1 && scalefact < 1.0)
1176  pix1 = pixScaleToGray(pix, scalefact);
1177  else
1178  pix1 = pixScale(pix, scalefact, scalefact);
1179 
1180  if (outdepth == 1)
1181  pixn = pixConvertTo1(pix1, 128);
1182  else if (outdepth == 8)
1183  pixn = pixConvertTo8(pix1, FALSE);
1184  else /* outdepth == 32 */
1185  pixn = pixConvertTo32(pix1);
1186  pixDestroy(&pix1);
1187 
1188  if (border)
1189  pixb = pixAddBorder(pixn, border, bordval);
1190  else
1191  pixb = pixClone(pixn);
1192 
1193  pixaAddPix(pixan, pixb, L_INSERT);
1194  pixDestroy(&pix);
1195  pixDestroy(&pixn);
1196  }
1197  if ((n = pixaGetCount(pixan)) == 0) { /* should not have changed! */
1198  pixaDestroy(&pixan);
1199  return (PIX *)ERROR_PTR("no components", procName, NULL);
1200  }
1201 
1202  /* Determine the size of each row and of pixd */
1203  wd = tilewidth * ncols + spacing * (ncols + 1);
1204  nrows = (n + ncols - 1) / ncols;
1205  if ((rowht = (l_int32 *)LEPT_CALLOC(nrows, sizeof(l_int32))) == NULL) {
1206  pixaDestroy(&pixan);
1207  return (PIX *)ERROR_PTR("rowht array not made", procName, NULL);
1208  }
1209  maxht = 0;
1210  ninrow = 0;
1211  irow = 0;
1212  for (i = 0; i < n; i++) {
1213  pix = pixaGetPix(pixan, i, L_CLONE);
1214  ninrow++;
1215  pixGetDimensions(pix, &w, &h, NULL);
1216  maxht = L_MAX(h, maxht);
1217  if (ninrow == ncols) {
1218  rowht[irow] = maxht;
1219  maxht = ninrow = 0; /* reset */
1220  irow++;
1221  }
1222  pixDestroy(&pix);
1223  }
1224  if (ninrow > 0) { /* last fencepost */
1225  rowht[irow] = maxht;
1226  irow++; /* total number of rows */
1227  }
1228  nrows = irow;
1229  hd = spacing * (nrows + 1);
1230  for (i = 0; i < nrows; i++)
1231  hd += rowht[i];
1232 
1233  pixd = pixCreate(wd, hd, outdepth);
1234  if ((background == 1 && outdepth == 1) ||
1235  (background == 0 && outdepth != 1))
1236  pixSetAll(pixd);
1237 
1238  /* Now blit images to pixd */
1239  x = y = spacing;
1240  irow = 0;
1241  for (i = 0; i < n; i++) {
1242  pix = pixaGetPix(pixan, i, L_CLONE);
1243  if (i == 0) {
1244  res = pixGetXRes(pix);
1245  pixSetResolution(pixd, res, res);
1246  }
1247  pixGetDimensions(pix, &w, &h, NULL);
1248  if (i && ((i % ncols) == 0)) { /* start new row */
1249  x = spacing;
1250  y += spacing + rowht[irow];
1251  irow++;
1252  }
1253  pixRasterop(pixd, x, y, w, h, PIX_SRC, pix, 0, 0);
1254  x += tilewidth + spacing;
1255  pixDestroy(&pix);
1256  }
1257 
1258  pixaDestroy(&pixan);
1259  LEPT_FREE(rowht);
1260  return pixd;
1261 }
1262 
1263 
1291 PIX *
1293  l_int32 maxwidth,
1294  l_float32 scalefactor,
1295  l_int32 spacing,
1296  l_int32 border,
1297  l_int32 fontsize,
1298  l_uint32 textcolor)
1299 {
1300 char buf[128];
1301 char *textstr;
1302 l_int32 i, n, maxw;
1303 L_BMF *bmf;
1304 PIX *pix1, *pix2, *pix3, *pix4, *pixd;
1305 PIXA *pixad;
1306 
1307  PROCNAME("pixaDisplayTiledWithText");
1308 
1309  if (!pixa)
1310  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
1311  if ((n = pixaGetCount(pixa)) == 0)
1312  return (PIX *)ERROR_PTR("no components", procName, NULL);
1313  if (maxwidth <= 0)
1314  return (PIX *)ERROR_PTR("invalid maxwidth", procName, NULL);
1315  if (border < 0)
1316  border = 0;
1317  if (scalefactor <= 0.0) {
1318  L_WARNING("invalid scalefactor; setting to 1.0\n", procName);
1319  scalefactor = 1.0;
1320  }
1321  if (fontsize < 4 || fontsize > 20 || (fontsize & 1)) {
1322  l_int32 fsize = L_MAX(L_MIN(fontsize, 20), 4);
1323  if (fsize & 1) fsize--;
1324  L_WARNING("changed fontsize from %d to %d\n", procName,
1325  fontsize, fsize);
1326  fontsize = fsize;
1327  }
1328 
1329  /* Be sure the width can accommodate a single column of images */
1330  pixaSizeRange(pixa, NULL, NULL, &maxw, NULL);
1331  maxwidth = L_MAX(maxwidth, scalefactor * (maxw + 2 * spacing + 2 * border));
1332 
1333  bmf = bmfCreate(NULL, fontsize);
1334  pixad = pixaCreate(n);
1335  for (i = 0; i < n; i++) {
1336  pix1 = pixaGetPix(pixa, i, L_CLONE);
1337  pix2 = pixConvertTo32(pix1);
1338  pix3 = pixAddBorderGeneral(pix2, spacing, spacing, spacing,
1339  spacing, 0xffffff00);
1340  textstr = pixGetText(pix1);
1341  if (textstr && strlen(textstr) > 0) {
1342  snprintf(buf, sizeof(buf), "%s", textstr);
1343  pix4 = pixAddSingleTextblock(pix3, bmf, buf, textcolor,
1344  L_ADD_BELOW, NULL);
1345  } else {
1346  pix4 = pixClone(pix3);
1347  }
1348  pixaAddPix(pixad, pix4, L_INSERT);
1349  pixDestroy(&pix1);
1350  pixDestroy(&pix2);
1351  pixDestroy(&pix3);
1352  }
1353  bmfDestroy(&bmf);
1354 
1355  pixd = pixaDisplayTiledInRows(pixad, 32, maxwidth, scalefactor,
1356  0, 10, border);
1357  pixaDestroy(&pixad);
1358  return pixd;
1359 }
1360 
1361 
1390 PIX *
1392  NUMA *na,
1393  l_int32 width,
1394  l_int32 spacing,
1395  l_int32 border,
1396  l_int32 fontsize,
1397  l_uint32 textcolor)
1398 {
1399 char buf[128];
1400 char *textstr;
1401 l_int32 i, n, x, y, w, h, yval, index;
1402 l_float32 maxindex;
1403 L_BMF *bmf;
1404 BOX *box;
1405 NUMA *nay; /* top of the next pix to add in that column */
1406 PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pixd;
1407 PIXA *pixad;
1408 
1409  PROCNAME("pixaDisplayTiledByIndex");
1410 
1411  if (!pixa)
1412  return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
1413  if (!na)
1414  return (PIX *)ERROR_PTR("na not defined", procName, NULL);
1415  if ((n = pixaGetCount(pixa)) == 0)
1416  return (PIX *)ERROR_PTR("no pixa components", procName, NULL);
1417  if (n != numaGetCount(na))
1418  return (PIX *)ERROR_PTR("pixa and na counts differ", procName, NULL);
1419  if (width <= 0)
1420  return (PIX *)ERROR_PTR("invalid width", procName, NULL);
1421  if (width < 20)
1422  L_WARNING("very small width: %d\n", procName, width);
1423  if (border < 0)
1424  border = 0;
1425  if (fontsize < 4 || fontsize > 20 || (fontsize & 1)) {
1426  l_int32 fsize = L_MAX(L_MIN(fontsize, 20), 4);
1427  if (fsize & 1) fsize--;
1428  L_WARNING("changed fontsize from %d to %d\n", procName,
1429  fontsize, fsize);
1430  fontsize = fsize;
1431  }
1432 
1433  /* The pix will be rendered in the order they occupy in pixa. */
1434  bmf = bmfCreate(NULL, fontsize);
1435  pixad = pixaCreate(n);
1436  numaGetMax(na, &maxindex, NULL);
1437  nay = numaMakeConstant(spacing, lept_roundftoi(maxindex) + 1);
1438  for (i = 0; i < n; i++) {
1439  numaGetIValue(na, i, &index);
1440  numaGetIValue(nay, index, &yval);
1441  pix1 = pixaGetPix(pixa, i, L_CLONE);
1442  pix2 = pixConvertTo32(pix1);
1443  pix3 = pixScaleToSize(pix2, width, 0);
1444  pix4 = pixAddBorderGeneral(pix3, border, border, border, border, 0);
1445  textstr = pixGetText(pix1);
1446  if (textstr && strlen(textstr) > 0) {
1447  snprintf(buf, sizeof(buf), "%s", textstr);
1448  pix5 = pixAddTextlines(pix4, bmf, textstr, textcolor, L_ADD_BELOW);
1449  } else {
1450  pix5 = pixClone(pix4);
1451  }
1452  pixaAddPix(pixad, pix5, L_INSERT);
1453  x = spacing + border + index * (2 * border + width + spacing);
1454  y = yval;
1455  pixGetDimensions(pix5, &w, &h, NULL);
1456  yval += h + spacing;
1457  numaSetValue(nay, index, yval);
1458  box = boxCreate(x, y, w, h);
1459  pixaAddBox(pixad, box, L_INSERT);
1460  pixDestroy(&pix1);
1461  pixDestroy(&pix2);
1462  pixDestroy(&pix3);
1463  pixDestroy(&pix4);
1464  }
1465  numaDestroy(&nay);
1466  bmfDestroy(&bmf);
1467 
1468  pixd = pixaDisplay(pixad, 0, 0);
1469  pixaDestroy(&pixad);
1470  return pixd;
1471 }
1472 
1473 
1474 
1475 /*---------------------------------------------------------------------*
1476  * Pixaa Display *
1477  *---------------------------------------------------------------------*/
1493 PIX *
1495  l_int32 w,
1496  l_int32 h)
1497 {
1498 l_int32 i, j, n, nbox, na, d, wmax, hmax, x, y, xb, yb, wb, hb;
1499 BOXA *boxa1; /* top-level boxa */
1500 BOXA *boxa;
1501 PIX *pix1, *pixd;
1502 PIXA *pixa;
1503 
1504  PROCNAME("pixaaDisplay");
1505 
1506  if (!paa)
1507  return (PIX *)ERROR_PTR("paa not defined", procName, NULL);
1508 
1509  n = pixaaGetCount(paa, NULL);
1510  if (n == 0)
1511  return (PIX *)ERROR_PTR("no components", procName, NULL);
1512 
1513  /* If w and h not input, determine the minimum size required
1514  * to contain the origin and all c.c. */
1515  boxa1 = pixaaGetBoxa(paa, L_CLONE);
1516  nbox = boxaGetCount(boxa1);
1517  if (w == 0 || h == 0) {
1518  if (nbox == n) {
1519  boxaGetExtent(boxa1, &w, &h, NULL);
1520  } else { /* have to use the lower-level boxa for each pixa */
1521  wmax = hmax = 0;
1522  for (i = 0; i < n; i++) {
1523  pixa = pixaaGetPixa(paa, i, L_CLONE);
1524  boxa = pixaGetBoxa(pixa, L_CLONE);
1525  boxaGetExtent(boxa, &w, &h, NULL);
1526  wmax = L_MAX(wmax, w);
1527  hmax = L_MAX(hmax, h);
1528  pixaDestroy(&pixa);
1529  boxaDestroy(&boxa);
1530  }
1531  w = wmax;
1532  h = hmax;
1533  }
1534  }
1535 
1536  /* Get depth from first pix */
1537  pixa = pixaaGetPixa(paa, 0, L_CLONE);
1538  pix1 = pixaGetPix(pixa, 0, L_CLONE);
1539  d = pixGetDepth(pix1);
1540  pixaDestroy(&pixa);
1541  pixDestroy(&pix1);
1542 
1543  if ((pixd = pixCreate(w, h, d)) == NULL) {
1544  boxaDestroy(&boxa1);
1545  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1546  }
1547 
1548  x = y = 0;
1549  for (i = 0; i < n; i++) {
1550  pixa = pixaaGetPixa(paa, i, L_CLONE);
1551  if (nbox == n)
1552  boxaGetBoxGeometry(boxa1, i, &x, &y, NULL, NULL);
1553  na = pixaGetCount(pixa);
1554  for (j = 0; j < na; j++) {
1555  pixaGetBoxGeometry(pixa, j, &xb, &yb, &wb, &hb);
1556  pix1 = pixaGetPix(pixa, j, L_CLONE);
1557  pixRasterop(pixd, x + xb, y + yb, wb, hb, PIX_PAINT, pix1, 0, 0);
1558  pixDestroy(&pix1);
1559  }
1560  pixaDestroy(&pixa);
1561  }
1562  boxaDestroy(&boxa1);
1563 
1564  return pixd;
1565 }
1566 
1567 
1587 PIX *
1589  l_int32 xspace,
1590  l_int32 yspace,
1591  l_int32 maxw)
1592 {
1593 l_int32 i, j, npixa, npix, same, use_maxw, x, y, w, h, hindex;
1594 l_int32 maxwidth, maxd, width, lmaxh, lmaxw;
1595 l_int32 *harray;
1596 NUMA *nah;
1597 PIX *pix, *pix1, *pixd;
1598 PIXA *pixa;
1599 
1600  PROCNAME("pixaaDisplayByPixa");
1601 
1602  if (!paa)
1603  return (PIX *)ERROR_PTR("paa not defined", procName, NULL);
1604 
1605  if ((npixa = pixaaGetCount(paa, NULL)) == 0)
1606  return (PIX *)ERROR_PTR("no components", procName, NULL);
1607  pixaaVerifyDepth(paa, &same, &maxd);
1608  if (!same && maxd < 8)
1609  return (PIX *)ERROR_PTR("depths differ; max < 8", procName, NULL);
1610 
1611  /* Be sure the widest box fits in the output pix */
1612  pixaaSizeRange(paa, NULL, NULL, &maxwidth, NULL);
1613  if (maxwidth > maxw) {
1614  L_WARNING("maxwidth > maxw; using maxwidth\n", procName);
1615  maxw = maxwidth;
1616  }
1617 
1618  /* Get size of output pix. The width is the minimum of the
1619  * maxw and the largest pixa line width. The height is whatever
1620  * it needs to be to accommodate all pixa. */
1621  lmaxw = 0; /* widest line found */
1622  use_maxw = FALSE;
1623  nah = numaCreate(0); /* store height of each line */
1624  y = yspace;
1625  for (i = 0; i < npixa; i++) {
1626  pixa = pixaaGetPixa(paa, i, L_CLONE);
1627  npix = pixaGetCount(pixa);
1628  if (npix == 0) {
1629  pixaDestroy(&pixa);
1630  continue;
1631  }
1632  x = xspace;
1633  lmaxh = 0; /* max height found in the line */
1634  for (j = 0; j < npix; j++) {
1635  pix = pixaGetPix(pixa, j, L_CLONE);
1636  pixGetDimensions(pix, &w, &h, NULL);
1637  if (x + w >= maxw) { /* start new line */
1638  x = xspace;
1639  y += lmaxh + yspace;
1640  numaAddNumber(nah, lmaxh);
1641  lmaxh = 0;
1642  use_maxw = TRUE;
1643  }
1644  x += w + xspace;
1645  lmaxh = L_MAX(h, lmaxh);
1646  lmaxw = L_MAX(lmaxw, x);
1647  pixDestroy(&pix);
1648  }
1649  y += lmaxh + yspace;
1650  numaAddNumber(nah, lmaxh);
1651  pixaDestroy(&pixa);
1652  }
1653  width = (use_maxw) ? maxw : lmaxw;
1654 
1655  if ((pixd = pixCreate(width, y, maxd)) == NULL) {
1656  numaDestroy(&nah);
1657  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1658  }
1659 
1660  /* Now layout the pix by pixa */
1661  y = yspace;
1662  harray = numaGetIArray(nah);
1663  hindex = 0;
1664  for (i = 0; i < npixa; i++) {
1665  x = xspace;
1666  pixa = pixaaGetPixa(paa, i, L_CLONE);
1667  npix = pixaGetCount(pixa);
1668  if (npix == 0) {
1669  pixaDestroy(&pixa);
1670  continue;
1671  }
1672  for (j = 0; j < npix; j++) {
1673  pix = pixaGetPix(pixa, j, L_CLONE);
1674  if (pixGetDepth(pix) != maxd) {
1675  if (maxd == 8)
1676  pix1 = pixConvertTo8(pix, 0);
1677  else /* 32 bpp */
1678  pix1 = pixConvertTo32(pix);
1679  } else {
1680  pix1 = pixClone(pix);
1681  }
1682  pixGetDimensions(pix1, &w, &h, NULL);
1683  if (x + w >= maxw) { /* start new line */
1684  x = xspace;
1685  y += harray[hindex++] + yspace;
1686  }
1687  pixRasterop(pixd, x, y, w, h, PIX_PAINT, pix1, 0, 0);
1688  pixDestroy(&pix);
1689  pixDestroy(&pix1);
1690  x += w + xspace;
1691  }
1692  y += harray[hindex++] + yspace;
1693  pixaDestroy(&pixa);
1694  }
1695  LEPT_FREE(harray);
1696 
1697  numaDestroy(&nah);
1698  return pixd;
1699 }
1700 
1701 
1724 PIXA *
1726  l_int32 outdepth,
1727  l_int32 tilewidth,
1728  l_int32 ncols,
1729  l_int32 background,
1730  l_int32 spacing,
1731  l_int32 border)
1732 {
1733 l_int32 i, n;
1734 PIX *pix;
1735 PIXA *pixa, *pixad;
1736 
1737  PROCNAME("pixaaDisplayTiledAndScaled");
1738 
1739  if (!paa)
1740  return (PIXA *)ERROR_PTR("paa not defined", procName, NULL);
1741  if (outdepth != 1 && outdepth != 8 && outdepth != 32)
1742  return (PIXA *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL);
1743  if (ncols <= 0)
1744  return (PIXA *)ERROR_PTR("ncols must be > 0", procName, NULL);
1745  if (border < 0 || border > tilewidth / 5)
1746  border = 0;
1747 
1748  if ((n = pixaaGetCount(paa, NULL)) == 0)
1749  return (PIXA *)ERROR_PTR("no components", procName, NULL);
1750 
1751  pixad = pixaCreate(n);
1752  for (i = 0; i < n; i++) {
1753  pixa = pixaaGetPixa(paa, i, L_CLONE);
1754  pix = pixaDisplayTiledAndScaled(pixa, outdepth, tilewidth, ncols,
1755  background, spacing, border);
1756  pixaAddPix(pixad, pix, L_INSERT);
1757  pixaDestroy(&pixa);
1758  }
1759 
1760  return pixad;
1761 }
1762 
1763 
1764 /*---------------------------------------------------------------------*
1765  * Conversion of all pix to specified type (e.g., depth) *
1766  *---------------------------------------------------------------------*/
1774 PIXA *
1776  l_int32 thresh)
1777 {
1778 l_int32 i, n;
1779 BOXA *boxa;
1780 PIX *pix1, *pix2;
1781 PIXA *pixad;
1782 
1783  PROCNAME("pixaConvertTo1");
1784 
1785  if (!pixas)
1786  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1787 
1788  n = pixaGetCount(pixas);
1789  pixad = pixaCreate(n);
1790  for (i = 0; i < n; i++) {
1791  pix1 = pixaGetPix(pixas, i, L_CLONE);
1792  pix2 = pixConvertTo1(pix1, thresh);
1793  pixaAddPix(pixad, pix2, L_INSERT);
1794  pixDestroy(&pix1);
1795  }
1796 
1797  boxa = pixaGetBoxa(pixas, L_COPY);
1798  pixaSetBoxa(pixad, boxa, L_INSERT);
1799  return pixad;
1800 }
1801 
1802 
1815 PIXA *
1817  l_int32 cmapflag)
1818 {
1819 l_int32 i, n;
1820 BOXA *boxa;
1821 PIX *pix1, *pix2;
1822 PIXA *pixad;
1823 
1824  PROCNAME("pixaConvertTo8");
1825 
1826  if (!pixas)
1827  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1828 
1829  n = pixaGetCount(pixas);
1830  pixad = pixaCreate(n);
1831  for (i = 0; i < n; i++) {
1832  pix1 = pixaGetPix(pixas, i, L_CLONE);
1833  pix2 = pixConvertTo8(pix1, cmapflag);
1834  pixaAddPix(pixad, pix2, L_INSERT);
1835  pixDestroy(&pix1);
1836  }
1837 
1838  boxa = pixaGetBoxa(pixas, L_COPY);
1839  pixaSetBoxa(pixad, boxa, L_INSERT);
1840  return pixad;
1841 }
1842 
1843 
1856 PIXA *
1858  l_int32 dither)
1859 {
1860 l_int32 i, n;
1861 BOXA *boxa;
1862 PIX *pix1, *pix2;
1863 PIXA *pixad;
1864 
1865  PROCNAME("pixaConvertTo8Colormap");
1866 
1867  if (!pixas)
1868  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1869 
1870  n = pixaGetCount(pixas);
1871  pixad = pixaCreate(n);
1872  for (i = 0; i < n; i++) {
1873  pix1 = pixaGetPix(pixas, i, L_CLONE);
1874  pix2 = pixConvertTo8Colormap(pix1, dither);
1875  pixaAddPix(pixad, pix2, L_INSERT);
1876  pixDestroy(&pix1);
1877  }
1878 
1879  boxa = pixaGetBoxa(pixas, L_COPY);
1880  pixaSetBoxa(pixad, boxa, L_INSERT);
1881  return pixad;
1882 }
1883 
1884 
1898 PIXA *
1900 {
1901 l_int32 i, n;
1902 BOXA *boxa;
1903 PIX *pix1, *pix2;
1904 PIXA *pixad;
1905 
1906  PROCNAME("pixaConvertTo32");
1907 
1908  if (!pixas)
1909  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1910 
1911  n = pixaGetCount(pixas);
1912  pixad = pixaCreate(n);
1913  for (i = 0; i < n; i++) {
1914  pix1 = pixaGetPix(pixas, i, L_CLONE);
1915  pix2 = pixConvertTo32(pix1);
1916  pixaAddPix(pixad, pix2, L_INSERT);
1917  pixDestroy(&pix1);
1918  }
1919 
1920  boxa = pixaGetBoxa(pixas, L_COPY);
1921  pixaSetBoxa(pixad, boxa, L_INSERT);
1922  return pixad;
1923 }
1924 
1925 
1926 /*---------------------------------------------------------------------*
1927  * Pixa constrained selection *
1928  *---------------------------------------------------------------------*/
1951 PIXA *
1953  l_int32 first,
1954  l_int32 last,
1955  l_int32 nmax,
1956  l_int32 use_pairs,
1957  l_int32 copyflag)
1958 {
1959 l_int32 i, n, nselect, index;
1960 NUMA *na;
1961 PIX *pix1;
1962 PIXA *pixad;
1963 
1964  PROCNAME("pixaConstrainedSelect");
1965 
1966  if (!pixas)
1967  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
1968  n = pixaGetCount(pixas);
1969  first = L_MAX(0, first);
1970  last = (last < 0) ? n - 1 : L_MIN(n - 1, last);
1971  if (last < first)
1972  return (PIXA *)ERROR_PTR("last < first!", procName, NULL);
1973  if (nmax < 1)
1974  return (PIXA *)ERROR_PTR("nmax < 1!", procName, NULL);
1975 
1976  na = genConstrainedNumaInRange(first, last, nmax, use_pairs);
1977  nselect = numaGetCount(na);
1978  pixad = pixaCreate(nselect);
1979  for (i = 0; i < nselect; i++) {
1980  numaGetIValue(na, i, &index);
1981  pix1 = pixaGetPix(pixas, index, copyflag);
1982  pixaAddPix(pixad, pix1, L_INSERT);
1983  }
1984  numaDestroy(&na);
1985  return pixad;
1986 }
1987 
1988 
2019 l_ok
2021  l_int32 first,
2022  l_int32 last,
2023  l_int32 res,
2024  l_float32 scalefactor,
2025  l_int32 type,
2026  l_int32 quality,
2027  l_uint32 color,
2028  l_int32 fontsize,
2029  const char *fileout)
2030 {
2031 l_int32 n;
2032 L_BMF *bmf;
2033 NUMA *na;
2034 PIXA *pixa1, *pixa2;
2035 
2036  PROCNAME("pixaSelectToPdf");
2037 
2038  if (!pixas)
2039  return ERROR_INT("pixas not defined", procName, 1);
2040  if (type < 0 || type > L_FLATE_ENCODE) {
2041  L_WARNING("invalid compression type; using default\n", procName);
2042  type = 0;
2043  }
2044  if (!fileout)
2045  return ERROR_INT("fileout not defined", procName, 1);
2046 
2047  /* Select from given range */
2048  n = pixaGetCount(pixas);
2049  first = L_MAX(0, first);
2050  last = (last < 0) ? n - 1 : L_MIN(n - 1, last);
2051  if (first > last) {
2052  L_ERROR("first = %d > last = %d\n", procName, first, last);
2053  return 1;
2054  }
2055  pixa1 = pixaSelectRange(pixas, first, last, L_CLONE);
2056 
2057  /* Optionally add index numbers */
2058  bmf = (fontsize <= 0) ? NULL : bmfCreate(NULL, fontsize);
2059  if (bmf) {
2060  na = numaMakeSequence(first, 1.0, last - first + 1);
2061  pixa2 = pixaAddTextNumber(pixa1, bmf, na, color, L_ADD_LEFT);
2062  numaDestroy(&na);
2063  } else {
2064  pixa2 = pixaCopy(pixa1, L_CLONE);
2065  }
2066  pixaDestroy(&pixa1);
2067  bmfDestroy(&bmf);
2068 
2069  pixaConvertToPdf(pixa2, res, scalefactor, type, quality, NULL, fileout);
2070  pixaDestroy(&pixa2);
2071  return 0;
2072 }
2073 
2074 
2075 /*---------------------------------------------------------------------*
2076  * Generate pixa from tiled images *
2077  *---------------------------------------------------------------------*/
2098 PIXA *
2100  l_int32 w,
2101  l_int32 h,
2102  l_int32 nsamp)
2103 {
2104 char buf[8];
2105 l_int32 ntiles, i;
2106 PIX *pix1;
2107 PIXA *pixad, *pixa1;
2108 
2109  PROCNAME("pixaMakeFromTiledPixa");
2110 
2111  if (!pixas)
2112  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
2113  if (nsamp > 1000)
2114  return (PIXA *)ERROR_PTR("nsamp too large; typ. 100", procName, NULL);
2115 
2116  if (w <= 0) w = 20;
2117  if (h <= 0) h = 30;
2118  if (nsamp <= 0) nsamp = 100;
2119 
2120  /* pixas has 10 pix of mosaic'd digits. Each of these images
2121  * must be extracted into a pixa of templates, where each template
2122  * is labeled with the digit value, and then selectively
2123  * concatenated into an output pixa. */
2124  pixad = pixaCreate(10 * nsamp);
2125  for (i = 0; i < 10; i++) {
2126  pix1 = pixaGetPix(pixas, i, L_CLONE);
2127  pixGetTileCount(pix1, &ntiles);
2128  if (nsamp > ntiles)
2129  L_WARNING("requested %d; only %d tiles\n", procName, nsamp, ntiles);
2130  pixa1 = pixaMakeFromTiledPix(pix1, w, h, 0, nsamp, NULL);
2131  snprintf(buf, sizeof(buf), "%d", i);
2132  pixaSetText(pixa1, buf, NULL);
2133  pixaJoin(pixad, pixa1, 0, -1);
2134  pixaDestroy(&pixa1);
2135  pixDestroy(&pix1);
2136  }
2137  return pixad;
2138 }
2139 
2140 
2178 PIXA *
2180  l_int32 w,
2181  l_int32 h,
2182  l_int32 start,
2183  l_int32 num,
2184  BOXA *boxa)
2185 {
2186 char *text;
2187 l_int32 i, j, k, ws, hs, d, nx, ny, n, n_isvalid, ntiles, nmax;
2188 PIX *pix1;
2189 PIXA *pixa1;
2190 PIXCMAP *cmap;
2191 
2192  PROCNAME("pixaMakeFromTiledPix");
2193 
2194  if (!pixs)
2195  return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
2196  if (!boxa && (w <= 0 || h <= 0))
2197  return (PIXA *)ERROR_PTR("w and h must be > 0", procName, NULL);
2198 
2199  if (boxa) /* general case */
2200  return pixaCreateFromBoxa(pixs, boxa, start, num, NULL);
2201 
2202  /* All tiles are the same size */
2203  pixGetDimensions(pixs, &ws, &hs, &d);
2204  nx = ws / w;
2205  ny = hs / h;
2206  if (nx < 1 || ny < 1)
2207  return (PIXA *)ERROR_PTR("invalid dimensions", procName, NULL);
2208  if (nx * w != ws || ny * h != hs)
2209  L_WARNING("some tiles will be clipped\n", procName);
2210 
2211  /* Check the text field of the pix. It may tell how many
2212  * tiles hold valid data. If a valid value is not found,
2213  * assume all (nx * ny) tiles are valid. */
2214  pixGetTileCount(pixs, &n);
2215  n_isvalid = (n <= nx * ny && n > nx * (ny - 1)) ? TRUE : FALSE;
2216  ntiles = (n_isvalid) ? n : nx * ny;
2217  nmax = ntiles - start; /* max available from start */
2218  num = (num == 0) ? nmax : L_MIN(num, nmax);
2219 
2220  /* Extract the tiles */
2221  if ((pixa1 = pixaCreate(num)) == NULL) {
2222  return (PIXA *)ERROR_PTR("pixa1 not made", procName, NULL);
2223  }
2224  cmap = pixGetColormap(pixs);
2225  for (i = 0, k = 0; i < ny; i++) {
2226  for (j = 0; j < nx; j++, k++) {
2227  if (k < start) continue;
2228  if (k >= start + num) break;
2229  pix1 = pixCreate(w, h, d);
2230  if (cmap) pixSetColormap(pix1, pixcmapCopy(cmap));
2231  pixRasterop(pix1, 0, 0, w, h, PIX_SRC, pixs, j * w, i * h);
2232  pixaAddPix(pixa1, pix1, L_INSERT);
2233  }
2234  }
2235  return pixa1;
2236 }
2237 
2238 
2254 l_ok
2256  l_int32 *pn)
2257 {
2258 char *text;
2259 l_int32 n;
2260 
2261  PROCNAME("pixGetTileCount");
2262 
2263  if (!pn)
2264  return ERROR_INT("&n not defined", procName, 1);
2265  *pn = 0;
2266  if (!pix)
2267  return ERROR_INT("pix not defined", procName, 1);
2268 
2269  text = pixGetText(pix);
2270  if (text && strlen(text) > 4) {
2271  if (sscanf(text, "n = %d", &n) == 1)
2272  *pn = n;
2273  }
2274  return 0;
2275 }
2276 
2277 
2278 /*---------------------------------------------------------------------*
2279  * Pixa display into multiple tiles *
2280  *---------------------------------------------------------------------*/
2302 PIXA *
2304  l_int32 nx,
2305  l_int32 ny,
2306  l_int32 maxw,
2307  l_int32 maxh,
2308  l_float32 scalefactor,
2309  l_int32 spacing,
2310  l_int32 border)
2311 {
2312 l_int32 n, i, j, ntile, nout, index;
2313 PIX *pix1, *pix2;
2314 PIXA *pixa1, *pixa2, *pixad;
2315 
2316  PROCNAME("pixaDisplayMultiTiled");
2317 
2318  if (!pixas)
2319  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
2320  if (nx < 1 || ny < 1 || nx > 50 || ny > 50)
2321  return (PIXA *)ERROR_PTR("invalid tiling factor(s)", procName, NULL);
2322  if ((n = pixaGetCount(pixas)) == 0)
2323  return (PIXA *)ERROR_PTR("pixas is empty", procName, NULL);
2324 
2325  /* Filter out large ones if requested */
2326  if (maxw == 0 && maxh == 0) {
2327  pixa1 = pixaCopy(pixas, L_CLONE);
2328  } else {
2329  maxw = (maxw == 0) ? 1000000 : maxw;
2330  maxh = (maxh == 0) ? 1000000 : maxh;
2331  pixa1 = pixaSelectBySize(pixas, maxw, maxh, L_SELECT_IF_BOTH,
2332  L_SELECT_IF_LTE, NULL);
2333  n = pixaGetCount(pixa1);
2334  }
2335 
2336  ntile = nx * ny;
2337  nout = L_MAX(1, (n + ntile - 1) / ntile);
2338  pixad = pixaCreate(nout);
2339  for (i = 0, index = 0; i < nout; i++) { /* over tiles */
2340  pixa2 = pixaCreate(ntile);
2341  for (j = 0; j < ntile && index < n; j++, index++) {
2342  pix1 = pixaGetPix(pixa1, index, L_COPY);
2343  pixaAddPix(pixa2, pix1, L_INSERT);
2344  }
2345  pix2 = pixaDisplayTiledInColumns(pixa2, nx, scalefactor, spacing,
2346  border);
2347  pixaAddPix(pixad, pix2, L_INSERT);
2348  pixaDestroy(&pixa2);
2349  }
2350  pixaDestroy(&pixa1);
2351 
2352  return pixad;
2353 }
2354 
2355 
2356 /*---------------------------------------------------------------------*
2357  * Split pixa into files *
2358  *---------------------------------------------------------------------*/
2381 l_ok
2383  l_int32 nsplit,
2384  l_float32 scale,
2385  l_int32 outwidth,
2386  l_int32 write_pixa,
2387  l_int32 write_pix,
2388  l_int32 write_pdf)
2389 {
2390 char buf[64];
2391 l_int32 i, j, index, n, nt;
2392 PIX *pix1, *pix2;
2393 PIXA *pixa1;
2394 
2395  PROCNAME("pixaSplitIntoFiles");
2396 
2397  if (!pixas)
2398  return ERROR_INT("pixas not defined", procName, 1);
2399  if (nsplit <= 1)
2400  return ERROR_INT("nsplit must be >= 2", procName, 1);
2401  if ((nt = pixaGetCount(pixas)) == 0)
2402  return ERROR_INT("pixas is empty", procName, 1);
2403  if (!write_pixa && !write_pix && !write_pdf)
2404  return ERROR_INT("no output is requested", procName, 1);
2405 
2406  lept_mkdir("lept/split");
2407  n = (nt + nsplit - 1) / nsplit;
2408  fprintf(stderr, "nt = %d, n = %d, nsplit = %d\n", nt, n, nsplit);
2409  for (i = 0, index = 0; i < nsplit; i++) {
2410  pixa1 = pixaCreate(n);
2411  for (j = 0; j < n && index < nt; j++, index++) {
2412  pix1 = pixaGetPix(pixas, index, L_CLONE);
2413  pix2 = pixScale(pix1, scale, scale);
2414  pixaAddPix(pixa1, pix2, L_INSERT);
2415  pixDestroy(&pix1);
2416  }
2417  if (write_pixa) {
2418  snprintf(buf, sizeof(buf), "/tmp/lept/split/split%d.pa", i + 1);
2419  pixaWriteDebug(buf, pixa1);
2420  }
2421  if (write_pix) {
2422  snprintf(buf, sizeof(buf), "/tmp/lept/split/split%d.tif", i + 1);
2423  pix1 = pixaDisplayTiledInRows(pixa1, 1, outwidth, 1.0, 0, 20, 2);
2424  pixWriteDebug(buf, pix1, IFF_TIFF_G4);
2425  pixDestroy(&pix1);
2426  }
2427  if (write_pdf) {
2428  snprintf(buf, sizeof(buf), "/tmp/lept/split/split%d.pdf", i + 1);
2429  pixaConvertToPdf(pixa1, 0, 1.0, L_G4_ENCODE, 0, buf, buf);
2430  }
2431  pixaDestroy(&pixa1);
2432  }
2433 
2434  return 0;
2435 }
2436 
2437 
2438 /*---------------------------------------------------------------------*
2439  * Tile N-Up *
2440  *---------------------------------------------------------------------*/
2470 l_ok
2471 convertToNUpFiles(const char *dir,
2472  const char *substr,
2473  l_int32 nx,
2474  l_int32 ny,
2475  l_int32 tw,
2476  l_int32 spacing,
2477  l_int32 border,
2478  l_int32 fontsize,
2479  const char *outdir)
2480 {
2481 l_int32 d, format;
2482 char rootpath[256];
2483 PIXA *pixa;
2484 
2485  PROCNAME("convertToNUpFiles");
2486 
2487  if (!dir)
2488  return ERROR_INT("dir not defined", procName, 1);
2489  if (nx < 1 || ny < 1 || nx > 50 || ny > 50)
2490  return ERROR_INT("invalid tiling N-factor", procName, 1);
2491  if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2492  return ERROR_INT("invalid fontsize", procName, 1);
2493  if (!outdir)
2494  return ERROR_INT("outdir not defined", procName, 1);
2495 
2496  pixa = convertToNUpPixa(dir, substr, nx, ny, tw, spacing, border,
2497  fontsize);
2498  if (!pixa)
2499  return ERROR_INT("pixa not made", procName, 1);
2500 
2501  lept_rmdir(outdir);
2502  lept_mkdir(outdir);
2503  pixaGetRenderingDepth(pixa, &d);
2504  format = (d == 1) ? IFF_TIFF_G4 : IFF_JFIF_JPEG;
2505  makeTempDirname(rootpath, 256, outdir);
2506  modifyTrailingSlash(rootpath, 256, L_ADD_TRAIL_SLASH);
2507  pixaWriteFiles(rootpath, pixa, format);
2508  pixaDestroy(&pixa);
2509  return 0;
2510 }
2511 
2512 
2532 PIXA *
2533 convertToNUpPixa(const char *dir,
2534  const char *substr,
2535  l_int32 nx,
2536  l_int32 ny,
2537  l_int32 tw,
2538  l_int32 spacing,
2539  l_int32 border,
2540  l_int32 fontsize)
2541 {
2542 l_int32 i, n;
2543 char *fname, *tail;
2544 PIXA *pixa1, *pixa2;
2545 SARRAY *sa1, *sa2;
2546 
2547  PROCNAME("convertToNUpPixa");
2548 
2549  if (!dir)
2550  return (PIXA *)ERROR_PTR("dir not defined", procName, NULL);
2551  if (nx < 1 || ny < 1 || nx > 50 || ny > 50)
2552  return (PIXA *)ERROR_PTR("invalid tiling N-factor", procName, NULL);
2553  if (tw < 20)
2554  return (PIXA *)ERROR_PTR("tw must be >= 20", procName, NULL);
2555  if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2556  return (PIXA *)ERROR_PTR("invalid fontsize", procName, NULL);
2557 
2558  sa1 = getSortedPathnamesInDirectory(dir, substr, 0, 0);
2559  pixa1 = pixaReadFilesSA(sa1);
2560  n = sarrayGetCount(sa1);
2561  sa2 = sarrayCreate(n);
2562  for (i = 0; i < n; i++) {
2563  fname = sarrayGetString(sa1, i, L_NOCOPY);
2564  splitPathAtDirectory(fname, NULL, &tail);
2565  sarrayAddString(sa2, tail, L_INSERT);
2566  }
2567  sarrayDestroy(&sa1);
2568  pixa2 = pixaConvertToNUpPixa(pixa1, sa2, nx, ny, tw, spacing,
2569  border, fontsize);
2570  pixaDestroy(&pixa1);
2571  sarrayDestroy(&sa2);
2572  return pixa2;
2573 }
2574 
2575 
2598 PIXA *
2600  SARRAY *sa,
2601  l_int32 nx,
2602  l_int32 ny,
2603  l_int32 tw,
2604  l_int32 spacing,
2605  l_int32 border,
2606  l_int32 fontsize)
2607 {
2608 l_int32 i, j, k, nt, n2, nout, d;
2609 char *str;
2610 L_BMF *bmf;
2611 PIX *pix1, *pix2, *pix3, *pix4;
2612 PIXA *pixa1, *pixad;
2613 
2614  PROCNAME("pixaConvertToNUpPixa");
2615 
2616  if (!pixas)
2617  return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL);
2618  if (nx < 1 || ny < 1 || nx > 50 || ny > 50)
2619  return (PIXA *)ERROR_PTR("invalid tiling N-factor", procName, NULL);
2620  if (tw < 20)
2621  return (PIXA *)ERROR_PTR("tw must be >= 20", procName, NULL);
2622  if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2623  return (PIXA *)ERROR_PTR("invalid fontsize", procName, NULL);
2624 
2625  nt = pixaGetCount(pixas);
2626  if (sa && (sarrayGetCount(sa) != nt)) {
2627  L_WARNING("pixa size %d not equal to sarray size %d\n", procName,
2628  nt, sarrayGetCount(sa));
2629  }
2630 
2631  n2 = nx * ny;
2632  nout = (nt + n2 - 1) / n2;
2633  pixad = pixaCreate(nout);
2634  bmf = (fontsize == 0) ? NULL : bmfCreate(NULL, fontsize);
2635  for (i = 0, j = 0; i < nout; i++) {
2636  pixa1 = pixaCreate(n2);
2637  for (k = 0; k < n2 && j < nt; j++, k++) {
2638  pix1 = pixaGetPix(pixas, j, L_CLONE);
2639  pix2 = pixScaleToSize(pix1, tw, 0); /* all images have width tw */
2640  if (bmf && sa) {
2641  str = sarrayGetString(sa, j, L_NOCOPY);
2642  pix3 = pixAddTextlines(pix2, bmf, str, 0xff000000,
2643  L_ADD_BELOW);
2644  } else {
2645  pix3 = pixClone(pix2);
2646  }
2647  pixaAddPix(pixa1, pix3, L_INSERT);
2648  pixDestroy(&pix1);
2649  pixDestroy(&pix2);
2650  }
2651  if (pixaGetCount(pixa1) == 0) { /* probably won't happen */
2652  pixaDestroy(&pixa1);
2653  continue;
2654  }
2655 
2656  /* Add 2 * border to image width to prevent scaling */
2657  pixaGetRenderingDepth(pixa1, &d);
2658  pix4 = pixaDisplayTiledAndScaled(pixa1, d, tw + 2 * border, nx, 0,
2659  spacing, border);
2660  pixaAddPix(pixad, pix4, L_INSERT);
2661  pixaDestroy(&pixa1);
2662  }
2663 
2664  bmfDestroy(&bmf);
2665  return pixad;
2666 }
2667 
2668 
2669 /*---------------------------------------------------------------------*
2670  * Render two pixa side-by-side for comparison *
2671  *---------------------------------------------------------------------*/
2711 l_ok
2713  PIXA *pixa2,
2714  l_int32 nx,
2715  l_int32 ny,
2716  l_int32 tw,
2717  l_int32 spacing,
2718  l_int32 border,
2719  l_int32 fontsize,
2720  const char *fileout)
2721 {
2722 l_int32 n1, n2, npairs;
2723 PIXA *pixa3, *pixa4, *pixa5;
2724 SARRAY *sa;
2725 
2726  PROCNAME("pixaCompareInPdf");
2727 
2728  if (!pixa1 || !pixa2)
2729  return ERROR_INT("pixa1 and pixa2 not both defined", procName, 1);
2730  if (nx < 1 || ny < 1 || nx > 20 || ny > 20)
2731  return ERROR_INT("invalid tiling factors", procName, 1);
2732  if (tw < 20)
2733  return ERROR_INT("invalid tw; tw must be >= 20", procName, 1);
2734  if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2735  return ERROR_INT("invalid fontsize", procName, 1);
2736  if (!fileout)
2737  return ERROR_INT("fileout not defined", procName, 1);
2738  n1 = pixaGetCount(pixa1);
2739  n2 = pixaGetCount(pixa2);
2740  if (n1 == 0 || n2 == 0)
2741  return ERROR_INT("at least one pixa is empty", procName, 1);
2742  if (n1 != n2)
2743  L_WARNING("sizes (%d, %d) differ; using the minimum in interleave\n",
2744  procName, n1, n2);
2745 
2746  /* Interleave the input pixa */
2747  if ((pixa3 = pixaInterleave(pixa1, pixa2, L_CLONE)) == NULL)
2748  return ERROR_INT("pixa3 not made", procName, 1);
2749 
2750  /* Scale the images if necessary and pair them up side/by/side */
2751  pixa4 = pixaConvertToNUpPixa(pixa3, NULL, 2, 1, tw, spacing, border, 0);
2752  pixaDestroy(&pixa3);
2753 
2754  /* Label the pairs and mosaic into pages without further scaling */
2755  npairs = pixaGetCount(pixa4);
2756  sa = (fontsize > 0) ? sarrayGenerateIntegers(npairs) : NULL;
2757  pixa5 = pixaConvertToNUpPixa(pixa4, sa, nx, ny,
2758  2 * tw + 4 * border + spacing,
2759  spacing, border, fontsize);
2760  pixaDestroy(&pixa4);
2761  sarrayDestroy(&sa);
2762 
2763  /* Output as pdf without scaling */
2764  pixaConvertToPdf(pixa5, 0, 1.0, 0, 0, NULL, fileout);
2765  pixaDestroy(&pixa5);
2766  return 0;
2767 }
2768 
2769 
PIX * pixaaDisplay(PIXAA *paa, l_int32 w, l_int32 h)
pixaaDisplay()
Definition: pixafunc2.c:1494
PIXA * pixaInterleave(PIXA *pixa1, PIXA *pixa2, l_int32 copyflag)
pixaInterleave()
Definition: pixabasic.c:1702
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:166
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
Definition: pixconv.c:2933
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:1944
Definition: pix.h:717
PIX * pixScaleToGray(PIX *pixs, l_float32 scalefactor)
pixScaleToGray()
Definition: scale2.c:204
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3233
l_int32 lept_roundftoi(l_float32 fval)
lept_roundftoi()
Definition: utils1.c:547
l_ok pixaSetText(PIXA *pixa, const char *text, SARRAY *sa)
pixaSetText()
Definition: pixabasic.c:1134
l_ok pixaaSizeRange(PIXAA *paa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
pixaaSizeRange()
Definition: pixafunc1.c:2396
SARRAY * sarrayGenerateIntegers(l_int32 n)
sarrayGenerateIntegers()
Definition: sarray2.c:648
l_ok pixaWriteDebug(const char *fname, PIXA *pixa)
pixaWriteDebug()
Definition: pixabasic.c:2705
l_ok pixaVerifyDepth(PIXA *pixa, l_int32 *psame, l_int32 *pmaxd)
pixaVerifyDepth()
Definition: pixabasic.c:941
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
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:1725
Definition: pix.h:716
l_ok pixaSetBoxa(PIXA *pixa, BOXA *boxa, l_int32 accesstype)
pixaSetBoxa()
Definition: pixabasic.c:877
l_ok pixaJoin(PIXA *pixad, PIXA *pixas, l_int32 istart, l_int32 iend)
pixaJoin()
Definition: pixabasic.c:1646
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:193
PIXA * pixaaGetPixa(PIXAA *paa, l_int32 index, l_int32 accesstype)
pixaaGetPixa()
Definition: pixabasic.c:2168
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:433
PIX * pixaDisplayUnsplit(PIXA *pixa, l_int32 nx, l_int32 ny, l_int32 borderwidth, l_uint32 bordercolor)
pixaDisplayUnsplit()
Definition: pixafunc2.c:647
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:2303
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
l_int32 pixaaGetCount(PIXAA *paa, NUMA **pna)
pixaaGetCount()
Definition: pixabasic.c:2119
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:781
PIX * pixaDisplayOnLattice(PIXA *pixa, l_int32 cellw, l_int32 cellh, l_int32 *pncols, BOXA **pboxa)
pixaDisplayOnLattice()
Definition: pixafunc2.c:530
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:163
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:741
PIXA * pixaConvertToSameDepth(PIXA *pixas)
pixaConvertToSameDepth()
Definition: pixafunc1.c:2781
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_ok pixaGetDepthInfo(PIXA *pixa, l_int32 *pmaxdepth, l_int32 *psame)
pixaGetDepthInfo()
Definition: pixafunc1.c:2732
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:580
PIXA * pixaCreateFromBoxa(PIX *pixs, BOXA *boxa, l_int32 start, l_int32 num, l_int32 *pcropwarn)
pixaCreateFromBoxa()
Definition: pixabasic.c:268
PIX * pixaDisplay(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplay()
Definition: pixafunc2.c:184
Definition: pix.h:492
PIX * pixaDisplayTiledInColumns(PIXA *pixas, l_int32 nx, l_float32 scalefactor, l_int32 spacing, l_int32 border)
pixaDisplayTiledInColumns()
Definition: pixafunc2.c:1020
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:759
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1573
l_ok modifyTrailingSlash(char *path, size_t nbytes, l_int32 flag)
modifyTrailingSlash()
Definition: utils2.c:3036
Definition: bmf.h:45
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:2020
Definition: array.h:116
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:2382
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1748
PIXA * pixaConvertTo8(PIXA *pixas, l_int32 cmapflag)
pixaConvertTo8()
Definition: pixafunc2.c:1816
l_ok pixSetText(PIX *pix, const char *textstring)
pixSetText()
Definition: pix1.c:1483
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:876
PIXA * pixaCopy(PIXA *pixa, l_int32 copyflag)
pixaCopy()
Definition: pixabasic.c:450
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:820
PIXA * pixaConstrainedSelect(PIXA *pixas, l_int32 first, l_int32 last, l_int32 nmax, l_int32 use_pairs, l_int32 copyflag)
pixaConstrainedSelect()
Definition: pixafunc2.c:1952
NUMA * genConstrainedNumaInRange(l_int32 first, l_int32 last, l_int32 nmax, l_int32 use_pairs)
genConstrainedNumaInRange()
Definition: numafunc2.c:3097
PIX * pixaDisplayRandomCmap(PIXA *pixa, l_int32 w, l_int32 h)
pixaDisplayRandomCmap()
Definition: pixafunc2.c:359
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
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:1391
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:446
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:863
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:836
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:618
PIXA * pixaSelectBySize(PIXA *pixas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged)
pixaSelectBySize()
Definition: pixafunc1.c:299
PIX * pixConvertTo8Colormap(PIX *pixs, l_int32 dither)
pixConvertTo8Colormap()
Definition: pixconv.c:3149
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:946
l_ok pixGetTileCount(PIX *pix, l_int32 *pn)
pixGetTileCount()
Definition: pixafunc2.c:2255
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:681
#define PIX_PAINT
Definition: pix.h:333
PIX * pixaDisplayOnColor(PIXA *pixa, l_int32 w, l_int32 h, l_uint32 bgcolor)
pixaDisplayOnColor()
Definition: pixafunc2.c:264
l_ok pixaGetBoxGeometry(PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
pixaGetBoxGeometry()
Definition: pixabasic.c:835
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
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:1137
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:317
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:750
l_ok pixCopyColormap(PIX *pixd, PIX *pixs)
pixCopyColormap()
Definition: pix1.c:745
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:2712
SARRAY * getSortedPathnamesInDirectory(const char *dirname, const char *substr, l_int32 first, l_int32 nfiles)
getSortedPathnamesInDirectory()
Definition: sarray1.c:1717
l_ok boxaWriteMem(l_uint8 **pdata, size_t *psize, BOXA *boxa)
boxaWriteMem()
Definition: boxbasic.c:2283
Definition: pix.h:454
PIX * pixaaDisplayByPixa(PIXAA *paa, l_int32 xspace, l_int32 yspace, l_int32 maxw)
pixaaDisplayByPixa()
Definition: pixafunc2.c:1588
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:943
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2540
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:2471
PIXA * pixaReadFilesSA(SARRAY *sa)
pixaReadFilesSA()
Definition: readfile.c:151
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
Definition: pix.h:465
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
PIXA * pixaMakeFromTiledPixa(PIXA *pixas, l_int32 w, l_int32 h, l_int32 nsamp)
pixaMakeFromTiledPixa()
Definition: pixafunc2.c:2099
l_ok pixaSizeRange(PIXA *pixa, l_int32 *pminw, l_int32 *pminh, l_int32 *pmaxw, l_int32 *pmaxh)
pixaSizeRange()
Definition: pixafunc1.c:2450
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:621
char * pixGetText(PIX *pix)
pixGetText()
Definition: pix1.c:1459
l_ok pixaGetRenderingDepth(PIXA *pixa, l_int32 *pdepth)
pixaGetRenderingDepth()
Definition: pixafunc1.c:2615
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:752
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:672
Definition: pix.h:718
Definition: pix.h:134
PIXA * pixaMakeFromTiledPix(PIX *pixs, l_int32 w, l_int32 h, l_int32 start, l_int32 num, BOXA *boxa)
pixaMakeFromTiledPix()
Definition: pixafunc2.c:2179
Definition: pix.h:719
l_ok makeTempDirname(char *result, size_t nbytes, const char *subdir)
makeTempDirname()
Definition: utils2.c:2986
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:2533
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:707
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:499
#define PIX_SRC
Definition: pix.h:327
PIXA * pixaConvertTo32(PIXA *pixas)
pixaConvertTo32()
Definition: pixafunc2.c:1899
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2366
l_ok pixaaVerifyDepth(PIXAA *paa, l_int32 *psame, l_int32 *pmaxd)
pixaaVerifyDepth()
Definition: pixabasic.c:2263
PIXA * pixaConvertTo8Colormap(PIXA *pixas, l_int32 dither)
pixaConvertTo8Colormap()
Definition: pixafunc2.c:1857
PIX * pixAddTextlines(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location)
pixAddTextlines()
Definition: textops.c:270
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:718
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:2599
BOXA * pixaaGetBoxa(PIXAA *paa, l_int32 accesstype)
pixaaGetBoxa()
Definition: pixabasic.c:2206
l_ok pixSetResolution(PIX *pix, l_int32 xres, l_int32 yres)
pixSetResolution()
Definition: pix1.c:1339
PIXCMAP * pixcmapCopy(PIXCMAP *cmaps)
pixcmapCopy()
Definition: colormap.c:234
PIXA * pixaConvertTo1(PIXA *pixas, l_int32 thresh)
pixaConvertTo1()
Definition: pixafunc2.c:1775
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:486
PIXA * pixaSelectRange(PIXA *pixas, l_int32 first, l_int32 last, l_int32 copyflag)
pixaSelectRange()
Definition: pixafunc1.c:1668
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2021
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:1292
l_ok pixaAddBox(PIXA *pixa, BOX *box, l_int32 copyflag)
pixaAddBox()
Definition: pixabasic.c:547
Definition: pix.h:480
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:244
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:115
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:631
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1842
PIXA * pixaAddTextNumber(PIXA *pixas, L_BMF *bmf, NUMA *na, l_uint32 val, l_int32 location)
pixaAddTextNumber()
Definition: textops.c:641
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:355
PIX * pixaDisplayTiled(PIXA *pixa, l_int32 maxwidth, l_int32 background, l_int32 spacing)
pixaDisplayTiled()
Definition: pixafunc2.c:722
l_ok pixaAnyColormaps(PIXA *pixa, l_int32 *phascmap)
pixaAnyColormaps()
Definition: pixafunc1.c:2693
PIXCMAP * pixcmapCreateRandom(l_int32 depth, l_int32 hasblack, l_int32 haswhite)
pixcmapCreateRandom()
Definition: colormap.c:158
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:114
BOXA * pixaGetBoxa(PIXA *pixa, l_int32 accesstype)
pixaGetBoxa()
Definition: pixabasic.c:741