Leptonica 1.68
C Image Processing Library

pixarith.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 /*
00018  *  pixarith.c
00019  *
00020  *      One-image grayscale arithmetic operations (8, 16, 32 bpp)
00021  *           l_int32     pixAddConstantGray()
00022  *           l_int32     pixMultConstantGray()
00023  *
00024  *      Two-image grayscale arithmetic operations (8, 16, 32 bpp)
00025  *           PIX        *pixAddGray()
00026  *           PIX        *pixSubtractGray()
00027  *
00028  *      Grayscale threshold operation (8, 16, 32 bpp)
00029  *           PIX        *pixThresholdToValue()
00030  *
00031  *      Image accumulator arithmetic operations
00032  *           PIX        *pixInitAccumulate()
00033  *           PIX        *pixFinalAccumulate()
00034  *           PIX        *pixFinalAccumulateThreshold()
00035  *           l_int32     pixAccumulate() 
00036  *           l_int32     pixMultConstAccumulate()
00037  *
00038  *      Absolute value of difference
00039  *           PIX        *pixAbsDifference()
00040  *
00041  *      Two-image min and max operations (8 and 16 bpp)
00042  *           PIX        *pixMinOrMax()
00043  *
00044  *      Scale pix for maximum dynamic range in 8 bpp image:
00045  *           PIX        *pixMaxDynamicRange()
00046  *
00047  *      Log base2 lookup
00048  *           l_float32  *makeLogBase2Tab()
00049  *           l_float32   getLogBase2()
00050  *
00051  *      The image accumulator operations are used when you expect
00052  *      overflow from 8 bits on intermediate results.  For example,
00053  *      you might want a tophat contrast operator which is
00054  *         3*I - opening(I,S) - closing(I,S)
00055  *      To use these operations, first use the init to generate
00056  *      a 16 bpp image, use the accumulate to add or subtract 8 bpp
00057  *      images from that, or the multiply constant to multiply
00058  *      by a small constant (much less than 256 -- we don't want
00059  *      overflow from the 16 bit images!), and when you're finished
00060  *      use final to bring the result back to 8 bpp, clipped
00061  *      if necessary.  There is also a divide function, which
00062  *      can be used to divide one image by another, scaling the
00063  *      result for maximum dynamic range, and giving back the
00064  *      8 bpp result.
00065  *
00066  *      A simpler interface to the arithmetic operations is
00067  *      provided in pixacc.c.
00068  */
00069 
00070 
00071 #include <stdio.h>
00072 #include <stdlib.h>
00073 #include <string.h>
00074 #include <math.h>
00075 #include "allheaders.h"
00076 
00077 
00078 /*-------------------------------------------------------------*
00079  *          One-image grayscale arithmetic operations          *
00080  *-------------------------------------------------------------*/
00081 /*!
00082  *  pixAddConstantGray()
00083  *
00084  *      Input:  pixs (8, 16 or 32 bpp)
00085  *              val  (amount to add to each pixel)
00086  *      Return: 0 if OK, 1 on error
00087  *
00088  *  Notes:
00089  *      (1) In-place operation.
00090  *      (2) No clipping for 32 bpp.
00091  *      (3) For 8 and 16 bpp, if val > 0 the result is clipped
00092  *          to 0xff and 0xffff, rsp.
00093  *      (4) For 8 and 16 bpp, if val < 0 the result is clipped to 0.
00094  */
00095 l_int32
00096 pixAddConstantGray(PIX      *pixs,
00097                    l_int32   val)
00098 {
00099 l_int32    w, h, d, wpl;
00100 l_uint32  *data;
00101 
00102     PROCNAME("pixAddConstantGray");
00103 
00104     if (!pixs)
00105         return ERROR_INT("pixs not defined", procName, 1);
00106     pixGetDimensions(pixs, &w, &h, &d);
00107     if (d != 8 && d != 16 && d != 32)
00108         return ERROR_INT("pixs not 8, 16 or 32 bpp", procName, 1);
00109 
00110     data = pixGetData(pixs);
00111     wpl = pixGetWpl(pixs);
00112     addConstantGrayLow(data, w, h, d, wpl, val);
00113 
00114     return 0;
00115 }
00116 
00117 
00118 /*!
00119  *  pixMultConstantGray()
00120  *
00121  *      Input:  pixs (8, 16 or 32 bpp)
00122  *              val  (>= 0.0; amount to multiply by each pixel)
00123  *      Return: 0 if OK, 1 on error
00124  *
00125  *  Notes:
00126  *      (1) In-place operation; val must be >= 0.
00127  *      (2) No clipping for 32 bpp.
00128  *      (3) For 8 and 16 bpp, the result is clipped to 0xff and 0xffff, rsp.
00129  */
00130 l_int32
00131 pixMultConstantGray(PIX       *pixs,
00132                     l_float32  val)
00133 {
00134 l_int32    w, h, d, wpl;
00135 l_uint32  *data;
00136 
00137     PROCNAME("pixMultConstantGray");
00138 
00139     if (!pixs)
00140         return ERROR_INT("pixs not defined", procName, 1);
00141     pixGetDimensions(pixs, &w, &h, &d);
00142     if (d != 8 && d != 16 && d != 32)
00143         return ERROR_INT("pixs not 8, 16 or 32 bpp", procName, 1);
00144     if (val < 0.0)
00145         return ERROR_INT("val < 0.0", procName, 1);
00146 
00147     data = pixGetData(pixs);
00148     wpl = pixGetWpl(pixs);
00149     multConstantGrayLow(data, w, h, d, wpl, val);
00150 
00151     return 0;
00152 }
00153 
00154             
00155 /*-------------------------------------------------------------*
00156  *             Two-image grayscale arithmetic ops              *
00157  *-------------------------------------------------------------*/
00158 /*!
00159  *  pixAddGray()
00160  *
00161  *      Input:  pixd (<optional>; this can be null, equal to pixs1, or
00162  *                    different from pixs1)
00163  *              pixs1 (can be == to pixd)
00164  *              pixs2
00165  *      Return: pixd always
00166  *
00167  *  Notes:
00168  *      (1) Arithmetic addition of two 8, 16 or 32 bpp images.
00169  *      (2) For 8 and 16 bpp, we do explicit clipping to 0xff and 0xffff,
00170  *          respectively.
00171  *      (3) Alignment is to UL corner.
00172  *      (4) There are 3 cases.  The result can go to a new dest,
00173  *          in-place to pixs1, or to an existing input dest:
00174  *          * pixd == null:   (src1 + src2) --> new pixd
00175  *          * pixd == pixs1:  (src1 + src2) --> src1  (in-place)
00176  *          * pixd != pixs1:  (src1 + src2) --> input pixd
00177  *      (5) pixs2 must be different from both pixd and pixs1.
00178  */
00179 PIX *
00180 pixAddGray(PIX  *pixd,
00181            PIX  *pixs1,
00182            PIX  *pixs2)
00183 {
00184 l_int32    d, ws, hs, w, h, wpls, wpld;
00185 l_uint32  *datas, *datad;
00186 
00187     PROCNAME("pixAddGray");
00188 
00189     if (!pixs1)
00190         return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
00191     if (!pixs2)
00192         return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
00193     if (pixs2 == pixs1)
00194         return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", procName, pixd);
00195     if (pixs2 == pixd)
00196         return (PIX *)ERROR_PTR("pixs2 and pixd must differ", procName, pixd);
00197     d = pixGetDepth(pixs1);
00198     if (d != 8 && d != 16 && d != 32)
00199         return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", procName, pixd);
00200     if (pixGetDepth(pixs2) != d)
00201         return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", procName, pixd);
00202     if (pixd && (pixGetDepth(pixd) != d))
00203         return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", procName, pixd);
00204 
00205     if (!pixSizesEqual(pixs1, pixs2))
00206         L_WARNING("pixs1 and pixs2 not equal in size", procName);
00207     if (pixd && !pixSizesEqual(pixs1, pixd))
00208         L_WARNING("pixs1 and pixd not equal in size", procName);
00209 
00210     if (pixs1 != pixd)
00211         pixd = pixCopy(pixd, pixs1);
00212 
00213         /* pixd + pixs2 ==> pixd  */
00214     datas = pixGetData(pixs2);
00215     datad = pixGetData(pixd);
00216     wpls = pixGetWpl(pixs2);
00217     wpld = pixGetWpl(pixd);
00218     pixGetDimensions(pixs2, &ws, &hs, NULL);
00219     pixGetDimensions(pixd, &w, &h, NULL);
00220     w = L_MIN(ws, w);
00221     h = L_MIN(hs, h);
00222     addGrayLow(datad, w, h, d, wpld, datas, wpls);
00223 
00224     return pixd;
00225 }
00226 
00227 
00228 /*!
00229  *  pixSubtractGray()
00230  *
00231  *      Input:  pixd (<optional>; this can be null, equal to pixs1, or
00232  *                    different from pixs1)
00233  *              pixs1 (can be == to pixd)
00234  *              pixs2
00235  *      Return: pixd always
00236  *
00237  *  Notes:
00238  *      (1) Arithmetic subtraction of two 8, 16 or 32 bpp images.
00239  *      (2) Source pixs2 is always subtracted from source pixs1.
00240  *      (3) Do explicit clipping to 0.
00241  *      (4) Alignment is to UL corner.
00242  *      (5) There are 3 cases.  The result can go to a new dest,
00243  *          in-place to pixs1, or to an existing input dest:
00244  *          (a) pixd == null   (src1 - src2) --> new pixd
00245  *          (b) pixd == pixs1  (src1 - src2) --> src1  (in-place)
00246  *          (d) pixd != pixs1  (src1 - src2) --> input pixd
00247  *      (6) pixs2 must be different from both pixd and pixs1.
00248  */
00249 PIX *
00250 pixSubtractGray(PIX  *pixd,
00251                 PIX  *pixs1,
00252                 PIX  *pixs2)
00253 {
00254 l_int32    w, h, ws, hs, d, wpls, wpld;
00255 l_uint32  *datas, *datad;
00256 
00257     PROCNAME("pixSubtractGray");
00258 
00259     if (!pixs1)
00260         return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
00261     if (!pixs2)
00262         return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
00263     if (pixs2 == pixs1)
00264         return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", procName, pixd);
00265     if (pixs2 == pixd)
00266         return (PIX *)ERROR_PTR("pixs2 and pixd must differ", procName, pixd);
00267     d = pixGetDepth(pixs1);
00268     if (d != 8 && d != 16 && d != 32)
00269         return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", procName, pixd);
00270     if (pixGetDepth(pixs2) != d)
00271         return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", procName, pixd);
00272     if (pixd && (pixGetDepth(pixd) != d))
00273         return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", procName, pixd);
00274 
00275     if (!pixSizesEqual(pixs1, pixs2))
00276         L_WARNING("pixs1 and pixs2 not equal in size", procName);
00277     if (pixd && !pixSizesEqual(pixs1, pixd))
00278         L_WARNING("pixs1 and pixd not equal in size", procName);
00279 
00280     if (pixs1 != pixd)
00281         pixd = pixCopy(pixd, pixs1);
00282 
00283         /* pixd - pixs2 ==> pixd  */
00284     datas = pixGetData(pixs2);
00285     datad = pixGetData(pixd);
00286     wpls = pixGetWpl(pixs2);
00287     wpld = pixGetWpl(pixd);
00288     pixGetDimensions(pixs2, &ws, &hs, NULL);
00289     pixGetDimensions(pixd, &w, &h, NULL);
00290     w = L_MIN(ws, w);
00291     h = L_MIN(hs, h);
00292     subtractGrayLow(datad, w, h, d, wpld, datas, wpls);
00293 
00294     return pixd;
00295 }
00296 
00297 
00298 /*-------------------------------------------------------------*
00299  *                Grayscale threshold operation                *
00300  *-------------------------------------------------------------*/
00301 /*!
00302  *  pixThresholdToValue()
00303  *
00304  *      Input:  pixd (<optional>; if not null, must be equal to pixs)
00305  *              pixs (8, 16, 32 bpp)
00306  *              threshval
00307  *              setval
00308  *      Return: pixd always
00309  *
00310  *  Notes:
00311  *    - operation can be in-place (pixs == pixd) or to a new pixd
00312  *    - if setval > threshval, sets pixels with a value >= threshval to setval
00313  *    - if setval < threshval, sets pixels with a value <= threshval to setval
00314  *    - if setval == threshval, no-op
00315  */
00316 PIX *
00317 pixThresholdToValue(PIX      *pixd,
00318                     PIX      *pixs,
00319                     l_int32   threshval,
00320                     l_int32   setval)
00321 {
00322 l_int32    w, h, d, wpld;
00323 l_uint32  *datad;
00324 
00325     PROCNAME("pixThresholdToValue");
00326 
00327     if (!pixs)
00328         return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
00329     d = pixGetDepth(pixs);
00330     if (d != 8 && d != 16 && d != 32)
00331         return (PIX *)ERROR_PTR("pixs not 8, 16 or 32 bpp", procName, pixd);
00332     if (pixd && (pixs != pixd))
00333         return (PIX *)ERROR_PTR("pixd exists and is not pixs", procName, pixd);
00334     if (threshval < 0 || setval < 0)
00335         return (PIX *)ERROR_PTR("threshval & setval not < 0", procName, pixd);
00336     if (d == 8 && setval > 255)
00337         return (PIX *)ERROR_PTR("setval > 255 for 8 bpp", procName, pixd);
00338     if (d == 16 && setval > 0xffff)
00339         return (PIX *)ERROR_PTR("setval > 0xffff for 16 bpp", procName, pixd);
00340 
00341     if (!pixd)
00342         pixd = pixCopy(NULL, pixs);
00343     if (setval == threshval) {
00344         L_WARNING("setval == threshval; no operation", procName);
00345         return pixd;
00346     }
00347 
00348     datad = pixGetData(pixd);
00349     pixGetDimensions(pixd, &w, &h, NULL);
00350     wpld = pixGetWpl(pixd);
00351 
00352     thresholdToValueLow(datad, w, h, d, wpld, threshval, setval);
00353     return pixd;
00354 }
00355 
00356 
00357 
00358 /*-------------------------------------------------------------*
00359  *            Image accumulator arithmetic operations          *
00360  *-------------------------------------------------------------*/
00361 /*!
00362  *  pixInitAccumulate()
00363  *
00364  *      Input:  w, h (of accumulate array)
00365  *              offset (initialize the 32 bpp to have this
00366  *                      value; not more than 0x40000000)
00367  *      Return: pixd (32 bpp), or null on error
00368  *
00369  *  Notes:
00370  *      (1) The offset must be >= 0.
00371  *      (2) The offset is used so that we can do arithmetic
00372  *          with negative number results on l_uint32 data; it
00373  *          prevents the l_uint32 data from going negative.
00374  *      (3) Because we use l_int32 intermediate data results,
00375  *          these should never exceed the max of l_int32 (0x7fffffff).
00376  *          We do not permit the offset to be above 0x40000000,
00377  *          which is half way between 0 and the max of l_int32.
00378  *      (4) The same offset should be used for initialization,
00379  *          multiplication by a constant, and final extraction!
00380  *      (5) If you're only adding positive values, offset can be 0.
00381  */
00382 PIX *
00383 pixInitAccumulate(l_int32   w,
00384                   l_int32   h,
00385                   l_uint32  offset)
00386 {
00387 PIX  *pixd;
00388 
00389     PROCNAME("pixInitAccumulate");
00390 
00391     if ((pixd = pixCreate(w, h, 32)) == NULL)
00392         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00393     if (offset > 0x40000000)
00394         offset = 0x40000000;
00395     pixSetAllArbitrary(pixd, offset);
00396     return pixd;
00397 }
00398 
00399 
00400 /*!
00401  *  pixFinalAccumulate()
00402  *
00403  *      Input:  pixs (32 bpp)
00404  *              offset (same as used for initialization)
00405  *              depth  (8, 16 or 32 bpp, of destination)
00406  *      Return: pixd (8, 16 or 32 bpp), or null on error
00407  *
00408  *  Notes:
00409  *      (1) The offset must be >= 0 and should not exceed 0x40000000.
00410  *      (2) The offset is subtracted from the src 32 bpp image
00411  *      (3) For 8 bpp dest, the result is clipped to [0, 0xff]
00412  *      (4) For 16 bpp dest, the result is clipped to [0, 0xffff]
00413  */
00414 PIX *
00415 pixFinalAccumulate(PIX      *pixs,
00416                    l_uint32  offset,
00417                    l_int32   depth)
00418 {
00419 l_int32    w, h, wpls, wpld;
00420 l_uint32  *datas, *datad;
00421 PIX       *pixd;
00422 
00423     PROCNAME("pixFinalAccumulate");
00424 
00425     if (!pixs)
00426         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
00427     if (pixGetDepth(pixs) != 32)
00428         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
00429     if (depth != 8 && depth != 16 && depth != 32)
00430         return (PIX *)ERROR_PTR("dest depth not 8, 16, 32 bpp", procName, NULL);
00431     if (offset > 0x40000000)
00432         offset = 0x40000000;
00433 
00434     pixGetDimensions(pixs, &w, &h, NULL);
00435     if ((pixd = pixCreate(w, h, depth)) == NULL)
00436         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00437     pixCopyResolution(pixd, pixs);  /* but how did pixs get it initially? */
00438     datas = pixGetData(pixs);
00439     datad = pixGetData(pixd);
00440     wpls = pixGetWpl(pixs);
00441     wpld = pixGetWpl(pixd);
00442 
00443     finalAccumulateLow(datad, w, h, depth, wpld, datas, wpls, offset);
00444     return pixd;
00445 }
00446 
00447 
00448 /*!
00449  *  pixFinalAccumulateThreshold()
00450  *
00451  *      Input:  pixs (32 bpp)
00452  *              offset (same as used for initialization)
00453  *              threshold (values less than this are set in the destination)
00454  *      Return: pixd (1 bpp), or null on error
00455  *
00456  *  Notes:
00457  *      (1) The offset must be >= 0 and should not exceed 0x40000000.
00458  *      (2) The offset is subtracted from the src 32 bpp image
00459  */
00460 PIX *
00461 pixFinalAccumulateThreshold(PIX      *pixs,
00462                             l_uint32  offset,
00463                             l_uint32  threshold)
00464 {
00465 l_int32    w, h, wpls, wpld;
00466 l_uint32  *datas, *datad;
00467 PIX       *pixd;
00468 
00469     PROCNAME("pixFinalAccumulateThreshold");
00470 
00471     if (!pixs)
00472         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
00473     if (pixGetDepth(pixs) != 32)
00474         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
00475     if (offset > 0x40000000)
00476         offset = 0x40000000;
00477 
00478     pixGetDimensions(pixs, &w, &h, NULL);
00479     if ((pixd = pixCreate(w, h, 1)) == NULL)
00480         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00481     pixCopyResolution(pixd, pixs);  /* but how did pixs get it initially? */
00482     datas = pixGetData(pixs);
00483     datad = pixGetData(pixd);
00484     wpls = pixGetWpl(pixs);
00485     wpld = pixGetWpl(pixd);
00486 
00487     finalAccumulateThreshLow(datad, w, h, wpld, datas, wpls, offset, threshold);
00488     return pixd;
00489 }
00490 
00491 
00492 /*!
00493  *  pixAccumulate() 
00494  *
00495  *      Input:  pixd (32 bpp)
00496  *              pixs (1, 8, 16 or 32 bpp)
00497  *              op  (L_ARITH_ADD or L_ARITH_SUBTRACT)
00498  *      Return: 0 if OK; 1 on error
00499  *
00500  *  Notes:
00501  *      (1) This adds or subtracts each pixs value from pixd.
00502  *      (2) This clips to the minimum of pixs and pixd, so they
00503  *          do not need to be the same size.
00504  *      (3) The alignment is to the origin (UL corner) of pixs & pixd.
00505  */
00506 l_int32
00507 pixAccumulate(PIX     *pixd,
00508               PIX     *pixs,
00509               l_int32  op)
00510 {
00511 l_int32    w, h, d, wd, hd, wpls, wpld;
00512 l_uint32  *datas, *datad;
00513 
00514     PROCNAME("pixAccumulate");
00515 
00516     if (!pixd || (pixGetDepth(pixd) != 32))
00517         return ERROR_INT("pixd not defined or not 32 bpp", procName, 1);
00518     if (!pixs)
00519         return ERROR_INT("pixs not defined", procName, 1);
00520     d = pixGetDepth(pixs);
00521     if (d != 1 && d != 8 && d != 16 && d != 32)
00522         return ERROR_INT("pixs not 1, 8, 16 or 32 bpp", procName, 1);
00523     if (op != L_ARITH_ADD && op != L_ARITH_SUBTRACT)
00524         return ERROR_INT("op must be in {L_ARITH_ADD, L_ARITH_SUBTRACT}",
00525                          procName, 1);
00526 
00527     datas = pixGetData(pixs);
00528     datad = pixGetData(pixd);
00529     wpls = pixGetWpl(pixs);
00530     wpld = pixGetWpl(pixd);
00531     pixGetDimensions(pixs, &w, &h, NULL);
00532     pixGetDimensions(pixd, &wd, &hd, NULL);
00533     w = L_MIN(w, wd);
00534     h = L_MIN(h, hd);
00535 
00536     accumulateLow(datad, w, h, wpld, datas, d, wpls, op);
00537     return 0;
00538 }
00539 
00540 
00541 /*!
00542  *  pixMultConstAccumulate() 
00543  *
00544  *      Input:  pixs (32 bpp)
00545  *              factor
00546  *              offset (same as used for initialization)
00547  *      Return: 0 if OK; 1 on error
00548  *
00549  *  Notes:
00550  *      (1) The offset must be >= 0 and should not exceed 0x40000000.
00551  *      (2) This multiplies each pixel, relative to offset, by the input factor
00552  *      (3) The result is returned with the offset back in place.
00553  */
00554 l_int32
00555 pixMultConstAccumulate(PIX       *pixs,
00556                        l_float32  factor,
00557                        l_uint32   offset)
00558 {
00559 l_int32    w, h, wpl;
00560 l_uint32  *data;
00561 
00562     PROCNAME("pixMultConstAccumulate");
00563 
00564     if (!pixs)
00565         return ERROR_INT("pixs not defined", procName, 1);
00566     if (pixGetDepth(pixs) != 32)
00567         return ERROR_INT("pixs not 32 bpp", procName, 1);
00568     if (offset > 0x40000000)
00569         offset = 0x40000000;
00570 
00571     pixGetDimensions(pixs, &w, &h, NULL);
00572     data = pixGetData(pixs);
00573     wpl = pixGetWpl(pixs);
00574 
00575     multConstAccumulateLow(data, w, h, wpl, factor, offset);
00576     return 0;
00577 }
00578 
00579 
00580 /*-----------------------------------------------------------------------*
00581  *                      Absolute value of difference                     *
00582  *-----------------------------------------------------------------------*/
00583 /*!
00584  *  pixAbsDifference()
00585  *
00586  *      Input:  pixs1, pixs2  (both either 8 or 16 bpp gray, or 32 bpp RGB)
00587  *      Return: pixd, or null on error
00588  *
00589  *  Notes:
00590  *      (1) The depth of pixs1 and pixs2 must be equal.
00591  *      (2) Clips computation to the min size, aligning the UL corners
00592  *      (3) For 8 and 16 bpp, assumes one gray component.
00593  *      (4) For 32 bpp, assumes 3 color components, and ignores the
00594  *          LSB of each word (the alpha channel)
00595  *      (5) Computes the absolute value of the difference between
00596  *          each component value.
00597  */
00598 PIX *
00599 pixAbsDifference(PIX  *pixs1,
00600                  PIX  *pixs2)
00601 {
00602 l_int32    w, h, w2, h2, d, wpls, wpld;
00603 l_uint32  *datas1, *datas2, *datad;
00604 PIX       *pixd;
00605 
00606     PROCNAME("pixAbsDifference");
00607 
00608     if (!pixs1)
00609         return (PIX *)ERROR_PTR("pixs1 not defined", procName, NULL);
00610     if (!pixs2)
00611         return (PIX *)ERROR_PTR("pixs2 not defined", procName, NULL);
00612     d = pixGetDepth(pixs1);
00613     if (d != pixGetDepth(pixs2))
00614         return (PIX *)ERROR_PTR("src1 and src2 depths unequal", procName, NULL);
00615     if (d != 8 && d != 16 && d != 32)
00616         return (PIX *)ERROR_PTR("depths not in {8, 16, 32}", procName, NULL);
00617 
00618     pixGetDimensions(pixs1, &w, &h, NULL);
00619     pixGetDimensions(pixs2, &w2, &h2, NULL);
00620     w = L_MIN(w, w2);
00621     h = L_MIN(h, h2);
00622     if ((pixd = pixCreate(w, h, d)) == NULL)
00623         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00624     pixCopyResolution(pixd, pixs1);
00625     datas1 = pixGetData(pixs1);
00626     datas2 = pixGetData(pixs2);
00627     datad = pixGetData(pixd);
00628     wpls = pixGetWpl(pixs1);
00629     wpld = pixGetWpl(pixd);
00630 
00631     absDifferenceLow(datad, w, h, wpld, datas1, datas2, d, wpls);
00632 
00633     return pixd;
00634 }
00635 
00636 
00637 /*-----------------------------------------------------------------------*
00638  *             Two-image min and max operations (8 and 16 bpp)           *
00639  *-----------------------------------------------------------------------*/
00640 /*!
00641  *  pixMinOrMax()
00642  *
00643  *      Input:  pixd  (<optional> destination: this can be null,
00644  *                     equal to pixs1, or different from pixs1)
00645  *              pixs1 (can be == to pixd)
00646  *              pixs2
00647  *              type (L_CHOOSE_MIN, L_CHOOSE_MAX)
00648  *      Return: pixd always
00649  *
00650  *  Notes:
00651  *      (1) This gives the min or max of two images.
00652  *      (2) The depth can be 8 or 16 bpp.
00653  *      (3) There are 3 cases:
00654  *          -  if pixd == null,   Min(src1, src2) --> new pixd
00655  *          -  if pixd == pixs1,  Min(src1, src2) --> src1  (in-place)
00656  *          -  if pixd != pixs1,  Min(src1, src2) --> input pixd
00657  */
00658 PIX *
00659 pixMinOrMax(PIX     *pixd,
00660             PIX     *pixs1,
00661             PIX     *pixs2,
00662             l_int32  type)
00663 {
00664 l_int32    d, ws, hs, w, h, wpls, wpld, i, j;
00665 l_int32    vals, vald, val;
00666 l_uint32  *datas, *datad, *lines, *lined;
00667 
00668     PROCNAME("pixMinOrMax");
00669 
00670     if (!pixs1)
00671         return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
00672     if (!pixs2)
00673         return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
00674     if (pixs1 == pixs2)
00675         return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd);
00676     if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX)
00677         return (PIX *)ERROR_PTR("invalid type", procName, pixd);
00678     d = pixGetDepth(pixs1);
00679     if (pixGetDepth(pixs2) != d)
00680         return (PIX *)ERROR_PTR("depths unequal", procName, pixd);
00681     if (d != 8 && d != 16)
00682         return (PIX *)ERROR_PTR("depth not 8 or 16 bpp", procName, pixd);
00683 
00684     if (pixs1 != pixd)
00685         pixd = pixCopy(pixd, pixs1);
00686 
00687     pixGetDimensions(pixs2, &ws, &hs, NULL);
00688     pixGetDimensions(pixd, &w, &h, NULL);
00689     w = L_MIN(w, ws);
00690     h = L_MIN(h, hs);
00691     datas = pixGetData(pixs2);
00692     datad = pixGetData(pixd);
00693     wpls = pixGetWpl(pixs2);
00694     wpld = pixGetWpl(pixd);
00695     for (i = 0; i < h; i++) {
00696         lines = datas + i * wpls;
00697         lined = datad + i * wpld;
00698         if (d == 8) {
00699             if (type == L_CHOOSE_MIN) {
00700                 for (j = 0; j < w; j++) {
00701                     vals = GET_DATA_BYTE(lines, j);
00702                     vald = GET_DATA_BYTE(lined, j);
00703                     val = L_MIN(vals, vald);
00704                     SET_DATA_BYTE(lined, j, val);
00705                 }
00706             } else {  /* type == L_CHOOSE_MAX */
00707                 for (j = 0; j < w; j++) {
00708                     vals = GET_DATA_BYTE(lines, j);
00709                     vald = GET_DATA_BYTE(lined, j);
00710                     val = L_MAX(vals, vald);
00711                     SET_DATA_BYTE(lined, j, val);
00712                 }
00713             }
00714         } else {  /* d == 16 */
00715             if (type == L_CHOOSE_MIN) {
00716                 for (j = 0; j < w; j++) {
00717                     vals = GET_DATA_TWO_BYTES(lines, j);
00718                     vald = GET_DATA_TWO_BYTES(lined, j);
00719                     val = L_MIN(vals, vald);
00720                     SET_DATA_TWO_BYTES(lined, j, val);
00721                 }
00722             } else {  /* type == L_CHOOSE_MAX */
00723                 for (j = 0; j < w; j++) {
00724                     vals = GET_DATA_TWO_BYTES(lines, j);
00725                     vald = GET_DATA_TWO_BYTES(lined, j);
00726                     val = L_MAX(vals, vald);
00727                     SET_DATA_TWO_BYTES(lined, j, val);
00728                 }
00729             }
00730         }
00731     }
00732 
00733     return pixd;
00734 }
00735 
00736 
00737 /*-----------------------------------------------------------------------*
00738  *            Scale for maximum dynamic range in 8 bpp image             *
00739  *-----------------------------------------------------------------------*/
00740 /*!
00741  *  pixMaxDynamicRange()
00742  *
00743  *      Input:  pixs  (4, 8, 16 or 32 bpp source)
00744  *              type  (L_LINEAR_SCALE or L_LOG_SCALE)
00745  *      Return: pixd (8 bpp), or null on error
00746  *
00747  *  Notes:
00748  *      (1) Scales pixel values to fit maximally within the dest 8 bpp pixd
00749  *      (2) Uses a LUT for log scaling
00750  */
00751 PIX *
00752 pixMaxDynamicRange(PIX     *pixs,
00753                    l_int32  type)
00754 {
00755 l_uint8     dval;
00756 l_int32     i, j, w, h, d, wpls, wpld, max, sval;
00757 l_uint32   *datas, *datad;
00758 l_uint32    word;
00759 l_uint32   *lines, *lined;
00760 l_float32   factor;
00761 l_float32  *tab;
00762 PIX        *pixd;
00763 
00764     PROCNAME("pixMaxDynamicRange");
00765 
00766     if (!pixs)
00767         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
00768     d = pixGetDepth(pixs);
00769     if (d != 4 && d != 8 && d != 16 && d != 32)
00770         return (PIX *)ERROR_PTR("pixs not in {4,8,16,32} bpp", procName, NULL);
00771     if (type != L_LINEAR_SCALE && type != L_LOG_SCALE)
00772         return (PIX *)ERROR_PTR("invalid type", procName, NULL);
00773 
00774     pixGetDimensions(pixs, &w, &h, NULL);
00775     if ((pixd = pixCreate(w, h, 8)) == NULL)
00776         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00777     pixCopyResolution(pixd, pixs);
00778     datas = pixGetData(pixs);
00779     datad = pixGetData(pixd);
00780     wpls = pixGetWpl(pixs);
00781     wpld = pixGetWpl(pixd);
00782 
00783         /* Get max */
00784     max = 0;
00785     for (i = 0; i < h; i++) {
00786         lines = datas + i * wpls;
00787         for (j = 0; j < wpls; j++) {
00788             word = *(lines + j);
00789             if (d == 4) {
00790                 max = L_MAX(max, word >> 28);
00791                 max = L_MAX(max, (word >> 24) & 0xf);
00792                 max = L_MAX(max, (word >> 20) & 0xf);
00793                 max = L_MAX(max, (word >> 16) & 0xf);
00794                 max = L_MAX(max, (word >> 12) & 0xf);
00795                 max = L_MAX(max, (word >> 8) & 0xf);
00796                 max = L_MAX(max, (word >> 4) & 0xf);
00797                 max = L_MAX(max, word & 0xf);
00798             } else if (d == 8) {
00799                 max = L_MAX(max, word >> 24);
00800                 max = L_MAX(max, (word >> 16) & 0xff);
00801                 max = L_MAX(max, (word >> 8) & 0xff);
00802                 max = L_MAX(max, word & 0xff);
00803             } else if (d == 16) {
00804                 max = L_MAX(max, word >> 16);
00805                 max = L_MAX(max, word & 0xffff);
00806             } else {  /* d == 32 */
00807                 max = L_MAX(max, word);
00808             }
00809         }
00810     }
00811 
00812         /* Map to the full dynamic range of 8 bpp output */
00813     if (d == 4) {
00814         if (type == L_LINEAR_SCALE) {
00815             factor = 255. / (l_float32)max;
00816             for (i = 0; i < h; i++) {
00817                 lines = datas + i * wpls;
00818                 lined = datad + i * wpld;
00819                 for (j = 0; j < w; j++) {
00820                     sval = GET_DATA_QBIT(lines, j);
00821                     dval = (l_uint8)(factor * (l_float32)sval + 0.5);
00822                     SET_DATA_QBIT(lined, j, dval);
00823                 }
00824             }
00825         } else {  /* type == L_LOG_SCALE) */
00826             tab = makeLogBase2Tab();
00827             factor = 255. / getLogBase2(max, tab);
00828             for (i = 0; i < h; i++) {
00829                 lines = datas + i * wpls;
00830                 lined = datad + i * wpld;
00831                 for (j = 0; j < w; j++) {
00832                     sval = GET_DATA_QBIT(lines, j);
00833                     dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
00834                     SET_DATA_BYTE(lined, j, dval);
00835                 }
00836             }
00837             FREE(tab);
00838         }
00839     } else if (d == 8) {
00840         if (type == L_LINEAR_SCALE) {
00841             factor = 255. / (l_float32)max;
00842             for (i = 0; i < h; i++) {
00843                 lines = datas + i * wpls;
00844                 lined = datad + i * wpld;
00845                 for (j = 0; j < w; j++) {
00846                     sval = GET_DATA_BYTE(lines, j);
00847                     dval = (l_uint8)(factor * (l_float32)sval + 0.5);
00848                     SET_DATA_BYTE(lined, j, dval);
00849                 }
00850             }
00851         } else {  /* type == L_LOG_SCALE) */
00852             tab = makeLogBase2Tab();
00853             factor = 255. / getLogBase2(max, tab);
00854             for (i = 0; i < h; i++) {
00855                 lines = datas + i * wpls;
00856                 lined = datad + i * wpld;
00857                 for (j = 0; j < w; j++) {
00858                     sval = GET_DATA_BYTE(lines, j);
00859                     dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
00860                     SET_DATA_BYTE(lined, j, dval);
00861                 }
00862             }
00863             FREE(tab);
00864         }
00865     } else if (d == 16) {
00866         if (type == L_LINEAR_SCALE) {
00867             factor = 255. / (l_float32)max;
00868             for (i = 0; i < h; i++) {
00869                 lines = datas + i * wpls;
00870                 lined = datad + i * wpld;
00871                 for (j = 0; j < w; j++) {
00872                     sval = GET_DATA_TWO_BYTES(lines, j);
00873                     dval = (l_uint8)(factor * (l_float32)sval + 0.5);
00874                     SET_DATA_BYTE(lined, j, dval);
00875                 }
00876             }
00877         } else {  /* type == L_LOG_SCALE) */
00878             tab = makeLogBase2Tab();
00879             factor = 255. / getLogBase2(max, tab);
00880             for (i = 0; i < h; i++) {
00881                 lines = datas + i * wpls;
00882                 lined = datad + i * wpld;
00883                 for (j = 0; j < w; j++) {
00884                     sval = GET_DATA_TWO_BYTES(lines, j);
00885                     dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
00886                     SET_DATA_BYTE(lined, j, dval);
00887                 }
00888             }
00889             FREE(tab);
00890         }
00891     } else {  /* d == 32 */
00892         if (type == L_LINEAR_SCALE) {
00893             factor = 255. / (l_float32)max;
00894             for (i = 0; i < h; i++) {
00895                 lines = datas + i * wpls;
00896                 lined = datad + i * wpld;
00897                 for (j = 0; j < w; j++) {
00898                     sval = lines[j];
00899                     dval = (l_uint8)(factor * (l_float32)sval + 0.5);
00900                     SET_DATA_BYTE(lined, j, dval);
00901                 }
00902             }
00903         } else {  /* type == L_LOG_SCALE) */
00904             tab = makeLogBase2Tab();
00905             factor = 255. / getLogBase2(max, tab);
00906             for (i = 0; i < h; i++) {
00907                 lines = datas + i * wpls;
00908                 lined = datad + i * wpld;
00909                 for (j = 0; j < w; j++) {
00910                     sval = lines[j];
00911                     dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
00912                     SET_DATA_BYTE(lined, j, dval);
00913                 }
00914             }
00915             FREE(tab);
00916         }
00917     }
00918 
00919     return pixd;
00920 }
00921 
00922 
00923 /*-----------------------------------------------------------------------*
00924  *                            Log base2 lookup                           *
00925  *-----------------------------------------------------------------------*/
00926 /*
00927  *  makeLogBase2Tab()
00928  *
00929  *      Input: void
00930  *      Return: table (giving the log[base 2] of val)
00931  */
00932 l_float32 *
00933 makeLogBase2Tab(void)
00934 {
00935 l_int32     i;
00936 l_float32   log2;
00937 l_float32  *tab;
00938 
00939     PROCNAME("makeLogBase2Tab");
00940 
00941     if ((tab = (l_float32 *)CALLOC(256, sizeof(l_float32))) == NULL)
00942         return (l_float32 *)ERROR_PTR("tab not made", procName, NULL);
00943 
00944     log2 = (l_float32)log((l_float32)2);
00945     for (i = 0; i < 256; i++)
00946         tab[i] = (l_float32)log((l_float32)i) / log2;
00947 
00948     return tab;
00949 }
00950 
00951 
00952 /*
00953  * getLogBase2()
00954  *
00955  *     Input:  val
00956  *             logtab (256-entry table of logs)
00957  *     Return: logdist, or 0 on error
00958  */
00959 l_float32
00960 getLogBase2(l_int32     val,
00961             l_float32  *logtab)
00962 {
00963     PROCNAME("getLogBase2");
00964 
00965     if (!logtab)
00966         return ERROR_INT("logtab not defined", procName, 0);
00967 
00968     if (val < 0x100)
00969         return logtab[val];
00970     else if (val < 0x10000)
00971         return 8.0 + logtab[val >> 8];
00972     else if (val < 0x1000000)
00973         return 16.0 + logtab[val >> 16];
00974     else
00975         return 24.0 + logtab[val >> 24];
00976 }
00977 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines