• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*====================================================================*
2  -  Copyright (C) 2001 Leptonica.  All rights reserved.
3  -  This software is distributed in the hope that it will be
4  -  useful, but with NO WARRANTY OF ANY KIND.
5  -  No author or distributor accepts responsibility to anyone for the
6  -  consequences of using this software, or for whether it serves any
7  -  particular purpose or works at all, unless he or she says so in
8  -  writing.  Everyone is granted permission to copy, modify and
9  -  redistribute this source code, for commercial or non-commercial
10  -  purposes, with the following restrictions: (1) the origin of this
11  -  source code must not be misrepresented; (2) modified versions must
12  -  be plainly marked as such; and (3) this notice may not be removed
13  -  or altered from any source or modified source distribution.
14  *====================================================================*/
15 
16 /*
17  *   boxbasic.c
18  *
19  *   Basic 'class' functions for box, boxa and boxaa,
20  *   including accessors and serialization.
21  *
22  *      Box creation, copy, clone, destruction
23  *           BOX      *boxCreate()
24  *           BOX      *boxCopy()
25  *           BOX      *boxClone()
26  *           void      boxDestroy()
27  *
28  *      Box accessors
29  *           l_int32   boxGetGeometry()
30  *           l_int32   boxSetGeometry()
31  *           l_int32   boxGetRefcount()
32  *           l_int32   boxChangeRefcount()
33  *
34  *      Boxa creation, copy, destruction
35  *           BOXA     *boxaCreate()
36  *           BOXA     *boxaCopy()
37  *           void      boxaDestroy()
38  *
39  *      Boxa array extension
40  *           l_int32   boxaAddBox()
41  *           l_int32   boxaExtendArray()
42  *
43  *      Boxa accessors
44  *           l_int32   boxaGetCount()
45  *           l_int32   boxaGetBox()
46  *           l_int32   boxaGetBoxGeometry()
47  *
48  *      Boxa array modifiers
49  *           l_int32   boxaReplaceBox()
50  *           l_int32   boxaInsertBox()
51  *           l_int32   boxaRemoveBox()
52  *
53  *      Boxaa creation, copy, destruction
54  *           BOXAA    *boxaaCreate()
55  *           BOXAA    *boxaaCopy()
56  *           void      boxaaDestroy()
57  *
58  *      Boxaa array extension
59  *           l_int32   boxaaAddBoxa()
60  *           l_int32   boxaaExtendArray()
61  *
62  *      Boxaa accessors
63  *           l_int32   boxaaGetCount()
64  *           l_int32   boxaaGetBoxCount()
65  *           BOXA     *boxaaGetBoxa()
66  *
67  *      Boxa array modifiers
68  *           l_int32   boxaaReplaceBoxa()
69  *           l_int32   boxaaInsertBoxa()
70  *           l_int32   boxaaRemoveBoxa()
71  *           l_int32   boxaaAddBox()
72  *
73  *      Boxaa serialized I/O
74  *           BOXAA    *boxaaRead()
75  *           BOXAA    *boxaaReadStream()
76  *           l_int32   boxaaWrite()
77  *           l_int32   boxaaWriteStream()
78  *
79  *      Boxa serialized I/O
80  *           BOXA     *boxaRead()
81  *           BOXA     *boxaReadStream()
82  *           l_int32   boxaWrite()
83  *           l_int32   boxaWriteStream()
84  *
85  *      Box print (for debug)
86  *           l_int32   boxPrintStreamInfo()
87  *
88  *      Backward compatibility old boxaa read functions
89  *           BOXAA    *boxaaReadVersion2()
90  *           BOXAA    *boxaaReadStreamVersion2()
91  */
92 
93 #include <stdio.h>
94 #include <stdlib.h>
95 #include <string.h>
96 #include "allheaders.h"
97 
98 static const l_int32  INITIAL_PTR_ARRAYSIZE = 20;   /* n'import quoi */
99 
100 
101 /*---------------------------------------------------------------------*
102  *                  Box creation, destruction and copy                 *
103  *---------------------------------------------------------------------*/
104 /*!
105  *  boxCreate()
106  *
107  *      Input:  x, y, width, height
108  *      Return: box, or null on error
109  *
110  *  Notes:
111  *      (1) This clips the box to the +quad.  If no part of the
112  *          box is in the +quad, this returns NULL.
113  */
114 BOX *
boxCreate(l_int32 x,l_int32 y,l_int32 w,l_int32 h)115 boxCreate(l_int32  x,
116           l_int32  y,
117           l_int32  w,
118           l_int32  h)
119 {
120 BOX  *box;
121 
122     PROCNAME("boxCreate");
123 
124     if (w <= 0 || h <= 0)
125         return (BOX *)ERROR_PTR("w and h not both > 0", procName, NULL);
126     if (x < 0) {  /* take part in +quad */
127         w = w + x;
128         x = 0;
129         if (w <= 0)
130             return (BOX *)ERROR_PTR("x < 0 and box off +quad", procName, NULL);
131     }
132     if (y < 0) {  /* take part in +quad */
133         h = h + y;
134         y = 0;
135         if (h <= 0)
136             return (BOX *)ERROR_PTR("y < 0 and box off +quad", procName, NULL);
137     }
138 
139     if ((box = (BOX *)CALLOC(1, sizeof(BOX))) == NULL)
140         return (BOX *)ERROR_PTR("box not made", procName, NULL);
141     boxSetGeometry(box, x, y, w, h);
142     box->refcount = 1;
143 
144     return box;
145 }
146 
147 
148 /*!
149  *  boxCopy()
150  *
151  *      Input:  box
152  *      Return: copy of box, or null on error
153  */
154 BOX *
boxCopy(BOX * box)155 boxCopy(BOX  *box)
156 {
157 BOX  *boxc;
158 
159     PROCNAME("boxCopy");
160 
161     if (!box)
162         return (BOX *)ERROR_PTR("box not defined", procName, NULL);
163 
164     boxc = boxCreate(box->x, box->y, box->w, box->h);
165 
166     return boxc;
167 }
168 
169 
170 /*!
171  *  boxClone()
172  *
173  *      Input:  box
174  *      Return: ptr to same box, or null on error
175  */
176 BOX *
boxClone(BOX * box)177 boxClone(BOX  *box)
178 {
179 
180     PROCNAME("boxClone");
181 
182     if (!box)
183         return (BOX *)ERROR_PTR("box not defined", procName, NULL);
184 
185     boxChangeRefcount(box, 1);
186     return box;
187 }
188 
189 
190 /*!
191  *  boxDestroy()
192  *
193  *      Input:  &box (<will be set to null before returning>)
194  *      Return: void
195  *
196  *  Notes:
197  *      (1) Decrements the ref count and, if 0, destroys the box.
198  *      (2) Always nulls the input ptr.
199  */
200 void
boxDestroy(BOX ** pbox)201 boxDestroy(BOX  **pbox)
202 {
203 BOX  *box;
204 
205     PROCNAME("boxDestroy");
206 
207     if (pbox == NULL) {
208         L_WARNING("ptr address is null!", procName);
209         return;
210     }
211     if ((box = *pbox) == NULL)
212         return;
213 
214     boxChangeRefcount(box, -1);
215     if (boxGetRefcount(box) <= 0)
216         FREE(box);
217     *pbox = NULL;
218     return;
219 }
220 
221 
222 /*---------------------------------------------------------------------*
223  *                              Box accessors                          *
224  *---------------------------------------------------------------------*/
225 /*!
226  *  boxGetGeometry()
227  *
228  *      Input:  box
229  *              &x, &y, &w, &h (<optional return>; each can be null)
230  *      Return: 0 if OK, 1 on error
231  */
232 l_int32
boxGetGeometry(BOX * box,l_int32 * px,l_int32 * py,l_int32 * pw,l_int32 * ph)233 boxGetGeometry(BOX      *box,
234                l_int32  *px,
235                l_int32  *py,
236                l_int32  *pw,
237                l_int32  *ph)
238 {
239     PROCNAME("boxGetGeometry");
240 
241     if (px) *px = 0;
242     if (py) *py = 0;
243     if (pw) *pw = 0;
244     if (ph) *ph = 0;
245     if (!box)
246         return ERROR_INT("box not defined", procName, 1);
247     if (px) *px = box->x;
248     if (py) *py = box->y;
249     if (pw) *pw = box->w;
250     if (ph) *ph = box->h;
251     return 0;
252 }
253 
254 
255 /*!
256  *  boxSetGeometry()
257  *
258  *      Input:  box
259  *              x, y, w, h (use -1 to leave unchanged)
260  *      Return: 0 if OK, 1 on error
261  */
262 l_int32
boxSetGeometry(BOX * box,l_int32 x,l_int32 y,l_int32 w,l_int32 h)263 boxSetGeometry(BOX     *box,
264                l_int32  x,
265                l_int32  y,
266                l_int32  w,
267                l_int32  h)
268 {
269     PROCNAME("boxSetGeometry");
270 
271     if (!box)
272         return ERROR_INT("box not defined", procName, 1);
273     if (x != -1) box->x = x;
274     if (y != -1) box->y = y;
275     if (w != -1) box->w = w;
276     if (h != -1) box->h = h;
277     return 0;
278 }
279 
280 
281 l_int32
boxGetRefcount(BOX * box)282 boxGetRefcount(BOX  *box)
283 {
284     PROCNAME("boxGetRefcount");
285 
286     if (!box)
287         return ERROR_INT("box not defined", procName, UNDEF);
288 
289     return box->refcount;
290 }
291 
292 
293 l_int32
boxChangeRefcount(BOX * box,l_int32 delta)294 boxChangeRefcount(BOX     *box,
295                   l_int32  delta)
296 {
297     PROCNAME("boxChangeRefcount");
298 
299     if (!box)
300         return ERROR_INT("box not defined", procName, 1);
301 
302     box->refcount += delta;
303     return 0;
304 }
305 
306 
307 /*---------------------------------------------------------------------*
308  *             Boxa creation, destruction, copy, extension             *
309  *---------------------------------------------------------------------*/
310 /*!
311  *  boxaCreate()
312  *
313  *      Input:  n  (initial number of ptrs)
314  *      Return: boxa, or null on error
315  */
316 BOXA *
boxaCreate(l_int32 n)317 boxaCreate(l_int32  n)
318 {
319 BOXA  *boxa;
320 
321     PROCNAME("boxaCreate");
322 
323     if (n <= 0)
324         n = INITIAL_PTR_ARRAYSIZE;
325 
326     if ((boxa = (BOXA *)CALLOC(1, sizeof(BOXA))) == NULL)
327         return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
328     boxa->n = 0;
329     boxa->nalloc = n;
330     boxa->refcount = 1;
331 
332     if ((boxa->box = (BOX **)CALLOC(n, sizeof(BOX *))) == NULL)
333         return (BOXA *)ERROR_PTR("boxa ptrs not made", procName, NULL);
334 
335     return boxa;
336 }
337 
338 
339 /*!
340  *  boxaCopy()
341  *
342  *      Input:  boxa
343  *              copyflag (L_COPY, L_CLONE, L_COPY_CLONE)
344  *      Return: new boxa, or null on error
345  *
346  *  Notes:
347  *      (1) See pix.h for description of the copyflag.
348  *      (2) The copy-clone makes a new boxa that holds clones of each box.
349  */
350 BOXA *
boxaCopy(BOXA * boxa,l_int32 copyflag)351 boxaCopy(BOXA    *boxa,
352          l_int32  copyflag)
353 {
354 l_int32  i;
355 BOX     *boxc;
356 BOXA    *boxac;
357 
358     PROCNAME("boxaCopy");
359 
360     if (!boxa)
361         return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
362 
363     if (copyflag == L_CLONE) {
364         boxa->refcount++;
365         return boxa;
366     }
367 
368     if (copyflag != L_COPY && copyflag != L_COPY_CLONE)
369         return (BOXA *)ERROR_PTR("invalid copyflag", procName, NULL);
370 
371     if ((boxac = boxaCreate(boxa->nalloc)) == NULL)
372         return (BOXA *)ERROR_PTR("boxac not made", procName, NULL);
373     for (i = 0; i < boxa->n; i++) {
374         if (copyflag == L_COPY)
375             boxc = boxaGetBox(boxa, i, L_COPY);
376         else   /* copy-clone */
377             boxc = boxaGetBox(boxa, i, L_CLONE);
378         boxaAddBox(boxac, boxc, L_INSERT);
379     }
380     return boxac;
381 }
382 
383 
384 /*!
385  *  boxaDestroy()
386  *
387  *      Input:  &boxa (<will be set to null before returning>)
388  *      Return: void
389  *
390  *  Note:
391  *      - Decrements the ref count and, if 0, destroys the boxa.
392  *      - Always nulls the input ptr.
393  */
394 void
boxaDestroy(BOXA ** pboxa)395 boxaDestroy(BOXA  **pboxa)
396 {
397 l_int32  i;
398 BOXA    *boxa;
399 
400     PROCNAME("boxaDestroy");
401 
402     if (pboxa == NULL) {
403         L_WARNING("ptr address is null!", procName);
404         return;
405     }
406 
407     if ((boxa = *pboxa) == NULL)
408         return;
409 
410         /* Decrement the ref count.  If it is 0, destroy the boxa. */
411     boxa->refcount--;
412     if (boxa->refcount <= 0) {
413         for (i = 0; i < boxa->n; i++)
414             boxDestroy(&boxa->box[i]);
415         FREE(boxa->box);
416         FREE(boxa);
417     }
418 
419     *pboxa = NULL;
420     return;
421 }
422 
423 
424 /*!
425  *  boxaAddBox()
426  *
427  *      Input:  boxa
428  *              box  (to be added)
429  *              copyflag (L_INSERT, L_COPY, L_CLONE)
430  *      Return: 0 if OK, 1 on error
431  */
432 l_int32
boxaAddBox(BOXA * boxa,BOX * box,l_int32 copyflag)433 boxaAddBox(BOXA    *boxa,
434            BOX     *box,
435            l_int32  copyflag)
436 {
437 l_int32  n;
438 BOX     *boxc;
439 
440     PROCNAME("boxaAddBox");
441 
442     if (!boxa)
443         return ERROR_INT("boxa not defined", procName, 1);
444     if (!box)
445         return ERROR_INT("box not defined", procName, 1);
446 
447     if (copyflag == L_INSERT)
448         boxc = box;
449     else if (copyflag == L_COPY)
450         boxc = boxCopy(box);
451     else if (copyflag == L_CLONE)
452         boxc = boxClone(box);
453     else
454         return ERROR_INT("invalid copyflag", procName, 1);
455     if (!boxc)
456         return ERROR_INT("boxc not made", procName, 1);
457 
458     n = boxaGetCount(boxa);
459     if (n >= boxa->nalloc)
460         boxaExtendArray(boxa);
461     boxa->box[n] = boxc;
462     boxa->n++;
463 
464     return 0;
465 }
466 
467 
468 /*!
469  *  boxaExtendArray()
470  *
471  *      Input:  boxa
472  *      Return: 0 if OK; 1 on error
473  */
474 l_int32
boxaExtendArray(BOXA * boxa)475 boxaExtendArray(BOXA  *boxa)
476 {
477 
478     PROCNAME("boxaExtendArray");
479 
480     if (!boxa)
481         return ERROR_INT("boxa not defined", procName, 1);
482 
483     if ((boxa->box = (BOX **)reallocNew((void **)&boxa->box,
484                                sizeof(BOX *) * boxa->nalloc,
485                                2 * sizeof(BOX *) * boxa->nalloc)) == NULL)
486         return ERROR_INT("new ptr array not returned", procName, 1);
487 
488     boxa->nalloc = 2 * boxa->nalloc;
489     return 0;
490 }
491 
492 
493 
494 /*---------------------------------------------------------------------*
495  *                             Boxa accessors                          *
496  *---------------------------------------------------------------------*/
497 /*!
498  *  boxaGetCount()
499  *
500  *      Input:  boxa
501  *      Return: count, or 0 on error
502  */
503 l_int32
boxaGetCount(BOXA * boxa)504 boxaGetCount(BOXA  *boxa)
505 {
506 
507     PROCNAME("boxaGetCount");
508 
509     if (!boxa)
510         return ERROR_INT("boxa not defined", procName, 0);
511 
512     return boxa->n;
513 }
514 
515 
516 /*!
517  *  boxaGetBox()
518  *
519  *      Input:  boxa
520  *              index  (to the index-th box)
521  *              accessflag  (L_COPY or L_CLONE)
522  *      Return: box, or null on error
523  */
524 BOX *
boxaGetBox(BOXA * boxa,l_int32 index,l_int32 accessflag)525 boxaGetBox(BOXA    *boxa,
526            l_int32  index,
527            l_int32  accessflag)
528 {
529     PROCNAME("boxaGetBox");
530 
531     if (!boxa)
532         return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
533     if (index < 0 || index >= boxa->n)
534         return (BOX *)ERROR_PTR("index not valid", procName, NULL);
535 
536     if (accessflag == L_COPY)
537         return boxCopy(boxa->box[index]);
538     else if (accessflag == L_CLONE)
539         return boxClone(boxa->box[index]);
540     else
541         return (BOX *)ERROR_PTR("invalid accessflag", procName, NULL);
542 }
543 
544 
545 /*!
546  *  boxaGetBoxGeometry()
547  *
548  *      Input:  boxa
549  *              index  (to the index-th box)
550  *              &x, &y, &w, &h (<optional return>; each can be null)
551  *      Return: 0 if OK, 1 on error
552  */
553 l_int32
boxaGetBoxGeometry(BOXA * boxa,l_int32 index,l_int32 * px,l_int32 * py,l_int32 * pw,l_int32 * ph)554 boxaGetBoxGeometry(BOXA     *boxa,
555                    l_int32   index,
556                    l_int32  *px,
557                    l_int32  *py,
558                    l_int32  *pw,
559                    l_int32  *ph)
560 {
561 BOX  *box;
562 
563     PROCNAME("boxaGetBoxGeometry");
564 
565     if (px) *px = 0;
566     if (py) *py = 0;
567     if (pw) *pw = 0;
568     if (ph) *ph = 0;
569     if (!boxa)
570         return ERROR_INT("boxa not defined", procName, 1);
571     if (index < 0 || index >= boxa->n)
572         return ERROR_INT("index not valid", procName, 1);
573 
574     if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL)
575         return ERROR_INT("box not found!", procName, 1);
576     boxGetGeometry(box, px, py, pw, ph);
577     boxDestroy(&box);
578     return 0;
579 }
580 
581 
582 /*---------------------------------------------------------------------*
583  *                        Boxa array modifiers                         *
584  *---------------------------------------------------------------------*/
585 /*!
586  *  boxaReplaceBox()
587  *
588  *      Input:  boxa
589  *              index  (to the index-th box)
590  *              box (insert to replace existing one)
591  *      Return: 0 if OK, 1 on error
592  *
593  *  Notes:
594  *      (1) In-place replacement of one box.
595  *      (2) The previous box at that location is destroyed.
596  */
597 l_int32
boxaReplaceBox(BOXA * boxa,l_int32 index,BOX * box)598 boxaReplaceBox(BOXA    *boxa,
599                l_int32  index,
600                BOX     *box)
601 {
602     PROCNAME("boxaReplaceBox");
603 
604     if (!boxa)
605         return ERROR_INT("boxa not defined", procName, 1);
606     if (index < 0 || index >= boxa->n)
607         return ERROR_INT("index not valid", procName, 1);
608     if (!box)
609         return ERROR_INT("box not defined", procName, 1);
610 
611     boxDestroy(&(boxa->box[index]));
612     boxa->box[index] = box;
613     return 0;
614 }
615 
616 
617 /*!
618  *  boxaInsertBox()
619  *
620  *      Input:  boxa
621  *              index (location in boxa to insert new value)
622  *              box (new box to be inserted)
623  *      Return: 0 if OK, 1 on error
624  *
625  *  Notes:
626  *      (1) This shifts box[i] --> box[i + 1] for all i >= index,
627  *          and then inserts box as box[index].
628  *      (2) To insert at the beginning of the array, set index = 0.
629  *      (3) To append to the array, it's easier to use boxaAddBox().
630  *      (4) This should not be used repeatedly to insert into large arrays,
631  *          because the function is O(n).
632  */
633 l_int32
boxaInsertBox(BOXA * boxa,l_int32 index,BOX * box)634 boxaInsertBox(BOXA    *boxa,
635               l_int32  index,
636               BOX     *box)
637 {
638 l_int32  i, n;
639 BOX    **array;
640 
641     PROCNAME("boxaInsertBox");
642 
643     if (!boxa)
644         return ERROR_INT("boxa not defined", procName, 1);
645     n = boxaGetCount(boxa);
646     if (index < 0 || index > n)
647         return ERROR_INT("index not in {0...n}", procName, 1);
648     if (!box)
649         return ERROR_INT("box not defined", procName, 1);
650 
651     if (n >= boxa->nalloc)
652         boxaExtendArray(boxa);
653     array = boxa->box;
654     boxa->n++;
655     for (i = n; i > index; i--)
656         array[i] = array[i - 1];
657     array[index] = box;
658 
659     return 0;
660 }
661 
662 
663 /*!
664  *  boxaRemoveBox()
665  *
666  *      Input:  boxa
667  *              index (of box to be removed)
668  *      Return: 0 if OK, 1 on error
669  *
670  *  Notes:
671  *      (1) This removes box[index] and then shifts
672  *          box[i] --> box[i - 1] for all i > index.
673  *      (2) It should not be used repeatedly to remove boxes from
674  *          large arrays, because the function is O(n).
675  */
676 l_int32
boxaRemoveBox(BOXA * boxa,l_int32 index)677 boxaRemoveBox(BOXA    *boxa,
678               l_int32  index)
679 {
680 l_int32  i, n;
681 BOX    **array;
682 
683     PROCNAME("boxaRemoveBox");
684 
685     if (!boxa)
686         return ERROR_INT("boxa not defined", procName, 1);
687     n = boxaGetCount(boxa);
688     if (index < 0 || index >= n)
689         return ERROR_INT("index not in {0...n - 1}", procName, 1);
690 
691     array = boxa->box;
692     boxDestroy(&array[index]);
693     for (i = index + 1; i < n; i++)
694         array[i - 1] = array[i];
695     array[n - 1] = NULL;
696     boxa->n--;
697 
698     return 0;
699 }
700 
701 
702 /*--------------------------------------------------------------------------*
703  *                     Boxaa creation, destruction                          *
704  *--------------------------------------------------------------------------*/
705 /*!
706  *  boxaaCreate()
707  *
708  *      Input:  size of boxa ptr array to be alloc'd (0 for default)
709  *      Return: baa, or null on error
710  */
711 BOXAA *
boxaaCreate(l_int32 n)712 boxaaCreate(l_int32  n)
713 {
714 BOXAA  *baa;
715 
716     PROCNAME("boxaaCreate");
717 
718     if (n <= 0)
719         n = INITIAL_PTR_ARRAYSIZE;
720 
721     if ((baa = (BOXAA *)CALLOC(1, sizeof(BOXAA))) == NULL)
722         return (BOXAA *)ERROR_PTR("baa not made", procName, NULL);
723     if ((baa->boxa = (BOXA **)CALLOC(n, sizeof(BOXA *))) == NULL)
724         return (BOXAA *)ERROR_PTR("boxa ptr array not made", procName, NULL);
725 
726     baa->nalloc = n;
727     baa->n = 0;
728 
729     return baa;
730 }
731 
732 
733 /*!
734  *  boxaaCopy()
735  *
736  *      Input:  baas (input boxaa to be copied)
737  *              copyflag (L_COPY, L_CLONE)
738  *      Return: baad (new boxaa, composed of copies or clones of the boxa
739  *                    in baas), or null on error
740  *
741  *  Notes:
742  *      (1) L_COPY makes a copy of each boxa in baas.
743  *          L_CLONE makes a clone of each boxa in baas.
744  */
745 BOXAA *
boxaaCopy(BOXAA * baas,l_int32 copyflag)746 boxaaCopy(BOXAA   *baas,
747           l_int32  copyflag)
748 {
749 l_int32  i, n;
750 BOXA    *boxa;
751 BOXAA   *baad;
752 
753     PROCNAME("boxaaCopy");
754 
755     if (!baas)
756         return (BOXAA *)ERROR_PTR("baas not defined", procName, NULL);
757     if (copyflag != L_COPY && copyflag != L_CLONE)
758         return (BOXAA *)ERROR_PTR("invalid copyflag", procName, NULL);
759 
760     n = boxaaGetCount(baas);
761     baad = boxaaCreate(n);
762     for (i = 0; i < n; i++) {
763         boxa = boxaaGetBoxa(baas, i, copyflag);
764         boxaaAddBoxa(baad, boxa, L_INSERT);
765     }
766 
767     return baad;
768 }
769 
770 
771 /*!
772  *  boxaaDestroy()
773  *
774  *      Input:  &boxaa (<will be set to null before returning>)
775  *      Return: void
776  */
777 void
boxaaDestroy(BOXAA ** pbaa)778 boxaaDestroy(BOXAA  **pbaa)
779 {
780 l_int32  i;
781 BOXAA   *baa;
782 
783     PROCNAME("boxaaDestroy");
784 
785     if (pbaa == NULL) {
786         L_WARNING("ptr address is NULL!", procName);
787         return;
788     }
789 
790     if ((baa = *pbaa) == NULL)
791         return;
792 
793     for (i = 0; i < baa->n; i++)
794         boxaDestroy(&baa->boxa[i]);
795     FREE(baa->boxa);
796     FREE(baa);
797     *pbaa = NULL;
798 
799     return;
800 }
801 
802 
803 
804 /*--------------------------------------------------------------------------*
805  *                              Add Boxa to Boxaa                           *
806  *--------------------------------------------------------------------------*/
807 /*!
808  *  boxaaAddBoxa()
809  *
810  *      Input:  boxaa
811  *              boxa     (to be added)
812  *              copyflag  (L_INSERT, L_COPY, L_CLONE)
813  *      Return: 0 if OK, 1 on error
814  */
815 l_int32
boxaaAddBoxa(BOXAA * baa,BOXA * ba,l_int32 copyflag)816 boxaaAddBoxa(BOXAA   *baa,
817              BOXA    *ba,
818              l_int32  copyflag)
819 {
820 l_int32  n;
821 BOXA    *bac;
822 
823     PROCNAME("boxaaAddBoxa");
824 
825     if (!baa)
826         return ERROR_INT("baa not defined", procName, 1);
827     if (!ba)
828         return ERROR_INT("ba not defined", procName, 1);
829     if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
830         return ERROR_INT("invalid copyflag", procName, 1);
831 
832     if (copyflag == L_INSERT)
833         bac = ba;
834     else
835         bac = boxaCopy(ba, copyflag);
836 
837     n = boxaaGetCount(baa);
838     if (n >= baa->nalloc)
839         boxaaExtendArray(baa);
840     baa->boxa[n] = bac;
841     baa->n++;
842     return 0;
843 }
844 
845 
846 /*!
847  *  boxaaExtendArray()
848  *
849  *      Input:  boxaa
850  *      Return: 0 if OK, 1 on error
851  */
852 l_int32
boxaaExtendArray(BOXAA * baa)853 boxaaExtendArray(BOXAA  *baa)
854 {
855 
856     PROCNAME("boxaaExtendArray");
857 
858     if (!baa)
859         return ERROR_INT("baa not defined", procName, 1);
860 
861     if ((baa->boxa = (BOXA **)reallocNew((void **)&baa->boxa,
862                               sizeof(BOXA *) * baa->nalloc,
863                               2 * sizeof(BOXA *) * baa->nalloc)) == NULL)
864             return ERROR_INT("new ptr array not returned", procName, 1);
865 
866     baa->nalloc *= 2;
867     return 0;
868 }
869 
870 
871 /*----------------------------------------------------------------------*
872  *                           Boxaa accessors                            *
873  *----------------------------------------------------------------------*/
874 /*!
875  *  boxaaGetCount()
876  *
877  *      Input:  boxaa
878  *      Return: count (number of boxa), or 0 if no boxa or on error
879  */
880 l_int32
boxaaGetCount(BOXAA * baa)881 boxaaGetCount(BOXAA  *baa)
882 {
883     PROCNAME("boxaaGetCount");
884 
885     if (!baa)
886         return ERROR_INT("baa not defined", procName, 0);
887     return baa->n;
888 }
889 
890 
891 /*!
892  *  boxaaGetBoxCount()
893  *
894  *      Input:  boxaa
895  *      Return: count (number of boxes), or 0 if no boxes or on error
896  */
897 l_int32
boxaaGetBoxCount(BOXAA * baa)898 boxaaGetBoxCount(BOXAA  *baa)
899 {
900 BOXA    *boxa;
901 l_int32  n, sum, i;
902 
903     PROCNAME("boxaaGetBoxCount");
904 
905     if (!baa)
906         return ERROR_INT("baa not defined", procName, 0);
907 
908     n = boxaaGetCount(baa);
909     for (sum = 0, i = 0; i < n; i++) {
910         boxa = boxaaGetBoxa(baa, i, L_CLONE);
911         sum += boxaGetCount(boxa);
912         boxaDestroy(&boxa);
913     }
914 
915     return sum;
916 }
917 
918 
919 /*!
920  *  boxaaGetBoxa()
921  *
922  *      Input:  boxaa
923  *              index  (to the index-th boxa)
924  *              accessflag   (L_COPY or L_CLONE)
925  *      Return: boxa, or null on error
926  */
927 BOXA *
boxaaGetBoxa(BOXAA * baa,l_int32 index,l_int32 accessflag)928 boxaaGetBoxa(BOXAA   *baa,
929              l_int32  index,
930              l_int32  accessflag)
931 {
932 l_int32  n;
933 
934     PROCNAME("boxaaGetBoxa");
935 
936     if (!baa)
937         return (BOXA *)ERROR_PTR("baa not defined", procName, NULL);
938     n = boxaaGetCount(baa);
939     if (index < 0 || index >= n)
940         return (BOXA *)ERROR_PTR("index not valid", procName, NULL);
941     if (accessflag != L_COPY && accessflag != L_CLONE)
942         return (BOXA *)ERROR_PTR("invalid accessflag", procName, NULL);
943 
944     return boxaCopy(baa->boxa[index], accessflag);
945 }
946 
947 
948 /*!
949  *  boxaaReplaceBoxa()
950  *
951  *      Input:  boxaa
952  *              index  (to the index-th boxa)
953  *              boxa (insert and replace any existing one)
954  *      Return: 0 if OK, 1 on error
955  *
956  *  Notes:
957  *      (1) Any existing boxa is destroyed, and the input one
958  *          is inserted in its place.
959  *      (2) If the index is invalid, return 1 (error)
960  */
961 l_int32
boxaaReplaceBoxa(BOXAA * baa,l_int32 index,BOXA * boxa)962 boxaaReplaceBoxa(BOXAA   *baa,
963                  l_int32  index,
964                  BOXA    *boxa)
965 {
966 l_int32  n;
967 
968     PROCNAME("boxaaReplaceBoxa");
969 
970     if (!baa)
971         return ERROR_INT("baa not defined", procName, 1);
972     if (!boxa)
973         return ERROR_INT("boxa not defined", procName, 1);
974     n = boxaaGetCount(baa);
975     if (index < 0 || index >= n)
976         return ERROR_INT("index not valid", procName, 1);
977 
978     boxaDestroy(&baa->boxa[index]);
979     baa->boxa[index] = boxa;
980     return 0;
981 }
982 
983 
984 /*!
985  *  boxaaInsertBoxa()
986  *
987  *      Input:  boxaa
988  *              index (location in boxaa to insert new boxa)
989  *              boxa (new boxa to be inserted)
990  *      Return: 0 if OK, 1 on error
991  *
992  *  Notes:
993  *      (1) This shifts boxa[i] --> boxa[i + 1] for all i >= index,
994  *          and then inserts boxa as boxa[index].
995  *      (2) To insert at the beginning of the array, set index = 0.
996  *      (3) To append to the array, it's easier to use boxaaAddBoxa().
997  *      (4) This should not be used repeatedly to insert into large arrays,
998  *          because the function is O(n).
999  */
1000 l_int32
boxaaInsertBoxa(BOXAA * baa,l_int32 index,BOXA * boxa)1001 boxaaInsertBoxa(BOXAA   *baa,
1002                 l_int32  index,
1003                 BOXA    *boxa)
1004 {
1005 l_int32  i, n;
1006 BOXA   **array;
1007 
1008     PROCNAME("boxaaInsertBoxa");
1009 
1010     if (!baa)
1011         return ERROR_INT("baa not defined", procName, 1);
1012     n = boxaaGetCount(baa);
1013     if (index < 0 || index > n)
1014         return ERROR_INT("index not in {0...n}", procName, 1);
1015     if (!boxa)
1016         return ERROR_INT("boxa not defined", procName, 1);
1017 
1018     if (n >= baa->nalloc)
1019         boxaaExtendArray(baa);
1020     array = baa->boxa;
1021     baa->n++;
1022     for (i = n; i > index; i--)
1023         array[i] = array[i - 1];
1024     array[index] = boxa;
1025 
1026     return 0;
1027 }
1028 
1029 
1030 /*!
1031  *  boxaaRemoveBoxa()
1032  *
1033  *      Input:  boxaa
1034  *              index  (of the boxa to be removed)
1035  *      Return: 0 if OK, 1 on error
1036  *
1037  *  Notes:
1038  *      (1) This removes boxa[index] and then shifts
1039  *          boxa[i] --> boxa[i - 1] for all i > index.
1040  *      (2) The removed boxaa is destroyed.
1041  *      (2) This should not be used repeatedly on large arrays,
1042  *          because the function is O(n).
1043  */
1044 l_int32
boxaaRemoveBoxa(BOXAA * baa,l_int32 index)1045 boxaaRemoveBoxa(BOXAA   *baa,
1046                 l_int32  index)
1047 {
1048 l_int32  i, n;
1049 BOXA   **array;
1050 
1051     PROCNAME("boxaaRemoveBox");
1052 
1053     if (!baa)
1054         return ERROR_INT("baa not defined", procName, 1);
1055     n = boxaaGetCount(baa);
1056     if (index < 0 || index >= n)
1057         return ERROR_INT("index not valid", procName, 1);
1058 
1059     array = baa->boxa;
1060     boxaDestroy(&array[index]);
1061     for (i = index + 1; i < n; i++)
1062         array[i - 1] = array[i];
1063     array[n - 1] = NULL;
1064     baa->n--;
1065 
1066     return 0;
1067 }
1068 
1069 
1070 /*!
1071  *  boxaaAddBox()
1072  *
1073  *      Input:  boxaa
1074  *              index (of boxa with boxaa)
1075  *              box (to be added)
1076  *              accessflag (L_INSERT, L_COPY or L_CLONE)
1077  *      Return: 0 if OK, 1 on error
1078  *
1079  *  Notes:
1080  *      (1) Adds to an existing boxa only.
1081  */
1082 l_int32
boxaaAddBox(BOXAA * baa,l_int32 index,BOX * box,l_int32 accessflag)1083 boxaaAddBox(BOXAA   *baa,
1084             l_int32  index,
1085             BOX     *box,
1086             l_int32  accessflag)
1087 {
1088 l_int32  n;
1089 BOXA    *boxa;
1090     PROCNAME("boxaaAddBox");
1091 
1092     if (!baa)
1093         return ERROR_INT("baa not defined", procName, 1);
1094     n = boxaaGetCount(baa);
1095     if (index < 0 || index >= n)
1096         return ERROR_INT("index not valid", procName, 1);
1097     if (accessflag != L_INSERT && accessflag != L_COPY && accessflag != L_CLONE)
1098         return ERROR_INT("invalid accessflag", procName, 1);
1099 
1100     boxa = boxaaGetBoxa(baa, index, L_CLONE);
1101     boxaAddBox(boxa, box, accessflag);
1102     boxaDestroy(&boxa);
1103     return 0;
1104 }
1105 
1106 
1107 /*---------------------------------------------------------------------*
1108  *                        Boxaa serialized I/O                         *
1109  *---------------------------------------------------------------------*/
1110 /*!
1111  *  boxaaRead()
1112  *
1113  *      Input:  filename
1114  *      Return: boxaa, or null on error
1115  */
1116 BOXAA *
boxaaRead(const char * filename)1117 boxaaRead(const char  *filename)
1118 {
1119 FILE   *fp;
1120 BOXAA  *baa;
1121 
1122     PROCNAME("boxaaRead");
1123 
1124     if (!filename)
1125         return (BOXAA *)ERROR_PTR("filename not defined", procName, NULL);
1126     if ((fp = fopenReadStream(filename)) == NULL)
1127         return (BOXAA *)ERROR_PTR("stream not opened", procName, NULL);
1128 
1129     if ((baa = boxaaReadStream(fp)) == NULL) {
1130         fclose(fp);
1131         return (BOXAA *)ERROR_PTR("boxaa not read", procName, NULL);
1132     }
1133 
1134     fclose(fp);
1135     return baa;
1136 }
1137 
1138 
1139 /*!
1140  *  boxaaReadStream()
1141  *
1142  *      Input:  stream
1143  *      Return: boxaa, or null on error
1144  */
1145 BOXAA *
boxaaReadStream(FILE * fp)1146 boxaaReadStream(FILE  *fp)
1147 {
1148 l_int32  n, i, x, y, w, h, version;
1149 l_int32  ignore;
1150 BOXA    *boxa;
1151 BOXAA   *baa;
1152 
1153     PROCNAME("boxaaReadStream");
1154 
1155     if (!fp)
1156         return (BOXAA *)ERROR_PTR("stream not defined", procName, NULL);
1157 
1158     if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1)
1159         return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
1160     if (version != BOXAA_VERSION_NUMBER)
1161         return (BOXAA *)ERROR_PTR("invalid boxa version", procName, NULL);
1162     if (fscanf(fp, "Number of boxa = %d\n", &n) != 1)
1163         return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
1164 
1165     if ((baa = boxaaCreate(n)) == NULL)
1166         return (BOXAA *)ERROR_PTR("boxaa not made", procName, NULL);
1167 
1168     for (i = 0; i < n; i++) {
1169         if (fscanf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
1170                    &ignore, &x, &y, &w, &h) != 5)
1171             return (BOXAA *)ERROR_PTR("boxa descr not valid", procName, NULL);
1172         if ((boxa = boxaReadStream(fp)) == NULL)
1173             return (BOXAA *)ERROR_PTR("boxa not made", procName, NULL);
1174         boxaaAddBoxa(baa, boxa, L_INSERT);
1175     }
1176 
1177     return baa;
1178 }
1179 
1180 /*!
1181  *  boxaaWrite()
1182  *
1183  *      Input:  filename
1184  *              boxaa
1185  *      Return: 0 if OK, 1 on error
1186  */
1187 l_int32
boxaaWrite(const char * filename,BOXAA * baa)1188 boxaaWrite(const char  *filename,
1189            BOXAA       *baa)
1190 {
1191 FILE  *fp;
1192 
1193     PROCNAME("boxaaWrite");
1194 
1195     if (!filename)
1196         return ERROR_INT("filename not defined", procName, 1);
1197     if (!baa)
1198         return ERROR_INT("baa not defined", procName, 1);
1199 
1200     if ((fp = fopen(filename, "w")) == NULL)
1201         return ERROR_INT("stream not opened", procName, 1);
1202     if (boxaaWriteStream(fp, baa))
1203         return ERROR_INT("baa not written to stream", procName, 1);
1204     fclose(fp);
1205 
1206     return 0;
1207 }
1208 
1209 
1210 /*!
1211  *  boxaaWriteStream()
1212  *
1213  *      Input: stream
1214  *             boxaa
1215  *      Return: 0 if OK, 1 on error
1216  */
1217 l_int32
boxaaWriteStream(FILE * fp,BOXAA * baa)1218 boxaaWriteStream(FILE   *fp,
1219                  BOXAA  *baa)
1220 {
1221 l_int32  n, i, x, y, w, h;
1222 BOX     *box;
1223 BOXA    *boxa;
1224 
1225     PROCNAME("boxaaWriteStream");
1226 
1227     if (!fp)
1228         return ERROR_INT("stream not defined", procName, 1);
1229     if (!baa)
1230         return ERROR_INT("baa not defined", procName, 1);
1231 
1232     n = boxaaGetCount(baa);
1233     fprintf(fp, "\nBoxaa Version %d\n", BOXAA_VERSION_NUMBER);
1234     fprintf(fp, "Number of boxa = %d\n", n);
1235 
1236     for (i = 0; i < n; i++) {
1237         if ((boxa = boxaaGetBoxa(baa, i, L_CLONE)) == NULL)
1238             return ERROR_INT("boxa not found", procName, 1);
1239         boxaGetExtent(boxa, NULL, NULL, &box);
1240         boxGetGeometry(box, &x, &y, &w, &h);
1241         fprintf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
1242                 i, x, y, w, h);
1243         boxaWriteStream(fp, boxa);
1244         boxDestroy(&box);
1245         boxaDestroy(&boxa);
1246     }
1247     return 0;
1248 }
1249 
1250 
1251 /*---------------------------------------------------------------------*
1252  *                         Boxa serialized I/O                         *
1253  *---------------------------------------------------------------------*/
1254 /*!
1255  *  boxaRead()
1256  *
1257  *      Input:  filename
1258  *      Return: boxa, or null on error
1259  */
1260 BOXA *
boxaRead(const char * filename)1261 boxaRead(const char  *filename)
1262 {
1263 FILE  *fp;
1264 BOXA  *boxa;
1265 
1266     PROCNAME("boxaRead");
1267 
1268     if (!filename)
1269         return (BOXA *)ERROR_PTR("filename not defined", procName, NULL);
1270     if ((fp = fopenReadStream(filename)) == NULL)
1271         return (BOXA *)ERROR_PTR("stream not opened", procName, NULL);
1272 
1273     if ((boxa = boxaReadStream(fp)) == NULL) {
1274         fclose(fp);
1275         return (BOXA *)ERROR_PTR("boxa not read", procName, NULL);
1276     }
1277 
1278     fclose(fp);
1279     return boxa;
1280 }
1281 
1282 
1283 /*!
1284  *  boxaReadStream()
1285  *
1286  *      Input:  stream
1287  *      Return: boxa, or null on error
1288  */
1289 BOXA *
boxaReadStream(FILE * fp)1290 boxaReadStream(FILE  *fp)
1291 {
1292 l_int32  n, i, x, y, w, h, version;
1293 l_int32  ignore;
1294 BOX     *box;
1295 BOXA    *boxa;
1296 
1297     PROCNAME("boxaReadStream");
1298 
1299     if (!fp)
1300         return (BOXA *)ERROR_PTR("stream not defined", procName, NULL);
1301 
1302     if (fscanf(fp, "\nBoxa Version %d\n", &version) != 1)
1303         return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL);
1304     if (version != BOXA_VERSION_NUMBER)
1305         return (BOXA *)ERROR_PTR("invalid boxa version", procName, NULL);
1306     if (fscanf(fp, "Number of boxes = %d\n", &n) != 1)
1307         return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL);
1308 
1309     if ((boxa = boxaCreate(n)) == NULL)
1310         return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
1311 
1312     for (i = 0; i < n; i++) {
1313         if (fscanf(fp, "  Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
1314                 &ignore, &x, &y, &w, &h) != 5)
1315             return (BOXA *)ERROR_PTR("box descr not valid", procName, NULL);
1316         if ((box = boxCreate(x, y, w, h)) == NULL)
1317             return (BOXA *)ERROR_PTR("box not made", procName, NULL);
1318         boxaAddBox(boxa, box, L_INSERT);
1319     }
1320 
1321     return boxa;
1322 }
1323 
1324 
1325 /*!
1326  *  boxaWrite()
1327  *
1328  *      Input:  filename
1329  *              boxa
1330  *      Return: 0 if OK, 1 on error
1331  */
1332 l_int32
boxaWrite(const char * filename,BOXA * boxa)1333 boxaWrite(const char  *filename,
1334           BOXA        *boxa)
1335 {
1336 FILE  *fp;
1337 
1338     PROCNAME("boxaWrite");
1339 
1340     if (!filename)
1341         return ERROR_INT("filename not defined", procName, 1);
1342     if (!boxa)
1343         return ERROR_INT("boxa not defined", procName, 1);
1344 
1345     if ((fp = fopen(filename, "w")) == NULL)
1346         return ERROR_INT("stream not opened", procName, 1);
1347     if (boxaWriteStream(fp, boxa))
1348         return ERROR_INT("boxa not written to stream", procName, 1);
1349     fclose(fp);
1350 
1351     return 0;
1352 }
1353 
1354 
1355 /*!
1356  *  boxaWriteStream()
1357  *
1358  *      Input: stream
1359  *             boxa
1360  *      Return: 0 if OK, 1 on error
1361  */
1362 l_int32
boxaWriteStream(FILE * fp,BOXA * boxa)1363 boxaWriteStream(FILE  *fp,
1364                 BOXA  *boxa)
1365 {
1366 l_int32  n, i;
1367 BOX     *box;
1368 
1369     PROCNAME("boxaWriteStream");
1370 
1371     if (!fp)
1372         return ERROR_INT("stream not defined", procName, 1);
1373     if (!boxa)
1374         return ERROR_INT("boxa not defined", procName, 1);
1375 
1376     n = boxaGetCount(boxa);
1377     fprintf(fp, "\nBoxa Version %d\n", BOXA_VERSION_NUMBER);
1378     fprintf(fp, "Number of boxes = %d\n", n);
1379     for (i = 0; i < n; i++) {
1380         if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL)
1381             return ERROR_INT("box not found", procName, 1);
1382         fprintf(fp, "  Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
1383                 i, box->x, box->y, box->w, box->h);
1384         boxDestroy(&box);
1385     }
1386     return 0;
1387 }
1388 
1389 
1390 /*---------------------------------------------------------------------*
1391  *                            Debug printing                           *
1392  *---------------------------------------------------------------------*/
1393 /*!
1394  *  boxPrintStreamInfo()
1395  *
1396  *      Input:  stream
1397  *              box
1398  *      Return: 0 if OK, 1 on error
1399  *
1400  *  Notes:
1401  *      (1) This outputs information about the box, for debugging.
1402  *      (2) Use serialization functions to write to file if you want
1403  *          to read the data back.
1404  */
1405 l_int32
boxPrintStreamInfo(FILE * fp,BOX * box)1406 boxPrintStreamInfo(FILE  *fp,
1407                    BOX   *box)
1408 {
1409     PROCNAME("boxPrintStreamInfo");
1410 
1411     if (!fp)
1412         return ERROR_INT("stream not defined", procName, 1);
1413     if (!box)
1414         return ERROR_INT("box not defined", procName, 1);
1415 
1416     fprintf(fp, " Box x (pixels) =           %d\n", box->x);
1417     fprintf(fp, " Box y (pixels) =           %d\n", box->y);
1418     fprintf(fp, " Box width (pixels) =       %d\n", box->w);
1419     fprintf(fp, " Box height (pixels) =      %d\n", box->h);
1420 
1421     return 0;
1422 }
1423 
1424 
1425 
1426 /*---------------------------------------------------------------------*
1427  *    Version for reading v.2 boxaa; kept for backward compatibility   *
1428  *---------------------------------------------------------------------*/
1429 /*!
1430  *  boxaaReadVersion2()
1431  *
1432  *      Input:  filename
1433  *      Return: boxaa, or null on error
1434  *
1435  *  Notes:
1436  *      (1) These old functions only work on version 2 boxaa.
1437  *          They will go to an archive directory sometime after Sept 2009.
1438  *      (2) The current format uses BOXAA_VERSION_NUMBER == 3)
1439  */
1440 BOXAA *
boxaaReadVersion2(const char * filename)1441 boxaaReadVersion2(const char  *filename)
1442 {
1443 FILE   *fp;
1444 BOXAA  *baa;
1445 
1446     PROCNAME("boxaaReadVersion2");
1447 
1448     if (!filename)
1449         return (BOXAA *)ERROR_PTR("filename not defined", procName, NULL);
1450     if ((fp = fopenReadStream(filename)) == NULL)
1451         return (BOXAA *)ERROR_PTR("stream not opened", procName, NULL);
1452 
1453     if ((baa = boxaaReadStreamVersion2(fp)) == NULL) {
1454         fclose(fp);
1455         return (BOXAA *)ERROR_PTR("boxaa not read", procName, NULL);
1456     }
1457 
1458     fclose(fp);
1459     return baa;
1460 }
1461 
1462 
1463 /*!
1464  *  boxaaReadStreamVersion2()
1465  *
1466  *      Input:  stream
1467  *      Return: boxaa, or null on error
1468  *
1469  */
1470 BOXAA *
boxaaReadStreamVersion2(FILE * fp)1471 boxaaReadStreamVersion2(FILE  *fp)
1472 {
1473 l_int32  n, i, x, y, w, h, version;
1474 l_int32  ignore;
1475 BOXA    *boxa;
1476 BOXAA   *baa;
1477 
1478     PROCNAME("boxaaReadStreamVersion2");
1479 
1480     if (!fp)
1481         return (BOXAA *)ERROR_PTR("stream not defined", procName, NULL);
1482 
1483     if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1)
1484         return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
1485     if (version != 2) {
1486         fprintf(stderr, "This is version %d\n", version);
1487         return (BOXAA *)ERROR_PTR("Not old version 2", procName, NULL);
1488     }
1489     if (fscanf(fp, "Number of boxa = %d\n", &n) != 1)
1490         return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
1491 
1492     if ((baa = boxaaCreate(n)) == NULL)
1493         return (BOXAA *)ERROR_PTR("boxaa not made", procName, NULL);
1494 
1495     for (i = 0; i < n; i++) {
1496         if (fscanf(fp, " Boxa[%d]: x = %d, y = %d, w = %d, h = %d\n",
1497                 &ignore, &x, &y, &w, &h) != 5)
1498             return (BOXAA *)ERROR_PTR("boxa descr not valid", procName, NULL);
1499         if ((boxa = boxaReadStream(fp)) == NULL)
1500             return (BOXAA *)ERROR_PTR("boxa not made", procName, NULL);
1501         boxaaAddBoxa(baa, boxa, L_INSERT);
1502     }
1503 
1504     return baa;
1505 }
1506 
1507 
1508