Leptonica 1.68
C Image Processing Library

boxbasic.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  *   boxbasic.c
00018  *
00019  *   Basic 'class' functions for box, boxa and boxaa,
00020  *   including accessors and serialization.
00021  *
00022  *      Box creation, copy, clone, destruction
00023  *           BOX      *boxCreate()
00024  *           BOX      *boxCreateValid()
00025  *           BOX      *boxCopy()
00026  *           BOX      *boxClone()
00027  *           void      boxDestroy()
00028  *
00029  *      Box accessors
00030  *           l_int32   boxGetGeometry()
00031  *           l_int32   boxSetGeometry()
00032  *           l_int32   boxGetRefcount()
00033  *           l_int32   boxChangeRefcount()
00034  *
00035  *      Boxa creation, copy, destruction
00036  *           BOXA     *boxaCreate()
00037  *           BOXA     *boxaCopy()
00038  *           void      boxaDestroy()
00039  *
00040  *      Boxa array extension
00041  *           l_int32   boxaAddBox()
00042  *           l_int32   boxaExtendArray()
00043  *           l_int32   boxaExtendArrayToSize()
00044  *
00045  *      Boxa accessors
00046  *           l_int32   boxaGetCount()
00047  *           l_int32   boxaGetValidCount()
00048  *           BOX      *boxaGetBox()
00049  *           BOX      *boxaGetValidBox()
00050  *           l_int32   boxaGetBoxGeometry()
00051  *
00052  *      Boxa array modifiers
00053  *           l_int32   boxaReplaceBox()
00054  *           l_int32   boxaInsertBox()
00055  *           l_int32   boxaRemoveBox()
00056  *           l_int32   boxaInitFull()
00057  *           l_int32   boxaClear()
00058  *
00059  *      Boxaa creation, copy, destruction
00060  *           BOXAA    *boxaaCreate()
00061  *           BOXAA    *boxaaCopy()
00062  *           void      boxaaDestroy()
00063  *
00064  *      Boxaa array extension
00065  *           l_int32   boxaaAddBoxa()
00066  *           l_int32   boxaaExtendArray()
00067  *
00068  *      Boxaa accessors
00069  *           l_int32   boxaaGetCount()
00070  *           l_int32   boxaaGetBoxCount()
00071  *           BOXA     *boxaaGetBoxa()
00072  *
00073  *      Boxa array modifiers
00074  *           l_int32   boxaaReplaceBoxa()
00075  *           l_int32   boxaaInsertBoxa()
00076  *           l_int32   boxaaRemoveBoxa()
00077  *           l_int32   boxaaAddBox()
00078  *
00079  *      Boxaa serialized I/O
00080  *           BOXAA    *boxaaRead()
00081  *           BOXAA    *boxaaReadStream()
00082  *           l_int32   boxaaWrite()
00083  *           l_int32   boxaaWriteStream()
00084  *
00085  *      Boxa serialized I/O
00086  *           BOXA     *boxaRead()
00087  *           BOXA     *boxaReadStream()
00088  *           l_int32   boxaWrite()
00089  *           l_int32   boxaWriteStream()
00090  *
00091  *      Box print (for debug)
00092  *           l_int32   boxPrintStreamInfo()
00093  *
00094  *   Most functions use only valid boxes, which are boxes that have both
00095  *   width and height > 0.  However, a few functions, such as
00096  *   boxaGetMedian() do not assume that all boxes are valid.  For any
00097  *   function that can use a boxa with invalid boxes, it is convenient 
00098  *   to use these accessors:
00099  *       boxaGetValidCount()   :  count of valid boxes
00100  *       boxaGetValidBox()     :  returns NULL for invalid boxes
00101  */
00102 
00103 #include <string.h>
00104 #include "allheaders.h"
00105 
00106 static const l_int32  INITIAL_PTR_ARRAYSIZE = 20;   /* n'import quoi */
00107 
00108 
00109 /*---------------------------------------------------------------------*
00110  *                  Box creation, destruction and copy                 *
00111  *---------------------------------------------------------------------*/
00112 /*!
00113  *  boxCreate()
00114  *
00115  *      Input:  x, y, w, h
00116  *      Return: box, or null on error
00117  *
00118  *  Notes:
00119  *      (1) This clips the box to the +quad.  If no part of the
00120  *          box is in the +quad, this returns NULL.
00121  *      (2) We allow you to make a box with w = 0 and/or h = 0.
00122  *          This does not represent a valid region, but it is useful
00123  *          as a placeholder in a boxa for which the index of the
00124  *          box in the boxa is important.  This is an atypical
00125  *          situation; usually you want to put only valid boxes with
00126  *          nonzero width and height in a boxa.  If you have a boxa
00127  *          with invalid boxes, the accessor boxaGetValidBox()
00128  *          will return NULL on each invalid box.
00129  *      (3) If you want to create only valid boxes, use boxCreateValid(),
00130  *          which returns NULL if either w or h is 0.
00131  */
00132 BOX *
00133 boxCreate(l_int32  x,
00134           l_int32  y,
00135           l_int32  w,
00136           l_int32  h)
00137 {
00138 BOX  *box;
00139 
00140     PROCNAME("boxCreate");
00141 
00142     if (w < 0 || h < 0)
00143         return (BOX *)ERROR_PTR("w and h not both >= 0", procName, NULL);
00144     if (x < 0) {  /* take part in +quad */
00145         w = w + x;
00146         x = 0;
00147         if (w <= 0)
00148             return (BOX *)ERROR_PTR("x < 0 and box off +quad", procName, NULL);
00149     }
00150     if (y < 0) {  /* take part in +quad */
00151         h = h + y;
00152         y = 0;
00153         if (h <= 0)
00154             return (BOX *)ERROR_PTR("y < 0 and box off +quad", procName, NULL);
00155     }
00156 
00157     if ((box = (BOX *)CALLOC(1, sizeof(BOX))) == NULL)
00158         return (BOX *)ERROR_PTR("box not made", procName, NULL);
00159     boxSetGeometry(box, x, y, w, h);
00160     box->refcount = 1;
00161 
00162     return box;
00163 }
00164 
00165 
00166 /*!
00167  *  boxCreateValid()
00168  *
00169  *      Input:  x, y, w, h
00170  *      Return: box, or null on error
00171  *
00172  *  Notes:
00173  *      (1) This returns NULL if either w = 0 or h = 0.
00174  */
00175 BOX *
00176 boxCreateValid(l_int32  x,
00177                l_int32  y,
00178                l_int32  w,
00179                l_int32  h)
00180 {
00181     PROCNAME("boxCreateValid");
00182 
00183     if (w <= 0 || h <= 0)
00184         return (BOX *)ERROR_PTR("w and h not both > 0", procName, NULL);
00185     return boxCreate(x, y, w, h);
00186 }
00187 
00188 
00189 /*!
00190  *  boxCopy()
00191  *
00192  *      Input:  box
00193  *      Return: copy of box, or null on error
00194  */
00195 BOX *
00196 boxCopy(BOX  *box)
00197 {
00198 BOX  *boxc;
00199 
00200     PROCNAME("boxCopy");
00201 
00202     if (!box)
00203         return (BOX *)ERROR_PTR("box not defined", procName, NULL);
00204 
00205     boxc = boxCreate(box->x, box->y, box->w, box->h);
00206 
00207     return boxc;
00208 }
00209 
00210 
00211 /*!
00212  *  boxClone()
00213  *
00214  *      Input:  box
00215  *      Return: ptr to same box, or null on error
00216  */
00217 BOX *
00218 boxClone(BOX  *box)
00219 {
00220 
00221     PROCNAME("boxClone");
00222 
00223     if (!box)
00224         return (BOX *)ERROR_PTR("box not defined", procName, NULL);
00225 
00226     boxChangeRefcount(box, 1);
00227     return box;
00228 }
00229 
00230 
00231 /*!
00232  *  boxDestroy()
00233  *
00234  *      Input:  &box (<will be set to null before returning>)
00235  *      Return: void
00236  *
00237  *  Notes:
00238  *      (1) Decrements the ref count and, if 0, destroys the box.
00239  *      (2) Always nulls the input ptr.
00240  */
00241 void
00242 boxDestroy(BOX  **pbox)
00243 {
00244 BOX  *box;
00245 
00246     PROCNAME("boxDestroy");
00247 
00248     if (pbox == NULL) {
00249         L_WARNING("ptr address is null!", procName);
00250         return;
00251     }
00252     if ((box = *pbox) == NULL)
00253         return;
00254 
00255     boxChangeRefcount(box, -1);
00256     if (boxGetRefcount(box) <= 0)
00257         FREE(box);
00258     *pbox = NULL;
00259     return;
00260 }
00261 
00262 
00263 /*---------------------------------------------------------------------*
00264  *                              Box accessors                          *
00265  *---------------------------------------------------------------------*/
00266 /*!
00267  *  boxGetGeometry()
00268  *
00269  *      Input:  box
00270  *              &x, &y, &w, &h (<optional return>; each can be null)
00271  *      Return: 0 if OK, 1 on error
00272  */
00273 l_int32
00274 boxGetGeometry(BOX      *box,
00275                l_int32  *px,
00276                l_int32  *py,
00277                l_int32  *pw,
00278                l_int32  *ph)
00279 {
00280     PROCNAME("boxGetGeometry");
00281 
00282     if (px) *px = 0;
00283     if (py) *py = 0;
00284     if (pw) *pw = 0;
00285     if (ph) *ph = 0;
00286     if (!box)
00287         return ERROR_INT("box not defined", procName, 1);
00288     if (px) *px = box->x;
00289     if (py) *py = box->y;
00290     if (pw) *pw = box->w;
00291     if (ph) *ph = box->h;
00292     return 0;
00293 }
00294 
00295 
00296 /*!
00297  *  boxSetGeometry()
00298  *
00299  *      Input:  box
00300  *              x, y, w, h (use -1 to leave unchanged)
00301  *      Return: 0 if OK, 1 on error
00302  */
00303 l_int32
00304 boxSetGeometry(BOX     *box,
00305                l_int32  x,
00306                l_int32  y,
00307                l_int32  w,
00308                l_int32  h)
00309 {
00310     PROCNAME("boxSetGeometry");
00311 
00312     if (!box)
00313         return ERROR_INT("box not defined", procName, 1);
00314     if (x != -1) box->x = x;
00315     if (y != -1) box->y = y;
00316     if (w != -1) box->w = w;
00317     if (h != -1) box->h = h;
00318     return 0;
00319 }
00320 
00321 
00322 l_int32
00323 boxGetRefcount(BOX  *box)
00324 {
00325     PROCNAME("boxGetRefcount");
00326 
00327     if (!box)
00328         return ERROR_INT("box not defined", procName, UNDEF);
00329 
00330     return box->refcount;
00331 }
00332 
00333 
00334 l_int32
00335 boxChangeRefcount(BOX     *box,
00336                   l_int32  delta)
00337 {
00338     PROCNAME("boxChangeRefcount");
00339 
00340     if (!box)
00341         return ERROR_INT("box not defined", procName, 1);
00342 
00343     box->refcount += delta;
00344     return 0;
00345 }
00346 
00347 
00348 /*---------------------------------------------------------------------*
00349  *             Boxa creation, destruction, copy, extension             *
00350  *---------------------------------------------------------------------*/
00351 /*!
00352  *  boxaCreate()
00353  *
00354  *      Input:  n  (initial number of ptrs)
00355  *      Return: boxa, or null on error
00356  */
00357 BOXA *
00358 boxaCreate(l_int32  n)
00359 {
00360 BOXA  *boxa;
00361 
00362     PROCNAME("boxaCreate");
00363 
00364     if (n <= 0)
00365         n = INITIAL_PTR_ARRAYSIZE;
00366 
00367     if ((boxa = (BOXA *)CALLOC(1, sizeof(BOXA))) == NULL)
00368         return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
00369     boxa->n = 0;
00370     boxa->nalloc = n;
00371     boxa->refcount = 1;
00372 
00373     if ((boxa->box = (BOX **)CALLOC(n, sizeof(BOX *))) == NULL)
00374         return (BOXA *)ERROR_PTR("boxa ptrs not made", procName, NULL);
00375 
00376     return boxa;
00377 }
00378 
00379 
00380 /*!
00381  *  boxaCopy()
00382  *
00383  *      Input:  boxa
00384  *              copyflag (L_COPY, L_CLONE, L_COPY_CLONE)
00385  *      Return: new boxa, or null on error
00386  *
00387  *  Notes:
00388  *      (1) See pix.h for description of the copyflag.
00389  *      (2) The copy-clone makes a new boxa that holds clones of each box.
00390  */
00391 BOXA *
00392 boxaCopy(BOXA    *boxa,
00393          l_int32  copyflag)
00394 {
00395 l_int32  i;
00396 BOX     *boxc;
00397 BOXA    *boxac;
00398 
00399     PROCNAME("boxaCopy");
00400 
00401     if (!boxa)
00402         return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
00403 
00404     if (copyflag == L_CLONE) {
00405         boxa->refcount++;
00406         return boxa;
00407     }
00408 
00409     if (copyflag != L_COPY && copyflag != L_COPY_CLONE)
00410         return (BOXA *)ERROR_PTR("invalid copyflag", procName, NULL);
00411 
00412     if ((boxac = boxaCreate(boxa->nalloc)) == NULL)
00413         return (BOXA *)ERROR_PTR("boxac not made", procName, NULL);
00414     for (i = 0; i < boxa->n; i++) {
00415         if (copyflag == L_COPY)
00416             boxc = boxaGetBox(boxa, i, L_COPY);
00417         else   /* copy-clone */
00418             boxc = boxaGetBox(boxa, i, L_CLONE);
00419         boxaAddBox(boxac, boxc, L_INSERT);
00420     }
00421     return boxac;
00422 }
00423 
00424 
00425 /*!
00426  *  boxaDestroy()
00427  *
00428  *      Input:  &boxa (<will be set to null before returning>)
00429  *      Return: void
00430  *
00431  *  Note:
00432  *      - Decrements the ref count and, if 0, destroys the boxa.
00433  *      - Always nulls the input ptr.
00434  */
00435 void
00436 boxaDestroy(BOXA  **pboxa)
00437 {
00438 l_int32  i;
00439 BOXA    *boxa;
00440 
00441     PROCNAME("boxaDestroy");
00442 
00443     if (pboxa == NULL) {
00444         L_WARNING("ptr address is null!", procName);
00445         return;
00446     }
00447 
00448     if ((boxa = *pboxa) == NULL)
00449         return;
00450 
00451         /* Decrement the ref count.  If it is 0, destroy the boxa. */
00452     boxa->refcount--;
00453     if (boxa->refcount <= 0) {
00454         for (i = 0; i < boxa->n; i++)
00455             boxDestroy(&boxa->box[i]);
00456         FREE(boxa->box);
00457         FREE(boxa);
00458     }
00459 
00460     *pboxa = NULL;
00461     return;
00462 }
00463 
00464 
00465 /*!
00466  *  boxaAddBox()
00467  *
00468  *      Input:  boxa
00469  *              box  (to be added)
00470  *              copyflag (L_INSERT, L_COPY, L_CLONE)
00471  *      Return: 0 if OK, 1 on error
00472  */
00473 l_int32
00474 boxaAddBox(BOXA    *boxa,
00475            BOX     *box,
00476            l_int32  copyflag)
00477 {
00478 l_int32  n;
00479 BOX     *boxc;
00480 
00481     PROCNAME("boxaAddBox");
00482 
00483     if (!boxa)
00484         return ERROR_INT("boxa not defined", procName, 1);
00485     if (!box)
00486         return ERROR_INT("box not defined", procName, 1);
00487 
00488     if (copyflag == L_INSERT)
00489         boxc = box;
00490     else if (copyflag == L_COPY)
00491         boxc = boxCopy(box);
00492     else if (copyflag == L_CLONE)
00493         boxc = boxClone(box);
00494     else
00495         return ERROR_INT("invalid copyflag", procName, 1);
00496     if (!boxc)
00497         return ERROR_INT("boxc not made", procName, 1);
00498 
00499     n = boxaGetCount(boxa);
00500     if (n >= boxa->nalloc)
00501         boxaExtendArray(boxa);
00502     boxa->box[n] = boxc;
00503     boxa->n++;
00504 
00505     return 0;
00506 }
00507 
00508 
00509 /*!
00510  *  boxaExtendArray()
00511  *
00512  *      Input:  boxa
00513  *      Return: 0 if OK; 1 on error
00514  *
00515  *  Notes:
00516  *      (1) Reallocs with doubled size of ptr array.
00517  */
00518 l_int32
00519 boxaExtendArray(BOXA  *boxa)
00520 {
00521     PROCNAME("boxaExtendArray");
00522 
00523     if (!boxa)
00524         return ERROR_INT("boxa not defined", procName, 1);
00525 
00526     return boxaExtendArrayToSize(boxa, 2 * boxa->nalloc);
00527 }
00528 
00529 
00530 /*!
00531  *  boxaExtendArrayToSize()
00532  *
00533  *      Input:  boxa
00534  *              size (new size of boxa array)
00535  *      Return: 0 if OK; 1 on error
00536  *
00537  *  Notes:
00538  *      (1) If necessary, reallocs new boxa ptr array to @size.
00539  */
00540 l_int32
00541 boxaExtendArrayToSize(BOXA    *boxa,
00542                       l_int32  size)
00543 {
00544     PROCNAME("boxaExtendArrayToSize");
00545 
00546     if (!boxa)
00547         return ERROR_INT("boxa not defined", procName, 1);
00548 
00549     if (size > boxa->nalloc) {
00550         if ((boxa->box = (BOX **)reallocNew((void **)&boxa->box,
00551                                             sizeof(BOX *) * boxa->nalloc,
00552                                             size * sizeof(BOX *))) == NULL)
00553             return ERROR_INT("new ptr array not returned", procName, 1);
00554         boxa->nalloc = size;
00555     }
00556     return 0;
00557 }
00558 
00559 
00560 /*---------------------------------------------------------------------*
00561  *                             Boxa accessors                          *
00562  *---------------------------------------------------------------------*/
00563 /*!
00564  *  boxaGetCount()
00565  *
00566  *      Input:  boxa
00567  *      Return: count (of all boxes); 0 if no boxes or on error
00568  */
00569 l_int32
00570 boxaGetCount(BOXA  *boxa)
00571 {
00572     PROCNAME("boxaGetCount");
00573 
00574     if (!boxa)
00575         return ERROR_INT("boxa not defined", procName, 0);
00576     return boxa->n;
00577 }
00578 
00579 
00580 /*!
00581  *  boxaGetValidCount()
00582  *
00583  *      Input:  boxa
00584  *      Return: count (of valid boxes); 0 if no valid boxes or on error
00585  */
00586 l_int32
00587 boxaGetValidCount(BOXA  *boxa)
00588 {
00589 l_int32  n, i, w, h, count;
00590 
00591     PROCNAME("boxaGetValidCount");
00592 
00593     if (!boxa)
00594         return ERROR_INT("boxa not defined", procName, 0);
00595 
00596     n = boxaGetCount(boxa);
00597     for (i = 0, count = 0; i < n; i++) {
00598         boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
00599         if (w > 0 && h > 0)
00600             count++;
00601     }
00602     return count;
00603 }
00604 
00605 
00606 /*!
00607  *  boxaGetBox()
00608  *
00609  *      Input:  boxa
00610  *              index  (to the index-th box)
00611  *              accessflag  (L_COPY or L_CLONE)
00612  *      Return: box, or null on error
00613  */
00614 BOX *
00615 boxaGetBox(BOXA    *boxa,
00616            l_int32  index,
00617            l_int32  accessflag)
00618 {
00619     PROCNAME("boxaGetBox");
00620 
00621     if (!boxa)
00622         return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
00623     if (index < 0 || index >= boxa->n)
00624         return (BOX *)ERROR_PTR("index not valid", procName, NULL);
00625 
00626     if (accessflag == L_COPY)
00627         return boxCopy(boxa->box[index]);
00628     else if (accessflag == L_CLONE)
00629         return boxClone(boxa->box[index]);
00630     else
00631         return (BOX *)ERROR_PTR("invalid accessflag", procName, NULL);
00632 }
00633 
00634 
00635 /*!
00636  *  boxaGetValidBox()
00637  *
00638  *      Input:  boxa
00639  *              index  (to the index-th box)
00640  *              accessflag  (L_COPY or L_CLONE)
00641  *      Return: box, or null if box is not valid or on error
00642  *
00643  *  Notes:
00644  *      (1) This returns NULL for an invalid box in a boxa.
00645  *          For a box to be valid, both the width and height must be > 0.
00646  *      (2) We allow invalid boxes, with w = 0 or h = 0, as placeholders
00647  *          in boxa for which the index of the box in the boxa is important.
00648  *          This is an atypical situation; usually you want to put only
00649  *          valid boxes in a boxa.
00650  */
00651 BOX *
00652 boxaGetValidBox(BOXA    *boxa,
00653                 l_int32  index,
00654                 l_int32  accessflag)
00655 {
00656 l_int32  w, h;
00657 BOX     *box;
00658 
00659     PROCNAME("boxaGetValidBox");
00660 
00661     if (!boxa)
00662         return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
00663 
00664     if ((box = boxaGetBox(boxa, index, accessflag)) == NULL)
00665         return (BOX *)ERROR_PTR("box not returned", procName, NULL);
00666     boxGetGeometry(box, NULL, NULL, &w, &h);
00667     if (w <= 0 || h <= 0)  /* not valid, but not necessarily an error */
00668         boxDestroy(&box);
00669     return box;
00670 }
00671 
00672 
00673 /*!
00674  *  boxaGetBoxGeometry()
00675  *
00676  *      Input:  boxa
00677  *              index  (to the index-th box)
00678  *              &x, &y, &w, &h (<optional return>; each can be null)
00679  *      Return: 0 if OK, 1 on error
00680  */
00681 l_int32
00682 boxaGetBoxGeometry(BOXA     *boxa,
00683                    l_int32   index,
00684                    l_int32  *px,
00685                    l_int32  *py,
00686                    l_int32  *pw,
00687                    l_int32  *ph)
00688 {
00689 BOX  *box;
00690 
00691     PROCNAME("boxaGetBoxGeometry");
00692 
00693     if (px) *px = 0;
00694     if (py) *py = 0;
00695     if (pw) *pw = 0;
00696     if (ph) *ph = 0;
00697     if (!boxa)
00698         return ERROR_INT("boxa not defined", procName, 1);
00699     if (index < 0 || index >= boxa->n)
00700         return ERROR_INT("index not valid", procName, 1);
00701 
00702     if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL)
00703         return ERROR_INT("box not found!", procName, 1);
00704     boxGetGeometry(box, px, py, pw, ph);
00705     boxDestroy(&box);
00706     return 0;
00707 }
00708 
00709 
00710 /*---------------------------------------------------------------------*
00711  *                        Boxa array modifiers                         *
00712  *---------------------------------------------------------------------*/
00713 /*!
00714  *  boxaReplaceBox()
00715  *
00716  *      Input:  boxa
00717  *              index  (to the index-th box)
00718  *              box (insert to replace existing one)
00719  *      Return: 0 if OK, 1 on error
00720  *
00721  *  Notes:
00722  *      (1) In-place replacement of one box.
00723  *      (2) The previous box at that location is destroyed.
00724  */
00725 l_int32
00726 boxaReplaceBox(BOXA    *boxa,
00727                l_int32  index,
00728                BOX     *box)
00729 {
00730     PROCNAME("boxaReplaceBox");
00731 
00732     if (!boxa)
00733         return ERROR_INT("boxa not defined", procName, 1);
00734     if (index < 0 || index >= boxa->n)
00735         return ERROR_INT("index not valid", procName, 1);
00736     if (!box)
00737         return ERROR_INT("box not defined", procName, 1);
00738 
00739     boxDestroy(&(boxa->box[index]));
00740     boxa->box[index] = box;
00741     return 0;
00742 }
00743 
00744 
00745 /*!
00746  *  boxaInsertBox()
00747  *
00748  *      Input:  boxa
00749  *              index (location in boxa to insert new value)
00750  *              box (new box to be inserted)
00751  *      Return: 0 if OK, 1 on error
00752  *
00753  *  Notes:
00754  *      (1) This shifts box[i] --> box[i + 1] for all i >= index,
00755  *          and then inserts box as box[index].
00756  *      (2) To insert at the beginning of the array, set index = 0.
00757  *      (3) To append to the array, it's easier to use boxaAddBox().
00758  *      (4) This should not be used repeatedly to insert into large arrays,
00759  *          because the function is O(n).
00760  */
00761 l_int32
00762 boxaInsertBox(BOXA    *boxa,
00763               l_int32  index,
00764               BOX     *box)
00765 {
00766 l_int32  i, n;
00767 BOX    **array;
00768 
00769     PROCNAME("boxaInsertBox");
00770 
00771     if (!boxa)
00772         return ERROR_INT("boxa not defined", procName, 1);
00773     n = boxaGetCount(boxa);
00774     if (index < 0 || index > n)
00775         return ERROR_INT("index not in {0...n}", procName, 1);
00776     if (!box)
00777         return ERROR_INT("box not defined", procName, 1);
00778 
00779     if (n >= boxa->nalloc)
00780         boxaExtendArray(boxa);
00781     array = boxa->box;
00782     boxa->n++;
00783     for (i = n; i > index; i--)
00784         array[i] = array[i - 1];
00785     array[index] = box;
00786 
00787     return 0;
00788 }
00789 
00790 
00791 /*!
00792  *  boxaRemoveBox()
00793  *
00794  *      Input:  boxa
00795  *              index (of box to be removed)
00796  *      Return: 0 if OK, 1 on error
00797  *
00798  *  Notes:
00799  *      (1) This removes box[index] and then shifts
00800  *          box[i] --> box[i - 1] for all i > index.
00801  *      (2) It should not be used repeatedly to remove boxes from
00802  *          large arrays, because the function is O(n).
00803  */
00804 l_int32
00805 boxaRemoveBox(BOXA    *boxa,
00806               l_int32  index)
00807 {
00808 l_int32  i, n;
00809 BOX    **array;
00810 
00811     PROCNAME("boxaRemoveBox");
00812 
00813     if (!boxa)
00814         return ERROR_INT("boxa not defined", procName, 1);
00815     n = boxaGetCount(boxa);
00816     if (index < 0 || index >= n)
00817         return ERROR_INT("index not in {0...n - 1}", procName, 1);
00818 
00819     array = boxa->box;
00820     boxDestroy(&array[index]);
00821     for (i = index + 1; i < n; i++)
00822         array[i - 1] = array[i];
00823     array[n - 1] = NULL;
00824     boxa->n--;
00825 
00826     return 0;
00827 }
00828 
00829 
00830 /*!
00831  *  boxaInitFull()
00832  *
00833  *      Input:  boxa (typically empty)
00834  *              box (to be replicated into the entire ptr array)
00835  *      Return: 0 if OK, 1 on error
00836  *
00837  *  Notes:
00838  *      (1) This initializes a boxa by filling up the entire box ptr array
00839  *          with copies of @box.  Any existing boxes are destroyed.
00840  *          After this oepration, the number of boxes is equal to
00841  *          the number of allocated ptrs.
00842  *      (2) Note that we use boxaReplaceBox() instead of boxaInsertBox().
00843  *          They both have the same effect when inserting into a NULL ptr
00844  *          in the boxa ptr array:
00845  *      (3) Example usage.  This function is useful to prepare for a
00846  *          random insertion (or replacement) of boxes into a boxa.
00847  *          To randomly insert boxes into a boxa, up to some index "max":
00848  *             Boxa *boxa = boxaCreate(max);
00849  *             Box *box = boxCreate(...);
00850  *             boxaInitFull(boxa, box);
00851  *          If we have an existing boxa with a smaller ptr array, it can
00852  *          be reused:
00853  *             boxaExtendArrayToSize(boxa, max);
00854  *             Box *box = boxCreate(...);
00855  *             boxaInitFull(boxa, box);
00856  *          The initialization allows the boxa to always be properly
00857  *          filled, even if all the boxes are not later replaced.
00858  *          If you want to know which boxes have been replaced, you can
00859  *          initialize the array with invalid boxes that have 
00860  *          w = 0 and/or h = 0.  Then boxaGetValidBox() will return
00861  *          NULL for the invalid boxes.
00862  */
00863 l_int32
00864 boxaInitFull(BOXA  *boxa,
00865              BOX   *box)
00866 {
00867 l_int32  i, n;
00868 BOX     *boxt;
00869 
00870     PROCNAME("boxaInitFull");
00871 
00872     if (!boxa)
00873         return ERROR_INT("boxa not defined", procName, 1);
00874     if (!box)
00875         return ERROR_INT("box not defined", procName, 1);
00876 
00877     n = boxa->nalloc;
00878     boxa->n = n;
00879     for (i = 0; i < n; i++) {
00880         boxt = boxCopy(box);
00881         boxaReplaceBox(boxa, i, boxt);
00882     }
00883     return 0;
00884 }
00885 
00886 
00887 /*!
00888  *  boxaClear()
00889  *
00890  *      Input:  boxa
00891  *      Return: 0 if OK, 1 on error
00892  *
00893  *  Notes:
00894  *      (1) This destroys all boxes in the boxa, setting the ptrs
00895  *          to null.  The number of allocated boxes, n, is set to 0.
00896  */
00897 l_int32
00898 boxaClear(BOXA  *boxa)
00899 {
00900 l_int32  i, n;
00901 
00902     PROCNAME("boxaClear");
00903 
00904     if (!boxa)
00905         return ERROR_INT("boxa not defined", procName, 1);
00906 
00907     n = boxaGetCount(boxa);
00908     for (i = 0; i < n; i++)
00909         boxDestroy(&boxa->box[i]);
00910     boxa->n = 0;
00911     return 0;
00912 }
00913 
00914 
00915 /*--------------------------------------------------------------------------*
00916  *                     Boxaa creation, destruction                          *
00917  *--------------------------------------------------------------------------*/
00918 /*!
00919  *  boxaaCreate()
00920  *
00921  *      Input:  size of boxa ptr array to be alloc'd (0 for default)
00922  *      Return: baa, or null on error
00923  */
00924 BOXAA *
00925 boxaaCreate(l_int32  n)
00926 {
00927 BOXAA  *baa;
00928 
00929     PROCNAME("boxaaCreate");
00930 
00931     if (n <= 0)
00932         n = INITIAL_PTR_ARRAYSIZE;
00933 
00934     if ((baa = (BOXAA *)CALLOC(1, sizeof(BOXAA))) == NULL)
00935         return (BOXAA *)ERROR_PTR("baa not made", procName, NULL);
00936     if ((baa->boxa = (BOXA **)CALLOC(n, sizeof(BOXA *))) == NULL)
00937         return (BOXAA *)ERROR_PTR("boxa ptr array not made", procName, NULL);
00938 
00939     baa->nalloc = n;
00940     baa->n = 0;
00941 
00942     return baa;
00943 }
00944 
00945 
00946 /*!
00947  *  boxaaCopy()
00948  *
00949  *      Input:  baas (input boxaa to be copied)
00950  *              copyflag (L_COPY, L_CLONE)
00951  *      Return: baad (new boxaa, composed of copies or clones of the boxa
00952  *                    in baas), or null on error
00953  *
00954  *  Notes:
00955  *      (1) L_COPY makes a copy of each boxa in baas.
00956  *          L_CLONE makes a clone of each boxa in baas.
00957  */
00958 BOXAA *
00959 boxaaCopy(BOXAA   *baas,
00960           l_int32  copyflag)
00961 {
00962 l_int32  i, n;
00963 BOXA    *boxa;
00964 BOXAA   *baad;
00965 
00966     PROCNAME("boxaaCopy");
00967 
00968     if (!baas)
00969         return (BOXAA *)ERROR_PTR("baas not defined", procName, NULL);
00970     if (copyflag != L_COPY && copyflag != L_CLONE)
00971         return (BOXAA *)ERROR_PTR("invalid copyflag", procName, NULL);
00972 
00973     n = boxaaGetCount(baas);
00974     baad = boxaaCreate(n);
00975     for (i = 0; i < n; i++) {
00976         boxa = boxaaGetBoxa(baas, i, copyflag);
00977         boxaaAddBoxa(baad, boxa, L_INSERT);
00978     }
00979 
00980     return baad;
00981 }
00982 
00983 
00984 /*!
00985  *  boxaaDestroy()
00986  *
00987  *      Input:  &boxaa (<will be set to null before returning>)
00988  *      Return: void
00989  */
00990 void
00991 boxaaDestroy(BOXAA  **pbaa)
00992 {
00993 l_int32  i;
00994 BOXAA   *baa;
00995 
00996     PROCNAME("boxaaDestroy");
00997 
00998     if (pbaa == NULL) {
00999         L_WARNING("ptr address is NULL!", procName);
01000         return;
01001     }
01002 
01003     if ((baa = *pbaa) == NULL)
01004         return;
01005 
01006     for (i = 0; i < baa->n; i++)
01007         boxaDestroy(&baa->boxa[i]);
01008     FREE(baa->boxa);
01009     FREE(baa);
01010     *pbaa = NULL;
01011 
01012     return;
01013 }
01014 
01015 
01016 
01017 /*--------------------------------------------------------------------------*
01018  *                              Add Boxa to Boxaa                           *
01019  *--------------------------------------------------------------------------*/
01020 /*!
01021  *  boxaaAddBoxa()
01022  *
01023  *      Input:  boxaa
01024  *              boxa     (to be added)
01025  *              copyflag  (L_INSERT, L_COPY, L_CLONE)
01026  *      Return: 0 if OK, 1 on error
01027  */
01028 l_int32
01029 boxaaAddBoxa(BOXAA   *baa,
01030              BOXA    *ba,
01031              l_int32  copyflag)
01032 {
01033 l_int32  n;
01034 BOXA    *bac;
01035 
01036     PROCNAME("boxaaAddBoxa");
01037 
01038     if (!baa)
01039         return ERROR_INT("baa not defined", procName, 1);
01040     if (!ba)
01041         return ERROR_INT("ba not defined", procName, 1);
01042     if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
01043         return ERROR_INT("invalid copyflag", procName, 1);
01044 
01045     if (copyflag == L_INSERT)
01046         bac = ba;
01047     else
01048         bac = boxaCopy(ba, copyflag);
01049 
01050     n = boxaaGetCount(baa);
01051     if (n >= baa->nalloc)
01052         boxaaExtendArray(baa);
01053     baa->boxa[n] = bac;
01054     baa->n++;
01055     return 0;
01056 }
01057 
01058 
01059 /*!
01060  *  boxaaExtendArray()
01061  *
01062  *      Input:  boxaa
01063  *      Return: 0 if OK, 1 on error
01064  */
01065 l_int32
01066 boxaaExtendArray(BOXAA  *baa)
01067 {
01068 
01069     PROCNAME("boxaaExtendArray");
01070 
01071     if (!baa)
01072         return ERROR_INT("baa not defined", procName, 1);
01073 
01074     if ((baa->boxa = (BOXA **)reallocNew((void **)&baa->boxa,
01075                               sizeof(BOXA *) * baa->nalloc,
01076                               2 * sizeof(BOXA *) * baa->nalloc)) == NULL)
01077             return ERROR_INT("new ptr array not returned", procName, 1);
01078 
01079     baa->nalloc *= 2;
01080     return 0;
01081 }
01082 
01083 
01084 /*----------------------------------------------------------------------*
01085  *                           Boxaa accessors                            *
01086  *----------------------------------------------------------------------*/
01087 /*!
01088  *  boxaaGetCount()
01089  *
01090  *      Input:  boxaa
01091  *      Return: count (number of boxa), or 0 if no boxa or on error
01092  */
01093 l_int32
01094 boxaaGetCount(BOXAA  *baa)
01095 {
01096     PROCNAME("boxaaGetCount");
01097 
01098     if (!baa)
01099         return ERROR_INT("baa not defined", procName, 0);
01100     return baa->n;
01101 }
01102 
01103 
01104 /*!
01105  *  boxaaGetBoxCount()
01106  *
01107  *      Input:  boxaa
01108  *      Return: count (number of boxes), or 0 if no boxes or on error
01109  */
01110 l_int32
01111 boxaaGetBoxCount(BOXAA  *baa)
01112 {
01113 BOXA    *boxa;
01114 l_int32  n, sum, i;
01115 
01116     PROCNAME("boxaaGetBoxCount");
01117 
01118     if (!baa)
01119         return ERROR_INT("baa not defined", procName, 0);
01120 
01121     n = boxaaGetCount(baa);
01122     for (sum = 0, i = 0; i < n; i++) {
01123         boxa = boxaaGetBoxa(baa, i, L_CLONE);
01124         sum += boxaGetCount(boxa);
01125         boxaDestroy(&boxa);
01126     }
01127 
01128     return sum;
01129 }
01130 
01131 
01132 /*!
01133  *  boxaaGetBoxa()
01134  *
01135  *      Input:  boxaa
01136  *              index  (to the index-th boxa)
01137  *              accessflag   (L_COPY or L_CLONE)
01138  *      Return: boxa, or null on error
01139  */
01140 BOXA *
01141 boxaaGetBoxa(BOXAA   *baa,
01142              l_int32  index,
01143              l_int32  accessflag)
01144 {
01145 l_int32  n;
01146 
01147     PROCNAME("boxaaGetBoxa");
01148 
01149     if (!baa)
01150         return (BOXA *)ERROR_PTR("baa not defined", procName, NULL);
01151     n = boxaaGetCount(baa);
01152     if (index < 0 || index >= n)
01153         return (BOXA *)ERROR_PTR("index not valid", procName, NULL);
01154     if (accessflag != L_COPY && accessflag != L_CLONE)
01155         return (BOXA *)ERROR_PTR("invalid accessflag", procName, NULL);
01156 
01157     return boxaCopy(baa->boxa[index], accessflag);
01158 }
01159 
01160 
01161 /*!
01162  *  boxaaReplaceBoxa()
01163  *
01164  *      Input:  boxaa
01165  *              index  (to the index-th boxa)
01166  *              boxa (insert and replace any existing one)
01167  *      Return: 0 if OK, 1 on error
01168  *
01169  *  Notes:
01170  *      (1) Any existing boxa is destroyed, and the input one
01171  *          is inserted in its place.
01172  *      (2) If the index is invalid, return 1 (error)
01173  */
01174 l_int32
01175 boxaaReplaceBoxa(BOXAA   *baa,
01176                  l_int32  index,
01177                  BOXA    *boxa)
01178 {
01179 l_int32  n;
01180 
01181     PROCNAME("boxaaReplaceBoxa");
01182 
01183     if (!baa)
01184         return ERROR_INT("baa not defined", procName, 1);
01185     if (!boxa)
01186         return ERROR_INT("boxa not defined", procName, 1);
01187     n = boxaaGetCount(baa);
01188     if (index < 0 || index >= n)
01189         return ERROR_INT("index not valid", procName, 1);
01190 
01191     boxaDestroy(&baa->boxa[index]);
01192     baa->boxa[index] = boxa;
01193     return 0;
01194 }
01195 
01196 
01197 /*!
01198  *  boxaaInsertBoxa()
01199  *
01200  *      Input:  boxaa
01201  *              index (location in boxaa to insert new boxa)
01202  *              boxa (new boxa to be inserted)
01203  *      Return: 0 if OK, 1 on error
01204  *
01205  *  Notes:
01206  *      (1) This shifts boxa[i] --> boxa[i + 1] for all i >= index,
01207  *          and then inserts boxa as boxa[index].
01208  *      (2) To insert at the beginning of the array, set index = 0.
01209  *      (3) To append to the array, it's easier to use boxaaAddBoxa().
01210  *      (4) This should not be used repeatedly to insert into large arrays,
01211  *          because the function is O(n).
01212  */
01213 l_int32
01214 boxaaInsertBoxa(BOXAA   *baa,
01215                 l_int32  index,
01216                 BOXA    *boxa)
01217 {
01218 l_int32  i, n;
01219 BOXA   **array;
01220 
01221     PROCNAME("boxaaInsertBoxa");
01222 
01223     if (!baa)
01224         return ERROR_INT("baa not defined", procName, 1);
01225     n = boxaaGetCount(baa);
01226     if (index < 0 || index > n)
01227         return ERROR_INT("index not in {0...n}", procName, 1);
01228     if (!boxa)
01229         return ERROR_INT("boxa not defined", procName, 1);
01230 
01231     if (n >= baa->nalloc)
01232         boxaaExtendArray(baa);
01233     array = baa->boxa;
01234     baa->n++;
01235     for (i = n; i > index; i--)
01236         array[i] = array[i - 1];
01237     array[index] = boxa;
01238 
01239     return 0;
01240 }
01241 
01242 
01243 /*!
01244  *  boxaaRemoveBoxa()
01245  *
01246  *      Input:  boxaa
01247  *              index  (of the boxa to be removed)
01248  *      Return: 0 if OK, 1 on error
01249  *
01250  *  Notes:
01251  *      (1) This removes boxa[index] and then shifts
01252  *          boxa[i] --> boxa[i - 1] for all i > index.
01253  *      (2) The removed boxaa is destroyed.
01254  *      (2) This should not be used repeatedly on large arrays,
01255  *          because the function is O(n).
01256  */
01257 l_int32
01258 boxaaRemoveBoxa(BOXAA   *baa,
01259                 l_int32  index)
01260 {
01261 l_int32  i, n;
01262 BOXA   **array;
01263 
01264     PROCNAME("boxaaRemoveBox");
01265 
01266     if (!baa)
01267         return ERROR_INT("baa not defined", procName, 1);
01268     n = boxaaGetCount(baa);
01269     if (index < 0 || index >= n)
01270         return ERROR_INT("index not valid", procName, 1);
01271 
01272     array = baa->boxa;
01273     boxaDestroy(&array[index]);
01274     for (i = index + 1; i < n; i++)
01275         array[i - 1] = array[i];
01276     array[n - 1] = NULL;
01277     baa->n--;
01278 
01279     return 0;
01280 }
01281 
01282 
01283 /*!
01284  *  boxaaAddBox()
01285  *
01286  *      Input:  boxaa
01287  *              index (of boxa with boxaa)
01288  *              box (to be added)
01289  *              accessflag (L_INSERT, L_COPY or L_CLONE)
01290  *      Return: 0 if OK, 1 on error
01291  *
01292  *  Notes:
01293  *      (1) Adds to an existing boxa only.
01294  */
01295 l_int32
01296 boxaaAddBox(BOXAA   *baa,
01297             l_int32  index,
01298             BOX     *box,
01299             l_int32  accessflag)
01300 {
01301 l_int32  n;
01302 BOXA    *boxa;
01303     PROCNAME("boxaaAddBox");
01304 
01305     if (!baa)
01306         return ERROR_INT("baa not defined", procName, 1);
01307     n = boxaaGetCount(baa);
01308     if (index < 0 || index >= n)
01309         return ERROR_INT("index not valid", procName, 1);
01310     if (accessflag != L_INSERT && accessflag != L_COPY && accessflag != L_CLONE)
01311         return ERROR_INT("invalid accessflag", procName, 1);
01312 
01313     boxa = boxaaGetBoxa(baa, index, L_CLONE);
01314     boxaAddBox(boxa, box, accessflag);
01315     boxaDestroy(&boxa);
01316     return 0;
01317 }
01318 
01319 
01320 /*---------------------------------------------------------------------*
01321  *                        Boxaa serialized I/O                         *
01322  *---------------------------------------------------------------------*/
01323 /*!
01324  *  boxaaRead()
01325  *
01326  *      Input:  filename
01327  *      Return: boxaa, or null on error
01328  */
01329 BOXAA *
01330 boxaaRead(const char  *filename)
01331 {
01332 FILE   *fp;
01333 BOXAA  *baa;
01334 
01335     PROCNAME("boxaaRead");
01336 
01337     if (!filename)
01338         return (BOXAA *)ERROR_PTR("filename not defined", procName, NULL);
01339     if ((fp = fopenReadStream(filename)) == NULL)
01340         return (BOXAA *)ERROR_PTR("stream not opened", procName, NULL);
01341 
01342     if ((baa = boxaaReadStream(fp)) == NULL) {
01343         fclose(fp);
01344         return (BOXAA *)ERROR_PTR("boxaa not read", procName, NULL);
01345     }
01346 
01347     fclose(fp);
01348     return baa;
01349 }
01350 
01351 
01352 /*!
01353  *  boxaaReadStream()
01354  *
01355  *      Input:  stream
01356  *      Return: boxaa, or null on error
01357  */
01358 BOXAA *
01359 boxaaReadStream(FILE  *fp)
01360 {
01361 l_int32  n, i, x, y, w, h, version;
01362 l_int32  ignore;
01363 BOXA    *boxa;
01364 BOXAA   *baa;
01365 
01366     PROCNAME("boxaaReadStream");
01367 
01368     if (!fp)
01369         return (BOXAA *)ERROR_PTR("stream not defined", procName, NULL);
01370 
01371     if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1)
01372         return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
01373     if (version != BOXAA_VERSION_NUMBER)
01374         return (BOXAA *)ERROR_PTR("invalid boxa version", procName, NULL);
01375     if (fscanf(fp, "Number of boxa = %d\n", &n) != 1)
01376         return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL);
01377 
01378     if ((baa = boxaaCreate(n)) == NULL)
01379         return (BOXAA *)ERROR_PTR("boxaa not made", procName, NULL);
01380 
01381     for (i = 0; i < n; i++) {
01382         if (fscanf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
01383                    &ignore, &x, &y, &w, &h) != 5)
01384             return (BOXAA *)ERROR_PTR("boxa descr not valid", procName, NULL);
01385         if ((boxa = boxaReadStream(fp)) == NULL)
01386             return (BOXAA *)ERROR_PTR("boxa not made", procName, NULL);
01387         boxaaAddBoxa(baa, boxa, L_INSERT);
01388     }
01389 
01390     return baa;
01391 }
01392 
01393 /*!
01394  *  boxaaWrite()
01395  *
01396  *      Input:  filename
01397  *              boxaa
01398  *      Return: 0 if OK, 1 on error
01399  */
01400 l_int32
01401 boxaaWrite(const char  *filename,
01402            BOXAA       *baa)
01403 {
01404 FILE  *fp;
01405 
01406     PROCNAME("boxaaWrite");
01407 
01408     if (!filename)
01409         return ERROR_INT("filename not defined", procName, 1);
01410     if (!baa)
01411         return ERROR_INT("baa not defined", procName, 1);
01412 
01413     if ((fp = fopenWriteStream(filename, "w")) == NULL)
01414         return ERROR_INT("stream not opened", procName, 1);
01415     if (boxaaWriteStream(fp, baa))
01416         return ERROR_INT("baa not written to stream", procName, 1);
01417     fclose(fp);
01418 
01419     return 0;
01420 }
01421 
01422 
01423 /*!
01424  *  boxaaWriteStream()
01425  *
01426  *      Input: stream
01427  *             boxaa
01428  *      Return: 0 if OK, 1 on error
01429  */
01430 l_int32
01431 boxaaWriteStream(FILE   *fp,
01432                  BOXAA  *baa)
01433 {
01434 l_int32  n, i, x, y, w, h;
01435 BOX     *box;
01436 BOXA    *boxa;
01437 
01438     PROCNAME("boxaaWriteStream");
01439 
01440     if (!fp)
01441         return ERROR_INT("stream not defined", procName, 1);
01442     if (!baa)
01443         return ERROR_INT("baa not defined", procName, 1);
01444 
01445     n = boxaaGetCount(baa);
01446     fprintf(fp, "\nBoxaa Version %d\n", BOXAA_VERSION_NUMBER);
01447     fprintf(fp, "Number of boxa = %d\n", n);
01448 
01449     for (i = 0; i < n; i++) {
01450         if ((boxa = boxaaGetBoxa(baa, i, L_CLONE)) == NULL)
01451             return ERROR_INT("boxa not found", procName, 1);
01452         boxaGetExtent(boxa, NULL, NULL, &box);
01453         boxGetGeometry(box, &x, &y, &w, &h);
01454         fprintf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d",
01455                 i, x, y, w, h);
01456         boxaWriteStream(fp, boxa);
01457         boxDestroy(&box);
01458         boxaDestroy(&boxa);
01459     }
01460     return 0;
01461 }
01462 
01463 
01464 /*---------------------------------------------------------------------*
01465  *                         Boxa serialized I/O                         *
01466  *---------------------------------------------------------------------*/
01467 /*!
01468  *  boxaRead()
01469  *
01470  *      Input:  filename
01471  *      Return: boxa, or null on error
01472  */
01473 BOXA *
01474 boxaRead(const char  *filename)
01475 {
01476 FILE  *fp;
01477 BOXA  *boxa;
01478 
01479     PROCNAME("boxaRead");
01480 
01481     if (!filename)
01482         return (BOXA *)ERROR_PTR("filename not defined", procName, NULL);
01483     if ((fp = fopenReadStream(filename)) == NULL)
01484         return (BOXA *)ERROR_PTR("stream not opened", procName, NULL);
01485 
01486     if ((boxa = boxaReadStream(fp)) == NULL) {
01487         fclose(fp);
01488         return (BOXA *)ERROR_PTR("boxa not read", procName, NULL);
01489     }
01490 
01491     fclose(fp);
01492     return boxa;
01493 }
01494 
01495 
01496 /*!
01497  *  boxaReadStream()
01498  *
01499  *      Input:  stream
01500  *      Return: boxa, or null on error
01501  */
01502 BOXA *
01503 boxaReadStream(FILE  *fp)
01504 {
01505 l_int32  n, i, x, y, w, h, version;
01506 l_int32  ignore;
01507 BOX     *box;
01508 BOXA    *boxa;
01509 
01510     PROCNAME("boxaReadStream");
01511 
01512     if (!fp)
01513         return (BOXA *)ERROR_PTR("stream not defined", procName, NULL);
01514 
01515     if (fscanf(fp, "\nBoxa Version %d\n", &version) != 1)
01516         return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL);
01517     if (version != BOXA_VERSION_NUMBER)
01518         return (BOXA *)ERROR_PTR("invalid boxa version", procName, NULL);
01519     if (fscanf(fp, "Number of boxes = %d\n", &n) != 1)
01520         return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL);
01521 
01522     if ((boxa = boxaCreate(n)) == NULL)
01523         return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
01524 
01525     for (i = 0; i < n; i++) {
01526         if (fscanf(fp, "  Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
01527                 &ignore, &x, &y, &w, &h) != 5)
01528             return (BOXA *)ERROR_PTR("box descr not valid", procName, NULL);
01529         if ((box = boxCreate(x, y, w, h)) == NULL)
01530             return (BOXA *)ERROR_PTR("box not made", procName, NULL);
01531         boxaAddBox(boxa, box, L_INSERT);
01532     }
01533 
01534     return boxa;
01535 }
01536 
01537 
01538 /*!
01539  *  boxaWrite()
01540  *
01541  *      Input:  filename
01542  *              boxa
01543  *      Return: 0 if OK, 1 on error
01544  */
01545 l_int32
01546 boxaWrite(const char  *filename,
01547           BOXA        *boxa)
01548 {
01549 FILE  *fp;
01550 
01551     PROCNAME("boxaWrite");
01552 
01553     if (!filename)
01554         return ERROR_INT("filename not defined", procName, 1);
01555     if (!boxa)
01556         return ERROR_INT("boxa not defined", procName, 1);
01557 
01558     if ((fp = fopenWriteStream(filename, "w")) == NULL)
01559         return ERROR_INT("stream not opened", procName, 1);
01560     if (boxaWriteStream(fp, boxa))
01561         return ERROR_INT("boxa not written to stream", procName, 1);
01562     fclose(fp);
01563 
01564     return 0;
01565 }
01566 
01567 
01568 /*!
01569  *  boxaWriteStream()
01570  *
01571  *      Input: stream
01572  *             boxa
01573  *      Return: 0 if OK, 1 on error
01574  */
01575 l_int32
01576 boxaWriteStream(FILE  *fp,
01577                 BOXA  *boxa)
01578 {
01579 l_int32  n, i;
01580 BOX     *box;
01581 
01582     PROCNAME("boxaWriteStream");
01583 
01584     if (!fp)
01585         return ERROR_INT("stream not defined", procName, 1);
01586     if (!boxa)
01587         return ERROR_INT("boxa not defined", procName, 1);
01588 
01589     n = boxaGetCount(boxa);
01590     fprintf(fp, "\nBoxa Version %d\n", BOXA_VERSION_NUMBER);
01591     fprintf(fp, "Number of boxes = %d\n", n);
01592     for (i = 0; i < n; i++) {
01593         if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL)
01594             return ERROR_INT("box not found", procName, 1);
01595         fprintf(fp, "  Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
01596                 i, box->x, box->y, box->w, box->h);
01597         boxDestroy(&box);
01598     }
01599     return 0;
01600 }
01601 
01602 
01603 /*---------------------------------------------------------------------*
01604  *                            Debug printing                           *
01605  *---------------------------------------------------------------------*/
01606 /*!
01607  *  boxPrintStreamInfo()
01608  *
01609  *      Input:  stream
01610  *              box
01611  *      Return: 0 if OK, 1 on error
01612  *
01613  *  Notes:
01614  *      (1) This outputs information about the box, for debugging.
01615  *      (2) Use serialization functions to write to file if you want
01616  *          to read the data back.
01617  */
01618 l_int32
01619 boxPrintStreamInfo(FILE  *fp,
01620                    BOX   *box)
01621 {
01622     PROCNAME("boxPrintStreamInfo");
01623 
01624     if (!fp)
01625         return ERROR_INT("stream not defined", procName, 1);
01626     if (!box)
01627         return ERROR_INT("box not defined", procName, 1);
01628 
01629     fprintf(fp, " Box x (pixels) =           %d\n", box->x);
01630     fprintf(fp, " Box y (pixels) =           %d\n", box->y);
01631     fprintf(fp, " Box width (pixels) =       %d\n", box->w);
01632     fprintf(fp, " Box height (pixels) =      %d\n", box->h);
01633 
01634     return 0;
01635 }
01636 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines