Leptonica 1.68
C Image Processing Library

pixabasic.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  *   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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines