Leptonica 1.68
C Image Processing Library

pixcomp.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  *   pixcomp.c
00018  *
00019  *      Pixcomp creation and destruction
00020  *           PIXC     *pixcompCreateFromPix()
00021  *           PIXC     *pixcompCreateFromString()
00022  *           PIXC     *pixcompCreateFromFile()
00023  *           void      pixcompDestroy()
00024 
00025  *      Pixcomp accessors
00026  *           l_int32   pixcompGetDimensions()
00027  *           l_int32   pixcompDetermineFormat()
00028  *
00029  *      Pixcomp conversion to Pix
00030  *           PIX      *pixCreateFromPixcomp()
00031  *
00032  *      Pixacomp creation and destruction
00033  *           PIXAC    *pixacompCreate()
00034  *           PIXAC    *pixacompCreateInitialized()
00035  *           PIXAC    *pixacompCreateFromPixa()
00036  *           PIXAC    *pixacompCreateFromFiles()
00037  *           PIXAC    *pixacompCreateFromSA()
00038  *           void      pixacompDestroy()
00039  *
00040  *      Pixacomp addition/replacement
00041  *           l_int32   pixacompAddPix()
00042  *           l_int32   pixacompAddPixcomp()
00043  *           l_int32   pixacompExtendArray()
00044  *           l_int32   pixacompReplacePix()
00045  *           l_int32   pixacompReplacePixcomp()
00046  *           l_int32   pixacompAddBox()
00047  *
00048  *      Pixacomp accessors
00049  *           l_int32   pixacompGetCount()
00050  *           PIXC     *pixacompGetPixcomp()
00051  *           PIX      *pixacompGetPix()
00052  *           l_int32   pixacompGetPixDimensions()
00053  *           BOXA     *pixacompGetBoxa()
00054  *           l_int32   pixacompGetBoxaCount()
00055  *           BOX      *pixacompGetBox()
00056  *           l_int32   pixacompGetBoxGeometry()
00057  *
00058  *      Pixacomp conversion to Pixa
00059  *           PIXA     *pixaCreateFromPixacomp()
00060  *
00061  *      Pixacomp serialized I/O
00062  *           PIXAC    *pixacompRead()
00063  *           PIXAC    *pixacompReadStream()
00064  *           l_int32   pixacompWrite()
00065  *           l_int32   pixacompWriteStream()
00066  *
00067  *      Output for debugging
00068  *           l_int32   pixacompWriteStreamInfo()
00069  *           l_int32   pixcompWriteStreamInfo()
00070  *           PIX      *pixacompDisplayTiledAndScaled()
00071  *
00072  *   The Pixacomp is an array of Pixcomp, where each Pixcomp is a compressed
00073  *   string of the image.  We don't use reference counting here.
00074  *   The basic application is to allow a large array of highly
00075  *   compressible images to reside in memory.  We purposely don't
00076  *   reuse the Pixa for this, to avoid confusion and programming errors.
00077  *
00078  *   Three compression formats are used: g4, png and jpeg.
00079  *   The compression type can be either specified or defaulted.
00080  *   If specified and it is not possible to compress (for example,
00081  *   you specify a jpeg on a 1 bpp image or one with a colormap),
00082  *   the compression type defaults to png.
00083  *
00084  *   The serialized version of the Pixacomp is similar to that for
00085  *   a Pixa, except that each Pixcomp can be compressed by one of
00086  *   tiffg4, png, or jpeg.  Unlike serialization of the Pixa,
00087  *   serialization of the Pixacomp does not require any imaging
00088  *   libraries because it simply reads and writes the compressed data.
00089  *
00090  *   For random insertion and replacement of pixcomp into a pixcomp,
00091  *   initialize a fully populated array using pixacompCreateInitialized().
00092  *   Then use pixacompReplacePix() or pixacompReplacePixcomp() for
00093  *   the random insertion.
00094  */
00095 
00096 #include <string.h>
00097 #include "allheaders.h"
00098 
00099 static const l_int32  INITIAL_PTR_ARRAYSIZE = 20;   /* n'import quoi */
00100 
00101     /* These two globals are defined in writefile.c */
00102 extern l_int32 NumImageFileFormatExtensions;
00103 extern const char *ImageFileFormatExtensions[];
00104 
00105 
00106 /*---------------------------------------------------------------------*
00107  *                  Pixcomp creation and destruction                   *
00108  *---------------------------------------------------------------------*/
00109 /*!
00110  *  pixcompCreateFromPix()
00111  *
00112  *      Input:  pix
00113  *              comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00114  *      Return: pixc, or null on error
00115  *
00116  *  Notes:
00117  *      (1) Use @comptype == IFF_DEFAULT to have the compression
00118  *          type automatically determined.
00119  */
00120 PIXC *
00121 pixcompCreateFromPix(PIX     *pix,
00122                      l_int32  comptype)
00123 {
00124 size_t    size;
00125 char     *text;
00126 l_int32   ret, format;
00127 l_uint8  *data;
00128 PIXC     *pixc;
00129 
00130     PROCNAME("pixcompCreateFromPix");
00131 
00132     if (!pix)
00133         return (PIXC *)ERROR_PTR("pix not defined", procName, NULL);
00134     if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 &&
00135         comptype != IFF_PNG && comptype != IFF_JFIF_JPEG)
00136         return (PIXC *)ERROR_PTR("invalid comptype", procName, NULL);
00137 
00138     if ((pixc = (PIXC *)CALLOC(1, sizeof(PIXC))) == NULL)
00139         return (PIXC *)ERROR_PTR("pixc not made", procName, NULL);
00140     pixGetDimensions(pix, &pixc->w, &pixc->h, &pixc->d);
00141     pixGetResolution(pix, &pixc->xres, &pixc->yres);
00142     if (pixGetColormap(pix))
00143         pixc->cmapflag = 1;
00144     if ((text = pixGetText(pix)) != NULL)
00145         pixc->text = stringNew(text);
00146 
00147     pixcompDetermineFormat(comptype, pixc->d, pixc->cmapflag, &format);
00148     pixc->comptype = format;
00149     ret = pixWriteMem(&data, &size, pix, format);
00150     if (ret) {
00151         L_ERROR("write to memory failed", procName);
00152         pixcompDestroy(&pixc);
00153         return NULL;
00154     }
00155     pixc->data = data;
00156     pixc->size = size;
00157 
00158     return pixc;
00159 }
00160 
00161 
00162 /*!
00163  *  pixcompCreateFromString()
00164  *
00165  *      Input:  data (compressed string)
00166  *              size (number of bytes)
00167  *              copyflag (L_INSERT or L_COPY)
00168  *      Return: pixc, or null on error
00169  *
00170  *  Notes:
00171  *      (1) This works when the compressed string is png, jpeg or tiffg4.
00172  *      (2) The copyflag determines if the data in the new Pixcomp is
00173  *          a copy of the input data.
00174  */
00175 PIXC *
00176 pixcompCreateFromString(l_uint8  *data,
00177                         size_t    size,
00178                         l_int32   copyflag)
00179 {
00180 l_int32  format, w, h, d, bps, spp, iscmap;
00181 PIXC    *pixc;
00182 
00183     PROCNAME("pixcompCreateFromString");
00184 
00185     if (!data)
00186         return (PIXC *)ERROR_PTR("data not defined", procName, NULL);
00187     if (copyflag != L_INSERT && copyflag != L_COPY)
00188         return (PIXC *)ERROR_PTR("invalid copyflag", procName, NULL);
00189 
00190     if (pixReadHeaderMem(data, size, &format, &w, &h, &bps, &spp, &iscmap) == 1)
00191         return (PIXC *)ERROR_PTR("header data not read", procName, NULL);
00192     if ((pixc = (PIXC *)CALLOC(1, sizeof(PIXC))) == NULL)
00193         return (PIXC *)ERROR_PTR("pixc not made", procName, NULL);
00194     d = (spp == 3) ? 32 : bps * spp;
00195     pixc->w = w;
00196     pixc->h = h;
00197     pixc->d = d;
00198     pixc->comptype = format;
00199     pixc->cmapflag = iscmap;
00200     if (copyflag == L_INSERT)
00201         pixc->data = data;
00202     else
00203         pixc->data = l_binaryCopy(data, size);
00204     pixc->size = size;
00205     return pixc;
00206 }
00207 
00208 
00209 /*!
00210  *  pixcompCreateFromFile()
00211  *
00212  *      Input:  filename
00213  *              comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00214  *      Return: pixc, or null on error
00215  *
00216  *  Notes:
00217  *      (1) Use @comptype == IFF_DEFAULT to have the compression
00218  *          type automatically determined.
00219  *      (2) If the comptype is invalid for this file, the default will
00220  *          be substituted.
00221  */
00222 PIXC *
00223 pixcompCreateFromFile(const char  *filename,
00224                       l_int32      comptype)
00225 {
00226 l_int32   format;
00227 size_t    nbytes;
00228 l_uint8  *data;
00229 PIX      *pix;
00230 PIXC     *pixc;
00231 
00232     PROCNAME("pixcompCreateFromFile");
00233 
00234     if (!filename)
00235         return (PIXC *)ERROR_PTR("filename not defined", procName, NULL);
00236     if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 &&
00237         comptype != IFF_PNG && comptype != IFF_JFIF_JPEG)
00238         return (PIXC *)ERROR_PTR("invalid comptype", procName, NULL);
00239 
00240     findFileFormat(filename, &format);
00241     if (format == IFF_UNKNOWN)
00242         return (PIXC *)ERROR_PTR("image file not readable", procName, NULL);
00243 
00244         /* Can we accept the encoded file directly?  Remember that
00245          * png is the "universal" compression type, so if requested
00246          * it takes precedence.  Otherwise, if the file is already
00247          * compressed in g4 or jpeg, just accept the string. */
00248     if ((format == IFF_TIFF_G4 && comptype != IFF_PNG) ||
00249         (format == IFF_JFIF_JPEG && comptype != IFF_PNG))
00250         comptype = format;
00251     if (comptype != IFF_DEFAULT && comptype == format) { 
00252         data = l_binaryRead(filename, &nbytes);
00253         if ((pixc = pixcompCreateFromString(data, nbytes, L_INSERT)) == NULL) {
00254             FREE(data);
00255             return (PIXC *)ERROR_PTR("pixc not made (string)", procName, NULL);
00256         }
00257         return pixc;
00258     }
00259 
00260         /* Need to recompress in the default format */
00261     if ((pix = pixRead(filename)) == NULL)
00262         return (PIXC *)ERROR_PTR("pix not read", procName, NULL);
00263     if ((pixc = pixcompCreateFromPix(pix, comptype)) == NULL) {
00264         pixDestroy(&pix);
00265         return (PIXC *)ERROR_PTR("pixc not made", procName, NULL);
00266     }
00267     pixDestroy(&pix);
00268     return pixc;
00269 }
00270 
00271 
00272 /*!
00273  *  pixcompDestroy()
00274  *
00275  *      Input:  &pixc <will be nulled>
00276  *      Return: void
00277  *
00278  *  Notes:
00279  *      (1) Always nulls the input ptr.
00280  */
00281 void
00282 pixcompDestroy(PIXC  **ppixc)
00283 {
00284 PIXC  *pixc;
00285 
00286     PROCNAME("pixcompDestroy");
00287 
00288     if (!ppixc) {
00289         L_WARNING("ptr address is null!", procName);
00290         return;
00291     }
00292 
00293     if ((pixc = *ppixc) == NULL)
00294         return;
00295 
00296     FREE(pixc->data);
00297     if (pixc->text)
00298         FREE(pixc->text);
00299     FREE(pixc);
00300     *ppixc = NULL;
00301     return;
00302 }
00303 
00304 
00305 /*---------------------------------------------------------------------*
00306  *                           Pixcomp accessors                         *
00307  *---------------------------------------------------------------------*/
00308 /*!
00309  *  pixcompGetDimensions()
00310  *
00311  *      Input:  pixc
00312  *              &w, &h, &d (<optional return>)
00313  *      Return: 0 if OK, 1 on error
00314  */
00315 l_int32
00316 pixcompGetDimensions(PIXC     *pixc,
00317                      l_int32  *pw,
00318                      l_int32  *ph,
00319                      l_int32  *pd)
00320 {
00321     PROCNAME("pixcompGetDimensions");
00322 
00323     if (!pixc)
00324         return ERROR_INT("pixc not defined", procName, 1);
00325     if (pw) *pw = pixc->w;
00326     if (ph) *ph = pixc->h;
00327     if (pd) *pd = pixc->d;
00328     return 0;
00329 }
00330 
00331 
00332 /*!
00333  *  pixcompDetermineFormat()
00334  *
00335  *      Input:  comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00336  *              d (pix depth)
00337  *              cmapflag (1 if pix to be compressed as a colormap; 0 otherwise)
00338  *              &format (return IFF_TIFF, IFF_PNG or IFF_JFIF_JPEG)
00339  *      Return: 0 if OK; 1 on error
00340  *
00341  *  Notes:
00342  *      (1) This determines the best format for a pix, given both
00343  *          the request (@comptype) and the image characteristics.
00344  *      (2) If @comptype == IFF_DEFAULT, this does not necessarily result
00345  *          in png encoding.  Instead, it returns one of the three formats
00346  *          that is both valid and most likely to give best compression.
00347  *      (3) If the pix cannot be compressed by the input value of
00348  *          @comptype, this selects IFF_PNG, which can compress all pix.
00349  */
00350 l_int32
00351 pixcompDetermineFormat(l_int32   comptype,
00352                        l_int32   d,
00353                        l_int32   cmapflag,
00354                        l_int32  *pformat)
00355 {
00356 
00357     PROCNAME("pixcompDetermineFormat");
00358 
00359     if (!pformat)
00360         return ERROR_INT("&format not defined", procName, 1);
00361     *pformat = IFF_PNG;  /* init value and default */
00362     if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 &&
00363         comptype != IFF_PNG && comptype != IFF_JFIF_JPEG)
00364         return ERROR_INT("invalid comptype", procName, 1);
00365 
00366     if (comptype == IFF_DEFAULT) {
00367         if (d == 1)
00368             *pformat = IFF_TIFF_G4;
00369         else if (d == 16)
00370             *pformat = IFF_PNG;
00371         else if (d >= 8 && !cmapflag)
00372             *pformat = IFF_JFIF_JPEG;
00373     }
00374     else if (comptype == IFF_TIFF_G4 && d == 1)
00375         *pformat = IFF_TIFF_G4;
00376     else if (comptype == IFF_JFIF_JPEG && d >= 8 && !cmapflag)
00377         *pformat = IFF_JFIF_JPEG;
00378 
00379     return 0;
00380 }
00381 
00382 
00383 /*---------------------------------------------------------------------*
00384  *                      Pixcomp conversion to Pix                      *
00385  *---------------------------------------------------------------------*/
00386 /*!
00387  *  pixCreateFromPixcomp()
00388  *
00389  *      Input:  pixc
00390  *      Return: pix, or null on error
00391  */
00392 PIX *
00393 pixCreateFromPixcomp(PIXC  *pixc)
00394 {
00395 l_int32  w, h, d, cmapinpix, format;
00396 PIX     *pix;
00397 
00398     PROCNAME("pixCreateFromPixcomp");
00399 
00400     if (!pixc)
00401         return (PIX *)ERROR_PTR("pixc not defined", procName, NULL);
00402 
00403     if ((pix = pixReadMem(pixc->data, pixc->size)) == NULL)
00404         return (PIX *)ERROR_PTR("pix not read", procName, NULL);
00405     pixSetResolution(pix, pixc->xres, pixc->yres);
00406     if (pixc->text)
00407         pixSetText(pix, pixc->text);
00408 
00409         /* Check fields for consistency */
00410     pixGetDimensions(pix, &w, &h, &d);
00411     if (pixc->w != w) {
00412         L_INFO_INT2("pix width %d != pixc width %d", procName, w, pixc->w);
00413         L_ERROR_INT("pix width %d != pixc width", procName, w);
00414     }
00415     if (pixc->h != h)
00416         L_ERROR_INT("pix height %d != pixc height", procName, h);
00417     if (pixc->d != d) {
00418         if (pixc->d == 16)  /* we strip 16 --> 8 bpp by default */
00419             L_WARNING_INT("pix depth %d != pixc depth 16", procName, d);
00420         else
00421             L_ERROR_INT("pix depth %d != pixc depth", procName, d);
00422     }
00423     cmapinpix = (pixGetColormap(pix) != NULL);
00424     if ((cmapinpix && !pixc->cmapflag) || (!cmapinpix && pixc->cmapflag))
00425         L_ERROR("pix cmap flag inconsistent", procName);
00426     format = pixGetInputFormat(pix);
00427     if (format != pixc->comptype) {
00428         L_ERROR_INT("pix comptype %d not equal to pixc comptype",
00429                     procName, format);
00430     }
00431     
00432     return pix;
00433 }
00434  
00435 
00436 
00437 /*---------------------------------------------------------------------*
00438  *                Pixacomp creation and destruction                    *
00439  *---------------------------------------------------------------------*/
00440 /*!
00441  *  pixacompCreate()
00442  *
00443  *      Input:  n  (initial number of ptrs)
00444  *      Return: pixac, or null on error
00445  */
00446 PIXAC *
00447 pixacompCreate(l_int32  n)
00448 {
00449 PIXAC  *pixac;
00450 
00451     PROCNAME("pixacompCreate");
00452 
00453     if (n <= 0)
00454         n = INITIAL_PTR_ARRAYSIZE;
00455 
00456     if ((pixac = (PIXAC *)CALLOC(1, sizeof(PIXAC))) == NULL)
00457         return (PIXAC *)ERROR_PTR("pixac not made", procName, NULL);
00458     pixac->n = 0;
00459     pixac->nalloc = n;
00460     
00461     if ((pixac->pixc = (PIXC **)CALLOC(n, sizeof(PIXC *))) == NULL)
00462         return (PIXAC *)ERROR_PTR("pixc ptrs not made", procName, NULL);
00463     if ((pixac->boxa = boxaCreate(n)) == NULL)
00464         return (PIXAC *)ERROR_PTR("boxa not made", procName, NULL);
00465 
00466     return pixac;
00467 }
00468 
00469 
00470 /*!
00471  *  pixacompCreateInitialized()
00472  *
00473  *      Input:  n  (initial number of ptrs)
00474  *              pix (initialize each ptr in pixacomp to this pix)
00475  *              comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00476  *      Return: pixac, or null on error
00477  *
00478  *  Notes:
00479  *      (1) Initializes a pixacomp to be fully populated with @pix.
00480  *      (2) Typically use a very small @pix (w = h = 1) with
00481  *          @comptype == IFF_TIFF_G4 for the initialization.
00482  *      (3) Example usage:
00483  *            Pix *pix = pixCreate(1, 1, 1);
00484  *            Pixacomp *pixac = pixacompCreateInitialized(50, pix, IFF_TIFF_G4);
00485  *            for (i = 0; i < 50; i++) {
00486  *                Pix *pixt = ...
00487  *                if (pixt)
00488  *                    pixacompReplacePix(pixac, i, pixt, IFF_TIFF_G4);
00489  *                pixDestroy(&pixt);
00490  *            }
00491  *          The result is a fully populated pixac with selected pixt
00492  *          replacing the placeholders.
00493  */
00494 PIXAC *
00495 pixacompCreateInitialized(l_int32  n,
00496                           PIX     *pix,
00497                           l_int32  comptype)
00498 {
00499 l_int32  i;
00500 PIXC    *pixc;
00501 PIXAC   *pixac;
00502 
00503     PROCNAME("pixacompCreateInitialized");
00504 
00505     if (n <= 0)
00506         return (PIXAC *)ERROR_PTR("n must be > 0", procName, NULL);
00507     if (!pix)
00508         return (PIXAC *)ERROR_PTR("pix not defined", procName, NULL);
00509 
00510     if ((pixac = pixacompCreate(n)) == NULL)
00511         return (PIXAC *)ERROR_PTR("pixac not made", procName, NULL);
00512     for (i = 0; i < n; i++) {
00513         pixc = pixcompCreateFromPix(pix, comptype);
00514         pixacompAddPixcomp(pixac, pixc);
00515     }
00516 
00517     return pixac;
00518 }
00519 
00520 
00521 /*!
00522  *  pixacompCreateFromPixa()
00523  *
00524  *      Input:  pixa
00525  *              comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00526  *              accesstype (L_COPY, L_CLONE, L_COPY_CLONE; for boxa)
00527  *      Return: 0 if OK, 1 on error
00528  *
00529  *  Notes:
00530  *      (1) If @format == IFF_DEFAULT, the conversion format for each
00531  *          image is chosen automatically.  Otherwise, we use the
00532  *          specified format unless it can't be done (e.g., jpeg
00533  *          for a 1, 2 or 4 bpp pix, or a pix with a colormap),
00534  *          in which case we use the default (assumed best) compression.
00535  */
00536 PIXAC *
00537 pixacompCreateFromPixa(PIXA    *pixa,
00538                        l_int32  comptype,
00539                        l_int32  accesstype)
00540 {
00541 l_int32  i, n;
00542 BOXA    *boxa;
00543 PIX     *pix;
00544 PIXAC   *pixac;
00545 
00546     PROCNAME("pixacompCreateFromPixa");
00547 
00548     if (!pixa)
00549         return (PIXAC *)ERROR_PTR("pixa not defined", procName, NULL);
00550     if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 &&
00551         comptype != IFF_PNG && comptype != IFF_JFIF_JPEG)
00552         return (PIXAC *)ERROR_PTR("invalid comptype", procName, NULL);
00553     if (accesstype != L_COPY && accesstype != L_CLONE &&
00554         accesstype != L_COPY_CLONE)
00555         return (PIXAC *)ERROR_PTR("invalid accesstype", procName, NULL);
00556 
00557     n = pixaGetCount(pixa);
00558     if ((pixac = pixacompCreate(n)) == NULL)
00559         return (PIXAC *)ERROR_PTR("pixac not made", procName, NULL);
00560     for (i = 0; i < n; i++) {
00561         pix = pixaGetPix(pixa, i, L_CLONE);
00562         pixacompAddPix(pixac, pix, comptype);
00563         pixDestroy(&pix);
00564     }
00565     if ((boxa = pixaGetBoxa(pixa, accesstype)) != NULL) {
00566         if (pixac->boxa) {
00567             boxaDestroy(&pixac->boxa);
00568             pixac->boxa = boxa;
00569         }
00570     }
00571 
00572     return pixac;
00573 }
00574 
00575 
00576 /*!
00577  *  pixacompCreateFromFiles()
00578  *
00579  *      Input:  dirname
00580  *              substr (<optional> substring filter on filenames; can be null)
00581  *              comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00582  *      Return: pixac, or null on error
00583  *
00584  *  Notes:
00585  *      (1) @dirname is the full path for the directory.
00586  *      (2) @substr is the part of the file name (excluding
00587  *          the directory) that is to be matched.  All matching
00588  *          filenames are read into the Pixa.  If substr is NULL,
00589  *          all filenames are read into the Pixa.
00590  *      (3) Use @comptype == IFF_DEFAULT to have the compression
00591  *          type automatically determined for each file.
00592  *      (4) If the comptype is invalid for a file, the default will
00593  *          be substituted.
00594  */
00595 PIXAC *
00596 pixacompCreateFromFiles(const char  *dirname,
00597                         const char  *substr,
00598                         l_int32      comptype)
00599 {
00600 PIXAC    *pixac;
00601 SARRAY   *sa;
00602 
00603     PROCNAME("pixacompCreateFromFiles");
00604 
00605     if (!dirname)
00606         return (PIXAC *)ERROR_PTR("dirname not defined", procName, NULL);
00607     if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 &&
00608         comptype != IFF_PNG && comptype != IFF_JFIF_JPEG)
00609         return (PIXAC *)ERROR_PTR("invalid comptype", procName, NULL);
00610 
00611     if ((sa = getSortedPathnamesInDirectory(dirname, substr, 0, 0)) == NULL)
00612         return (PIXAC *)ERROR_PTR("sa not made", procName, NULL);
00613     pixac = pixacompCreateFromSA(sa, comptype);
00614     sarrayDestroy(&sa);
00615     return pixac;
00616 }
00617 
00618 
00619 /*!
00620  *  pixacompCreateFromSA()
00621  *
00622  *      Input:  sarray (full pathnames for all files)
00623  *              comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00624  *      Return: pixac, or null on error
00625  *
00626  *  Notes:
00627  *      (1) Use @comptype == IFF_DEFAULT to have the compression
00628  *          type automatically determined for each file.
00629  *      (2) If the comptype is invalid for a file, the default will
00630  *          be substituted.
00631  */
00632 PIXAC *
00633 pixacompCreateFromSA(SARRAY  *sa,
00634                      l_int32  comptype)
00635 {
00636 char     *str;
00637 l_int32   i, n;
00638 PIXC     *pixc;
00639 PIXAC    *pixac;
00640 
00641     PROCNAME("pixacompCreateFromSA");
00642 
00643     if (!sa)
00644         return (PIXAC *)ERROR_PTR("sarray not defined", procName, NULL);
00645     if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 &&
00646         comptype != IFF_PNG && comptype != IFF_JFIF_JPEG)
00647         return (PIXAC *)ERROR_PTR("invalid comptype", procName, NULL);
00648 
00649     n = sarrayGetCount(sa);
00650     pixac = pixacompCreate(n);
00651     for (i = 0; i < n; i++) {
00652         str = sarrayGetString(sa, i, L_NOCOPY);
00653         if ((pixc = pixcompCreateFromFile(str, comptype)) == NULL) {
00654             L_WARNING_STRING("pixc not read from file %s", procName, str);
00655             continue;
00656         }
00657         pixacompAddPixcomp(pixac, pixc);
00658     }
00659     return pixac;
00660 }
00661 
00662 
00663 /*!
00664  *  pixacompDestroy()
00665  *
00666  *      Input:  &pixac (<to be nulled>)
00667  *      Return: void
00668  *
00669  *  Notes:
00670  *      (1) Always nulls the input ptr.
00671  */
00672 void
00673 pixacompDestroy(PIXAC  **ppixac)
00674 {
00675 l_int32  i;
00676 PIXAC   *pixac;
00677 
00678     PROCNAME("pixacompDestroy");
00679 
00680     if (ppixac == NULL) {
00681         L_WARNING("ptr address is NULL!", procName);
00682         return;
00683     }
00684 
00685     if ((pixac = *ppixac) == NULL)
00686         return;
00687 
00688     for (i = 0; i < pixac->n; i++)
00689         pixcompDestroy(&pixac->pixc[i]);
00690     FREE(pixac->pixc);
00691     boxaDestroy(&pixac->boxa);
00692     FREE(pixac);
00693 
00694     *ppixac = NULL;
00695     return;
00696 }
00697 
00698 
00699 /*---------------------------------------------------------------------*
00700  *                          Pixacomp addition                          *
00701  *---------------------------------------------------------------------*/
00702 /*!
00703  *  pixacompAddPix()
00704  *
00705  *      Input:  pixac
00706  *              pix  (to be added)
00707  *              comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00708  *      Return: 0 if OK; 1 on error
00709  */
00710 l_int32
00711 pixacompAddPix(PIXAC   *pixac,
00712                PIX     *pix,
00713                l_int32  comptype)
00714 {
00715 l_int32  cmapflag, format;
00716 PIXC    *pixc;
00717 
00718     PROCNAME("pixacompAddPix");
00719 
00720     if (!pixac)
00721         return ERROR_INT("pixac not defined", procName, 1);
00722     if (!pix)
00723         return ERROR_INT("pix not defined", procName, 1);
00724     if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 &&
00725         comptype != IFF_PNG && comptype != IFF_JFIF_JPEG)
00726         return ERROR_INT("invalid format", procName, 1);
00727 
00728     cmapflag = pixGetColormap(pix) ? 1 : 0;
00729     pixcompDetermineFormat(comptype, pixGetDepth(pix), cmapflag, &format);
00730     if ((pixc = pixcompCreateFromPix(pix, format)) == NULL)
00731         return ERROR_INT("pixc not made", procName, 1);
00732     pixacompAddPixcomp(pixac, pixc);
00733     return 0;
00734 }
00735 
00736 
00737 /*!
00738  *  pixacompAddPixcomp()
00739  *
00740  *      Input:  pixac
00741  *              pixc  (to be added by insertion)
00742  *      Return: 0 if OK; 1 on error
00743  */
00744 l_int32
00745 pixacompAddPixcomp(PIXAC  *pixac,
00746                    PIXC   *pixc)
00747 {
00748 l_int32  n;
00749 
00750     PROCNAME("pixacompAddPixcomp");
00751 
00752     if (!pixac)
00753         return ERROR_INT("pixac not defined", procName, 1);
00754     if (!pixc)
00755         return ERROR_INT("pixc not defined", procName, 1);
00756 
00757     n = pixac->n;
00758     if (n >= pixac->nalloc)
00759         pixacompExtendArray(pixac);
00760     pixac->pixc[n] = pixc;
00761     pixac->n++;
00762 
00763     return 0;
00764 }
00765 
00766 
00767 /*!
00768  *  pixacompExtendArray()
00769  *
00770  *      Input:  pixac
00771  *      Return: 0 if OK; 1 on error
00772  *
00773  *  Notes:
00774  *      (1) We extend the boxa array simultaneously.  This is
00775  *          necessary in case we are NOT adding boxes simultaneously
00776  *          with adding pixc.  We always want the sizes of the
00777  *          pixac and boxa ptr arrays to be equal.
00778  */
00779 l_int32
00780 pixacompExtendArray(PIXAC  *pixac)
00781 {
00782     PROCNAME("pixacompExtendArray");
00783 
00784     if (!pixac)
00785         return ERROR_INT("pixac not defined", procName, 1);
00786 
00787     if ((pixac->pixc = (PIXC **)reallocNew((void **)&pixac->pixc,
00788                             sizeof(PIXC *) * pixac->nalloc,
00789                             2 * sizeof(PIXC *) * pixac->nalloc)) == NULL)
00790         return ERROR_INT("new ptr array not returned", procName, 1);
00791     pixac->nalloc = 2 * pixac->nalloc;
00792     boxaExtendArray(pixac->boxa);
00793     return 0;
00794 }
00795 
00796 
00797 /*!
00798  *  pixacompReplacePix()
00799  *
00800  *      Input:  pixac
00801  *              index (of pixc within pixac to be replaced)
00802  *              pix  (owned by the caller)
00803  *              comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG)
00804  *      Return: 0 if OK; 1 on error
00805  *
00806  *  Notes:
00807  *      (1) The input @pix is converted to a pixc, which is then inserted
00808  *          into the pixac.
00809  */
00810 l_int32
00811 pixacompReplacePix(PIXAC   *pixac,
00812                    l_int32  index,
00813                    PIX     *pix,
00814                    l_int32  comptype)
00815 {
00816 l_int32  n;
00817 PIXC    *pixc;
00818 
00819     PROCNAME("pixacompReplacePix");
00820 
00821     if (!pixac)
00822         return ERROR_INT("pixac not defined", procName, 1);
00823     n = pixacompGetCount(pixac);
00824     if (index < 0 || index >= n)
00825         return ERROR_INT("array index out of bounds", procName, 1);
00826     if (!pix)
00827         return ERROR_INT("pix not defined", procName, 1);
00828     if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 &&
00829         comptype != IFF_PNG && comptype != IFF_JFIF_JPEG)
00830         return ERROR_INT("invalid format", procName, 1);
00831 
00832     pixc = pixcompCreateFromPix(pix, comptype);
00833     pixacompReplacePixcomp(pixac, index, pixc);
00834     return 0;
00835 }
00836 
00837 
00838 /*!
00839  *  pixacompReplacePixcomp()
00840  *
00841  *      Input:  pixac
00842  *              index (of pixc within pixac to be replaced)
00843  *              pixc  (to replace existing one, which is destroyed)
00844  *      Return: 0 if OK; 1 on error
00845  *
00846  *  Notes:
00847  *      (1) The inserted @pixc is now owned by the pixac.  The caller
00848  *          must not destroy it.
00849  */
00850 l_int32
00851 pixacompReplacePixcomp(PIXAC   *pixac,
00852                        l_int32  index,
00853                        PIXC    *pixc)
00854 {
00855 l_int32  n;
00856 PIXC    *pixct;
00857 
00858     PROCNAME("pixacompReplacePixcomp");
00859 
00860     if (!pixac)
00861         return ERROR_INT("pixac not defined", procName, 1);
00862     n = pixacompGetCount(pixac);
00863     if (index < 0 || index >= n)
00864         return ERROR_INT("array index out of bounds", procName, 1);
00865     if (!pixc)
00866         return ERROR_INT("pixc not defined", procName, 1);
00867 
00868     pixct = pixacompGetPixcomp(pixac, index);
00869     pixcompDestroy(&pixct);
00870     pixac->pixc[index] = pixc;  /* replace */
00871 
00872     return 0;
00873 }
00874 
00875 
00876 /*!
00877  *  pixacompAddBox()
00878  *
00879  *      Input:  pixac
00880  *              box
00881  *              copyflag (L_INSERT, L_COPY)
00882  *      Return: 0 if OK, 1 on error
00883  */
00884 l_int32
00885 pixacompAddBox(PIXAC   *pixac,
00886                BOX     *box,
00887                l_int32  copyflag)
00888 {
00889     PROCNAME("pixacompAddBox");
00890 
00891     if (!pixac)
00892         return ERROR_INT("pixac not defined", procName, 1);
00893     if (!box)
00894         return ERROR_INT("box not defined", procName, 1);
00895     if (copyflag != L_INSERT && copyflag != L_COPY)
00896         return ERROR_INT("invalid copyflag", procName, 1);
00897 
00898     boxaAddBox(pixac->boxa, box, copyflag);
00899     return 0;
00900 }
00901 
00902 
00903 /*---------------------------------------------------------------------*
00904  *                         Pixacomp accessors                          *
00905  *---------------------------------------------------------------------*/
00906 /*!
00907  *  pixacompGetCount()
00908  *
00909  *      Input:  pixac
00910  *      Return: count, or 0 if no pixa
00911  */
00912 l_int32
00913 pixacompGetCount(PIXAC  *pixac)
00914 {
00915     PROCNAME("pixacompGetCount");
00916 
00917     if (!pixac)
00918         return ERROR_INT("pixac not defined", procName, 0);
00919 
00920     return pixac->n;
00921 }
00922 
00923 
00924 /*!
00925  *  pixacompGetPixcomp()
00926  *
00927  *      Input:  pixac
00928  *              index  (to the index-th pix)
00929  *      Return: pixc, or null on error
00930  *
00931  *  Notes:
00932  *      (1) Important: this is just a ptr to the pixc owned by the pixac.
00933  *          Do not destroy unless you are replacing the pixc.
00934  */
00935 PIXC *
00936 pixacompGetPixcomp(PIXAC   *pixac,
00937                    l_int32  index)
00938 {
00939     PROCNAME("pixacompGetPixcomp");
00940 
00941     if (!pixac)
00942         return (PIXC *)ERROR_PTR("pixac not defined", procName, NULL);
00943     if (index < 0 || index >= pixac->n)
00944         return (PIXC *)ERROR_PTR("index not valid", procName, NULL);
00945 
00946     return pixac->pixc[index];
00947 }
00948 
00949 
00950 /*!
00951  *  pixacompGetPix()
00952  *
00953  *      Input:  pixac
00954  *              index  (to the index-th pix)
00955  *      Return: pix, or null on error
00956  */
00957 PIX *
00958 pixacompGetPix(PIXAC   *pixac,
00959                l_int32  index)
00960 {
00961 PIXC  *pixc;
00962 
00963     PROCNAME("pixacompGetPix");
00964 
00965     if (!pixac)
00966         return (PIX *)ERROR_PTR("pixac not defined", procName, NULL);
00967     if (index < 0 || index >= pixac->n)
00968         return (PIX *)ERROR_PTR("index not valid", procName, NULL);
00969 
00970     pixc = pixacompGetPixcomp(pixac, index);
00971     return pixCreateFromPixcomp(pixc);
00972 }
00973 
00974 
00975 /*!
00976  *  pixacompGetPixDimensions()
00977  *
00978  *      Input:  pixa
00979  *              index  (to the index-th box)
00980  *              &w, &h, &d (<optional return>; each can be null)
00981  *      Return: 0 if OK, 1 on error
00982  */
00983 l_int32
00984 pixacompGetPixDimensions(PIXAC    *pixac,
00985                          l_int32   index,
00986                          l_int32  *pw,
00987                          l_int32  *ph,
00988                          l_int32  *pd)
00989 {
00990 PIXC  *pixc;
00991 
00992     PROCNAME("pixacompGetPixDimensions");
00993 
00994     if (!pixac)
00995         return ERROR_INT("pixac not defined", procName, 1);
00996     if (index < 0 || index >= pixac->n)
00997         return ERROR_INT("index not valid", procName, 1);
00998 
00999     if ((pixc = pixac->pixc[index]) == NULL)
01000         return ERROR_INT("pixc not found!", procName, 1);
01001     pixcompGetDimensions(pixc, pw, ph, pd);
01002     return 0;
01003 }
01004 
01005 
01006 /*!
01007  *  pixacompGetBoxa()
01008  *
01009  *      Input:  pixac
01010  *              accesstype  (L_COPY, L_CLONE, L_COPY_CLONE)
01011  *      Return: boxa, or null on error
01012  */
01013 BOXA *
01014 pixacompGetBoxa(PIXAC   *pixac,
01015                 l_int32  accesstype)
01016 {
01017     PROCNAME("pixacompGetBoxa");
01018 
01019     if (!pixac)
01020         return (BOXA *)ERROR_PTR("pixac not defined", procName, NULL);
01021     if (!pixac->boxa)
01022         return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
01023     if (accesstype != L_COPY && accesstype != L_CLONE &&
01024         accesstype != L_COPY_CLONE)
01025         return (BOXA *)ERROR_PTR("invalid accesstype", procName, NULL);
01026 
01027     return boxaCopy(pixac->boxa, accesstype);
01028 }
01029 
01030 
01031 /*!
01032  *  pixacompGetBoxaCount()
01033  *
01034  *      Input:  pixac
01035  *      Return: count, or 0 on error
01036  */
01037 l_int32
01038 pixacompGetBoxaCount(PIXAC  *pixac)
01039 {
01040     PROCNAME("pixacompGetBoxaCount");
01041 
01042     if (!pixac)
01043         return ERROR_INT("pixac not defined", procName, 0);
01044     
01045     return boxaGetCount(pixac->boxa);
01046 }
01047 
01048 
01049 /*!
01050  *  pixacompGetBox()
01051  *
01052  *      Input:  pixac
01053  *              index  (to the index-th pix)
01054  *              accesstype  (L_COPY or L_CLONE)
01055  *      Return: box (if null, not automatically an error), or null on error
01056  *
01057  *  Notes:
01058  *      (1) There is always a boxa with a pixac, and it is initialized so
01059  *          that each box ptr is NULL.
01060  *      (2) In general, we expect that there is either a box associated
01061  *          with each pixc, or no boxes at all in the boxa.
01062  *      (3) Having no boxes is thus not an automatic error.  Whether it
01063  *          is an actual error is determined by the calling program.
01064  *          If the caller expects to get a box, it is an error; see, e.g.,
01065  *          pixacGetBoxGeometry().
01066  */
01067 BOX *
01068 pixacompGetBox(PIXAC    *pixac,
01069                l_int32   index,
01070                l_int32   accesstype)
01071 {
01072 BOX  *box;
01073 
01074     PROCNAME("pixacompGetBox");
01075 
01076     if (!pixac)
01077         return (BOX *)ERROR_PTR("pixac not defined", procName, NULL);
01078     if (!pixac->boxa)
01079         return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
01080     if (index < 0 || index >= pixac->boxa->n)
01081         return (BOX *)ERROR_PTR("index not valid", procName, NULL);
01082     if (accesstype != L_COPY && accesstype != L_CLONE)
01083         return (BOX *)ERROR_PTR("invalid accesstype", procName, NULL);
01084 
01085     box = pixac->boxa->box[index];
01086     if (box) {
01087         if (accesstype == L_COPY)
01088             return boxCopy(box);
01089         else  /* accesstype == L_CLONE */
01090             return boxClone(box);
01091     }
01092     else
01093         return NULL;
01094 }
01095 
01096 
01097 /*!
01098  *  pixacompGetBoxGeometry()
01099  *
01100  *      Input:  pixac
01101  *              index  (to the index-th box)
01102  *              &x, &y, &w, &h (<optional return>; each can be null)
01103  *      Return: 0 if OK, 1 on error
01104  */
01105 l_int32
01106 pixacompGetBoxGeometry(PIXAC     *pixac,
01107                        l_int32    index,
01108                        l_int32   *px,
01109                        l_int32   *py,
01110                        l_int32   *pw,
01111                        l_int32  *ph)
01112 {
01113 BOX  *box;
01114 
01115     PROCNAME("pixacompGetBoxGeometry");
01116 
01117     if (!pixac)
01118         return ERROR_INT("pixac not defined", procName, 1);
01119     if (index < 0 || index >= pixac->n)
01120         return ERROR_INT("index not valid", procName, 1);
01121 
01122     if ((box = pixacompGetBox(pixac, index, L_CLONE)) == NULL)
01123         return ERROR_INT("box not found!", procName, 1);
01124     boxGetGeometry(box, px, py, pw, ph);
01125     boxDestroy(&box);
01126     return 0;
01127 }
01128 
01129 
01130 /*---------------------------------------------------------------------*
01131  *                      Pixacomp conversion to Pixa                    *
01132  *---------------------------------------------------------------------*/
01133 /*!
01134  *  pixaCreateFromPixacomp()
01135  *
01136  *      Input:  pixac
01137  *              accesstype (L_COPY, L_CLONE, L_COPY_CLONE; for boxa)
01138  *      Return: pixa if OK, or null on error
01139  */
01140 PIXA *
01141 pixaCreateFromPixacomp(PIXAC   *pixac,
01142                        l_int32  accesstype)
01143 {
01144 l_int32  i, n;
01145 PIX     *pix;
01146 PIXA    *pixa;
01147 
01148     PROCNAME("pixaCreateFromPixacomp");
01149 
01150     if (!pixac)
01151         return (PIXA *)ERROR_PTR("pixac not defined", procName, NULL);
01152     if (accesstype != L_COPY && accesstype != L_CLONE &&
01153         accesstype != L_COPY_CLONE)
01154         return (PIXA *)ERROR_PTR("invalid accesstype", procName, NULL);
01155 
01156     n = pixacompGetCount(pixac);
01157     if ((pixa = pixaCreate(n)) == NULL)
01158         return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
01159     for (i = 0; i < n; i++) {
01160         if ((pix = pixacompGetPix(pixac, i)) == NULL) {
01161             L_WARNING_INT("pix %d not made", procName, i);
01162             continue;
01163         }
01164         pixaAddPix(pixa, pix, L_INSERT);
01165     }
01166     if (pixa->boxa) {
01167         boxaDestroy(&pixa->boxa);
01168         pixa->boxa = pixacompGetBoxa(pixac, accesstype);
01169     }
01170 
01171     return pixa;
01172 }
01173 
01174 
01175 /*---------------------------------------------------------------------*
01176  *                       Pixacomp serialized I/O                       *
01177  *---------------------------------------------------------------------*/
01178 /*!
01179  *  pixacompRead()
01180  *
01181  *      Input:  filename
01182  *      Return: pixac, or null on error
01183  *
01184  *  Notes:
01185  *      (1) Unlike the situation with serialized Pixa, where the image
01186  *          data is stored in png format, the Pixacomp image data
01187  *          can be stored in tiffg4, png and jpg formats.
01188  */
01189 PIXAC *
01190 pixacompRead(const char  *filename)
01191 {
01192 FILE   *fp;
01193 PIXAC  *pixac;
01194 
01195     PROCNAME("pixacompRead");
01196 
01197     if (!filename)
01198         return (PIXAC *)ERROR_PTR("filename not defined", procName, NULL);
01199     if ((fp = fopenReadStream(filename)) == NULL)
01200         return (PIXAC *)ERROR_PTR("stream not opened", procName, NULL);
01201 
01202     if ((pixac = pixacompReadStream(fp)) == NULL) {
01203         fclose(fp);
01204         return (PIXAC *)ERROR_PTR("pixac not read", procName, NULL);
01205     }
01206 
01207     fclose(fp);
01208     return pixac;
01209 }
01210 
01211 
01212 /*!
01213  *  pixacompReadStream()
01214  *
01215  *      Input:  stream
01216  *      Return: pixac, or null on error
01217  */
01218 PIXAC *
01219 pixacompReadStream(FILE  *fp)
01220 {
01221 l_uint8  *data;
01222 l_int32   n, i, w, h, d, ignore;
01223 l_int32   comptype, size, cmapflag, version, xres, yres;
01224 BOXA     *boxa;
01225 PIXC     *pixc;
01226 PIXAC    *pixac;
01227 
01228     PROCNAME("pixacompReadStream");
01229 
01230     if (!fp)
01231         return (PIXAC *)ERROR_PTR("stream not defined", procName, NULL);
01232 
01233     if (fscanf(fp, "\nPixacomp Version %d\n", &version) != 1)
01234         return (PIXAC *)ERROR_PTR("not a pixacomp file", procName, NULL);
01235     if (version != PIXACOMP_VERSION_NUMBER)
01236         return (PIXAC *)ERROR_PTR("invalid pixacomp version", procName, NULL);
01237     if (fscanf(fp, "Number of pixcomp = %d", &n) != 1)
01238         return (PIXAC *)ERROR_PTR("not a pixacomp file", procName, NULL);
01239 
01240     if ((pixac = pixacompCreate(n)) == NULL)
01241         return (PIXAC *)ERROR_PTR("pixac not made", procName, NULL);
01242     if ((boxa = boxaReadStream(fp)) == NULL)
01243         return (PIXAC *)ERROR_PTR("boxa not made", procName, NULL);
01244     boxaDestroy(&pixac->boxa);  /* empty */
01245     pixac->boxa = boxa;
01246 
01247     for (i = 0; i < n; i++) {
01248         if ((pixc = (PIXC *)CALLOC(1, sizeof(PIXC))) == NULL)
01249             return (PIXAC *)ERROR_PTR("pixc not made", procName, NULL);
01250         if (fscanf(fp, "  Pixcomp[%d]: w = %d, h = %d, d = %d\n",
01251                    &ignore, &w, &h, &d) != 4)
01252             return (PIXAC *)ERROR_PTR("size reading", procName, NULL);
01253         if (fscanf(fp, "    comptype = %d, size = %d, cmapflag = %d\n",
01254                    &comptype, &size, &cmapflag) != 3)
01255             return (PIXAC *)ERROR_PTR("comptype/size reading", procName, NULL);
01256         if (fscanf(fp, "    xres = %d, yres = %d\n", &xres, &yres) != 2)
01257             return (PIXAC *)ERROR_PTR("res reading", procName, NULL);
01258         if ((data = (l_uint8 *)CALLOC(1, size)) == NULL)
01259             return (PIXAC *)ERROR_PTR("calloc fail for data", procName, NULL);
01260         if (fread(data, 1, size, fp) != size)
01261             return (PIXAC *)ERROR_PTR("error reading data", procName, NULL);
01262         pixc->w = w;
01263         pixc->h = h;
01264         pixc->d = d;
01265         pixc->xres = xres;
01266         pixc->yres = yres;
01267         pixc->comptype = comptype;
01268         pixc->cmapflag = cmapflag;
01269         pixc->data = data;
01270         pixc->size = size;
01271         pixacompAddPixcomp(pixac, pixc);
01272     }
01273     return pixac;
01274 }
01275 
01276 
01277 /*!
01278  *  pixacompWrite()
01279  *
01280  *      Input:  filename
01281  *              pixac
01282  *      Return: 0 if OK, 1 on error
01283  *
01284  *  Notes:
01285  *      (1) Unlike the situation with serialized Pixa, where the image
01286  *          data is stored in png format, the Pixacomp image data
01287  *          can be stored in tiffg4, png and jpg formats.
01288  */
01289 l_int32
01290 pixacompWrite(const char  *filename,
01291               PIXAC       *pixac)
01292 {
01293 FILE  *fp;
01294 
01295     PROCNAME("pixacompWrite");
01296 
01297     if (!filename)
01298         return ERROR_INT("filename not defined", procName, 1);
01299     if (!pixac)
01300         return ERROR_INT("pixacomp not defined", procName, 1);
01301 
01302     if ((fp = fopenWriteStream(filename, "wb")) == NULL)
01303         return ERROR_INT("stream not opened", procName, 1);
01304     if (pixacompWriteStream(fp, pixac))
01305         return ERROR_INT("pixacomp not written to stream", procName, 1);
01306     fclose(fp);
01307     return 0;
01308 }
01309 
01310 
01311 /*!
01312  *  pixacompWriteStream()
01313  *
01314  *      Input:  stream
01315  *              pixac
01316  *      Return: 0 if OK, 1 on error
01317  */
01318 l_int32
01319 pixacompWriteStream(FILE   *fp,
01320                     PIXAC  *pixac)
01321 {
01322 l_int32  n, i;
01323 PIXC    *pixc;
01324 
01325     PROCNAME("pixacompWriteStream");
01326 
01327     if (!fp)
01328         return ERROR_INT("stream not defined", procName, 1);
01329     if (!pixac)
01330         return ERROR_INT("pixac not defined", procName, 1);
01331 
01332     n = pixacompGetCount(pixac);
01333     fprintf(fp, "\nPixacomp Version %d\n", PIXACOMP_VERSION_NUMBER);
01334     fprintf(fp, "Number of pixcomp = %d", n);
01335     boxaWriteStream(fp, pixac->boxa);
01336     for (i = 0; i < n; i++) {
01337         if ((pixc = pixacompGetPixcomp(pixac, i)) == NULL)
01338             return ERROR_INT("pixc not found", procName, 1);
01339         fprintf(fp, "  Pixcomp[%d]: w = %d, h = %d, d = %d\n",
01340                 i, pixc->w, pixc->h, pixc->d);
01341         fprintf(fp, "    comptype = %d, size = %ld, cmapflag = %d\n",
01342                 pixc->comptype, pixc->size, pixc->cmapflag);
01343         fprintf(fp, "    xres = %d, yres = %d\n", pixc->xres, pixc->yres);
01344         fwrite(pixc->data, 1, pixc->size, fp);
01345     }
01346     return 0;
01347 }
01348 
01349 
01350 /*--------------------------------------------------------------------*
01351  *                        Output for debugging                        *
01352  *--------------------------------------------------------------------*/
01353 /*!
01354  *  pixacompWriteStreamInfo()
01355  *
01356  *      Input:  fp (file stream)
01357  *              pixac
01358  *              text (<optional> identifying string; can be null)
01359  *      Return: 0 if OK, 1 on error
01360  */
01361 l_int32
01362 pixacompWriteStreamInfo(FILE        *fp,
01363                         PIXAC       *pixac,
01364                         const char  *text)
01365 {
01366 l_int32  i, n, nboxes;
01367 PIXC    *pixc;
01368 
01369     PROCNAME("pixacompWriteStreamInfo");
01370 
01371     if (!fp)
01372         return ERROR_INT("fp not defined", procName, 1);
01373     if (!pixac)
01374         return ERROR_INT("pixac not defined", procName, 1);
01375 
01376     if (text)
01377         fprintf(fp, "Pixacomp Info for %s:\n", text);
01378     else
01379         fprintf(fp, "Pixacomp Info:\n");
01380     n = pixacompGetCount(pixac);
01381     nboxes = pixacompGetBoxaCount(pixac);
01382     fprintf(fp, "Number of pixcomp: %d\n", n);
01383     fprintf(fp, "Size of pixcomp array alloc: %d\n", pixac->nalloc);
01384     if (nboxes  > 0)
01385         fprintf(fp, "Boxa has %d boxes\n", nboxes);
01386     else
01387         fprintf(fp, "Boxa is empty\n");
01388     for (i = 0; i < n; i++) {
01389         pixc = pixacompGetPixcomp(pixac, i);
01390         pixcompWriteStreamInfo(fp, pixc, NULL);
01391     }
01392     return 0;
01393 }
01394 
01395 
01396 /*!
01397  *  pixcompWriteStreamInfo()
01398  *
01399  *      Input:  fp (file stream)
01400  *              pixc
01401  *              text (<optional> identifying string; can be null)
01402  *      Return: 0 if OK, 1 on error
01403  */
01404 l_int32
01405 pixcompWriteStreamInfo(FILE        *fp,
01406                        PIXC        *pixc,
01407                        const char  *text)
01408 {
01409     PROCNAME("pixcompWriteStreamInfo");
01410 
01411     if (!fp)
01412         return ERROR_INT("fp not defined", procName, 1);
01413     if (!pixc)
01414         return ERROR_INT("pixc not defined", procName, 1);
01415 
01416     if (text)
01417         fprintf(fp, "  Pixcomp Info for %s:", text);
01418     else
01419         fprintf(fp, "  Pixcomp Info:");
01420     fprintf(fp, " width = %d, height = %d, depth = %d\n",
01421             pixc->w, pixc->h, pixc->d);
01422     fprintf(fp, "    xres = %d, yres = %d, size in bytes = %ld\n",
01423             pixc->xres, pixc->yres, pixc->size);
01424     if (pixc->cmapflag)
01425         fprintf(fp, "    has colormap\n");
01426     else
01427         fprintf(fp, "    no colormap\n");
01428     if (pixc->comptype < NumImageFileFormatExtensions)
01429         fprintf(fp, "    comptype = %s (%d)\n",
01430                 ImageFileFormatExtensions[pixc->comptype], pixc->comptype);
01431     else
01432         fprintf(fp, "    Error!! Invalid comptype index: %d\n", pixc->comptype);
01433     return 0;
01434 }
01435 
01436 
01437 /*!
01438  *  pixacompDisplayTiledAndScaled()
01439  *
01440  *      Input:  pixac
01441  *              outdepth (output depth: 1, 8 or 32 bpp)
01442  *              tilewidth (each pix is scaled to this width)
01443  *              ncols (number of tiles in each row)
01444  *              background (0 for white, 1 for black; this is the color
01445  *                 of the spacing between the images)
01446  *              spacing  (between images, and on outside)
01447  *              border (width of additional black border on each image;
01448  *                      use 0 for no border)
01449  *      Return: pix of tiled images, or null on error
01450  *
01451  *  Notes:
01452  *      (1) This is the same function as pixaDisplayTiledAndScaled(),
01453  *          except it works on a Pixacomp instead of a Pix.  It is particularly
01454  *          useful for showing the images in a Pixacomp at reduced resolution.
01455  *      (2) This can be used to tile a number of renderings of
01456  *          an image that are at different scales and depths.
01457  *      (3) Each image, after scaling and optionally adding the
01458  *          black border, has width 'tilewidth'.  Thus, the border does
01459  *          not affect the spacing between the image tiles.  The
01460  *          maximum allowed border width is tilewidth / 5.
01461  */
01462 PIX *
01463 pixacompDisplayTiledAndScaled(PIXAC   *pixac,
01464                               l_int32  outdepth,
01465                               l_int32  tilewidth,
01466                               l_int32  ncols,
01467                               l_int32  background,
01468                               l_int32  spacing,
01469                               l_int32  border)
01470 {
01471 l_int32    x, y, w, h, wd, hd, d;
01472 l_int32    i, n, nrows, maxht, ninrow, irow, bordval;
01473 l_int32   *rowht;
01474 l_float32  scalefact;
01475 PIX       *pix, *pixn, *pixt, *pixb, *pixd;
01476 PIXA      *pixan;
01477 
01478     PROCNAME("pixacompDisplayTiledAndScaled");
01479 
01480     if (!pixac)
01481         return (PIX *)ERROR_PTR("pixac not defined", procName, NULL);
01482     if (outdepth != 1 && outdepth != 8 && outdepth != 32)
01483         return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL);
01484     if (border < 0 || border > tilewidth / 5)
01485         border = 0;
01486     
01487     if ((n = pixacompGetCount(pixac)) == 0)
01488         return (PIX *)ERROR_PTR("no components", procName, NULL);
01489 
01490         /* Normalize scale and depth for each pix; optionally add border */
01491     pixan = pixaCreate(n);
01492     bordval = (outdepth == 1) ? 1 : 0;
01493     for (i = 0; i < n; i++) {
01494         if ((pix = pixacompGetPix(pixac, i)) == NULL) {
01495             L_WARNING_INT("pix %d not made", procName, i);
01496             continue;
01497         }
01498 
01499         pixGetDimensions(pix, &w, &h, &d);
01500         scalefact = (l_float32)(tilewidth - 2 * border) / (l_float32)w;
01501         if (d == 1 && outdepth > 1 && scalefact < 1.0)
01502             pixt = pixScaleToGray(pix, scalefact);
01503         else
01504             pixt = pixScale(pix, scalefact, scalefact);
01505 
01506         if (outdepth == 1)
01507             pixn = pixConvertTo1(pixt, 128);
01508         else if (outdepth == 8)
01509             pixn = pixConvertTo8(pixt, FALSE);
01510         else  /* outdepth == 32 */
01511             pixn = pixConvertTo32(pixt);
01512         pixDestroy(&pixt);
01513 
01514         if (border)
01515             pixb = pixAddBorder(pixn, border, bordval);
01516         else
01517             pixb = pixClone(pixn);
01518 
01519         pixaAddPix(pixan, pixb, L_INSERT);
01520         pixDestroy(&pix);
01521         pixDestroy(&pixn);
01522     }
01523     if ((n = pixaGetCount(pixan)) == 0) { /* should not have changed! */
01524         pixaDestroy(&pixan);
01525         return (PIX *)ERROR_PTR("no components", procName, NULL);
01526     }
01527 
01528         /* Determine the size of each row and of pixd */
01529     wd = tilewidth * ncols + spacing * (ncols + 1);
01530     nrows = (n + ncols - 1) / ncols;
01531     if ((rowht = (l_int32 *)CALLOC(nrows, sizeof(l_int32))) == NULL)
01532         return (PIX *)ERROR_PTR("rowht array not made", procName, NULL);
01533     maxht = 0;
01534     ninrow = 0;
01535     irow = 0;
01536     for (i = 0; i < n; i++) {
01537         pix = pixaGetPix(pixan, i, L_CLONE);
01538         ninrow++;
01539         pixGetDimensions(pix, &w, &h, NULL);
01540         maxht = L_MAX(h, maxht);
01541         if (ninrow == ncols) {
01542             rowht[irow] = maxht;
01543             maxht = ninrow = 0;  /* reset */
01544             irow++;
01545         }
01546         pixDestroy(&pix);
01547     }
01548     if (ninrow > 0) {   /* last fencepost */
01549         rowht[irow] = maxht;
01550         irow++;  /* total number of rows */
01551     }
01552     nrows = irow;
01553     hd = spacing * (nrows + 1);
01554     for (i = 0; i < nrows; i++)
01555         hd += rowht[i];
01556 
01557     pixd = pixCreate(wd, hd, outdepth);
01558     if ((background == 1 && outdepth == 1) ||
01559         (background == 0 && outdepth != 1))
01560         pixSetAll(pixd);
01561 
01562         /* Now blit images to pixd */
01563     x = y = spacing;
01564     irow = 0;
01565     for (i = 0; i < n; i++) {
01566         pix = pixaGetPix(pixan, i, L_CLONE);
01567         pixGetDimensions(pix, &w, &h, NULL);
01568         if (i && ((i % ncols) == 0)) {  /* start new row */
01569             x = spacing;
01570             y += spacing + rowht[irow];
01571             irow++;
01572         }
01573         pixRasterop(pixd, x, y, w, h, PIX_SRC, pix, 0, 0);
01574         x += tilewidth + spacing;
01575         pixDestroy(&pix);
01576     }
01577 
01578     pixaDestroy(&pixan);
01579     FREE(rowht);
01580     return pixd;
01581 }
01582 
01583 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines