Leptonica 1.68
C Image Processing Library
|
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