Leptonica 1.68
C Image Processing Library

fpix1.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  *  fpix1.c
00018  *
00019  *    This file has basic constructors, destructors and field accessors
00020  *    for FPix, FPixa and DPix.  It also has uncompressed read/write.
00021  *
00022  *    FPix Create/copy/destroy
00023  *          FPIX          *fpixCreate()
00024  *          FPIX          *fpixCreateTemplate()
00025  *          FPIX          *fpixClone()
00026  *          FPIX          *fpixCopy()
00027  *          l_int32        fpixResizeImageData()
00028  *          void           fpixDestroy()
00029  *
00030  *    FPix accessors
00031  *          l_int32        fpixGetDimensions()
00032  *          l_int32        fpixSetDimensions()
00033  *          l_int32        fpixGetWpl()
00034  *          l_int32        fpixSetWpl()
00035  *          l_int32        fpixGetRefcount()
00036  *          l_int32        fpixChangeRefcount()
00037  *          l_int32        fpixGetResolution()
00038  *          l_int32        fpixSetResolution()
00039  *          l_int32        fpixCopyResolution()
00040  *          l_float32     *fpixGetData()
00041  *          l_int32        fpixSetData()
00042  *          l_int32        fpixGetPixel()
00043  *          l_int32        fpixSetPixel()
00044  *
00045  *    FPixa Create/copy/destroy
00046  *          FPIXA         *fpixaCreate()
00047  *          FPIXA         *fpixaCopy()
00048  *          void           fpixaDestroy()
00049  *
00050  *    FPixa addition
00051  *          l_int32        fpixaAddFPix()
00052  *          l_int32        fpixaExtendArray()
00053  *          l_int32        fpixaExtendArrayToSize()
00054  *
00055  *    FPixa accessors
00056  *          l_int32        fpixaGetCount()
00057  *          l_int32        fpixaChangeRefcount()
00058  *          FPIX          *fpixaGetFPix()
00059  *          l_int32        fpixaGetFPixDimensions()
00060  *          l_int32        fpixaGetPixel()
00061  *          l_int32        fpixaSetPixel()
00062  *
00063  *    DPix Create/copy/destroy
00064  *          DPIX          *dpixCreate()
00065  *          DPIX          *dpixCreateTemplate()
00066  *          DPIX          *dpixClone()
00067  *          DPIX          *dpixCopy()
00068  *          l_int32        dpixResizeImageData()
00069  *          void           dpixDestroy()
00070  *
00071  *    DPix accessors
00072  *          l_int32        dpixGetDimensions()
00073  *          l_int32        dpixSetDimensions()
00074  *          l_int32        dpixGetWpl()
00075  *          l_int32        dpixSetWpl()
00076  *          l_int32        dpixGetRefcount()
00077  *          l_int32        dpixChangeRefcount()
00078  *          l_int32        dpixGetResolution()
00079  *          l_int32        dpixSetResolution()
00080  *          l_int32        dpixCopyResolution()
00081  *          l_float64     *dpixGetData()
00082  *          l_int32        dpixSetData()
00083  *          l_int32        dpixGetPixel()
00084  *          l_int32        dpixSetPixel()
00085  *
00086  *    FPix serialized I/O
00087  *          FPIX          *fpixRead()
00088  *          FPIX          *fpixReadStream()
00089  *          l_int32        fpixWrite()
00090  *          l_int32        fpixWriteStream()
00091  *          FPIX          *fpixEndianByteSwap()
00092  *
00093  *    DPix serialized I/O
00094  *          DPIX          *dpixRead()
00095  *          DPIX          *dpixReadStream()
00096  *          l_int32        dpixWrite()
00097  *          l_int32        dpixWriteStream()
00098  *          DPIX          *dpixEndianByteSwap()
00099  * 
00100  *    Print FPix (subsampled, for debugging)
00101  *          l_int32        fpixPrintStream()
00102  */
00103 
00104 #include <string.h>
00105 #include "allheaders.h"
00106 
00107 static const l_int32  INITIAL_PTR_ARRAYSIZE = 20;   /* must be > 0 */
00108 
00109 
00110 /*--------------------------------------------------------------------*
00111  *                     FPix Create/copy/destroy                       *
00112  *--------------------------------------------------------------------*/
00113 /*!
00114  *  fpixCreate()
00115  *
00116  *      Input:  width, height
00117  *      Return: fpixd (with data allocated and initialized to 0),
00118  *                     or null on error
00119  *
00120  *  Notes:
00121  *      (1) Makes a FPix of specified size, with the data array
00122  *          allocated and initialized to 0.
00123  */
00124 FPIX *
00125 fpixCreate(l_int32  width,
00126            l_int32  height)
00127 {
00128 l_float32  *data;
00129 FPIX       *fpixd;
00130 
00131     PROCNAME("fpixCreate");
00132 
00133     if (width <= 0)
00134         return (FPIX *)ERROR_PTR("width must be > 0", procName, NULL);
00135     if (height <= 0)
00136         return (FPIX *)ERROR_PTR("height must be > 0", procName, NULL);
00137 
00138     if ((fpixd = (FPIX *)CALLOC(1, sizeof(FPIX))) == NULL)
00139         return (FPIX *)ERROR_PTR("CALLOC fail for fpixd", procName, NULL);
00140     fpixSetDimensions(fpixd, width, height);
00141     fpixSetWpl(fpixd, width);
00142     fpixd->refcount = 1;
00143 
00144     data = (l_float32 *)CALLOC(width * height, sizeof(l_float32));
00145     if (!data)
00146         return (FPIX *)ERROR_PTR("CALLOC fail for data", procName, NULL);
00147     fpixSetData(fpixd, data);
00148 
00149     return fpixd;
00150 }
00151 
00152 
00153 /*!
00154  *  fpixCreateTemplate()
00155  *
00156  *      Input:  fpixs
00157  *      Return: fpixd, or null on error
00158  *
00159  *  Notes:
00160  *      (1) Makes a FPix of the same size as the input FPix, with the
00161  *          data array allocated and initialized to 0.
00162  *      (2) Copies the resolution.
00163  */
00164 FPIX *
00165 fpixCreateTemplate(FPIX  *fpixs)
00166 {
00167 l_int32  w, h;
00168 FPIX    *fpixd;
00169 
00170     PROCNAME("fpixCreateTemplate");
00171 
00172     if (!fpixs)
00173         return (FPIX *)ERROR_PTR("fpixs not defined", procName, NULL);
00174 
00175     fpixGetDimensions(fpixs, &w, &h);
00176     fpixd = fpixCreate(w, h);
00177     fpixCopyResolution(fpixd, fpixs);
00178     return fpixd;
00179 }
00180 
00181 
00182 /*!
00183  *  fpixClone()
00184  *
00185  *      Input:  fpix
00186  *      Return: same fpix (ptr), or null on error
00187  *
00188  *  Notes:
00189  *      (1) See pixClone() for definition and usage.
00190  */
00191 FPIX *
00192 fpixClone(FPIX  *fpix)
00193 {
00194     PROCNAME("fpixClone");
00195 
00196     if (!fpix)
00197         return (FPIX *)ERROR_PTR("fpix not defined", procName, NULL);
00198     fpixChangeRefcount(fpix, 1);
00199 
00200     return fpix;
00201 }
00202 
00203 
00204 /*!
00205  *  fpixCopy()
00206  *
00207  *      Input:  fpixd (<optional>; can be null, or equal to fpixs,
00208  *                    or different from fpixs)
00209  *              fpixs
00210  *      Return: fpixd, or null on error
00211  *
00212  *  Notes:
00213  *      (1) There are three cases:
00214  *            (a) fpixd == null  (makes a new fpix; refcount = 1)
00215  *            (b) fpixd == fpixs  (no-op)
00216  *            (c) fpixd != fpixs  (data copy; no change in refcount)
00217  *          If the refcount of fpixd > 1, case (c) will side-effect
00218  *          these handles.
00219  *      (2) The general pattern of use is:
00220  *             fpixd = fpixCopy(fpixd, fpixs);
00221  *          This will work for all three cases.
00222  *          For clarity when the case is known, you can use:
00223  *            (a) fpixd = fpixCopy(NULL, fpixs);
00224  *            (c) fpixCopy(fpixd, fpixs);
00225  *      (3) For case (c), we check if fpixs and fpixd are the same size.
00226  *          If so, the data is copied directly.
00227  *          Otherwise, the data is reallocated to the correct size
00228  *          and the copy proceeds.  The refcount of fpixd is unchanged.
00229  *      (4) This operation, like all others that may involve a pre-existing
00230  *          fpixd, will side-effect any existing clones of fpixd.
00231  */
00232 FPIX *
00233 fpixCopy(FPIX  *fpixd,   /* can be null */
00234          FPIX  *fpixs)
00235 {
00236 l_int32     w, h, bytes;
00237 l_float32  *datas, *datad;
00238 
00239     PROCNAME("fpixCopy");
00240 
00241     if (!fpixs)
00242         return (FPIX *)ERROR_PTR("fpixs not defined", procName, NULL);
00243     if (fpixs == fpixd)
00244         return fpixd;
00245 
00246         /* Total bytes in image data */
00247     fpixGetDimensions(fpixs, &w, &h);
00248     bytes = 4 * w * h;
00249 
00250         /* If we're making a new fpix ... */
00251     if (!fpixd) {
00252         if ((fpixd = fpixCreateTemplate(fpixs)) == NULL)
00253             return (FPIX *)ERROR_PTR("fpixd not made", procName, NULL);
00254         datas = fpixGetData(fpixs);
00255         datad = fpixGetData(fpixd);
00256         memcpy((char *)datad, (char *)datas, bytes);
00257         return fpixd;
00258     }
00259 
00260         /* Reallocate image data if sizes are different */
00261     fpixResizeImageData(fpixd, fpixs);
00262 
00263         /* Copy data */
00264     fpixCopyResolution(fpixd, fpixs);
00265     datas = fpixGetData(fpixs);
00266     datad = fpixGetData(fpixd);
00267     memcpy((char*)datad, (char*)datas, bytes);
00268     return fpixd;
00269 }
00270 
00271 
00272 /*!
00273  *  fpixResizeImageData()
00274  *
00275  *      Input:  fpixd, fpixs
00276  *      Return: 0 if OK, 1 on error
00277  *
00278  *  Notes:
00279  *      (1) If the data sizes differ, this destroys the existing
00280  *          data in fpixd and allocates a new, uninitialized, data array
00281  *          of the same size as the data in fpixs.  Otherwise, this
00282  *          doesn't do anything.
00283  */
00284 l_int32
00285 fpixResizeImageData(FPIX  *fpixd,
00286                     FPIX  *fpixs)
00287 {
00288 l_int32     ws, hs, wd, hd, bytes;
00289 l_float32  *data;
00290 
00291     PROCNAME("fpixResizeImageData");
00292 
00293     if (!fpixs)
00294         return ERROR_INT("fpixs not defined", procName, 1);
00295     if (!fpixd)
00296         return ERROR_INT("fpixd not defined", procName, 1);
00297 
00298     fpixGetDimensions(fpixs, &ws, &hs);
00299     fpixGetDimensions(fpixd, &wd, &hd);
00300     if (ws == wd && hs == hd)  /* nothing to do */
00301         return 0;
00302 
00303     fpixSetDimensions(fpixd, ws, hs);
00304     fpixSetWpl(fpixd, ws);
00305     bytes = 4 * ws * hs;
00306     data = fpixGetData(fpixd);
00307     if (data) FREE(data);
00308     if ((data = (l_float32 *)MALLOC(bytes)) == NULL)
00309         return ERROR_INT("MALLOC fail for data", procName, 1);
00310     fpixSetData(fpixd, data);
00311     return 0;
00312 }
00313 
00314 
00315 /*!
00316  *  fpixDestroy()
00317  *
00318  *      Input:  &fpix <will be nulled>
00319  *      Return: void
00320  *
00321  *  Notes:
00322  *      (1) Decrements the ref count and, if 0, destroys the fpix.
00323  *      (2) Always nulls the input ptr.
00324  */
00325 void
00326 fpixDestroy(FPIX  **pfpix)
00327 {
00328 l_float32  *data;
00329 FPIX       *fpix;
00330 
00331     PROCNAME("fpixDestroy");
00332 
00333     if (!pfpix) {
00334         L_WARNING("ptr address is null!", procName);
00335         return;
00336     }
00337 
00338     if ((fpix = *pfpix) == NULL)
00339         return;
00340 
00341         /* Decrement the ref count.  If it is 0, destroy the fpix. */
00342     fpixChangeRefcount(fpix, -1);
00343     if (fpixGetRefcount(fpix) <= 0) {
00344         if ((data = fpixGetData(fpix)) != NULL)
00345             FREE(data);
00346         FREE(fpix);
00347     }
00348 
00349     *pfpix = NULL;
00350     return;
00351 }
00352 
00353 
00354 /*--------------------------------------------------------------------*
00355  *                          FPix  Accessors                           *
00356  *--------------------------------------------------------------------*/
00357 /*!
00358  *  fpixGetDimensions()
00359  *
00360  *      Input:  fpix
00361  *              &w, &h (<optional return>; each can be null)
00362  *      Return: 0 if OK, 1 on error
00363  */
00364 l_int32
00365 fpixGetDimensions(FPIX     *fpix,
00366                   l_int32  *pw,
00367                   l_int32  *ph)
00368 {
00369     PROCNAME("fpixGetDimensions");
00370 
00371     if (!fpix)
00372         return ERROR_INT("fpix not defined", procName, 1);
00373     if (pw) *pw = fpix->w;
00374     if (ph) *ph = fpix->h;
00375     return 0;
00376 }
00377 
00378 
00379 /*!
00380  *  fpixSetDimensions()
00381  *
00382  *      Input:  fpix
00383  *              w, h
00384  *      Return: 0 if OK, 1 on error
00385  */
00386 l_int32
00387 fpixSetDimensions(FPIX     *fpix,
00388                   l_int32   w,
00389                   l_int32   h)
00390 {
00391     PROCNAME("fpixSetDimensions");
00392 
00393     if (!fpix)
00394         return ERROR_INT("fpix not defined", procName, 1);
00395     fpix->w = w;
00396     fpix->h = h;
00397     return 0;
00398 }
00399 
00400 
00401 l_int32
00402 fpixGetWpl(FPIX  *fpix)
00403 {
00404     PROCNAME("fpixGetWpl");
00405 
00406     if (!fpix)
00407         return ERROR_INT("fpix not defined", procName, 1);
00408     return fpix->wpl;
00409 }
00410 
00411 
00412 l_int32
00413 fpixSetWpl(FPIX    *fpix,
00414            l_int32  wpl)
00415 {
00416     PROCNAME("fpixSetWpl");
00417 
00418     if (!fpix)
00419         return ERROR_INT("fpix not defined", procName, 1);
00420 
00421     fpix->wpl = wpl;
00422     return 0;
00423 }
00424 
00425 
00426 l_int32
00427 fpixGetRefcount(FPIX  *fpix)
00428 {
00429     PROCNAME("fpixGetRefcount");
00430 
00431     if (!fpix)
00432         return ERROR_INT("fpix not defined", procName, UNDEF);
00433     return fpix->refcount;
00434 }
00435 
00436 
00437 l_int32
00438 fpixChangeRefcount(FPIX    *fpix,
00439                    l_int32  delta)
00440 {
00441     PROCNAME("fpixChangeRefcount");
00442 
00443     if (!fpix)
00444         return ERROR_INT("fpix not defined", procName, 1);
00445 
00446     fpix->refcount += delta;
00447     return 0;
00448 }
00449 
00450 
00451 l_int32
00452 fpixGetResolution(FPIX     *fpix,
00453                   l_int32  *pxres,
00454                   l_int32  *pyres)
00455 {
00456     PROCNAME("fpixGetResolution");
00457 
00458     if (!fpix)
00459         return ERROR_INT("fpix not defined", procName, 1);
00460     if (pxres) *pxres = fpix->xres;
00461     if (pyres) *pyres = fpix->yres;
00462     return 0;
00463 }
00464 
00465 
00466 l_int32
00467 fpixSetResolution(FPIX    *fpix,
00468                   l_int32  xres,
00469                   l_int32  yres)
00470 {
00471     PROCNAME("fpixSetResolution");
00472 
00473     if (!fpix)
00474         return ERROR_INT("fpix not defined", procName, 1);
00475 
00476     fpix->xres = xres;
00477     fpix->yres = yres;
00478     return 0;
00479 }
00480 
00481 
00482 l_int32
00483 fpixCopyResolution(FPIX  *fpixd,
00484                    FPIX  *fpixs)
00485 {
00486 l_int32  xres, yres;
00487     PROCNAME("fpixCopyResolution");
00488 
00489     if (!fpixs || !fpixd)
00490         return ERROR_INT("fpixs and fpixd not both defined", procName, 1);
00491 
00492     fpixGetResolution(fpixs, &xres, &yres);
00493     fpixSetResolution(fpixd, xres, yres);
00494     return 0;
00495 }
00496 
00497 
00498 l_float32 *
00499 fpixGetData(FPIX  *fpix)
00500 {
00501     PROCNAME("fpixGetData");
00502 
00503     if (!fpix)
00504         return (l_float32 *)ERROR_PTR("fpix not defined", procName, NULL);
00505     return fpix->data;
00506 }
00507 
00508 
00509 l_int32
00510 fpixSetData(FPIX       *fpix,
00511             l_float32  *data)
00512 {
00513     PROCNAME("fpixSetData");
00514 
00515     if (!fpix)
00516         return ERROR_INT("fpix not defined", procName, 1);
00517 
00518     fpix->data = data;
00519     return 0;
00520 }
00521 
00522 
00523 /*!
00524  *  fpixGetPixel()
00525  *
00526  *      Input:  fpix
00527  *              (x,y) pixel coords
00528  *              &val (<return> pixel value)
00529  *      Return: 0 if OK; 1 on error
00530  */
00531 l_int32
00532 fpixGetPixel(FPIX       *fpix,
00533              l_int32     x,
00534              l_int32     y,
00535              l_float32  *pval)
00536 {
00537 l_int32  w, h;
00538 
00539     PROCNAME("fpixGetPixel");
00540 
00541     if (!pval)
00542         return ERROR_INT("pval not defined", procName, 1);
00543     *pval = 0.0;
00544     if (!fpix)
00545         return ERROR_INT("fpix not defined", procName, 1);
00546 
00547     fpixGetDimensions(fpix, &w, &h);
00548     if (x < 0 || x >= w)
00549         return ERROR_INT("x out of bounds", procName, 1);
00550     if (y < 0 || y >= h)
00551         return ERROR_INT("y out of bounds", procName, 1);
00552 
00553     *pval = *(fpix->data + y * w + x);
00554     return 0;
00555 }
00556 
00557 
00558 /*!
00559  *  fpixSetPixel()
00560  *
00561  *      Input:  fpix
00562  *              (x,y) pixel coords
00563  *              val (pixel value)
00564  *      Return: 0 if OK; 1 on error
00565  */
00566 l_int32
00567 fpixSetPixel(FPIX      *fpix,
00568              l_int32    x,
00569              l_int32    y,
00570              l_float32  val)
00571 {
00572 l_int32  w, h;
00573 
00574     PROCNAME("fpixSetPixel");
00575 
00576     if (!fpix)
00577         return ERROR_INT("fpix not defined", procName, 1);
00578 
00579     fpixGetDimensions(fpix, &w, &h);
00580     if (x < 0 || x >= w)
00581         return ERROR_INT("x out of bounds", procName, 1);
00582     if (y < 0 || y >= h)
00583         return ERROR_INT("y out of bounds", procName, 1);
00584 
00585     *(fpix->data + y * w + x) = val;
00586     return 0;
00587 }
00588 
00589 
00590 /*--------------------------------------------------------------------*
00591  *                     FPixa Create/copy/destroy                      *
00592  *--------------------------------------------------------------------*/
00593 /*!
00594  *  fpixaCreate()
00595  *
00596  *      Input:  n  (initial number of ptrs)
00597  *      Return: fpixa, or null on error
00598  */
00599 FPIXA *
00600 fpixaCreate(l_int32  n)
00601 {
00602 FPIXA  *fpixa;
00603 
00604     PROCNAME("fpixaCreate");
00605 
00606     if (n <= 0)
00607         n = INITIAL_PTR_ARRAYSIZE;
00608 
00609     if ((fpixa = (FPIXA *)CALLOC(1, sizeof(FPIXA))) == NULL)
00610         return (FPIXA *)ERROR_PTR("pixa not made", procName, NULL);
00611     fpixa->n = 0;
00612     fpixa->nalloc = n;
00613     fpixa->refcount = 1;
00614 
00615     if ((fpixa->fpix = (FPIX **)CALLOC(n, sizeof(FPIX *))) == NULL)
00616         return (FPIXA *)ERROR_PTR("fpix ptrs not made", procName, NULL);
00617 
00618     return fpixa;
00619 }
00620 
00621 
00622 /*!
00623  *  fpixaCopy()
00624  *
00625  *      Input:  fpixas
00626  *              copyflag:
00627  *                L_COPY makes a new fpixa and copies each fpix
00628  *                L_CLONE gives a new ref-counted handle to the input fpixa
00629  *                L_COPY_CLONE makes a new fpixa with clones of all fpix
00630  *      Return: new fpixa, or null on error
00631  */
00632 FPIXA *
00633 fpixaCopy(FPIXA   *fpixa,
00634           l_int32  copyflag)
00635 {
00636 l_int32  i;
00637 FPIX    *fpixc;
00638 FPIXA   *fpixac;
00639 
00640     PROCNAME("fpixaCopy");
00641 
00642     if (!fpixa)
00643         return (FPIXA *)ERROR_PTR("fpixa not defined", procName, NULL);
00644 
00645     if (copyflag == L_CLONE) {
00646         fpixaChangeRefcount(fpixa, 1);
00647         return fpixa;
00648     }
00649 
00650     if (copyflag != L_COPY && copyflag != L_COPY_CLONE)
00651         return (FPIXA *)ERROR_PTR("invalid copyflag", procName, NULL);
00652 
00653     if ((fpixac = fpixaCreate(fpixa->n)) == NULL)
00654         return (FPIXA *)ERROR_PTR("fpixac not made", procName, NULL);
00655     for (i = 0; i < fpixa->n; i++) {
00656         if (copyflag == L_COPY)
00657             fpixc = fpixaGetFPix(fpixa, i, L_COPY);
00658         else  /* copy-clone */
00659             fpixc = fpixaGetFPix(fpixa, i, L_CLONE);
00660         fpixaAddFPix(fpixac, fpixc, L_INSERT);
00661     }
00662 
00663     return fpixac;
00664 }
00665 
00666 
00667 /*!
00668  *  fpixaDestroy()
00669  *
00670  *      Input:  &fpixa (<can be nulled>)
00671  *      Return: void
00672  *
00673  *  Notes:
00674  *      (1) Decrements the ref count and, if 0, destroys the fpixa.
00675  *      (2) Always nulls the input ptr.
00676  */
00677 void
00678 fpixaDestroy(FPIXA  **pfpixa)
00679 {
00680 l_int32  i;
00681 FPIXA   *fpixa;
00682 
00683     PROCNAME("fpixaDestroy");
00684 
00685     if (pfpixa == NULL) {
00686         L_WARNING("ptr address is NULL!", procName);
00687         return;
00688     }
00689 
00690     if ((fpixa = *pfpixa) == NULL)
00691         return;
00692 
00693         /* Decrement the refcount.  If it is 0, destroy the pixa. */
00694     fpixaChangeRefcount(fpixa, -1);
00695     if (fpixa->refcount <= 0) {
00696         for (i = 0; i < fpixa->n; i++)
00697             fpixDestroy(&fpixa->fpix[i]);
00698         FREE(fpixa->fpix);
00699         FREE(fpixa);
00700     }
00701 
00702     *pfpixa = NULL;
00703     return;
00704 }
00705 
00706 
00707 /*--------------------------------------------------------------------*
00708  *                           FPixa addition                           *
00709  *--------------------------------------------------------------------*/
00710 /*!
00711  *  fpixaAddFPix()
00712  *
00713  *      Input:  fpixa
00714  *              fpix  (to be added)
00715  *              copyflag (L_INSERT, L_COPY, L_CLONE)
00716  *      Return: 0 if OK; 1 on error
00717  */
00718 l_int32
00719 fpixaAddFPix(FPIXA   *fpixa,
00720              FPIX    *fpix,
00721              l_int32  copyflag)
00722 {
00723 l_int32  n;
00724 FPIX    *fpixc;
00725 
00726     PROCNAME("fpixaAddFPix");
00727 
00728     if (!fpixa)
00729         return ERROR_INT("fpixa not defined", procName, 1);
00730     if (!fpix)
00731         return ERROR_INT("fpix not defined", procName, 1);
00732 
00733     if (copyflag == L_INSERT)
00734         fpixc = fpix;
00735     else if (copyflag == L_COPY)
00736         fpixc = fpixCopy(NULL, fpix);
00737     else if (copyflag == L_CLONE)
00738         fpixc = fpixClone(fpix);
00739     else
00740         return ERROR_INT("invalid copyflag", procName, 1);
00741     if (!fpixc)
00742         return ERROR_INT("fpixc not made", procName, 1);
00743 
00744     n = fpixaGetCount(fpixa);
00745     if (n >= fpixa->nalloc)
00746         fpixaExtendArray(fpixa);
00747     fpixa->fpix[n] = fpixc;
00748     fpixa->n++;
00749 
00750     return 0;
00751 }
00752 
00753 
00754 /*!
00755  *  fpixaExtendArray()
00756  *
00757  *      Input:  fpixa
00758  *      Return: 0 if OK; 1 on error
00759  *
00760  *  Notes:
00761  *      (1) Doubles the size of the fpixa ptr array.
00762  */
00763 l_int32
00764 fpixaExtendArray(FPIXA  *fpixa)
00765 {
00766     PROCNAME("fpixaExtendArray");
00767 
00768     if (!fpixa)
00769         return ERROR_INT("fpixa not defined", procName, 1);
00770 
00771     return fpixaExtendArrayToSize(fpixa, 2 * fpixa->nalloc);
00772 }
00773 
00774 
00775 /*!
00776  *  fpixaExtendArrayToSize()
00777  *
00778  *      Input:  fpixa
00779  *      Return: 0 if OK; 1 on error
00780  *
00781  *  Notes:
00782  *      (1) If necessary, reallocs new fpixa ptrs array to @size.
00783  */
00784 l_int32
00785 fpixaExtendArrayToSize(FPIXA   *fpixa,
00786                        l_int32  size)
00787 {
00788     PROCNAME("fpixaExtendArrayToSize");
00789 
00790     if (!fpixa)
00791         return ERROR_INT("fpixa not defined", procName, 1);
00792 
00793     if (size > fpixa->nalloc) {
00794         if ((fpixa->fpix = (FPIX **)reallocNew((void **)&fpixa->fpix,
00795                                  sizeof(FPIX *) * fpixa->nalloc,
00796                                  size * sizeof(FPIX *))) == NULL)
00797             return ERROR_INT("new ptr array not returned", procName, 1);
00798         fpixa->nalloc = size;
00799     }
00800     return 0;
00801 }
00802 
00803 
00804 /*--------------------------------------------------------------------*
00805  *                          FPixa accessors                           *
00806  *--------------------------------------------------------------------*/
00807 /*!
00808  *  fpixaGetCount()
00809  *
00810  *      Input:  fpixa
00811  *      Return: count, or 0 if no pixa
00812  */
00813 l_int32
00814 fpixaGetCount(FPIXA  *fpixa)
00815 {
00816     PROCNAME("fpixaGetCount");
00817 
00818     if (!fpixa)
00819         return ERROR_INT("fpixa not defined", procName, 0);
00820 
00821     return fpixa->n;
00822 }
00823 
00824 
00825 /*!
00826  *  fpixaChangeRefcount()
00827  *
00828  *      Input:  fpixa
00829  *      Return: 0 if OK, 1 on error
00830  */
00831 l_int32
00832 fpixaChangeRefcount(FPIXA   *fpixa,
00833                     l_int32  delta)
00834 {
00835     PROCNAME("fpixaChangeRefcount");
00836 
00837     if (!fpixa)
00838         return ERROR_INT("fpixa not defined", procName, 1);
00839 
00840     fpixa->refcount += delta;
00841     return 0;
00842 }
00843 
00844 
00845 /*!
00846  *  fpixaGetFPix()
00847  *
00848  *      Input:  fpixa
00849  *              index  (to the index-th fpix)
00850  *              accesstype  (L_COPY or L_CLONE)
00851  *      Return: fpix, or null on error
00852  */
00853 FPIX *
00854 fpixaGetFPix(FPIXA   *fpixa,
00855              l_int32  index,
00856              l_int32  accesstype)
00857 {
00858     PROCNAME("fpixaGetFPix");
00859 
00860     if (!fpixa)
00861         return (FPIX *)ERROR_PTR("fpixa not defined", procName, NULL);
00862     if (index < 0 || index >= fpixa->n)
00863         return (FPIX *)ERROR_PTR("index not valid", procName, NULL);
00864 
00865     if (accesstype == L_COPY)
00866         return fpixCopy(NULL, fpixa->fpix[index]);
00867     else if (accesstype == L_CLONE)
00868         return fpixClone(fpixa->fpix[index]);
00869     else
00870         return (FPIX *)ERROR_PTR("invalid accesstype", procName, NULL);
00871 }
00872 
00873 
00874 /*!
00875  *  fpixaGetFPixDimensions()
00876  *
00877  *      Input:  fpixa
00878  *              index  (to the index-th box)
00879  *              &w, &h (<optional return>; each can be null)
00880  *      Return: 0 if OK, 1 on error
00881  */
00882 l_int32
00883 fpixaGetFPixDimensions(FPIXA    *fpixa,
00884                        l_int32   index,
00885                        l_int32  *pw,
00886                        l_int32  *ph)
00887 {
00888 FPIX  *fpix;
00889 
00890     PROCNAME("fpixaGetFPixDimensions");
00891 
00892     if (!fpixa)
00893         return ERROR_INT("fpixa not defined", procName, 1);
00894     if (index < 0 || index >= fpixa->n)
00895         return ERROR_INT("index not valid", procName, 1);
00896 
00897     if ((fpix = fpixaGetFPix(fpixa, index, L_CLONE)) == NULL)
00898         return ERROR_INT("fpix not found!", procName, 1);
00899     fpixGetDimensions(fpix, pw, ph);
00900     fpixDestroy(&fpix);
00901     return 0;
00902 }
00903 
00904 
00905 /*!
00906  *  fpixaGetPixel()
00907  *
00908  *      Input:  fpixa
00909  *              index (into fpixa array)
00910  *              (x,y) pixel coords
00911  *              &val (<return> pixel value)
00912  *      Return: 0 if OK; 1 on error
00913  */
00914 l_int32
00915 fpixaGetPixel(FPIXA      *fpixa,
00916               l_int32     index,
00917               l_int32     x,
00918               l_int32     y,
00919               l_float32  *pval)
00920 {
00921 l_int32  n, ret;
00922 FPIX    *fpix;
00923 
00924     PROCNAME("fpixaGetPixel");
00925 
00926     if (!pval)
00927         return ERROR_INT("pval not defined", procName, 1);
00928     *pval = 0.0;
00929     if (!fpixa)
00930         return ERROR_INT("fpixa not defined", procName, 1);
00931     n = fpixaGetCount(fpixa);
00932     if (index < 0 || index >= n)
00933         return ERROR_INT("invalid index into fpixa", procName, 1);
00934 
00935     fpix = fpixaGetFPix(fpixa, index, L_CLONE);
00936     ret = fpixGetPixel(fpix, x, y, pval);
00937     fpixDestroy(&fpix);
00938     return ret;
00939 }
00940 
00941 
00942 /*!
00943  *  fpixaSetPixel()
00944  *
00945  *      Input:  fpixa
00946  *              index (into fpixa array)
00947  *              (x,y) pixel coords
00948  *              val (pixel value)
00949  *      Return: 0 if OK; 1 on error
00950  */
00951 l_int32
00952 fpixaSetPixel(FPIXA     *fpixa,
00953               l_int32    index,
00954               l_int32    x,
00955               l_int32    y,
00956               l_float32  val)
00957 {
00958 l_int32  n, ret;
00959 FPIX    *fpix;
00960 
00961     PROCNAME("fpixaSetPixel");
00962 
00963     if (!fpixa)
00964         return ERROR_INT("fpixa not defined", procName, 1);
00965     n = fpixaGetCount(fpixa);
00966     if (index < 0 || index >= n)
00967         return ERROR_INT("invalid index into fpixa", procName, 1);
00968 
00969     fpix = fpixaGetFPix(fpixa, index, L_CLONE);
00970     ret = fpixSetPixel(fpix, x, y, val);
00971     fpixDestroy(&fpix);
00972     return ret;
00973 }
00974 
00975 
00976 /*--------------------------------------------------------------------*
00977  *                     DPix Create/copy/destroy                       *
00978  *--------------------------------------------------------------------*/
00979 /*!
00980  *  dpixCreate()
00981  *
00982  *      Input:  width, height
00983  *      Return: dpix (with data allocated and initialized to 0),
00984  *                     or null on error
00985  *
00986  *  Notes:
00987  *      (1) Makes a DPix of specified size, with the data array
00988  *          allocated and initialized to 0.
00989  */
00990 DPIX *
00991 dpixCreate(l_int32  width,
00992            l_int32  height)
00993 {
00994 l_float64  *data;
00995 DPIX       *dpix;
00996 
00997     PROCNAME("dpixCreate");
00998 
00999     if (width <= 0)
01000         return (DPIX *)ERROR_PTR("width must be > 0", procName, NULL);
01001     if (height <= 0)
01002         return (DPIX *)ERROR_PTR("height must be > 0", procName, NULL);
01003 
01004     if ((dpix = (DPIX *)CALLOC(1, sizeof(DPIX))) == NULL)
01005         return (DPIX *)ERROR_PTR("CALLOC fail for dpix", procName, NULL);
01006     dpixSetDimensions(dpix, width, height);
01007     dpixSetWpl(dpix, width);  /* Note: 8 byte words here */
01008     dpix->refcount = 1;
01009 
01010     data = (l_float64 *)CALLOC(width * height, sizeof(l_float64));
01011     if (!data)
01012         return (DPIX *)ERROR_PTR("CALLOC fail for data", procName, NULL);
01013     dpixSetData(dpix, data);
01014 
01015     return dpix;
01016 }
01017 
01018 
01019 /*!
01020  *  dpixCreateTemplate()
01021  *
01022  *      Input:  dpixs
01023  *      Return: dpixd, or null on error
01024  *
01025  *  Notes:
01026  *      (1) Makes a DPix of the same size as the input DPix, with the
01027  *          data array allocated and initialized to 0.
01028  *      (2) Copies the resolution.
01029  */
01030 DPIX *
01031 dpixCreateTemplate(DPIX  *dpixs)
01032 {
01033 l_int32  w, h;
01034 DPIX    *dpixd;
01035 
01036     PROCNAME("dpixCreateTemplate");
01037 
01038     if (!dpixs)
01039         return (DPIX *)ERROR_PTR("dpixs not defined", procName, NULL);
01040 
01041     dpixGetDimensions(dpixs, &w, &h);
01042     dpixd = dpixCreate(w, h);
01043     dpixCopyResolution(dpixd, dpixs);
01044     return dpixd;
01045 }
01046 
01047 
01048 /*!
01049  *  dpixClone()
01050  *
01051  *      Input:  dpix
01052  *      Return: same dpix (ptr), or null on error
01053  *
01054  *  Notes:
01055  *      (1) See pixClone() for definition and usage.
01056  */
01057 DPIX *
01058 dpixClone(DPIX  *dpix)
01059 {
01060     PROCNAME("dpixClone");
01061 
01062     if (!dpix)
01063         return (DPIX *)ERROR_PTR("dpix not defined", procName, NULL);
01064     dpixChangeRefcount(dpix, 1);
01065 
01066     return dpix;
01067 }
01068 
01069 
01070 /*!
01071  *  dpixCopy()
01072  *
01073  *      Input:  dpixd (<optional>; can be null, or equal to dpixs,
01074  *                    or different from dpixs)
01075  *              dpixs
01076  *      Return: dpixd, or null on error
01077  *
01078  *  Notes:
01079  *      (1) There are three cases:
01080  *            (a) dpixd == null  (makes a new dpix; refcount = 1)
01081  *            (b) dpixd == dpixs  (no-op)
01082  *            (c) dpixd != dpixs  (data copy; no change in refcount)
01083  *          If the refcount of dpixd > 1, case (c) will side-effect
01084  *          these handles.
01085  *      (2) The general pattern of use is:
01086  *             dpixd = dpixCopy(dpixd, dpixs);
01087  *          This will work for all three cases.
01088  *          For clarity when the case is known, you can use:
01089  *            (a) dpixd = dpixCopy(NULL, dpixs);
01090  *            (c) dpixCopy(dpixd, dpixs);
01091  *      (3) For case (c), we check if dpixs and dpixd are the same size.
01092  *          If so, the data is copied directly.
01093  *          Otherwise, the data is reallocated to the correct size
01094  *          and the copy proceeds.  The refcount of dpixd is unchanged.
01095  *      (4) This operation, like all others that may involve a pre-existing
01096  *          dpixd, will side-effect any existing clones of dpixd.
01097  */
01098 DPIX *
01099 dpixCopy(DPIX  *dpixd,   /* can be null */
01100          DPIX  *dpixs)
01101 {
01102 l_int32     w, h, bytes;
01103 l_float64  *datas, *datad;
01104 
01105     PROCNAME("dpixCopy");
01106 
01107     if (!dpixs)
01108         return (DPIX *)ERROR_PTR("dpixs not defined", procName, NULL);
01109     if (dpixs == dpixd)
01110         return dpixd;
01111 
01112         /* Total bytes in image data */
01113     dpixGetDimensions(dpixs, &w, &h);
01114     bytes = 8 * w * h;
01115 
01116         /* If we're making a new dpix ... */
01117     if (!dpixd) {
01118         if ((dpixd = dpixCreateTemplate(dpixs)) == NULL)
01119             return (DPIX *)ERROR_PTR("dpixd not made", procName, NULL);
01120         datas = dpixGetData(dpixs);
01121         datad = dpixGetData(dpixd);
01122         memcpy((char *)datad, (char *)datas, bytes);
01123         return dpixd;
01124     }
01125 
01126         /* Reallocate image data if sizes are different */
01127     dpixResizeImageData(dpixd, dpixs);
01128 
01129         /* Copy data */
01130     dpixCopyResolution(dpixd, dpixs);
01131     datas = dpixGetData(dpixs);
01132     datad = dpixGetData(dpixd);
01133     memcpy((char*)datad, (char*)datas, bytes);
01134     return dpixd;
01135 }
01136 
01137 
01138 /*!
01139  *  dpixResizeImageData()
01140  *
01141  *      Input:  dpixd, dpixs
01142  *      Return: 0 if OK, 1 on error
01143  */
01144 l_int32
01145 dpixResizeImageData(DPIX  *dpixd,
01146                     DPIX  *dpixs)
01147 {
01148 l_int32     ws, hs, wd, hd, bytes;
01149 l_float64  *data;
01150 
01151     PROCNAME("dpixResizeImageData");
01152 
01153     if (!dpixs)
01154         return ERROR_INT("dpixs not defined", procName, 1);
01155     if (!dpixd)
01156         return ERROR_INT("dpixd not defined", procName, 1);
01157 
01158     dpixGetDimensions(dpixs, &ws, &hs);
01159     dpixGetDimensions(dpixd, &wd, &hd);
01160     if (ws == wd && hs == hd)  /* nothing to do */
01161         return 0;
01162 
01163     dpixSetDimensions(dpixd, ws, hs);
01164     dpixSetWpl(dpixd, ws);  /* Note: 8 byte words */
01165     bytes = 8 * ws * hs;
01166     data = dpixGetData(dpixd);
01167     if (data) FREE(data);
01168     if ((data = (l_float64 *)MALLOC(bytes)) == NULL)
01169         return ERROR_INT("MALLOC fail for data", procName, 1);
01170     dpixSetData(dpixd, data);
01171     return 0;
01172 }
01173 
01174 
01175 /*!
01176  *  dpixDestroy()
01177  *
01178  *      Input:  &dpix <will be nulled>
01179  *      Return: void
01180  *
01181  *  Notes:
01182  *      (1) Decrements the ref count and, if 0, destroys the dpix.
01183  *      (2) Always nulls the input ptr.
01184  */
01185 void
01186 dpixDestroy(DPIX  **pdpix)
01187 {
01188 l_float64  *data;
01189 DPIX       *dpix;
01190 
01191     PROCNAME("dpixDestroy");
01192 
01193     if (!pdpix) {
01194         L_WARNING("ptr address is null!", procName);
01195         return;
01196     }
01197 
01198     if ((dpix = *pdpix) == NULL)
01199         return;
01200 
01201         /* Decrement the ref count.  If it is 0, destroy the dpix. */
01202     dpixChangeRefcount(dpix, -1);
01203     if (dpixGetRefcount(dpix) <= 0) {
01204         if ((data = dpixGetData(dpix)) != NULL)
01205             FREE(data);
01206         FREE(dpix);
01207     }
01208 
01209     *pdpix = NULL;
01210     return;
01211 }
01212 
01213 
01214 /*--------------------------------------------------------------------*
01215  *                          DPix  Accessors                           *
01216  *--------------------------------------------------------------------*/
01217 /*!
01218  *  dpixGetDimensions()
01219  *
01220  *      Input:  dpix
01221  *              &w, &h (<optional return>; each can be null)
01222  *      Return: 0 if OK, 1 on error
01223  */
01224 l_int32
01225 dpixGetDimensions(DPIX     *dpix,
01226                   l_int32  *pw,
01227                   l_int32  *ph)
01228 {
01229     PROCNAME("dpixGetDimensions");
01230 
01231     if (!dpix)
01232         return ERROR_INT("dpix not defined", procName, 1);
01233     if (pw) *pw = dpix->w;
01234     if (ph) *ph = dpix->h;
01235     return 0;
01236 }
01237 
01238 
01239 /*!
01240  *  dpixSetDimensions()
01241  *
01242  *      Input:  dpix
01243  *              w, h
01244  *      Return: 0 if OK, 1 on error
01245  */
01246 l_int32
01247 dpixSetDimensions(DPIX     *dpix,
01248                   l_int32   w,
01249                   l_int32   h)
01250 {
01251     PROCNAME("dpixSetDimensions");
01252 
01253     if (!dpix)
01254         return ERROR_INT("dpix not defined", procName, 1);
01255     dpix->w = w;
01256     dpix->h = h;
01257     return 0;
01258 }
01259 
01260 
01261 l_int32
01262 dpixGetWpl(DPIX  *dpix)
01263 {
01264     PROCNAME("dpixGetWpl");
01265 
01266     if (!dpix)
01267         return ERROR_INT("dpix not defined", procName, 1);
01268     return dpix->wpl;
01269 }
01270 
01271 
01272 l_int32
01273 dpixSetWpl(DPIX    *dpix,
01274            l_int32  wpl)
01275 {
01276     PROCNAME("dpixSetWpl");
01277 
01278     if (!dpix)
01279         return ERROR_INT("dpix not defined", procName, 1);
01280 
01281     dpix->wpl = wpl;
01282     return 0;
01283 }
01284 
01285 
01286 l_int32
01287 dpixGetRefcount(DPIX  *dpix)
01288 {
01289     PROCNAME("dpixGetRefcount");
01290 
01291     if (!dpix)
01292         return ERROR_INT("dpix not defined", procName, UNDEF);
01293     return dpix->refcount;
01294 }
01295 
01296 
01297 l_int32
01298 dpixChangeRefcount(DPIX    *dpix,
01299                    l_int32  delta)
01300 {
01301     PROCNAME("dpixChangeRefcount");
01302 
01303     if (!dpix)
01304         return ERROR_INT("dpix not defined", procName, 1);
01305 
01306     dpix->refcount += delta;
01307     return 0;
01308 }
01309 
01310 
01311 l_int32
01312 dpixGetResolution(DPIX     *dpix,
01313                   l_int32  *pxres,
01314                   l_int32  *pyres)
01315 {
01316     PROCNAME("dpixGetResolution");
01317 
01318     if (!dpix)
01319         return ERROR_INT("dpix not defined", procName, 1);
01320     if (pxres) *pxres = dpix->xres;
01321     if (pyres) *pyres = dpix->yres;
01322     return 0;
01323 }
01324 
01325 
01326 l_int32
01327 dpixSetResolution(DPIX    *dpix,
01328                   l_int32  xres,
01329                   l_int32  yres)
01330 {
01331     PROCNAME("dpixSetResolution");
01332 
01333     if (!dpix)
01334         return ERROR_INT("dpix not defined", procName, 1);
01335 
01336     dpix->xres = xres;
01337     dpix->yres = yres;
01338     return 0;
01339 }
01340 
01341 
01342 l_int32
01343 dpixCopyResolution(DPIX  *dpixd,
01344                    DPIX  *dpixs)
01345 {
01346 l_int32  xres, yres;
01347     PROCNAME("dpixCopyResolution");
01348 
01349     if (!dpixs || !dpixd)
01350         return ERROR_INT("dpixs and dpixd not both defined", procName, 1);
01351 
01352     dpixGetResolution(dpixs, &xres, &yres);
01353     dpixSetResolution(dpixd, xres, yres);
01354     return 0;
01355 }
01356 
01357 
01358 l_float64 *
01359 dpixGetData(DPIX  *dpix)
01360 {
01361     PROCNAME("dpixGetData");
01362 
01363     if (!dpix)
01364         return (l_float64 *)ERROR_PTR("dpix not defined", procName, NULL);
01365     return dpix->data;
01366 }
01367 
01368 
01369 l_int32
01370 dpixSetData(DPIX       *dpix,
01371             l_float64  *data)
01372 {
01373     PROCNAME("dpixSetData");
01374 
01375     if (!dpix)
01376         return ERROR_INT("dpix not defined", procName, 1);
01377 
01378     dpix->data = data;
01379     return 0;
01380 }
01381 
01382 
01383 /*!
01384  *  dpixGetPixel()
01385  *
01386  *      Input:  dpix
01387  *              (x,y) pixel coords
01388  *              &val (<return> pixel value)
01389  *      Return: 0 if OK; 1 on error
01390  */
01391 l_int32
01392 dpixGetPixel(DPIX       *dpix,
01393              l_int32     x,
01394              l_int32     y,
01395              l_float64  *pval)
01396 {
01397 l_int32  w, h;
01398 
01399     PROCNAME("dpixGetPixel");
01400 
01401     if (!pval)
01402         return ERROR_INT("pval not defined", procName, 1);
01403     *pval = 0.0;
01404     if (!dpix)
01405         return ERROR_INT("dpix not defined", procName, 1);
01406 
01407     dpixGetDimensions(dpix, &w, &h);
01408     if (x < 0 || x >= w)
01409         return ERROR_INT("x out of bounds", procName, 1);
01410     if (y < 0 || y >= h)
01411         return ERROR_INT("y out of bounds", procName, 1);
01412 
01413     *pval = *(dpix->data + y * w + x);
01414     return 0;
01415 }
01416 
01417 
01418 /*!
01419  *  dpixSetPixel()
01420  *
01421  *      Input:  dpix
01422  *              (x,y) pixel coords
01423  *              val (pixel value)
01424  *      Return: 0 if OK; 1 on error
01425  */
01426 l_int32
01427 dpixSetPixel(DPIX      *dpix,
01428              l_int32    x,
01429              l_int32    y,
01430              l_float64  val)
01431 {
01432 l_int32  w, h;
01433 
01434     PROCNAME("dpixSetPixel");
01435 
01436     if (!dpix)
01437         return ERROR_INT("dpix not defined", procName, 1);
01438 
01439     dpixGetDimensions(dpix, &w, &h);
01440     if (x < 0 || x >= w)
01441         return ERROR_INT("x out of bounds", procName, 1);
01442     if (y < 0 || y >= h)
01443         return ERROR_INT("y out of bounds", procName, 1);
01444 
01445     *(dpix->data + y * w + x) = val;
01446     return 0;
01447 }
01448 
01449 
01450 /*--------------------------------------------------------------------*
01451  *                       FPix serialized I/O                          *
01452  *--------------------------------------------------------------------*/
01453 /*!
01454  *  fpixRead()
01455  *
01456  *      Input:  filename
01457  *      Return: fpix, or null on error
01458  */
01459 FPIX *
01460 fpixRead(const char  *filename)
01461 {
01462 FILE  *fp;
01463 FPIX  *fpix;
01464 
01465     PROCNAME("fpixRead");
01466 
01467     if (!filename)
01468         return (FPIX *)ERROR_PTR("filename not defined", procName, NULL);
01469     if ((fp = fopenReadStream(filename)) == NULL)
01470         return (FPIX *)ERROR_PTR("stream not opened", procName, NULL);
01471 
01472     if ((fpix = fpixReadStream(fp)) == NULL) {
01473         fclose(fp);
01474         return (FPIX *)ERROR_PTR("fpix not read", procName, NULL);
01475     }
01476 
01477     fclose(fp);
01478     return fpix;
01479 }
01480 
01481 
01482 /*!
01483  *  fpixReadStream()
01484  *
01485  *      Input:  stream
01486  *      Return: fpix, or null on error
01487  */
01488 FPIX *
01489 fpixReadStream(FILE  *fp)
01490 {
01491 l_int32     w, h, nbytes, version;
01492 l_float32  *data;
01493 FPIX       *fpix;
01494 
01495     PROCNAME("fpixReadStream");
01496 
01497     if (!fp)
01498         return (FPIX *)ERROR_PTR("stream not defined", procName, NULL);
01499 
01500     if (fscanf(fp, "\nFPix Version %d\n", &version) != 1)
01501         return (FPIX *)ERROR_PTR("not a fpix file", procName, NULL);
01502     if (version != FPIX_VERSION_NUMBER)
01503         return (FPIX *)ERROR_PTR("invalid fpix version", procName, NULL);
01504     if (fscanf(fp, "w = %d, h = %d, nbytes = %d\n", &w, &h, &nbytes) != 3)
01505         return (FPIX *)ERROR_PTR("read fail for data size", procName, NULL);
01506 
01507     if ((fpix = fpixCreate(w, h)) == NULL)
01508         return (FPIX *)ERROR_PTR("fpix not made", procName, NULL);
01509     data = fpixGetData(fpix);
01510     if (fread(data, 1, nbytes, fp) != nbytes)
01511         return (FPIX *)ERROR_PTR("read error for nbytes", procName, NULL);
01512 
01513         /* Convert to little-endian if necessary */
01514     fpixEndianByteSwap(fpix, fpix);
01515     return fpix;
01516 }
01517 
01518 
01519 /*!
01520  *  fpixWrite()
01521  *
01522  *      Input:  filename
01523  *              fpix
01524  *      Return: 0 if OK, 1 on error
01525  */
01526 l_int32
01527 fpixWrite(const char  *filename,
01528           FPIX        *fpix)
01529 {
01530 FILE  *fp;
01531 
01532     PROCNAME("fpixWrite");
01533 
01534     if (!filename)
01535         return ERROR_INT("filename not defined", procName, 1);
01536     if (!fpix)
01537         return ERROR_INT("fpix not defined", procName, 1);
01538 
01539     if ((fp = fopenWriteStream(filename, "wb")) == NULL)
01540         return ERROR_INT("stream not opened", procName, 1);
01541     if (fpixWriteStream(fp, fpix))
01542         return ERROR_INT("fpix not written to stream", procName, 1);
01543     fclose(fp);
01544 
01545     return 0;
01546 }
01547 
01548 
01549 /*!
01550  *  fpixWriteStream()
01551  *
01552  *      Input:  stream (opened for "wb")
01553  *              fpix
01554  *      Return: 0 if OK, 1 on error
01555  */
01556 l_int32
01557 fpixWriteStream(FILE  *fp,
01558                 FPIX  *fpix)
01559 {
01560 l_int32     w, h, nbytes;
01561 l_float32  *data;
01562 FPIX       *fpixt;
01563 
01564     PROCNAME("fpixWriteStream");
01565 
01566     if (!fp)
01567         return ERROR_INT("stream not defined", procName, 1);
01568     if (!fpix)
01569         return ERROR_INT("fpix not defined", procName, 1);
01570 
01571         /* Convert to little-endian if necessary */
01572     fpixt = fpixEndianByteSwap(NULL, fpix);
01573 
01574     fpixGetDimensions(fpixt, &w, &h);
01575     data = fpixGetData(fpixt);
01576     nbytes = 4 * h * fpixGetWpl(fpixt);
01577     fprintf(fp, "\nFPix Version %d\n", FPIX_VERSION_NUMBER);
01578     fprintf(fp, "w = %d, h = %d, nbytes = %d\n", w, h, nbytes);
01579     fwrite(data, 1, nbytes, fp);
01580 
01581     fpixDestroy(&fpixt);
01582     return 0;
01583 }
01584 
01585 
01586 /*!
01587  *  fpixEndianByteSwap()
01588  *
01589  *      Input:  fpixd (can be equal to fpixs or NULL)
01590  *              fpixs
01591  *      Return: fpixd always
01592  *
01593  *  Notes:
01594  *      (1) On big-endian hardware, this does byte-swapping on each of
01595  *          the 4-byte floats in the fpix data.  On little-endians,
01596  *          the data is unchanged.  This is used for serialization
01597  *          of fpix; the data is serialized in little-endian byte
01598  *          order because most hardware is little-endian.
01599  *      (2) The operation can be either in-place or, if fpixd == NULL,
01600  *          a new fpix is made.  If not in-place, caller must catch
01601  *          the returned pointer.
01602  */
01603 FPIX *
01604 fpixEndianByteSwap(FPIX  *fpixd,
01605                    FPIX  *fpixs)
01606 {
01607     PROCNAME("fpixEndianByteSwap");
01608         
01609     if (!fpixs)
01610         return (FPIX *)ERROR_PTR("fpixs not defined", procName, fpixd);
01611     if (fpixd && (fpixs != fpixd))
01612         return (FPIX *)ERROR_PTR("fpixd != fpixs", procName, fpixd);
01613 
01614 #ifdef L_BIG_ENDIAN
01615     {
01616     l_uint32  *data;
01617     l_int32    i, j, w, h;
01618     l_uint32   word;
01619 
01620         fpixGetDimensions(fpixs, &w, &h);
01621         fpixd = fpixCopy(fpixd, fpixs);  /* no copy if fpixd == fpixs */
01622 
01623         data = (l_uint32 *)fpixGetData(fpixd);
01624         for (i = 0; i < h; i++) {
01625             for (j = 0; j < w; j++, data++) {
01626                 word = *data;
01627                 *data = (word >> 24) |
01628                         ((word >> 8) & 0x0000ff00) |
01629                         ((word << 8) & 0x00ff0000) |
01630                         (word << 24);
01631             }
01632         }
01633         return fpixd;
01634     }
01635 #else   /* L_LITTLE_ENDIAN */
01636 
01637     if (fpixd)
01638         return fpixd;  /* no-op */
01639     else
01640         return fpixClone(fpixs);
01641 
01642 #endif   /* L_BIG_ENDIAN */
01643 }
01644 
01645 
01646 /*--------------------------------------------------------------------*
01647  *                       DPix serialized I/O                          *
01648  *--------------------------------------------------------------------*/
01649 /*!
01650  *  dpixRead()
01651  *
01652  *      Input:  filename
01653  *      Return: dpix, or null on error
01654  */
01655 DPIX *
01656 dpixRead(const char  *filename)
01657 {
01658 FILE  *fp;
01659 DPIX  *dpix;
01660 
01661     PROCNAME("dpixRead");
01662 
01663     if (!filename)
01664         return (DPIX *)ERROR_PTR("filename not defined", procName, NULL);
01665     if ((fp = fopenReadStream(filename)) == NULL)
01666         return (DPIX *)ERROR_PTR("stream not opened", procName, NULL);
01667 
01668     if ((dpix = dpixReadStream(fp)) == NULL) {
01669         fclose(fp);
01670         return (DPIX *)ERROR_PTR("dpix not read", procName, NULL);
01671     }
01672 
01673     fclose(fp);
01674     return dpix;
01675 }
01676 
01677 
01678 /*!
01679  *  dpixReadStream()
01680  *
01681  *      Input:  stream
01682  *      Return: dpix, or null on error
01683  */
01684 DPIX *
01685 dpixReadStream(FILE  *fp)
01686 {
01687 l_int32     w, h, nbytes, version;
01688 l_float64  *data;
01689 DPIX       *dpix;
01690 
01691     PROCNAME("dpixReadStream");
01692 
01693     if (!fp)
01694         return (DPIX *)ERROR_PTR("stream not defined", procName, NULL);
01695 
01696     if (fscanf(fp, "\nDPix Version %d\n", &version) != 1)
01697         return (DPIX *)ERROR_PTR("not a dpix file", procName, NULL);
01698     if (version != DPIX_VERSION_NUMBER)
01699         return (DPIX *)ERROR_PTR("invalid dpix version", procName, NULL);
01700     if (fscanf(fp, "w = %d, h = %d, nbytes = %d\n", &w, &h, &nbytes) != 3)
01701         return (DPIX *)ERROR_PTR("read fail for data size", procName, NULL);
01702 
01703     if ((dpix = dpixCreate(w, h)) == NULL)
01704         return (DPIX *)ERROR_PTR("dpix not made", procName, NULL);
01705     data = dpixGetData(dpix);
01706     if (fread(data, 1, nbytes, fp) != nbytes)
01707         return (DPIX *)ERROR_PTR("read error for nbytes", procName, NULL);
01708 
01709         /* Convert to little-endian if necessary */
01710     dpixEndianByteSwap(dpix, dpix);
01711     return dpix;
01712 }
01713 
01714 
01715 /*!
01716  *  dpixWrite()
01717  *
01718  *      Input:  filename
01719  *              dpix
01720  *      Return: 0 if OK, 1 on error
01721  */
01722 l_int32
01723 dpixWrite(const char  *filename,
01724           DPIX        *dpix)
01725 {
01726 FILE  *fp;
01727 
01728     PROCNAME("dpixWrite");
01729 
01730     if (!filename)
01731         return ERROR_INT("filename not defined", procName, 1);
01732     if (!dpix)
01733         return ERROR_INT("dpix not defined", procName, 1);
01734 
01735     if ((fp = fopenWriteStream(filename, "wb")) == NULL)
01736         return ERROR_INT("stream not opened", procName, 1);
01737     if (dpixWriteStream(fp, dpix))
01738         return ERROR_INT("dpix not written to stream", procName, 1);
01739     fclose(fp);
01740 
01741     return 0;
01742 }
01743 
01744 
01745 /*!
01746  *  dpixWriteStream()
01747  *
01748  *      Input:  stream (opened for "wb")
01749  *              dpix
01750  *      Return: 0 if OK, 1 on error
01751  */
01752 l_int32
01753 dpixWriteStream(FILE  *fp,
01754                 DPIX  *dpix)
01755 {
01756 l_int32     w, h, nbytes;
01757 l_float64  *data;
01758 DPIX       *dpixt;
01759 
01760     PROCNAME("dpixWriteStream");
01761 
01762     if (!fp)
01763         return ERROR_INT("stream not defined", procName, 1);
01764     if (!dpix)
01765         return ERROR_INT("dpix not defined", procName, 1);
01766 
01767         /* Convert to little-endian if necessary */
01768     dpixt = dpixEndianByteSwap(NULL, dpix);
01769 
01770     dpixGetDimensions(dpixt, &w, &h);
01771     data = dpixGetData(dpixt);
01772     nbytes = 8 * h * dpixGetWpl(dpixt);
01773     fprintf(fp, "\nDPix Version %d\n", DPIX_VERSION_NUMBER);
01774     fprintf(fp, "w = %d, h = %d, nbytes = %d\n", w, h, nbytes);
01775     fwrite(data, 1, nbytes, fp);
01776 
01777     dpixDestroy(&dpixt);
01778     return 0;
01779 }
01780 
01781 
01782 /*!
01783  *  dpixEndianByteSwap()
01784  *
01785  *      Input:  dpixd (can be equal to dpixs or NULL)
01786  *              dpixs
01787  *      Return: dpixd always
01788  *
01789  *  Notes:
01790  *      (1) On big-endian hardware, this does byte-swapping on each of
01791  *          the 4-byte words in the dpix data.  On little-endians,
01792  *          the data is unchanged.  This is used for serialization
01793  *          of dpix; the data is serialized in little-endian byte
01794  *          order because most hardware is little-endian.
01795  *      (2) The operation can be either in-place or, if dpixd == NULL,
01796  *          a new dpix is made.  If not in-place, caller must catch
01797  *          the returned pointer.
01798  */
01799 DPIX *
01800 dpixEndianByteSwap(DPIX  *dpixd,
01801                    DPIX  *dpixs)
01802 {
01803     PROCNAME("dpixEndianByteSwap");
01804         
01805     if (!dpixs)
01806         return (DPIX *)ERROR_PTR("dpixs not defined", procName, dpixd);
01807     if (dpixd && (dpixs != dpixd))
01808         return (DPIX *)ERROR_PTR("dpixd != dpixs", procName, dpixd);
01809 
01810 #ifdef L_BIG_ENDIAN
01811     {
01812     l_uint32  *data;
01813     l_int32    i, j, w, h;
01814     l_uint32   word;
01815 
01816         dpixGetDimensions(dpixs, &w, &h);
01817         dpixd = dpixCopy(dpixd, dpixs);  /* no copy if dpixd == dpixs */
01818 
01819         data = (l_uint32 *)dpixGetData(dpixd);
01820         for (i = 0; i < h; i++) {
01821             for (j = 0; j < 2 * w; j++, data++) {
01822                 word = *data;
01823                 *data = (word >> 24) |
01824                         ((word >> 8) & 0x0000ff00) |
01825                         ((word << 8) & 0x00ff0000) |
01826                         (word << 24);
01827             }
01828         }
01829         return dpixd;
01830     }
01831 #else   /* L_LITTLE_ENDIAN */
01832 
01833     if (dpixd)
01834         return dpixd;  /* no-op */
01835     else
01836         return dpixClone(dpixs);
01837 
01838 #endif   /* L_BIG_ENDIAN */
01839 }
01840 
01841 
01842 /*--------------------------------------------------------------------*
01843  *                 Print FPix (subsampled, for debugging)             *
01844  *--------------------------------------------------------------------*/
01845 /*!
01846  *  fpixPrintStream()
01847  *
01848  *      Input:  stream
01849  *              fpix
01850  *              factor (subsampled)
01851  *      Return: 0 if OK, 1 on error
01852  *
01853  *  Notes:
01854  *      (1) Subsampled printout of fpix for debugging.
01855  */
01856 l_int32
01857 fpixPrintStream(FILE    *fp,
01858                 FPIX    *fpix,
01859                 l_int32  factor)
01860 {
01861 l_int32    i, j, w, h, count;
01862 l_float32  val;
01863 
01864     PROCNAME("fpixPrintStream");
01865 
01866     if (!fp)
01867         return ERROR_INT("stream not defined", procName, 1);
01868     if (!fpix)
01869         return ERROR_INT("fpix not defined", procName, 1);
01870     if (factor < 1)
01871         return ERROR_INT("sampling factor < 1f", procName, 1);
01872 
01873     fpixGetDimensions(fpix, &w, &h);
01874     fprintf(fp, "\nFPix: w = %d, h = %d\n", w, h);
01875     for (i = 0; i < h; i += factor) {
01876         for (count = 0, j = 0; j < w; j += factor, count++) {
01877             fpixGetPixel(fpix, j, i, &val);
01878             fprintf(fp, "val[%d, %d] = %f   ", i, j, val);
01879             if ((count + 1) % 3 == 0) fprintf(fp, "\n");
01880         }
01881         if (count % 3) fprintf(fp, "\n");
01882      }
01883      fprintf(fp, "\n");
01884      return 0;
01885 }
01886 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines