Coverage Report

Created: 2024-07-27 06:27

/src/leptonica/src/boxbasic.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  boxbasic.c
29
 * <pre>
30
 *
31
 *   Basic 'class' functions for box, boxa and boxaa,
32
 *   including accessors and serialization.
33
 *
34
 *      Box creation, copy, clone, destruction
35
 *           BOX      *boxCreate()
36
 *           BOX      *boxCreateValid()
37
 *           BOX      *boxCopy()
38
 *           BOX      *boxClone()
39
 *           void      boxDestroy()
40
 *
41
 *      Box accessors
42
 *           l_int32   boxGetGeometry()
43
 *           l_int32   boxSetGeometry()
44
 *           l_int32   boxGetSideLocations()
45
 *           l_int32   boxSetSideLocations()
46
 *           l_int32   boxIsValid()
47
 *
48
 *      Boxa creation, copy, destruction
49
 *           BOXA     *boxaCreate()
50
 *           BOXA     *boxaCopy()
51
 *           void      boxaDestroy()
52
 *
53
 *      Boxa array extension
54
 *           l_int32   boxaAddBox()
55
 *           l_int32   boxaExtendArray()
56
 *           l_int32   boxaExtendArrayToSize()
57
 *
58
 *      Boxa accessors
59
 *           l_int32   boxaGetCount()
60
 *           l_int32   boxaGetValidCount()
61
 *           BOX      *boxaGetBox()
62
 *           BOX      *boxaGetValidBox()
63
 *           NUMA     *boxaFindInvalidBoxes()
64
 *           l_int32   boxaGetBoxGeometry()
65
 *           l_int32   boxaIsFull()
66
 *
67
 *      Boxa array modifiers
68
 *           l_int32   boxaReplaceBox()
69
 *           l_int32   boxaInsertBox()
70
 *           l_int32   boxaRemoveBox()
71
 *           l_int32   boxaRemoveBoxAndSave()
72
 *           BOXA     *boxaSaveValid()
73
 *           l_int32   boxaInitFull()
74
 *           l_int32   boxaClear()
75
 *
76
 *      Boxaa creation, copy, destruction
77
 *           BOXAA    *boxaaCreate()
78
 *           BOXAA    *boxaaCopy()
79
 *           void      boxaaDestroy()
80
 *
81
 *      Boxaa array extension
82
 *           l_int32   boxaaAddBoxa()
83
 *           l_int32   boxaaExtendArray()
84
 *           l_int32   boxaaExtendArrayToSize()
85
 *
86
 *      Boxaa accessors
87
 *           l_int32   boxaaGetCount()
88
 *           l_int32   boxaaGetBoxCount()
89
 *           BOXA     *boxaaGetBoxa()
90
 *           BOX      *boxaaGetBox()
91
 *
92
 *      Boxaa array modifiers
93
 *           l_int32   boxaaInitFull()
94
 *           l_int32   boxaaExtendWithInit()
95
 *           l_int32   boxaaReplaceBoxa()
96
 *           l_int32   boxaaInsertBoxa()
97
 *           l_int32   boxaaRemoveBoxa()
98
 *           l_int32   boxaaAddBox()
99
 *
100
 *      Boxaa serialized I/O
101
 *           BOXAA    *boxaaReadFromFiles()
102
 *           BOXAA    *boxaaRead()
103
 *           BOXAA    *boxaaReadStream()
104
 *           BOXAA    *boxaaReadMem()
105
 *           l_int32   boxaaWrite()
106
 *           l_int32   boxaaWriteStream()
107
 *           l_int32   boxaaWriteMem()
108
 *
109
 *      Boxa serialized I/O
110
 *           BOXA     *boxaRead()
111
 *           BOXA     *boxaReadStream()
112
 *           BOXA     *boxaReadMem()
113
 *           l_int32   boxaWriteDebug()
114
 *           l_int32   boxaWrite()
115
 *           l_int32   boxaWriteStream()
116
 *           l_int32   boxaWriteStderr()
117
 *           l_int32   boxaWriteMem()
118
 *
119
 *      Box print (for debug)
120
 *           l_int32   boxPrintStreamInfo()
121
 *
122
 *   Most functions use only valid boxes, which are boxes that have both
123
 *   width and height > 0.  However, a few functions, such as
124
 *   boxaGetMedianVals() do not assume that all boxes are valid.  For any
125
 *   function that can use a boxa with invalid boxes, it is convenient
126
 *   to use these accessors:
127
 *       boxaGetValidCount()   :  count of valid boxes
128
 *       boxaGetValidBox()     :  returns NULL for invalid boxes
129
 * </pre>
130
 */
131
132
#ifdef HAVE_CONFIG_H
133
#include <config_auto.h>
134
#endif  /* HAVE_CONFIG_H */
135
136
#include <string.h>
137
#include "allheaders.h"
138
#include "pix_internal.h"
139
140
    /* Bounds on array sizes */
141
static const size_t  MaxBoxaPtrArraySize = 10000000;
142
static const size_t  MaxBoxaaPtrArraySize = 1000000;
143
static const size_t  InitialPtrArraySize = 20;      /*!< n'importe quoi */
144
145
/*---------------------------------------------------------------------*
146
 *                  Box creation, destruction and copy                 *
147
 *---------------------------------------------------------------------*/
148
/*!
149
 * \brief   boxCreate()
150
 *
151
 * \param[in]    x, y, w, h
152
 * \return  box, or NULL on error
153
 *
154
 * <pre>
155
 * Notes:
156
 *      (1) This clips the box to the +quad.  If no part of the
157
 *          box is in the +quad, this returns NULL.
158
 *      (2) We allow you to make a box with w = 0 and/or h = 0.
159
 *          This does not represent a valid region, but it is useful
160
 *          as a placeholder in a boxa for which the index of the
161
 *          box in the boxa is important.  This is an atypical
162
 *          situation; usually you want to put only valid boxes with
163
 *          nonzero width and height in a boxa.  If you have a boxa
164
 *          with invalid boxes, the accessor boxaGetValidBox()
165
 *          will return NULL on each invalid box.
166
 *      (3) If you want to create only valid boxes, use boxCreateValid(),
167
 *          which returns NULL if either w or h is 0.
168
 * </pre>
169
 */
170
BOX *
171
boxCreate(l_int32  x,
172
          l_int32  y,
173
          l_int32  w,
174
          l_int32  h)
175
154
{
176
154
BOX  *box;
177
178
154
    if (w < 0 || h < 0)
179
0
        return (BOX *)ERROR_PTR("w and h not both >= 0", __func__, NULL);
180
154
    if (x < 0) {  /* take part in +quad */
181
0
        w = w + x;
182
0
        x = 0;
183
0
        if (w <= 0)
184
0
            return (BOX *)ERROR_PTR("x < 0 and box off +quad", __func__, NULL);
185
0
    }
186
154
    if (y < 0) {  /* take part in +quad */
187
0
        h = h + y;
188
0
        y = 0;
189
0
        if (h <= 0)
190
0
            return (BOX *)ERROR_PTR("y < 0 and box off +quad", __func__, NULL);
191
0
    }
192
193
154
    box = (BOX *)LEPT_CALLOC(1, sizeof(BOX));
194
154
    boxSetGeometry(box, x, y, w, h);
195
154
    box->refcount = 1;
196
154
    return box;
197
154
}
198
199
200
/*!
201
 * \brief   boxCreateValid()
202
 *
203
 * \param[in]    x, y, w, h
204
 * \return  box, or NULL on error
205
 *
206
 * <pre>
207
 * Notes:
208
 *      (1) This returns NULL if either w = 0 or h = 0.
209
 * </pre>
210
 */
211
BOX *
212
boxCreateValid(l_int32  x,
213
               l_int32  y,
214
               l_int32  w,
215
               l_int32  h)
216
0
{
217
0
    if (w <= 0 || h <= 0)
218
0
        return (BOX *)ERROR_PTR("w and h not both > 0", __func__, NULL);
219
0
    return boxCreate(x, y, w, h);
220
0
}
221
222
223
/*!
224
 * \brief   boxCopy()
225
 *
226
 * \param[in]    box
227
 * \return  copy of box, or NULL on error
228
 */
229
BOX *
230
boxCopy(BOX  *box)
231
0
{
232
0
BOX  *boxc;
233
234
0
    if (!box)
235
0
        return (BOX *)ERROR_PTR("box not defined", __func__, NULL);
236
237
0
    boxc = boxCreate(box->x, box->y, box->w, box->h);
238
0
    return boxc;
239
0
}
240
241
242
/*!
243
 * \brief   boxClone()
244
 *
245
 * \param[in]    box
246
 * \return  ptr to same box, or NULL on error
247
 */
248
BOX *
249
boxClone(BOX  *box)
250
0
{
251
252
0
    if (!box)
253
0
        return (BOX *)ERROR_PTR("box not defined", __func__, NULL);
254
255
0
    ++box->refcount;
256
0
    return box;
257
0
}
258
259
260
/*!
261
 * \brief   boxDestroy()
262
 *
263
 * \param[in,out]   pbox     will be set to null before returning
264
 * \return  void
265
 *
266
 * <pre>
267
 * Notes:
268
 *      (1) Decrements the ref count and, if 0, destroys the box.
269
 *      (2) Always nulls the input ptr.
270
 * </pre>
271
 */
272
void
273
boxDestroy(BOX  **pbox)
274
154
{
275
154
BOX  *box;
276
277
154
    if (pbox == NULL) {
278
0
        L_WARNING("ptr address is null!\n", __func__);
279
0
        return;
280
0
    }
281
154
    if ((box = *pbox) == NULL)
282
0
        return;
283
284
154
    if (--box->refcount == 0)
285
154
        LEPT_FREE(box);
286
154
    *pbox = NULL;
287
154
}
288
289
290
/*---------------------------------------------------------------------*
291
 *                              Box accessors                          *
292
 *---------------------------------------------------------------------*/
293
/*!
294
 * \brief   boxGetGeometry()
295
 *
296
 * \param[in]    box
297
 * \param[out]   px, py, pw, ph [optional]  each can be null
298
 * \return  0 if OK, 1 on error
299
 */
300
l_ok
301
boxGetGeometry(const BOX *box,
302
               l_int32   *px,
303
               l_int32   *py,
304
               l_int32   *pw,
305
               l_int32   *ph)
306
95
{
307
95
    if (px) *px = 0;
308
95
    if (py) *py = 0;
309
95
    if (pw) *pw = 0;
310
95
    if (ph) *ph = 0;
311
95
    if (!box)
312
0
        return ERROR_INT("box not defined", __func__, 1);
313
95
    if (px) *px = box->x;
314
95
    if (py) *py = box->y;
315
95
    if (pw) *pw = box->w;
316
95
    if (ph) *ph = box->h;
317
95
    return 0;
318
95
}
319
320
321
/*!
322
 * \brief   boxSetGeometry()
323
 *
324
 * \param[in]    box
325
 * \param[in]    x, y, w, h     [optional] use -1 to leave unchanged
326
 * \return  0 if OK, 1 on error
327
 */
328
l_ok
329
boxSetGeometry(BOX     *box,
330
               l_int32  x,
331
               l_int32  y,
332
               l_int32  w,
333
               l_int32  h)
334
154
{
335
154
    if (!box)
336
0
        return ERROR_INT("box not defined", __func__, 1);
337
154
    if (x != -1) box->x = x;
338
154
    if (y != -1) box->y = y;
339
154
    if (w != -1) box->w = w;
340
154
    if (h != -1) box->h = h;
341
154
    return 0;
342
154
}
343
344
345
/*!
346
 * \brief   boxGetSideLocations()
347
 *
348
 * \param[in]    box
349
 * \param[out]   pl, pr, pt, pb     [optional] each can be null
350
 * \return  0 if OK, 1 on error
351
 *
352
 * <pre>
353
 * Notes:
354
 *      (1) All returned values are within the box.
355
 * </pre>
356
 */
357
l_ok
358
boxGetSideLocations(const BOX *box,
359
                    l_int32   *pl,
360
                    l_int32   *pr,
361
                    l_int32   *pt,
362
                    l_int32   *pb)
363
0
{
364
0
l_int32  x, y, w, h;
365
366
0
    if (pl) *pl = 0;
367
0
    if (pr) *pr = 0;
368
0
    if (pt) *pt = 0;
369
0
    if (pb) *pb = 0;
370
0
    if (!box)
371
0
        return ERROR_INT("box not defined", __func__, 1);
372
373
0
    boxGetGeometry(box, &x, &y, &w, &h);
374
0
    if (pl) *pl = x;
375
0
    if (pr) *pr = x + w - 1;
376
0
    if (pt) *pt = y;
377
0
    if (pb) *pb = y + h - 1;
378
0
    return 0;
379
0
}
380
381
382
/*!
383
 * \brief   boxSetSideLocations()
384
 *
385
 * \param[in]    box
386
 * \param[in]    l, r, t, b     [optional] use -1 to leave unchanged
387
 * \return  0 if OK, 1 on error
388
 */
389
l_ok
390
boxSetSideLocations(BOX     *box,
391
                    l_int32  l,
392
                    l_int32  r,
393
                    l_int32  t,
394
                    l_int32  b)
395
0
{
396
0
l_int32  x, y, w, h;
397
398
0
    if (!box)
399
0
        return ERROR_INT("box not defined", __func__, 1);
400
0
    x = (l != -1) ? l : box->x;
401
0
    w = (r != -1) ? r - x + 1 : box->x + box->w - x;
402
0
    y = (t != -1) ? t : box->y;
403
0
    h = (b != -1) ? b - y + 1 : box->y + box->h - y;
404
0
    boxSetGeometry(box, x, y, w, h);
405
0
    return 0;
406
0
}
407
408
409
/*!
410
 * \brief   boxIsValid()
411
 *
412
 * \param[in]    box
413
 * \param[out]   pvalid    1 if valid; 0 otherwise
414
 * \return  0 if OK, 1 on error
415
 */
416
l_ok
417
boxIsValid(BOX      *box,
418
           l_int32  *pvalid)
419
0
{
420
0
    if (!pvalid)
421
0
        return ERROR_INT("&valid not defined", __func__, 1);
422
0
    *pvalid = 0;
423
0
    if (!box)
424
0
        return ERROR_INT("box not defined", __func__, 1);
425
426
0
    if (box->w > 0 && box->h > 0)
427
0
        *pvalid = 1;
428
0
    return 0;
429
0
}
430
431
432
/*---------------------------------------------------------------------*
433
 *             Boxa creation, destruction, copy, extension             *
434
 *---------------------------------------------------------------------*/
435
/*!
436
 * \brief   boxaCreate()
437
 *
438
 * \param[in]    n    initial number of ptrs; 0 for default
439
 * \return  boxa, or NULL on error
440
 */
441
BOXA *
442
boxaCreate(l_int32  n)
443
0
{
444
0
BOXA  *boxa;
445
446
0
    if (n <= 0 || n > MaxBoxaPtrArraySize)
447
0
        n = InitialPtrArraySize;
448
449
0
    boxa = (BOXA *)LEPT_CALLOC(1, sizeof(BOXA));
450
0
    boxa->n = 0;
451
0
    boxa->nalloc = n;
452
0
    boxa->refcount = 1;
453
0
    if ((boxa->box = (BOX **)LEPT_CALLOC(n, sizeof(BOX *))) == NULL) {
454
0
        boxaDestroy(&boxa);
455
0
        return (BOXA *)ERROR_PTR("boxa ptrs not made", __func__, NULL);
456
0
    }
457
0
    return boxa;
458
0
}
459
460
461
/*!
462
 * \brief   boxaCopy()
463
 *
464
 * \param[in]    boxa
465
 * \param[in]    copyflag    L_COPY, L_CLONE, L_COPY_CLONE
466
 * \return  new boxa, or NULL on error
467
 *
468
 * <pre>
469
 * Notes:
470
 *      (1) See pix.h for description of the copyflag.
471
 *      (2) The copy-clone makes a new boxa that holds clones of each box.
472
 * </pre>
473
 */
474
BOXA *
475
boxaCopy(BOXA    *boxa,
476
         l_int32  copyflag)
477
0
{
478
0
l_int32  i;
479
0
BOX     *boxc;
480
0
BOXA    *boxac;
481
482
0
    if (!boxa)
483
0
        return (BOXA *)ERROR_PTR("boxa not defined", __func__, NULL);
484
485
0
    if (copyflag == L_CLONE) {
486
0
        boxa->refcount++;
487
0
        return boxa;
488
0
    }
489
490
0
    if (copyflag != L_COPY && copyflag != L_COPY_CLONE)
491
0
        return (BOXA *)ERROR_PTR("invalid copyflag", __func__, NULL);
492
493
0
    if ((boxac = boxaCreate(boxa->nalloc)) == NULL)
494
0
        return (BOXA *)ERROR_PTR("boxac not made", __func__, NULL);
495
0
    for (i = 0; i < boxa->n; i++) {
496
0
        if (copyflag == L_COPY)
497
0
            boxc = boxaGetBox(boxa, i, L_COPY);
498
0
        else   /* copy-clone */
499
0
            boxc = boxaGetBox(boxa, i, L_CLONE);
500
0
        boxaAddBox(boxac, boxc, L_INSERT);
501
0
    }
502
0
    return boxac;
503
0
}
504
505
506
/*!
507
 * \brief   boxaDestroy()
508
 *
509
 * \param[in,out]   pboxa    will be set to null before returning
510
 * \return  void
511
 *
512
 * <pre>
513
 * Notes:
514
 *      (1) Decrements the ref count and, if 0, destroys the boxa.
515
 *      (2) Always nulls the input ptr.
516
 * </pre>
517
 */
518
void
519
boxaDestroy(BOXA  **pboxa)
520
0
{
521
0
l_int32  i;
522
0
BOXA    *boxa;
523
524
0
    if (pboxa == NULL) {
525
0
        L_WARNING("ptr address is null!\n", __func__);
526
0
        return;
527
0
    }
528
529
0
    if ((boxa = *pboxa) == NULL)
530
0
        return;
531
532
        /* Decrement the ref count.  If it is 0, destroy the boxa. */
533
0
    if (--boxa->refcount == 0) {
534
0
        for (i = 0; i < boxa->n; i++)
535
0
            boxDestroy(&boxa->box[i]);
536
0
        LEPT_FREE(boxa->box);
537
0
        LEPT_FREE(boxa);
538
0
    }
539
540
0
    *pboxa = NULL;
541
0
}
542
543
544
/*!
545
 * \brief   boxaAddBox()
546
 *
547
 * \param[in]    boxa
548
 * \param[in]    box         to be added
549
 * \param[in]    copyflag    L_INSERT, L_COPY, L_CLONE
550
 * \return  0 if OK, 1 on error
551
 */
552
l_ok
553
boxaAddBox(BOXA    *boxa,
554
           BOX     *box,
555
           l_int32  copyflag)
556
0
{
557
0
l_int32  n;
558
0
BOX     *boxc;
559
560
0
    if (!boxa)
561
0
        return ERROR_INT("boxa not defined", __func__, 1);
562
0
    if (!box)
563
0
        return ERROR_INT("box not defined", __func__, 1);
564
565
0
    if (copyflag == L_INSERT)
566
0
        boxc = box;
567
0
    else if (copyflag == L_COPY)
568
0
        boxc = boxCopy(box);
569
0
    else if (copyflag == L_CLONE)
570
0
        boxc = boxClone(box);
571
0
    else
572
0
        return ERROR_INT("invalid copyflag", __func__, 1);
573
0
    if (!boxc)
574
0
        return ERROR_INT("boxc not made", __func__, 1);
575
576
0
    n = boxaGetCount(boxa);
577
0
    if (n >= boxa->nalloc) {
578
0
        if (boxaExtendArray(boxa)) {
579
0
            if (copyflag != L_INSERT)
580
0
                boxDestroy(&boxc);
581
0
            return ERROR_INT("extension failed", __func__, 1);
582
0
        }
583
0
    }
584
0
    boxa->box[n] = boxc;
585
0
    boxa->n++;
586
0
    return 0;
587
0
}
588
589
590
/*!
591
 * \brief   boxaExtendArray()
592
 *
593
 * \param[in]    boxa
594
 * \return  0 if OK; 1 on error
595
 *
596
 * <pre>
597
 * Notes:
598
 *      (1) Reallocs with doubled size of ptr array.
599
 * </pre>
600
 */
601
l_ok
602
boxaExtendArray(BOXA  *boxa)
603
0
{
604
0
    if (!boxa)
605
0
        return ERROR_INT("boxa not defined", __func__, 1);
606
607
0
    return boxaExtendArrayToSize(boxa, 2 * boxa->nalloc);
608
0
}
609
610
611
/*!
612
 * \brief   boxaExtendArrayToSize()
613
 *
614
 * \param[in]    boxa
615
 * \param[in]    size     new size of boxa ptr array
616
 * \return  0 if OK; 1 on error
617
 *
618
 * <pre>
619
 * Notes:
620
 *      (1) If necessary, reallocs new boxa ptr array to %size.
621
 *      (2) The max number of box ptrs is 10M.
622
 * </pre>
623
 */
624
l_ok
625
boxaExtendArrayToSize(BOXA   *boxa,
626
                      size_t  size)
627
0
{
628
0
size_t  oldsize, newsize;
629
630
0
    if (!boxa)
631
0
        return ERROR_INT("boxa not defined", __func__, 1);
632
0
    if (boxa->nalloc > MaxBoxaPtrArraySize)  /* belt & suspenders */
633
0
        return ERROR_INT("boxa has too many ptrs", __func__, 1);
634
0
    if (size > MaxBoxaPtrArraySize)
635
0
        return ERROR_INT("size > 10M box ptrs; too large", __func__, 1);
636
0
    if (size <= boxa->nalloc) {
637
0
        L_INFO("size too small; no extension\n", __func__);
638
0
        return 0;
639
0
    }
640
641
0
    oldsize = boxa->nalloc * sizeof(BOX *);
642
0
    newsize = size * sizeof(BOX *);
643
0
    if ((boxa->box = (BOX **)reallocNew((void **)&boxa->box,
644
0
                                        oldsize, newsize)) == NULL)
645
0
        return ERROR_INT("new ptr array not returned", __func__, 1);
646
0
    boxa->nalloc = size;
647
0
    return 0;
648
0
}
649
650
651
/*---------------------------------------------------------------------*
652
 *                             Boxa accessors                          *
653
 *---------------------------------------------------------------------*/
654
/*!
655
 * \brief   boxaGetCount()
656
 *
657
 * \param[in]    boxa
658
 * \return  count of all boxes; 0 if no boxes or on error
659
 */
660
l_int32
661
boxaGetCount(const BOXA  *boxa)
662
0
{
663
0
    if (!boxa)
664
0
        return ERROR_INT("boxa not defined", __func__, 0);
665
0
    return boxa->n;
666
0
}
667
668
669
/*!
670
 * \brief   boxaGetValidCount()
671
 *
672
 * \param[in]    boxa
673
 * \return  count of valid boxes; 0 if no valid boxes or on error
674
 */
675
l_int32
676
boxaGetValidCount(BOXA  *boxa)
677
0
{
678
0
l_int32  n, i, w, h, count;
679
680
0
    if (!boxa)
681
0
        return ERROR_INT("boxa not defined", __func__, 0);
682
683
0
    n = boxaGetCount(boxa);
684
0
    for (i = 0, count = 0; i < n; i++) {
685
0
        boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
686
0
        if (w > 0 && h > 0)
687
0
            count++;
688
0
    }
689
0
    return count;
690
0
}
691
692
693
/*!
694
 * \brief   boxaGetBox()
695
 *
696
 * \param[in]    boxa
697
 * \param[in]    index        to the index-th box
698
 * \param[in]    accessflag   L_COPY or L_CLONE
699
 * \return  box, or NULL on error
700
 */
701
BOX *
702
boxaGetBox(BOXA    *boxa,
703
           l_int32  index,
704
           l_int32  accessflag)
705
0
{
706
0
    if (!boxa)
707
0
        return (BOX *)ERROR_PTR("boxa not defined", __func__, NULL);
708
0
    if (index < 0 || index >= boxa->n)
709
0
        return (BOX *)ERROR_PTR("index not valid", __func__, NULL);
710
711
0
    if (accessflag == L_COPY)
712
0
        return boxCopy(boxa->box[index]);
713
0
    else if (accessflag == L_CLONE)
714
0
        return boxClone(boxa->box[index]);
715
0
    else
716
0
        return (BOX *)ERROR_PTR("invalid accessflag", __func__, NULL);
717
0
}
718
719
720
/*!
721
 * \brief   boxaGetValidBox()
722
 *
723
 * \param[in]    boxa
724
 * \param[in]    index        to the index-th box
725
 * \param[in]    accessflag   L_COPY or L_CLONE
726
 * \return  box, or NULL if box is not valid or on error
727
 *
728
 * <pre>
729
 * Notes:
730
 *      (1) This returns NULL for an invalid box in a boxa.
731
 *          For a box to be valid, both the width and height must be > 0.
732
 *      (2) We allow invalid boxes, with w = 0 or h = 0, as placeholders
733
 *          in boxa for which the index of the box in the boxa is important.
734
 *          This is an atypical situation; usually you want to put only
735
 *          valid boxes in a boxa.
736
 * </pre>
737
 */
738
BOX *
739
boxaGetValidBox(BOXA    *boxa,
740
                l_int32  index,
741
                l_int32  accessflag)
742
0
{
743
0
l_int32  w, h;
744
0
BOX     *box;
745
746
0
    if (!boxa)
747
0
        return (BOX *)ERROR_PTR("boxa not defined", __func__, NULL);
748
749
0
    if ((box = boxaGetBox(boxa, index, accessflag)) == NULL)
750
0
        return (BOX *)ERROR_PTR("box not returned", __func__, NULL);
751
0
    boxGetGeometry(box, NULL, NULL, &w, &h);
752
0
    if (w <= 0 || h <= 0)  /* not valid, but not necessarily an error */
753
0
        boxDestroy(&box);
754
0
    return box;
755
0
}
756
757
758
/*!
759
 * \brief   boxaFindInvalidBoxes()
760
 *
761
 * \param[in]    boxa
762
 * \return  na   numa of invalid boxes; NULL if there are none or on error
763
 */
764
NUMA *
765
boxaFindInvalidBoxes(BOXA  *boxa)
766
0
{
767
0
l_int32  i, n, w, h;
768
0
NUMA    *na;
769
770
0
    if (!boxa)
771
0
        return (NUMA *)ERROR_PTR("boxa not defined", __func__, NULL);
772
773
0
    n = boxaGetCount(boxa);
774
0
    if (boxaGetValidCount(boxa) == n)
775
0
        return NULL;
776
777
0
    na = numaMakeConstant(0, n);
778
0
    for (i = 0; i < n; i++) {
779
0
        boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
780
0
        if (w == 0 || h == 0)
781
0
            numaSetValue(na, i, 1);
782
0
    }
783
0
    return na;
784
0
}
785
786
787
/*!
788
 * \brief   boxaGetBoxGeometry()
789
 *
790
 * \param[in]    boxa
791
 * \param[in]    index            to the index-th box
792
 * \param[out]   px, py, pw, ph   [optional] each can be null
793
 * \return  0 if OK, 1 on error
794
 */
795
l_ok
796
boxaGetBoxGeometry(BOXA     *boxa,
797
                   l_int32   index,
798
                   l_int32  *px,
799
                   l_int32  *py,
800
                   l_int32  *pw,
801
                   l_int32  *ph)
802
0
{
803
0
BOX  *box;
804
805
0
    if (px) *px = 0;
806
0
    if (py) *py = 0;
807
0
    if (pw) *pw = 0;
808
0
    if (ph) *ph = 0;
809
0
    if (!boxa)
810
0
        return ERROR_INT("boxa not defined", __func__, 1);
811
0
    if (index < 0 || index >= boxa->n)
812
0
        return ERROR_INT("index not valid", __func__, 1);
813
814
0
    if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL)
815
0
        return ERROR_INT("box not found!", __func__, 1);
816
0
    boxGetGeometry(box, px, py, pw, ph);
817
0
    boxDestroy(&box);
818
0
    return 0;
819
0
}
820
821
822
/*!
823
 * \brief   boxaIsFull()
824
 *
825
 * \param[in]    boxa
826
 * \param[out]   pfull    1 if boxa is full; 0 otherwise
827
 * \return  0 if OK, 1 on error
828
 */
829
l_ok
830
boxaIsFull(BOXA     *boxa,
831
           l_int32  *pfull)
832
0
{
833
0
l_int32  i, n, full;
834
0
BOX     *box;
835
836
0
    if (!pfull)
837
0
        return ERROR_INT("&full not defined", __func__, 1);
838
0
    *pfull = 0;
839
0
    if (!boxa)
840
0
        return ERROR_INT("boxa not defined", __func__, 1);
841
842
0
    n = boxaGetCount(boxa);
843
0
    full = 1;
844
0
    for (i = 0; i < n; i++) {
845
0
        if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL) {
846
0
            full = 0;
847
0
            break;
848
0
        }
849
0
        boxDestroy(&box);
850
0
    }
851
0
    *pfull = full;
852
0
    return 0;
853
0
}
854
855
856
/*---------------------------------------------------------------------*
857
 *                        Boxa array modifiers                         *
858
 *---------------------------------------------------------------------*/
859
/*!
860
 * \brief   boxaReplaceBox()
861
 *
862
 * \param[in]    boxa
863
 * \param[in]    index     to the index-th box
864
 * \param[in]    box       insert this box to replace existing one
865
 * \return  0 if OK, 1 on error
866
 *
867
 * <pre>
868
 * Notes:
869
 *      (1) In-place replacement of one box; the input %box is now
870
 *          owned by the boxa.
871
 *      (2) The previous box at that location, if any, is destroyed.
872
 * </pre>
873
 */
874
l_ok
875
boxaReplaceBox(BOXA    *boxa,
876
               l_int32  index,
877
               BOX     *box)
878
0
{
879
0
    if (!boxa)
880
0
        return ERROR_INT("boxa not defined", __func__, 1);
881
0
    if (index < 0 || index >= boxa->n)
882
0
        return ERROR_INT("index not valid", __func__, 1);
883
0
    if (!box)
884
0
        return ERROR_INT("box not defined", __func__, 1);
885
886
0
    boxDestroy(&(boxa->box[index]));
887
0
    boxa->box[index] = box;
888
0
    return 0;
889
0
}
890
891
892
/*!
893
 * \brief   boxaInsertBox()
894
 *
895
 * \param[in]    boxa
896
 * \param[in]    index    location in boxa to insert new value
897
 * \param[in]    box      new box to be inserted; the boxa now owns it
898
 * \return  0 if OK, 1 on error
899
 *
900
 * <pre>
901
 * Notes:
902
 *      (1) This shifts box[i] --> box[i + 1] for all i >= index,
903
 *          and then inserts box as box[index].
904
 *      (2) To insert at the beginning of the array, set index = 0.
905
 *      (3) To append to the array, it's easier to use boxaAddBox().
906
 *      (4) This should not be used repeatedly to insert into large arrays,
907
 *          because the function is O(n).
908
 * </pre>
909
 */
910
l_ok
911
boxaInsertBox(BOXA    *boxa,
912
              l_int32  index,
913
              BOX     *box)
914
0
{
915
0
l_int32  i, n;
916
0
BOX    **array;
917
918
0
    if (!boxa)
919
0
        return ERROR_INT("boxa not defined", __func__, 1);
920
0
    n = boxaGetCount(boxa);
921
0
    if (index < 0 || index > n) {
922
0
        L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n);
923
0
        return 1;
924
0
    }
925
0
    if (!box)
926
0
        return ERROR_INT("box not defined", __func__, 1);
927
928
0
    if (n >= boxa->nalloc) {
929
0
        if (boxaExtendArray(boxa))
930
0
            return ERROR_INT("extension failed", __func__, 1);
931
0
    }
932
0
    array = boxa->box;
933
0
    boxa->n++;
934
0
    for (i = n; i > index; i--)
935
0
        array[i] = array[i - 1];
936
0
    array[index] = box;
937
0
    return 0;
938
0
}
939
940
941
/*!
942
 * \brief   boxaRemoveBox()
943
 *
944
 * \param[in]    boxa
945
 * \param[in]    index    of box to be removed and destroyed
946
 * \return  0 if OK, 1 on error
947
 *
948
 * <pre>
949
 * Notes:
950
 *      (1) This removes box[index] and then shifts
951
 *          box[i] --> box[i - 1] for all i > index.
952
 *      (2) It should not be used repeatedly to remove boxes from
953
 *          large arrays, because the function is O(n).
954
 * </pre>
955
 */
956
l_ok
957
boxaRemoveBox(BOXA    *boxa,
958
              l_int32  index)
959
0
{
960
0
    return boxaRemoveBoxAndSave(boxa, index, NULL);
961
0
}
962
963
964
/*!
965
 * \brief   boxaRemoveBoxAndSave()
966
 *
967
 * \param[in]    boxa
968
 * \param[in]    index     of box to be removed
969
 * \param[out]   pbox      [optional] removed box
970
 * \return  0 if OK, 1 on error
971
 *
972
 * <pre>
973
 * Notes:
974
 *      (1) This removes box[index] and then shifts
975
 *          box[i] --> box[i - 1] for all i > index.
976
 *      (2) It should not be used repeatedly to remove boxes from
977
 *          large arrays, because the function is O(n).
978
 * </pre>
979
 */
980
l_ok
981
boxaRemoveBoxAndSave(BOXA    *boxa,
982
                     l_int32  index,
983
                     BOX    **pbox)
984
0
{
985
0
l_int32  i, n;
986
0
BOX    **array;
987
988
0
    if (pbox) *pbox = NULL;
989
0
    if (!boxa)
990
0
        return ERROR_INT("boxa not defined", __func__, 1);
991
0
    n = boxaGetCount(boxa);
992
0
    if (index < 0 || index >= n) {
993
0
        L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n - 1);
994
0
        return 1;
995
0
    }
996
997
0
    if (pbox)
998
0
        *pbox = boxaGetBox(boxa, index, L_CLONE);
999
0
    array = boxa->box;
1000
0
    boxDestroy(&array[index]);
1001
0
    for (i = index + 1; i < n; i++)
1002
0
        array[i - 1] = array[i];
1003
0
    array[n - 1] = NULL;
1004
0
    boxa->n--;
1005
1006
0
    return 0;
1007
0
}
1008
1009
1010
/*!
1011
 * \brief   boxaSaveValid()
1012
 *
1013
 * \param[in]    boxas
1014
 * \param[in]    copyflag    L_COPY or L_CLONE
1015
 * \return  boxad if OK, NULL on error
1016
 *
1017
 * <pre>
1018
 * Notes:
1019
 *      (1) This makes a copy/clone of each valid box.
1020
 * </pre>
1021
 */
1022
BOXA *
1023
boxaSaveValid(BOXA    *boxas,
1024
              l_int32  copyflag)
1025
0
{
1026
0
l_int32  i, n;
1027
0
BOX     *box;
1028
0
BOXA    *boxad;
1029
1030
0
    if (!boxas)
1031
0
        return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
1032
0
    if (copyflag != L_COPY && copyflag != L_CLONE)
1033
0
        return (BOXA *)ERROR_PTR("invalid copyflag", __func__, NULL);
1034
1035
0
    n = boxaGetCount(boxas);
1036
0
    boxad = boxaCreate(n);
1037
0
    for (i = 0; i < n; i++) {
1038
0
        if ((box = boxaGetValidBox(boxas, i, copyflag)) != NULL)
1039
0
            boxaAddBox(boxad, box, L_INSERT);
1040
0
    }
1041
1042
0
    return boxad;
1043
0
}
1044
1045
1046
/*!
1047
 * \brief   boxaInitFull()
1048
 *
1049
 * \param[in]    boxa    typically empty
1050
 * \param[in]    box     [optional] to be replicated into the entire ptr array
1051
 * \return  0 if OK, 1 on error
1052
 *
1053
 * <pre>
1054
 * Notes:
1055
 *      (1) This initializes a boxa by filling up the entire box ptr array
1056
 *          with copies of %box.  If %box == NULL, use a placeholder box
1057
 *          of zero size.  Any existing boxes are destroyed.
1058
 *          After this opepration, the number of boxes is equal to
1059
 *          the number of allocated ptrs.
1060
 *      (2) Note that we use boxaReplaceBox() instead of boxaInsertBox().
1061
 *          They both have the same effect when inserting into a NULL ptr
1062
 *          in the boxa ptr array:
1063
 *      (3) Example usage.  This function is useful to prepare for a
1064
 *          random insertion (or replacement) of boxes into a boxa.
1065
 *          To randomly insert boxes into a boxa, up to some index "max":
1066
 *             Boxa *boxa = boxaCreate(max);
1067
 *             boxaInitFull(boxa, NULL);
1068
 *          If you want placeholder boxes of non-zero size:
1069
 *             Boxa *boxa = boxaCreate(max);
1070
 *             Box *box = boxCreate(...);
1071
 *             boxaInitFull(boxa, box);
1072
 *             boxDestroy(&box);
1073
 *          If we have an existing boxa with a smaller ptr array, it can
1074
 *          be reused for up to max boxes:
1075
 *             boxaExtendArrayToSize(boxa, max);
1076
 *             boxaInitFull(boxa, NULL);
1077
 *          The initialization allows the boxa to always be properly
1078
 *          filled, even if all the boxes are not later replaced.
1079
 *          If you want to know which boxes have been replaced,
1080
 *          and you initialized with invalid zero-sized boxes,
1081
 *          use boxaGetValidBox() to return NULL for the invalid boxes.
1082
 * </pre>
1083
 */
1084
l_ok
1085
boxaInitFull(BOXA  *boxa,
1086
             BOX   *box)
1087
0
{
1088
0
l_int32  i, n;
1089
0
BOX     *boxt;
1090
1091
0
    if (!boxa)
1092
0
        return ERROR_INT("boxa not defined", __func__, 1);
1093
1094
0
    n = boxa->nalloc;
1095
0
    boxa->n = n;
1096
0
    for (i = 0; i < n; i++) {
1097
0
        if (box)
1098
0
            boxt = boxCopy(box);
1099
0
        else
1100
0
            boxt = boxCreate(0, 0, 0, 0);
1101
0
        boxaReplaceBox(boxa, i, boxt);
1102
0
    }
1103
0
    return 0;
1104
0
}
1105
1106
1107
/*!
1108
 * \brief   boxaClear()
1109
 *
1110
 * \param[in]    boxa
1111
 * \return  0 if OK, 1 on error
1112
 *
1113
 * <pre>
1114
 * Notes:
1115
 *      (1) This destroys all boxes in the boxa, setting the ptrs
1116
 *          to null.  The number of allocated boxes, n, is set to 0.
1117
 * </pre>
1118
 */
1119
l_ok
1120
boxaClear(BOXA  *boxa)
1121
0
{
1122
0
l_int32  i, n;
1123
1124
0
    if (!boxa)
1125
0
        return ERROR_INT("boxa not defined", __func__, 1);
1126
1127
0
    n = boxaGetCount(boxa);
1128
0
    for (i = 0; i < n; i++)
1129
0
        boxDestroy(&boxa->box[i]);
1130
0
    boxa->n = 0;
1131
0
    return 0;
1132
0
}
1133
1134
1135
/*--------------------------------------------------------------------------*
1136
 *                     Boxaa creation, destruction                          *
1137
 *--------------------------------------------------------------------------*/
1138
/*!
1139
 * \brief   boxaaCreate()
1140
 *
1141
 * \param[in]    n     size of boxa ptr array to be alloc'd; 0 for default
1142
 * \return  baa, or NULL on error
1143
 */
1144
BOXAA *
1145
boxaaCreate(l_int32  n)
1146
0
{
1147
0
BOXAA  *baa;
1148
1149
0
    if (n <= 0 || n > MaxBoxaaPtrArraySize)
1150
0
        n = InitialPtrArraySize;
1151
1152
0
    baa = (BOXAA *)LEPT_CALLOC(1, sizeof(BOXAA));
1153
0
    if ((baa->boxa = (BOXA **)LEPT_CALLOC(n, sizeof(BOXA *))) == NULL) {
1154
0
        boxaaDestroy(&baa);
1155
0
        return (BOXAA *)ERROR_PTR("boxa ptr array not made", __func__, NULL);
1156
0
    }
1157
0
    baa->nalloc = n;
1158
0
    baa->n = 0;
1159
0
    return baa;
1160
0
}
1161
1162
1163
/*!
1164
 * \brief   boxaaCopy()
1165
 *
1166
 * \param[in]    baas       input boxaa to be copied
1167
 * \param[in]    copyflag   L_COPY, L_CLONE
1168
 * \return  baad new boxaa, composed of copies or clones of the boxa
1169
 *                    in baas, or NULL on error
1170
 *
1171
 * <pre>
1172
 * Notes:
1173
 *      (1) L_COPY makes a copy of each boxa in baas.
1174
 *          L_CLONE makes a clone of each boxa in baas.
1175
 * </pre>
1176
 */
1177
BOXAA *
1178
boxaaCopy(BOXAA   *baas,
1179
          l_int32  copyflag)
1180
0
{
1181
0
l_int32  i, n;
1182
0
BOXA    *boxa;
1183
0
BOXAA   *baad;
1184
1185
0
    if (!baas)
1186
0
        return (BOXAA *)ERROR_PTR("baas not defined", __func__, NULL);
1187
0
    if (copyflag != L_COPY && copyflag != L_CLONE)
1188
0
        return (BOXAA *)ERROR_PTR("invalid copyflag", __func__, NULL);
1189
1190
0
    n = boxaaGetCount(baas);
1191
0
    baad = boxaaCreate(n);
1192
0
    for (i = 0; i < n; i++) {
1193
0
        boxa = boxaaGetBoxa(baas, i, copyflag);
1194
0
        boxaaAddBoxa(baad, boxa, L_INSERT);
1195
0
    }
1196
1197
0
    return baad;
1198
0
}
1199
1200
1201
/*!
1202
 * \brief   boxaaDestroy()
1203
 *
1204
 * \param[in,out]   pbaa     will be set to null before returning
1205
 */
1206
void
1207
boxaaDestroy(BOXAA  **pbaa)
1208
0
{
1209
0
l_int32  i;
1210
0
BOXAA   *baa;
1211
1212
0
    if (pbaa == NULL) {
1213
0
        L_WARNING("ptr address is NULL!\n", __func__);
1214
0
        return;
1215
0
    }
1216
1217
0
    if ((baa = *pbaa) == NULL)
1218
0
        return;
1219
1220
0
    for (i = 0; i < baa->n; i++)
1221
0
        boxaDestroy(&baa->boxa[i]);
1222
0
    LEPT_FREE(baa->boxa);
1223
0
    LEPT_FREE(baa);
1224
0
    *pbaa = NULL;
1225
0
}
1226
1227
1228
1229
/*--------------------------------------------------------------------------*
1230
 *                              Add Boxa to Boxaa                           *
1231
 *--------------------------------------------------------------------------*/
1232
/*!
1233
 * \brief   boxaaAddBoxa()
1234
 *
1235
 * \param[in]    baa
1236
 * \param[in]    ba         to be added
1237
 * \param[in]    copyflag   L_INSERT, L_COPY, L_CLONE
1238
 * \return  0 if OK, 1 on error
1239
 */
1240
l_ok
1241
boxaaAddBoxa(BOXAA   *baa,
1242
             BOXA    *ba,
1243
             l_int32  copyflag)
1244
0
{
1245
0
l_int32  n;
1246
0
BOXA    *bac;
1247
1248
0
    if (!baa)
1249
0
        return ERROR_INT("baa not defined", __func__, 1);
1250
0
    if (!ba)
1251
0
        return ERROR_INT("ba not defined", __func__, 1);
1252
0
    if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
1253
0
        return ERROR_INT("invalid copyflag", __func__, 1);
1254
1255
0
    if (copyflag == L_INSERT)
1256
0
        bac = ba;
1257
0
    else
1258
0
        bac = boxaCopy(ba, copyflag);
1259
1260
0
    n = boxaaGetCount(baa);
1261
0
    if (n >= baa->nalloc) {
1262
0
        if (boxaaExtendArray(baa))
1263
0
            return ERROR_INT("extension failed", __func__, 1);
1264
0
    }
1265
0
    baa->boxa[n] = bac;
1266
0
    baa->n++;
1267
0
    return 0;
1268
0
}
1269
1270
1271
/*!
1272
 * \brief   boxaaExtendArray()
1273
 *
1274
 * \param[in]    baa
1275
 * \return  0 if OK, 1 on error
1276
 *
1277
 * <pre>
1278
 * Notes:
1279
 *      (1) Doubles the size of the boxa ptr array.
1280
 *      (2) The max number of boxa ptrs is 1 million.
1281
 * </pre>
1282
 */
1283
l_ok
1284
boxaaExtendArray(BOXAA  *baa)
1285
0
{
1286
0
    if (!baa)
1287
0
        return ERROR_INT("baa not defined", __func__, 1);
1288
1289
0
    return boxaaExtendArrayToSize(baa, 2 * baa->nalloc);
1290
0
}
1291
1292
1293
/*!
1294
 * \brief   boxaaExtendArrayToSize()
1295
 *
1296
 * \param[in]    baa
1297
 * \param[in]    size     new size of boxa array
1298
 * \return  0 if OK; 1 on error
1299
 *
1300
 * <pre>
1301
 * Notes:
1302
 *      (1) If necessary, reallocs the boxa ptr array to %size.
1303
 *      (2) %size limited to 1M boxa ptrs.
1304
 * </pre>
1305
 */
1306
l_ok
1307
boxaaExtendArrayToSize(BOXAA   *baa,
1308
                       l_int32  size)
1309
0
{
1310
0
size_t  oldsize, newsize;
1311
1312
0
    if (!baa)
1313
0
        return ERROR_INT("baa not defined", __func__, 1);
1314
0
    if (baa->nalloc > MaxBoxaaPtrArraySize)  /* belt & suspenders */
1315
0
        return ERROR_INT("baa has too many ptrs", __func__, 1);
1316
0
    if (size > MaxBoxaaPtrArraySize)
1317
0
        return ERROR_INT("size > 1M boxa ptrs; too large", __func__, 1);
1318
0
    if (size <= baa->nalloc) {
1319
0
        L_INFO("size too small; no extension\n", __func__);
1320
0
        return 0;
1321
0
    }
1322
1323
0
    oldsize = baa->nalloc * sizeof(BOXA *);
1324
0
    newsize = size * sizeof(BOXA *);
1325
0
    if ((baa->boxa = (BOXA **)reallocNew((void **)&baa->boxa,
1326
0
                                         oldsize, newsize)) == NULL)
1327
0
        return ERROR_INT("new ptr array not returned", __func__, 1);
1328
0
    baa->nalloc = size;
1329
0
    return 0;
1330
0
}
1331
1332
1333
/*----------------------------------------------------------------------*
1334
 *                           Boxaa accessors                            *
1335
 *----------------------------------------------------------------------*/
1336
/*!
1337
 * \brief   boxaaGetCount()
1338
 *
1339
 * \param[in]    baa
1340
 * \return  count number of boxa, or 0 if no boxa or on error
1341
 */
1342
l_int32
1343
boxaaGetCount(BOXAA  *baa)
1344
0
{
1345
0
    if (!baa)
1346
0
        return ERROR_INT("baa not defined", __func__, 0);
1347
0
    return baa->n;
1348
0
}
1349
1350
1351
/*!
1352
 * \brief   boxaaGetBoxCount()
1353
 *
1354
 * \param[in]    baa
1355
 * \return  count number of boxes, or 0 if no boxes or on error
1356
 */
1357
l_int32
1358
boxaaGetBoxCount(BOXAA  *baa)
1359
0
{
1360
0
BOXA    *boxa;
1361
0
l_int32  n, sum, i;
1362
1363
0
    if (!baa)
1364
0
        return ERROR_INT("baa not defined", __func__, 0);
1365
1366
0
    n = boxaaGetCount(baa);
1367
0
    for (sum = 0, i = 0; i < n; i++) {
1368
0
        boxa = boxaaGetBoxa(baa, i, L_CLONE);
1369
0
        sum += boxaGetCount(boxa);
1370
0
        boxaDestroy(&boxa);
1371
0
    }
1372
1373
0
    return sum;
1374
0
}
1375
1376
1377
/*!
1378
 * \brief   boxaaGetBoxa()
1379
 *
1380
 * \param[in]    baa
1381
 * \param[in]    index        to the index-th boxa
1382
 * \param[in]    accessflag   L_COPY or L_CLONE
1383
 * \return  boxa, or NULL on error
1384
 */
1385
BOXA *
1386
boxaaGetBoxa(BOXAA   *baa,
1387
             l_int32  index,
1388
             l_int32  accessflag)
1389
0
{
1390
0
l_int32  n;
1391
1392
0
    if (!baa)
1393
0
        return (BOXA *)ERROR_PTR("baa not defined", __func__, NULL);
1394
0
    n = boxaaGetCount(baa);
1395
0
    if (index < 0 || index >= n)
1396
0
        return (BOXA *)ERROR_PTR("index not valid", __func__, NULL);
1397
0
    if (accessflag != L_COPY && accessflag != L_CLONE)
1398
0
        return (BOXA *)ERROR_PTR("invalid accessflag", __func__, NULL);
1399
1400
0
    return boxaCopy(baa->boxa[index], accessflag);
1401
0
}
1402
1403
1404
/*!
1405
 * \brief   boxaaGetBox()
1406
 *
1407
 * \param[in]    baa
1408
 * \param[in]    iboxa        index into the boxa array in the boxaa
1409
 * \param[in]    ibox         index into the box array in the boxa
1410
 * \param[in]    accessflag   L_COPY or L_CLONE
1411
 * \return  box, or NULL on error
1412
 */
1413
BOX *
1414
boxaaGetBox(BOXAA   *baa,
1415
            l_int32  iboxa,
1416
            l_int32  ibox,
1417
            l_int32  accessflag)
1418
0
{
1419
0
BOX   *box;
1420
0
BOXA  *boxa;
1421
1422
0
    if ((boxa = boxaaGetBoxa(baa, iboxa, L_CLONE)) == NULL)
1423
0
        return (BOX *)ERROR_PTR("boxa not retrieved", __func__, NULL);
1424
0
    if ((box = boxaGetBox(boxa, ibox, accessflag)) == NULL)
1425
0
        L_ERROR("box not retrieved\n", __func__);
1426
0
    boxaDestroy(&boxa);
1427
0
    return box;
1428
0
}
1429
1430
1431
/*----------------------------------------------------------------------*
1432
 *                           Boxaa array modifiers                      *
1433
 *----------------------------------------------------------------------*/
1434
/*!
1435
 * \brief   boxaaInitFull()
1436
 *
1437
 * \param[in]    baa      typically empty
1438
 * \param[in]    boxa     to be replicated into the entire ptr array
1439
 * \return  0 if OK, 1 on error
1440
 *
1441
 * <pre>
1442
 * Notes:
1443
 *      (1) This initializes a boxaa by filling up the entire boxa ptr array
1444
 *          with copies of %boxa.  Any existing boxa are destroyed.
1445
 *          After this operation, the number of boxa is equal to
1446
 *          the number of allocated ptrs.
1447
 *      (2) Note that we use boxaaReplaceBoxa() which replaces a boxa,
1448
 *          instead of boxaaInsertBoxa(), which is O(n) and shifts all
1449
 *          the boxa pointers from the insertion point to the end.
1450
 *      (3) Example usage.  This function is useful to prepare for a
1451
 *          random insertion (or replacement) of boxa into a boxaa.
1452
 *          To randomly insert boxa into a boxaa, up to some index "max":
1453
 *             Boxaa *baa = boxaaCreate(max);
1454
 *               // initialize the boxa
1455
 *             Boxa *boxa = boxaCreate(...);
1456
 *             ...  [optionally fill with boxes]
1457
 *             boxaaInitFull(baa, boxa);
1458
 *          A typical use is to initialize the array with empty boxa,
1459
 *          and to replace only a subset that must be aligned with
1460
 *          something else, such as a pixa.
1461
 * </pre>
1462
 */
1463
l_ok
1464
boxaaInitFull(BOXAA  *baa,
1465
              BOXA   *boxa)
1466
0
{
1467
0
l_int32  i, n;
1468
0
BOXA    *boxat;
1469
1470
0
    if (!baa)
1471
0
        return ERROR_INT("baa not defined", __func__, 1);
1472
0
    if (!boxa)
1473
0
        return ERROR_INT("boxa not defined", __func__, 1);
1474
1475
0
    n = baa->nalloc;
1476
0
    baa->n = n;
1477
0
    for (i = 0; i < n; i++) {
1478
0
        boxat = boxaCopy(boxa, L_COPY);
1479
0
        boxaaReplaceBoxa(baa, i, boxat);
1480
0
    }
1481
0
    return 0;
1482
0
}
1483
1484
1485
/*!
1486
 * \brief   boxaaExtendWithInit()
1487
 *
1488
 * \param[in]    baa
1489
 * \param[in]    maxindex
1490
 * \param[in]    boxa       to be replicated into the extended ptr array
1491
 * \return  0 if OK, 1 on error
1492
 *
1493
 * <pre>
1494
 * Notes:
1495
 *      (1) This should be used on an existing boxaa that has been
1496
 *          fully loaded with boxa.  It then extends the boxaa,
1497
 *          loading all the additional ptrs with copies of boxa.
1498
 *          Typically, boxa will be empty.
1499
 * </pre>
1500
 */
1501
l_ok
1502
boxaaExtendWithInit(BOXAA   *baa,
1503
                    l_int32  maxindex,
1504
                    BOXA    *boxa)
1505
0
{
1506
0
l_int32  i, n;
1507
1508
0
    if (!baa)
1509
0
        return ERROR_INT("baa not defined", __func__, 1);
1510
0
    if (!boxa)
1511
0
        return ERROR_INT("boxa not defined", __func__, 1);
1512
1513
        /* Extend the ptr array if necessary */
1514
0
    n = boxaaGetCount(baa);
1515
0
    if (maxindex < n) return 0;
1516
0
    if (boxaaExtendArrayToSize(baa, maxindex + 1))
1517
0
        return ERROR_INT("extension failed", __func__, 1);
1518
1519
        /* Fill the new entries with copies of boxa */
1520
0
    for (i = n; i <= maxindex; i++)
1521
0
        boxaaAddBoxa(baa, boxa, L_COPY);
1522
0
    return 0;
1523
0
}
1524
1525
1526
/*!
1527
 * \brief   boxaaReplaceBoxa()
1528
 *
1529
 * \param[in]    baa
1530
 * \param[in]    index    to the index-th boxa
1531
 * \param[in]    boxa     insert and replace any existing one
1532
 * \return  0 if OK, 1 on error
1533
 *
1534
 * <pre>
1535
 * Notes:
1536
 *      (1) Any existing boxa is destroyed, and the input one
1537
 *          is inserted in its place.
1538
 *      (2) If the index is invalid, return 1 (error)
1539
 * </pre>
1540
 */
1541
l_ok
1542
boxaaReplaceBoxa(BOXAA   *baa,
1543
                 l_int32  index,
1544
                 BOXA    *boxa)
1545
0
{
1546
0
l_int32  n;
1547
1548
0
    if (!baa)
1549
0
        return ERROR_INT("baa not defined", __func__, 1);
1550
0
    if (!boxa)
1551
0
        return ERROR_INT("boxa not defined", __func__, 1);
1552
0
    n = boxaaGetCount(baa);
1553
0
    if (index < 0 || index >= n)
1554
0
        return ERROR_INT("index not valid", __func__, 1);
1555
1556
0
    boxaDestroy(&baa->boxa[index]);
1557
0
    baa->boxa[index] = boxa;
1558
0
    return 0;
1559
0
}
1560
1561
1562
/*!
1563
 * \brief   boxaaInsertBoxa()
1564
 *
1565
 * \param[in]    baa
1566
 * \param[in]    index    location in boxaa to insert new boxa
1567
 * \param[in]    boxa     new boxa to be inserted
1568
 * \return  0 if OK, 1 on error
1569
 *
1570
 * <pre>
1571
 * Notes:
1572
 *      (1) This shifts boxa[i] --> boxa[i + 1] for all i >= index,
1573
 *          and then inserts boxa as boxa[index].  It is typically used
1574
 *          when %baa is full of boxa.
1575
 *      (2) To insert at the beginning of the array, set %index = 0.
1576
 *      (3) To append to the array, it is equivalent to boxaaAddBoxa().
1577
 *      (4) This should not be used repeatedly to insert into large arrays,
1578
 *          because the function is O(n).
1579
 * </pre>
1580
 */
1581
l_ok
1582
boxaaInsertBoxa(BOXAA   *baa,
1583
                l_int32  index,
1584
                BOXA    *boxa)
1585
0
{
1586
0
l_int32  i, n;
1587
0
BOXA   **array;
1588
1589
0
    if (!baa)
1590
0
        return ERROR_INT("baa not defined", __func__, 1);
1591
0
    n = boxaaGetCount(baa);
1592
0
    if (index < 0 || index > n) {
1593
0
        L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n);
1594
0
        return 1;
1595
0
    }
1596
0
    if (!boxa)
1597
0
        return ERROR_INT("boxa not defined", __func__, 1);
1598
1599
0
    if (n >= baa->nalloc) {
1600
0
        if (boxaaExtendArray(baa))
1601
0
            return ERROR_INT("extension failed", __func__, 1);
1602
0
    }
1603
0
    array = baa->boxa;
1604
0
    baa->n++;
1605
0
    for (i = n; i > index; i--)
1606
0
        array[i] = array[i - 1];
1607
0
    array[index] = boxa;
1608
0
    return 0;
1609
0
}
1610
1611
1612
/*!
1613
 * \brief   boxaaRemoveBoxa()
1614
 *
1615
 * \param[in]    baa
1616
 * \param[in]    index   of the boxa to be removed and destroyed
1617
 * \return  0 if OK, 1 on error
1618
 *
1619
 * <pre>
1620
 * Notes:
1621
 *      (1) This removes boxa[index] and then shifts
1622
 *          boxa[i] --> boxa[i - 1] for all i > index.
1623
 *      (2) The removed boxaa is destroyed.
1624
 *      (2) This should not be used repeatedly on large arrays,
1625
 *          because the function is O(n).
1626
 * </pre>
1627
 */
1628
l_ok
1629
boxaaRemoveBoxa(BOXAA   *baa,
1630
                l_int32  index)
1631
0
{
1632
0
l_int32  i, n;
1633
0
BOXA   **array;
1634
1635
0
    if (!baa)
1636
0
        return ERROR_INT("baa not defined", __func__, 1);
1637
0
    n = boxaaGetCount(baa);
1638
0
    if (index < 0 || index >= n)
1639
0
        return ERROR_INT("index not valid", __func__, 1);
1640
1641
0
    array = baa->boxa;
1642
0
    boxaDestroy(&array[index]);
1643
0
    for (i = index + 1; i < n; i++)
1644
0
        array[i - 1] = array[i];
1645
0
    array[n - 1] = NULL;
1646
0
    baa->n--;
1647
1648
0
    return 0;
1649
0
}
1650
1651
1652
/*!
1653
 * \brief   boxaaAddBox()
1654
 *
1655
 * \param[in]    baa
1656
 * \param[in]    index       of boxa with boxaa
1657
 * \param[in]    box         to be added
1658
 * \param[in]    accessflag  L_INSERT, L_COPY or L_CLONE
1659
 * \return  0 if OK, 1 on error
1660
 *
1661
 * <pre>
1662
 * Notes:
1663
 *      (1) Adds to an existing boxa only.
1664
 * </pre>
1665
 */
1666
l_ok
1667
boxaaAddBox(BOXAA   *baa,
1668
            l_int32  index,
1669
            BOX     *box,
1670
            l_int32  accessflag)
1671
0
{
1672
0
l_int32  n;
1673
0
BOXA    *boxa;
1674
0
    if (!baa)
1675
0
        return ERROR_INT("baa not defined", __func__, 1);
1676
0
    n = boxaaGetCount(baa);
1677
0
    if (index < 0 || index >= n)
1678
0
        return ERROR_INT("index not valid", __func__, 1);
1679
0
    if (accessflag != L_INSERT && accessflag != L_COPY && accessflag != L_CLONE)
1680
0
        return ERROR_INT("invalid accessflag", __func__, 1);
1681
1682
0
    boxa = boxaaGetBoxa(baa, index, L_CLONE);
1683
0
    boxaAddBox(boxa, box, accessflag);
1684
0
    boxaDestroy(&boxa);
1685
0
    return 0;
1686
0
}
1687
1688
1689
/*---------------------------------------------------------------------*
1690
 *                        Boxaa serialized I/O                         *
1691
 *---------------------------------------------------------------------*/
1692
/*!
1693
 * \brief   boxaaReadFromFiles()
1694
 *
1695
 * \param[in]    dirname   directory
1696
 * \param[in]    substr    [optional] substring filter on filenames; can be NULL
1697
 * \param[in]    first     0-based
1698
 * \param[in]    nfiles    use 0 for everything from %first to the end
1699
 * \return  baa, or NULL on error or if no boxa files are found.
1700
 *
1701
 * <pre>
1702
 * Notes:
1703
 *      (1) The files must be serialized boxa files (e.g., *.ba).
1704
 *          If some files cannot be read, warnings are issued.
1705
 *      (2) Use %substr to filter filenames in the directory.  If
1706
 *          %substr == NULL, this takes all files.
1707
 *      (3) After filtering, use %first and %nfiles to select
1708
 *          a contiguous set of files, that have been lexically
1709
 *          sorted in increasing order.
1710
 * </pre>
1711
 */
1712
BOXAA *
1713
boxaaReadFromFiles(const char  *dirname,
1714
                   const char  *substr,
1715
                   l_int32      first,
1716
                   l_int32      nfiles)
1717
0
{
1718
0
char    *fname;
1719
0
l_int32  i, n;
1720
0
BOXA    *boxa;
1721
0
BOXAA   *baa;
1722
0
SARRAY  *sa;
1723
1724
0
  if (!dirname)
1725
0
      return (BOXAA *)ERROR_PTR("dirname not defined", __func__, NULL);
1726
1727
0
  sa = getSortedPathnamesInDirectory(dirname, substr, first, nfiles);
1728
0
  if (!sa || ((n = sarrayGetCount(sa)) == 0)) {
1729
0
      sarrayDestroy(&sa);
1730
0
      return (BOXAA *)ERROR_PTR("no pixa files found", __func__, NULL);
1731
0
  }
1732
1733
0
  baa = boxaaCreate(n);
1734
0
  for (i = 0; i < n; i++) {
1735
0
      fname = sarrayGetString(sa, i, L_NOCOPY);
1736
0
      if ((boxa = boxaRead(fname)) == NULL) {
1737
0
          L_ERROR("boxa not read for %d-th file", __func__, i);
1738
0
          continue;
1739
0
      }
1740
0
      boxaaAddBoxa(baa, boxa, L_INSERT);
1741
0
  }
1742
1743
0
  sarrayDestroy(&sa);
1744
0
  return baa;
1745
0
}
1746
1747
1748
/*!
1749
 * \brief   boxaaRead()
1750
 *
1751
 * \param[in]    filename
1752
 * \return  boxaa, or NULL on error
1753
 */
1754
BOXAA *
1755
boxaaRead(const char  *filename)
1756
0
{
1757
0
FILE   *fp;
1758
0
BOXAA  *baa;
1759
1760
0
    if (!filename)
1761
0
        return (BOXAA *)ERROR_PTR("filename not defined", __func__, NULL);
1762
1763
0
    if ((fp = fopenReadStream(filename)) == NULL)
1764
0
        return (BOXAA *)ERROR_PTR_1("stream not opened",
1765
0
                                    filename, __func__, NULL);
1766
0
    baa = boxaaReadStream(fp);
1767
0
    fclose(fp);
1768
0
    if (!baa)
1769
0
        return (BOXAA *)ERROR_PTR_1("boxaa not read",
1770
0
                                    filename, __func__, NULL);
1771
0
    return baa;
1772
0
}
1773
1774
1775
/*!
1776
 * \brief   boxaaReadStream()
1777
 *
1778
 * \param[in]    fp    input file stream
1779
 * \return  boxaa, or NULL on error
1780
 *
1781
 * <pre>
1782
 * Notes:
1783
 *      (1) It is OK for the boxaa to be empty (n == 0).
1784
 * </pre>
1785
 */
1786
BOXAA *
1787
boxaaReadStream(FILE  *fp)
1788
0
{
1789
0
l_int32  n, i, x, y, w, h, version;
1790
0
l_int32  ignore;
1791
0
BOXA    *boxa;
1792
0
BOXAA   *baa;
1793
1794
0
    if (!fp)
1795
0
        return (BOXAA *)ERROR_PTR("stream not defined", __func__, NULL);
1796
1797
0
    if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1)
1798
0
        return (BOXAA *)ERROR_PTR("not a boxaa file", __func__, NULL);
1799
0
    if (version != BOXAA_VERSION_NUMBER)
1800
0
        return (BOXAA *)ERROR_PTR("invalid boxa version", __func__, NULL);
1801
0
    if (fscanf(fp, "Number of boxa = %d\n", &n) != 1)
1802
0
        return (BOXAA *)ERROR_PTR("not a boxaa file", __func__, NULL);
1803
0
    if (n < 0)
1804
0
        return (BOXAA *)ERROR_PTR("num boxa ptrs < 0", __func__, NULL);
1805
0
    if (n > MaxBoxaaPtrArraySize)
1806
0
        return (BOXAA *)ERROR_PTR("too many boxa ptrs", __func__, NULL);
1807
0
    if (n == 0) L_INFO("the boxaa is empty\n", __func__);
1808
1809
0
    if ((baa = boxaaCreate(n)) == NULL)
1810
0
        return (BOXAA *)ERROR_PTR("boxaa not made", __func__, NULL);
1811
0
    for (i = 0; i < n; i++) {
1812
0
        if (fscanf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
1813
0
                   &ignore, &x, &y, &w, &h) != 5) {
1814
0
            boxaaDestroy(&baa);
1815
0
            return (BOXAA *)ERROR_PTR("boxa descr not valid", __func__, NULL);
1816
0
        }
1817
0
        if ((boxa = boxaReadStream(fp)) == NULL) {
1818
0
            boxaaDestroy(&baa);
1819
0
            return (BOXAA *)ERROR_PTR("boxa not made", __func__, NULL);
1820
0
        }
1821
0
        boxaaAddBoxa(baa, boxa, L_INSERT);
1822
0
    }
1823
0
    return baa;
1824
0
}
1825
1826
1827
/*!
1828
 * \brief   boxaaReadMem()
1829
 *
1830
 * \param[in]    data     serialization of boxaa; in ascii
1831
 * \param[in]    size     of data in bytes; can use strlen to get it
1832
 * \return  baa, or NULL on error
1833
 */
1834
BOXAA *
1835
boxaaReadMem(const l_uint8  *data,
1836
             size_t          size)
1837
0
{
1838
0
FILE   *fp;
1839
0
BOXAA  *baa;
1840
1841
0
    if (!data)
1842
0
        return (BOXAA *)ERROR_PTR("data not defined", __func__, NULL);
1843
0
    if ((fp = fopenReadFromMemory(data, size)) == NULL)
1844
0
        return (BOXAA *)ERROR_PTR("stream not opened", __func__, NULL);
1845
1846
0
    baa = boxaaReadStream(fp);
1847
0
    fclose(fp);
1848
0
    if (!baa) L_ERROR("baa not read\n", __func__);
1849
0
    return baa;
1850
0
}
1851
1852
1853
/*!
1854
 * \brief   boxaaWrite()
1855
 *
1856
 * \param[in]    filename
1857
 * \param[in]    baa
1858
 * \return  0 if OK, 1 on error
1859
 */
1860
l_ok
1861
boxaaWrite(const char  *filename,
1862
           BOXAA       *baa)
1863
0
{
1864
0
l_int32  ret;
1865
0
FILE    *fp;
1866
1867
0
    if (!filename)
1868
0
        return ERROR_INT("filename not defined", __func__, 1);
1869
0
    if (!baa)
1870
0
        return ERROR_INT("baa not defined", __func__, 1);
1871
1872
0
    if ((fp = fopenWriteStream(filename, "w")) == NULL)
1873
0
        return ERROR_INT_1("stream not opened", filename, __func__, 1);
1874
0
    ret = boxaaWriteStream(fp, baa);
1875
0
    fclose(fp);
1876
0
    if (ret)
1877
0
        return ERROR_INT_1("baa not written to stream", filename, __func__, 1);
1878
0
    return 0;
1879
0
}
1880
1881
1882
/*!
1883
 * \brief   boxaaWriteStream()
1884
 *
1885
 * \param[in]   fp    output file stream
1886
 * \param[in]   baa
1887
 * \return  0 if OK, 1 on error
1888
 */
1889
l_ok
1890
boxaaWriteStream(FILE   *fp,
1891
                 BOXAA  *baa)
1892
0
{
1893
0
l_int32  n, i, x, y, w, h;
1894
0
BOX     *box;
1895
0
BOXA    *boxa;
1896
1897
0
    if (!fp)
1898
0
        return ERROR_INT("stream not defined", __func__, 1);
1899
0
    if (!baa)
1900
0
        return ERROR_INT("baa not defined", __func__, 1);
1901
1902
0
    n = boxaaGetCount(baa);
1903
0
    fprintf(fp, "\nBoxaa Version %d\n", BOXAA_VERSION_NUMBER);
1904
0
    fprintf(fp, "Number of boxa = %d\n", n);
1905
1906
0
    for (i = 0; i < n; i++) {
1907
0
        if ((boxa = boxaaGetBoxa(baa, i, L_CLONE)) == NULL)
1908
0
            return ERROR_INT("boxa not found", __func__, 1);
1909
0
        boxaGetExtent(boxa, NULL, NULL, &box);
1910
0
        boxGetGeometry(box, &x, &y, &w, &h);
1911
0
        fprintf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
1912
0
                i, x, y, w, h);
1913
0
        boxaWriteStream(fp, boxa);
1914
0
        boxDestroy(&box);
1915
0
        boxaDestroy(&boxa);
1916
0
    }
1917
0
    return 0;
1918
0
}
1919
1920
1921
/*!
1922
 * \brief   boxaaWriteMem()
1923
 *
1924
 * \param[out]   pdata    data of serialized boxaa; ascii
1925
 * \param[out]   psize    size of returned data
1926
 * \param[in]    baa
1927
 * \return  0 if OK, 1 on error
1928
 *
1929
 * <pre>
1930
 * Notes:
1931
 *      (1) Serializes a boxaa in memory and puts the result in a buffer.
1932
 * </pre>
1933
 */
1934
l_ok
1935
boxaaWriteMem(l_uint8  **pdata,
1936
              size_t    *psize,
1937
              BOXAA     *baa)
1938
0
{
1939
0
l_int32  ret;
1940
0
FILE    *fp;
1941
1942
0
    if (pdata) *pdata = NULL;
1943
0
    if (psize) *psize = 0;
1944
0
    if (!pdata)
1945
0
        return ERROR_INT("&data not defined", __func__, 1);
1946
0
    if (!psize)
1947
0
        return ERROR_INT("&size not defined", __func__, 1);
1948
0
    if (!baa)
1949
0
        return ERROR_INT("baa not defined", __func__, 1);
1950
1951
0
#if HAVE_FMEMOPEN
1952
0
    if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1953
0
        return ERROR_INT("stream not opened", __func__, 1);
1954
0
    ret = boxaaWriteStream(fp, baa);
1955
0
    fputc('\0', fp);
1956
0
    fclose(fp);
1957
0
    if (*psize > 0) *psize = *psize - 1;
1958
#else
1959
    L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
1960
  #ifdef _WIN32
1961
    if ((fp = fopenWriteWinTempfile()) == NULL)
1962
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
1963
  #else
1964
    if ((fp = tmpfile()) == NULL)
1965
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
1966
  #endif  /* _WIN32 */
1967
    ret = boxaaWriteStream(fp, baa);
1968
    rewind(fp);
1969
    *pdata = l_binaryReadStream(fp, psize);
1970
    fclose(fp);
1971
#endif  /* HAVE_FMEMOPEN */
1972
0
    return ret;
1973
0
}
1974
1975
1976
/*---------------------------------------------------------------------*
1977
 *                         Boxa serialized I/O                         *
1978
 *---------------------------------------------------------------------*/
1979
/*!
1980
 * \brief   boxaRead()
1981
 *
1982
 * \param[in]    filename
1983
 * \return  boxa, or NULL on error
1984
 */
1985
BOXA *
1986
boxaRead(const char  *filename)
1987
0
{
1988
0
FILE  *fp;
1989
0
BOXA  *boxa;
1990
1991
0
    if (!filename)
1992
0
        return (BOXA *)ERROR_PTR("filename not defined", __func__, NULL);
1993
1994
0
    if ((fp = fopenReadStream(filename)) == NULL)
1995
0
        return (BOXA *)ERROR_PTR_1("stream not opened",
1996
0
                                   filename, __func__, NULL);
1997
0
    boxa = boxaReadStream(fp);
1998
0
    fclose(fp);
1999
0
    if (!boxa)
2000
0
        return (BOXA *)ERROR_PTR_1("boxa not read",
2001
0
                                   filename, __func__, NULL);
2002
0
    return boxa;
2003
0
}
2004
2005
2006
/*!
2007
 * \brief   boxaReadStream()
2008
 *
2009
 * \param[in]    fp   input file stream
2010
 * \return  boxa, or NULL on error
2011
 *
2012
 * <pre>
2013
 * Notes:
2014
 *      (1) It is OK for the boxa to be empty (n == 0).
2015
 * </pre>
2016
 */
2017
BOXA *
2018
boxaReadStream(FILE  *fp)
2019
0
{
2020
0
l_int32  n, i, x, y, w, h, version;
2021
0
l_int32  ignore;
2022
0
BOX     *box;
2023
0
BOXA    *boxa;
2024
2025
0
    if (!fp)
2026
0
        return (BOXA *)ERROR_PTR("stream not defined", __func__, NULL);
2027
2028
0
    if (fscanf(fp, "\nBoxa Version %d\n", &version) != 1)
2029
0
        return (BOXA *)ERROR_PTR("not a boxa file", __func__, NULL);
2030
0
    if (version != BOXA_VERSION_NUMBER)
2031
0
        return (BOXA *)ERROR_PTR("invalid boxa version", __func__, NULL);
2032
0
    if (fscanf(fp, "Number of boxes = %d\n", &n) != 1)
2033
0
        return (BOXA *)ERROR_PTR("not a boxa file", __func__, NULL);
2034
0
    if (n < 0)
2035
0
        return (BOXA *)ERROR_PTR("num box ptrs < 0", __func__, NULL);
2036
0
    if (n > MaxBoxaPtrArraySize)
2037
0
        return (BOXA *)ERROR_PTR("too many box ptrs", __func__, NULL);
2038
0
    if (n == 0) L_INFO("the boxa is empty\n", __func__);
2039
2040
0
    if ((boxa = boxaCreate(n)) == NULL)
2041
0
        return (BOXA *)ERROR_PTR("boxa not made", __func__, NULL);
2042
0
    for (i = 0; i < n; i++) {
2043
0
        if (fscanf(fp, "  Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
2044
0
                &ignore, &x, &y, &w, &h) != 5) {
2045
0
            boxaDestroy(&boxa);
2046
0
            return (BOXA *)ERROR_PTR("box descr not valid", __func__, NULL);
2047
0
        }
2048
0
        box = boxCreate(x, y, w, h);
2049
0
        boxaAddBox(boxa, box, L_INSERT);
2050
0
    }
2051
0
    return boxa;
2052
0
}
2053
2054
2055
/*!
2056
 * \brief   boxaReadMem()
2057
 *
2058
 * \param[in]    data    serialization of boxa; in ascii
2059
 * \param[in]    size    of data in bytes; can use strlen to get it
2060
 * \return  boxa, or NULL on error
2061
 */
2062
BOXA *
2063
boxaReadMem(const l_uint8  *data,
2064
            size_t          size)
2065
0
{
2066
0
FILE  *fp;
2067
0
BOXA  *boxa;
2068
2069
0
    if (!data)
2070
0
        return (BOXA *)ERROR_PTR("data not defined", __func__, NULL);
2071
0
    if ((fp = fopenReadFromMemory(data, size)) == NULL)
2072
0
        return (BOXA *)ERROR_PTR("stream not opened", __func__, NULL);
2073
2074
0
    boxa = boxaReadStream(fp);
2075
0
    fclose(fp);
2076
0
    if (!boxa) L_ERROR("boxa not read\n", __func__);
2077
0
    return boxa;
2078
0
}
2079
2080
2081
/*!
2082
 * \brief   boxaWriteDebug()
2083
 *
2084
 * \param[in]    filename
2085
 * \param[in]    boxa
2086
 * \return  0 if OK; 1 on error
2087
 *
2088
 * <pre>
2089
 * Notes:
2090
 *      (1) Debug version, intended for use in the library when writing
2091
 *          to files in a temp directory with names that are compiled in.
2092
 *          This is used instead of boxaWrite() for all such library calls.
2093
 *      (2) The global variable LeptDebugOK defaults to 0, and can be set
2094
 *          or cleared by the function setLeptDebugOK().
2095
 * </pre>
2096
 */
2097
l_ok
2098
boxaWriteDebug(const char  *filename,
2099
               BOXA        *boxa)
2100
0
{
2101
0
    if (LeptDebugOK) {
2102
0
        return boxaWrite(filename, boxa);
2103
0
    } else {
2104
0
        L_INFO("write to named temp file %s is disabled\n", __func__, filename);
2105
0
        return 0;
2106
0
    }
2107
0
}
2108
2109
2110
/*!
2111
 * \brief   boxaWrite()
2112
 *
2113
 * \param[in]    filename
2114
 * \param[in]    boxa
2115
 * \return  0 if OK, 1 on error
2116
 */
2117
l_ok
2118
boxaWrite(const char  *filename,
2119
          BOXA        *boxa)
2120
0
{
2121
0
l_int32  ret;
2122
0
FILE    *fp;
2123
2124
0
    if (!filename)
2125
0
        return ERROR_INT("filename not defined", __func__, 1);
2126
0
    if (!boxa)
2127
0
        return ERROR_INT("boxa not defined", __func__, 1);
2128
2129
0
    if ((fp = fopenWriteStream(filename, "w")) == NULL)
2130
0
        return ERROR_INT_1("stream not opened", filename, __func__, 1);
2131
0
    ret = boxaWriteStream(fp, boxa);
2132
0
    fclose(fp);
2133
0
    if (ret)
2134
0
        return ERROR_INT_1("boxa not written to stream", filename, __func__, 1);
2135
2136
0
    return 0;
2137
0
}
2138
2139
2140
/*!
2141
 * \brief   boxaWriteStream()
2142
 *
2143
 * \param[in]   fp     file stream; use NULL for stderr
2144
 * \param[in]   boxa
2145
 * \return  0 if OK, 1 on error
2146
 */
2147
l_ok
2148
boxaWriteStream(FILE  *fp,
2149
                BOXA  *boxa)
2150
0
{
2151
0
l_int32  n, i;
2152
0
BOX     *box;
2153
2154
0
    if (!boxa)
2155
0
        return ERROR_INT("boxa not defined", __func__, 1);
2156
0
    if (!fp)
2157
0
        return boxaWriteStderr(boxa);
2158
2159
0
    n = boxaGetCount(boxa);
2160
0
    fprintf(fp, "\nBoxa Version %d\n", BOXA_VERSION_NUMBER);
2161
0
    fprintf(fp, "Number of boxes = %d\n", n);
2162
0
    for (i = 0; i < n; i++) {
2163
0
        if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL)
2164
0
            return ERROR_INT("box not found", __func__, 1);
2165
0
        fprintf(fp, "  Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
2166
0
                i, box->x, box->y, box->w, box->h);
2167
0
        boxDestroy(&box);
2168
0
    }
2169
0
    return 0;
2170
0
}
2171
2172
2173
/*!
2174
 * \brief   boxaWriteStderr()
2175
 *
2176
 * \param[in]   boxa
2177
 * \return  0 if OK, 1 on error
2178
 */
2179
l_ok
2180
boxaWriteStderr(BOXA  *boxa)
2181
0
{
2182
0
l_int32  n, i;
2183
0
BOX     *box;
2184
2185
0
    if (!boxa)
2186
0
        return ERROR_INT("boxa not defined", __func__, 1);
2187
2188
0
    n = boxaGetCount(boxa);
2189
0
    lept_stderr("\nBoxa Version %d\n", BOXA_VERSION_NUMBER);
2190
0
    lept_stderr("Number of boxes = %d\n", n);
2191
0
    for (i = 0; i < n; i++) {
2192
0
        if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL)
2193
0
            return ERROR_INT("box not found", __func__, 1);
2194
0
        lept_stderr("  Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
2195
0
                i, box->x, box->y, box->w, box->h);
2196
0
        boxDestroy(&box);
2197
0
    }
2198
0
    return 0;
2199
0
}
2200
2201
2202
/*!
2203
 * \brief   boxaWriteMem()
2204
 *
2205
 * \param[out]   pdata   data of serialized boxa; ascii
2206
 * \param[out]   psize   size of returned data
2207
 * \param[in]    boxa
2208
 * \return  0 if OK, 1 on error
2209
 *
2210
 * <pre>
2211
 * Notes:
2212
 *      (1) Serializes a boxa in memory and puts the result in a buffer.
2213
 * </pre>
2214
 */
2215
l_ok
2216
boxaWriteMem(l_uint8  **pdata,
2217
             size_t    *psize,
2218
             BOXA      *boxa)
2219
0
{
2220
0
l_int32  ret;
2221
0
FILE    *fp;
2222
2223
0
    if (pdata) *pdata = NULL;
2224
0
    if (psize) *psize = 0;
2225
0
    if (!pdata)
2226
0
        return ERROR_INT("&data not defined", __func__, 1);
2227
0
    if (!psize)
2228
0
        return ERROR_INT("&size not defined", __func__, 1);
2229
0
    if (!boxa)
2230
0
        return ERROR_INT("boxa not defined", __func__, 1);
2231
2232
0
#if HAVE_FMEMOPEN
2233
0
    if ((fp = open_memstream((char **)pdata, psize)) == NULL)
2234
0
        return ERROR_INT("stream not opened", __func__, 1);
2235
0
    ret = boxaWriteStream(fp, boxa);
2236
0
    fputc('\0', fp);
2237
0
    fclose(fp);
2238
0
    if (*psize > 0) *psize = *psize - 1;
2239
#else
2240
    L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
2241
  #ifdef _WIN32
2242
    if ((fp = fopenWriteWinTempfile()) == NULL)
2243
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
2244
  #else
2245
    if ((fp = tmpfile()) == NULL)
2246
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
2247
  #endif  /* _WIN32 */
2248
    ret = boxaWriteStream(fp, boxa);
2249
    rewind(fp);
2250
    *pdata = l_binaryReadStream(fp, psize);
2251
    fclose(fp);
2252
#endif  /* HAVE_FMEMOPEN */
2253
0
    return ret;
2254
0
}
2255
2256
2257
/*---------------------------------------------------------------------*
2258
 *                            Debug printing                           *
2259
 *---------------------------------------------------------------------*/
2260
/*!
2261
 * \brief   boxPrintStreamInfo()
2262
 *
2263
 * \param[in]    fp    file stream; use NULL for stderr
2264
 * \param[in]    box
2265
 * \return  0 if OK, 1 on error
2266
 *
2267
 * <pre>
2268
 * Notes:
2269
 *      (1) This outputs debug info.  Use serialization functions to
2270
 *          write to file if you want to read the data back.
2271
 * </pre>
2272
 */
2273
l_ok
2274
boxPrintStreamInfo(FILE  *fp,
2275
                   BOX   *box)
2276
0
{
2277
0
    if (!box)
2278
0
        return ERROR_INT("box not defined", __func__, 1);
2279
2280
0
    if (!fp) {  /* output to stderr */
2281
0
        lept_stderr(" Box: x = %d, y = %d, w = %d, h = %d\n",
2282
0
                    box->x, box->y, box->w, box->h);
2283
0
    } else {
2284
0
        fprintf(fp, " Box: x = %d, y = %d, w = %d, h = %d\n",
2285
0
                box->x, box->y, box->w, box->h);
2286
0
    }
2287
0
    return 0;
2288
0
}