Leptonica 1.68
C Image Processing Library

fpix2.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  *  fpix2.c
00018  *
00019  *    This file has these FPix utilities:
00020  *       - interconversion with pix
00021  *       - interconversion with dpix
00022  *       - min and max values
00023  *       - border functions
00024  *       - simple rasterop (source --> dest)
00025  *       - integer scaling
00026  *       - arithmetic operations
00027  *
00028  *    Interconversions between Pix and FPix
00029  *          FPIX          *pixConvertToFPix()
00030  *          PIX           *fpixConvertToPix()
00031  *          PIX           *fpixDisplayMaxDynamicRange()  [useful for debugging]
00032  *
00033  *    Interconversions between FPix and DPix
00034  *          DPIX          *fpixConvertToDPix()
00035  *          FPIX          *dpixConvertToFPix()
00036  *
00037  *    FPix min/max value
00038  *          l_int32        fpixGetMin()
00039  *          l_int32        fpixGetMax()
00040  *
00041  *    FPix border functions
00042  *          FPIX          *fpixAddBorder()
00043  *          FPIX          *fpixRemoveBorder()
00044  *          FPIX          *fpixAddMirroredBorder()
00045  *
00046  *    FPix simple rasterop
00047  *          l_int32        fpixRasterop()
00048  *
00049  *    Integer scaling
00050  *          FPIX          *fpixScaleByInteger()
00051  *          DPIX          *dpixScaleByInteger()
00052  *
00053  *    FPix arithmetic operations
00054  *          FPIX          *fpixLinearCombination()
00055  *          l_int32        fpixAddMultConstant()
00056  */
00057 
00058 #include "allheaders.h"
00059 
00060 /*--------------------------------------------------------------------*
00061  *                     FPix  <-->  Pix conversions                    *
00062  *--------------------------------------------------------------------*/
00063 /*!
00064  *  pixConvertToFPix()
00065  *
00066  *      Input:  pix (1, 2, 4, 8, 16 or 32 bpp)
00067  *              ncomps (number of components: 3 for RGB, 1 otherwise)
00068  *      Return: fpix, or null on error
00069  *
00070  *  Notes:
00071  *      (1) If colormapped, remove to grayscale.
00072  *      (2) If 32 bpp and @ncomps == 3, this is RGB; convert to luminance.
00073  *          In all other cases the src image is treated as having a single
00074  *          component of pixel values.
00075  */
00076 FPIX *
00077 pixConvertToFPix(PIX     *pixs,
00078                  l_int32  ncomps)
00079 {
00080 l_int32     w, h, d, i, j, val, wplt, wpld;
00081 l_uint32    uval;
00082 l_uint32   *datat, *linet;
00083 l_float32  *datad, *lined;
00084 PIX        *pixt;
00085 FPIX       *fpixd;
00086 
00087     PROCNAME("pixConvertToFPix");
00088 
00089     if (!pixs)
00090         return (FPIX *)ERROR_PTR("pixs not defined", procName, NULL);
00091 
00092     if (pixGetColormap(pixs))
00093         pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
00094     else if (pixGetDepth(pixs) == 32 && ncomps == 3)
00095         pixt = pixConvertRGBToLuminance(pixs);
00096     else
00097         pixt = pixClone(pixs);
00098 
00099     pixGetDimensions(pixt, &w, &h, &d);
00100     if ((fpixd = fpixCreate(w, h)) == NULL)
00101         return (FPIX *)ERROR_PTR("fpixd not made", procName, NULL);
00102     datat = pixGetData(pixt);
00103     wplt = pixGetWpl(pixt);
00104     datad = fpixGetData(fpixd);
00105     wpld = fpixGetWpl(fpixd);
00106     for (i = 0; i < h; i++) {
00107         linet = datat + i * wplt;
00108         lined = datad + i * wpld;
00109         if (d == 1) {
00110             for (j = 0; j < w; j++) {
00111                 val = GET_DATA_BIT(linet, j);
00112                 lined[j] = (l_float32)val;
00113             }
00114         }
00115         else if (d == 2) {
00116             for (j = 0; j < w; j++) {
00117                 val = GET_DATA_DIBIT(linet, j);
00118                 lined[j] = (l_float32)val;
00119             }
00120         }
00121         else if (d == 4) {
00122             for (j = 0; j < w; j++) {
00123                 val = GET_DATA_QBIT(linet, j);
00124                 lined[j] = (l_float32)val;
00125             }
00126         }
00127         else if (d == 8) {
00128             for (j = 0; j < w; j++) {
00129                 val = GET_DATA_BYTE(linet, j);
00130                 lined[j] = (l_float32)val;
00131             }
00132         }
00133         else if (d == 16) {
00134             for (j = 0; j < w; j++) {
00135                 val = GET_DATA_TWO_BYTES(linet, j);
00136                 lined[j] = (l_float32)val;
00137             }
00138         }
00139         else if (d == 32) {
00140             for (j = 0; j < w; j++) {
00141                 uval = GET_DATA_FOUR_BYTES(linet, j);
00142                 lined[j] = (l_float32)uval;
00143             }
00144         }
00145     }
00146 
00147     pixDestroy(&pixt);
00148     return fpixd;
00149 }
00150 
00151 
00152 /*!
00153  *  fpixConvertToPix()
00154  *
00155  *      Input:  fpixs
00156  *              outdepth (0, 8, 16 or 32 bpp)
00157  *              negvals (L_CLIP_TO_ZERO, L_TAKE_ABSVAL)
00158  *              errorflag (1 to output error stats; 0 otherwise)
00159  *      Return: pixd, or null on error
00160  *
00161  *  Notes:
00162  *      (1) Use @outdepth = 0 to programmatically determine the
00163  *          output depth.  If no values are greater than 255,
00164  *          it will set outdepth = 8; otherwise to 16 or 32.
00165  *      (2) Because we are converting a float to an unsigned int
00166  *          with a specified dynamic range (8, 16 or 32 bits), errors
00167  *          can occur.  If errorflag == TRUE, output the number
00168  *          of values out of range, both negative and positive.
00169  *      (3) If a pixel value is positive and out of range, clip to
00170  *          the maximum value represented at the outdepth of 8, 16
00171  *          or 32 bits.
00172  */
00173 PIX *
00174 fpixConvertToPix(FPIX    *fpixs,
00175                  l_int32  outdepth,
00176                  l_int32  negvals,
00177                  l_int32  errorflag)
00178 {
00179 l_int32     w, h, i, j, wpls, wpld, maxval;
00180 l_uint32    vald;
00181 l_float32   val;
00182 l_float32  *datas, *lines;
00183 l_uint32   *datad, *lined;
00184 PIX        *pixd;
00185 
00186     PROCNAME("fpixConvertToPix");
00187 
00188     if (!fpixs)
00189         return (PIX *)ERROR_PTR("fpixs not defined", procName, NULL);
00190     if (negvals != L_CLIP_TO_ZERO && negvals != L_TAKE_ABSVAL)
00191         return (PIX *)ERROR_PTR("invalid negvals", procName, NULL);
00192     if (outdepth != 0 && outdepth != 8 && outdepth != 16 && outdepth != 32)
00193         return (PIX *)ERROR_PTR("outdepth not in {0,8,16,32}", procName, NULL);
00194 
00195     fpixGetDimensions(fpixs, &w, &h);
00196     datas = fpixGetData(fpixs);
00197     wpls = fpixGetWpl(fpixs);
00198 
00199         /* Adaptive determination of output depth */
00200     if (outdepth == 0) {
00201         outdepth = 8;
00202         for (i = 0; i < h; i++) {
00203             lines = datas + i * wpls;
00204             for (j = 0; j < w; j++) {
00205                 if (lines[j] > 65535.5) {
00206                     outdepth = 32;
00207                     break;
00208                 }
00209                 if (lines[j] > 255.5)
00210                     outdepth = 16;
00211             }
00212             if (outdepth == 32) break;
00213         }
00214     }
00215     maxval = (1 << outdepth) - 1;
00216 
00217         /* Gather statistics if @errorflag = TRUE */
00218     if (errorflag) {
00219         l_int32  negs = 0;
00220         l_int32  overvals = 0;
00221         for (i = 0; i < h; i++) {
00222             lines = datas + i * wpls;
00223             for (j = 0; j < w; j++) {
00224                 val = lines[j];
00225                 if (val < 0.0)
00226                     negs++;
00227                 else if (val > maxval)
00228                     overvals++;
00229             }
00230         }
00231         if (negs > 0)
00232             L_ERROR_INT("Number of negative values: %d", procName, negs);
00233         if (overvals > 0)
00234             L_ERROR_INT("Number of too-large values: %d", procName, overvals);
00235     }
00236 
00237         /* Make the pix and convert the data */
00238     if ((pixd = pixCreate(w, h, outdepth)) == NULL)
00239         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00240     datad = pixGetData(pixd);
00241     wpld = pixGetWpl(pixd);
00242     for (i = 0; i < h; i++) {
00243         lines = datas + i * wpls;
00244         lined = datad + i * wpld;
00245         for (j = 0; j < w; j++) {
00246             val = lines[j];
00247             if (val >= 0.0)
00248                 vald = (l_uint32)(val + 0.5);
00249             else {  /* val < 0.0 */
00250                 if (negvals == L_CLIP_TO_ZERO)
00251                     vald = 0;
00252                 else
00253                     vald = (l_uint32)(-val + 0.5);
00254             }
00255             if (vald > maxval)
00256                 vald = maxval;
00257             if (outdepth == 8)
00258                 SET_DATA_BYTE(lined, j, vald);
00259             else if (outdepth == 16)
00260                 SET_DATA_TWO_BYTES(lined, j, vald);
00261             else  /* outdepth == 32 */
00262                 SET_DATA_FOUR_BYTES(lined, j, vald);
00263         }
00264     }
00265 
00266     return pixd;
00267 }
00268 
00269 
00270 /*!
00271  *  fpixDisplayMaxDynamicRange()
00272  *
00273  *      Input:  fpixs
00274  *      Return: pixd (8 bpp), or null on error
00275  */
00276 PIX *
00277 fpixDisplayMaxDynamicRange(FPIX  *fpixs)
00278 {
00279 l_uint8     dval;
00280 l_int32     i, j, w, h, wpls, wpld;
00281 l_float32   factor, sval, maxval;
00282 l_float32  *lines, *datas;
00283 l_uint32   *lined, *datad;
00284 PIX        *pixd;
00285 
00286     PROCNAME("fpixDisplayMaxDynamicRange");
00287 
00288     if (!fpixs)
00289         return (PIX *)ERROR_PTR("fpixs not defined", procName, NULL);
00290 
00291     fpixGetDimensions(fpixs, &w, &h);
00292     datas = fpixGetData(fpixs);
00293     wpls = fpixGetWpl(fpixs);
00294 
00295     maxval = 0.0;
00296     for (i = 0; i < h; i++) {
00297         lines = datas + i * wpls;
00298         for (j = 0; j < w; j++) {
00299             sval = *(lines + j);
00300             if (sval > maxval)
00301                 maxval = sval;
00302         }
00303     }
00304 
00305     pixd = pixCreate(w, h, 8);
00306     if (maxval == 0.0)
00307         return pixd;  /* all pixels are 0 */
00308 
00309     datad = pixGetData(pixd);
00310     wpld = pixGetWpl(pixd);
00311     factor = 255. / maxval;
00312     for (i = 0; i < h; i++) {
00313         lines = datas + i * wpls;
00314         lined = datad + i * wpld;
00315         for (j = 0; j < w; j++) {
00316             sval = *(lines + j);
00317             if (sval < 0.0) sval = 0.0;
00318             dval = (l_uint8)(factor * sval + 0.5);
00319             SET_DATA_BYTE(lined, j, dval);
00320         }
00321     }
00322 
00323     return pixd;
00324 }
00325 
00326 
00327 /*--------------------------------------------------------------------*
00328  *                     FPix  <-->  DPix conversions                   *
00329  *--------------------------------------------------------------------*/
00330 /*!
00331  *  fpixConvertToDPix()
00332  *
00333  *      Input:  fpix
00334  *      Return: dpix, or null on error
00335  */
00336 DPIX *
00337 fpixConvertToDPix(FPIX  *fpix)
00338 {
00339 l_int32     w, h, i, j, wpls, wpld;
00340 l_float32   val;
00341 l_float32  *datas, *lines;
00342 l_float64  *datad, *lined;
00343 DPIX       *dpix;
00344 
00345     PROCNAME("fpixConvertToDPix");
00346 
00347     if (!fpix)
00348         return (DPIX *)ERROR_PTR("fpix not defined", procName, NULL);
00349 
00350     fpixGetDimensions(fpix, &w, &h);
00351     if ((dpix = dpixCreate(w, h)) == NULL)
00352         return (DPIX *)ERROR_PTR("dpix not made", procName, NULL);
00353 
00354     datas = fpixGetData(fpix);
00355     datad = dpixGetData(dpix);
00356     wpls = fpixGetWpl(fpix);
00357     wpld = dpixGetWpl(dpix);  /* 8 byte words */
00358     for (i = 0; i < h; i++) {
00359         lines = datas + i * wpls;
00360         lined = datad + i * wpld;
00361         for (j = 0; j < w; j++) {
00362             val = lines[j];
00363             lined[j] = val;
00364         }
00365     }
00366 
00367     return dpix;
00368 }
00369 
00370 
00371 /*!
00372  *  dpixConvertToFPix()
00373  *
00374  *      Input:  dpix
00375  *      Return: fpix, or null on error
00376  */
00377 FPIX *
00378 dpixConvertToFPix(DPIX  *dpix)
00379 {
00380 l_int32     w, h, i, j, wpls, wpld;
00381 l_float64   val;
00382 l_float32  *datad, *lined;
00383 l_float64  *datas, *lines;
00384 FPIX       *fpix;
00385 
00386     PROCNAME("dpixConvertToFPix");
00387 
00388     if (!dpix)
00389         return (FPIX *)ERROR_PTR("dpix not defined", procName, NULL);
00390 
00391     dpixGetDimensions(dpix, &w, &h);
00392     if ((fpix = fpixCreate(w, h)) == NULL)
00393         return (FPIX *)ERROR_PTR("fpix not made", procName, NULL);
00394 
00395     datas = dpixGetData(dpix);
00396     datad = fpixGetData(fpix);
00397     wpls = dpixGetWpl(dpix);  /* 8 byte words */
00398     wpld = fpixGetWpl(fpix);
00399     for (i = 0; i < h; i++) {
00400         lines = datas + i * wpls;
00401         lined = datad + i * wpld;
00402         for (j = 0; j < w; j++) {
00403             val = lines[j];
00404             lined[j] = (l_float32)val;
00405         }
00406     }
00407 
00408     return fpix;
00409 }
00410 
00411 
00412 
00413 /*--------------------------------------------------------------------*
00414  *                           Min/max value                            *
00415  *--------------------------------------------------------------------*/
00416 /*!
00417  *  fpixGetMin()
00418  *
00419  *      Input:  fpix
00420  *              &minval (<optional return> min value)
00421  *              &xminloc (<optional return> x location of min)
00422  *              &yminloc (<optional return> y location of min)
00423  *      Return: 0 if OK; 1 on error
00424  */
00425 l_int32
00426 fpixGetMin(FPIX       *fpix,
00427            l_float32  *pminval,
00428            l_int32    *pxminloc,
00429            l_int32    *pyminloc)
00430 {
00431 l_int32     i, j, w, h, wpl, xminloc, yminloc;
00432 l_float32  *data, *line;
00433 l_float32   minval;
00434 
00435     PROCNAME("fpixGetMin");
00436 
00437     if (!pminval && !pxminloc && !pyminloc)
00438         return ERROR_INT("nothing to do", procName, 1);
00439     if (pminval) *pminval = 0.0;
00440     if (pxminloc) *pxminloc = 0;
00441     if (pyminloc) *pyminloc = 0;
00442     if (!fpix)
00443         return ERROR_INT("fpix not defined", procName, 1);
00444 
00445     minval = +1.0e20;
00446     xminloc = 0;
00447     yminloc = 0;
00448     fpixGetDimensions(fpix, &w, &h);
00449     data = fpixGetData(fpix);
00450     wpl = fpixGetWpl(fpix);
00451     for (i = 0; i < h; i++) {
00452         line = data + i * wpl;
00453         for (j = 0; j < w; j++) {
00454             if (line[j] < minval) {
00455                 minval = line[j];
00456                 xminloc = j;
00457                 yminloc = i;
00458             }
00459         }
00460     }
00461 
00462     if (pminval) *pminval = minval;
00463     if (pxminloc) *pxminloc = xminloc;
00464     if (pyminloc) *pyminloc = yminloc;
00465     return 0;
00466 }
00467 
00468 
00469 /*!
00470  *  fpixGetMax()
00471  *
00472  *      Input:  fpix
00473  *              &maxval (<optional return> max value)
00474  *              &xmaxloc (<optional return> x location of max)
00475  *              &ymaxloc (<optional return> y location of max)
00476  *      Return: 0 if OK; 1 on error
00477  */
00478 l_int32
00479 fpixGetMax(FPIX       *fpix,
00480            l_float32  *pmaxval,
00481            l_int32    *pxmaxloc,
00482            l_int32    *pymaxloc)
00483 {
00484 l_int32     i, j, w, h, wpl, xmaxloc, ymaxloc;
00485 l_float32  *data, *line;
00486 l_float32   maxval;
00487 
00488     PROCNAME("fpixGetMax");
00489 
00490     if (!pmaxval && !pxmaxloc && !pymaxloc)
00491         return ERROR_INT("nothing to do", procName, 1);
00492     if (pmaxval) *pmaxval = 0.0;
00493     if (pxmaxloc) *pxmaxloc = 0;
00494     if (pymaxloc) *pymaxloc = 0;
00495     if (!fpix)
00496         return ERROR_INT("fpix not defined", procName, 1);
00497 
00498     maxval = -1.0e20;
00499     xmaxloc = 0;
00500     ymaxloc = 0;
00501     fpixGetDimensions(fpix, &w, &h);
00502     data = fpixGetData(fpix);
00503     wpl = fpixGetWpl(fpix);
00504     for (i = 0; i < h; i++) {
00505         line = data + i * wpl;
00506         for (j = 0; j < w; j++) {
00507             if (line[j] < maxval) {
00508                 maxval = line[j];
00509                 xmaxloc = j;
00510                 ymaxloc = i;
00511             }
00512         }
00513     }
00514 
00515     if (pmaxval) *pmaxval = maxval;
00516     if (pxmaxloc) *pxmaxloc = xmaxloc;
00517     if (pymaxloc) *pymaxloc = ymaxloc;
00518     return 0;
00519 }
00520 
00521 
00522 /*--------------------------------------------------------------------*
00523  *                          Border functions                          *
00524  *--------------------------------------------------------------------*/
00525 /*!
00526  *  fpixAddBorder()
00527  *
00528  *      Input:  fpixs
00529  *              left, right, top, bot (pixels on each side to be added)
00530  *      Return: fpixd, or null on error
00531  *
00532  *  Notes:
00533  *      (1) Adds border of '0' 32-bit pixels
00534  */
00535 FPIX *
00536 fpixAddBorder(FPIX    *fpixs,
00537               l_int32  left,
00538               l_int32  right,
00539               l_int32  top,
00540               l_int32  bot)
00541 {
00542 l_int32  ws, hs, wd, hd;
00543 FPIX    *fpixd;
00544 
00545     PROCNAME("fpixAddBorder");
00546 
00547     if (!fpixs)
00548         return (FPIX *)ERROR_PTR("fpixs not defined", procName, NULL);
00549 
00550     if (left <= 0 && right <= 0 && top <= 0 && bot <= 0)
00551         return fpixCopy(NULL, fpixs);
00552     fpixGetDimensions(fpixs, &ws, &hs);
00553     wd = ws + left + right;
00554     hd = hs + top + bot;
00555     if ((fpixd = fpixCreate(wd, hd)) == NULL)
00556         return (FPIX *)ERROR_PTR("fpixd not made", procName, NULL);
00557 
00558     fpixCopyResolution(fpixd, fpixs);
00559     fpixRasterop(fpixd, left, top, ws, hs, fpixs, 0, 0);
00560     return fpixd;
00561 }
00562 
00563 
00564 /*!
00565  *  fpixRemoveBorder()
00566  *
00567  *      Input:  fpixs
00568  *              left, right, top, bot (pixels on each side to be removed)
00569  *      Return: fpixd, or null on error
00570  */
00571 FPIX *
00572 fpixRemoveBorder(FPIX    *fpixs,
00573                  l_int32  left,
00574                  l_int32  right,
00575                  l_int32  top,
00576                  l_int32  bot)
00577 {
00578 l_int32  ws, hs, wd, hd;
00579 FPIX    *fpixd;
00580 
00581     PROCNAME("fpixRemoveBorder");
00582 
00583     if (!fpixs)
00584         return (FPIX *)ERROR_PTR("fpixs not defined", procName, NULL);
00585 
00586     if (left <= 0 && right <= 0 && top <= 0 && bot <= 0)
00587         return fpixCopy(NULL, fpixs);
00588     fpixGetDimensions(fpixs, &ws, &hs);
00589     wd = ws - left - right;
00590     hd = hs - top - bot;
00591     if (wd <= 0 || hd <= 0)
00592         return (FPIX *)ERROR_PTR("width & height not both > 0", procName, NULL);
00593     if ((fpixd = fpixCreate(wd, hd)) == NULL)
00594         return (FPIX *)ERROR_PTR("fpixd not made", procName, NULL);
00595 
00596     fpixCopyResolution(fpixd, fpixs);
00597     fpixRasterop(fpixd, 0, 0, wd, hd, fpixs, left, top);
00598     return fpixd;
00599 }
00600 
00601 
00602 
00603 /*!
00604  *  fpixAddMirroredBorder()
00605  *
00606  *      Input:  fpixs
00607  *              left, right, top, bot (pixels on each side to be added)
00608  *      Return: fpixd, or null on error
00609  *
00610  *  Notes:
00611  *      (1) See pixAddMirroredBorder() for situations of usage.
00612  */
00613 FPIX *
00614 fpixAddMirroredBorder(FPIX    *fpixs,
00615                       l_int32  left,
00616                       l_int32  right,
00617                       l_int32  top,
00618                       l_int32  bot)
00619 {
00620 l_int32  i, j, w, h;
00621 FPIX    *fpixd;
00622 
00623     PROCNAME("fpixAddMirroredBorder");
00624 
00625     if (!fpixs)
00626         return (FPIX *)ERROR_PTR("fpixs not defined", procName, NULL);
00627 
00628     fpixd = fpixAddBorder(fpixs, left, right, top, bot);
00629     fpixGetDimensions(fpixs, &w, &h);
00630     for (j = 0; j < left; j++)
00631         fpixRasterop(fpixd, left - 1 - j, top, 1, h,
00632                      fpixd, left + j, top);
00633     for (j = 0; j < right; j++)
00634         fpixRasterop(fpixd, left + w + j, top, 1, h,
00635                      fpixd, left + w - 1 - j, top);
00636     for (i = 0; i < top; i++)
00637         fpixRasterop(fpixd, 0, top - 1 - i, left + w + right, 1,
00638                      fpixd, 0, top + i);
00639     for (i = 0; i < bot; i++)
00640         fpixRasterop(fpixd, 0, top + h + i, left + w + right, 1,
00641                      fpixd, 0, top + h - 1 - i);
00642 
00643     return fpixd;
00644 }
00645 
00646 
00647 /*--------------------------------------------------------------------*
00648  *                          Simple rasterop                           *
00649  *--------------------------------------------------------------------*/
00650 /*!
00651  *  fpixRasterop()
00652  *
00653  *      Input:  fpixd  (dest fpix)
00654  *              dx     (x val of UL corner of dest rectangle)
00655  *              dy     (y val of UL corner of dest rectangle)
00656  *              dw     (width of dest rectangle)
00657  *              dh     (height of dest rectangle)
00658  *              fpixs  (src fpix)
00659  *              sx     (x val of UL corner of src rectangle)
00660  *              sy     (y val of UL corner of src rectangle)
00661  *      Return: 0 if OK; 1 on error.
00662  *
00663  *  Notes:
00664  *      (1) This is similiar in structure to pixRasterop(), except
00665  *          it only allows copying from the source into the destination.
00666  *          For that reason, no op code is necessary.  Additionally,
00667  *          all pixels are 32 bit words (float values), which makes
00668  *          the copy very simple.
00669  *      (2) Clipping of both src and dest fpix are done automatically.
00670  *      (3) This allows in-place copying, without checking to see if
00671  *          the result is valid:  use for in-place with caution!
00672  */
00673 l_int32
00674 fpixRasterop(FPIX    *fpixd,
00675              l_int32  dx,
00676              l_int32  dy,
00677              l_int32  dw,
00678              l_int32  dh,
00679              FPIX    *fpixs,
00680              l_int32  sx,
00681              l_int32  sy)
00682 {
00683 l_int32     fsw, fsh, fdw, fdh, dhangw, shangw, dhangh, shangh;
00684 l_int32     i, j, wpls, wpld;
00685 l_float32  *datas, *datad, *lines, *lined;
00686 
00687     PROCNAME("fpixRasterop");
00688 
00689     if (!fpixs)
00690         return ERROR_INT("fpixs not defined", procName, 1);
00691     if (!fpixd)
00692         return ERROR_INT("fpixd not defined", procName, 1);
00693 
00694     /* -------------------------------------------------------- *
00695      *      Clip to maximum rectangle with both src and dest    *
00696      * -------------------------------------------------------- */
00697     fpixGetDimensions(fpixs, &fsw, &fsh);
00698     fpixGetDimensions(fpixd, &fdw, &fdh);
00699 
00700         /* First clip horizontally (sx, dx, dw) */
00701     if (dx < 0) {
00702         sx -= dx;  /* increase sx */
00703         dw += dx;  /* reduce dw */
00704         dx = 0;
00705     }
00706     if (sx < 0) {
00707         dx -= sx;  /* increase dx */
00708         dw += sx;  /* reduce dw */
00709         sx = 0;
00710     }
00711     dhangw = dx + dw - fdw;  /* rect overhang of dest to right */
00712     if (dhangw > 0)
00713         dw -= dhangw;  /* reduce dw */
00714     shangw = sx + dw - fsw;   /* rect overhang of src to right */
00715     if (shangw > 0)
00716         dw -= shangw;  /* reduce dw */
00717 
00718         /* Then clip vertically (sy, dy, dh) */
00719     if (dy < 0) {
00720         sy -= dy;  /* increase sy */
00721         dh += dy;  /* reduce dh */
00722         dy = 0;
00723     }
00724     if (sy < 0) {
00725         dy -= sy;  /* increase dy */
00726         dh += sy;  /* reduce dh */
00727         sy = 0;
00728     }
00729     dhangh = dy + dh - fdh;  /* rect overhang of dest below */
00730     if (dhangh > 0)
00731         dh -= dhangh;  /* reduce dh */
00732     shangh = sy + dh - fsh;  /* rect overhang of src below */
00733     if (shangh > 0)
00734         dh -= shangh;  /* reduce dh */
00735 
00736         /* if clipped entirely, quit */
00737     if ((dw <= 0) || (dh <= 0))
00738         return 0;
00739 
00740     /* -------------------------------------------------------- *
00741      *                    Copy block of data                    *
00742      * -------------------------------------------------------- */
00743     datas = fpixGetData(fpixs);
00744     datad = fpixGetData(fpixd);
00745     wpls = fpixGetWpl(fpixs);
00746     wpld = fpixGetWpl(fpixd);
00747     datas += sy * wpls + sx;  /* at UL corner of block */
00748     datad += dy * wpld + dx;  /* at UL corner of block */
00749     for (i = 0; i < dh; i++) {
00750         lines = datas + i * wpls;
00751         lined = datad + i * wpld;
00752         for (j = 0; j < dw; j++) {
00753             *lined = *lines;
00754             lines++;
00755             lined++;
00756         }
00757     }
00758 
00759     return 0;
00760 }
00761 
00762 
00763 /*--------------------------------------------------------------------*
00764  *                       Special integer scaling                      *
00765  *--------------------------------------------------------------------*/
00766 /*!
00767  *  fpixScaleByInteger()
00768  *
00769  *      Input:  fpixs (low resolution, subsampled)
00770  *              factor (scaling factor)
00771  *      Return: fpixd (interpolated result), or null on error
00772  *
00773  *  Notes:
00774  *      (1) The width wd of fpixd is related to ws of fpixs by:
00775  *              wd = factor * (ws - 1) + 1   (and ditto for the height)
00776  *          We avoid special-casing boundary pixels in the interpolation
00777  *          by constructing fpixd by inserting (factor - 1) interpolated
00778  *          pixels between each pixel in fpixs.  Then
00779  *               wd = ws + (ws - 1) * (factor - 1)    (same as above)
00780  *          This also has the advantage that if we subsample by @factor,
00781  *          throwing out all the interpolated pixels, we regain the
00782  *          original low resolution fpix.
00783  */
00784 FPIX *
00785 fpixScaleByInteger(FPIX    *fpixs,
00786                    l_int32  factor)
00787 {
00788 l_int32     i, j, k, m, ws, hs, wd, hd, wpls, wpld;
00789 l_float32   val0, val1, val2, val3;
00790 l_float32  *datas, *datad, *lines, *lined, *fract;
00791 FPIX       *fpixd;
00792 
00793     PROCNAME("fpixScaleByInteger");
00794 
00795     if (!fpixs)
00796         return (FPIX *)ERROR_PTR("fpixs not defined", procName, NULL);
00797 
00798     fpixGetDimensions(fpixs, &ws, &hs);
00799     wd = factor * (ws - 1) + 1;
00800     hd = factor * (hs - 1) + 1;
00801     fpixd = fpixCreate(wd, hd);
00802     datas = fpixGetData(fpixs);
00803     datad = fpixGetData(fpixd);
00804     wpls = fpixGetWpl(fpixs);
00805     wpld = fpixGetWpl(fpixd);
00806     fract = (l_float32 *)CALLOC(factor, sizeof(l_float32));
00807     for (i = 0; i < factor; i++)
00808         fract[i] = i / (l_float32)factor;
00809     for (i = 0; i < hs - 1; i++) {
00810         lines = datas + i * wpls;
00811         for (j = 0; j < ws - 1; j++) {
00812             val0 = lines[j];
00813             val1 = lines[j + 1];
00814             val2 = lines[wpls + j];
00815             val3 = lines[wpls + j + 1];
00816             for (k = 0; k < factor; k++) {  /* rows of sub-block */
00817                 lined = datad + (i * factor + k) * wpld;
00818                 for (m = 0; m < factor; m++) {  /* cols of sub-block */
00819                      *(lined + j * factor + m) =
00820                             val0 * (1.0 - fract[m]) * (1.0 - fract[k]) +
00821                             val1 * fract[m] * (1.0 - fract[k]) +
00822                             val2 * (1.0 - fract[m]) * fract[k] +
00823                             val3 * fract[m] * fract[k];
00824                 }
00825             }
00826         }
00827     }
00828 
00829         /* Do the right-most column of fpixd, skipping LR corner */
00830     for (i = 0; i < hs - 1; i++) {
00831         lines = datas + i * wpls;
00832         val0 = lines[ws - 1];
00833         val1 = lines[wpls + ws - 1];
00834         for (k = 0; k < factor; k++) {
00835             lined = datad + (i * factor + k) * wpld;
00836             lined[wd - 1] = val0 * (1.0 - fract[k]) + val1 * fract[k];
00837         }
00838     }
00839 
00840         /* Do the bottom-most row of fpixd */
00841     lines = datas + (hs - 1) * wpls;
00842     lined = datad + (hd - 1) * wpld;
00843     for (j = 0; j < ws - 1; j++) {
00844         val0 = lines[j];
00845         val1 = lines[j + 1];
00846         for (m = 0; m < factor; m++)
00847             lined[j * factor + m] = val0 * (1.0 - fract[m]) + val1 * fract[m];
00848         lined[wd - 1] = lines[ws - 1];  /* LR corner */
00849     }
00850 
00851     FREE(fract);
00852     return fpixd;
00853 }
00854 
00855 
00856 /*!
00857  *  dpixScaleByInteger()
00858  *
00859  *      Input:  dpixs (low resolution, subsampled)
00860  *              factor (scaling factor)
00861  *      Return: dpixd (interpolated result), or null on error
00862  *
00863  *  Notes:
00864  *      (1) The width wd of dpixd is related to ws of dpixs by:
00865  *              wd = factor * (ws - 1) + 1   (and ditto for the height)
00866  *          We avoid special-casing boundary pixels in the interpolation
00867  *          by constructing fpixd by inserting (factor - 1) interpolated
00868  *          pixels between each pixel in fpixs.  Then
00869  *               wd = ws + (ws - 1) * (factor - 1)    (same as above)
00870  *          This also has the advantage that if we subsample by @factor,
00871  *          throwing out all the interpolated pixels, we regain the
00872  *          original low resolution dpix.
00873  */
00874 DPIX *
00875 dpixScaleByInteger(DPIX    *dpixs,
00876                    l_int32  factor)
00877 {
00878 l_int32     i, j, k, m, ws, hs, wd, hd, wpls, wpld;
00879 l_float64   val0, val1, val2, val3;
00880 l_float64  *datas, *datad, *lines, *lined, *fract;
00881 DPIX       *dpixd;
00882 
00883     PROCNAME("dpixScaleByInteger");
00884 
00885     if (!dpixs)
00886         return (DPIX *)ERROR_PTR("dpixs not defined", procName, NULL);
00887 
00888     dpixGetDimensions(dpixs, &ws, &hs);
00889     wd = factor * (ws - 1) + 1;
00890     hd = factor * (hs - 1) + 1;
00891     dpixd = dpixCreate(wd, hd);
00892     datas = dpixGetData(dpixs);
00893     datad = dpixGetData(dpixd);
00894     wpls = dpixGetWpl(dpixs);
00895     wpld = dpixGetWpl(dpixd);
00896     fract = (l_float64 *)CALLOC(factor, sizeof(l_float64));
00897     for (i = 0; i < factor; i++)
00898         fract[i] = i / (l_float64)factor;
00899     for (i = 0; i < hs - 1; i++) {
00900         lines = datas + i * wpls;
00901         for (j = 0; j < ws - 1; j++) {
00902             val0 = lines[j];
00903             val1 = lines[j + 1];
00904             val2 = lines[wpls + j];
00905             val3 = lines[wpls + j + 1];
00906             for (k = 0; k < factor; k++) {  /* rows of sub-block */
00907                 lined = datad + (i * factor + k) * wpld;
00908                 for (m = 0; m < factor; m++) {  /* cols of sub-block */
00909                      *(lined + j * factor + m) =
00910                             val0 * (1.0 - fract[m]) * (1.0 - fract[k]) +
00911                             val1 * fract[m] * (1.0 - fract[k]) +
00912                             val2 * (1.0 - fract[m]) * fract[k] +
00913                             val3 * fract[m] * fract[k];
00914                 }
00915             }
00916         }
00917     }
00918 
00919         /* Do the right-most column of dpixd, skipping LR corner */
00920     for (i = 0; i < hs - 1; i++) {
00921         lines = datas + i * wpls;
00922         val0 = lines[ws - 1];
00923         val1 = lines[wpls + ws - 1];
00924         for (k = 0; k < factor; k++) {
00925             lined = datad + (i * factor + k) * wpld;
00926             lined[wd - 1] = val0 * (1.0 - fract[k]) + val1 * fract[k];
00927         }
00928     }
00929 
00930         /* Do the bottom-most row of dpixd */
00931     lines = datas + (hs - 1) * wpls;
00932     lined = datad + (hd - 1) * wpld;
00933     for (j = 0; j < ws - 1; j++) {
00934         val0 = lines[j];
00935         val1 = lines[j + 1];
00936         for (m = 0; m < factor; m++)
00937             lined[j * factor + m] = val0 * (1.0 - fract[m]) + val1 * fract[m];
00938         lined[wd - 1] = lines[ws - 1];  /* LR corner */
00939     }
00940 
00941     FREE(fract);
00942     return dpixd;
00943 }
00944 
00945 
00946 /*--------------------------------------------------------------------*
00947  *                        Arithmetic operations                       *
00948  *--------------------------------------------------------------------*/
00949 /*!
00950  *  fpixLinearCombo()
00951  *
00952  *      Input:  fpixd (<optional>; this can be null, equal to fpixs1, or
00953  *                     different from fpixs1)
00954  *              fpixs1 (can be == to fpixd)
00955  *              fpixs2
00956  *      Return: pixd always
00957  *
00958  *  Notes:
00959  *      (1) Computes pixelwise linear combination: a * src1 + b * src2
00960  *      (2) Alignment is to UL corner.
00961  *      (3) There are 3 cases.  The result can go to a new dest,
00962  *          in-place to fpixs1, or to an existing input dest:
00963  *          * fpixd == null:   (src1 + src2) --> new fpixd
00964  *          * fpixd == fpixs1:  (src1 + src2) --> src1  (in-place)
00965  *          * fpixd != fpixs1: (src1 + src2) --> input fpixd
00966  *      (4) fpixs2 must be different from both fpixd and fpixs1.
00967  */
00968 FPIX *
00969 fpixLinearCombination(FPIX      *fpixd,
00970                       FPIX      *fpixs1,
00971                       FPIX      *fpixs2,
00972                       l_float32  a,
00973                       l_float32  b)
00974 {
00975 l_int32     i, j, ws, hs, w, h, wpls, wpld;
00976 l_float32   val;
00977 l_float32  *datas, *datad, *lines, *lined;
00978 
00979     PROCNAME("fpixLinearCombination");
00980 
00981     if (!fpixs1)
00982         return (FPIX *)ERROR_PTR("fpixs1 not defined", procName, fpixd);
00983     if (!fpixs2)
00984         return (FPIX *)ERROR_PTR("fpixs2 not defined", procName, fpixd);
00985     if (fpixs1 == fpixs2)
00986         return (FPIX *)ERROR_PTR("fpixs1 == fpixs2", procName, fpixd);
00987     if (fpixs2 == fpixd)
00988         return (FPIX *)ERROR_PTR("fpixs2 == fpixd", procName, fpixd);
00989 
00990     if (fpixs1 != fpixd)
00991         fpixd = fpixCopy(fpixd, fpixs1);
00992 
00993     datas = fpixGetData(fpixs2);
00994     datad = fpixGetData(fpixd);
00995     wpls = fpixGetWpl(fpixs2);
00996     wpld = fpixGetWpl(fpixd);
00997     fpixGetDimensions(fpixs2, &ws, &hs);
00998     fpixGetDimensions(fpixd, &w, &h);
00999     w = L_MIN(ws, w);
01000     h = L_MIN(hs, h);
01001     for (i = 0; i < h; i++) {
01002         lines = datas + i * wpls;
01003         lined = datad + i * wpld;
01004         if (a == 1.0 && b == 1.0) {  /* sum */
01005             for (j = 0; j < w; j++)
01006                 *(lined + j) += *(lines + j);
01007         }
01008         else if (a == 1.0 && b == -1.0) {  /* diff */
01009             for (j = 0; j < w; j++)
01010                 *(lined + j) -= *(lines + j);
01011         }
01012         else if (a == -1.0 && b == 1.0) {  /* diff */
01013             for (j = 0; j < w; j++) {
01014                 val = *(lined + j);
01015                 *(lined + j) = -val + *(lines + j);
01016             }
01017         }
01018         else if (a == -1.0 && b == -1.0) {
01019             for (j = 0; j < w; j++) {
01020                 val = *(lined + j);
01021                 *(lined + j) = -val - *(lines + j);
01022             }
01023         }
01024         else {
01025             for (j = 0; j < w; j++)
01026                 *(lined + j) = a * lined[j] + b * lines[j];
01027         }
01028     }
01029 
01030     return fpixd;
01031 }
01032 
01033 
01034 /*!
01035  *  fpixAddMultConstant()
01036  *
01037  *      Input:  fpix
01038  *              addc  (use 0.0 to skip the operation)
01039  *              multc (use 1.0 to skip the operation)
01040  *      Return: 0 if OK, 1 on error
01041  *
01042  *  Notes:
01043  *      (1) This is an in-place operation.
01044  *      (2) It can be used to multiply each pixel by a constant,
01045  *          and also to add a constant to each pixel.  Multiplication
01046  *          is done first.
01047  */
01048 l_int32
01049 fpixAddMultConstant(FPIX      *fpix,
01050                     l_float32  addc,
01051                     l_float32  multc)
01052 {
01053 l_int32     i, j, w, h, wpl;
01054 l_float32   val;
01055 l_float32  *line, *data;
01056 
01057     PROCNAME("fpixAddMultConstant");
01058 
01059     if (!fpix)
01060         return ERROR_INT("fpix not defined", procName, 1);
01061 
01062     if (addc == 0.0 && multc == 1.0)
01063         return 0;
01064 
01065     fpixGetDimensions(fpix, &w, &h);
01066     data = fpixGetData(fpix);
01067     wpl = fpixGetWpl(fpix);
01068     for (i = 0; i < h; i++) {
01069         line = data + i * wpl;
01070         if (addc == 0.0) {
01071             for (j = 0; j < w; j++)
01072                 *(line + j) *= multc;
01073         }
01074         else if (multc == 1.0) {
01075             for (j = 0; j < w; j++)
01076                 *(line + j) += addc;
01077         }
01078         else  {
01079             for (j = 0; j < w; j++) {
01080                 val = *(line + j);
01081                 *(line + j) = multc * val + addc;
01082             }
01083         }
01084     }
01085 
01086     return 0;
01087 }
01088 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines