Leptonica 1.68
C Image Processing Library

arithlow.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  *  arithlow.c
00019  *
00020  *      One image grayscale arithmetic (8, 16 or 32 bpp)
00021  *            void       addConstantGrayLow()
00022  *            void       multConstantGrayLow()
00023  *
00024  *      Two image grayscale arithmetic (8, 16 or 32 bpp)
00025  *            void       addGrayLow()
00026  *            void       subtractGrayLow()
00027  *
00028  *      Grayscale threshold operation (8, 16 or 32 bpp)
00029  *            void       thresholdToValueLow()
00030  *
00031  *      Image accumulator arithmetic operations (8, 16, 32 bpp)
00032  *            void       finalAccumulateLow()
00033  *            void       finalAccumulateThreshLow()
00034  *            void       accumulateLow()
00035  *            void       multConstAccumulateLow()
00036  *
00037  *      Absolute value of difference, component-wise.
00038  *            void       absDifferenceLow()
00039  */
00040 
00041 
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 #include <math.h>
00046 #include "allheaders.h"
00047 
00048 
00049 /*------------------------------------------------------------------*
00050  *        One image grayscale arithmetic (8, 16 or 32 bpp)          *
00051  *------------------------------------------------------------------*/
00052 /*!
00053  *  addConstantGrayLow()
00054  */
00055 void
00056 addConstantGrayLow(l_uint32  *data,
00057                    l_int32    w,
00058                    l_int32    h,
00059                    l_int32    d,
00060                    l_int32    wpl,
00061                    l_int32    val)
00062 {
00063 l_int32    i, j, pval;
00064 l_uint32  *line;
00065 
00066     for (i = 0; i < h; i++) {
00067         line = data + i * wpl;
00068         if (d == 8) {
00069             if (val < 0) {
00070                 for (j = 0; j < w; j++) {
00071                     pval = GET_DATA_BYTE(line, j);
00072                     pval = L_MAX(0, pval + val);
00073                     SET_DATA_BYTE(line, j, pval);
00074                 }
00075             }
00076             else {  /* val >= 0 */
00077                 for (j = 0; j < w; j++) {
00078                     pval = GET_DATA_BYTE(line, j);
00079                     pval = L_MIN(255, pval + val);
00080                     SET_DATA_BYTE(line, j, pval);
00081                 }
00082             }
00083         }
00084         else if (d == 16) {
00085             if (val < 0) {
00086                 for (j = 0; j < w; j++) {
00087                     pval = GET_DATA_TWO_BYTES(line, j);
00088                     pval = L_MAX(0, pval + val);
00089                     SET_DATA_TWO_BYTES(line, j, pval);
00090                 }
00091             }
00092             else {  /* val >= 0 */
00093                 for (j = 0; j < w; j++) {
00094                     pval = GET_DATA_TWO_BYTES(line, j);
00095                     pval = L_MIN(0xffff, pval + val);
00096                     SET_DATA_TWO_BYTES(line, j, pval);
00097                 }
00098             }
00099         }
00100         else {  /* d == 32; no check for overflow (< 0 or > 0xffffffff) */
00101             for (j = 0; j < w; j++)
00102                 *(line + j) += val;
00103         }
00104     }
00105     return;
00106 }
00107 
00108 
00109 /*!
00110  *  multConstantGrayLow()
00111  */
00112 void
00113 multConstantGrayLow(l_uint32  *data,
00114                     l_int32    w,
00115                     l_int32    h,
00116                     l_int32    d,
00117                     l_int32    wpl,
00118                     l_float32  val)
00119 {
00120 l_int32    i, j, pval;
00121 l_uint32   upval;
00122 l_uint32  *line;
00123 
00124     for (i = 0; i < h; i++) {
00125         line = data + i * wpl;
00126         if (d == 8) {
00127             for (j = 0; j < w; j++) {
00128                 pval = GET_DATA_BYTE(line, j);
00129                 pval = (l_int32)(val * pval);
00130                 pval = L_MIN(255, pval);
00131                 SET_DATA_BYTE(line, j, pval);
00132             }
00133         }
00134         else if (d == 16) {
00135             for (j = 0; j < w; j++) {
00136                 pval = GET_DATA_TWO_BYTES(line, j);
00137                 pval = (l_int32)(val * pval);
00138                 pval = L_MIN(0xffff, pval);
00139                 SET_DATA_TWO_BYTES(line, j, pval);
00140             }
00141         }
00142         else {  /* d == 32; no clipping */
00143             for (j = 0; j < w; j++) {
00144                 upval = *(line + j);
00145                 upval = (l_uint32)(val * upval); 
00146                 *(line + j) = upval;
00147             }
00148         }
00149     }
00150     return;
00151 }
00152 
00153 
00154 /*------------------------------------------------------------------*
00155  *        Two image grayscale arithmetic (8, 16 or 32 bpp)          *
00156  *------------------------------------------------------------------*/
00157 /*!
00158  *  addGrayLow()
00159  */
00160 void
00161 addGrayLow(l_uint32  *datad,
00162            l_int32    w,
00163            l_int32    h,
00164            l_int32    d,
00165            l_int32    wpld,
00166            l_uint32  *datas,
00167            l_int32    wpls)
00168 {
00169 l_int32    i, j, val, sum;
00170 l_uint32  *lines, *lined;
00171 
00172 
00173     for (i = 0; i < h; i++) {
00174         lined = datad + i * wpld;
00175         lines = datas + i * wpls;
00176         if (d == 8) {
00177             for (j = 0; j < w; j++) {
00178                 sum = GET_DATA_BYTE(lines, j) + GET_DATA_BYTE(lined, j);
00179                 val = L_MIN(sum, 255);
00180                 SET_DATA_BYTE(lined, j, val);
00181             }
00182         }
00183         else if (d == 16) {
00184             for (j = 0; j < w; j++) {
00185                 sum = GET_DATA_TWO_BYTES(lines, j)
00186                       + GET_DATA_TWO_BYTES(lined, j);
00187                 val = L_MIN(sum, 0xffff);
00188                 SET_DATA_TWO_BYTES(lined, j, val);
00189             }
00190         }
00191         else {   /* d == 32; no clipping */
00192             for (j = 0; j < w; j++)
00193                 *(lined + j) += *(lines + j);
00194         }
00195     }
00196 
00197     return;
00198 }
00199 
00200 
00201 /*!
00202  *  subtractGrayLow()
00203  */
00204 void
00205 subtractGrayLow(l_uint32  *datad,
00206                 l_int32    w,
00207                 l_int32    h,
00208                 l_int32    d,
00209                 l_int32    wpld,
00210                 l_uint32  *datas,
00211                 l_int32    wpls)
00212 {
00213 l_int32    i, j, val, diff;
00214 l_uint32  *lines, *lined;
00215 
00216     for (i = 0; i < h; i++) {
00217         lined = datad + i * wpld;
00218         lines = datas + i * wpls;
00219         if (d == 8) {
00220             for (j = 0; j < w; j++) {
00221                 diff = GET_DATA_BYTE(lined, j) - GET_DATA_BYTE(lines, j);
00222                 val = L_MAX(diff, 0);
00223                 SET_DATA_BYTE(lined, j, val);
00224             }
00225         }
00226         else if (d == 16) {
00227             for (j = 0; j < w; j++) {
00228                 diff = GET_DATA_TWO_BYTES(lined, j)
00229                        - GET_DATA_TWO_BYTES(lines, j);
00230                 val = L_MAX(diff, 0);
00231                 SET_DATA_TWO_BYTES(lined, j, val);
00232             }
00233         }
00234         else {  /* d == 32; no clipping */
00235             for (j = 0; j < w; j++)
00236                 *(lined + j) -= *(lines + j);
00237         }
00238     }
00239 
00240     return;
00241 }
00242 
00243 
00244 /*-------------------------------------------------------------*
00245  *                  Grayscale threshold operation              *
00246  *-------------------------------------------------------------*/
00247 /*!
00248  *  thresholdToValueLow()
00249  */
00250 void
00251 thresholdToValueLow(l_uint32  *datad,
00252                     l_int32    w,
00253                     l_int32    h,
00254                     l_int32    d,
00255                     l_int32    wpld,
00256                     l_int32    threshval,
00257                     l_int32    setval)
00258 {
00259 l_int32    i, j, setabove;
00260 l_uint32  *lined;
00261 
00262     if (setval > threshval)
00263         setabove = TRUE;
00264     else
00265         setabove = FALSE;
00266 
00267     for (i = 0; i < h; i++) {
00268         lined = datad + i * wpld;
00269         if (setabove == TRUE) {
00270             if (d == 8) {
00271                 for (j = 0; j < w; j++) {
00272                     if (GET_DATA_BYTE(lined, j) - threshval >= 0)
00273                         SET_DATA_BYTE(lined, j, setval);
00274                 }
00275             }
00276             else if (d == 16) {
00277                 for (j = 0; j < w; j++) {
00278                     if (GET_DATA_TWO_BYTES(lined, j) - threshval >= 0)
00279                         SET_DATA_TWO_BYTES(lined, j, setval);
00280                 }
00281             }
00282             else {  /* d == 32 */
00283                 for (j = 0; j < w; j++) {
00284                     if (*(lined + j) >= threshval)
00285                         *(lined + j) = setval;
00286                 }
00287             }
00288         }
00289         else  { /* set if below or at threshold */
00290             if (d == 8) {
00291                 for (j = 0; j < w; j++) {
00292                     if (GET_DATA_BYTE(lined, j) - threshval <= 0)
00293                         SET_DATA_BYTE(lined, j, setval);
00294                 }
00295             }
00296             else if (d == 16) {
00297                 for (j = 0; j < w; j++) {
00298                     if (GET_DATA_TWO_BYTES(lined, j) - threshval <= 0)
00299                         SET_DATA_TWO_BYTES(lined, j, setval);
00300                 }
00301             }
00302             else {  /* d == 32 */
00303                 for (j = 0; j < w; j++) {
00304                     if (*(lined + j) <= threshval)
00305                         *(lined + j) = setval;
00306                 }
00307             }
00308         }
00309     }
00310     return;
00311 }
00312 
00313 
00314 
00315 /*-------------------------------------------------------------*
00316  *          Image accumulator arithmetic operations            *
00317  *-------------------------------------------------------------*/
00318 /*!
00319  *  finalAccumulateLow()
00320  */
00321 void
00322 finalAccumulateLow(l_uint32  *datad,
00323                    l_int32    w,
00324                    l_int32    h,
00325                    l_int32    d,
00326                    l_int32    wpld,
00327                    l_uint32  *datas,
00328                    l_int32    wpls,
00329                    l_uint32   offset)
00330 {
00331 l_int32    i, j;
00332 l_int32    val;
00333 l_uint32  *lines, *lined;
00334 
00335     switch (d)
00336     {
00337     case 8:
00338         for (i = 0; i < h; i++) {
00339             lines = datas + i * wpls;
00340             lined = datad + i * wpld;
00341             for (j = 0; j < w; j++) {
00342                 val = lines[j] - offset;
00343                 val = L_MAX(0, val);
00344                 val = L_MIN(255, val);
00345                 SET_DATA_BYTE(lined, j, (l_uint8)val);
00346             }
00347         }
00348         break;
00349     case 16:
00350         for (i = 0; i < h; i++) {
00351             lines = datas + i * wpls;
00352             lined = datad + i * wpld;
00353             for (j = 0; j < w; j++) {
00354                 val = lines[j] - offset;
00355                 val = L_MAX(0, val);
00356                 val = L_MIN(0xffff, val);
00357                 SET_DATA_TWO_BYTES(lined, j, (l_uint16)val);
00358             }
00359         }
00360         break;
00361     case 32:
00362         for (i = 0; i < h; i++) {
00363             lines = datas + i * wpls;
00364             lined = datad + i * wpld;
00365             for (j = 0; j < w; j++)
00366                 lined[j] = lines[j] - offset;
00367         }
00368         break;
00369     }
00370     return;
00371 }
00372    
00373 
00374 void
00375 finalAccumulateThreshLow(l_uint32 *datad,
00376                          l_int32 w,
00377                          l_int32 h,
00378                          l_int32 wpld,
00379                          l_uint32 *datas,
00380                          l_int32 wpls,
00381                          l_uint32 offset,
00382                          l_uint32 threshold)
00383 {
00384 l_int32    i, j;
00385 l_int32    val;
00386 l_uint32  *lines, *lined;
00387 
00388     for (i = 0; i < h; i++) {
00389         lines = datas + i * wpls;
00390         lined = datad + i * wpld;
00391 
00392         for (j = 0; j < w; j++) {
00393             val = lines[j] - offset;
00394             if (val >= threshold) {
00395                 SET_DATA_BIT(lined, j);
00396             }
00397         }
00398     }
00399 }
00400 
00401 
00402 /*!
00403  *  accumulateLow()
00404  */
00405 void
00406 accumulateLow(l_uint32  *datad,
00407               l_int32    w,
00408               l_int32    h,
00409               l_int32    wpld,
00410               l_uint32  *datas,
00411               l_int32    d,
00412               l_int32    wpls,
00413               l_int32    op)
00414 {
00415 l_int32    i, j;
00416 l_uint32  *lines, *lined;
00417 
00418     switch (d)
00419     {
00420     case 1:
00421         for (i = 0; i < h; i++) {
00422             lines = datas + i * wpls;
00423             lined = datad + i * wpld;
00424             if (op == L_ARITH_ADD) {
00425                 for (j = 0; j < w; j++)
00426                     lined[j] += GET_DATA_BIT(lines, j);
00427             }
00428             else {  /* op == L_ARITH_SUBTRACT */
00429                 for (j = 0; j < w; j++)
00430                     lined[j] -= GET_DATA_BIT(lines, j);
00431             }
00432         }
00433         break;
00434     case 8:
00435         for (i = 0; i < h; i++) {
00436             lines = datas + i * wpls;
00437             lined = datad + i * wpld;
00438             if (op == L_ARITH_ADD) {
00439                 for (j = 0; j < w; j++)
00440                     lined[j] += GET_DATA_BYTE(lines, j);
00441             }
00442             else {  /* op == L_ARITH_SUBTRACT */
00443                 for (j = 0; j < w; j++)
00444                     lined[j] -= GET_DATA_BYTE(lines, j);
00445             }
00446         }
00447         break;
00448     case 16:
00449         for (i = 0; i < h; i++) {
00450             lines = datas + i * wpls;
00451             lined = datad + i * wpld;
00452             if (op == L_ARITH_ADD) {
00453                 for (j = 0; j < w; j++)
00454                     lined[j] += GET_DATA_TWO_BYTES(lines, j);
00455             }
00456             else {  /* op == L_ARITH_SUBTRACT */
00457                 for (j = 0; j < w; j++)
00458                     lined[j] -= GET_DATA_TWO_BYTES(lines, j);
00459             }
00460         }
00461         break;
00462     case 32:
00463         for (i = 0; i < h; i++) {
00464             lines = datas + i * wpls;
00465             lined = datad + i * wpld;
00466             if (op == L_ARITH_ADD) {
00467                 for (j = 0; j < w; j++)
00468                     lined[j] += lines[j];
00469             }
00470             else {  /* op == L_ARITH_SUBTRACT */
00471                 for (j = 0; j < w; j++)
00472                     lined[j] -= lines[j];
00473             }
00474         }
00475         break;
00476     }
00477     return;
00478 }
00479    
00480 
00481 /*!
00482  *  multConstAccumulateLow()
00483  */
00484 void
00485 multConstAccumulateLow(l_uint32  *data,
00486                        l_int32    w,
00487                        l_int32    h,
00488                        l_int32    wpl,
00489                        l_float32  factor,
00490                        l_uint32   offset)
00491 {
00492 l_int32    i, j;
00493 l_int32    val;
00494 l_uint32  *line;
00495 
00496     for (i = 0; i < h; i++) {
00497         line = data + i * wpl;
00498         for (j = 0; j < w; j++) {
00499             val = line[j] - offset;
00500             val = (l_int32)(val * factor);
00501             val += offset;
00502             line[j] = (l_uint32)val;
00503         }
00504     }
00505     return;
00506 }
00507    
00508 
00509 /*-----------------------------------------------------------------------*
00510  *              Absolute value of difference, component-wise             *
00511  *-----------------------------------------------------------------------*/
00512 /*!
00513  *  absDifferenceLow()
00514  *
00515  *  Finds the absolute value of the difference of each pixel,
00516  *  for 8 and 16 bpp gray and for 32 bpp rgb.  For 32 bpp, the
00517  *  differences are found for each of the RGB components
00518  *  separately, and the LSB component is ignored.
00519  *  The results are written into datad.  
00520  */
00521 void
00522 absDifferenceLow(l_uint32  *datad,
00523                  l_int32    w,
00524                  l_int32    h,
00525                  l_int32    wpld,
00526                  l_uint32  *datas1,
00527                  l_uint32  *datas2,
00528                  l_int32    d,
00529                  l_int32    wpls)
00530 {
00531 l_int32    i, j, val1, val2, diff;
00532 l_uint32   word1, word2;
00533 l_uint32  *lines1, *lines2, *lined, *pdword;
00534 
00535     PROCNAME("absDifferenceLow");
00536 
00537     switch (d)
00538     {
00539     case 8:
00540         for (i = 0; i < h; i++) {
00541             lines1 = datas1 + i * wpls;
00542             lines2 = datas2 + i * wpls;
00543             lined = datad + i * wpld;
00544             for (j = 0; j < w; j++) {
00545                 val1 = GET_DATA_BYTE(lines1, j);
00546                 val2 = GET_DATA_BYTE(lines2, j);
00547                 diff = L_ABS(val1 - val2);
00548                 SET_DATA_BYTE(lined, j, diff);
00549             }
00550         }
00551         break;
00552     case 16:
00553         for (i = 0; i < h; i++) {
00554             lines1 = datas1 + i * wpls;
00555             lines2 = datas2 + i * wpls;
00556             lined = datad + i * wpld;
00557             for (j = 0; j < w; j++) {
00558                 val1 = GET_DATA_TWO_BYTES(lines1, j);
00559                 val2 = GET_DATA_TWO_BYTES(lines2, j);
00560                 diff = L_ABS(val1 - val2);
00561                 SET_DATA_TWO_BYTES(lined, j, diff);
00562             }
00563         }
00564         break;
00565     case 32:
00566         for (i = 0; i < h; i++) {
00567             lines1 = datas1 + i * wpls;
00568             lines2 = datas2 + i * wpls;
00569             lined = datad + i * wpld;
00570             for (j = 0; j < w; j++) {
00571                 word1 = lines1[j];
00572                 word2 = lines2[j];
00573                 pdword = lined + j;
00574                 val1 = GET_DATA_BYTE(&word1, COLOR_RED);
00575                 val2 = GET_DATA_BYTE(&word2, COLOR_RED);
00576                 diff = L_ABS(val1 - val2);
00577                 SET_DATA_BYTE(pdword, COLOR_RED, diff);
00578                 val1 = GET_DATA_BYTE(&word1, COLOR_GREEN);
00579                 val2 = GET_DATA_BYTE(&word2, COLOR_GREEN);
00580                 diff = L_ABS(val1 - val2);
00581                 SET_DATA_BYTE(pdword, COLOR_GREEN, diff);
00582                 val1 = GET_DATA_BYTE(&word1, COLOR_BLUE);
00583                 val2 = GET_DATA_BYTE(&word2, COLOR_BLUE);
00584                 diff = L_ABS(val1 - val2);
00585                 SET_DATA_BYTE(pdword, COLOR_BLUE, diff);
00586             }
00587         }
00588         break;
00589     default:
00590         L_ERROR("source depth must be 8, 16 or 32 bpp", procName);
00591         break;
00592     }
00593 
00594     return;
00595 }
00596 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines