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 * pixabasic.c 00018 * 00019 * Pixa creation, destruction, copying 00020 * PIXA *pixaCreate() 00021 * PIXA *pixaCreateFromPix() 00022 * PIXA *pixaCreateFromBoxa() 00023 * PIXA *pixaSplitPix() 00024 * void pixaDestroy() 00025 * PIXA *pixaCopy() 00026 * 00027 * Pixa addition 00028 * l_int32 pixaAddPix() 00029 * l_int32 pixaExtendArray() 00030 * l_int32 pixaExtendArrayToSize() 00031 * l_int32 pixaAddBox() 00032 * 00033 * Pixa accessors 00034 * l_int32 pixaGetCount() 00035 * l_int32 pixaChangeRefcount() 00036 * PIX *pixaGetPix() 00037 * l_int32 pixaGetPixDimensions() 00038 * PIX *pixaGetBoxa() 00039 * l_int32 pixaGetBoxaCount() 00040 * BOX *pixaGetBox() 00041 * l_int32 pixaGetBoxGeometry() 00042 * PIX **pixaGetPixArray() 00043 * 00044 * Pixa array modifiers 00045 * l_int32 pixaReplacePix() 00046 * l_int32 pixaInsertPix() 00047 * l_int32 pixaRemovePix() 00048 * l_int32 pixaInitFull() 00049 * l_int32 pixaClear() 00050 * 00051 * Pixa combination 00052 * PIXA *pixaJoin() 00053 * 00054 * Pixaa creation, destruction 00055 * PIXAA *pixaaCreate() 00056 * PIXAA *pixaaCreateFromPixa() 00057 * void pixaaDestroy() 00058 * 00059 * Pixaa addition 00060 * l_int32 pixaaAddPixa() 00061 * l_int32 pixaaExtendArray() 00062 * l_int32 pixaaAddBox() 00063 * 00064 * Pixaa accessors 00065 * l_int32 pixaaGetCount() 00066 * PIXA *pixaaGetPixa() 00067 * BOXA *pixaaGetBoxa() 00068 * 00069 * Pixa serialized I/O (requires png support) 00070 * PIXA *pixaRead() 00071 * PIXA *pixaReadStream() 00072 * l_int32 pixaWrite() 00073 * l_int32 pixaWriteStream() 00074 * 00075 * Pixaa serialized I/O (requires png support) 00076 * PIXAA *pixaaRead() 00077 * PIXAA *pixaaReadStream() 00078 * l_int32 pixaaWrite() 00079 * l_int32 pixaaWriteStream() 00080 * 00081 * 00082 * Important note on reference counting: 00083 * Reference counting for the Pixa is analogous to that for the Boxa. 00084 * See pix.h for details. pixaCopy() provides three possible modes 00085 * of copy. The basic rule is that however a Pixa is obtained 00086 * (e.g., from pixaCreate*(), pixaCopy(), or a Pixaa accessor), 00087 * it is necessary to call pixaDestroy() on it. 00088 */ 00089 00090 #include <string.h> 00091 #include "allheaders.h" 00092 00093 static const l_int32 INITIAL_PTR_ARRAYSIZE = 20; /* n'import quoi */ 00094 00095 00096 /*---------------------------------------------------------------------* 00097 * Pixa creation, destruction, copy * 00098 *---------------------------------------------------------------------*/ 00099 /*! 00100 * pixaCreate() 00101 * 00102 * Input: n (initial number of ptrs) 00103 * Return: pixa, or null on error 00104 */ 00105 PIXA * 00106 pixaCreate(l_int32 n) 00107 { 00108 PIXA *pixa; 00109 00110 PROCNAME("pixaCreate"); 00111 00112 if (n <= 0) 00113 n = INITIAL_PTR_ARRAYSIZE; 00114 00115 if ((pixa = (PIXA *)CALLOC(1, sizeof(PIXA))) == NULL) 00116 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL); 00117 pixa->n = 0; 00118 pixa->nalloc = n; 00119 pixa->refcount = 1; 00120 00121 if ((pixa->pix = (PIX **)CALLOC(n, sizeof(PIX *))) == NULL) 00122 return (PIXA *)ERROR_PTR("pix ptrs not made", procName, NULL); 00123 if ((pixa->boxa = boxaCreate(n)) == NULL) 00124 return (PIXA *)ERROR_PTR("boxa not made", procName, NULL); 00125 00126 return pixa; 00127 } 00128 00129 00130 /*! 00131 * pixaCreateFromPix() 00132 * 00133 * Input: pixs (with individual components on a lattice) 00134 * n (number of components) 00135 * cellw (width of each cell) 00136 * cellh (height of each cell) 00137 * Return: pixa, or null on error 00138 * 00139 * Note: for bpp = 1, we truncate each retrieved pix to 00140 * the ON pixels, which we assume for now start at (0,0) 00141 */ 00142 PIXA * 00143 pixaCreateFromPix(PIX *pixs, 00144 l_int32 n, 00145 l_int32 cellw, 00146 l_int32 cellh) 00147 { 00148 l_int32 w, h, d, nw, nh, i, j, index; 00149 PIX *pix, *pixt; 00150 PIXA *pixa; 00151 00152 PROCNAME("pixaCreateFromPix"); 00153 00154 if (!pixs) 00155 return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL); 00156 if (n <= 0) 00157 return (PIXA *)ERROR_PTR("n must be > 0", procName, NULL); 00158 00159 if ((pixa = pixaCreate(n)) == NULL) 00160 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL); 00161 pixGetDimensions(pixs, &w, &h, &d); 00162 if ((pixt = pixCreate(cellw, cellh, d)) == NULL) 00163 return (PIXA *)ERROR_PTR("pixt not made", procName, NULL); 00164 00165 nw = (w + cellw - 1) / cellw; 00166 nh = (h + cellh - 1) / cellh; 00167 for (i = 0, index = 0; i < nh; i++) { 00168 for (j = 0; j < nw && index < n; j++, index++) { 00169 pixRasterop(pixt, 0, 0, cellw, cellh, PIX_SRC, pixs, 00170 j * cellw, i * cellh); 00171 if (d == 1 && !pixClipToForeground(pixt, &pix, NULL)) 00172 pixaAddPix(pixa, pix, L_INSERT); 00173 else 00174 pixaAddPix(pixa, pixt, L_COPY); 00175 } 00176 } 00177 00178 pixDestroy(&pixt); 00179 return pixa; 00180 } 00181 00182 00183 /*! 00184 * pixaCreateFromBoxa() 00185 * 00186 * Input: pixs 00187 * boxa 00188 * &cropwarn (<optional return> TRUE if the boxa extent 00189 * is larger than pixs. 00190 * Return: pixad, or null on error 00191 * 00192 * Notes: 00193 * (1) This simply extracts from pixs the region corresponding to each 00194 * box in the boxa. 00195 * (2) The 3rd arg is optional. If the extent of the boxa exceeds the 00196 * size of the pixa, so that some boxes are either clipped 00197 * or entirely outside the pix, a warning is returned as TRUE. 00198 * (3) pixad will have only the properly clipped elements, and 00199 * the internal boxa will be correct. 00200 */ 00201 PIXA * 00202 pixaCreateFromBoxa(PIX *pixs, 00203 BOXA *boxa, 00204 l_int32 *pcropwarn) 00205 { 00206 l_int32 i, n, w, h, wbox, hbox, cropwarn; 00207 BOX *box, *boxc; 00208 PIX *pixd; 00209 PIXA *pixad; 00210 00211 PROCNAME("pixaCreateFromBoxa"); 00212 00213 if (!pixs) 00214 return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL); 00215 if (!boxa) 00216 return (PIXA *)ERROR_PTR("boxa not defined", procName, NULL); 00217 00218 n = boxaGetCount(boxa); 00219 if ((pixad = pixaCreate(n)) == NULL) 00220 return (PIXA *)ERROR_PTR("pixad not made", procName, NULL); 00221 00222 boxaGetExtent(boxa, &wbox, &hbox, NULL); 00223 pixGetDimensions(pixs, &w, &h, NULL); 00224 cropwarn = FALSE; 00225 if (wbox > w || hbox > h) 00226 cropwarn = TRUE; 00227 if (pcropwarn) 00228 *pcropwarn = cropwarn; 00229 00230 for (i = 0; i < n; i++) { 00231 box = boxaGetBox(boxa, i, L_COPY); 00232 if (cropwarn) { /* if box is outside pixs, pixd is NULL */ 00233 pixd = pixClipRectangle(pixs, box, &boxc); /* may be NULL */ 00234 if (pixd) { 00235 pixaAddPix(pixad, pixd, L_INSERT); 00236 pixaAddBox(pixad, boxc, L_INSERT); 00237 } 00238 boxDestroy(&box); 00239 } 00240 else { 00241 pixd = pixClipRectangle(pixs, box, NULL); 00242 pixaAddPix(pixad, pixd, L_INSERT); 00243 pixaAddBox(pixad, box, L_INSERT); 00244 } 00245 } 00246 00247 return pixad; 00248 } 00249 00250 00251 /*! 00252 * pixaSplitPix() 00253 * 00254 * Input: pixs (with individual components on a lattice) 00255 * nx (number of mosaic cells horizontally) 00256 * ny (number of mosaic cells vertically) 00257 * borderwidth (of added border on all sides) 00258 * bordercolor (in our RGBA format: 0xrrggbbaa) 00259 * Return: pixa, or null on error 00260 * 00261 * Notes: 00262 * (1) This is a variant on pixaCreateFromPix(), where we 00263 * simply divide the image up into (approximately) equal 00264 * subunits. If you want the subimages to have essentially 00265 * the same aspect ratio as the input pix, use nx = ny. 00266 * (2) If borderwidth is 0, we ignore the input bordercolor and 00267 * redefine it to white. 00268 * (3) The bordercolor is always used to initialize each tiled pix, 00269 * so that if the src is clipped, the unblitted part will 00270 * be this color. This avoids 1 pixel wide black stripes at the 00271 * left and lower edges. 00272 */ 00273 PIXA * 00274 pixaSplitPix(PIX *pixs, 00275 l_int32 nx, 00276 l_int32 ny, 00277 l_int32 borderwidth, 00278 l_uint32 bordercolor) 00279 { 00280 l_int32 w, h, d, cellw, cellh, i, j; 00281 PIX *pixt; 00282 PIXA *pixa; 00283 00284 PROCNAME("pixaSplitPix"); 00285 00286 if (!pixs) 00287 return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL); 00288 if (nx <= 0 || ny <= 0) 00289 return (PIXA *)ERROR_PTR("nx and ny must be > 0", procName, NULL); 00290 borderwidth = L_MAX(0, borderwidth); 00291 00292 if ((pixa = pixaCreate(nx * ny)) == NULL) 00293 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL); 00294 pixGetDimensions(pixs, &w, &h, &d); 00295 cellw = (w + nx - 1) / nx; /* round up */ 00296 cellh = (h + ny - 1) / ny; 00297 00298 for (i = 0; i < ny; i++) { 00299 for (j = 0; j < nx; j++) { 00300 if ((pixt = pixCreate(cellw + 2 * borderwidth, 00301 cellh + 2 * borderwidth, d)) == NULL) 00302 return (PIXA *)ERROR_PTR("pixt not made", procName, NULL); 00303 pixCopyColormap(pixt, pixs); 00304 if (borderwidth == 0) { /* initialize full image to white */ 00305 if (d == 1) 00306 pixClearAll(pixt); 00307 else 00308 pixSetAll(pixt); 00309 } 00310 else 00311 pixSetAllArbitrary(pixt, bordercolor); 00312 pixRasterop(pixt, borderwidth, borderwidth, cellw, cellh, 00313 PIX_SRC, pixs, j * cellw, i * cellh); 00314 pixaAddPix(pixa, pixt, L_INSERT); 00315 } 00316 } 00317 00318 return pixa; 00319 } 00320 00321 00322 /*! 00323 * pixaDestroy() 00324 * 00325 * Input: &pixa (<can be nulled>) 00326 * Return: void 00327 * 00328 * Notes: 00329 * (1) Decrements the ref count and, if 0, destroys the pixa. 00330 * (2) Always nulls the input ptr. 00331 */ 00332 void 00333 pixaDestroy(PIXA **ppixa) 00334 { 00335 l_int32 i; 00336 PIXA *pixa; 00337 00338 PROCNAME("pixaDestroy"); 00339 00340 if (ppixa == NULL) { 00341 L_WARNING("ptr address is NULL!", procName); 00342 return; 00343 } 00344 00345 if ((pixa = *ppixa) == NULL) 00346 return; 00347 00348 /* Decrement the refcount. If it is 0, destroy the pixa. */ 00349 pixaChangeRefcount(pixa, -1); 00350 if (pixa->refcount <= 0) { 00351 for (i = 0; i < pixa->n; i++) 00352 pixDestroy(&pixa->pix[i]); 00353 FREE(pixa->pix); 00354 boxaDestroy(&pixa->boxa); 00355 FREE(pixa); 00356 } 00357 00358 *ppixa = NULL; 00359 return; 00360 } 00361 00362 00363 /*! 00364 * pixaCopy() 00365 * 00366 * Input: pixas 00367 * copyflag: 00368 * L_COPY makes a new pixa and copies each pix and each box 00369 * L_CLONE gives a new ref-counted handle to the input pixa 00370 * L_COPY_CLONE makes a new pixa and inserts clones of 00371 * all pix and boxes 00372 * Return: new pixa, or null on error 00373 * 00374 * Note: see pix.h for description of the copy types. 00375 */ 00376 PIXA * 00377 pixaCopy(PIXA *pixa, 00378 l_int32 copyflag) 00379 { 00380 l_int32 i; 00381 BOX *boxc; 00382 PIX *pixc; 00383 PIXA *pixac; 00384 00385 PROCNAME("pixaCopy"); 00386 00387 if (!pixa) 00388 return (PIXA *)ERROR_PTR("pixa not defined", procName, NULL); 00389 00390 if (copyflag == L_CLONE) { 00391 pixaChangeRefcount(pixa, 1); 00392 return pixa; 00393 } 00394 00395 if (copyflag != L_COPY && copyflag != L_COPY_CLONE) 00396 return (PIXA *)ERROR_PTR("invalid copyflag", procName, NULL); 00397 00398 if ((pixac = pixaCreate(pixa->n)) == NULL) 00399 return (PIXA *)ERROR_PTR("pixac not made", procName, NULL); 00400 for (i = 0; i < pixa->n; i++) { 00401 if (copyflag == L_COPY) { 00402 pixc = pixaGetPix(pixa, i, L_COPY); 00403 boxc = pixaGetBox(pixa, i, L_COPY); 00404 } 00405 else { /* copy-clone */ 00406 pixc = pixaGetPix(pixa, i, L_CLONE); 00407 boxc = pixaGetBox(pixa, i, L_CLONE); 00408 } 00409 pixaAddPix(pixac, pixc, L_INSERT); 00410 pixaAddBox(pixac, boxc, L_INSERT); 00411 } 00412 00413 return pixac; 00414 } 00415 00416 00417 00418 /*---------------------------------------------------------------------* 00419 * Pixa addition * 00420 *---------------------------------------------------------------------*/ 00421 /*! 00422 * pixaAddPix() 00423 * 00424 * Input: pixa 00425 * pix (to be added) 00426 * copyflag (L_INSERT, L_COPY, L_CLONE) 00427 * Return: 0 if OK; 1 on error 00428 */ 00429 l_int32 00430 pixaAddPix(PIXA *pixa, 00431 PIX *pix, 00432 l_int32 copyflag) 00433 { 00434 l_int32 n; 00435 PIX *pixc; 00436 00437 PROCNAME("pixaAddPix"); 00438 00439 if (!pixa) 00440 return ERROR_INT("pixa not defined", procName, 1); 00441 if (!pix) 00442 return ERROR_INT("pix not defined", procName, 1); 00443 00444 if (copyflag == L_INSERT) 00445 pixc = pix; 00446 else if (copyflag == L_COPY) 00447 pixc = pixCopy(NULL, pix); 00448 else if (copyflag == L_CLONE) 00449 pixc = pixClone(pix); 00450 else 00451 return ERROR_INT("invalid copyflag", procName, 1); 00452 if (!pixc) 00453 return ERROR_INT("pixc not made", procName, 1); 00454 00455 n = pixaGetCount(pixa); 00456 if (n >= pixa->nalloc) 00457 pixaExtendArray(pixa); 00458 pixa->pix[n] = pixc; 00459 pixa->n++; 00460 00461 return 0; 00462 } 00463 00464 00465 /*! 00466 * pixaExtendArray() 00467 * 00468 * Input: pixa 00469 * Return: 0 if OK; 1 on error 00470 * 00471 * Notes: 00472 * (1) Doubles the size of the pixa and boxa ptr arrays. 00473 */ 00474 l_int32 00475 pixaExtendArray(PIXA *pixa) 00476 { 00477 PROCNAME("pixaExtendArray"); 00478 00479 if (!pixa) 00480 return ERROR_INT("pixa not defined", procName, 1); 00481 00482 return pixaExtendArrayToSize(pixa, 2 * pixa->nalloc); 00483 } 00484 00485 00486 /*! 00487 * pixaExtendArrayToSize() 00488 * 00489 * Input: pixa 00490 * Return: 0 if OK; 1 on error 00491 * 00492 * Notes: 00493 * (1) If necessary, reallocs new pixa and boxa ptrs arrays to @size. 00494 * The pixa and boxa ptr arrays must always be equal in size. 00495 */ 00496 l_int32 00497 pixaExtendArrayToSize(PIXA *pixa, 00498 l_int32 size) 00499 { 00500 PROCNAME("pixaExtendArrayToSize"); 00501 00502 if (!pixa) 00503 return ERROR_INT("pixa not defined", procName, 1); 00504 00505 if (size > pixa->nalloc) { 00506 if ((pixa->pix = (PIX **)reallocNew((void **)&pixa->pix, 00507 sizeof(PIX *) * pixa->nalloc, 00508 size * sizeof(PIX *))) == NULL) 00509 return ERROR_INT("new ptr array not returned", procName, 1); 00510 pixa->nalloc = size; 00511 } 00512 return boxaExtendArrayToSize(pixa->boxa, size); 00513 } 00514 00515 00516 /*! 00517 * pixaAddBox() 00518 * 00519 * Input: pixa 00520 * box 00521 * copyflag (L_INSERT, L_COPY, L_CLONE) 00522 * Return: 0 if OK, 1 on error 00523 */ 00524 l_int32 00525 pixaAddBox(PIXA *pixa, 00526 BOX *box, 00527 l_int32 copyflag) 00528 { 00529 PROCNAME("pixaAddBox"); 00530 00531 if (!pixa) 00532 return ERROR_INT("pixa not defined", procName, 1); 00533 if (!box) 00534 return ERROR_INT("box not defined", procName, 1); 00535 if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE) 00536 return ERROR_INT("invalid copyflag", procName, 1); 00537 00538 boxaAddBox(pixa->boxa, box, copyflag); 00539 return 0; 00540 } 00541 00542 00543 00544 /*---------------------------------------------------------------------* 00545 * Pixa accessors * 00546 *---------------------------------------------------------------------*/ 00547 /*! 00548 * pixaGetCount() 00549 * 00550 * Input: pixa 00551 * Return: count, or 0 if no pixa 00552 */ 00553 l_int32 00554 pixaGetCount(PIXA *pixa) 00555 { 00556 PROCNAME("pixaGetCount"); 00557 00558 if (!pixa) 00559 return ERROR_INT("pixa not defined", procName, 0); 00560 00561 return pixa->n; 00562 } 00563 00564 00565 /*! 00566 * pixaChangeRefcount() 00567 * 00568 * Input: pixa 00569 * Return: 0 if OK, 1 on error 00570 */ 00571 l_int32 00572 pixaChangeRefcount(PIXA *pixa, 00573 l_int32 delta) 00574 { 00575 PROCNAME("pixaChangeRefcount"); 00576 00577 if (!pixa) 00578 return ERROR_INT("pixa not defined", procName, 1); 00579 00580 pixa->refcount += delta; 00581 return 0; 00582 } 00583 00584 00585 /*! 00586 * pixaGetPix() 00587 * 00588 * Input: pixa 00589 * index (to the index-th pix) 00590 * accesstype (L_COPY or L_CLONE) 00591 * Return: pix, or null on error 00592 */ 00593 PIX * 00594 pixaGetPix(PIXA *pixa, 00595 l_int32 index, 00596 l_int32 accesstype) 00597 { 00598 PROCNAME("pixaGetPix"); 00599 00600 if (!pixa) 00601 return (PIX *)ERROR_PTR("pixa not defined", procName, NULL); 00602 if (index < 0 || index >= pixa->n) 00603 return (PIX *)ERROR_PTR("index not valid", procName, NULL); 00604 00605 if (accesstype == L_COPY) 00606 return pixCopy(NULL, pixa->pix[index]); 00607 else if (accesstype == L_CLONE) 00608 return pixClone(pixa->pix[index]); 00609 else 00610 return (PIX *)ERROR_PTR("invalid accesstype", procName, NULL); 00611 } 00612 00613 00614 /*! 00615 * pixaGetPixDimensions() 00616 * 00617 * Input: pixa 00618 * index (to the index-th box) 00619 * &w, &h, &d (<optional return>; each can be null) 00620 * Return: 0 if OK, 1 on error 00621 */ 00622 l_int32 00623 pixaGetPixDimensions(PIXA *pixa, 00624 l_int32 index, 00625 l_int32 *pw, 00626 l_int32 *ph, 00627 l_int32 *pd) 00628 { 00629 PIX *pix; 00630 00631 PROCNAME("pixaGetPixDimensions"); 00632 00633 if (!pixa) 00634 return ERROR_INT("pixa not defined", procName, 1); 00635 if (index < 0 || index >= pixa->n) 00636 return ERROR_INT("index not valid", procName, 1); 00637 00638 if ((pix = pixaGetPix(pixa, index, L_CLONE)) == NULL) 00639 return ERROR_INT("pix not found!", procName, 1); 00640 pixGetDimensions(pix, pw, ph, pd); 00641 pixDestroy(&pix); 00642 return 0; 00643 } 00644 00645 00646 /*! 00647 * pixaGetBoxa() 00648 * 00649 * Input: pixa 00650 * accesstype (L_COPY, L_CLONE, L_COPY_CLONE) 00651 * Return: boxa, or null on error 00652 */ 00653 BOXA * 00654 pixaGetBoxa(PIXA *pixa, 00655 l_int32 accesstype) 00656 { 00657 PROCNAME("pixaGetBoxa"); 00658 00659 if (!pixa) 00660 return (BOXA *)ERROR_PTR("pixa not defined", procName, NULL); 00661 if (!pixa->boxa) 00662 return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL); 00663 if (accesstype != L_COPY && accesstype != L_CLONE && 00664 accesstype != L_COPY_CLONE) 00665 return (BOXA *)ERROR_PTR("invalid accesstype", procName, NULL); 00666 00667 return boxaCopy(pixa->boxa, accesstype); 00668 } 00669 00670 00671 /*! 00672 * pixaGetBoxaCount() 00673 * 00674 * Input: pixa 00675 * Return: count, or 0 on error 00676 */ 00677 l_int32 00678 pixaGetBoxaCount(PIXA *pixa) 00679 { 00680 PROCNAME("pixaGetBoxaCount"); 00681 00682 if (!pixa) 00683 return ERROR_INT("pixa not defined", procName, 0); 00684 00685 return boxaGetCount(pixa->boxa); 00686 } 00687 00688 00689 /*! 00690 * pixaGetBox() 00691 * 00692 * Input: pixa 00693 * index (to the index-th pix) 00694 * accesstype (L_COPY or L_CLONE) 00695 * Return: box (if null, not automatically an error), or null on error 00696 * 00697 * Notes: 00698 * (1) There is always a boxa with a pixa, and it is initialized so 00699 * that each box ptr is NULL. 00700 * (2) In general, we expect that there is either a box associated 00701 * with each pix, or no boxes at all in the boxa. 00702 * (3) Having no boxes is thus not an automatic error. Whether it 00703 * is an actual error is determined by the calling program. 00704 * If the caller expects to get a box, it is an error; see, e.g., 00705 * pixaGetBoxGeometry(). 00706 */ 00707 BOX * 00708 pixaGetBox(PIXA *pixa, 00709 l_int32 index, 00710 l_int32 accesstype) 00711 { 00712 BOX *box; 00713 00714 PROCNAME("pixaGetBox"); 00715 00716 if (!pixa) 00717 return (BOX *)ERROR_PTR("pixa not defined", procName, NULL); 00718 if (!pixa->boxa) 00719 return (BOX *)ERROR_PTR("boxa not defined", procName, NULL); 00720 if (index < 0 || index >= pixa->boxa->n) 00721 return (BOX *)ERROR_PTR("index not valid", procName, NULL); 00722 if (accesstype != L_COPY && accesstype != L_CLONE) 00723 return (BOX *)ERROR_PTR("invalid accesstype", procName, NULL); 00724 00725 box = pixa->boxa->box[index]; 00726 if (box) { 00727 if (accesstype == L_COPY) 00728 return boxCopy(box); 00729 else /* accesstype == L_CLONE */ 00730 return boxClone(box); 00731 } 00732 else 00733 return NULL; 00734 } 00735 00736 00737 /*! 00738 * pixaGetBoxGeometry() 00739 * 00740 * Input: pixa 00741 * index (to the index-th box) 00742 * &x, &y, &w, &h (<optional return>; each can be null) 00743 * Return: 0 if OK, 1 on error 00744 */ 00745 l_int32 00746 pixaGetBoxGeometry(PIXA *pixa, 00747 l_int32 index, 00748 l_int32 *px, 00749 l_int32 *py, 00750 l_int32 *pw, 00751 l_int32 *ph) 00752 { 00753 BOX *box; 00754 00755 PROCNAME("pixaGetBoxGeometry"); 00756 00757 if (!pixa) 00758 return ERROR_INT("pixa not defined", procName, 1); 00759 if (index < 0 || index >= pixa->n) 00760 return ERROR_INT("index not valid", procName, 1); 00761 00762 if ((box = pixaGetBox(pixa, index, L_CLONE)) == NULL) 00763 return ERROR_INT("box not found!", procName, 1); 00764 boxGetGeometry(box, px, py, pw, ph); 00765 boxDestroy(&box); 00766 return 0; 00767 } 00768 00769 00770 /*! 00771 * pixaGetPixArray() 00772 * 00773 * Input: pixa 00774 * Return: pix array, or null on error 00775 * 00776 * Notes: 00777 * (1) This returns a ptr to the actual array. The array is 00778 * owned by the pixa, so it must not be destroyed. 00779 * (2) The caller should always check if the return value is NULL 00780 * before accessing any of the pix ptrs in this array! 00781 */ 00782 PIX ** 00783 pixaGetPixArray(PIXA *pixa) 00784 { 00785 PROCNAME("pixaGetPixArray"); 00786 00787 if (!pixa) 00788 return (PIX **)ERROR_PTR("pixa not defined", procName, NULL); 00789 00790 return pixa->pix; 00791 } 00792 00793 00794 00795 /*---------------------------------------------------------------------* 00796 * Pixa array modifiers * 00797 *---------------------------------------------------------------------*/ 00798 /*! 00799 * pixaReplacePix() 00800 * 00801 * Input: pixa 00802 * index (to the index-th pix) 00803 * pix (insert to replace existing one) 00804 * box (<optional> insert to replace existing) 00805 * Return: 0 if OK, 1 on error 00806 * 00807 * Notes: 00808 * (1) In-place replacement of one pix. 00809 * (2) The previous pix at that location is destroyed. 00810 */ 00811 l_int32 00812 pixaReplacePix(PIXA *pixa, 00813 l_int32 index, 00814 PIX *pix, 00815 BOX *box) 00816 { 00817 BOXA *boxa; 00818 00819 PROCNAME("pixaReplacePix"); 00820 00821 if (!pixa) 00822 return ERROR_INT("pixa not defined", procName, 1); 00823 if (index < 0 || index >= pixa->n) 00824 return ERROR_INT("index not valid", procName, 1); 00825 if (!pix) 00826 return ERROR_INT("pix not defined", procName, 1); 00827 00828 pixDestroy(&(pixa->pix[index])); 00829 pixa->pix[index] = pix; 00830 00831 if (box) { 00832 boxa = pixa->boxa; 00833 if (index > boxa->n) 00834 return ERROR_INT("boxa index not valid", procName, 1); 00835 boxaReplaceBox(boxa, index, box); 00836 } 00837 00838 return 0; 00839 } 00840 00841 00842 /*! 00843 * pixaInsertPix() 00844 * 00845 * Input: pixa 00846 * index (at which pix is to be inserted) 00847 * pixs (new pix to be inserted) 00848 * box (<optional> new box to be inserted) 00849 * Return: 0 if OK, 1 on error 00850 * 00851 * Notes: 00852 * (1) This shifts pixa[i] --> pixa[i + 1] for all i >= index, 00853 * and then inserts at pixa[index]. 00854 * (2) To insert at the beginning of the array, set index = 0. 00855 * (3) It should not be used repeatedly on large arrays, 00856 * because the function is O(n). 00857 * (4) To append a pix to a pixa, it's easier to use pixaAddPix(). 00858 */ 00859 l_int32 00860 pixaInsertPix(PIXA *pixa, 00861 l_int32 index, 00862 PIX *pixs, 00863 BOX *box) 00864 { 00865 l_int32 i, n; 00866 00867 PROCNAME("pixaInsertPix"); 00868 00869 if (!pixa) 00870 return ERROR_INT("pixa not defined", procName, 1); 00871 n = pixaGetCount(pixa); 00872 if (index < 0 || index > n) 00873 return ERROR_INT("index not in {0...n}", procName, 1); 00874 if (!pixs) 00875 return ERROR_INT("pixs not defined", procName, 1); 00876 00877 if (n >= pixa->nalloc) { /* extend both ptr arrays */ 00878 pixaExtendArray(pixa); 00879 boxaExtendArray(pixa->boxa); 00880 } 00881 pixa->n++; 00882 for (i = n; i > index; i--) 00883 pixa->pix[i] = pixa->pix[i - 1]; 00884 pixa->pix[index] = pixs; 00885 00886 /* Optionally, insert the box */ 00887 if (box) 00888 boxaInsertBox(pixa->boxa, index, box); 00889 00890 return 0; 00891 } 00892 00893 00894 /*! 00895 * pixaRemovePix() 00896 * 00897 * Input: pixa 00898 * index (of pix to be removed) 00899 * Return: 0 if OK, 1 on error 00900 * 00901 * Notes: 00902 * (1) This shifts pixa[i] --> pixa[i - 1] for all i > index. 00903 * (2) It should not be used repeatedly on large arrays, 00904 * because the function is O(n). 00905 * (3) The corresponding box is removed as well, if it exists. 00906 */ 00907 l_int32 00908 pixaRemovePix(PIXA *pixa, 00909 l_int32 index) 00910 { 00911 l_int32 i, n, nbox; 00912 BOXA *boxa; 00913 PIX **array; 00914 00915 PROCNAME("pixaRemovePix"); 00916 00917 if (!pixa) 00918 return ERROR_INT("pixa not defined", procName, 1); 00919 n = pixaGetCount(pixa); 00920 if (index < 0 || index >= n) 00921 return ERROR_INT("index not in {0...n - 1}", procName, 1); 00922 00923 /* Remove the pix */ 00924 array = pixa->pix; 00925 pixDestroy(&array[index]); 00926 for (i = index + 1; i < n; i++) 00927 array[i - 1] = array[i]; 00928 array[n - 1] = NULL; 00929 pixa->n--; 00930 00931 /* Remove the box if it exists */ 00932 boxa = pixa->boxa; 00933 nbox = boxaGetCount(boxa); 00934 if (index < nbox) 00935 boxaRemoveBox(boxa, index); 00936 00937 return 0; 00938 } 00939 00940 00941 /*! 00942 * pixaInitFull() 00943 * 00944 * Input: pixa (typically empty) 00945 * pix (to be replicated into the entire pixa ptr array) 00946 * box (<optional> to be replicated into the entire boxa ptr array) 00947 * Return: 0 if OK, 1 on error 00948 * 00949 * Notes: 00950 * (1) This initializes a pixa by filling up the entire pix ptr array 00951 * with copies of @pix. Any existing pix are destroyed. 00952 * It also fills the boxa with copies of @box. 00953 * After this oepration, the numbers of pix and boxes are equal to 00954 * the number of allocated ptrs. 00955 * (2) Note that we use pixaReplacePix() instead of pixaInsertPix(). 00956 * They both have the same effect when inserting into a NULL ptr 00957 * in the pixa ptr array: 00958 * (3) Example usage. This function is useful to prepare for a 00959 * random insertion (or replacement) of pix into a pixa. 00960 * To randomly insert pix into a pixa, up to some index "max": 00961 * Pixa *pixa = pixaCreate(max); 00962 * Pix *pix = pixCreate(1, 1, 1); // little memory 00963 * Box *box = boxCreate(...); 00964 * pixaInitFull(pixa, pix, box); 00965 * An existing pixa with a smaller ptr array can also be reused: 00966 * pixaExtendArrayToSize(pixa, max); 00967 * Pix *pix = pixCreate(...); 00968 * Box *box = boxCreate(...); 00969 * pixaInitFull(pixa, pix, box); 00970 * For these situations, the pix should be small and disposable. 00971 * The initialization allows the pixa to always be properly 00972 * filled, even if all pix (and boxes) are not later replaced. 00973 */ 00974 l_int32 00975 pixaInitFull(PIXA *pixa, 00976 PIX *pix, 00977 BOX *box) 00978 { 00979 l_int32 i, n; 00980 PIX *pixt; 00981 00982 PROCNAME("pixaInitFull"); 00983 00984 if (!pixa) 00985 return ERROR_INT("pixa not defined", procName, 1); 00986 if (!pix) 00987 return ERROR_INT("pix not defined", procName, 1); 00988 00989 n = pixa->nalloc; 00990 pixa->n = n; 00991 for (i = 0; i < n; i++) { 00992 pixt = pixCopy(NULL, pix); 00993 pixaReplacePix(pixa, i, pixt, NULL); 00994 } 00995 if (box) 00996 boxaInitFull(pixa->boxa, box); 00997 00998 return 0; 00999 } 01000 01001 01002 /*! 01003 * pixaClear() 01004 * 01005 * Input: pixa 01006 * Return: 0 if OK, 1 on error 01007 * 01008 * Notes: 01009 * (1) This destroys all pix in the pixa, as well as 01010 * all boxes in the boxa. The ptrs in the pix ptr array 01011 * are all null'd. The number of allocated pix, n, is set to 0. 01012 */ 01013 l_int32 01014 pixaClear(PIXA *pixa) 01015 { 01016 l_int32 i, n; 01017 01018 PROCNAME("pixaClear"); 01019 01020 if (!pixa) 01021 return ERROR_INT("pixa not defined", procName, 1); 01022 01023 n = pixaGetCount(pixa); 01024 for (i = 0; i < n; i++) 01025 pixDestroy(&pixa->pix[i]); 01026 pixa->n = 0; 01027 return boxaClear(pixa->boxa); 01028 } 01029 01030 01031 /*---------------------------------------------------------------------* 01032 * Pixa combination * 01033 *---------------------------------------------------------------------*/ 01034 /*! 01035 * pixaJoin() 01036 * 01037 * Input: pixad (dest pixa; add to this one) 01038 * pixas (source pixa; add from this one) 01039 * istart (starting index in nas) 01040 * iend (ending index in nas; use 0 to cat all) 01041 * Return: 0 if OK, 1 on error 01042 * 01043 * Notes: 01044 * (1) This appends a clone of each indicated pix in pixas to pixad 01045 * (2) istart < 0 is taken to mean 'read from the start' (istart = 0) 01046 * (3) iend <= 0 means 'read to the end' 01047 */ 01048 l_int32 01049 pixaJoin(PIXA *pixad, 01050 PIXA *pixas, 01051 l_int32 istart, 01052 l_int32 iend) 01053 { 01054 l_int32 ns, i; 01055 BOXA *boxas, *boxad; 01056 PIX *pix; 01057 01058 PROCNAME("pixaJoin"); 01059 01060 if (!pixad) 01061 return ERROR_INT("pixad not defined", procName, 1); 01062 if (!pixas) 01063 return ERROR_INT("pixas not defined", procName, 1); 01064 if ((ns = pixaGetCount(pixas)) == 0) { 01065 L_INFO("empty pixas", procName); 01066 return 0; 01067 } 01068 if (istart < 0) 01069 istart = 0; 01070 if (istart >= ns) 01071 return ERROR_INT("istart out of bounds", procName, 1); 01072 if (iend <= 0) 01073 iend = ns - 1; 01074 if (iend >= ns) 01075 return ERROR_INT("iend out of bounds", procName, 1); 01076 if (istart > iend) 01077 return ERROR_INT("istart > iend; nothing to add", procName, 1); 01078 01079 for (i = istart; i <= iend; i++) { 01080 pix = pixaGetPix(pixas, i, L_CLONE); 01081 pixaAddPix(pixad, pix, L_INSERT); 01082 } 01083 01084 boxas = pixaGetBoxa(pixas, L_CLONE); 01085 boxad = pixaGetBoxa(pixad, L_CLONE); 01086 boxaJoin(boxad, boxas, 0, 0); 01087 boxaDestroy(&boxas); /* just the clones */ 01088 boxaDestroy(&boxad); 01089 return 0; 01090 } 01091 01092 01093 /*---------------------------------------------------------------------* 01094 * Pixaa creation and destruction * 01095 *---------------------------------------------------------------------*/ 01096 /*! 01097 * pixaaCreate() 01098 * 01099 * Input: n (initial number of pixa ptrs) 01100 * Return: pixaa, or null on error 01101 * 01102 * Notes: 01103 * (1) A pixaa provides a 2-level hierarchy of images. 01104 * A common use is for segmentation masks, which are 01105 * inexpensive to store in png format. 01106 * (2) For example, suppose you want a mask for each textline 01107 * in a two-column page. The textline masks for each column 01108 * can be represented by a pixa, of which there are 2 in the pixaa. 01109 * The boxes for the textline mask components within a column 01110 * can have their origin referred to the column rather than the page. 01111 * Then the boxa field can be used to represent the two box (regions) 01112 * for the columns, and the (x,y) components of each box can 01113 * be used to get the absolute position of the textlines on 01114 * the page. 01115 */ 01116 PIXAA * 01117 pixaaCreate(l_int32 n) 01118 { 01119 PIXAA *pixaa; 01120 01121 PROCNAME("pixaaCreate"); 01122 01123 if (n <= 0) 01124 n = INITIAL_PTR_ARRAYSIZE; 01125 01126 if ((pixaa = (PIXAA *)CALLOC(1, sizeof(PIXAA))) == NULL) 01127 return (PIXAA *)ERROR_PTR("pixaa not made", procName, NULL); 01128 pixaa->n = 0; 01129 pixaa->nalloc = n; 01130 01131 if ((pixaa->pixa = (PIXA **)CALLOC(n, sizeof(PIXA *))) == NULL) 01132 return (PIXAA *)ERROR_PTR("pixa ptrs not made", procName, NULL); 01133 pixaa->boxa = boxaCreate(n); 01134 01135 return pixaa; 01136 } 01137 01138 01139 /*! 01140 * pixaaCreateFromPixa() 01141 * 01142 * Input: pixa 01143 * n (number specifying subdivision of pixa) 01144 * type (L_CHOOSE_CONSECUTIVE, L_CHOOSE_SKIP_BY) 01145 * copyflag (L_CLONE, L_COPY) 01146 * Return: pixaa, or null on error 01147 * 01148 * Notes: 01149 * (1) This subdivides a pixa into a set of smaller pixa that 01150 * are accumulated into a pixaa. 01151 * (2) If type == L_CHOOSE_CONSECUTIVE, the first 'n' pix are 01152 * put in a pixa and added to pixaa, then the next 'n', etc. 01153 * If type == L_CHOOSE_SKIP_BY, the first pixa is made by 01154 * aggregating pix[0], pix[n], pix[2*n], etc. 01155 * (3) The copyflag specifies if each new pix is a copy or a clone. 01156 */ 01157 PIXAA * 01158 pixaaCreateFromPixa(PIXA *pixa, 01159 l_int32 n, 01160 l_int32 type, 01161 l_int32 copyflag) 01162 { 01163 l_int32 count, i, j, npixa; 01164 PIX *pix; 01165 PIXA *pixat; 01166 PIXAA *pixaa; 01167 01168 PROCNAME("pixaaCreateFromPixa"); 01169 01170 if (!pixa) 01171 return (PIXAA *)ERROR_PTR("pixa not defined", procName, NULL); 01172 count = pixaGetCount(pixa); 01173 if (count == 0) 01174 return (PIXAA *)ERROR_PTR("no pix in pixa", procName, NULL); 01175 if (n <= 0) 01176 return (PIXAA *)ERROR_PTR("n must be > 0", procName, NULL); 01177 if (type != L_CHOOSE_CONSECUTIVE && type != L_CHOOSE_SKIP_BY) 01178 return (PIXAA *)ERROR_PTR("invalid type", procName, NULL); 01179 if (copyflag != L_CLONE && copyflag != L_COPY) 01180 return (PIXAA *)ERROR_PTR("invalid copyflag", procName, NULL); 01181 01182 if (type == L_CHOOSE_CONSECUTIVE) 01183 npixa = (count + n - 1) / n; 01184 else /* L_CHOOSE_SKIP_BY */ 01185 npixa = L_MIN(n, count); 01186 pixaa = pixaaCreate(npixa); 01187 if (type == L_CHOOSE_CONSECUTIVE) { 01188 for (i = 0; i < count; i++) { 01189 if (i % n == 0) 01190 pixat = pixaCreate(n); 01191 pix = pixaGetPix(pixa, i, copyflag); 01192 pixaAddPix(pixat, pix, L_INSERT); 01193 if (i % n == n - 1) 01194 pixaaAddPixa(pixaa, pixat, L_INSERT); 01195 } 01196 if (i % n != 0) 01197 pixaaAddPixa(pixaa, pixat, L_INSERT); 01198 } 01199 else { /* L_CHOOSE_SKIP_BY */ 01200 for (i = 0; i < npixa; i++) { 01201 pixat = pixaCreate(count / npixa + 1); 01202 for (j = i; j < count; j += n) { 01203 pix = pixaGetPix(pixa, j, copyflag); 01204 pixaAddPix(pixat, pix, L_INSERT); 01205 } 01206 pixaaAddPixa(pixaa, pixat, L_INSERT); 01207 } 01208 } 01209 01210 return pixaa; 01211 } 01212 01213 01214 /*! 01215 * pixaaDestroy() 01216 * 01217 * Input: &pixaa <to be nulled> 01218 * Return: void 01219 */ 01220 void 01221 pixaaDestroy(PIXAA **ppixaa) 01222 { 01223 l_int32 i; 01224 PIXAA *pixaa; 01225 01226 PROCNAME("pixaaDestroy"); 01227 01228 if (ppixaa == NULL) { 01229 L_WARNING("ptr address is NULL!", procName); 01230 return; 01231 } 01232 01233 if ((pixaa = *ppixaa) == NULL) 01234 return; 01235 01236 for (i = 0; i < pixaa->n; i++) 01237 pixaDestroy(&pixaa->pixa[i]); 01238 FREE(pixaa->pixa); 01239 boxaDestroy(&pixaa->boxa); 01240 01241 FREE(pixaa); 01242 *ppixaa = NULL; 01243 01244 return; 01245 } 01246 01247 01248 /*---------------------------------------------------------------------* 01249 * Pixaa addition * 01250 *---------------------------------------------------------------------*/ 01251 /*! 01252 * pixaaAddPixa() 01253 * 01254 * Input: pixaa 01255 * pixa (to be added) 01256 * copyflag: 01257 * L_INSERT inserts the pixa directly 01258 * L_COPY makes a new pixa and copies each pix and each box 01259 * L_CLONE gives a new handle to the input pixa 01260 * L_COPY_CLONE makes a new pixa and inserts clones of 01261 * all pix and boxes 01262 * Return: 0 if OK; 1 on error 01263 */ 01264 l_int32 01265 pixaaAddPixa(PIXAA *pixaa, 01266 PIXA *pixa, 01267 l_int32 copyflag) 01268 { 01269 l_int32 n; 01270 PIXA *pixac; 01271 01272 PROCNAME("pixaaAddPixa"); 01273 01274 if (!pixaa) 01275 return ERROR_INT("pixaa not defined", procName, 1); 01276 if (!pixa) 01277 return ERROR_INT("pixa not defined", procName, 1); 01278 if (copyflag != L_INSERT && copyflag != L_COPY && 01279 copyflag != L_CLONE && copyflag != L_COPY_CLONE) 01280 return ERROR_INT("invalid copyflag", procName, 1); 01281 01282 if (copyflag == L_INSERT) 01283 pixac = pixa; 01284 else { 01285 if ((pixac = pixaCopy(pixa, copyflag)) == NULL) 01286 return ERROR_INT("pixac not made", procName, 1); 01287 } 01288 01289 n = pixaaGetCount(pixaa); 01290 if (n >= pixaa->nalloc) 01291 pixaaExtendArray(pixaa); 01292 pixaa->pixa[n] = pixac; 01293 pixaa->n++; 01294 01295 return 0; 01296 } 01297 01298 01299 /*! 01300 * pixaaExtendArray() 01301 * 01302 * Input: pixaa 01303 * Return: 0 if OK; 1 on error 01304 */ 01305 l_int32 01306 pixaaExtendArray(PIXAA *pixaa) 01307 { 01308 PROCNAME("pixaaExtendArray"); 01309 01310 if (!pixaa) 01311 return ERROR_INT("pixaa not defined", procName, 1); 01312 01313 if ((pixaa->pixa = (PIXA **)reallocNew((void **)&pixaa->pixa, 01314 sizeof(PIXA *) * pixaa->nalloc, 01315 2 * sizeof(PIXA *) * pixaa->nalloc)) == NULL) 01316 return ERROR_INT("new ptr array not returned", procName, 1); 01317 01318 pixaa->nalloc = 2 * pixaa->nalloc; 01319 return 0; 01320 } 01321 01322 01323 /*! 01324 * pixaaAddBox() 01325 * 01326 * Input: pixaa 01327 * box 01328 * copyflag (L_INSERT, L_COPY, L_CLONE) 01329 * Return: 0 if OK, 1 on error 01330 * 01331 * Notes: 01332 * (1) The box can be used, for example, to hold the support region 01333 * of a pixa that is being added to the pixaa. 01334 */ 01335 l_int32 01336 pixaaAddBox(PIXAA *pixaa, 01337 BOX *box, 01338 l_int32 copyflag) 01339 { 01340 PROCNAME("pixaaAddBox"); 01341 01342 if (!pixaa) 01343 return ERROR_INT("pixaa not defined", procName, 1); 01344 if (!box) 01345 return ERROR_INT("box not defined", procName, 1); 01346 if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE) 01347 return ERROR_INT("invalid copyflag", procName, 1); 01348 01349 boxaAddBox(pixaa->boxa, box, copyflag); 01350 return 0; 01351 } 01352 01353 01354 01355 /*---------------------------------------------------------------------* 01356 * Pixaa accessors * 01357 *---------------------------------------------------------------------*/ 01358 /*! 01359 * pixaaGetCount() 01360 * 01361 * Input: pixaa 01362 * Return: count, or 0 if no pixaa 01363 */ 01364 l_int32 01365 pixaaGetCount(PIXAA *pixaa) 01366 { 01367 PROCNAME("pixaaGetCount"); 01368 01369 if (!pixaa) 01370 return ERROR_INT("pixaa not defined", procName, 0); 01371 01372 return pixaa->n; 01373 } 01374 01375 01376 /*! 01377 * pixaaGetPixa() 01378 * 01379 * Input: pixaa 01380 * index (to the index-th pixa) 01381 * accesstype (L_COPY, L_CLONE, L_COPY_CLONE) 01382 * Return: pixa, or null on error 01383 * 01384 * Notes: 01385 * (1) L_COPY makes a new pixa with a copy of every pix 01386 * (2) L_CLONE just makes a new reference to the pixa, 01387 * and bumps the counter. You would use this, for example, 01388 * when you need to extract some data from a pix within a 01389 * pixa within a pixaa. 01390 * (3) L_COPY_CLONE makes a new pixa with a clone of every pix 01391 * and box 01392 * (4) In all cases, you must invoke pixaDestroy() on the returned pixa 01393 */ 01394 PIXA * 01395 pixaaGetPixa(PIXAA *pixaa, 01396 l_int32 index, 01397 l_int32 accesstype) 01398 { 01399 PIXA *pixa; 01400 01401 PROCNAME("pixaaGetPixa"); 01402 01403 if (!pixaa) 01404 return (PIXA *)ERROR_PTR("pixaa not defined", procName, NULL); 01405 if (index < 0 || index >= pixaa->n) 01406 return (PIXA *)ERROR_PTR("index not valid", procName, NULL); 01407 if (accesstype != L_COPY && accesstype != L_CLONE && 01408 accesstype != L_COPY_CLONE) 01409 return (PIXA *)ERROR_PTR("invalid accesstype", procName, NULL); 01410 01411 if ((pixa = pixaa->pixa[index]) == NULL) /* shouldn't happen! */ 01412 return (PIXA *)ERROR_PTR("no pixa[index]", procName, NULL); 01413 return pixaCopy(pixa, accesstype); 01414 } 01415 01416 01417 /*! 01418 * pixaaGetBoxa() 01419 * 01420 * Input: pixaa 01421 * accesstype (L_COPY, L_CLONE) 01422 * Return: boxa, or null on error 01423 * 01424 * Notes: 01425 * (1) L_COPY returns a copy; L_CLONE returns a new reference to the boxa. 01426 * (2) In both cases, invoke boxaDestroy() on the returned boxa. 01427 */ 01428 BOXA * 01429 pixaaGetBoxa(PIXAA *pixaa, 01430 l_int32 accesstype) 01431 { 01432 PROCNAME("pixaaGetBoxa"); 01433 01434 if (!pixaa) 01435 return (BOXA *)ERROR_PTR("pixaa not defined", procName, NULL); 01436 if (accesstype != L_COPY && accesstype != L_CLONE) 01437 return (BOXA *)ERROR_PTR("invalid access type", procName, NULL); 01438 01439 return boxaCopy(pixaa->boxa, accesstype); 01440 } 01441 01442 01443 /*---------------------------------------------------------------------* 01444 * Pixa serialized I/O * 01445 *---------------------------------------------------------------------*/ 01446 #ifdef HAVE_CONFIG_H 01447 #include "config_auto.h" 01448 #endif /* HAVE_CONFIG_H */ 01449 01450 /*! 01451 * pixaRead() 01452 * 01453 * Input: filename 01454 * Return: pixa, or null on error 01455 * 01456 * Notes: 01457 * (1) The pix are stored in the file as png. 01458 * If the png library is not linked, this will fail. 01459 */ 01460 PIXA * 01461 pixaRead(const char *filename) 01462 { 01463 FILE *fp; 01464 PIXA *pixa; 01465 01466 PROCNAME("pixaRead"); 01467 01468 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */ 01469 return (PIXA *)ERROR_PTR("no libpng: can't read data", procName, NULL); 01470 #endif /* !HAVE_LIBPNG */ 01471 01472 if (!filename) 01473 return (PIXA *)ERROR_PTR("filename not defined", procName, NULL); 01474 if ((fp = fopenReadStream(filename)) == NULL) 01475 return (PIXA *)ERROR_PTR("stream not opened", procName, NULL); 01476 01477 if ((pixa = pixaReadStream(fp)) == NULL) { 01478 fclose(fp); 01479 return (PIXA *)ERROR_PTR("pixa not read", procName, NULL); 01480 } 01481 01482 fclose(fp); 01483 return pixa; 01484 } 01485 01486 01487 /*! 01488 * pixaReadStream() 01489 * 01490 * Input: stream 01491 * Return: pixa, or null on error 01492 * 01493 * Notes: 01494 * (1) The pix are stored in the file as png. 01495 * If the png library is not linked, this will fail. 01496 */ 01497 PIXA * 01498 pixaReadStream(FILE *fp) 01499 { 01500 l_int32 n, i, xres, yres, version; 01501 l_int32 ignore; 01502 BOXA *boxa; 01503 PIX *pix; 01504 PIXA *pixa; 01505 01506 PROCNAME("pixaReadStream"); 01507 01508 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */ 01509 return (PIXA *)ERROR_PTR("no libpng: can't read data", procName, NULL); 01510 #endif /* !HAVE_LIBPNG */ 01511 01512 if (!fp) 01513 return (PIXA *)ERROR_PTR("stream not defined", procName, NULL); 01514 01515 if (fscanf(fp, "\nPixa Version %d\n", &version) != 1) 01516 return (PIXA *)ERROR_PTR("not a pixa file", procName, NULL); 01517 if (version != PIXA_VERSION_NUMBER) 01518 return (PIXA *)ERROR_PTR("invalid pixa version", procName, NULL); 01519 if (fscanf(fp, "Number of pix = %d\n", &n) != 1) 01520 return (PIXA *)ERROR_PTR("not a pixa file", procName, NULL); 01521 01522 if ((pixa = pixaCreate(n)) == NULL) 01523 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL); 01524 if ((boxa = boxaReadStream(fp)) == NULL) 01525 return (PIXA *)ERROR_PTR("boxa not made", procName, NULL); 01526 boxaDestroy(&pixa->boxa); 01527 pixa->boxa = boxa; 01528 01529 for (i = 0; i < n; i++) { 01530 if ((fscanf(fp, " pix[%d]: xres = %d, yres = %d\n", 01531 &ignore, &xres, &yres)) != 3) 01532 return (PIXA *)ERROR_PTR("res reading", procName, NULL); 01533 if ((pix = pixReadStreamPng(fp)) == NULL) { 01534 pixaDestroy(&pixa); 01535 return (PIXA *)ERROR_PTR("pix not read", procName, NULL); 01536 } 01537 pixSetXRes(pix, xres); 01538 pixSetYRes(pix, yres); 01539 pixaAddPix(pixa, pix, L_INSERT); 01540 } 01541 return pixa; 01542 } 01543 01544 01545 /*! 01546 * pixaWrite() 01547 * 01548 * Input: filename 01549 * pixa 01550 * Return: 0 if OK, 1 on error 01551 * 01552 * Notes: 01553 * (1) The pix are stored in the file as png. 01554 * If the png library is not linked, this will fail. 01555 */ 01556 l_int32 01557 pixaWrite(const char *filename, 01558 PIXA *pixa) 01559 { 01560 FILE *fp; 01561 01562 PROCNAME("pixaWrite"); 01563 01564 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */ 01565 return ERROR_INT("no libpng: can't write data", procName, 1); 01566 #endif /* !HAVE_LIBPNG */ 01567 01568 if (!filename) 01569 return ERROR_INT("filename not defined", procName, 1); 01570 if (!pixa) 01571 return ERROR_INT("pixa not defined", procName, 1); 01572 01573 if ((fp = fopen(filename, "wb")) == NULL) 01574 return ERROR_INT("stream not opened", procName, 1); 01575 if (pixaWriteStream(fp, pixa)) 01576 return ERROR_INT("pixa not written to stream", procName, 1); 01577 fclose(fp); 01578 return 0; 01579 } 01580 01581 01582 /*! 01583 * pixaWriteStream() 01584 * 01585 * Input: stream (opened for "wb") 01586 * pixa 01587 * Return: 0 if OK, 1 on error 01588 * 01589 * Notes: 01590 * (1) The pix are stored in the file as png. 01591 * If the png library is not linked, this will fail. 01592 */ 01593 l_int32 01594 pixaWriteStream(FILE *fp, 01595 PIXA *pixa) 01596 { 01597 l_int32 n, i; 01598 PIX *pix; 01599 01600 PROCNAME("pixaWriteStream"); 01601 01602 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */ 01603 return ERROR_INT("no libpng: can't write data", procName, 1); 01604 #endif /* !HAVE_LIBPNG */ 01605 01606 if (!fp) 01607 return ERROR_INT("stream not defined", procName, 1); 01608 if (!pixa) 01609 return ERROR_INT("pixa not defined", procName, 1); 01610 01611 n = pixaGetCount(pixa); 01612 fprintf(fp, "\nPixa Version %d\n", PIXA_VERSION_NUMBER); 01613 fprintf(fp, "Number of pix = %d\n", n); 01614 boxaWriteStream(fp, pixa->boxa); 01615 for (i = 0; i < n; i++) { 01616 if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) 01617 return ERROR_INT("pix not found", procName, 1); 01618 fprintf(fp, " pix[%d]: xres = %d, yres = %d\n", 01619 i, pix->xres, pix->yres); 01620 pixWriteStreamPng(fp, pix, 0.0); 01621 pixDestroy(&pix); 01622 } 01623 return 0; 01624 } 01625 01626 01627 /*---------------------------------------------------------------------* 01628 * Pixaa serialized I/O * 01629 *---------------------------------------------------------------------*/ 01630 /*! 01631 * pixaaRead() 01632 * 01633 * Input: filename 01634 * Return: pixaa, or null on error 01635 * 01636 * Notes: 01637 * (1) The pix are stored in the file as png. 01638 * If the png library is not linked, this will fail. 01639 */ 01640 PIXAA * 01641 pixaaRead(const char *filename) 01642 { 01643 FILE *fp; 01644 PIXAA *pixaa; 01645 01646 PROCNAME("pixaaRead"); 01647 01648 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */ 01649 return (PIXAA *)ERROR_PTR("no libpng: can't read data", procName, NULL); 01650 #endif /* !HAVE_LIBPNG */ 01651 01652 if (!filename) 01653 return (PIXAA *)ERROR_PTR("filename not defined", procName, NULL); 01654 if ((fp = fopenReadStream(filename)) == NULL) 01655 return (PIXAA *)ERROR_PTR("stream not opened", procName, NULL); 01656 01657 if ((pixaa = pixaaReadStream(fp)) == NULL) { 01658 fclose(fp); 01659 return (PIXAA *)ERROR_PTR("pixaa not read", procName, NULL); 01660 } 01661 01662 fclose(fp); 01663 return pixaa; 01664 } 01665 01666 01667 /*! 01668 * pixaaReadStream() 01669 * 01670 * Input: stream 01671 * Return: pixaa, or null on error 01672 * 01673 * Notes: 01674 * (1) The pix are stored in the file as png. 01675 * If the png library is not linked, this will fail. 01676 */ 01677 PIXAA * 01678 pixaaReadStream(FILE *fp) 01679 { 01680 l_int32 n, i, version; 01681 l_int32 ignore; 01682 BOXA *boxa; 01683 PIXA *pixa; 01684 PIXAA *pixaa; 01685 01686 PROCNAME("pixaaReadStream"); 01687 01688 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */ 01689 return (PIXAA *)ERROR_PTR("no libpng: can't read data", procName, NULL); 01690 #endif /* !HAVE_LIBPNG */ 01691 01692 if (!fp) 01693 return (PIXAA *)ERROR_PTR("stream not defined", procName, NULL); 01694 01695 if (fscanf(fp, "\nPixaa Version %d\n", &version) != 1) 01696 return (PIXAA *)ERROR_PTR("not a pixaa file", procName, NULL); 01697 if (version != PIXAA_VERSION_NUMBER) 01698 return (PIXAA *)ERROR_PTR("invalid pixaa version", procName, NULL); 01699 if (fscanf(fp, "Number of pixa = %d\n", &n) != 1) 01700 return (PIXAA *)ERROR_PTR("not a pixaa file", procName, NULL); 01701 01702 if ((pixaa = pixaaCreate(n)) == NULL) 01703 return (PIXAA *)ERROR_PTR("pixaa not made", procName, NULL); 01704 if ((boxa = boxaReadStream(fp)) == NULL) 01705 return (PIXAA *)ERROR_PTR("boxa not made", procName, NULL); 01706 boxaDestroy(&pixaa->boxa); 01707 pixaa->boxa = boxa; 01708 01709 for (i = 0; i < n; i++) { 01710 if ((fscanf(fp, "\n\n --------------- pixa[%d] ---------------\n", 01711 &ignore)) != 1) { 01712 return (PIXAA *)ERROR_PTR("text reading", procName, NULL); 01713 } 01714 if ((pixa = pixaReadStream(fp)) == NULL) 01715 return (PIXAA *)ERROR_PTR("pixa not read", procName, NULL); 01716 pixaaAddPixa(pixaa, pixa, L_INSERT); 01717 } 01718 01719 return pixaa; 01720 } 01721 01722 01723 /*! 01724 * pixaaWrite() 01725 * 01726 * Input: filename 01727 * pixaa 01728 * Return: 0 if OK, 1 on error 01729 * 01730 * Notes: 01731 * (1) The pix are stored in the file as png. 01732 * If the png library is not linked, this will fail. 01733 */ 01734 l_int32 01735 pixaaWrite(const char *filename, 01736 PIXAA *pixaa) 01737 { 01738 FILE *fp; 01739 01740 PROCNAME("pixaaWrite"); 01741 01742 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */ 01743 return ERROR_INT("no libpng: can't read data", procName, 1); 01744 #endif /* !HAVE_LIBPNG */ 01745 01746 if (!filename) 01747 return ERROR_INT("filename not defined", procName, 1); 01748 if (!pixaa) 01749 return ERROR_INT("pixaa not defined", procName, 1); 01750 01751 if ((fp = fopen(filename, "wb")) == NULL) 01752 return ERROR_INT("stream not opened", procName, 1); 01753 if (pixaaWriteStream(fp, pixaa)) 01754 return ERROR_INT("pixaa not written to stream", procName, 1); 01755 fclose(fp); 01756 01757 return 0; 01758 } 01759 01760 01761 /*! 01762 * pixaaWriteStream() 01763 * 01764 * Input: stream (opened for "wb") 01765 * pixaa 01766 * Return: 0 if OK, 1 on error 01767 * 01768 * Notes: 01769 * (1) The pix are stored in the file as png. 01770 * If the png library is not linked, this will fail. 01771 */ 01772 l_int32 01773 pixaaWriteStream(FILE *fp, 01774 PIXAA *pixaa) 01775 { 01776 l_int32 n, i; 01777 PIXA *pixa; 01778 01779 PROCNAME("pixaaWriteStream"); 01780 01781 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */ 01782 return ERROR_INT("no libpng: can't read data", procName, 1); 01783 #endif /* !HAVE_LIBPNG */ 01784 01785 if (!fp) 01786 return ERROR_INT("stream not defined", procName, 1); 01787 if (!pixaa) 01788 return ERROR_INT("pixaa not defined", procName, 1); 01789 01790 n = pixaaGetCount(pixaa); 01791 fprintf(fp, "\nPixaa Version %d\n", PIXAA_VERSION_NUMBER); 01792 fprintf(fp, "Number of pixa = %d\n", n); 01793 boxaWriteStream(fp, pixaa->boxa); 01794 for (i = 0; i < n; i++) { 01795 if ((pixa = pixaaGetPixa(pixaa, i, L_CLONE)) == NULL) 01796 return ERROR_INT("pixa not found", procName, 1); 01797 fprintf(fp, "\n\n --------------- pixa[%d] ---------------\n", i); 01798 pixaWriteStream(fp, pixa); 01799 pixaDestroy(&pixa); 01800 } 01801 return 0; 01802 } 01803 01804