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