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 
27 /*!
28  * \file  pixabasic.c
29  * <pre>
30  *
31  *      Pixa creation, destruction, copying
32  *           PIXA     *pixaCreate()
33  *           PIXA     *pixaCreateFromPix()
34  *           PIXA     *pixaCreateFromBoxa()
35  *           PIXA     *pixaSplitPix()
36  *           void      pixaDestroy()
37  *           PIXA     *pixaCopy()
38  *
39  *      Pixa addition
40  *           l_int32   pixaAddPix()
41  *           l_int32   pixaAddBox()
42  *           static l_int32   pixaExtendArray()
43  *           l_int32   pixaExtendArrayToSize()
44  *
45  *      Pixa accessors
46  *           l_int32   pixaGetCount()
47  *           l_int32   pixaChangeRefcount()
48  *           PIX      *pixaGetPix()
49  *           l_int32   pixaGetPixDimensions()
50  *           BOXA     *pixaGetBoxa()
51  *           l_int32   pixaGetBoxaCount()
52  *           BOX      *pixaGetBox()
53  *           l_int32   pixaGetBoxGeometry()
54  *           l_int32   pixaSetBoxa()
55  *           PIX     **pixaGetPixArray()
56  *           l_int32   pixaVerifyDepth()
57  *           l_int32   pixaVerifyDimensions()
58  *           l_int32   pixaIsFull()
59  *           l_int32   pixaCountText()
60  *           l_int32   pixaSetText()
61  *           void   ***pixaGetLinePtrs()
62  *
63  *      Pixa output info
64  *           l_int32   pixaWriteStreamInfo()
65  *
66  *      Pixa array modifiers
67  *           l_int32   pixaReplacePix()
68  *           l_int32   pixaInsertPix()
69  *           l_int32   pixaRemovePix()
70  *           l_int32   pixaRemovePixAndSave()
71  *           l_int32   pixaInitFull()
72  *           l_int32   pixaClear()
73  *
74  *      Pixa and Pixaa combination
75  *           l_int32   pixaJoin()
76  *           PIXA     *pixaInterleave()
77  *           l_int32   pixaaJoin()
78  *
79  *      Pixaa creation, destruction
80  *           PIXAA    *pixaaCreate()
81  *           PIXAA    *pixaaCreateFromPixa()
82  *           void      pixaaDestroy()
83  *
84  *      Pixaa addition
85  *           l_int32   pixaaAddPixa()
86  *           l_int32   pixaaExtendArray()
87  *           l_int32   pixaaAddPix()
88  *           l_int32   pixaaAddBox()
89  *
90  *      Pixaa accessors
91  *           l_int32   pixaaGetCount()
92  *           PIXA     *pixaaGetPixa()
93  *           BOXA     *pixaaGetBoxa()
94  *           PIX      *pixaaGetPix()
95  *           l_int32   pixaaVerifyDepth()
96  *           l_int32   pixaaVerifyDimensions()
97  *           l_int32   pixaaIsFull()
98  *
99  *      Pixaa array modifiers
100  *           l_int32   pixaaInitFull()
101  *           l_int32   pixaaReplacePixa()
102  *           l_int32   pixaaClear()
103  *           l_int32   pixaaTruncate()
104  *
105  *      Pixa serialized I/O  (requires png support)
106  *           PIXA     *pixaRead()
107  *           PIXA     *pixaReadStream()
108  *           PIXA     *pixaReadMem()
109  *           l_int32   pixaWriteDebug()
110  *           l_int32   pixaWrite()
111  *           l_int32   pixaWriteStream()
112  *           l_int32   pixaWriteMem()
113  *           PIXA     *pixaReadBoth()
114  *
115  *      Pixaa serialized I/O  (requires png support)
116  *           PIXAA    *pixaaReadFromFiles()
117  *           PIXAA    *pixaaRead()
118  *           PIXAA    *pixaaReadStream()
119  *           PIXAA    *pixaaReadMem()
120  *           l_int32   pixaaWrite()
121  *           l_int32   pixaaWriteStream()
122  *           l_int32   pixaaWriteMem()
123  *
124  *
125  *   Important note on reference counting:
126  *     Reference counting for the Pixa is analogous to that for the Boxa.
127  *     See pix.h for details.   pixaCopy() provides three possible modes
128  *     of copy.  The basic rule is that however a Pixa is obtained
129  *     (e.g., from pixaCreate*(), pixaCopy(), or a Pixaa accessor),
130  *     it is necessary to call pixaDestroy() on it.
131  * </pre>
132  */
133 
134 #ifdef HAVE_CONFIG_H
135 #include "config_auto.h"
136 #endif  /* HAVE_CONFIG_H */
137 
138 #include <string.h>
139 #include "allheaders.h"
140 
141 static const l_int32  INITIAL_PTR_ARRAYSIZE = 20;   /* n'import quoi */
142 
143     /* Static functions */
144 static l_int32 pixaExtendArray(PIXA  *pixa);
145 
146 
147 /*---------------------------------------------------------------------*
148  *                    Pixa creation, destruction, copy                 *
149  *---------------------------------------------------------------------*/
150 /*!
151  * \brief   pixaCreate()
152  *
153  * \param[in]    n  initial number of ptrs
154  * \return  pixa, or NULL on error
155  *
156  * <pre>
157  * Notes:
158  *      (1) This creates an empty boxa.
159  * </pre>
160  */
161 PIXA *
pixaCreate(l_int32 n)162 pixaCreate(l_int32  n)
163 {
164 PIXA  *pixa;
165 
166     PROCNAME("pixaCreate");
167 
168     if (n <= 0)
169         n = INITIAL_PTR_ARRAYSIZE;
170 
171     pixa = (PIXA *)LEPT_CALLOC(1, sizeof(PIXA));
172     pixa->n = 0;
173     pixa->nalloc = n;
174     pixa->refcount = 1;
175     pixa->pix = (PIX **)LEPT_CALLOC(n, sizeof(PIX *));
176     pixa->boxa = boxaCreate(n);
177     if (!pixa->pix || !pixa->boxa) {
178         pixaDestroy(&pixa);
179         return (PIXA *)ERROR_PTR("pix or boxa not made", procName, NULL);
180     }
181     return pixa;
182 }
183 
184 
185 /*!
186  * \brief   pixaCreateFromPix()
187  *
188  * \param[in]    pixs  with individual components on a lattice
189  * \param[in]    n   number of components
190  * \param[in]    cellw   width of each cell
191  * \param[in]    cellh   height of each cell
192  * \return  pixa, or NULL on error
193  *
194  * <pre>
195  * Notes:
196  *      (1) For bpp = 1, we truncate each retrieved pix to the ON
197  *          pixels, which we assume for now start at (0,0)
198  * </pre>
199  */
200 PIXA *
pixaCreateFromPix(PIX * pixs,l_int32 n,l_int32 cellw,l_int32 cellh)201 pixaCreateFromPix(PIX     *pixs,
202                   l_int32  n,
203                   l_int32  cellw,
204                   l_int32  cellh)
205 {
206 l_int32  w, h, d, nw, nh, i, j, index;
207 PIX     *pix1, *pix2;
208 PIXA    *pixa;
209 
210     PROCNAME("pixaCreateFromPix");
211 
212     if (!pixs)
213         return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
214     if (n <= 0)
215         return (PIXA *)ERROR_PTR("n must be > 0", procName, NULL);
216 
217     if ((pixa = pixaCreate(n)) == NULL)
218         return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
219     pixGetDimensions(pixs, &w, &h, &d);
220     if ((pix1 = pixCreate(cellw, cellh, d)) == NULL) {
221         pixaDestroy(&pixa);
222         return (PIXA *)ERROR_PTR("pix1 not made", procName, NULL);
223     }
224 
225     nw = (w + cellw - 1) / cellw;
226     nh = (h + cellh - 1) / cellh;
227     for (i = 0, index = 0; i < nh; i++) {
228         for (j = 0; j < nw && index < n; j++, index++) {
229             pixRasterop(pix1, 0, 0, cellw, cellh, PIX_SRC, pixs,
230                    j * cellw, i * cellh);
231             if (d == 1 && !pixClipToForeground(pix1, &pix2, NULL))
232                 pixaAddPix(pixa, pix2, L_INSERT);
233             else
234                 pixaAddPix(pixa, pix1, L_COPY);
235         }
236     }
237 
238     pixDestroy(&pix1);
239     return pixa;
240 }
241 
242 
243 /*!
244  * \brief   pixaCreateFromBoxa()
245  *
246  * \param[in]    pixs
247  * \param[in]    boxa
248  * \param[out]   pcropwarn [optional] TRUE if the boxa extent
249  *                         is larger than pixs.
250  * \return  pixad, or NULL on error
251  *
252  * <pre>
253  * Notes:
254  *      (1) This simply extracts from pixs the region corresponding to each
255  *          box in the boxa.
256  *      (2) The 3rd arg is optional.  If the extent of the boxa exceeds the
257  *          size of the pixa, so that some boxes are either clipped
258  *          or entirely outside the pix, a warning is returned as TRUE.
259  *      (3) pixad will have only the properly clipped elements, and
260  *          the internal boxa will be correct.
261  * </pre>
262  */
263 PIXA *
pixaCreateFromBoxa(PIX * pixs,BOXA * boxa,l_int32 * pcropwarn)264 pixaCreateFromBoxa(PIX      *pixs,
265                    BOXA     *boxa,
266                    l_int32  *pcropwarn)
267 {
268 l_int32  i, n, w, h, wbox, hbox, cropwarn;
269 BOX     *box, *boxc;
270 PIX     *pixd;
271 PIXA    *pixad;
272 
273     PROCNAME("pixaCreateFromBoxa");
274 
275     if (!pixs)
276         return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
277     if (!boxa)
278         return (PIXA *)ERROR_PTR("boxa not defined", procName, NULL);
279 
280     n = boxaGetCount(boxa);
281     if ((pixad = pixaCreate(n)) == NULL)
282         return (PIXA *)ERROR_PTR("pixad not made", procName, NULL);
283 
284     boxaGetExtent(boxa, &wbox, &hbox, NULL);
285     pixGetDimensions(pixs, &w, &h, NULL);
286     cropwarn = FALSE;
287     if (wbox > w || hbox > h)
288         cropwarn = TRUE;
289     if (pcropwarn)
290         *pcropwarn = cropwarn;
291 
292     for (i = 0; i < n; i++) {
293         box = boxaGetBox(boxa, i, L_COPY);
294         if (cropwarn) {  /* if box is outside pixs, pixd is NULL */
295             pixd = pixClipRectangle(pixs, box, &boxc);  /* may be NULL */
296             if (pixd) {
297                 pixaAddPix(pixad, pixd, L_INSERT);
298                 pixaAddBox(pixad, boxc, L_INSERT);
299             }
300             boxDestroy(&box);
301         } else {
302             pixd = pixClipRectangle(pixs, box, NULL);
303             pixaAddPix(pixad, pixd, L_INSERT);
304             pixaAddBox(pixad, box, L_INSERT);
305         }
306     }
307 
308     return pixad;
309 }
310 
311 
312 /*!
313  * \brief   pixaSplitPix()
314  *
315  * \param[in]    pixs  with individual components on a lattice
316  * \param[in]    nx   number of mosaic cells horizontally
317  * \param[in]    ny   number of mosaic cells vertically
318  * \param[in]    borderwidth  of added border on all sides
319  * \param[in]    bordercolor  in our RGBA format: 0xrrggbbaa
320  * \return  pixa, or NULL on error
321  *
322  * <pre>
323  * Notes:
324  *      (1) This is a variant on pixaCreateFromPix(), where we
325  *          simply divide the image up into (approximately) equal
326  *          subunits.  If you want the subimages to have essentially
327  *          the same aspect ratio as the input pix, use nx = ny.
328  *      (2) If borderwidth is 0, we ignore the input bordercolor and
329  *          redefine it to white.
330  *      (3) The bordercolor is always used to initialize each tiled pix,
331  *          so that if the src is clipped, the unblitted part will
332  *          be this color.  This avoids 1 pixel wide black stripes at the
333  *          left and lower edges.
334  * </pre>
335  */
336 PIXA *
pixaSplitPix(PIX * pixs,l_int32 nx,l_int32 ny,l_int32 borderwidth,l_uint32 bordercolor)337 pixaSplitPix(PIX      *pixs,
338              l_int32   nx,
339              l_int32   ny,
340              l_int32   borderwidth,
341              l_uint32  bordercolor)
342 {
343 l_int32  w, h, d, cellw, cellh, i, j;
344 PIX     *pix1;
345 PIXA    *pixa;
346 
347     PROCNAME("pixaSplitPix");
348 
349     if (!pixs)
350         return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
351     if (nx <= 0 || ny <= 0)
352         return (PIXA *)ERROR_PTR("nx and ny must be > 0", procName, NULL);
353     borderwidth = L_MAX(0, borderwidth);
354 
355     if ((pixa = pixaCreate(nx * ny)) == NULL)
356         return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
357     pixGetDimensions(pixs, &w, &h, &d);
358     cellw = (w + nx - 1) / nx;  /* round up */
359     cellh = (h + ny - 1) / ny;
360 
361     for (i = 0; i < ny; i++) {
362         for (j = 0; j < nx; j++) {
363             if ((pix1 = pixCreate(cellw + 2 * borderwidth,
364                                   cellh + 2 * borderwidth, d)) == NULL) {
365                 pixaDestroy(&pixa);
366                 return (PIXA *)ERROR_PTR("pix1 not made", procName, NULL);
367             }
368             pixCopyColormap(pix1, pixs);
369             if (borderwidth == 0) {  /* initialize full image to white */
370                 if (d == 1)
371                     pixClearAll(pix1);
372                 else
373                     pixSetAll(pix1);
374             } else {
375                 pixSetAllArbitrary(pix1, bordercolor);
376             }
377             pixRasterop(pix1, borderwidth, borderwidth, cellw, cellh,
378                         PIX_SRC, pixs, j * cellw, i * cellh);
379             pixaAddPix(pixa, pix1, L_INSERT);
380         }
381     }
382 
383     return pixa;
384 }
385 
386 
387 /*!
388  * \brief   pixaDestroy()
389  *
390  * \param[in,out]  ppixa can be nulled
391  *
392  * <pre>
393  * Notes:
394  *      (1) Decrements the ref count and, if 0, destroys the pixa.
395  *      (2) Always nulls the input ptr.
396  * </pre>
397  */
398 void
pixaDestroy(PIXA ** ppixa)399 pixaDestroy(PIXA  **ppixa)
400 {
401 l_int32  i;
402 PIXA    *pixa;
403 
404     PROCNAME("pixaDestroy");
405 
406     if (ppixa == NULL) {
407         L_WARNING("ptr address is NULL!\n", procName);
408         return;
409     }
410 
411     if ((pixa = *ppixa) == NULL)
412         return;
413 
414         /* Decrement the refcount.  If it is 0, destroy the pixa. */
415     pixaChangeRefcount(pixa, -1);
416     if (pixa->refcount <= 0) {
417         for (i = 0; i < pixa->n; i++)
418             pixDestroy(&pixa->pix[i]);
419         LEPT_FREE(pixa->pix);
420         boxaDestroy(&pixa->boxa);
421         LEPT_FREE(pixa);
422     }
423 
424     *ppixa = NULL;
425     return;
426 }
427 
428 
429 /*!
430  * \brief   pixaCopy()
431  *
432  * \param[in]    pixa
433  * \param[in]    copyflag see pix.h for details:
434  *                 L_COPY makes a new pixa and copies each pix and each box;
435  *                 L_CLONE gives a new ref-counted handle to the input pixa;
436  *                 L_COPY_CLONE makes a new pixa and inserts clones of
437  *                     all pix and boxes
438  * \return  new pixa, or NULL on error
439  */
440 PIXA *
pixaCopy(PIXA * pixa,l_int32 copyflag)441 pixaCopy(PIXA    *pixa,
442          l_int32  copyflag)
443 {
444 l_int32  i, nb;
445 BOX     *boxc;
446 PIX     *pixc;
447 PIXA    *pixac;
448 
449     PROCNAME("pixaCopy");
450 
451     if (!pixa)
452         return (PIXA *)ERROR_PTR("pixa not defined", procName, NULL);
453 
454     if (copyflag == L_CLONE) {
455         pixaChangeRefcount(pixa, 1);
456         return pixa;
457     }
458 
459     if (copyflag != L_COPY && copyflag != L_COPY_CLONE)
460         return (PIXA *)ERROR_PTR("invalid copyflag", procName, NULL);
461 
462     if ((pixac = pixaCreate(pixa->n)) == NULL)
463         return (PIXA *)ERROR_PTR("pixac not made", procName, NULL);
464     nb = pixaGetBoxaCount(pixa);
465     for (i = 0; i < pixa->n; i++) {
466         if (copyflag == L_COPY) {
467             pixc = pixaGetPix(pixa, i, L_COPY);
468             if (i < nb) boxc = pixaGetBox(pixa, i, L_COPY);
469         } else {  /* copy-clone */
470             pixc = pixaGetPix(pixa, i, L_CLONE);
471             if (i < nb) boxc = pixaGetBox(pixa, i, L_CLONE);
472         }
473         pixaAddPix(pixac, pixc, L_INSERT);
474         if (i < nb) pixaAddBox(pixac, boxc, L_INSERT);
475     }
476 
477     return pixac;
478 }
479 
480 
481 
482 /*---------------------------------------------------------------------*
483  *                              Pixa addition                          *
484  *---------------------------------------------------------------------*/
485 /*!
486  * \brief   pixaAddPix()
487  *
488  * \param[in]    pixa
489  * \param[in]    pix  to be added
490  * \param[in]    copyflag L_INSERT, L_COPY, L_CLONE
491  * \return  0 if OK; 1 on error
492  */
493 l_int32
pixaAddPix(PIXA * pixa,PIX * pix,l_int32 copyflag)494 pixaAddPix(PIXA    *pixa,
495            PIX     *pix,
496            l_int32  copyflag)
497 {
498 l_int32  n;
499 PIX     *pixc;
500 
501     PROCNAME("pixaAddPix");
502 
503     if (!pixa)
504         return ERROR_INT("pixa not defined", procName, 1);
505     if (!pix)
506         return ERROR_INT("pix not defined", procName, 1);
507 
508     if (copyflag == L_INSERT)
509         pixc = pix;
510     else if (copyflag == L_COPY)
511         pixc = pixCopy(NULL, pix);
512     else if (copyflag == L_CLONE)
513         pixc = pixClone(pix);
514     else
515         return ERROR_INT("invalid copyflag", procName, 1);
516     if (!pixc)
517         return ERROR_INT("pixc not made", procName, 1);
518 
519     n = pixaGetCount(pixa);
520     if (n >= pixa->nalloc)
521         pixaExtendArray(pixa);
522     pixa->pix[n] = pixc;
523     pixa->n++;
524 
525     return 0;
526 }
527 
528 
529 /*!
530  * \brief   pixaAddBox()
531  *
532  * \param[in]    pixa
533  * \param[in]    box
534  * \param[in]    copyflag L_INSERT, L_COPY, L_CLONE
535  * \return  0 if OK, 1 on error
536  */
537 l_int32
pixaAddBox(PIXA * pixa,BOX * box,l_int32 copyflag)538 pixaAddBox(PIXA    *pixa,
539            BOX     *box,
540            l_int32  copyflag)
541 {
542     PROCNAME("pixaAddBox");
543 
544     if (!pixa)
545         return ERROR_INT("pixa not defined", procName, 1);
546     if (!box)
547         return ERROR_INT("box not defined", procName, 1);
548     if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
549         return ERROR_INT("invalid copyflag", procName, 1);
550 
551     boxaAddBox(pixa->boxa, box, copyflag);
552     return 0;
553 }
554 
555 
556 /*!
557  * \brief   pixaExtendArray()
558  *
559  * \param[in]    pixa
560  * \return  0 if OK; 1 on error
561  *
562  * <pre>
563  * Notes:
564  *      (1) Doubles the size of the pixa and boxa ptr arrays.
565  * </pre>
566  */
567 static l_int32
pixaExtendArray(PIXA * pixa)568 pixaExtendArray(PIXA  *pixa)
569 {
570     PROCNAME("pixaExtendArray");
571 
572     if (!pixa)
573         return ERROR_INT("pixa not defined", procName, 1);
574 
575     return pixaExtendArrayToSize(pixa, 2 * pixa->nalloc);
576 }
577 
578 
579 /*!
580  * \brief   pixaExtendArrayToSize()
581  *
582  * \param[in]    pixa
583  * \return  0 if OK; 1 on error
584  *
585  * <pre>
586  * Notes:
587  *      (1) If necessary, reallocs new pixa and boxa ptrs arrays to %size.
588  *          The pixa and boxa ptr arrays must always be equal in size.
589  * </pre>
590  */
591 l_int32
pixaExtendArrayToSize(PIXA * pixa,l_int32 size)592 pixaExtendArrayToSize(PIXA    *pixa,
593                       l_int32  size)
594 {
595     PROCNAME("pixaExtendArrayToSize");
596 
597     if (!pixa)
598         return ERROR_INT("pixa not defined", procName, 1);
599 
600     if (size > pixa->nalloc) {
601         if ((pixa->pix = (PIX **)reallocNew((void **)&pixa->pix,
602                                  sizeof(PIX *) * pixa->nalloc,
603                                  size * sizeof(PIX *))) == NULL)
604             return ERROR_INT("new ptr array not returned", procName, 1);
605         pixa->nalloc = size;
606     }
607     return boxaExtendArrayToSize(pixa->boxa, size);
608 }
609 
610 
611 /*---------------------------------------------------------------------*
612  *                             Pixa accessors                          *
613  *---------------------------------------------------------------------*/
614 /*!
615  * \brief   pixaGetCount()
616  *
617  * \param[in]    pixa
618  * \return  count, or 0 if no pixa
619  */
620 l_int32
pixaGetCount(PIXA * pixa)621 pixaGetCount(PIXA  *pixa)
622 {
623     PROCNAME("pixaGetCount");
624 
625     if (!pixa)
626         return ERROR_INT("pixa not defined", procName, 0);
627 
628     return pixa->n;
629 }
630 
631 
632 /*!
633  * \brief   pixaChangeRefcount()
634  *
635  * \param[in]    pixa
636  * \return  0 if OK, 1 on error
637  */
638 l_int32
pixaChangeRefcount(PIXA * pixa,l_int32 delta)639 pixaChangeRefcount(PIXA    *pixa,
640                    l_int32  delta)
641 {
642     PROCNAME("pixaChangeRefcount");
643 
644     if (!pixa)
645         return ERROR_INT("pixa not defined", procName, 1);
646 
647     pixa->refcount += delta;
648     return 0;
649 }
650 
651 
652 /*!
653  * \brief   pixaGetPix()
654  *
655  * \param[in]    pixa
656  * \param[in]    index  to the index-th pix
657  * \param[in]    accesstype  L_COPY or L_CLONE
658  * \return  pix, or NULL on error
659  */
660 PIX *
pixaGetPix(PIXA * pixa,l_int32 index,l_int32 accesstype)661 pixaGetPix(PIXA    *pixa,
662            l_int32  index,
663            l_int32  accesstype)
664 {
665 PIX  *pix;
666 
667     PROCNAME("pixaGetPix");
668 
669     if (!pixa)
670         return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
671     if (index < 0 || index >= pixa->n)
672         return (PIX *)ERROR_PTR("index not valid", procName, NULL);
673     if ((pix = pixa->pix[index]) == NULL) {
674         L_ERROR("no pix at pixa[%d]\n", procName, index);
675         return (PIX *)ERROR_PTR("pix not found!", procName, NULL);
676     }
677 
678     if (accesstype == L_COPY)
679         return pixCopy(NULL, pix);
680     else if (accesstype == L_CLONE)
681         return pixClone(pix);
682     else
683         return (PIX *)ERROR_PTR("invalid accesstype", procName, NULL);
684 }
685 
686 
687 /*!
688  * \brief   pixaGetPixDimensions()
689  *
690  * \param[in]    pixa
691  * \param[in]    index  to the index-th box
692  * \param[out]   pw, ph, pd [optional]  each can be null
693  * \return  0 if OK, 1 on error
694  */
695 l_int32
pixaGetPixDimensions(PIXA * pixa,l_int32 index,l_int32 * pw,l_int32 * ph,l_int32 * pd)696 pixaGetPixDimensions(PIXA     *pixa,
697                      l_int32   index,
698                      l_int32  *pw,
699                      l_int32  *ph,
700                      l_int32  *pd)
701 {
702 PIX  *pix;
703 
704     PROCNAME("pixaGetPixDimensions");
705 
706     if (pw) *pw = 0;
707     if (ph) *ph = 0;
708     if (pd) *pd = 0;
709     if (!pixa)
710         return ERROR_INT("pixa not defined", procName, 1);
711     if (index < 0 || index >= pixa->n)
712         return ERROR_INT("index not valid", procName, 1);
713 
714     if ((pix = pixaGetPix(pixa, index, L_CLONE)) == NULL)
715         return ERROR_INT("pix not found!", procName, 1);
716     pixGetDimensions(pix, pw, ph, pd);
717     pixDestroy(&pix);
718     return 0;
719 }
720 
721 
722 /*!
723  * \brief   pixaGetBoxa()
724  *
725  * \param[in]    pixa
726  * \param[in]    accesstype  L_COPY, L_CLONE, L_COPY_CLONE
727  * \return  boxa, or NULL on error
728  */
729 BOXA *
pixaGetBoxa(PIXA * pixa,l_int32 accesstype)730 pixaGetBoxa(PIXA    *pixa,
731             l_int32  accesstype)
732 {
733     PROCNAME("pixaGetBoxa");
734 
735     if (!pixa)
736         return (BOXA *)ERROR_PTR("pixa not defined", procName, NULL);
737     if (!pixa->boxa)
738         return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
739     if (accesstype != L_COPY && accesstype != L_CLONE &&
740         accesstype != L_COPY_CLONE)
741         return (BOXA *)ERROR_PTR("invalid accesstype", procName, NULL);
742 
743     return boxaCopy(pixa->boxa, accesstype);
744 }
745 
746 
747 /*!
748  * \brief   pixaGetBoxaCount()
749  *
750  * \param[in]    pixa
751  * \return  count, or 0 on error
752  */
753 l_int32
pixaGetBoxaCount(PIXA * pixa)754 pixaGetBoxaCount(PIXA  *pixa)
755 {
756     PROCNAME("pixaGetBoxaCount");
757 
758     if (!pixa)
759         return ERROR_INT("pixa not defined", procName, 0);
760 
761     return boxaGetCount(pixa->boxa);
762 }
763 
764 
765 /*!
766  * \brief   pixaGetBox()
767  *
768  * \param[in]    pixa
769  * \param[in]    index  to the index-th pix
770  * \param[in]    accesstype  L_COPY or L_CLONE
771  * \return  box if null, not automatically an error, or NULL on error
772  *
773  * <pre>
774  * Notes:
775  *      (1) There is always a boxa with a pixa, and it is initialized so
776  *          that each box ptr is NULL.
777  *      (2) In general, we expect that there is either a box associated
778  *          with each pix, or no boxes at all in the boxa.
779  *      (3) Having no boxes is thus not an automatic error.  Whether it
780  *          is an actual error is determined by the calling program.
781  *          If the caller expects to get a box, it is an error; see, e.g.,
782  *          pixaGetBoxGeometry().
783  * </pre>
784  */
785 BOX *
pixaGetBox(PIXA * pixa,l_int32 index,l_int32 accesstype)786 pixaGetBox(PIXA    *pixa,
787            l_int32  index,
788            l_int32  accesstype)
789 {
790 BOX  *box;
791 
792     PROCNAME("pixaGetBox");
793 
794     if (!pixa)
795         return (BOX *)ERROR_PTR("pixa not defined", procName, NULL);
796     if (!pixa->boxa)
797         return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
798     if (index < 0 || index >= pixa->boxa->n)
799         return (BOX *)ERROR_PTR("index not valid", procName, NULL);
800     if (accesstype != L_COPY && accesstype != L_CLONE)
801         return (BOX *)ERROR_PTR("invalid accesstype", procName, NULL);
802 
803     box = pixa->boxa->box[index];
804     if (box) {
805         if (accesstype == L_COPY)
806             return boxCopy(box);
807         else  /* accesstype == L_CLONE */
808             return boxClone(box);
809     } else {
810         return NULL;
811     }
812 }
813 
814 
815 /*!
816  * \brief   pixaGetBoxGeometry()
817  *
818  * \param[in]    pixa
819  * \param[in]    index  to the index-th box
820  * \param[out]   px, py, pw, ph [optional]  each can be null
821  * \return  0 if OK, 1 on error
822  */
823 l_int32
pixaGetBoxGeometry(PIXA * pixa,l_int32 index,l_int32 * px,l_int32 * py,l_int32 * pw,l_int32 * ph)824 pixaGetBoxGeometry(PIXA     *pixa,
825                    l_int32   index,
826                    l_int32  *px,
827                    l_int32  *py,
828                    l_int32  *pw,
829                    l_int32  *ph)
830 {
831 BOX  *box;
832 
833     PROCNAME("pixaGetBoxGeometry");
834 
835     if (px) *px = 0;
836     if (py) *py = 0;
837     if (pw) *pw = 0;
838     if (ph) *ph = 0;
839     if (!pixa)
840         return ERROR_INT("pixa not defined", procName, 1);
841     if (index < 0 || index >= pixa->n)
842         return ERROR_INT("index not valid", procName, 1);
843 
844     if ((box = pixaGetBox(pixa, index, L_CLONE)) == NULL)
845         return ERROR_INT("box not found!", procName, 1);
846     boxGetGeometry(box, px, py, pw, ph);
847     boxDestroy(&box);
848     return 0;
849 }
850 
851 
852 /*!
853  * \brief   pixaSetBoxa()
854  *
855  * \param[in]    pixa
856  * \param[in]    boxa
857  * \param[in]    accesstype  L_INSERT, L_COPY, L_CLONE
858  * \return  0 if OK, 1 on error
859  *
860  * <pre>
861  * Notes:
862  *      (1) This destroys the existing boxa in the pixa.
863  * </pre>
864  */
865 l_int32
pixaSetBoxa(PIXA * pixa,BOXA * boxa,l_int32 accesstype)866 pixaSetBoxa(PIXA    *pixa,
867             BOXA    *boxa,
868             l_int32  accesstype)
869 {
870     PROCNAME("pixaSetBoxa");
871 
872     if (!pixa)
873         return ERROR_INT("pixa not defined", procName, 1);
874     if (!boxa)
875         return ERROR_INT("boxa not defined", procName, 1);
876     if (accesstype != L_INSERT && accesstype != L_COPY &&
877         accesstype != L_CLONE)
878         return ERROR_INT("invalid access type", procName, 1);
879 
880     boxaDestroy(&pixa->boxa);
881     if (accesstype == L_INSERT)
882         pixa->boxa = boxa;
883     else
884         pixa->boxa = boxaCopy(boxa, accesstype);
885 
886     return 0;
887 }
888 
889 
890 /*!
891  * \brief   pixaGetPixArray()
892  *
893  * \param[in]    pixa
894  * \return  pix array, or NULL on error
895  *
896  * <pre>
897  * Notes:
898  *      (1) This returns a ptr to the actual array.  The array is
899  *          owned by the pixa, so it must not be destroyed.
900  *      (2) The caller should always check if the return value is NULL
901  *          before accessing any of the pix ptrs in this array!
902  * </pre>
903  */
904 PIX **
pixaGetPixArray(PIXA * pixa)905 pixaGetPixArray(PIXA  *pixa)
906 {
907     PROCNAME("pixaGetPixArray");
908 
909     if (!pixa)
910         return (PIX **)ERROR_PTR("pixa not defined", procName, NULL);
911 
912     return pixa->pix;
913 }
914 
915 
916 /*!
917  * \brief   pixaVerifyDepth()
918  *
919  * \param[in]    pixa
920  * \param[out]   psame   1 if depth is the same for all pix; 0 otherwise
921  * \param[out]   pmaxd   [optional] max depth of all pix
922  * \return  0 if OK, 1 on error
923  *
924  * <pre>
925  * Notes:
926  *      (1) It is considered to be an error if there are no pix.
927  * </pre>
928  */
929 l_int32
pixaVerifyDepth(PIXA * pixa,l_int32 * psame,l_int32 * pmaxd)930 pixaVerifyDepth(PIXA     *pixa,
931                 l_int32  *psame,
932                 l_int32  *pmaxd)
933 {
934 l_int32  i, n, d, maxd, same;
935 
936     PROCNAME("pixaVerifyDepth");
937 
938     if (pmaxd) *pmaxd = 0;
939     if (!psame)
940         return ERROR_INT("psame not defined", procName, 1);
941     if (!pixa)
942         return ERROR_INT("pixa not defined", procName, 1);
943     if ((n = pixaGetCount(pixa)) == 0)
944         return ERROR_INT("no pix in pixa", procName, 1);
945 
946     same = 1;
947     pixaGetPixDimensions(pixa, 0, NULL, NULL, &maxd);
948     for (i = 1; i < n; i++) {
949         if (pixaGetPixDimensions(pixa, i, NULL, NULL, &d))
950             return ERROR_INT("pix depth not found", procName, 1);
951         maxd = L_MAX(maxd, d);
952         if (d != maxd)
953             same = 0;
954     }
955     *psame = same;
956     if (pmaxd) *pmaxd = maxd;
957     return 0;
958 }
959 
960 
961 /*!
962  * \brief   pixaVerifyDimensions()
963  *
964  * \param[in]    pixa
965  * \param[out]   psame   1 if dimensions are the same for all pix; 0 otherwise
966  * \param[out]   pmaxw   [optional] max width of all pix
967  * \param[out]   pmaxh   [optional] max height of all pix
968  * \return  0 if OK, 1 on error
969  *
970  * <pre>
971  * Notes:
972  *      (1) It is considered to be an error if there are no pix.
973  * </pre>
974  */
975 l_int32
pixaVerifyDimensions(PIXA * pixa,l_int32 * psame,l_int32 * pmaxw,l_int32 * pmaxh)976 pixaVerifyDimensions(PIXA     *pixa,
977                      l_int32  *psame,
978                      l_int32  *pmaxw,
979                      l_int32  *pmaxh)
980 {
981 l_int32  i, n, w, h, maxw, maxh, same;
982 
983     PROCNAME("pixaVerifyDimensions");
984 
985     if (pmaxw) *pmaxw = 0;
986     if (pmaxh) *pmaxh = 0;
987     if (!psame)
988         return ERROR_INT("psame not defined", procName, 1);
989     *psame = 0;
990     if (!pixa)
991         return ERROR_INT("pixa not defined", procName, 1);
992     if ((n = pixaGetCount(pixa)) == 0)
993         return ERROR_INT("no pix in pixa", procName, 1);
994 
995     same = 1;
996     pixaGetPixDimensions(pixa, 0, &maxw, &maxh, NULL);
997     for (i = 1; i < n; i++) {
998         if (pixaGetPixDimensions(pixa, i, &w, &h, NULL))
999             return ERROR_INT("pix dimensions not found", procName, 1);
1000         maxw = L_MAX(maxw, w);
1001         maxh = L_MAX(maxh, h);
1002         if (w != maxw || h != maxh)
1003             same = 0;
1004     }
1005     *psame = same;
1006     if (pmaxw) *pmaxw = maxw;
1007     if (pmaxh) *pmaxh = maxh;
1008     return 0;
1009 }
1010 
1011 
1012 /*!
1013  * \brief   pixaIsFull()
1014  *
1015  * \param[in]    pixa
1016  * \param[out]   pfullpa [optional] 1 if pixa is full
1017  * \param[out]   pfullba [optional] 1 if boxa is full
1018  * \return  0 if OK, 1 on error
1019  *
1020  * <pre>
1021  * Notes:
1022  *      (1) A pixa is "full" if the array of pix is fully
1023  *          occupied from index 0 to index (pixa->n - 1).
1024  * </pre>
1025  */
1026 l_int32
pixaIsFull(PIXA * pixa,l_int32 * pfullpa,l_int32 * pfullba)1027 pixaIsFull(PIXA     *pixa,
1028            l_int32  *pfullpa,
1029            l_int32  *pfullba)
1030 {
1031 l_int32  i, n, full;
1032 BOXA    *boxa;
1033 PIX     *pix;
1034 
1035     PROCNAME("pixaIsFull");
1036 
1037     if (pfullpa) *pfullpa = 0;
1038     if (pfullba) *pfullba = 0;
1039     if (!pixa)
1040         return ERROR_INT("pixa not defined", procName, 1);
1041 
1042     n = pixaGetCount(pixa);
1043     if (pfullpa) {
1044         full = 1;
1045         for (i = 0; i < n; i++) {
1046             if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) {
1047                 full = 0;
1048                 break;
1049             }
1050             pixDestroy(&pix);
1051         }
1052         *pfullpa = full;
1053     }
1054     if (pfullba) {
1055         boxa = pixaGetBoxa(pixa, L_CLONE);
1056         boxaIsFull(boxa, pfullba);
1057         boxaDestroy(&boxa);
1058     }
1059     return 0;
1060 }
1061 
1062 
1063 /*!
1064  * \brief   pixaCountText()
1065  *
1066  * \param[in]    pixa
1067  * \param[out]   pntext number of pix with non-empty text strings
1068  * \return  0 if OK, 1 on error.
1069  *
1070  * <pre>
1071  * Notes:
1072  *      (1) All pix have non-empty text strings if the returned value %ntext
1073  *          equals the pixa count.
1074  * </pre>
1075  */
1076 l_int32
pixaCountText(PIXA * pixa,l_int32 * pntext)1077 pixaCountText(PIXA     *pixa,
1078               l_int32  *pntext)
1079 {
1080 char    *text;
1081 l_int32  i, n;
1082 PIX     *pix;
1083 
1084     PROCNAME("pixaCountText");
1085 
1086     if (!pntext)
1087         return ERROR_INT("&ntext not defined", procName, 1);
1088     *pntext = 0;
1089     if (!pixa)
1090         return ERROR_INT("pixa not defined", procName, 1);
1091 
1092     n = pixaGetCount(pixa);
1093     for (i = 0; i < n; i++) {
1094         if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
1095             continue;
1096         text = pixGetText(pix);
1097         if (text && strlen(text) > 0)
1098             (*pntext)++;
1099         pixDestroy(&pix);
1100     }
1101 
1102     return 0;
1103 }
1104 
1105 
1106 /*!
1107  * \brief   pixaSetText()
1108  *
1109  * \param[in]    pixa
1110  * \param[in]    sa  [optional] array of text strings, to insert in each pix
1111  * \return  0 if OK, 1 on error.
1112  *
1113  * <pre>
1114  * Notes:
1115  *      (1) To clear all the text fields, use sa == NULL;
1116  *      (2) If sa is defined, it must be the same size as %pixa.
1117  * </pre>
1118  */
1119 l_int32
pixaSetText(PIXA * pixa,SARRAY * sa)1120 pixaSetText(PIXA    *pixa,
1121             SARRAY  *sa)
1122 {
1123 char    *str;
1124 l_int32  i, n;
1125 PIX     *pix;
1126 
1127     PROCNAME("pixaSetText");
1128 
1129     if (!pixa)
1130         return ERROR_INT("pixa not defined", procName, 1);
1131 
1132     n = pixaGetCount(pixa);
1133     if (!sa) {
1134         for (i = 0; i < n; i++) {
1135             if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
1136                 continue;
1137             pixSetText(pix, NULL);
1138             pixDestroy(&pix);
1139         }
1140         return 0;
1141     }
1142 
1143     if (sarrayGetCount(sa) != n)
1144         return ERROR_INT("pixa and sa sizes differ", procName, 1);
1145 
1146     for (i = 0; i < n; i++) {
1147         if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
1148             continue;
1149         str = sarrayGetString(sa, i, L_NOCOPY);
1150         pixSetText(pix, str);
1151         pixDestroy(&pix);
1152     }
1153 
1154     return 0;
1155 }
1156 
1157 
1158 /*!
1159  * \brief   pixaGetLinePtrs()
1160  *
1161  * \param[in]    pixa of pix that all have the same depth
1162  * \param[out]   psize [optional] number of pix in the pixa
1163  * \return  array of array of line ptrs, or NULL on error
1164  *
1165  * <pre>
1166  * Notes:
1167  *      (1) See pixGetLinePtrs() for details.
1168  *      (2) It is best if all pix in the pixa are the same size.
1169  *          The size of each line ptr array is equal to the height
1170  *          of the pix that it refers to.
1171  *      (3) This is an array of arrays.  To destroy it:
1172  *            for (i = 0; i < size; i++)
1173  *                LEPT_FREE(lineset[i]);
1174  *            LEPT_FREE(lineset);
1175  * </pre>
1176  */
1177 void ***
pixaGetLinePtrs(PIXA * pixa,l_int32 * psize)1178 pixaGetLinePtrs(PIXA     *pixa,
1179                 l_int32  *psize)
1180 {
1181 l_int32  i, n, same;
1182 void   **lineptrs;
1183 void  ***lineset;
1184 PIX     *pix;
1185 
1186     PROCNAME("pixaGetLinePtrs");
1187 
1188     if (psize) *psize = 0;
1189     if (!pixa)
1190         return (void ***)ERROR_PTR("pixa not defined", procName, NULL);
1191     pixaVerifyDepth(pixa, &same, NULL);
1192     if (!same)
1193         return (void ***)ERROR_PTR("pixa not all same depth", procName, NULL);
1194     n = pixaGetCount(pixa);
1195     if (psize) *psize = n;
1196     if ((lineset = (void ***)LEPT_CALLOC(n, sizeof(void **))) == NULL)
1197         return (void ***)ERROR_PTR("lineset not made", procName, NULL);
1198     for (i = 0; i < n; i++) {
1199         pix = pixaGetPix(pixa, i, L_CLONE);
1200         lineptrs = pixGetLinePtrs(pix, NULL);
1201         lineset[i] = lineptrs;
1202         pixDestroy(&pix);
1203     }
1204 
1205     return lineset;
1206 }
1207 
1208 
1209 /*---------------------------------------------------------------------*
1210  *                         Pixa output info                            *
1211  *---------------------------------------------------------------------*/
1212 /*!
1213  * \brief   pixaWriteStreamInfo()
1214  *
1215  * \param[in]    fp file stream
1216  * \param[in]    pixa
1217  * \return  0 if OK, 1 on error.
1218  *
1219  * <pre>
1220  * Notes:
1221  *      (1) For each pix in the pixa, write out the pix dimensions, spp,
1222  *          text string (if it exists), and cmap info.
1223  * </pre>
1224  */
1225 l_int32
pixaWriteStreamInfo(FILE * fp,PIXA * pixa)1226 pixaWriteStreamInfo(FILE  *fp,
1227                     PIXA  *pixa)
1228 {
1229 char     *text;
1230 l_int32   i, n, w, h, d, spp, count, hastext;
1231 PIX      *pix;
1232 PIXCMAP  *cmap;
1233 
1234     PROCNAME("pixaWriteStreamInfo");
1235 
1236     if (!fp)
1237         return ERROR_INT("stream not defined", procName, 1);
1238     if (!pixa)
1239         return ERROR_INT("pixa not defined", procName, 1);
1240 
1241     n = pixaGetCount(pixa);
1242     for (i = 0; i < n; i++) {
1243         if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) {
1244             fprintf(fp, "%d: no pix at this index\n", i);
1245             continue;
1246         }
1247         pixGetDimensions(pix, &w, &h, &d);
1248         spp = pixGetSpp(pix);
1249         text = pixGetText(pix);
1250         hastext = (text && strlen(text) > 0);
1251         if ((cmap = pixGetColormap(pix)) != NULL)
1252             count = pixcmapGetCount(cmap);
1253         fprintf(fp, "Pix %d: w = %d, h = %d, d = %d, spp = %d",
1254                 i, w, h, d, spp);
1255         if (cmap) fprintf(fp, ", cmap(%d colors)", count);
1256         if (hastext) fprintf(fp, ", text = %s", text);
1257         fprintf(fp, "\n");
1258         pixDestroy(&pix);
1259     }
1260 
1261     return 0;
1262 }
1263 
1264 
1265 /*---------------------------------------------------------------------*
1266  *                       Pixa array modifiers                          *
1267  *---------------------------------------------------------------------*/
1268 /*!
1269  * \brief   pixaReplacePix()
1270  *
1271  * \param[in]    pixa
1272  * \param[in]    index  to the index-th pix
1273  * \param[in]    pix insert to replace existing one
1274  * \param[in]    box [optional] insert to replace existing
1275  * \return  0 if OK, 1 on error
1276  *
1277  * <pre>
1278  * Notes:
1279  *      (1) In-place replacement of one pix.
1280  *      (2) The previous pix at that location is destroyed.
1281  * </pre>
1282  */
1283 l_int32
pixaReplacePix(PIXA * pixa,l_int32 index,PIX * pix,BOX * box)1284 pixaReplacePix(PIXA    *pixa,
1285                l_int32  index,
1286                PIX     *pix,
1287                BOX     *box)
1288 {
1289 BOXA  *boxa;
1290 
1291     PROCNAME("pixaReplacePix");
1292 
1293     if (!pixa)
1294         return ERROR_INT("pixa not defined", procName, 1);
1295     if (index < 0 || index >= pixa->n)
1296         return ERROR_INT("index not valid", procName, 1);
1297     if (!pix)
1298         return ERROR_INT("pix not defined", procName, 1);
1299 
1300     pixDestroy(&(pixa->pix[index]));
1301     pixa->pix[index] = pix;
1302 
1303     if (box) {
1304         boxa = pixa->boxa;
1305         if (index > boxa->n)
1306             return ERROR_INT("boxa index not valid", procName, 1);
1307         boxaReplaceBox(boxa, index, box);
1308     }
1309 
1310     return 0;
1311 }
1312 
1313 
1314 /*!
1315  * \brief   pixaInsertPix()
1316  *
1317  * \param[in]    pixa
1318  * \param[in]    index at which pix is to be inserted
1319  * \param[in]    pixs new pix to be inserted
1320  * \param[in]    box [optional] new box to be inserted
1321  * \return  0 if OK, 1 on error
1322  *
1323  * <pre>
1324  * Notes:
1325  *      (1) This shifts pixa[i] --> pixa[i + 1] for all i >= index,
1326  *          and then inserts at pixa[index].
1327  *      (2) To insert at the beginning of the array, set index = 0.
1328  *      (3) It should not be used repeatedly on large arrays,
1329  *          because the function is O(n).
1330  *      (4) To append a pix to a pixa, it's easier to use pixaAddPix().
1331  * </pre>
1332  */
1333 l_int32
pixaInsertPix(PIXA * pixa,l_int32 index,PIX * pixs,BOX * box)1334 pixaInsertPix(PIXA    *pixa,
1335               l_int32  index,
1336               PIX     *pixs,
1337               BOX     *box)
1338 {
1339 l_int32  i, n;
1340 
1341     PROCNAME("pixaInsertPix");
1342 
1343     if (!pixa)
1344         return ERROR_INT("pixa not defined", procName, 1);
1345     n = pixaGetCount(pixa);
1346     if (index < 0 || index > n)
1347         return ERROR_INT("index not in {0...n}", procName, 1);
1348     if (!pixs)
1349         return ERROR_INT("pixs not defined", procName, 1);
1350 
1351     if (n >= pixa->nalloc) {  /* extend both ptr arrays */
1352         pixaExtendArray(pixa);
1353         boxaExtendArray(pixa->boxa);
1354     }
1355     pixa->n++;
1356     for (i = n; i > index; i--)
1357       pixa->pix[i] = pixa->pix[i - 1];
1358     pixa->pix[index] = pixs;
1359 
1360         /* Optionally, insert the box */
1361     if (box)
1362         boxaInsertBox(pixa->boxa, index, box);
1363 
1364     return 0;
1365 }
1366 
1367 
1368 /*!
1369  * \brief   pixaRemovePix()
1370  *
1371  * \param[in]    pixa
1372  * \param[in]    index of pix to be removed
1373  * \return  0 if OK, 1 on error
1374  *
1375  * <pre>
1376  * Notes:
1377  *      (1) This shifts pixa[i] --> pixa[i - 1] for all i > index.
1378  *      (2) It should not be used repeatedly on large arrays,
1379  *          because the function is O(n).
1380  *      (3) The corresponding box is removed as well, if it exists.
1381  * </pre>
1382  */
1383 l_int32
pixaRemovePix(PIXA * pixa,l_int32 index)1384 pixaRemovePix(PIXA    *pixa,
1385               l_int32  index)
1386 {
1387 l_int32  i, n, nbox;
1388 BOXA    *boxa;
1389 PIX    **array;
1390 
1391     PROCNAME("pixaRemovePix");
1392 
1393     if (!pixa)
1394         return ERROR_INT("pixa not defined", procName, 1);
1395     n = pixaGetCount(pixa);
1396     if (index < 0 || index >= n)
1397         return ERROR_INT("index not in {0...n - 1}", procName, 1);
1398 
1399         /* Remove the pix */
1400     array = pixa->pix;
1401     pixDestroy(&array[index]);
1402     for (i = index + 1; i < n; i++)
1403         array[i - 1] = array[i];
1404     array[n - 1] = NULL;
1405     pixa->n--;
1406 
1407         /* Remove the box if it exists */
1408     boxa = pixa->boxa;
1409     nbox = boxaGetCount(boxa);
1410     if (index < nbox)
1411         boxaRemoveBox(boxa, index);
1412 
1413     return 0;
1414 }
1415 
1416 
1417 /*!
1418  * \brief   pixaRemovePixAndSave()
1419  *
1420  * \param[in]    pixa
1421  * \param[in]    index of pix to be removed
1422  * \param[out]   ppix [optional] removed pix
1423  * \param[out]   pbox [optional] removed box
1424  * \return  0 if OK, 1 on error
1425  *
1426  * <pre>
1427  * Notes:
1428  *      (1) This shifts pixa[i] --> pixa[i - 1] for all i > index.
1429  *      (2) It should not be used repeatedly on large arrays,
1430  *          because the function is O(n).
1431  *      (3) The corresponding box is removed as well, if it exists.
1432  *      (4) The removed pix and box can either be retained or destroyed.
1433  * </pre>
1434  */
1435 l_int32
pixaRemovePixAndSave(PIXA * pixa,l_int32 index,PIX ** ppix,BOX ** pbox)1436 pixaRemovePixAndSave(PIXA    *pixa,
1437                      l_int32  index,
1438                      PIX    **ppix,
1439                      BOX    **pbox)
1440 {
1441 l_int32  i, n, nbox;
1442 BOXA    *boxa;
1443 PIX    **array;
1444 
1445     PROCNAME("pixaRemovePixAndSave");
1446 
1447     if (ppix) *ppix = NULL;
1448     if (pbox) *pbox = NULL;
1449     if (!pixa)
1450         return ERROR_INT("pixa not defined", procName, 1);
1451     n = pixaGetCount(pixa);
1452     if (index < 0 || index >= n)
1453         return ERROR_INT("index not in {0...n - 1}", procName, 1);
1454 
1455         /* Remove the pix */
1456     array = pixa->pix;
1457     if (ppix)
1458         *ppix = pixaGetPix(pixa, index, L_CLONE);
1459     pixDestroy(&array[index]);
1460     for (i = index + 1; i < n; i++)
1461         array[i - 1] = array[i];
1462     array[n - 1] = NULL;
1463     pixa->n--;
1464 
1465         /* Remove the box if it exists  */
1466     boxa = pixa->boxa;
1467     nbox = boxaGetCount(boxa);
1468     if (index < nbox)
1469         boxaRemoveBoxAndSave(boxa, index, pbox);
1470 
1471     return 0;
1472 }
1473 
1474 
1475 /*!
1476  * \brief   pixaInitFull()
1477  *
1478  * \param[in]    pixa typically empty
1479  * \param[in]    pix [optional] to be replicated into the entire pixa ptr array
1480  * \param[in]    box [optional] to be replicated into the entire boxa ptr array
1481  * \return  0 if OK, 1 on error
1482  *
1483  * <pre>
1484  * Notes:
1485  *      (1) This initializes a pixa by filling up the entire pix ptr array
1486  *          with copies of %pix.  If %pix == NULL, we use a tiny placeholder
1487  *          pix (w = h = d = 1).  Any existing pix are destroyed.
1488  *          It also optionally fills the boxa with copies of %box.
1489  *          After this operation, the numbers of pix and (optionally)
1490  *          boxes are equal to the number of allocated ptrs.
1491  *      (2) Note that we use pixaReplacePix() instead of pixaInsertPix().
1492  *          They both have the same effect when inserting into a NULL ptr
1493  *          in the pixa ptr array:
1494  *      (3) If the boxa is not initialized (i.e., filled with boxes),
1495  *          later insertion of boxes will cause an error, because the
1496  *          'n' field is 0.
1497  *      (4) Example usage.  This function is useful to prepare for a
1498  *          random insertion (or replacement) of pix into a pixa.
1499  *          To randomly insert pix into a pixa, without boxes, up to
1500  *          some index "max":
1501  *             Pixa *pixa = pixaCreate(max);
1502  *             pixaInitFull(pixa, NULL, NULL);
1503  *          An existing pixa with a smaller ptr array can also be reused:
1504  *             pixaExtendArrayToSize(pixa, max);
1505  *             pixaInitFull(pixa, NULL, NULL);
1506  *          The initialization allows the pixa to always be properly
1507  *          filled, even if all pix (and boxes) are not later replaced.
1508  * </pre>
1509  */
1510 l_int32
pixaInitFull(PIXA * pixa,PIX * pix,BOX * box)1511 pixaInitFull(PIXA  *pixa,
1512              PIX   *pix,
1513              BOX   *box)
1514 {
1515 l_int32  i, n;
1516 PIX     *pix1;
1517 
1518     PROCNAME("pixaInitFull");
1519 
1520     if (!pixa)
1521         return ERROR_INT("pixa not defined", procName, 1);
1522 
1523     n = pixa->nalloc;
1524     pixa->n = n;
1525     for (i = 0; i < n; i++) {
1526         if (pix)
1527             pix1 = pixCopy(NULL, pix);
1528         else
1529             pix1 = pixCreate(1, 1, 1);
1530         pixaReplacePix(pixa, i, pix1, NULL);
1531     }
1532     if (box)
1533         boxaInitFull(pixa->boxa, box);
1534 
1535     return 0;
1536 }
1537 
1538 
1539 /*!
1540  * \brief   pixaClear()
1541  *
1542  * \param[in]    pixa
1543  * \return  0 if OK, 1 on error
1544  *
1545  * <pre>
1546  * Notes:
1547  *      (1) This destroys all pix in the pixa, as well as
1548  *          all boxes in the boxa.  The ptrs in the pix ptr array
1549  *          are all null'd.  The number of allocated pix, n, is set to 0.
1550  * </pre>
1551  */
1552 l_int32
pixaClear(PIXA * pixa)1553 pixaClear(PIXA  *pixa)
1554 {
1555 l_int32  i, n;
1556 
1557     PROCNAME("pixaClear");
1558 
1559     if (!pixa)
1560         return ERROR_INT("pixa not defined", procName, 1);
1561 
1562     n = pixaGetCount(pixa);
1563     for (i = 0; i < n; i++)
1564         pixDestroy(&pixa->pix[i]);
1565     pixa->n = 0;
1566     return boxaClear(pixa->boxa);
1567 }
1568 
1569 
1570 /*---------------------------------------------------------------------*
1571  *                      Pixa and Pixaa combination                     *
1572  *---------------------------------------------------------------------*/
1573 /*!
1574  * \brief   pixaJoin()
1575  *
1576  * \param[in]    pixad  dest pixa; add to this one
1577  * \param[in]    pixas  [optional] source pixa; add from this one
1578  * \param[in]    istart  starting index in pixas
1579  * \param[in]    iend  ending index in pixas; use -1 to cat all
1580  * \return  0 if OK, 1 on error
1581  *
1582  * <pre>
1583  * Notes:
1584  *      (1) This appends a clone of each indicated pix in pixas to pixad
1585  *      (2) istart < 0 is taken to mean 'read from the start' (istart = 0)
1586  *      (3) iend < 0 means 'read to the end'
1587  *      (4) If pixas is NULL or contains no pix, this is a no-op.
1588  * </pre>
1589  */
1590 l_int32
pixaJoin(PIXA * pixad,PIXA * pixas,l_int32 istart,l_int32 iend)1591 pixaJoin(PIXA    *pixad,
1592          PIXA    *pixas,
1593          l_int32  istart,
1594          l_int32  iend)
1595 {
1596 l_int32  i, n, nb;
1597 BOXA    *boxas, *boxad;
1598 PIX     *pix;
1599 
1600     PROCNAME("pixaJoin");
1601 
1602     if (!pixad)
1603         return ERROR_INT("pixad not defined", procName, 1);
1604     if (!pixas || ((n = pixaGetCount(pixas)) == 0))
1605         return 0;
1606 
1607     if (istart < 0)
1608         istart = 0;
1609     if (iend < 0 || iend >= n)
1610         iend = n - 1;
1611     if (istart > iend)
1612         return ERROR_INT("istart > iend; nothing to add", procName, 1);
1613 
1614     for (i = istart; i <= iend; i++) {
1615         pix = pixaGetPix(pixas, i, L_CLONE);
1616         pixaAddPix(pixad, pix, L_INSERT);
1617     }
1618 
1619     boxas = pixaGetBoxa(pixas, L_CLONE);
1620     boxad = pixaGetBoxa(pixad, L_CLONE);
1621     nb = pixaGetBoxaCount(pixas);
1622     iend = L_MIN(iend, nb - 1);
1623     boxaJoin(boxad, boxas, istart, iend);
1624     boxaDestroy(&boxas);  /* just the clones */
1625     boxaDestroy(&boxad);
1626     return 0;
1627 }
1628 
1629 
1630 /*!
1631  * \brief   pixaInterleave()
1632  *
1633  * \param[in]    pixa1  first src pixa
1634  * \param[in]    pixa2  second src pixa
1635  * \param[in]    copyflag L_CLONE, L_COPY
1636  * \return  pixa  interleaved from sources, or NULL on error.
1637  *
1638  * <pre>
1639  * Notes:
1640  *      (1) %copyflag determines if the pix are copied or cloned.
1641  *          The boxes, if they exist, are copied.
1642  *      (2) If the two pixa have different sizes, a warning is issued,
1643  *          and the number of pairs returned is the minimum size.
1644  * </pre>
1645  */
1646 PIXA *
pixaInterleave(PIXA * pixa1,PIXA * pixa2,l_int32 copyflag)1647 pixaInterleave(PIXA    *pixa1,
1648                PIXA    *pixa2,
1649                l_int32  copyflag)
1650 {
1651 l_int32  i, n1, n2, n, nb1, nb2;
1652 BOX     *box;
1653 PIX     *pix;
1654 PIXA    *pixad;
1655 
1656     PROCNAME("pixaInterleave");
1657 
1658     if (!pixa1)
1659         return (PIXA *)ERROR_PTR("pixa1 not defined", procName, NULL);
1660     if (!pixa2)
1661         return (PIXA *)ERROR_PTR("pixa2 not defined", procName, NULL);
1662     if (copyflag != L_COPY && copyflag != L_CLONE)
1663         return (PIXA *)ERROR_PTR("invalid copyflag", procName, NULL);
1664     n1 = pixaGetCount(pixa1);
1665     n2 = pixaGetCount(pixa2);
1666     n = L_MIN(n1, n2);
1667     if (n == 0)
1668         return (PIXA *)ERROR_PTR("at least one input pixa is empty",
1669                                  procName, NULL);
1670     if (n1 != n2)
1671         L_WARNING("counts differ: %d != %d\n", procName, n1, n2);
1672 
1673     pixad = pixaCreate(2 * n);
1674     nb1 = pixaGetBoxaCount(pixa1);
1675     nb2 = pixaGetBoxaCount(pixa2);
1676     for (i = 0; i < n; i++) {
1677         pix = pixaGetPix(pixa1, i, copyflag);
1678         pixaAddPix(pixad, pix, L_INSERT);
1679         if (i < nb1) {
1680             box = pixaGetBox(pixa1, i, L_COPY);
1681             pixaAddBox(pixad, box, L_INSERT);
1682         }
1683         pix = pixaGetPix(pixa2, i, copyflag);
1684         pixaAddPix(pixad, pix, L_INSERT);
1685         if (i < nb2) {
1686             box = pixaGetBox(pixa2, i, L_COPY);
1687             pixaAddBox(pixad, box, L_INSERT);
1688         }
1689     }
1690 
1691     return pixad;
1692 }
1693 
1694 
1695 /*!
1696  * \brief   pixaaJoin()
1697  *
1698  * \param[in]    paad  dest pixaa; add to this one
1699  * \param[in]    paas  [optional] source pixaa; add from this one
1700  * \param[in]    istart  starting index in pixaas
1701  * \param[in]    iend  ending index in pixaas; use -1 to cat all
1702  * \return  0 if OK, 1 on error
1703  *
1704  * <pre>
1705  * Notes:
1706  *      (1) This appends a clone of each indicated pixa in paas to pixaad
1707  *      (2) istart < 0 is taken to mean 'read from the start' (istart = 0)
1708  *      (3) iend < 0 means 'read to the end'
1709  * </pre>
1710  */
1711 l_int32
pixaaJoin(PIXAA * paad,PIXAA * paas,l_int32 istart,l_int32 iend)1712 pixaaJoin(PIXAA   *paad,
1713           PIXAA   *paas,
1714           l_int32  istart,
1715           l_int32  iend)
1716 {
1717 l_int32  i, n;
1718 PIXA    *pixa;
1719 
1720     PROCNAME("pixaaJoin");
1721 
1722     if (!paad)
1723         return ERROR_INT("pixaad not defined", procName, 1);
1724     if (!paas)
1725         return 0;
1726 
1727     if (istart < 0)
1728         istart = 0;
1729     n = pixaaGetCount(paas, NULL);
1730     if (iend < 0 || iend >= n)
1731         iend = n - 1;
1732     if (istart > iend)
1733         return ERROR_INT("istart > iend; nothing to add", procName, 1);
1734 
1735     for (i = istart; i <= iend; i++) {
1736         pixa = pixaaGetPixa(paas, i, L_CLONE);
1737         pixaaAddPixa(paad, pixa, L_INSERT);
1738     }
1739 
1740     return 0;
1741 }
1742 
1743 
1744 /*---------------------------------------------------------------------*
1745  *                    Pixaa creation and destruction                   *
1746  *---------------------------------------------------------------------*/
1747 /*!
1748  * \brief   pixaaCreate()
1749  *
1750  * \param[in]    n  initial number of pixa ptrs
1751  * \return  paa, or NULL on error
1752  *
1753  * <pre>
1754  * Notes:
1755  *      (1) A pixaa provides a 2-level hierarchy of images.
1756  *          A common use is for segmentation masks, which are
1757  *          inexpensive to store in png format.
1758  *      (2) For example, suppose you want a mask for each textline
1759  *          in a two-column page.  The textline masks for each column
1760  *          can be represented by a pixa, of which there are 2 in the pixaa.
1761  *          The boxes for the textline mask components within a column
1762  *          can have their origin referred to the column rather than the page.
1763  *          Then the boxa field can be used to represent the two box (regions)
1764  *          for the columns, and the (x,y) components of each box can
1765  *          be used to get the absolute position of the textlines on
1766  *          the page.
1767  * </pre>
1768  */
1769 PIXAA *
pixaaCreate(l_int32 n)1770 pixaaCreate(l_int32  n)
1771 {
1772 PIXAA  *paa;
1773 
1774     PROCNAME("pixaaCreate");
1775 
1776     if (n <= 0)
1777         n = INITIAL_PTR_ARRAYSIZE;
1778 
1779     if ((paa = (PIXAA *)LEPT_CALLOC(1, sizeof(PIXAA))) == NULL)
1780         return (PIXAA *)ERROR_PTR("paa not made", procName, NULL);
1781     paa->n = 0;
1782     paa->nalloc = n;
1783 
1784     if ((paa->pixa = (PIXA **)LEPT_CALLOC(n, sizeof(PIXA *))) == NULL) {
1785         pixaaDestroy(&paa);
1786         return (PIXAA *)ERROR_PTR("pixa ptrs not made", procName, NULL);
1787     }
1788     paa->boxa = boxaCreate(n);
1789 
1790     return paa;
1791 }
1792 
1793 
1794 /*!
1795  * \brief   pixaaCreateFromPixa()
1796  *
1797  * \param[in]    pixa
1798  * \param[in]    n number specifying subdivision of pixa
1799  * \param[in]    type L_CHOOSE_CONSECUTIVE, L_CHOOSE_SKIP_BY
1800  * \param[in]    copyflag L_CLONE, L_COPY
1801  * \return  paa, or NULL on error
1802  *
1803  * <pre>
1804  * Notes:
1805  *      (1) This subdivides a pixa into a set of smaller pixa that
1806  *          are accumulated into a pixaa.
1807  *      (2) If type == L_CHOOSE_CONSECUTIVE, the first 'n' pix are
1808  *          put in a pixa and added to pixaa, then the next 'n', etc.
1809  *          If type == L_CHOOSE_SKIP_BY, the first pixa is made by
1810  *          aggregating pix[0], pix[n], pix[2*n], etc.
1811  *      (3) The copyflag specifies if each new pix is a copy or a clone.
1812  * </pre>
1813  */
1814 PIXAA *
pixaaCreateFromPixa(PIXA * pixa,l_int32 n,l_int32 type,l_int32 copyflag)1815 pixaaCreateFromPixa(PIXA    *pixa,
1816                     l_int32  n,
1817                     l_int32  type,
1818                     l_int32  copyflag)
1819 {
1820 l_int32  count, i, j, npixa;
1821 PIX     *pix;
1822 PIXA    *pixat;
1823 PIXAA   *paa;
1824 
1825     PROCNAME("pixaaCreateFromPixa");
1826 
1827     if (!pixa)
1828         return (PIXAA *)ERROR_PTR("pixa not defined", procName, NULL);
1829     count = pixaGetCount(pixa);
1830     if (count == 0)
1831         return (PIXAA *)ERROR_PTR("no pix in pixa", procName, NULL);
1832     if (n <= 0)
1833         return (PIXAA *)ERROR_PTR("n must be > 0", procName, NULL);
1834     if (type != L_CHOOSE_CONSECUTIVE && type != L_CHOOSE_SKIP_BY)
1835         return (PIXAA *)ERROR_PTR("invalid type", procName, NULL);
1836     if (copyflag != L_CLONE && copyflag != L_COPY)
1837         return (PIXAA *)ERROR_PTR("invalid copyflag", procName, NULL);
1838 
1839     if (type == L_CHOOSE_CONSECUTIVE)
1840         npixa = (count + n - 1) / n;
1841     else  /* L_CHOOSE_SKIP_BY */
1842         npixa = L_MIN(n, count);
1843     paa = pixaaCreate(npixa);
1844     if (type == L_CHOOSE_CONSECUTIVE) {
1845         for (i = 0; i < count; i++) {
1846             if (i % n == 0)
1847                 pixat = pixaCreate(n);
1848             pix = pixaGetPix(pixa, i, copyflag);
1849             pixaAddPix(pixat, pix, L_INSERT);
1850             if (i % n == n - 1)
1851                 pixaaAddPixa(paa, pixat, L_INSERT);
1852         }
1853         if (i % n != 0)
1854             pixaaAddPixa(paa, pixat, L_INSERT);
1855     } else {  /* L_CHOOSE_SKIP_BY */
1856         for (i = 0; i < npixa; i++) {
1857             pixat = pixaCreate(count / npixa + 1);
1858             for (j = i; j < count; j += n) {
1859                 pix = pixaGetPix(pixa, j, copyflag);
1860                 pixaAddPix(pixat, pix, L_INSERT);
1861             }
1862             pixaaAddPixa(paa, pixat, L_INSERT);
1863         }
1864     }
1865 
1866     return paa;
1867 }
1868 
1869 
1870 /*!
1871  * \brief   pixaaDestroy()
1872  *
1873  * \param[in,out]   ppaa to be nulled
1874  * \return  void
1875  */
1876 void
pixaaDestroy(PIXAA ** ppaa)1877 pixaaDestroy(PIXAA  **ppaa)
1878 {
1879 l_int32  i;
1880 PIXAA   *paa;
1881 
1882     PROCNAME("pixaaDestroy");
1883 
1884     if (ppaa == NULL) {
1885         L_WARNING("ptr address is NULL!\n", procName);
1886         return;
1887     }
1888 
1889     if ((paa = *ppaa) == NULL)
1890         return;
1891 
1892     for (i = 0; i < paa->n; i++)
1893         pixaDestroy(&paa->pixa[i]);
1894     LEPT_FREE(paa->pixa);
1895     boxaDestroy(&paa->boxa);
1896 
1897     LEPT_FREE(paa);
1898     *ppaa = NULL;
1899 
1900     return;
1901 }
1902 
1903 
1904 /*---------------------------------------------------------------------*
1905  *                             Pixaa addition                          *
1906  *---------------------------------------------------------------------*/
1907 /*!
1908  * \brief   pixaaAddPixa()
1909  *
1910  * \param[in]    paa
1911  * \param[in]    pixa  to be added
1912  * \param[in]    copyflag:
1913  *                 L_INSERT inserts the pixa directly;
1914  *                 L_COPY makes a new pixa and copies each pix and each box;
1915  *                 L_CLONE gives a new handle to the input pixa;
1916  *                 L_COPY_CLONE makes a new pixa and inserts clones of
1917  *                     all pix and boxes
1918  * \return  0 if OK; 1 on error
1919  */
1920 l_int32
pixaaAddPixa(PIXAA * paa,PIXA * pixa,l_int32 copyflag)1921 pixaaAddPixa(PIXAA   *paa,
1922              PIXA    *pixa,
1923              l_int32  copyflag)
1924 {
1925 l_int32  n;
1926 PIXA    *pixac;
1927 
1928     PROCNAME("pixaaAddPixa");
1929 
1930     if (!paa)
1931         return ERROR_INT("paa not defined", procName, 1);
1932     if (!pixa)
1933         return ERROR_INT("pixa not defined", procName, 1);
1934     if (copyflag != L_INSERT && copyflag != L_COPY &&
1935         copyflag != L_CLONE && copyflag != L_COPY_CLONE)
1936         return ERROR_INT("invalid copyflag", procName, 1);
1937 
1938     if (copyflag == L_INSERT) {
1939         pixac = pixa;
1940     } else {
1941         if ((pixac = pixaCopy(pixa, copyflag)) == NULL)
1942             return ERROR_INT("pixac not made", procName, 1);
1943     }
1944 
1945     n = pixaaGetCount(paa, NULL);
1946     if (n >= paa->nalloc)
1947         pixaaExtendArray(paa);
1948     paa->pixa[n] = pixac;
1949     paa->n++;
1950 
1951     return 0;
1952 }
1953 
1954 
1955 /*!
1956  * \brief   pixaaExtendArray()
1957  *
1958  * \param[in]    paa
1959  * \return  0 if OK; 1 on error
1960  */
1961 l_int32
pixaaExtendArray(PIXAA * paa)1962 pixaaExtendArray(PIXAA  *paa)
1963 {
1964     PROCNAME("pixaaExtendArray");
1965 
1966     if (!paa)
1967         return ERROR_INT("paa not defined", procName, 1);
1968 
1969     if ((paa->pixa = (PIXA **)reallocNew((void **)&paa->pixa,
1970                              sizeof(PIXA *) * paa->nalloc,
1971                              2 * sizeof(PIXA *) * paa->nalloc)) == NULL)
1972         return ERROR_INT("new ptr array not returned", procName, 1);
1973 
1974     paa->nalloc = 2 * paa->nalloc;
1975     return 0;
1976 }
1977 
1978 
1979 /*!
1980  * \brief   pixaaAddPix()
1981  *
1982  * \param[in]    paa  input paa
1983  * \param[in]    index index of pixa in paa
1984  * \param[in]    pix to be added
1985  * \param[in]    box [optional] to be added
1986  * \param[in]    copyflag L_INSERT, L_COPY, L_CLONE
1987  * \return  0 if OK; 1 on error
1988  */
1989 l_int32
pixaaAddPix(PIXAA * paa,l_int32 index,PIX * pix,BOX * box,l_int32 copyflag)1990 pixaaAddPix(PIXAA   *paa,
1991             l_int32  index,
1992             PIX     *pix,
1993             BOX     *box,
1994             l_int32  copyflag)
1995 {
1996 PIXA  *pixa;
1997 
1998     PROCNAME("pixaaAddPix");
1999 
2000     if (!paa)
2001         return ERROR_INT("paa not defined", procName, 1);
2002     if (!pix)
2003         return ERROR_INT("pix not defined", procName, 1);
2004 
2005     if ((pixa = pixaaGetPixa(paa, index, L_CLONE)) == NULL)
2006         return ERROR_INT("pixa not found", procName, 1);
2007     pixaAddPix(pixa, pix, copyflag);
2008     if (box) pixaAddBox(pixa, box, copyflag);
2009     pixaDestroy(&pixa);
2010     return 0;
2011 }
2012 
2013 
2014 /*!
2015  * \brief   pixaaAddBox()
2016  *
2017  * \param[in]    paa
2018  * \param[in]    box
2019  * \param[in]    copyflag L_INSERT, L_COPY, L_CLONE
2020  * \return  0 if OK, 1 on error
2021  *
2022  * <pre>
2023  * Notes:
2024  *      (1) The box can be used, for example, to hold the support region
2025  *          of a pixa that is being added to the pixaa.
2026  * </pre>
2027  */
2028 l_int32
pixaaAddBox(PIXAA * paa,BOX * box,l_int32 copyflag)2029 pixaaAddBox(PIXAA   *paa,
2030             BOX     *box,
2031             l_int32  copyflag)
2032 {
2033     PROCNAME("pixaaAddBox");
2034 
2035     if (!paa)
2036         return ERROR_INT("paa not defined", procName, 1);
2037     if (!box)
2038         return ERROR_INT("box not defined", procName, 1);
2039     if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
2040         return ERROR_INT("invalid copyflag", procName, 1);
2041 
2042     boxaAddBox(paa->boxa, box, copyflag);
2043     return 0;
2044 }
2045 
2046 
2047 
2048 /*---------------------------------------------------------------------*
2049  *                            Pixaa accessors                          *
2050  *---------------------------------------------------------------------*/
2051 /*!
2052  * \brief   pixaaGetCount()
2053  *
2054  * \param[in]    paa
2055  * \param[out]   pna [optional] number of pix in each pixa
2056  * \return  count, or 0 if no pixaa
2057  *
2058  * <pre>
2059  * Notes:
2060  *      (1) If paa is empty, a returned na will also be empty.
2061  * </pre>
2062  */
2063 l_int32
pixaaGetCount(PIXAA * paa,NUMA ** pna)2064 pixaaGetCount(PIXAA  *paa,
2065               NUMA  **pna)
2066 {
2067 l_int32  i, n;
2068 NUMA    *na;
2069 PIXA    *pixa;
2070 
2071     PROCNAME("pixaaGetCount");
2072 
2073     if (pna) *pna = NULL;
2074     if (!paa)
2075         return ERROR_INT("paa not defined", procName, 0);
2076 
2077     n = paa->n;
2078     if (pna) {
2079         if ((na = numaCreate(n)) == NULL)
2080             return ERROR_INT("na not made", procName, 0);
2081         *pna = na;
2082         for (i = 0; i < n; i++) {
2083             pixa = pixaaGetPixa(paa, i, L_CLONE);
2084             numaAddNumber(na, pixaGetCount(pixa));
2085             pixaDestroy(&pixa);
2086         }
2087     }
2088     return n;
2089 }
2090 
2091 
2092 /*!
2093  * \brief   pixaaGetPixa()
2094  *
2095  * \param[in]    paa
2096  * \param[in]    index  to the index-th pixa
2097  * \param[in]    accesstype  L_COPY, L_CLONE, L_COPY_CLONE
2098  * \return  pixa, or NULL on error
2099  *
2100  * <pre>
2101  * Notes:
2102  *      (1) L_COPY makes a new pixa with a copy of every pix
2103  *      (2) L_CLONE just makes a new reference to the pixa,
2104  *          and bumps the counter.  You would use this, for example,
2105  *          when you need to extract some data from a pix within a
2106  *          pixa within a pixaa.
2107  *      (3) L_COPY_CLONE makes a new pixa with a clone of every pix
2108  *          and box
2109  *      (4) In all cases, you must invoke pixaDestroy() on the returned pixa
2110  * </pre>
2111  */
2112 PIXA *
pixaaGetPixa(PIXAA * paa,l_int32 index,l_int32 accesstype)2113 pixaaGetPixa(PIXAA   *paa,
2114              l_int32  index,
2115              l_int32  accesstype)
2116 {
2117 PIXA  *pixa;
2118 
2119     PROCNAME("pixaaGetPixa");
2120 
2121     if (!paa)
2122         return (PIXA *)ERROR_PTR("paa not defined", procName, NULL);
2123     if (index < 0 || index >= paa->n)
2124         return (PIXA *)ERROR_PTR("index not valid", procName, NULL);
2125     if (accesstype != L_COPY && accesstype != L_CLONE &&
2126         accesstype != L_COPY_CLONE)
2127         return (PIXA *)ERROR_PTR("invalid accesstype", procName, NULL);
2128 
2129     if ((pixa = paa->pixa[index]) == NULL) {  /* shouldn't happen! */
2130         L_ERROR("missing pixa[%d]\n", procName, index);
2131         return (PIXA *)ERROR_PTR("pixa not found at index", procName, NULL);
2132     }
2133     return pixaCopy(pixa, accesstype);
2134 }
2135 
2136 
2137 /*!
2138  * \brief   pixaaGetBoxa()
2139  *
2140  * \param[in]    paa
2141  * \param[in]    accesstype  L_COPY, L_CLONE
2142  * \return  boxa, or NULL on error
2143  *
2144  * <pre>
2145  * Notes:
2146  *      (1) L_COPY returns a copy; L_CLONE returns a new reference to the boxa.
2147  *      (2) In both cases, invoke boxaDestroy() on the returned boxa.
2148  * </pre>
2149  */
2150 BOXA *
pixaaGetBoxa(PIXAA * paa,l_int32 accesstype)2151 pixaaGetBoxa(PIXAA   *paa,
2152              l_int32  accesstype)
2153 {
2154     PROCNAME("pixaaGetBoxa");
2155 
2156     if (!paa)
2157         return (BOXA *)ERROR_PTR("paa not defined", procName, NULL);
2158     if (accesstype != L_COPY && accesstype != L_CLONE)
2159         return (BOXA *)ERROR_PTR("invalid access type", procName, NULL);
2160 
2161     return boxaCopy(paa->boxa, accesstype);
2162 }
2163 
2164 
2165 /*!
2166  * \brief   pixaaGetPix()
2167  *
2168  * \param[in]    paa
2169  * \param[in]    index  index into the pixa array in the pixaa
2170  * \param[in]    ipix  index into the pix array in the pixa
2171  * \param[in]    accessflag  L_COPY or L_CLONE
2172  * \return  pix, or NULL on error
2173  */
2174 PIX *
pixaaGetPix(PIXAA * paa,l_int32 index,l_int32 ipix,l_int32 accessflag)2175 pixaaGetPix(PIXAA   *paa,
2176             l_int32  index,
2177             l_int32  ipix,
2178             l_int32  accessflag)
2179 {
2180 PIX   *pix;
2181 PIXA  *pixa;
2182 
2183     PROCNAME("pixaaGetPix");
2184 
2185     if ((pixa = pixaaGetPixa(paa, index, L_CLONE)) == NULL)
2186         return (PIX *)ERROR_PTR("pixa not retrieved", procName, NULL);
2187     if ((pix = pixaGetPix(pixa, ipix, accessflag)) == NULL)
2188         L_ERROR("pix not retrieved\n", procName);
2189     pixaDestroy(&pixa);
2190     return pix;
2191 }
2192 
2193 
2194 /*!
2195  * \brief   pixaaVerifyDepth()
2196  *
2197  * \param[in]    paa
2198  * \param[out]   psame   1 if all pix have the same depth; 0 otherwise
2199  * \param[out]   pmaxd   [optional] max depth of all pix in pixaa
2200  * \return   0 if OK; 1 on error
2201  *
2202  * <pre>
2203  * Notes:
2204  *      (1) It is considered to be an error if any pixa have no pix.
2205  * </pre>
2206  */
2207 l_int32
pixaaVerifyDepth(PIXAA * paa,l_int32 * psame,l_int32 * pmaxd)2208 pixaaVerifyDepth(PIXAA    *paa,
2209                  l_int32  *psame,
2210                  l_int32  *pmaxd)
2211 {
2212 l_int32  i, n, d, maxd, same, samed;
2213 PIXA    *pixa;
2214 
2215     PROCNAME("pixaaVerifyDepth");
2216 
2217     if (pmaxd) *pmaxd = 0;
2218     if (!psame)
2219         return ERROR_INT("psame not defined", procName, 1);
2220     *psame = 0;
2221     if (!paa)
2222         return ERROR_INT("paa not defined", procName, 1);
2223     if ((n = pixaaGetCount(paa, NULL)) == 0)
2224         return ERROR_INT("no pixa in paa", procName, 1);
2225 
2226     pixa = pixaaGetPixa(paa, 0, L_CLONE);
2227     pixaVerifyDepth(pixa, &same, &maxd);  /* init same, maxd with first pixa */
2228     pixaDestroy(&pixa);
2229     for (i = 1; i < n; i++) {
2230         pixa = pixaaGetPixa(paa, i, L_CLONE);
2231         pixaVerifyDepth(pixa, &samed, &d);
2232         pixaDestroy(&pixa);
2233         maxd = L_MAX(maxd, d);
2234         if (!samed || maxd != d)
2235             same = 0;
2236     }
2237     *psame = same;
2238     if (pmaxd) *pmaxd = maxd;
2239     return 0;
2240 }
2241 
2242 
2243 /*!
2244  * \brief   pixaaVerifyDimensions()
2245  *
2246  * \param[in]    paa
2247  * \param[out]   psame   1 if all pix have the same depth; 0 otherwise
2248  * \param[out]   pmaxw   [optional] max width of all pix in pixaa
2249  * \param[out]   pmaxh   [optional] max height of all pix in pixaa
2250  * \return   0 if OK; 1 on error
2251  *
2252  * <pre>
2253  * Notes:
2254  *      (1) It is considered to be an error if any pixa have no pix.
2255  * </pre>
2256  */
2257 l_int32
pixaaVerifyDimensions(PIXAA * paa,l_int32 * psame,l_int32 * pmaxw,l_int32 * pmaxh)2258 pixaaVerifyDimensions(PIXAA    *paa,
2259                       l_int32  *psame,
2260                       l_int32  *pmaxw,
2261                       l_int32  *pmaxh)
2262 {
2263 l_int32  i, n, w, h, maxw, maxh, same, same2;
2264 PIXA    *pixa;
2265 
2266     PROCNAME("pixaaVerifyDimensions");
2267 
2268     if (pmaxw) *pmaxw = 0;
2269     if (pmaxh) *pmaxh = 0;
2270     if (!psame)
2271         return ERROR_INT("psame not defined", procName, 1);
2272     *psame = 0;
2273     if (!paa)
2274         return ERROR_INT("paa not defined", procName, 1);
2275     if ((n = pixaaGetCount(paa, NULL)) == 0)
2276         return ERROR_INT("no pixa in paa", procName, 1);
2277 
2278         /* Init same; init maxw and maxh from first pixa */
2279     pixa = pixaaGetPixa(paa, 0, L_CLONE);
2280     pixaVerifyDimensions(pixa, &same, &maxw, &maxh);
2281     pixaDestroy(&pixa);
2282 
2283     for (i = 1; i < n; i++) {
2284         pixa = pixaaGetPixa(paa, i, L_CLONE);
2285         pixaVerifyDimensions(pixa, &same2, &w, &h);
2286         pixaDestroy(&pixa);
2287         maxw = L_MAX(maxw, w);
2288         maxh = L_MAX(maxh, h);
2289         if (!same2 || maxw != w || maxh != h)
2290             same = 0;
2291     }
2292     *psame = same;
2293     if (pmaxw) *pmaxw = maxw;
2294     if (pmaxh) *pmaxh = maxh;
2295     return 0;
2296 }
2297 
2298 
2299 /*!
2300  * \brief   pixaaIsFull()
2301  *
2302  * \param[in]    paa
2303  * \param[out]   pfull 1 if all pixa in the paa have full pix arrays
2304  * \return  return 0 if OK, 1 on error
2305  *
2306  * <pre>
2307  * Notes:
2308  *      (1) Does not require boxa associated with each pixa to be full.
2309  * </pre>
2310  */
2311 l_int32
pixaaIsFull(PIXAA * paa,l_int32 * pfull)2312 pixaaIsFull(PIXAA    *paa,
2313             l_int32  *pfull)
2314 {
2315 l_int32  i, n, full;
2316 PIXA    *pixa;
2317 
2318     PROCNAME("pixaaIsFull");
2319 
2320     if (!pfull)
2321         return ERROR_INT("&full not defined", procName, 0);
2322     *pfull = 0;
2323     if (!paa)
2324         return ERROR_INT("paa not defined", procName, 0);
2325 
2326     n = pixaaGetCount(paa, NULL);
2327     full = 1;
2328     for (i = 0; i < n; i++) {
2329         pixa = pixaaGetPixa(paa, i, L_CLONE);
2330         pixaIsFull(pixa, &full, NULL);
2331         pixaDestroy(&pixa);
2332         if (!full) break;
2333     }
2334     *pfull = full;
2335     return 0;
2336 }
2337 
2338 
2339 /*---------------------------------------------------------------------*
2340  *                         Pixaa array modifiers                       *
2341  *---------------------------------------------------------------------*/
2342 /*!
2343  * \brief   pixaaInitFull()
2344  *
2345  * \param[in]    paa typically empty
2346  * \param[in]    pixa to be replicated into the entire pixa ptr array
2347  * \return  0 if OK, 1 on error
2348  *
2349  * <pre>
2350  * Notes:
2351  *      (1) This initializes a pixaa by filling up the entire pixa ptr array
2352  *          with copies of %pixa.  Any existing pixa are destroyed.
2353  *      (2) Example usage.  This function is useful to prepare for a
2354  *          random insertion (or replacement) of pixa into a pixaa.
2355  *          To randomly insert pixa into a pixaa, up to some index "max":
2356  *             Pixaa *paa = pixaaCreate(max);
2357  *             Pixa *pixa = pixaCreate(1);  // if you want little memory
2358  *             pixaaInitFull(paa, pixa);  // copy it to entire array
2359  *             pixaDestroy(&pixa);  // no longer needed
2360  *          The initialization allows the pixaa to always be properly filled.
2361  * </pre>
2362  */
2363 l_int32
pixaaInitFull(PIXAA * paa,PIXA * pixa)2364 pixaaInitFull(PIXAA  *paa,
2365               PIXA   *pixa)
2366 {
2367 l_int32  i, n;
2368 PIXA    *pixat;
2369 
2370     PROCNAME("pixaaInitFull");
2371 
2372     if (!paa)
2373         return ERROR_INT("paa not defined", procName, 1);
2374     if (!pixa)
2375         return ERROR_INT("pixa not defined", procName, 1);
2376 
2377     n = paa->nalloc;
2378     paa->n = n;
2379     for (i = 0; i < n; i++) {
2380         pixat = pixaCopy(pixa, L_COPY);
2381         pixaaReplacePixa(paa, i, pixat);
2382     }
2383 
2384     return 0;
2385 }
2386 
2387 
2388 /*!
2389  * \brief   pixaaReplacePixa()
2390  *
2391  * \param[in]    paa
2392  * \param[in]    index  to the index-th pixa
2393  * \param[in]    pixa insert to replace existing one
2394  * \return  0 if OK, 1 on error
2395  *
2396  * <pre>
2397  * Notes:
2398  *      (1) This allows random insertion of a pixa into a pixaa, with
2399  *          destruction of any existing pixa at that location.
2400  *          The input pixa is now owned by the pixaa.
2401  *      (2) No other pixa in the array are affected.
2402  *      (3) The index must be within the allowed set.
2403  * </pre>
2404  */
2405 l_int32
pixaaReplacePixa(PIXAA * paa,l_int32 index,PIXA * pixa)2406 pixaaReplacePixa(PIXAA   *paa,
2407                  l_int32  index,
2408                  PIXA    *pixa)
2409 {
2410 
2411     PROCNAME("pixaaReplacePixa");
2412 
2413     if (!paa)
2414         return ERROR_INT("paa not defined", procName, 1);
2415     if (index < 0 || index >= paa->n)
2416         return ERROR_INT("index not valid", procName, 1);
2417     if (!pixa)
2418         return ERROR_INT("pixa not defined", procName, 1);
2419 
2420     pixaDestroy(&(paa->pixa[index]));
2421     paa->pixa[index] = pixa;
2422     return 0;
2423 }
2424 
2425 
2426 /*!
2427  * \brief   pixaaClear()
2428  *
2429  * \param[in]    paa
2430  * \return  0 if OK, 1 on error
2431  *
2432  * <pre>
2433  * Notes:
2434  *      (1) This destroys all pixa in the pixaa, and nulls the ptrs
2435  *          in the pixa ptr array.
2436  * </pre>
2437  */
2438 l_int32
pixaaClear(PIXAA * paa)2439 pixaaClear(PIXAA  *paa)
2440 {
2441 l_int32  i, n;
2442 
2443     PROCNAME("pixaClear");
2444 
2445     if (!paa)
2446         return ERROR_INT("paa not defined", procName, 1);
2447 
2448     n = pixaaGetCount(paa, NULL);
2449     for (i = 0; i < n; i++)
2450         pixaDestroy(&paa->pixa[i]);
2451     paa->n = 0;
2452     return 0;
2453 }
2454 
2455 
2456 /*!
2457  * \brief   pixaaTruncate()
2458  *
2459  * \param[in]    paa
2460  * \return  0 if OK, 1 on error
2461  *
2462  * <pre>
2463  * Notes:
2464  *      (1) This identifies the largest index containing a pixa that
2465  *          has any pix within it, destroys all pixa above that index,
2466  *          and resets the count.
2467  * </pre>
2468  */
2469 l_int32
pixaaTruncate(PIXAA * paa)2470 pixaaTruncate(PIXAA  *paa)
2471 {
2472 l_int32  i, n, np;
2473 PIXA    *pixa;
2474 
2475     PROCNAME("pixaaTruncate");
2476 
2477     if (!paa)
2478         return ERROR_INT("paa not defined", procName, 1);
2479 
2480     n = pixaaGetCount(paa, NULL);
2481     for (i = n - 1; i >= 0; i--) {
2482         pixa = pixaaGetPixa(paa, i, L_CLONE);
2483         if (!pixa) {
2484             paa->n--;
2485             continue;
2486         }
2487         np = pixaGetCount(pixa);
2488         pixaDestroy(&pixa);
2489         if (np == 0) {
2490             pixaDestroy(&paa->pixa[i]);
2491             paa->n--;
2492         } else {
2493             break;
2494         }
2495     }
2496     return 0;
2497 }
2498 
2499 
2500 
2501 /*---------------------------------------------------------------------*
2502  *                          Pixa serialized I/O                        *
2503  *---------------------------------------------------------------------*/
2504 /*!
2505  * \brief   pixaRead()
2506  *
2507  * \param[in]    filename
2508  * \return  pixa, or NULL on error
2509  *
2510  * <pre>
2511  * Notes:
2512  *      (1) The pix are stored in the file as png.
2513  *          If the png library is not linked, this will fail.
2514  * </pre>
2515  */
2516 PIXA *
pixaRead(const char * filename)2517 pixaRead(const char  *filename)
2518 {
2519 FILE  *fp;
2520 PIXA  *pixa;
2521 
2522     PROCNAME("pixaRead");
2523 
2524 #if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2525     return (PIXA *)ERROR_PTR("no libpng: can't read data", procName, NULL);
2526 #endif  /* !HAVE_LIBPNG */
2527 
2528     if (!filename)
2529         return (PIXA *)ERROR_PTR("filename not defined", procName, NULL);
2530 
2531     if ((fp = fopenReadStream(filename)) == NULL)
2532         return (PIXA *)ERROR_PTR("stream not opened", procName, NULL);
2533     pixa = pixaReadStream(fp);
2534     fclose(fp);
2535     if (!pixa)
2536         return (PIXA *)ERROR_PTR("pixa not read", procName, NULL);
2537     return pixa;
2538 }
2539 
2540 
2541 /*!
2542  * \brief   pixaReadStream()
2543  *
2544  * \param[in]    fp file stream
2545  * \return  pixa, or NULL on error
2546  *
2547  * <pre>
2548  * Notes:
2549  *      (1) The pix are stored in the file as png.
2550  *          If the png library is not linked, this will fail.
2551  * </pre>
2552  */
2553 PIXA *
pixaReadStream(FILE * fp)2554 pixaReadStream(FILE  *fp)
2555 {
2556 l_int32  n, i, xres, yres, version;
2557 l_int32  ignore;
2558 BOXA    *boxa;
2559 PIX     *pix;
2560 PIXA    *pixa;
2561 
2562     PROCNAME("pixaReadStream");
2563 
2564 #if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2565     return (PIXA *)ERROR_PTR("no libpng: can't read data", procName, NULL);
2566 #endif  /* !HAVE_LIBPNG */
2567 
2568     if (!fp)
2569         return (PIXA *)ERROR_PTR("stream not defined", procName, NULL);
2570 
2571     if (fscanf(fp, "\nPixa Version %d\n", &version) != 1)
2572         return (PIXA *)ERROR_PTR("not a pixa file", procName, NULL);
2573     if (version != PIXA_VERSION_NUMBER)
2574         return (PIXA *)ERROR_PTR("invalid pixa version", procName, NULL);
2575     if (fscanf(fp, "Number of pix = %d\n", &n) != 1)
2576         return (PIXA *)ERROR_PTR("not a pixa file", procName, NULL);
2577 
2578     if ((boxa = boxaReadStream(fp)) == NULL)
2579         return (PIXA *)ERROR_PTR("boxa not made", procName, NULL);
2580     if ((pixa = pixaCreate(n)) == NULL) {
2581         boxaDestroy(&boxa);
2582         return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
2583     }
2584     boxaDestroy(&pixa->boxa);
2585     pixa->boxa = boxa;
2586 
2587     for (i = 0; i < n; i++) {
2588         if ((fscanf(fp, " pix[%d]: xres = %d, yres = %d\n",
2589               &ignore, &xres, &yres)) != 3) {
2590             pixaDestroy(&pixa);
2591             return (PIXA *)ERROR_PTR("res reading error", procName, NULL);
2592         }
2593         if ((pix = pixReadStreamPng(fp)) == NULL) {
2594             pixaDestroy(&pixa);
2595             return (PIXA *)ERROR_PTR("pix not read", procName, NULL);
2596         }
2597         pixSetXRes(pix, xres);
2598         pixSetYRes(pix, yres);
2599         pixaAddPix(pixa, pix, L_INSERT);
2600     }
2601     return pixa;
2602 }
2603 
2604 
2605 /*!
2606  * \brief   pixaReadMem()
2607  *
2608  * \param[in]    data  of serialized pixa
2609  * \param[in]    size  of data in bytes
2610  * \return  pixa, or NULL on error
2611  */
2612 PIXA *
pixaReadMem(const l_uint8 * data,size_t size)2613 pixaReadMem(const l_uint8  *data,
2614             size_t          size)
2615 {
2616 FILE  *fp;
2617 PIXA  *pixa;
2618 
2619     PROCNAME("pixaReadMem");
2620 
2621     if (!data)
2622         return (PIXA *)ERROR_PTR("data not defined", procName, NULL);
2623     if ((fp = fopenReadFromMemory(data, size)) == NULL)
2624         return (PIXA *)ERROR_PTR("stream not opened", procName, NULL);
2625 
2626     pixa = pixaReadStream(fp);
2627     fclose(fp);
2628     if (!pixa) L_ERROR("pixa not read\n", procName);
2629     return pixa;
2630 }
2631 
2632 
2633 /*!
2634  * \brief   pixaWriteDebug()
2635  *
2636  * \param[in]    fname
2637  * \param[in]    pixa
2638  * \return  0 if OK; 1 on error
2639  *
2640  * <pre>
2641  * Notes:
2642  *      (1) Debug version, intended for use in the library when writing
2643  *          to files in a temp directory with names that are compiled in.
2644  *          This is used instead of pixaWrite() for all such library calls.
2645  *      (2) The global variable LeptDebugOK defaults to 0, and can be set
2646  *          or cleared by the function setLeptDebugOK().
2647  * </pre>
2648  */
2649 l_int32
pixaWriteDebug(const char * fname,PIXA * pixa)2650 pixaWriteDebug(const char  *fname,
2651                PIXA        *pixa)
2652 {
2653     PROCNAME("pixaWriteDebug");
2654 
2655     if (LeptDebugOK) {
2656         return pixaWrite(fname, pixa);
2657     } else {
2658         L_INFO("write to named temp file %s is disabled\n", procName, fname);
2659         return 0;
2660     }
2661 }
2662 
2663 
2664 /*!
2665  * \brief   pixaWrite()
2666  *
2667  * \param[in]    filename
2668  * \param[in]    pixa
2669  * \return  0 if OK, 1 on error
2670  *
2671  * <pre>
2672  * Notes:
2673  *      (1) The pix are stored in the file as png.
2674  *          If the png library is not linked, this will fail.
2675  * </pre>
2676  */
2677 l_int32
pixaWrite(const char * filename,PIXA * pixa)2678 pixaWrite(const char  *filename,
2679           PIXA        *pixa)
2680 {
2681 l_int32  ret;
2682 FILE    *fp;
2683 
2684     PROCNAME("pixaWrite");
2685 
2686 #if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2687     return ERROR_INT("no libpng: can't write data", procName, 1);
2688 #endif  /* !HAVE_LIBPNG */
2689 
2690     if (!filename)
2691         return ERROR_INT("filename not defined", procName, 1);
2692     if (!pixa)
2693         return ERROR_INT("pixa not defined", procName, 1);
2694 
2695     if ((fp = fopenWriteStream(filename, "wb")) == NULL)
2696         return ERROR_INT("stream not opened", procName, 1);
2697     ret = pixaWriteStream(fp, pixa);
2698     fclose(fp);
2699     if (ret)
2700         return ERROR_INT("pixa not written to stream", procName, 1);
2701     return 0;
2702 }
2703 
2704 
2705 /*!
2706  * \brief   pixaWriteStream()
2707  *
2708  * \param[in]    fp file stream opened for "wb"
2709  * \param[in]    pixa
2710  * \return  0 if OK, 1 on error
2711  *
2712  * <pre>
2713  * Notes:
2714  *      (1) The pix are stored in the file as png.
2715  *          If the png library is not linked, this will fail.
2716  * </pre>
2717  */
2718 l_int32
pixaWriteStream(FILE * fp,PIXA * pixa)2719 pixaWriteStream(FILE  *fp,
2720                 PIXA  *pixa)
2721 {
2722 l_int32  n, i;
2723 PIX     *pix;
2724 
2725     PROCNAME("pixaWriteStream");
2726 
2727 #if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2728     return ERROR_INT("no libpng: can't write data", procName, 1);
2729 #endif  /* !HAVE_LIBPNG */
2730 
2731     if (!fp)
2732         return ERROR_INT("stream not defined", procName, 1);
2733     if (!pixa)
2734         return ERROR_INT("pixa not defined", procName, 1);
2735 
2736     n = pixaGetCount(pixa);
2737     fprintf(fp, "\nPixa Version %d\n", PIXA_VERSION_NUMBER);
2738     fprintf(fp, "Number of pix = %d\n", n);
2739     boxaWriteStream(fp, pixa->boxa);
2740     for (i = 0; i < n; i++) {
2741         if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
2742             return ERROR_INT("pix not found", procName, 1);
2743         fprintf(fp, " pix[%d]: xres = %d, yres = %d\n",
2744                 i, pix->xres, pix->yres);
2745         pixWriteStreamPng(fp, pix, 0.0);
2746         pixDestroy(&pix);
2747     }
2748     return 0;
2749 }
2750 
2751 
2752 /*!
2753  * \brief   pixaWriteMem()
2754  *
2755  * \param[out]   pdata data of serialized pixa
2756  * \param[out]   psize size of returned data
2757  * \param[in]    pixa
2758  * \return  0 if OK, 1 on error
2759  *
2760  * <pre>
2761  * Notes:
2762  *      (1) Serializes a pixa in memory and puts the result in a buffer.
2763  * </pre>
2764  */
2765 l_int32
pixaWriteMem(l_uint8 ** pdata,size_t * psize,PIXA * pixa)2766 pixaWriteMem(l_uint8  **pdata,
2767              size_t    *psize,
2768              PIXA      *pixa)
2769 {
2770 l_int32  ret;
2771 FILE    *fp;
2772 
2773     PROCNAME("pixaWriteMem");
2774 
2775     if (pdata) *pdata = NULL;
2776     if (psize) *psize = 0;
2777     if (!pdata)
2778         return ERROR_INT("&data not defined", procName, 1);
2779     if (!psize)
2780         return ERROR_INT("&size not defined", procName, 1);
2781     if (!pixa)
2782         return ERROR_INT("pixa not defined", procName, 1);
2783 
2784 #if HAVE_FMEMOPEN
2785     if ((fp = open_memstream((char **)pdata, psize)) == NULL)
2786         return ERROR_INT("stream not opened", procName, 1);
2787     ret = pixaWriteStream(fp, pixa);
2788 #else
2789     L_INFO("work-around: writing to a temp file\n", procName);
2790   #ifdef _WIN32
2791     if ((fp = fopenWriteWinTempfile()) == NULL)
2792         return ERROR_INT("tmpfile stream not opened", procName, 1);
2793   #else
2794     if ((fp = tmpfile()) == NULL)
2795         return ERROR_INT("tmpfile stream not opened", procName, 1);
2796   #endif  /* _WIN32 */
2797     ret = pixaWriteStream(fp, pixa);
2798     rewind(fp);
2799     *pdata = l_binaryReadStream(fp, psize);
2800 #endif  /* HAVE_FMEMOPEN */
2801     fclose(fp);
2802     return ret;
2803 }
2804 
2805 
2806 /*!
2807  * \brief   pixaReadBoth()
2808  *
2809  * \param[in]    filename
2810  * \return  pixa, or NULL on error
2811  *
2812  * <pre>
2813  * Notes:
2814  *      (1) This reads serialized files of either a pixa or a pixacomp,
2815  *          and returns a pixa in memory.  It requires png and jpeg libraries.
2816  * </pre>
2817  */
2818 PIXA *
pixaReadBoth(const char * filename)2819 pixaReadBoth(const char  *filename)
2820 {
2821 char    buf[32];
2822 char   *sname;
2823 PIXA   *pixa;
2824 PIXAC  *pac;
2825 
2826     PROCNAME("pixaReadBoth");
2827 
2828     if (!filename)
2829         return (PIXA *)ERROR_PTR("filename not defined", procName, NULL);
2830 
2831     l_getStructStrFromFile(filename, L_STR_NAME, &sname);
2832     if (!sname)
2833         return (PIXA *)ERROR_PTR("struct name not found", procName, NULL);
2834     snprintf(buf, sizeof(buf), "%s", sname);
2835     LEPT_FREE(sname);
2836 
2837     if (strcmp(buf, "Pixacomp") == 0) {
2838         if ((pac = pixacompRead(filename)) == NULL)
2839             return (PIXA *)ERROR_PTR("pac not made", procName, NULL);
2840         pixa = pixaCreateFromPixacomp(pac, L_COPY);
2841         pixacompDestroy(&pac);
2842     } else if (strcmp(buf, "Pixa") == 0) {
2843         if ((pixa = pixaRead(filename)) == NULL)
2844             return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
2845     } else {
2846         return (PIXA *)ERROR_PTR("invalid file type", procName, NULL);
2847     }
2848     return pixa;
2849 }
2850 
2851 
2852 /*---------------------------------------------------------------------*
2853  *                         Pixaa serialized I/O                        *
2854  *---------------------------------------------------------------------*/
2855 /*!
2856  * \brief   pixaaReadFromFiles()
2857  *
2858  * \param[in]    dirname directory
2859  * \param[in]    substr [optional] substring filter on filenames; can be NULL
2860  * \param[in]    first 0-based
2861  * \param[in]    nfiles use 0 for everything from %first to the end
2862  * \return  paa, or NULL on error or if no pixa files are found.
2863  *
2864  * <pre>
2865  * Notes:
2866  *      (1) The files must be serialized pixa files (e.g., *.pa)
2867  *          If some files cannot be read, warnings are issued.
2868  *      (2) Use %substr to filter filenames in the directory.  If
2869  *          %substr == NULL, this takes all files.
2870  *      (3) After filtering, use %first and %nfiles to select
2871  *          a contiguous set of files, that have been lexically
2872  *          sorted in increasing order.
2873  * </pre>
2874  */
2875 PIXAA *
pixaaReadFromFiles(const char * dirname,const char * substr,l_int32 first,l_int32 nfiles)2876 pixaaReadFromFiles(const char  *dirname,
2877                    const char  *substr,
2878                    l_int32      first,
2879                    l_int32      nfiles)
2880 {
2881 char    *fname;
2882 l_int32  i, n;
2883 PIXA    *pixa;
2884 PIXAA   *paa;
2885 SARRAY  *sa;
2886 
2887   PROCNAME("pixaaReadFromFiles");
2888 
2889   if (!dirname)
2890       return (PIXAA *)ERROR_PTR("dirname not defined", procName, NULL);
2891 
2892   sa = getSortedPathnamesInDirectory(dirname, substr, first, nfiles);
2893   if (!sa || ((n = sarrayGetCount(sa)) == 0)) {
2894       sarrayDestroy(&sa);
2895       return (PIXAA *)ERROR_PTR("no pixa files found", procName, NULL);
2896   }
2897 
2898   paa = pixaaCreate(n);
2899   for (i = 0; i < n; i++) {
2900       fname = sarrayGetString(sa, i, L_NOCOPY);
2901       if ((pixa = pixaRead(fname)) == NULL) {
2902           L_ERROR("pixa not read for %d-th file", procName, i);
2903           continue;
2904       }
2905       pixaaAddPixa(paa, pixa, L_INSERT);
2906   }
2907 
2908   sarrayDestroy(&sa);
2909   return paa;
2910 }
2911 
2912 
2913 /*!
2914  * \brief   pixaaRead()
2915  *
2916  * \param[in]    filename
2917  * \return  paa, or NULL on error
2918  *
2919  * <pre>
2920  * Notes:
2921  *      (1) The pix are stored in the file as png.
2922  *          If the png library is not linked, this will fail.
2923  * </pre>
2924  */
2925 PIXAA *
pixaaRead(const char * filename)2926 pixaaRead(const char  *filename)
2927 {
2928 FILE   *fp;
2929 PIXAA  *paa;
2930 
2931     PROCNAME("pixaaRead");
2932 
2933 #if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2934     return (PIXAA *)ERROR_PTR("no libpng: can't read data", procName, NULL);
2935 #endif  /* !HAVE_LIBPNG */
2936 
2937     if (!filename)
2938         return (PIXAA *)ERROR_PTR("filename not defined", procName, NULL);
2939 
2940     if ((fp = fopenReadStream(filename)) == NULL)
2941         return (PIXAA *)ERROR_PTR("stream not opened", procName, NULL);
2942     paa = pixaaReadStream(fp);
2943     fclose(fp);
2944     if (!paa)
2945         return (PIXAA *)ERROR_PTR("paa not read", procName, NULL);
2946     return paa;
2947 }
2948 
2949 
2950 /*!
2951  * \brief   pixaaReadStream()
2952  *
2953  * \param[in]    fp file stream
2954  * \return  paa, or NULL on error
2955  *
2956  * <pre>
2957  * Notes:
2958  *      (1) The pix are stored in the file as png.
2959  *          If the png library is not linked, this will fail.
2960  * </pre>
2961  */
2962 PIXAA *
pixaaReadStream(FILE * fp)2963 pixaaReadStream(FILE  *fp)
2964 {
2965 l_int32  n, i, version;
2966 l_int32  ignore;
2967 BOXA    *boxa;
2968 PIXA    *pixa;
2969 PIXAA   *paa;
2970 
2971     PROCNAME("pixaaReadStream");
2972 
2973 #if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2974     return (PIXAA *)ERROR_PTR("no libpng: can't read data", procName, NULL);
2975 #endif  /* !HAVE_LIBPNG */
2976 
2977     if (!fp)
2978         return (PIXAA *)ERROR_PTR("stream not defined", procName, NULL);
2979 
2980     if (fscanf(fp, "\nPixaa Version %d\n", &version) != 1)
2981         return (PIXAA *)ERROR_PTR("not a pixaa file", procName, NULL);
2982     if (version != PIXAA_VERSION_NUMBER)
2983         return (PIXAA *)ERROR_PTR("invalid pixaa version", procName, NULL);
2984     if (fscanf(fp, "Number of pixa = %d\n", &n) != 1)
2985         return (PIXAA *)ERROR_PTR("not a pixaa file", procName, NULL);
2986 
2987     if ((paa = pixaaCreate(n)) == NULL)
2988         return (PIXAA *)ERROR_PTR("paa not made", procName, NULL);
2989     if ((boxa = boxaReadStream(fp)) == NULL) {
2990         pixaaDestroy(&paa);
2991         return (PIXAA *)ERROR_PTR("boxa not made", procName, NULL);
2992     }
2993     boxaDestroy(&paa->boxa);
2994     paa->boxa = boxa;
2995 
2996     for (i = 0; i < n; i++) {
2997         if ((fscanf(fp, "\n\n --------------- pixa[%d] ---------------\n",
2998                     &ignore)) != 1) {
2999             pixaaDestroy(&paa);
3000             return (PIXAA *)ERROR_PTR("text reading", procName, NULL);
3001         }
3002         if ((pixa = pixaReadStream(fp)) == NULL) {
3003             pixaaDestroy(&paa);
3004             return (PIXAA *)ERROR_PTR("pixa not read", procName, NULL);
3005         }
3006         pixaaAddPixa(paa, pixa, L_INSERT);
3007     }
3008 
3009     return paa;
3010 }
3011 
3012 
3013 /*!
3014  * \brief   pixaaReadMem()
3015  *
3016  * \param[in]    data  of serialized pixaa
3017  * \param[in]    size  of data in bytes
3018  * \return  paa, or NULL on error
3019  */
3020 PIXAA *
pixaaReadMem(const l_uint8 * data,size_t size)3021 pixaaReadMem(const l_uint8  *data,
3022              size_t          size)
3023 {
3024 FILE   *fp;
3025 PIXAA  *paa;
3026 
3027     PROCNAME("paaReadMem");
3028 
3029     if (!data)
3030         return (PIXAA *)ERROR_PTR("data not defined", procName, NULL);
3031     if ((fp = fopenReadFromMemory(data, size)) == NULL)
3032         return (PIXAA *)ERROR_PTR("stream not opened", procName, NULL);
3033 
3034     paa = pixaaReadStream(fp);
3035     fclose(fp);
3036     if (!paa) L_ERROR("paa not read\n", procName);
3037     return paa;
3038 }
3039 
3040 
3041 /*!
3042  * \brief   pixaaWrite()
3043  *
3044  * \param[in]    filename
3045  * \param[in]    paa
3046  * \return  0 if OK, 1 on error
3047  *
3048  * <pre>
3049  * Notes:
3050  *      (1) The pix are stored in the file as png.
3051  *          If the png library is not linked, this will fail.
3052  * </pre>
3053  */
3054 l_int32
pixaaWrite(const char * filename,PIXAA * paa)3055 pixaaWrite(const char  *filename,
3056            PIXAA       *paa)
3057 {
3058 l_int32  ret;
3059 FILE    *fp;
3060 
3061     PROCNAME("pixaaWrite");
3062 
3063 #if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
3064     return ERROR_INT("no libpng: can't read data", procName, 1);
3065 #endif  /* !HAVE_LIBPNG */
3066 
3067     if (!filename)
3068         return ERROR_INT("filename not defined", procName, 1);
3069     if (!paa)
3070         return ERROR_INT("paa not defined", procName, 1);
3071 
3072     if ((fp = fopenWriteStream(filename, "wb")) == NULL)
3073         return ERROR_INT("stream not opened", procName, 1);
3074     ret = pixaaWriteStream(fp, paa);
3075     fclose(fp);
3076     if (ret)
3077         return ERROR_INT("paa not written to stream", procName, 1);
3078     return 0;
3079 }
3080 
3081 
3082 /*!
3083  * \brief   pixaaWriteStream()
3084  *
3085  * \param[in]    fp file stream opened for "wb"
3086  * \param[in]    paa
3087  * \return  0 if OK, 1 on error
3088  *
3089  * <pre>
3090  * Notes:
3091  *      (1) The pix are stored in the file as png.
3092  *          If the png library is not linked, this will fail.
3093  * </pre>
3094  */
3095 l_int32
pixaaWriteStream(FILE * fp,PIXAA * paa)3096 pixaaWriteStream(FILE   *fp,
3097                  PIXAA  *paa)
3098 {
3099 l_int32  n, i;
3100 PIXA    *pixa;
3101 
3102     PROCNAME("pixaaWriteStream");
3103 
3104 #if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
3105     return ERROR_INT("no libpng: can't read data", procName, 1);
3106 #endif  /* !HAVE_LIBPNG */
3107 
3108     if (!fp)
3109         return ERROR_INT("stream not defined", procName, 1);
3110     if (!paa)
3111         return ERROR_INT("paa not defined", procName, 1);
3112 
3113     n = pixaaGetCount(paa, NULL);
3114     fprintf(fp, "\nPixaa Version %d\n", PIXAA_VERSION_NUMBER);
3115     fprintf(fp, "Number of pixa = %d\n", n);
3116     boxaWriteStream(fp, paa->boxa);
3117     for (i = 0; i < n; i++) {
3118         if ((pixa = pixaaGetPixa(paa, i, L_CLONE)) == NULL)
3119             return ERROR_INT("pixa not found", procName, 1);
3120         fprintf(fp, "\n\n --------------- pixa[%d] ---------------\n", i);
3121         pixaWriteStream(fp, pixa);
3122         pixaDestroy(&pixa);
3123     }
3124     return 0;
3125 }
3126 
3127 
3128 /*!
3129  * \brief   pixaaWriteMem()
3130  *
3131  * \param[out]   pdata data of serialized pixaa
3132  * \param[out]   psize size of returned data
3133  * \param[in]    paa
3134  * \return  0 if OK, 1 on error
3135  *
3136  * <pre>
3137  * Notes:
3138  *      (1) Serializes a pixaa in memory and puts the result in a buffer.
3139  * </pre>
3140  */
3141 l_int32
pixaaWriteMem(l_uint8 ** pdata,size_t * psize,PIXAA * paa)3142 pixaaWriteMem(l_uint8  **pdata,
3143               size_t    *psize,
3144               PIXAA     *paa)
3145 {
3146 l_int32  ret;
3147 FILE    *fp;
3148 
3149     PROCNAME("pixaaWriteMem");
3150 
3151     if (pdata) *pdata = NULL;
3152     if (psize) *psize = 0;
3153     if (!pdata)
3154         return ERROR_INT("&data not defined", procName, 1);
3155     if (!psize)
3156         return ERROR_INT("&size not defined", procName, 1);
3157     if (!paa)
3158         return ERROR_INT("paa not defined", procName, 1);
3159 
3160 #if HAVE_FMEMOPEN
3161     if ((fp = open_memstream((char **)pdata, psize)) == NULL)
3162         return ERROR_INT("stream not opened", procName, 1);
3163     ret = pixaaWriteStream(fp, paa);
3164 #else
3165     L_INFO("work-around: writing to a temp file\n", procName);
3166   #ifdef _WIN32
3167     if ((fp = fopenWriteWinTempfile()) == NULL)
3168         return ERROR_INT("tmpfile stream not opened", procName, 1);
3169   #else
3170     if ((fp = tmpfile()) == NULL)
3171         return ERROR_INT("tmpfile stream not opened", procName, 1);
3172   #endif  /* _WIN32 */
3173     ret = pixaaWriteStream(fp, paa);
3174     rewind(fp);
3175     *pdata = l_binaryReadStream(fp, psize);
3176 #endif  /* HAVE_FMEMOPEN */
3177     fclose(fp);
3178     return ret;
3179 }
3180 
3181