Coverage Report

Created: 2025-06-13 06:48

/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 = 5000000;
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
0
{
169
0
PIXA  *pixa;
170
171
0
    if (n <= 0 || n > MaxInitPtrArraySize)
172
0
        n = InitialPtrArraySize;
173
174
0
    pixa = (PIXA *)LEPT_CALLOC(1, sizeof(PIXA));
175
0
    pixa->n = 0;
176
0
    pixa->nalloc = n;
177
0
    pixa->refcount = 1;
178
0
    pixa->pix = (PIX **)LEPT_CALLOC(n, sizeof(PIX *));
179
0
    pixa->boxa = boxaCreate(n);
180
0
    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
0
    return pixa;
185
0
}
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
0
{
406
0
l_int32  i;
407
0
PIXA    *pixa;
408
409
0
    if (ppixa == NULL) {
410
0
        L_WARNING("ptr address is NULL!\n", __func__);
411
0
        return;
412
0
    }
413
414
0
    if ((pixa = *ppixa) == NULL)
415
0
        return;
416
417
        /* Decrement the refcount.  If it is 0, destroy the pixa. */
418
0
    if (--pixa->refcount == 0) {
419
0
        for (i = 0; i < pixa->n; i++)
420
0
            pixDestroy(&pixa->pix[i]);
421
0
        LEPT_FREE(pixa->pix);
422
0
        boxaDestroy(&pixa->boxa);
423
0
        LEPT_FREE(pixa);
424
0
    }
425
426
0
    *ppixa = NULL;
427
0
}
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
0
{
497
0
l_int32  n;
498
0
PIX     *pixc;
499
500
0
    if (!pixa)
501
0
        return ERROR_INT("pixa not defined", __func__, 1);
502
0
    if (!pix)
503
0
        return ERROR_INT("pix not defined", __func__, 1);
504
505
0
    if (copyflag == L_INSERT)
506
0
        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
0
    if (!pixc)
514
0
        return ERROR_INT("pixc not made", __func__, 1);
515
516
0
    n = pixaGetCount(pixa);
517
0
    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
0
    pixa->pix[n] = pixc;
526
0
    pixa->n++;
527
0
    return 0;
528
0
}
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
0
{
631
0
    if (!pixa)
632
0
        return ERROR_INT("pixa not defined", __func__, 0);
633
634
0
    return pixa->n;
635
0
}
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
0
{
651
0
PIX  *pix;
652
653
0
    if (!pixa)
654
0
        return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
655
0
    if (index < 0 || index >= pixa->n)
656
0
        return (PIX *)ERROR_PTR("index not valid", __func__, NULL);
657
0
    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
0
    if (accesstype == L_COPY)
663
0
        return pixCopy(NULL, pix);
664
0
    else if (accesstype == L_CLONE)
665
0
        return pixClone(pix);
666
0
    else
667
0
        return (PIX *)ERROR_PTR("invalid accesstype", __func__, NULL);
668
0
}
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
0
{
686
0
PIX  *pix;
687
688
0
    if (pw) *pw = 0;
689
0
    if (ph) *ph = 0;
690
0
    if (pd) *pd = 0;
691
0
    if (!pixa)
692
0
        return ERROR_INT("pixa not defined", __func__, 1);
693
0
    if (index < 0 || index >= pixa->n)
694
0
        return ERROR_INT("index not valid", __func__, 1);
695
696
0
    if ((pix = pixaGetPix(pixa, index, L_CLONE)) == NULL)
697
0
        return ERROR_INT("pix not found!", __func__, 1);
698
0
    pixGetDimensions(pix, pw, ph, pd);
699
0
    pixDestroy(&pix);
700
0
    return 0;
701
0
}
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
0
{
904
0
l_int32  i, n, d, maxd, same;
905
906
0
    if (pmaxd) *pmaxd = 0;
907
0
    if (!psame)
908
0
        return ERROR_INT("psame not defined", __func__, 1);
909
0
    if (!pixa)
910
0
        return ERROR_INT("pixa not defined", __func__, 1);
911
0
    if ((n = pixaGetCount(pixa)) == 0)
912
0
        return ERROR_INT("no pix in pixa", __func__, 1);
913
914
0
    same = 1;
915
0
    pixaGetPixDimensions(pixa, 0, NULL, NULL, &maxd);
916
0
    for (i = 1; i < n; i++) {
917
0
        if (pixaGetPixDimensions(pixa, i, NULL, NULL, &d))
918
0
            return ERROR_INT("pix depth not found", __func__, 1);
919
0
        maxd = L_MAX(maxd, d);
920
0
        if (d != maxd)
921
0
            same = 0;
922
0
    }
923
0
    *psame = same;
924
0
    if (pmaxd) *pmaxd = maxd;
925
0
    return 0;
926
0
}
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
0
{
1147
0
l_int32  i, n, same;
1148
0
void   **lineptrs;
1149
0
void  ***lineset;
1150
0
PIX     *pix;
1151
1152
0
    if (psize) *psize = 0;
1153
0
    if (!pixa)
1154
0
        return (void ***)ERROR_PTR("pixa not defined", __func__, NULL);
1155
0
    pixaVerifyDepth(pixa, &same, NULL);
1156
0
    if (!same)
1157
0
        return (void ***)ERROR_PTR("pixa not all same depth", __func__, NULL);
1158
0
    n = pixaGetCount(pixa);
1159
0
    if (psize) *psize = n;
1160
0
    if ((lineset = (void ***)LEPT_CALLOC(n, sizeof(void **))) == NULL)
1161
0
        return (void ***)ERROR_PTR("lineset not made", __func__, NULL);
1162
0
    for (i = 0; i < n; i++) {
1163
0
        pix = pixaGetPix(pixa, i, L_CLONE);
1164
0
        lineptrs = pixGetLinePtrs(pix, NULL);
1165
0
        lineset[i] = lineptrs;
1166
0
        pixDestroy(&pix);
1167
0
    }
1168
1169
0
    return lineset;
1170
0
}
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 5M.  The reason it is so large
1943
 *          is that some applications, like jbig2enc, can create a very
1944
 *          large array of Pixa, each representing a character class
1945
 *          that contains one or a few tiny bitmaps.
1946
 * </pre>
1947
 */
1948
static l_int32
1949
pixaaExtendArray(PIXAA  *paa)
1950
0
{
1951
0
size_t  oldsize, newsize;
1952
1953
0
    if (!paa)
1954
0
        return ERROR_INT("paa not defined", __func__, 1);
1955
0
    if (paa->nalloc > MaxPixaaPtrArraySize)  /* belt & suspenders */
1956
0
        return ERROR_INT("paa has too many ptrs", __func__, 1);
1957
0
    oldsize = paa->nalloc * sizeof(PIXA *);
1958
0
    newsize = 2 * oldsize;
1959
0
    if (newsize > 8 * MaxPixaaPtrArraySize) {
1960
0
        L_ERROR("newsize = %zu > 40 MB; too large\n", __func__, newsize);
1961
0
        return 1;
1962
0
    }
1963
0
    if ((paa->pixa = (PIXA **)reallocNew((void **)&paa->pixa,
1964
0
                                         oldsize, newsize)) == NULL)
1965
0
        return ERROR_INT("new ptr array not returned", __func__, 1);
1966
1967
0
    paa->nalloc *= 2;
1968
0
    return 0;
1969
0
}
1970
1971
1972
/*!
1973
 * \brief   pixaaAddPix()
1974
 *
1975
 * \param[in]    paa        input paa
1976
 * \param[in]    index      index of pixa in paa
1977
 * \param[in]    pix        to be added
1978
 * \param[in]    box        [optional] to be added
1979
 * \param[in]    copyflag   L_INSERT, L_COPY, L_CLONE
1980
 * \return  0 if OK; 1 on error
1981
 */
1982
l_ok
1983
pixaaAddPix(PIXAA   *paa,
1984
            l_int32  index,
1985
            PIX     *pix,
1986
            BOX     *box,
1987
            l_int32  copyflag)
1988
0
{
1989
0
PIXA  *pixa;
1990
1991
0
    if (!paa)
1992
0
        return ERROR_INT("paa not defined", __func__, 1);
1993
0
    if (!pix)
1994
0
        return ERROR_INT("pix not defined", __func__, 1);
1995
1996
0
    if ((pixa = pixaaGetPixa(paa, index, L_CLONE)) == NULL)
1997
0
        return ERROR_INT("pixa not found", __func__, 1);
1998
0
    pixaAddPix(pixa, pix, copyflag);
1999
0
    if (box) pixaAddBox(pixa, box, copyflag);
2000
0
    pixaDestroy(&pixa);
2001
0
    return 0;
2002
0
}
2003
2004
2005
/*!
2006
 * \brief   pixaaAddBox()
2007
 *
2008
 * \param[in]    paa
2009
 * \param[in]    box
2010
 * \param[in]    copyflag    L_INSERT, L_COPY, L_CLONE
2011
 * \return  0 if OK, 1 on error
2012
 *
2013
 * <pre>
2014
 * Notes:
2015
 *      (1) The box can be used, for example, to hold the support region
2016
 *          of a pixa that is being added to the pixaa.
2017
 * </pre>
2018
 */
2019
l_ok
2020
pixaaAddBox(PIXAA   *paa,
2021
            BOX     *box,
2022
            l_int32  copyflag)
2023
0
{
2024
0
    if (!paa)
2025
0
        return ERROR_INT("paa not defined", __func__, 1);
2026
0
    if (!box)
2027
0
        return ERROR_INT("box not defined", __func__, 1);
2028
0
    if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
2029
0
        return ERROR_INT("invalid copyflag", __func__, 1);
2030
2031
0
    boxaAddBox(paa->boxa, box, copyflag);
2032
0
    return 0;
2033
0
}
2034
2035
2036
2037
/*---------------------------------------------------------------------*
2038
 *                            Pixaa accessors                          *
2039
 *---------------------------------------------------------------------*/
2040
/*!
2041
 * \brief   pixaaGetCount()
2042
 *
2043
 * \param[in]    paa
2044
 * \param[out]   pna    [optional] number of pix in each pixa
2045
 * \return  count, or 0 if no pixaa
2046
 *
2047
 * <pre>
2048
 * Notes:
2049
 *      (1) If paa is empty, a returned na will also be empty.
2050
 * </pre>
2051
 */
2052
l_int32
2053
pixaaGetCount(PIXAA  *paa,
2054
              NUMA  **pna)
2055
0
{
2056
0
l_int32  i, n;
2057
0
NUMA    *na;
2058
0
PIXA    *pixa;
2059
2060
0
    if (pna) *pna = NULL;
2061
0
    if (!paa)
2062
0
        return ERROR_INT("paa not defined", __func__, 0);
2063
2064
0
    n = paa->n;
2065
0
    if (pna) {
2066
0
        if ((na = numaCreate(n)) == NULL)
2067
0
            return ERROR_INT("na not made", __func__, 0);
2068
0
        *pna = na;
2069
0
        for (i = 0; i < n; i++) {
2070
0
            pixa = pixaaGetPixa(paa, i, L_CLONE);
2071
0
            numaAddNumber(na, pixaGetCount(pixa));
2072
0
            pixaDestroy(&pixa);
2073
0
        }
2074
0
    }
2075
0
    return n;
2076
0
}
2077
2078
2079
/*!
2080
 * \brief   pixaaGetPixa()
2081
 *
2082
 * \param[in]    paa
2083
 * \param[in]    index        to the index-th pixa
2084
 * \param[in]    accesstype   L_COPY, L_CLONE, L_COPY_CLONE
2085
 * \return  pixa, or NULL on error
2086
 *
2087
 * <pre>
2088
 * Notes:
2089
 *      (1) L_COPY makes a new pixa with a copy of every pix
2090
 *      (2) L_CLONE just makes a new reference to the pixa,
2091
 *          and bumps the counter.  You would use this, for example,
2092
 *          when you need to extract some data from a pix within a
2093
 *          pixa within a pixaa.
2094
 *      (3) L_COPY_CLONE makes a new pixa with a clone of every pix
2095
 *          and box
2096
 *      (4) In all cases, you must invoke pixaDestroy() on the returned pixa
2097
 * </pre>
2098
 */
2099
PIXA *
2100
pixaaGetPixa(PIXAA   *paa,
2101
             l_int32  index,
2102
             l_int32  accesstype)
2103
0
{
2104
0
PIXA  *pixa;
2105
2106
0
    if (!paa)
2107
0
        return (PIXA *)ERROR_PTR("paa not defined", __func__, NULL);
2108
0
    if (index < 0 || index >= paa->n)
2109
0
        return (PIXA *)ERROR_PTR("index not valid", __func__, NULL);
2110
0
    if (accesstype != L_COPY && accesstype != L_CLONE &&
2111
0
        accesstype != L_COPY_CLONE)
2112
0
        return (PIXA *)ERROR_PTR("invalid accesstype", __func__, NULL);
2113
2114
0
    if ((pixa = paa->pixa[index]) == NULL) {  /* shouldn't happen! */
2115
0
        L_ERROR("missing pixa[%d]\n", __func__, index);
2116
0
        return (PIXA *)ERROR_PTR("pixa not found at index", __func__, NULL);
2117
0
    }
2118
0
    return pixaCopy(pixa, accesstype);
2119
0
}
2120
2121
2122
/*!
2123
 * \brief   pixaaGetBoxa()
2124
 *
2125
 * \param[in]    paa
2126
 * \param[in]    accesstype    L_COPY, L_CLONE
2127
 * \return  boxa, or NULL on error
2128
 *
2129
 * <pre>
2130
 * Notes:
2131
 *      (1) L_COPY returns a copy; L_CLONE returns a new reference to the boxa.
2132
 *      (2) In both cases, invoke boxaDestroy() on the returned boxa.
2133
 * </pre>
2134
 */
2135
BOXA *
2136
pixaaGetBoxa(PIXAA   *paa,
2137
             l_int32  accesstype)
2138
0
{
2139
0
    if (!paa)
2140
0
        return (BOXA *)ERROR_PTR("paa not defined", __func__, NULL);
2141
0
    if (accesstype != L_COPY && accesstype != L_CLONE)
2142
0
        return (BOXA *)ERROR_PTR("invalid access type", __func__, NULL);
2143
2144
0
    return boxaCopy(paa->boxa, accesstype);
2145
0
}
2146
2147
2148
/*!
2149
 * \brief   pixaaGetPix()
2150
 *
2151
 * \param[in]    paa
2152
 * \param[in]    index        index into the pixa array in the pixaa
2153
 * \param[in]    ipix         index into the pix array in the pixa
2154
 * \param[in]    accessflag   L_COPY or L_CLONE
2155
 * \return  pix, or NULL on error
2156
 */
2157
PIX *
2158
pixaaGetPix(PIXAA   *paa,
2159
            l_int32  index,
2160
            l_int32  ipix,
2161
            l_int32  accessflag)
2162
0
{
2163
0
PIX   *pix;
2164
0
PIXA  *pixa;
2165
2166
0
    if ((pixa = pixaaGetPixa(paa, index, L_CLONE)) == NULL)
2167
0
        return (PIX *)ERROR_PTR("pixa not retrieved", __func__, NULL);
2168
0
    if ((pix = pixaGetPix(pixa, ipix, accessflag)) == NULL)
2169
0
        L_ERROR("pix not retrieved\n", __func__);
2170
0
    pixaDestroy(&pixa);
2171
0
    return pix;
2172
0
}
2173
2174
2175
/*!
2176
 * \brief   pixaaVerifyDepth()
2177
 *
2178
 * \param[in]    paa
2179
 * \param[out]   psame   1 if all pix have the same depth; 0 otherwise
2180
 * \param[out]   pmaxd   [optional] max depth of all pix in pixaa
2181
 * \return   0 if OK; 1 on error
2182
 *
2183
 * <pre>
2184
 * Notes:
2185
 *      (1) It is considered to be an error if any pixa have no pix.
2186
 * </pre>
2187
 */
2188
l_ok
2189
pixaaVerifyDepth(PIXAA    *paa,
2190
                 l_int32  *psame,
2191
                 l_int32  *pmaxd)
2192
0
{
2193
0
l_int32  i, n, d, maxd, same, samed;
2194
0
PIXA    *pixa;
2195
2196
0
    if (pmaxd) *pmaxd = 0;
2197
0
    if (!psame)
2198
0
        return ERROR_INT("psame not defined", __func__, 1);
2199
0
    *psame = 0;
2200
0
    if (!paa)
2201
0
        return ERROR_INT("paa not defined", __func__, 1);
2202
0
    if ((n = pixaaGetCount(paa, NULL)) == 0)
2203
0
        return ERROR_INT("no pixa in paa", __func__, 1);
2204
2205
0
    pixa = pixaaGetPixa(paa, 0, L_CLONE);
2206
0
    pixaVerifyDepth(pixa, &same, &maxd);  /* init same, maxd with first pixa */
2207
0
    pixaDestroy(&pixa);
2208
0
    for (i = 1; i < n; i++) {
2209
0
        pixa = pixaaGetPixa(paa, i, L_CLONE);
2210
0
        pixaVerifyDepth(pixa, &samed, &d);
2211
0
        pixaDestroy(&pixa);
2212
0
        maxd = L_MAX(maxd, d);
2213
0
        if (!samed || maxd != d)
2214
0
            same = 0;
2215
0
    }
2216
0
    *psame = same;
2217
0
    if (pmaxd) *pmaxd = maxd;
2218
0
    return 0;
2219
0
}
2220
2221
2222
/*!
2223
 * \brief   pixaaVerifyDimensions()
2224
 *
2225
 * \param[in]    paa
2226
 * \param[out]   psame   1 if all pix have the same depth; 0 otherwise
2227
 * \param[out]   pmaxw   [optional] max width of all pix in pixaa
2228
 * \param[out]   pmaxh   [optional] max height of all pix in pixaa
2229
 * \return   0 if OK; 1 on error
2230
 *
2231
 * <pre>
2232
 * Notes:
2233
 *      (1) It is considered to be an error if any pixa have no pix.
2234
 * </pre>
2235
 */
2236
l_ok
2237
pixaaVerifyDimensions(PIXAA    *paa,
2238
                      l_int32  *psame,
2239
                      l_int32  *pmaxw,
2240
                      l_int32  *pmaxh)
2241
0
{
2242
0
l_int32  i, n, w, h, maxw, maxh, same, same2;
2243
0
PIXA    *pixa;
2244
2245
0
    if (pmaxw) *pmaxw = 0;
2246
0
    if (pmaxh) *pmaxh = 0;
2247
0
    if (!psame)
2248
0
        return ERROR_INT("psame not defined", __func__, 1);
2249
0
    *psame = 0;
2250
0
    if (!paa)
2251
0
        return ERROR_INT("paa not defined", __func__, 1);
2252
0
    if ((n = pixaaGetCount(paa, NULL)) == 0)
2253
0
        return ERROR_INT("no pixa in paa", __func__, 1);
2254
2255
        /* Init same; init maxw and maxh from first pixa */
2256
0
    pixa = pixaaGetPixa(paa, 0, L_CLONE);
2257
0
    pixaVerifyDimensions(pixa, &same, &maxw, &maxh);
2258
0
    pixaDestroy(&pixa);
2259
2260
0
    for (i = 1; i < n; i++) {
2261
0
        pixa = pixaaGetPixa(paa, i, L_CLONE);
2262
0
        pixaVerifyDimensions(pixa, &same2, &w, &h);
2263
0
        pixaDestroy(&pixa);
2264
0
        maxw = L_MAX(maxw, w);
2265
0
        maxh = L_MAX(maxh, h);
2266
0
        if (!same2 || maxw != w || maxh != h)
2267
0
            same = 0;
2268
0
    }
2269
0
    *psame = same;
2270
0
    if (pmaxw) *pmaxw = maxw;
2271
0
    if (pmaxh) *pmaxh = maxh;
2272
0
    return 0;
2273
0
}
2274
2275
2276
/*!
2277
 * \brief   pixaaIsFull()
2278
 *
2279
 * \param[in]    paa
2280
 * \param[out]   pfull    1 if all pixa in the paa have full pix arrays
2281
 * \return  return 0 if OK, 1 on error
2282
 *
2283
 * <pre>
2284
 * Notes:
2285
 *      (1) Does not require boxa associated with each pixa to be full.
2286
 * </pre>
2287
 */
2288
l_int32
2289
pixaaIsFull(PIXAA    *paa,
2290
            l_int32  *pfull)
2291
0
{
2292
0
l_int32  i, n, full;
2293
0
PIXA    *pixa;
2294
2295
0
    if (!pfull)
2296
0
        return ERROR_INT("&full not defined", __func__, 0);
2297
0
    *pfull = 0;
2298
0
    if (!paa)
2299
0
        return ERROR_INT("paa not defined", __func__, 0);
2300
2301
0
    n = pixaaGetCount(paa, NULL);
2302
0
    full = 1;
2303
0
    for (i = 0; i < n; i++) {
2304
0
        pixa = pixaaGetPixa(paa, i, L_CLONE);
2305
0
        pixaIsFull(pixa, &full, NULL);
2306
0
        pixaDestroy(&pixa);
2307
0
        if (!full) break;
2308
0
    }
2309
0
    *pfull = full;
2310
0
    return 0;
2311
0
}
2312
2313
2314
/*---------------------------------------------------------------------*
2315
 *                         Pixaa array modifiers                       *
2316
 *---------------------------------------------------------------------*/
2317
/*!
2318
 * \brief   pixaaInitFull()
2319
 *
2320
 * \param[in]    paa     typically empty
2321
 * \param[in]    pixa    to be replicated into the entire pixa ptr array
2322
 * \return  0 if OK, 1 on error
2323
 *
2324
 * <pre>
2325
 * Notes:
2326
 *      (1) This initializes a pixaa by filling up the entire pixa ptr array
2327
 *          with copies of %pixa.  Any existing pixa are destroyed.
2328
 *      (2) Example usage.  This function is useful to prepare for a
2329
 *          random insertion (or replacement) of pixa into a pixaa.
2330
 *          To randomly insert pixa into a pixaa, up to some index "max":
2331
 *             Pixaa *paa = pixaaCreate(max);
2332
 *             Pixa *pixa = pixaCreate(1);  // if you want little memory
2333
 *             pixaaInitFull(paa, pixa);  // copy it to entire array
2334
 *             pixaDestroy(&pixa);  // no longer needed
2335
 *          The initialization allows the pixaa to always be properly filled.
2336
 * </pre>
2337
 */
2338
l_ok
2339
pixaaInitFull(PIXAA  *paa,
2340
              PIXA   *pixa)
2341
0
{
2342
0
l_int32  i, n;
2343
0
PIXA    *pixat;
2344
2345
0
    if (!paa)
2346
0
        return ERROR_INT("paa not defined", __func__, 1);
2347
0
    if (!pixa)
2348
0
        return ERROR_INT("pixa not defined", __func__, 1);
2349
2350
0
    n = paa->nalloc;
2351
0
    paa->n = n;
2352
0
    for (i = 0; i < n; i++) {
2353
0
        pixat = pixaCopy(pixa, L_COPY);
2354
0
        pixaaReplacePixa(paa, i, pixat);
2355
0
    }
2356
2357
0
    return 0;
2358
0
}
2359
2360
2361
/*!
2362
 * \brief   pixaaReplacePixa()
2363
 *
2364
 * \param[in]    paa
2365
 * \param[in]    index  to the index-th pixa
2366
 * \param[in]    pixa   insert to replace existing one
2367
 * \return  0 if OK, 1 on error
2368
 *
2369
 * <pre>
2370
 * Notes:
2371
 *      (1) This allows random insertion of a pixa into a pixaa, with
2372
 *          destruction of any existing pixa at that location.
2373
 *          The input pixa is now owned by the pixaa.
2374
 *      (2) No other pixa in the array are affected.
2375
 *      (3) The index must be within the allowed set.
2376
 * </pre>
2377
 */
2378
l_ok
2379
pixaaReplacePixa(PIXAA   *paa,
2380
                 l_int32  index,
2381
                 PIXA    *pixa)
2382
0
{
2383
2384
0
    if (!paa)
2385
0
        return ERROR_INT("paa not defined", __func__, 1);
2386
0
    if (index < 0 || index >= paa->n)
2387
0
        return ERROR_INT("index not valid", __func__, 1);
2388
0
    if (!pixa)
2389
0
        return ERROR_INT("pixa not defined", __func__, 1);
2390
2391
0
    pixaDestroy(&(paa->pixa[index]));
2392
0
    paa->pixa[index] = pixa;
2393
0
    return 0;
2394
0
}
2395
2396
2397
/*!
2398
 * \brief   pixaaClear()
2399
 *
2400
 * \param[in]    paa
2401
 * \return  0 if OK, 1 on error
2402
 *
2403
 * <pre>
2404
 * Notes:
2405
 *      (1) This destroys all pixa in the pixaa, and nulls the ptrs
2406
 *          in the pixa ptr array.
2407
 * </pre>
2408
 */
2409
l_ok
2410
pixaaClear(PIXAA  *paa)
2411
0
{
2412
0
l_int32  i, n;
2413
2414
0
    if (!paa)
2415
0
        return ERROR_INT("paa not defined", __func__, 1);
2416
2417
0
    n = pixaaGetCount(paa, NULL);
2418
0
    for (i = 0; i < n; i++)
2419
0
        pixaDestroy(&paa->pixa[i]);
2420
0
    paa->n = 0;
2421
0
    return 0;
2422
0
}
2423
2424
2425
/*!
2426
 * \brief   pixaaTruncate()
2427
 *
2428
 * \param[in]    paa
2429
 * \return  0 if OK, 1 on error
2430
 *
2431
 * <pre>
2432
 * Notes:
2433
 *      (1) This identifies the largest index containing a pixa that
2434
 *          has any pix within it, destroys all pixa above that index,
2435
 *          and resets the count.
2436
 * </pre>
2437
 */
2438
l_ok
2439
pixaaTruncate(PIXAA  *paa)
2440
0
{
2441
0
l_int32  i, n, np;
2442
0
PIXA    *pixa;
2443
2444
0
    if (!paa)
2445
0
        return ERROR_INT("paa not defined", __func__, 1);
2446
2447
0
    n = pixaaGetCount(paa, NULL);
2448
0
    for (i = n - 1; i >= 0; i--) {
2449
0
        pixa = pixaaGetPixa(paa, i, L_CLONE);
2450
0
        if (!pixa) {
2451
0
            paa->n--;
2452
0
            continue;
2453
0
        }
2454
0
        np = pixaGetCount(pixa);
2455
0
        pixaDestroy(&pixa);
2456
0
        if (np == 0) {
2457
0
            pixaDestroy(&paa->pixa[i]);
2458
0
            paa->n--;
2459
0
        } else {
2460
0
            break;
2461
0
        }
2462
0
    }
2463
0
    return 0;
2464
0
}
2465
2466
2467
2468
/*---------------------------------------------------------------------*
2469
 *                          Pixa serialized I/O                        *
2470
 *---------------------------------------------------------------------*/
2471
/*!
2472
 * \brief   pixaRead()
2473
 *
2474
 * \param[in]    filename
2475
 * \return  pixa, or NULL on error
2476
 *
2477
 * <pre>
2478
 * Notes:
2479
 *      (1) The pix are stored in the file as png.
2480
 *          If the png library is not linked, this will fail.
2481
 * </pre>
2482
 */
2483
PIXA *
2484
pixaRead(const char  *filename)
2485
0
{
2486
0
FILE  *fp;
2487
0
PIXA  *pixa;
2488
2489
#if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2490
    return (PIXA *)ERROR_PTR("no libpng: can't read data", __func__, NULL);
2491
#endif  /* !HAVE_LIBPNG */
2492
2493
0
    if (!filename)
2494
0
        return (PIXA *)ERROR_PTR("filename not defined", __func__, NULL);
2495
2496
0
    if ((fp = fopenReadStream(filename)) == NULL)
2497
0
        return (PIXA *)ERROR_PTR_1("stream not opened",
2498
0
                                   filename, __func__, NULL);
2499
0
    pixa = pixaReadStream(fp);
2500
0
    fclose(fp);
2501
0
    if (!pixa)
2502
0
        return (PIXA *)ERROR_PTR_1("pixa not read",
2503
0
                                   filename, __func__, NULL);
2504
0
    return pixa;
2505
0
}
2506
2507
2508
/*!
2509
 * \brief   pixaReadStream()
2510
 *
2511
 * \param[in]    fp    file stream
2512
 * \return  pixa, or NULL on error
2513
 *
2514
 * <pre>
2515
 * Notes:
2516
 *      (1) The pix are stored in the file as png.
2517
 *          If the png library is not linked, this will fail.
2518
 *      (2) It is OK for the pixa to be empty.
2519
 * </pre>
2520
 */
2521
PIXA *
2522
pixaReadStream(FILE  *fp)
2523
0
{
2524
0
l_int32  n, i, xres, yres, version;
2525
0
l_int32  ignore;
2526
0
BOXA    *boxa;
2527
0
PIX     *pix;
2528
0
PIXA    *pixa;
2529
2530
#if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2531
    return (PIXA *)ERROR_PTR("no libpng: can't read data", __func__, NULL);
2532
#endif  /* !HAVE_LIBPNG */
2533
2534
0
    if (!fp)
2535
0
        return (PIXA *)ERROR_PTR("stream not defined", __func__, NULL);
2536
2537
0
    if (fscanf(fp, "\nPixa Version %d\n", &version) != 1)
2538
0
        return (PIXA *)ERROR_PTR("not a pixa file", __func__, NULL);
2539
0
    if (version != PIXA_VERSION_NUMBER)
2540
0
        return (PIXA *)ERROR_PTR("invalid pixa version", __func__, NULL);
2541
0
    if (fscanf(fp, "Number of pix = %d\n", &n) != 1)
2542
0
        return (PIXA *)ERROR_PTR("not a pixa file", __func__, NULL);
2543
0
    if (n < 0)
2544
0
        return (PIXA *)ERROR_PTR("num pix ptrs < 0", __func__, NULL);
2545
0
    if (n > MaxPixaPtrArraySize)
2546
0
        return (PIXA *)ERROR_PTR("too many pix ptrs", __func__, NULL);
2547
0
    if (n == 0) L_INFO("the pixa is empty\n", __func__);
2548
2549
0
    if ((boxa = boxaReadStream(fp)) == NULL)
2550
0
        return (PIXA *)ERROR_PTR("boxa not made", __func__, NULL);
2551
0
    if ((pixa = pixaCreate(n)) == NULL) {
2552
0
        boxaDestroy(&boxa);
2553
0
        return (PIXA *)ERROR_PTR("pixa not made", __func__, NULL);
2554
0
    }
2555
0
    boxaDestroy(&pixa->boxa);
2556
0
    pixa->boxa = boxa;
2557
2558
0
    for (i = 0; i < n; i++) {
2559
0
        if ((fscanf(fp, " pix[%d]: xres = %d, yres = %d\n",
2560
0
              &ignore, &xres, &yres)) != 3) {
2561
0
            pixaDestroy(&pixa);
2562
0
            return (PIXA *)ERROR_PTR("res reading error", __func__, NULL);
2563
0
        }
2564
0
        if ((pix = pixReadStreamPng(fp)) == NULL) {
2565
0
            pixaDestroy(&pixa);
2566
0
            return (PIXA *)ERROR_PTR("pix not read", __func__, NULL);
2567
0
        }
2568
0
        pixSetXRes(pix, xres);
2569
0
        pixSetYRes(pix, yres);
2570
0
        pixaAddPix(pixa, pix, L_INSERT);
2571
0
    }
2572
0
    return pixa;
2573
0
}
2574
2575
2576
/*!
2577
 * \brief   pixaReadMem()
2578
 *
2579
 * \param[in]    data   of serialized pixa
2580
 * \param[in]    size   of data in bytes
2581
 * \return  pixa, or NULL on error
2582
 */
2583
PIXA *
2584
pixaReadMem(const l_uint8  *data,
2585
            size_t          size)
2586
0
{
2587
0
FILE  *fp;
2588
0
PIXA  *pixa;
2589
2590
0
    if (!data)
2591
0
        return (PIXA *)ERROR_PTR("data not defined", __func__, NULL);
2592
0
    if ((fp = fopenReadFromMemory(data, size)) == NULL)
2593
0
        return (PIXA *)ERROR_PTR("stream not opened", __func__, NULL);
2594
2595
0
    pixa = pixaReadStream(fp);
2596
0
    fclose(fp);
2597
0
    if (!pixa) L_ERROR("pixa not read\n", __func__);
2598
0
    return pixa;
2599
0
}
2600
2601
2602
/*!
2603
 * \brief   pixaWriteDebug()
2604
 *
2605
 * \param[in]    fname
2606
 * \param[in]    pixa
2607
 * \return  0 if OK; 1 on error
2608
 *
2609
 * <pre>
2610
 * Notes:
2611
 *      (1) Debug version, intended for use in the library when writing
2612
 *          to files in a temp directory with names that are compiled in.
2613
 *          This is used instead of pixaWrite() for all such library calls.
2614
 *      (2) The global variable LeptDebugOK defaults to 0, and can be set
2615
 *          or cleared by the function setLeptDebugOK().
2616
 * </pre>
2617
 */
2618
l_ok
2619
pixaWriteDebug(const char  *fname,
2620
               PIXA        *pixa)
2621
0
{
2622
0
    if (LeptDebugOK) {
2623
0
        return pixaWrite(fname, pixa);
2624
0
    } else {
2625
0
        L_INFO("write to named temp file %s is disabled\n", __func__, fname);
2626
0
        return 0;
2627
0
    }
2628
0
}
2629
2630
2631
/*!
2632
 * \brief   pixaWrite()
2633
 *
2634
 * \param[in]    filename
2635
 * \param[in]    pixa
2636
 * \return  0 if OK, 1 on error
2637
 *
2638
 * <pre>
2639
 * Notes:
2640
 *      (1) The pix are stored in the file as png.
2641
 *          If the png library is not linked, this will fail.
2642
 * </pre>
2643
 */
2644
l_ok
2645
pixaWrite(const char  *filename,
2646
          PIXA        *pixa)
2647
0
{
2648
0
l_int32  ret;
2649
0
FILE    *fp;
2650
2651
#if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2652
    return ERROR_INT("no libpng: can't write data", __func__, 1);
2653
#endif  /* !HAVE_LIBPNG */
2654
2655
0
    if (!filename)
2656
0
        return ERROR_INT("filename not defined", __func__, 1);
2657
0
    if (!pixa)
2658
0
        return ERROR_INT("pixa not defined", __func__, 1);
2659
2660
0
    if ((fp = fopenWriteStream(filename, "wb")) == NULL)
2661
0
        return ERROR_INT_1("stream not opened", filename, __func__, 1);
2662
0
    ret = pixaWriteStream(fp, pixa);
2663
0
    fclose(fp);
2664
0
    if (ret)
2665
0
        return ERROR_INT_1("pixa not written to stream", filename, __func__, 1);
2666
0
    return 0;
2667
0
}
2668
2669
2670
/*!
2671
 * \brief   pixaWriteStream()
2672
 *
2673
 * \param[in]    fp     file stream opened for "wb"
2674
 * \param[in]    pixa
2675
 * \return  0 if OK, 1 on error
2676
 *
2677
 * <pre>
2678
 * Notes:
2679
 *      (1) The pix are stored in the file as png.
2680
 *          If the png library is not linked, this will fail.
2681
 * </pre>
2682
 */
2683
l_ok
2684
pixaWriteStream(FILE  *fp,
2685
                PIXA  *pixa)
2686
0
{
2687
0
l_int32  n, i;
2688
0
PIX     *pix;
2689
2690
#if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2691
    return ERROR_INT("no libpng: can't write data", __func__, 1);
2692
#endif  /* !HAVE_LIBPNG */
2693
2694
0
    if (!fp)
2695
0
        return ERROR_INT("stream not defined", __func__, 1);
2696
0
    if (!pixa)
2697
0
        return ERROR_INT("pixa not defined", __func__, 1);
2698
2699
0
    n = pixaGetCount(pixa);
2700
0
    fprintf(fp, "\nPixa Version %d\n", PIXA_VERSION_NUMBER);
2701
0
    fprintf(fp, "Number of pix = %d\n", n);
2702
0
    boxaWriteStream(fp, pixa->boxa);
2703
0
    for (i = 0; i < n; i++) {
2704
0
        if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
2705
0
            return ERROR_INT("pix not found", __func__, 1);
2706
0
        fprintf(fp, " pix[%d]: xres = %d, yres = %d\n",
2707
0
                i, pix->xres, pix->yres);
2708
0
        pixWriteStreamPng(fp, pix, 0.0);
2709
0
        pixDestroy(&pix);
2710
0
    }
2711
0
    return 0;
2712
0
}
2713
2714
2715
/*!
2716
 * \brief   pixaWriteMem()
2717
 *
2718
 * \param[out]   pdata    data of serialized pixa
2719
 * \param[out]   psize    size of returned data
2720
 * \param[in]    pixa
2721
 * \return  0 if OK, 1 on error
2722
 *
2723
 * <pre>
2724
 * Notes:
2725
 *      (1) Serializes a pixa in memory and puts the result in a buffer.
2726
 * </pre>
2727
 */
2728
l_ok
2729
pixaWriteMem(l_uint8  **pdata,
2730
             size_t    *psize,
2731
             PIXA      *pixa)
2732
0
{
2733
0
l_int32  ret;
2734
0
FILE    *fp;
2735
2736
0
    if (pdata) *pdata = NULL;
2737
0
    if (psize) *psize = 0;
2738
0
    if (!pdata)
2739
0
        return ERROR_INT("&data not defined", __func__, 1);
2740
0
    if (!psize)
2741
0
        return ERROR_INT("&size not defined", __func__, 1);
2742
0
    if (!pixa)
2743
0
        return ERROR_INT("pixa not defined", __func__, 1);
2744
2745
0
#if HAVE_FMEMOPEN
2746
0
    if ((fp = open_memstream((char **)pdata, psize)) == NULL)
2747
0
        return ERROR_INT("stream not opened", __func__, 1);
2748
0
    ret = pixaWriteStream(fp, pixa);
2749
0
    fputc('\0', fp);
2750
0
    fclose(fp);
2751
0
    if (*psize > 0) *psize = *psize - 1;
2752
#else
2753
    L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
2754
  #ifdef _WIN32
2755
    if ((fp = fopenWriteWinTempfile()) == NULL)
2756
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
2757
  #else
2758
    if ((fp = tmpfile()) == NULL)
2759
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
2760
  #endif  /* _WIN32 */
2761
    ret = pixaWriteStream(fp, pixa);
2762
    rewind(fp);
2763
    *pdata = l_binaryReadStream(fp, psize);
2764
    fclose(fp);
2765
#endif  /* HAVE_FMEMOPEN */
2766
0
    return ret;
2767
0
}
2768
2769
2770
/*!
2771
 * \brief   pixaReadBoth()
2772
 *
2773
 * \param[in]    filename
2774
 * \return  pixa, or NULL on error
2775
 *
2776
 * <pre>
2777
 * Notes:
2778
 *      (1) This reads serialized files of either a pixa or a pixacomp,
2779
 *          and returns a pixa in memory.  It requires png and jpeg libraries.
2780
 * </pre>
2781
 */
2782
PIXA *
2783
pixaReadBoth(const char  *filename)
2784
0
{
2785
0
char    buf[32];
2786
0
char   *sname;
2787
0
PIXA   *pixa;
2788
0
PIXAC  *pac;
2789
2790
0
    if (!filename)
2791
0
        return (PIXA *)ERROR_PTR("filename not defined", __func__, NULL);
2792
2793
0
    l_getStructStrFromFile(filename, L_STR_NAME, &sname);
2794
0
    if (!sname)
2795
0
        return (PIXA *)ERROR_PTR("struct name not found", __func__, NULL);
2796
0
    snprintf(buf, sizeof(buf), "%s", sname);
2797
0
    LEPT_FREE(sname);
2798
2799
0
    if (strcmp(buf, "Pixacomp") == 0) {
2800
0
        if ((pac = pixacompRead(filename)) == NULL)
2801
0
            return (PIXA *)ERROR_PTR("pac not made", __func__, NULL);
2802
0
        pixa = pixaCreateFromPixacomp(pac, L_COPY);
2803
0
        pixacompDestroy(&pac);
2804
0
    } else if (strcmp(buf, "Pixa") == 0) {
2805
0
        if ((pixa = pixaRead(filename)) == NULL)
2806
0
            return (PIXA *)ERROR_PTR("pixa not made", __func__, NULL);
2807
0
    } else {
2808
0
        return (PIXA *)ERROR_PTR("invalid file type", __func__, NULL);
2809
0
    }
2810
0
    return pixa;
2811
0
}
2812
2813
2814
/*---------------------------------------------------------------------*
2815
 *                         Pixaa serialized I/O                        *
2816
 *---------------------------------------------------------------------*/
2817
/*!
2818
 * \brief   pixaaReadFromFiles()
2819
 *
2820
 * \param[in]    dirname   directory
2821
 * \param[in]    substr    [optional] substring filter on filenames; can be NULL
2822
 * \param[in]    first     0-based
2823
 * \param[in]    nfiles    use 0 for everything from %first to the end
2824
 * \return  paa, or NULL on error or if no pixa files are found.
2825
 *
2826
 * <pre>
2827
 * Notes:
2828
 *      (1) The files must be serialized pixa files (e.g., *.pa)
2829
 *          If some files cannot be read, warnings are issued.
2830
 *      (2) Use %substr to filter filenames in the directory.  If
2831
 *          %substr == NULL, this takes all files.
2832
 *      (3) After filtering, use %first and %nfiles to select
2833
 *          a contiguous set of files, that have been lexically
2834
 *          sorted in increasing order.
2835
 * </pre>
2836
 */
2837
PIXAA *
2838
pixaaReadFromFiles(const char  *dirname,
2839
                   const char  *substr,
2840
                   l_int32      first,
2841
                   l_int32      nfiles)
2842
0
{
2843
0
char    *fname;
2844
0
l_int32  i, n;
2845
0
PIXA    *pixa;
2846
0
PIXAA   *paa;
2847
0
SARRAY  *sa;
2848
2849
0
  if (!dirname)
2850
0
      return (PIXAA *)ERROR_PTR("dirname not defined", __func__, NULL);
2851
2852
0
  sa = getSortedPathnamesInDirectory(dirname, substr, first, nfiles);
2853
0
  if (!sa || ((n = sarrayGetCount(sa)) == 0)) {
2854
0
      sarrayDestroy(&sa);
2855
0
      return (PIXAA *)ERROR_PTR("no pixa files found", __func__, NULL);
2856
0
  }
2857
2858
0
  paa = pixaaCreate(n);
2859
0
  for (i = 0; i < n; i++) {
2860
0
      fname = sarrayGetString(sa, i, L_NOCOPY);
2861
0
      if ((pixa = pixaRead(fname)) == NULL) {
2862
0
          L_ERROR("pixa not read for %d-th file", __func__, i);
2863
0
          continue;
2864
0
      }
2865
0
      pixaaAddPixa(paa, pixa, L_INSERT);
2866
0
  }
2867
2868
0
  sarrayDestroy(&sa);
2869
0
  return paa;
2870
0
}
2871
2872
2873
/*!
2874
 * \brief   pixaaRead()
2875
 *
2876
 * \param[in]    filename
2877
 * \return  paa, or NULL on error
2878
 *
2879
 * <pre>
2880
 * Notes:
2881
 *      (1) The pix are stored in the file as png.
2882
 *          If the png library is not linked, this will fail.
2883
 * </pre>
2884
 */
2885
PIXAA *
2886
pixaaRead(const char  *filename)
2887
0
{
2888
0
FILE   *fp;
2889
0
PIXAA  *paa;
2890
2891
#if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2892
    return (PIXAA *)ERROR_PTR("no libpng: can't read data", __func__, NULL);
2893
#endif  /* !HAVE_LIBPNG */
2894
2895
0
    if (!filename)
2896
0
        return (PIXAA *)ERROR_PTR("filename not defined", __func__, NULL);
2897
2898
0
    if ((fp = fopenReadStream(filename)) == NULL)
2899
0
        return (PIXAA *)ERROR_PTR_1("stream not opened",
2900
0
                                    filename, __func__, NULL);
2901
0
    paa = pixaaReadStream(fp);
2902
0
    fclose(fp);
2903
0
    if (!paa)
2904
0
        return (PIXAA *)ERROR_PTR_1("paa not read", filename, __func__, NULL);
2905
0
    return paa;
2906
0
}
2907
2908
2909
/*!
2910
 * \brief   pixaaReadStream()
2911
 *
2912
 * \param[in]    fp    file stream
2913
 * \return  paa, or NULL on error
2914
 *
2915
 * <pre>
2916
 * Notes:
2917
 *      (1) The pix are stored in the file as png.
2918
 *          If the png library is not linked, this will fail.
2919
 *      (2) It is OK for the pixaa to be empty.
2920
 * </pre>
2921
 */
2922
PIXAA *
2923
pixaaReadStream(FILE  *fp)
2924
0
{
2925
0
l_int32  n, i, version;
2926
0
l_int32  ignore;
2927
0
BOXA    *boxa;
2928
0
PIXA    *pixa;
2929
0
PIXAA   *paa;
2930
2931
#if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
2932
    return (PIXAA *)ERROR_PTR("no libpng: can't read data", __func__, NULL);
2933
#endif  /* !HAVE_LIBPNG */
2934
2935
0
    if (!fp)
2936
0
        return (PIXAA *)ERROR_PTR("stream not defined", __func__, NULL);
2937
2938
0
    if (fscanf(fp, "\nPixaa Version %d\n", &version) != 1)
2939
0
        return (PIXAA *)ERROR_PTR("not a pixaa file", __func__, NULL);
2940
0
    if (version != PIXAA_VERSION_NUMBER)
2941
0
        return (PIXAA *)ERROR_PTR("invalid pixaa version", __func__, NULL);
2942
0
    if (fscanf(fp, "Number of pixa = %d\n", &n) != 1)
2943
0
        return (PIXAA *)ERROR_PTR("not a pixaa file", __func__, NULL);
2944
0
    if (n < 0)
2945
0
        return (PIXAA *)ERROR_PTR("num pixa ptrs < 0", __func__, NULL);
2946
0
    if (n > MaxPixaaPtrArraySize)
2947
0
        return (PIXAA *)ERROR_PTR("too many pixa ptrs", __func__, NULL);
2948
0
    if (n == 0) L_INFO("the pixaa is empty\n", __func__);
2949
2950
0
    if ((paa = pixaaCreate(n)) == NULL)
2951
0
        return (PIXAA *)ERROR_PTR("paa not made", __func__, NULL);
2952
0
    if ((boxa = boxaReadStream(fp)) == NULL) {
2953
0
        pixaaDestroy(&paa);
2954
0
        return (PIXAA *)ERROR_PTR("boxa not made", __func__, NULL);
2955
0
    }
2956
0
    boxaDestroy(&paa->boxa);
2957
0
    paa->boxa = boxa;
2958
2959
0
    for (i = 0; i < n; i++) {
2960
0
        if ((fscanf(fp, "\n\n --------------- pixa[%d] ---------------\n",
2961
0
                    &ignore)) != 1) {
2962
0
            pixaaDestroy(&paa);
2963
0
            return (PIXAA *)ERROR_PTR("text reading", __func__, NULL);
2964
0
        }
2965
0
        if ((pixa = pixaReadStream(fp)) == NULL) {
2966
0
            pixaaDestroy(&paa);
2967
0
            return (PIXAA *)ERROR_PTR("pixa not read", __func__, NULL);
2968
0
        }
2969
0
        pixaaAddPixa(paa, pixa, L_INSERT);
2970
0
    }
2971
2972
0
    return paa;
2973
0
}
2974
2975
2976
/*!
2977
 * \brief   pixaaReadMem()
2978
 *
2979
 * \param[in]    data   of serialized pixaa
2980
 * \param[in]    size   of data in bytes
2981
 * \return  paa, or NULL on error
2982
 */
2983
PIXAA *
2984
pixaaReadMem(const l_uint8  *data,
2985
             size_t          size)
2986
0
{
2987
0
FILE   *fp;
2988
0
PIXAA  *paa;
2989
2990
0
    if (!data)
2991
0
        return (PIXAA *)ERROR_PTR("data not defined", __func__, NULL);
2992
0
    if ((fp = fopenReadFromMemory(data, size)) == NULL)
2993
0
        return (PIXAA *)ERROR_PTR("stream not opened", __func__, NULL);
2994
2995
0
    paa = pixaaReadStream(fp);
2996
0
    fclose(fp);
2997
0
    if (!paa) L_ERROR("paa not read\n", __func__);
2998
0
    return paa;
2999
0
}
3000
3001
3002
/*!
3003
 * \brief   pixaaWrite()
3004
 *
3005
 * \param[in]    filename
3006
 * \param[in]    paa
3007
 * \return  0 if OK, 1 on error
3008
 *
3009
 * <pre>
3010
 * Notes:
3011
 *      (1) The pix are stored in the file as png.
3012
 *          If the png library is not linked, this will fail.
3013
 * </pre>
3014
 */
3015
l_ok
3016
pixaaWrite(const char  *filename,
3017
           PIXAA       *paa)
3018
0
{
3019
0
l_int32  ret;
3020
0
FILE    *fp;
3021
3022
#if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
3023
    return ERROR_INT("no libpng: can't read data", __func__, 1);
3024
#endif  /* !HAVE_LIBPNG */
3025
3026
0
    if (!filename)
3027
0
        return ERROR_INT("filename not defined", __func__, 1);
3028
0
    if (!paa)
3029
0
        return ERROR_INT("paa not defined", __func__, 1);
3030
3031
0
    if ((fp = fopenWriteStream(filename, "wb")) == NULL)
3032
0
        return ERROR_INT_1("stream not opened", filename, __func__, 1);
3033
0
    ret = pixaaWriteStream(fp, paa);
3034
0
    fclose(fp);
3035
0
    if (ret)
3036
0
        return ERROR_INT_1("paa not written to stream", filename, __func__, 1);
3037
0
    return 0;
3038
0
}
3039
3040
3041
/*!
3042
 * \brief   pixaaWriteStream()
3043
 *
3044
 * \param[in]    fp    file stream opened for "wb"
3045
 * \param[in]    paa
3046
 * \return  0 if OK, 1 on error
3047
 *
3048
 * <pre>
3049
 * Notes:
3050
 *      (1) The pix are stored in the file as png.
3051
 *          If the png library is not linked, this will fail.
3052
 * </pre>
3053
 */
3054
l_ok
3055
pixaaWriteStream(FILE   *fp,
3056
                 PIXAA  *paa)
3057
0
{
3058
0
l_int32  n, i;
3059
0
PIXA    *pixa;
3060
3061
#if !HAVE_LIBPNG     /* defined in environ.h and config_auto.h */
3062
    return ERROR_INT("no libpng: can't read data", __func__, 1);
3063
#endif  /* !HAVE_LIBPNG */
3064
3065
0
    if (!fp)
3066
0
        return ERROR_INT("stream not defined", __func__, 1);
3067
0
    if (!paa)
3068
0
        return ERROR_INT("paa not defined", __func__, 1);
3069
3070
0
    n = pixaaGetCount(paa, NULL);
3071
0
    fprintf(fp, "\nPixaa Version %d\n", PIXAA_VERSION_NUMBER);
3072
0
    fprintf(fp, "Number of pixa = %d\n", n);
3073
0
    boxaWriteStream(fp, paa->boxa);
3074
0
    for (i = 0; i < n; i++) {
3075
0
        if ((pixa = pixaaGetPixa(paa, i, L_CLONE)) == NULL)
3076
0
            return ERROR_INT("pixa not found", __func__, 1);
3077
0
        fprintf(fp, "\n\n --------------- pixa[%d] ---------------\n", i);
3078
0
        pixaWriteStream(fp, pixa);
3079
0
        pixaDestroy(&pixa);
3080
0
    }
3081
0
    return 0;
3082
0
}
3083
3084
3085
/*!
3086
 * \brief   pixaaWriteMem()
3087
 *
3088
 * \param[out]   pdata   data of serialized pixaa
3089
 * \param[out]   psize   size of returned data
3090
 * \param[in]    paa
3091
 * \return  0 if OK, 1 on error
3092
 *
3093
 * <pre>
3094
 * Notes:
3095
 *      (1) Serializes a pixaa in memory and puts the result in a buffer.
3096
 * </pre>
3097
 */
3098
l_ok
3099
pixaaWriteMem(l_uint8  **pdata,
3100
              size_t    *psize,
3101
              PIXAA     *paa)
3102
0
{
3103
0
l_int32  ret;
3104
0
FILE    *fp;
3105
3106
0
    if (pdata) *pdata = NULL;
3107
0
    if (psize) *psize = 0;
3108
0
    if (!pdata)
3109
0
        return ERROR_INT("&data not defined", __func__, 1);
3110
0
    if (!psize)
3111
0
        return ERROR_INT("&size not defined", __func__, 1);
3112
0
    if (!paa)
3113
0
        return ERROR_INT("paa not defined", __func__, 1);
3114
3115
0
#if HAVE_FMEMOPEN
3116
0
    if ((fp = open_memstream((char **)pdata, psize)) == NULL)
3117
0
        return ERROR_INT("stream not opened", __func__, 1);
3118
0
    ret = pixaaWriteStream(fp, paa);
3119
0
    fputc('\0', fp);
3120
0
    fclose(fp);
3121
0
    if (*psize > 0) *psize = *psize - 1;
3122
#else
3123
    L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
3124
  #ifdef _WIN32
3125
    if ((fp = fopenWriteWinTempfile()) == NULL)
3126
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
3127
  #else
3128
    if ((fp = tmpfile()) == NULL)
3129
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
3130
  #endif  /* _WIN32 */
3131
    ret = pixaaWriteStream(fp, paa);
3132
    rewind(fp);
3133
    *pdata = l_binaryReadStream(fp, psize);
3134
    fclose(fp);
3135
#endif  /* HAVE_FMEMOPEN */
3136
0
    return ret;
3137
0
}
3138