comparison mupdf-source/thirdparty/leptonica/src/boxbasic.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
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 {
176 BOX *box;
177
178 if (w < 0 || h < 0)
179 return (BOX *)ERROR_PTR("w and h not both >= 0", __func__, NULL);
180 if (x < 0) { /* take part in +quad */
181 w = w + x;
182 x = 0;
183 if (w <= 0)
184 return (BOX *)ERROR_PTR("x < 0 and box off +quad", __func__, NULL);
185 }
186 if (y < 0) { /* take part in +quad */
187 h = h + y;
188 y = 0;
189 if (h <= 0)
190 return (BOX *)ERROR_PTR("y < 0 and box off +quad", __func__, NULL);
191 }
192
193 box = (BOX *)LEPT_CALLOC(1, sizeof(BOX));
194 boxSetGeometry(box, x, y, w, h);
195 box->refcount = 1;
196 return box;
197 }
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 {
217 if (w <= 0 || h <= 0)
218 return (BOX *)ERROR_PTR("w and h not both > 0", __func__, NULL);
219 return boxCreate(x, y, w, h);
220 }
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 {
232 BOX *boxc;
233
234 if (!box)
235 return (BOX *)ERROR_PTR("box not defined", __func__, NULL);
236
237 boxc = boxCreate(box->x, box->y, box->w, box->h);
238 return boxc;
239 }
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 {
251
252 if (!box)
253 return (BOX *)ERROR_PTR("box not defined", __func__, NULL);
254
255 ++box->refcount;
256 return box;
257 }
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 {
275 BOX *box;
276
277 if (pbox == NULL) {
278 L_WARNING("ptr address is null!\n", __func__);
279 return;
280 }
281 if ((box = *pbox) == NULL)
282 return;
283
284 if (--box->refcount == 0)
285 LEPT_FREE(box);
286 *pbox = NULL;
287 }
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 {
307 if (px) *px = 0;
308 if (py) *py = 0;
309 if (pw) *pw = 0;
310 if (ph) *ph = 0;
311 if (!box)
312 return ERROR_INT("box not defined", __func__, 1);
313 if (px) *px = box->x;
314 if (py) *py = box->y;
315 if (pw) *pw = box->w;
316 if (ph) *ph = box->h;
317 return 0;
318 }
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 {
335 if (!box)
336 return ERROR_INT("box not defined", __func__, 1);
337 if (x != -1) box->x = x;
338 if (y != -1) box->y = y;
339 if (w != -1) box->w = w;
340 if (h != -1) box->h = h;
341 return 0;
342 }
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 {
364 l_int32 x, y, w, h;
365
366 if (pl) *pl = 0;
367 if (pr) *pr = 0;
368 if (pt) *pt = 0;
369 if (pb) *pb = 0;
370 if (!box)
371 return ERROR_INT("box not defined", __func__, 1);
372
373 boxGetGeometry(box, &x, &y, &w, &h);
374 if (pl) *pl = x;
375 if (pr) *pr = x + w - 1;
376 if (pt) *pt = y;
377 if (pb) *pb = y + h - 1;
378 return 0;
379 }
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 {
396 l_int32 x, y, w, h;
397
398 if (!box)
399 return ERROR_INT("box not defined", __func__, 1);
400 x = (l != -1) ? l : box->x;
401 w = (r != -1) ? r - x + 1 : box->x + box->w - x;
402 y = (t != -1) ? t : box->y;
403 h = (b != -1) ? b - y + 1 : box->y + box->h - y;
404 boxSetGeometry(box, x, y, w, h);
405 return 0;
406 }
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 {
420 if (!pvalid)
421 return ERROR_INT("&valid not defined", __func__, 1);
422 *pvalid = 0;
423 if (!box)
424 return ERROR_INT("box not defined", __func__, 1);
425
426 if (box->w > 0 && box->h > 0)
427 *pvalid = 1;
428 return 0;
429 }
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 {
444 BOXA *boxa;
445
446 if (n <= 0 || n > MaxBoxaPtrArraySize)
447 n = InitialPtrArraySize;
448
449 boxa = (BOXA *)LEPT_CALLOC(1, sizeof(BOXA));
450 boxa->n = 0;
451 boxa->nalloc = n;
452 boxa->refcount = 1;
453 if ((boxa->box = (BOX **)LEPT_CALLOC(n, sizeof(BOX *))) == NULL) {
454 boxaDestroy(&boxa);
455 return (BOXA *)ERROR_PTR("boxa ptrs not made", __func__, NULL);
456 }
457 return boxa;
458 }
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 {
478 l_int32 i;
479 BOX *boxc;
480 BOXA *boxac;
481
482 if (!boxa)
483 return (BOXA *)ERROR_PTR("boxa not defined", __func__, NULL);
484
485 if (copyflag == L_CLONE) {
486 boxa->refcount++;
487 return boxa;
488 }
489
490 if (copyflag != L_COPY && copyflag != L_COPY_CLONE)
491 return (BOXA *)ERROR_PTR("invalid copyflag", __func__, NULL);
492
493 if ((boxac = boxaCreate(boxa->nalloc)) == NULL)
494 return (BOXA *)ERROR_PTR("boxac not made", __func__, NULL);
495 for (i = 0; i < boxa->n; i++) {
496 if (copyflag == L_COPY)
497 boxc = boxaGetBox(boxa, i, L_COPY);
498 else /* copy-clone */
499 boxc = boxaGetBox(boxa, i, L_CLONE);
500 boxaAddBox(boxac, boxc, L_INSERT);
501 }
502 return boxac;
503 }
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 {
521 l_int32 i;
522 BOXA *boxa;
523
524 if (pboxa == NULL) {
525 L_WARNING("ptr address is null!\n", __func__);
526 return;
527 }
528
529 if ((boxa = *pboxa) == NULL)
530 return;
531
532 /* Decrement the ref count. If it is 0, destroy the boxa. */
533 if (--boxa->refcount == 0) {
534 for (i = 0; i < boxa->n; i++)
535 boxDestroy(&boxa->box[i]);
536 LEPT_FREE(boxa->box);
537 LEPT_FREE(boxa);
538 }
539
540 *pboxa = NULL;
541 }
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 {
557 l_int32 n;
558 BOX *boxc;
559
560 if (!boxa)
561 return ERROR_INT("boxa not defined", __func__, 1);
562 if (!box)
563 return ERROR_INT("box not defined", __func__, 1);
564
565 if (copyflag == L_INSERT)
566 boxc = box;
567 else if (copyflag == L_COPY)
568 boxc = boxCopy(box);
569 else if (copyflag == L_CLONE)
570 boxc = boxClone(box);
571 else
572 return ERROR_INT("invalid copyflag", __func__, 1);
573 if (!boxc)
574 return ERROR_INT("boxc not made", __func__, 1);
575
576 n = boxaGetCount(boxa);
577 if (n >= boxa->nalloc) {
578 if (boxaExtendArray(boxa)) {
579 if (copyflag != L_INSERT)
580 boxDestroy(&boxc);
581 return ERROR_INT("extension failed", __func__, 1);
582 }
583 }
584 boxa->box[n] = boxc;
585 boxa->n++;
586 return 0;
587 }
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 {
604 if (!boxa)
605 return ERROR_INT("boxa not defined", __func__, 1);
606
607 return boxaExtendArrayToSize(boxa, 2 * boxa->nalloc);
608 }
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 {
628 size_t oldsize, newsize;
629
630 if (!boxa)
631 return ERROR_INT("boxa not defined", __func__, 1);
632 if (boxa->nalloc > MaxBoxaPtrArraySize) /* belt & suspenders */
633 return ERROR_INT("boxa has too many ptrs", __func__, 1);
634 if (size > MaxBoxaPtrArraySize)
635 return ERROR_INT("size > 10M box ptrs; too large", __func__, 1);
636 if (size <= boxa->nalloc) {
637 L_INFO("size too small; no extension\n", __func__);
638 return 0;
639 }
640
641 oldsize = boxa->nalloc * sizeof(BOX *);
642 newsize = size * sizeof(BOX *);
643 if ((boxa->box = (BOX **)reallocNew((void **)&boxa->box,
644 oldsize, newsize)) == NULL)
645 return ERROR_INT("new ptr array not returned", __func__, 1);
646 boxa->nalloc = size;
647 return 0;
648 }
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 {
663 if (!boxa)
664 return ERROR_INT("boxa not defined", __func__, 0);
665 return boxa->n;
666 }
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 {
678 l_int32 n, i, w, h, count;
679
680 if (!boxa)
681 return ERROR_INT("boxa not defined", __func__, 0);
682
683 n = boxaGetCount(boxa);
684 for (i = 0, count = 0; i < n; i++) {
685 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
686 if (w > 0 && h > 0)
687 count++;
688 }
689 return count;
690 }
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 {
706 if (!boxa)
707 return (BOX *)ERROR_PTR("boxa not defined", __func__, NULL);
708 if (index < 0 || index >= boxa->n)
709 return (BOX *)ERROR_PTR("index not valid", __func__, NULL);
710
711 if (accessflag == L_COPY)
712 return boxCopy(boxa->box[index]);
713 else if (accessflag == L_CLONE)
714 return boxClone(boxa->box[index]);
715 else
716 return (BOX *)ERROR_PTR("invalid accessflag", __func__, NULL);
717 }
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 {
743 l_int32 w, h;
744 BOX *box;
745
746 if (!boxa)
747 return (BOX *)ERROR_PTR("boxa not defined", __func__, NULL);
748
749 if ((box = boxaGetBox(boxa, index, accessflag)) == NULL)
750 return (BOX *)ERROR_PTR("box not returned", __func__, NULL);
751 boxGetGeometry(box, NULL, NULL, &w, &h);
752 if (w <= 0 || h <= 0) /* not valid, but not necessarily an error */
753 boxDestroy(&box);
754 return box;
755 }
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 {
767 l_int32 i, n, w, h;
768 NUMA *na;
769
770 if (!boxa)
771 return (NUMA *)ERROR_PTR("boxa not defined", __func__, NULL);
772
773 n = boxaGetCount(boxa);
774 if (boxaGetValidCount(boxa) == n)
775 return NULL;
776
777 na = numaMakeConstant(0, n);
778 for (i = 0; i < n; i++) {
779 boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
780 if (w == 0 || h == 0)
781 numaSetValue(na, i, 1);
782 }
783 return na;
784 }
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 {
803 BOX *box;
804
805 if (px) *px = 0;
806 if (py) *py = 0;
807 if (pw) *pw = 0;
808 if (ph) *ph = 0;
809 if (!boxa)
810 return ERROR_INT("boxa not defined", __func__, 1);
811 if (index < 0 || index >= boxa->n)
812 return ERROR_INT("index not valid", __func__, 1);
813
814 if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL)
815 return ERROR_INT("box not found!", __func__, 1);
816 boxGetGeometry(box, px, py, pw, ph);
817 boxDestroy(&box);
818 return 0;
819 }
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 {
833 l_int32 i, n, full;
834 BOX *box;
835
836 if (!pfull)
837 return ERROR_INT("&full not defined", __func__, 1);
838 *pfull = 0;
839 if (!boxa)
840 return ERROR_INT("boxa not defined", __func__, 1);
841
842 n = boxaGetCount(boxa);
843 full = 1;
844 for (i = 0; i < n; i++) {
845 if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL) {
846 full = 0;
847 break;
848 }
849 boxDestroy(&box);
850 }
851 *pfull = full;
852 return 0;
853 }
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 {
879 if (!boxa)
880 return ERROR_INT("boxa not defined", __func__, 1);
881 if (index < 0 || index >= boxa->n)
882 return ERROR_INT("index not valid", __func__, 1);
883 if (!box)
884 return ERROR_INT("box not defined", __func__, 1);
885
886 boxDestroy(&(boxa->box[index]));
887 boxa->box[index] = box;
888 return 0;
889 }
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 {
915 l_int32 i, n;
916 BOX **array;
917
918 if (!boxa)
919 return ERROR_INT("boxa not defined", __func__, 1);
920 n = boxaGetCount(boxa);
921 if (index < 0 || index > n) {
922 L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n);
923 return 1;
924 }
925 if (!box)
926 return ERROR_INT("box not defined", __func__, 1);
927
928 if (n >= boxa->nalloc) {
929 if (boxaExtendArray(boxa))
930 return ERROR_INT("extension failed", __func__, 1);
931 }
932 array = boxa->box;
933 boxa->n++;
934 for (i = n; i > index; i--)
935 array[i] = array[i - 1];
936 array[index] = box;
937 return 0;
938 }
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 {
960 return boxaRemoveBoxAndSave(boxa, index, NULL);
961 }
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 {
985 l_int32 i, n;
986 BOX **array;
987
988 if (pbox) *pbox = NULL;
989 if (!boxa)
990 return ERROR_INT("boxa not defined", __func__, 1);
991 n = boxaGetCount(boxa);
992 if (index < 0 || index >= n) {
993 L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n - 1);
994 return 1;
995 }
996
997 if (pbox)
998 *pbox = boxaGetBox(boxa, index, L_CLONE);
999 array = boxa->box;
1000 boxDestroy(&array[index]);
1001 for (i = index + 1; i < n; i++)
1002 array[i - 1] = array[i];
1003 array[n - 1] = NULL;
1004 boxa->n--;
1005
1006 return 0;
1007 }
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 {
1026 l_int32 i, n;
1027 BOX *box;
1028 BOXA *boxad;
1029
1030 if (!boxas)
1031 return (BOXA *)ERROR_PTR("boxas not defined", __func__, NULL);
1032 if (copyflag != L_COPY && copyflag != L_CLONE)
1033 return (BOXA *)ERROR_PTR("invalid copyflag", __func__, NULL);
1034
1035 n = boxaGetCount(boxas);
1036 boxad = boxaCreate(n);
1037 for (i = 0; i < n; i++) {
1038 if ((box = boxaGetValidBox(boxas, i, copyflag)) != NULL)
1039 boxaAddBox(boxad, box, L_INSERT);
1040 }
1041
1042 return boxad;
1043 }
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 {
1088 l_int32 i, n;
1089 BOX *boxt;
1090
1091 if (!boxa)
1092 return ERROR_INT("boxa not defined", __func__, 1);
1093
1094 n = boxa->nalloc;
1095 boxa->n = n;
1096 for (i = 0; i < n; i++) {
1097 if (box)
1098 boxt = boxCopy(box);
1099 else
1100 boxt = boxCreate(0, 0, 0, 0);
1101 boxaReplaceBox(boxa, i, boxt);
1102 }
1103 return 0;
1104 }
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 {
1122 l_int32 i, n;
1123
1124 if (!boxa)
1125 return ERROR_INT("boxa not defined", __func__, 1);
1126
1127 n = boxaGetCount(boxa);
1128 for (i = 0; i < n; i++)
1129 boxDestroy(&boxa->box[i]);
1130 boxa->n = 0;
1131 return 0;
1132 }
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 {
1147 BOXAA *baa;
1148
1149 if (n <= 0 || n > MaxBoxaaPtrArraySize)
1150 n = InitialPtrArraySize;
1151
1152 baa = (BOXAA *)LEPT_CALLOC(1, sizeof(BOXAA));
1153 if ((baa->boxa = (BOXA **)LEPT_CALLOC(n, sizeof(BOXA *))) == NULL) {
1154 boxaaDestroy(&baa);
1155 return (BOXAA *)ERROR_PTR("boxa ptr array not made", __func__, NULL);
1156 }
1157 baa->nalloc = n;
1158 baa->n = 0;
1159 return baa;
1160 }
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 {
1181 l_int32 i, n;
1182 BOXA *boxa;
1183 BOXAA *baad;
1184
1185 if (!baas)
1186 return (BOXAA *)ERROR_PTR("baas not defined", __func__, NULL);
1187 if (copyflag != L_COPY && copyflag != L_CLONE)
1188 return (BOXAA *)ERROR_PTR("invalid copyflag", __func__, NULL);
1189
1190 n = boxaaGetCount(baas);
1191 baad = boxaaCreate(n);
1192 for (i = 0; i < n; i++) {
1193 boxa = boxaaGetBoxa(baas, i, copyflag);
1194 boxaaAddBoxa(baad, boxa, L_INSERT);
1195 }
1196
1197 return baad;
1198 }
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 {
1209 l_int32 i;
1210 BOXAA *baa;
1211
1212 if (pbaa == NULL) {
1213 L_WARNING("ptr address is NULL!\n", __func__);
1214 return;
1215 }
1216
1217 if ((baa = *pbaa) == NULL)
1218 return;
1219
1220 for (i = 0; i < baa->n; i++)
1221 boxaDestroy(&baa->boxa[i]);
1222 LEPT_FREE(baa->boxa);
1223 LEPT_FREE(baa);
1224 *pbaa = NULL;
1225 }
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 {
1245 l_int32 n;
1246 BOXA *bac;
1247
1248 if (!baa)
1249 return ERROR_INT("baa not defined", __func__, 1);
1250 if (!ba)
1251 return ERROR_INT("ba not defined", __func__, 1);
1252 if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
1253 return ERROR_INT("invalid copyflag", __func__, 1);
1254
1255 if (copyflag == L_INSERT)
1256 bac = ba;
1257 else
1258 bac = boxaCopy(ba, copyflag);
1259
1260 n = boxaaGetCount(baa);
1261 if (n >= baa->nalloc) {
1262 if (boxaaExtendArray(baa))
1263 return ERROR_INT("extension failed", __func__, 1);
1264 }
1265 baa->boxa[n] = bac;
1266 baa->n++;
1267 return 0;
1268 }
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 {
1286 if (!baa)
1287 return ERROR_INT("baa not defined", __func__, 1);
1288
1289 return boxaaExtendArrayToSize(baa, 2 * baa->nalloc);
1290 }
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 {
1310 size_t oldsize, newsize;
1311
1312 if (!baa)
1313 return ERROR_INT("baa not defined", __func__, 1);
1314 if (baa->nalloc > MaxBoxaaPtrArraySize) /* belt & suspenders */
1315 return ERROR_INT("baa has too many ptrs", __func__, 1);
1316 if (size > MaxBoxaaPtrArraySize)
1317 return ERROR_INT("size > 1M boxa ptrs; too large", __func__, 1);
1318 if (size <= baa->nalloc) {
1319 L_INFO("size too small; no extension\n", __func__);
1320 return 0;
1321 }
1322
1323 oldsize = baa->nalloc * sizeof(BOXA *);
1324 newsize = size * sizeof(BOXA *);
1325 if ((baa->boxa = (BOXA **)reallocNew((void **)&baa->boxa,
1326 oldsize, newsize)) == NULL)
1327 return ERROR_INT("new ptr array not returned", __func__, 1);
1328 baa->nalloc = size;
1329 return 0;
1330 }
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 {
1345 if (!baa)
1346 return ERROR_INT("baa not defined", __func__, 0);
1347 return baa->n;
1348 }
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 {
1360 BOXA *boxa;
1361 l_int32 n, sum, i;
1362
1363 if (!baa)
1364 return ERROR_INT("baa not defined", __func__, 0);
1365
1366 n = boxaaGetCount(baa);
1367 for (sum = 0, i = 0; i < n; i++) {
1368 boxa = boxaaGetBoxa(baa, i, L_CLONE);
1369 sum += boxaGetCount(boxa);
1370 boxaDestroy(&boxa);
1371 }
1372
1373 return sum;
1374 }
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 {
1390 l_int32 n;
1391
1392 if (!baa)
1393 return (BOXA *)ERROR_PTR("baa not defined", __func__, NULL);
1394 n = boxaaGetCount(baa);
1395 if (index < 0 || index >= n)
1396 return (BOXA *)ERROR_PTR("index not valid", __func__, NULL);
1397 if (accessflag != L_COPY && accessflag != L_CLONE)
1398 return (BOXA *)ERROR_PTR("invalid accessflag", __func__, NULL);
1399
1400 return boxaCopy(baa->boxa[index], accessflag);
1401 }
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 {
1419 BOX *box;
1420 BOXA *boxa;
1421
1422 if ((boxa = boxaaGetBoxa(baa, iboxa, L_CLONE)) == NULL)
1423 return (BOX *)ERROR_PTR("boxa not retrieved", __func__, NULL);
1424 if ((box = boxaGetBox(boxa, ibox, accessflag)) == NULL)
1425 L_ERROR("box not retrieved\n", __func__);
1426 boxaDestroy(&boxa);
1427 return box;
1428 }
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 {
1467 l_int32 i, n;
1468 BOXA *boxat;
1469
1470 if (!baa)
1471 return ERROR_INT("baa not defined", __func__, 1);
1472 if (!boxa)
1473 return ERROR_INT("boxa not defined", __func__, 1);
1474
1475 n = baa->nalloc;
1476 baa->n = n;
1477 for (i = 0; i < n; i++) {
1478 boxat = boxaCopy(boxa, L_COPY);
1479 boxaaReplaceBoxa(baa, i, boxat);
1480 }
1481 return 0;
1482 }
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 {
1506 l_int32 i, n;
1507
1508 if (!baa)
1509 return ERROR_INT("baa not defined", __func__, 1);
1510 if (!boxa)
1511 return ERROR_INT("boxa not defined", __func__, 1);
1512
1513 /* Extend the ptr array if necessary */
1514 n = boxaaGetCount(baa);
1515 if (maxindex < n) return 0;
1516 if (boxaaExtendArrayToSize(baa, maxindex + 1))
1517 return ERROR_INT("extension failed", __func__, 1);
1518
1519 /* Fill the new entries with copies of boxa */
1520 for (i = n; i <= maxindex; i++)
1521 boxaaAddBoxa(baa, boxa, L_COPY);
1522 return 0;
1523 }
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 {
1546 l_int32 n;
1547
1548 if (!baa)
1549 return ERROR_INT("baa not defined", __func__, 1);
1550 if (!boxa)
1551 return ERROR_INT("boxa not defined", __func__, 1);
1552 n = boxaaGetCount(baa);
1553 if (index < 0 || index >= n)
1554 return ERROR_INT("index not valid", __func__, 1);
1555
1556 boxaDestroy(&baa->boxa[index]);
1557 baa->boxa[index] = boxa;
1558 return 0;
1559 }
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 {
1586 l_int32 i, n;
1587 BOXA **array;
1588
1589 if (!baa)
1590 return ERROR_INT("baa not defined", __func__, 1);
1591 n = boxaaGetCount(baa);
1592 if (index < 0 || index > n) {
1593 L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n);
1594 return 1;
1595 }
1596 if (!boxa)
1597 return ERROR_INT("boxa not defined", __func__, 1);
1598
1599 if (n >= baa->nalloc) {
1600 if (boxaaExtendArray(baa))
1601 return ERROR_INT("extension failed", __func__, 1);
1602 }
1603 array = baa->boxa;
1604 baa->n++;
1605 for (i = n; i > index; i--)
1606 array[i] = array[i - 1];
1607 array[index] = boxa;
1608 return 0;
1609 }
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 {
1632 l_int32 i, n;
1633 BOXA **array;
1634
1635 if (!baa)
1636 return ERROR_INT("baa not defined", __func__, 1);
1637 n = boxaaGetCount(baa);
1638 if (index < 0 || index >= n)
1639 return ERROR_INT("index not valid", __func__, 1);
1640
1641 array = baa->boxa;
1642 boxaDestroy(&array[index]);
1643 for (i = index + 1; i < n; i++)
1644 array[i - 1] = array[i];
1645 array[n - 1] = NULL;
1646 baa->n--;
1647
1648 return 0;
1649 }
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 {
1672 l_int32 n;
1673 BOXA *boxa;
1674 if (!baa)
1675 return ERROR_INT("baa not defined", __func__, 1);
1676 n = boxaaGetCount(baa);
1677 if (index < 0 || index >= n)
1678 return ERROR_INT("index not valid", __func__, 1);
1679 if (accessflag != L_INSERT && accessflag != L_COPY && accessflag != L_CLONE)
1680 return ERROR_INT("invalid accessflag", __func__, 1);
1681
1682 boxa = boxaaGetBoxa(baa, index, L_CLONE);
1683 boxaAddBox(boxa, box, accessflag);
1684 boxaDestroy(&boxa);
1685 return 0;
1686 }
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 {
1718 char *fname;
1719 l_int32 i, n;
1720 BOXA *boxa;
1721 BOXAA *baa;
1722 SARRAY *sa;
1723
1724 if (!dirname)
1725 return (BOXAA *)ERROR_PTR("dirname not defined", __func__, NULL);
1726
1727 sa = getSortedPathnamesInDirectory(dirname, substr, first, nfiles);
1728 if (!sa || ((n = sarrayGetCount(sa)) == 0)) {
1729 sarrayDestroy(&sa);
1730 return (BOXAA *)ERROR_PTR("no pixa files found", __func__, NULL);
1731 }
1732
1733 baa = boxaaCreate(n);
1734 for (i = 0; i < n; i++) {
1735 fname = sarrayGetString(sa, i, L_NOCOPY);
1736 if ((boxa = boxaRead(fname)) == NULL) {
1737 L_ERROR("boxa not read for %d-th file", __func__, i);
1738 continue;
1739 }
1740 boxaaAddBoxa(baa, boxa, L_INSERT);
1741 }
1742
1743 sarrayDestroy(&sa);
1744 return baa;
1745 }
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 {
1757 FILE *fp;
1758 BOXAA *baa;
1759
1760 if (!filename)
1761 return (BOXAA *)ERROR_PTR("filename not defined", __func__, NULL);
1762
1763 if ((fp = fopenReadStream(filename)) == NULL)
1764 return (BOXAA *)ERROR_PTR_1("stream not opened",
1765 filename, __func__, NULL);
1766 baa = boxaaReadStream(fp);
1767 fclose(fp);
1768 if (!baa)
1769 return (BOXAA *)ERROR_PTR_1("boxaa not read",
1770 filename, __func__, NULL);
1771 return baa;
1772 }
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 {
1789 l_int32 n, i, x, y, w, h, version;
1790 l_int32 ignore;
1791 BOXA *boxa;
1792 BOXAA *baa;
1793
1794 if (!fp)
1795 return (BOXAA *)ERROR_PTR("stream not defined", __func__, NULL);
1796
1797 if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1)
1798 return (BOXAA *)ERROR_PTR("not a boxaa file", __func__, NULL);
1799 if (version != BOXAA_VERSION_NUMBER)
1800 return (BOXAA *)ERROR_PTR("invalid boxa version", __func__, NULL);
1801 if (fscanf(fp, "Number of boxa = %d\n", &n) != 1)
1802 return (BOXAA *)ERROR_PTR("not a boxaa file", __func__, NULL);
1803 if (n < 0)
1804 return (BOXAA *)ERROR_PTR("num boxa ptrs < 0", __func__, NULL);
1805 if (n > MaxBoxaaPtrArraySize)
1806 return (BOXAA *)ERROR_PTR("too many boxa ptrs", __func__, NULL);
1807 if (n == 0) L_INFO("the boxaa is empty\n", __func__);
1808
1809 if ((baa = boxaaCreate(n)) == NULL)
1810 return (BOXAA *)ERROR_PTR("boxaa not made", __func__, NULL);
1811 for (i = 0; i < n; i++) {
1812 if (fscanf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
1813 &ignore, &x, &y, &w, &h) != 5) {
1814 boxaaDestroy(&baa);
1815 return (BOXAA *)ERROR_PTR("boxa descr not valid", __func__, NULL);
1816 }
1817 if ((boxa = boxaReadStream(fp)) == NULL) {
1818 boxaaDestroy(&baa);
1819 return (BOXAA *)ERROR_PTR("boxa not made", __func__, NULL);
1820 }
1821 boxaaAddBoxa(baa, boxa, L_INSERT);
1822 }
1823 return baa;
1824 }
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 {
1838 FILE *fp;
1839 BOXAA *baa;
1840
1841 if (!data)
1842 return (BOXAA *)ERROR_PTR("data not defined", __func__, NULL);
1843 if ((fp = fopenReadFromMemory(data, size)) == NULL)
1844 return (BOXAA *)ERROR_PTR("stream not opened", __func__, NULL);
1845
1846 baa = boxaaReadStream(fp);
1847 fclose(fp);
1848 if (!baa) L_ERROR("baa not read\n", __func__);
1849 return baa;
1850 }
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 {
1864 l_int32 ret;
1865 FILE *fp;
1866
1867 if (!filename)
1868 return ERROR_INT("filename not defined", __func__, 1);
1869 if (!baa)
1870 return ERROR_INT("baa not defined", __func__, 1);
1871
1872 if ((fp = fopenWriteStream(filename, "w")) == NULL)
1873 return ERROR_INT_1("stream not opened", filename, __func__, 1);
1874 ret = boxaaWriteStream(fp, baa);
1875 fclose(fp);
1876 if (ret)
1877 return ERROR_INT_1("baa not written to stream", filename, __func__, 1);
1878 return 0;
1879 }
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 {
1893 l_int32 n, i, x, y, w, h;
1894 BOX *box;
1895 BOXA *boxa;
1896
1897 if (!fp)
1898 return ERROR_INT("stream not defined", __func__, 1);
1899 if (!baa)
1900 return ERROR_INT("baa not defined", __func__, 1);
1901
1902 n = boxaaGetCount(baa);
1903 fprintf(fp, "\nBoxaa Version %d\n", BOXAA_VERSION_NUMBER);
1904 fprintf(fp, "Number of boxa = %d\n", n);
1905
1906 for (i = 0; i < n; i++) {
1907 if ((boxa = boxaaGetBoxa(baa, i, L_CLONE)) == NULL)
1908 return ERROR_INT("boxa not found", __func__, 1);
1909 boxaGetExtent(boxa, NULL, NULL, &box);
1910 boxGetGeometry(box, &x, &y, &w, &h);
1911 fprintf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
1912 i, x, y, w, h);
1913 boxaWriteStream(fp, boxa);
1914 boxDestroy(&box);
1915 boxaDestroy(&boxa);
1916 }
1917 return 0;
1918 }
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 {
1939 l_int32 ret;
1940 FILE *fp;
1941
1942 if (pdata) *pdata = NULL;
1943 if (psize) *psize = 0;
1944 if (!pdata)
1945 return ERROR_INT("&data not defined", __func__, 1);
1946 if (!psize)
1947 return ERROR_INT("&size not defined", __func__, 1);
1948 if (!baa)
1949 return ERROR_INT("baa not defined", __func__, 1);
1950
1951 #if HAVE_FMEMOPEN
1952 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1953 return ERROR_INT("stream not opened", __func__, 1);
1954 ret = boxaaWriteStream(fp, baa);
1955 fputc('\0', fp);
1956 fclose(fp);
1957 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 return ret;
1973 }
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 {
1988 FILE *fp;
1989 BOXA *boxa;
1990
1991 if (!filename)
1992 return (BOXA *)ERROR_PTR("filename not defined", __func__, NULL);
1993
1994 if ((fp = fopenReadStream(filename)) == NULL)
1995 return (BOXA *)ERROR_PTR_1("stream not opened",
1996 filename, __func__, NULL);
1997 boxa = boxaReadStream(fp);
1998 fclose(fp);
1999 if (!boxa)
2000 return (BOXA *)ERROR_PTR_1("boxa not read",
2001 filename, __func__, NULL);
2002 return boxa;
2003 }
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 {
2020 l_int32 n, i, x, y, w, h, version;
2021 l_int32 ignore;
2022 BOX *box;
2023 BOXA *boxa;
2024
2025 if (!fp)
2026 return (BOXA *)ERROR_PTR("stream not defined", __func__, NULL);
2027
2028 if (fscanf(fp, "\nBoxa Version %d\n", &version) != 1)
2029 return (BOXA *)ERROR_PTR("not a boxa file", __func__, NULL);
2030 if (version != BOXA_VERSION_NUMBER)
2031 return (BOXA *)ERROR_PTR("invalid boxa version", __func__, NULL);
2032 if (fscanf(fp, "Number of boxes = %d\n", &n) != 1)
2033 return (BOXA *)ERROR_PTR("not a boxa file", __func__, NULL);
2034 if (n < 0)
2035 return (BOXA *)ERROR_PTR("num box ptrs < 0", __func__, NULL);
2036 if (n > MaxBoxaPtrArraySize)
2037 return (BOXA *)ERROR_PTR("too many box ptrs", __func__, NULL);
2038 if (n == 0) L_INFO("the boxa is empty\n", __func__);
2039
2040 if ((boxa = boxaCreate(n)) == NULL)
2041 return (BOXA *)ERROR_PTR("boxa not made", __func__, NULL);
2042 for (i = 0; i < n; i++) {
2043 if (fscanf(fp, " Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
2044 &ignore, &x, &y, &w, &h) != 5) {
2045 boxaDestroy(&boxa);
2046 return (BOXA *)ERROR_PTR("box descr not valid", __func__, NULL);
2047 }
2048 box = boxCreate(x, y, w, h);
2049 boxaAddBox(boxa, box, L_INSERT);
2050 }
2051 return boxa;
2052 }
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 {
2066 FILE *fp;
2067 BOXA *boxa;
2068
2069 if (!data)
2070 return (BOXA *)ERROR_PTR("data not defined", __func__, NULL);
2071 if ((fp = fopenReadFromMemory(data, size)) == NULL)
2072 return (BOXA *)ERROR_PTR("stream not opened", __func__, NULL);
2073
2074 boxa = boxaReadStream(fp);
2075 fclose(fp);
2076 if (!boxa) L_ERROR("boxa not read\n", __func__);
2077 return boxa;
2078 }
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 {
2101 if (LeptDebugOK) {
2102 return boxaWrite(filename, boxa);
2103 } else {
2104 L_INFO("write to named temp file %s is disabled\n", __func__, filename);
2105 return 0;
2106 }
2107 }
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 {
2121 l_int32 ret;
2122 FILE *fp;
2123
2124 if (!filename)
2125 return ERROR_INT("filename not defined", __func__, 1);
2126 if (!boxa)
2127 return ERROR_INT("boxa not defined", __func__, 1);
2128
2129 if ((fp = fopenWriteStream(filename, "w")) == NULL)
2130 return ERROR_INT_1("stream not opened", filename, __func__, 1);
2131 ret = boxaWriteStream(fp, boxa);
2132 fclose(fp);
2133 if (ret)
2134 return ERROR_INT_1("boxa not written to stream", filename, __func__, 1);
2135
2136 return 0;
2137 }
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 {
2151 l_int32 n, i;
2152 BOX *box;
2153
2154 if (!boxa)
2155 return ERROR_INT("boxa not defined", __func__, 1);
2156 if (!fp)
2157 return boxaWriteStderr(boxa);
2158
2159 n = boxaGetCount(boxa);
2160 fprintf(fp, "\nBoxa Version %d\n", BOXA_VERSION_NUMBER);
2161 fprintf(fp, "Number of boxes = %d\n", n);
2162 for (i = 0; i < n; i++) {
2163 if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL)
2164 return ERROR_INT("box not found", __func__, 1);
2165 fprintf(fp, " Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
2166 i, box->x, box->y, box->w, box->h);
2167 boxDestroy(&box);
2168 }
2169 return 0;
2170 }
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 {
2182 l_int32 n, i;
2183 BOX *box;
2184
2185 if (!boxa)
2186 return ERROR_INT("boxa not defined", __func__, 1);
2187
2188 n = boxaGetCount(boxa);
2189 lept_stderr("\nBoxa Version %d\n", BOXA_VERSION_NUMBER);
2190 lept_stderr("Number of boxes = %d\n", n);
2191 for (i = 0; i < n; i++) {
2192 if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL)
2193 return ERROR_INT("box not found", __func__, 1);
2194 lept_stderr(" Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
2195 i, box->x, box->y, box->w, box->h);
2196 boxDestroy(&box);
2197 }
2198 return 0;
2199 }
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 {
2220 l_int32 ret;
2221 FILE *fp;
2222
2223 if (pdata) *pdata = NULL;
2224 if (psize) *psize = 0;
2225 if (!pdata)
2226 return ERROR_INT("&data not defined", __func__, 1);
2227 if (!psize)
2228 return ERROR_INT("&size not defined", __func__, 1);
2229 if (!boxa)
2230 return ERROR_INT("boxa not defined", __func__, 1);
2231
2232 #if HAVE_FMEMOPEN
2233 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
2234 return ERROR_INT("stream not opened", __func__, 1);
2235 ret = boxaWriteStream(fp, boxa);
2236 fputc('\0', fp);
2237 fclose(fp);
2238 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 return ret;
2254 }
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 {
2277 if (!box)
2278 return ERROR_INT("box not defined", __func__, 1);
2279
2280 if (!fp) { /* output to stderr */
2281 lept_stderr(" Box: x = %d, y = %d, w = %d, h = %d\n",
2282 box->x, box->y, box->w, box->h);
2283 } else {
2284 fprintf(fp, " Box: x = %d, y = %d, w = %d, h = %d\n",
2285 box->x, box->y, box->w, box->h);
2286 }
2287 return 0;
2288 }