Coverage Report

Created: 2024-06-18 06:05

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