Logo Search packages:      
Sourcecode: leptonlib version File versions  Download package

arithlow.c

/*====================================================================*
 -  Copyright (C) 2001 Leptonica.  All rights reserved.
 -  This software is distributed in the hope that it will be
 -  useful, but with NO WARRANTY OF ANY KIND.
 -  No author or distributor accepts responsibility to anyone for the
 -  consequences of using this software, or for whether it serves any
 -  particular purpose or works at all, unless he or she says so in
 -  writing.  Everyone is granted permission to copy, modify and
 -  redistribute this source code, for commercial or non-commercial
 -  purposes, with the following restrictions: (1) the origin of this
 -  source code must not be misrepresented; (2) modified versions must
 -  be plainly marked as such; and (3) this notice may not be removed
 -  or altered from any source or modified source distribution.
 *====================================================================*/


/*
 *  arithlow.c
 *
 *      One image grayscale arithmetic (8, 16 or 32 bpp)
 *            void       addConstantGrayLow()
 *
 *      Two image grayscale arithmetic (8, 16 or 32 bpp)
 *            void       addGrayLow()
 *            void       subtractGrayLow()
 *
 *      Grayscale threshold operation (8, 16 or 32 bpp)
 *            void       thresholdToValueLow()
 *
 *      Image accumulator arithmetic operations (8, 16, 32 bpp)
 *            void       finalAccumulateLow()
 *            void       accumulateLow()
 *            void       multConstAccumulateLow()
 *
 *      Absolute value of difference, component-wise.
 *            void       absDifferenceLow()
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "allheaders.h"


/*------------------------------------------------------------------*
 *        One image grayscale arithmetic (8, 16 or 32 bpp)          *
 *------------------------------------------------------------------*/
/*!
 *  addConstantGrayLow()
 */
void
addConstantGrayLow(l_uint32  *data,
                   l_int32    w,
                   l_int32    h,
                   l_int32    d,
                 l_int32    wpl,
                 l_int32    val)
{
l_int32    i, j, pval;
l_uint32  *line;

    for (i = 0; i < h; i++) {
      line = data + i * wpl;
      if (d == 8) {
          if (val < 0) {
            for (j = 0; j < w; j++) {
                pval = GET_DATA_BYTE(line, j);
                pval = L_MAX(0, pval + val);
                SET_DATA_BYTE(line, j, pval);
            }
          }
          else {  /* val >= 0 */
            for (j = 0; j < w; j++) {
                pval = GET_DATA_BYTE(line, j);
                pval = L_MIN(255, pval + val);
                SET_DATA_BYTE(line, j, pval);
            }
          }
      }
      else if (d == 16) {
          if (val < 0) {
            for (j = 0; j < w; j++) {
                pval = GET_DATA_TWO_BYTES(line, j);
                pval = L_MAX(0, pval + val);
                SET_DATA_TWO_BYTES(line, j, pval);
            }
          }
          else {  /* val >= 0 */
            for (j = 0; j < w; j++) {
                pval = GET_DATA_TWO_BYTES(line, j);
                pval = L_MIN(0xffff, pval + val);
                SET_DATA_TWO_BYTES(line, j, pval);
            }
          }
      }
      else {  /* d == 32; no clipping */
          for (j = 0; j < w; j++)
            *(line + j) += val;
      }
    }
    return;
}


/*------------------------------------------------------------------*
 *        Two image grayscale arithmetic (8, 16 or 32 bpp)          *
 *------------------------------------------------------------------*/
/*!
 *  addGrayLow()
 */
void
addGrayLow(l_uint32  *datad,
           l_int32    w,
           l_int32    h,
           l_int32    d,
         l_int32    wpld,
           l_uint32  *datas,
           l_int32    wpls)
{
l_int32    i, j, val, sum;
l_uint32  *lines, *lined;


    for (i = 0; i < h; i++) {
      lined = datad + i * wpld;
      lines = datas + i * wpls;
      if (d == 8) {
          for (j = 0; j < w; j++) {
            sum = GET_DATA_BYTE(lines, j) + GET_DATA_BYTE(lined, j);
            val = L_MIN(sum, 255);
            SET_DATA_BYTE(lined, j, val);
          }
      }
      else if (d == 16) {
          for (j = 0; j < w; j++) {
            sum = GET_DATA_TWO_BYTES(lines, j)
                  + GET_DATA_TWO_BYTES(lined, j);
            val = L_MIN(sum, 0xffff);
            SET_DATA_TWO_BYTES(lined, j, val);
          }
      }
      else {   /* d == 32; no clipping */
          for (j = 0; j < w; j++)
            *(lined + j) += *(lines + j);
      }
    }

    return;
}


/*!
 *  subtractGrayLow()
 */
void
subtractGrayLow(l_uint32  *datad,
                l_int32    w,
                l_int32    h,
                l_int32    d,
              l_int32    wpld,
                l_uint32  *datas,
                l_int32    wpls,
                l_int32    swap)
{
l_int32    i, j, val, diff;
l_uint32  *lines, *lined;

    for (i = 0; i < h; i++) {
      lined = datad + i * wpld;
      lines = datas + i * wpls;
      if (swap == 0) {
          if (d == 8) {
            for (j = 0; j < w; j++) {
                diff = GET_DATA_BYTE(lined, j) - GET_DATA_BYTE(lines, j);
                val = L_MAX(diff, 0);
                SET_DATA_BYTE(lined, j, val);
            }
          }
          else if (d == 16) {
            for (j = 0; j < w; j++) {
                diff = GET_DATA_TWO_BYTES(lined, j)
                       - GET_DATA_TWO_BYTES(lines, j);
                val = L_MAX(diff, 0);
                SET_DATA_TWO_BYTES(lined, j, val);
            }
          }
          else {  /* d == 32; no clipping */
            for (j = 0; j < w; j++)
                *(lined + j) -= *(lines + j);
          }
      }
      else {   /* swap == 1 */
          if (d == 8) {
            for (j = 0; j < w; j++) {
                diff = GET_DATA_BYTE(lines, j) - GET_DATA_BYTE(lined, j);
                val = L_MAX(diff, 0);
                SET_DATA_BYTE(lined, j, val);
            }
          }
          else if (d == 16) {
            for (j = 0; j < w; j++) {
                diff = GET_DATA_TWO_BYTES(lines, j)
                       - GET_DATA_TWO_BYTES(lined, j);
                val = L_MAX(diff, 0);
                SET_DATA_TWO_BYTES(lined, j, val);
            }
          }
          else {  /* d == 32; no clipping */
            for (j = 0; j < w; j++)
                *(lined + j) = *(lines + j) - *(lined + j);
          }
      }
    }

    return;
}


/*-------------------------------------------------------------*
 *                  Grayscale threshold operation              *
 *-------------------------------------------------------------*/
/*!
 *  thresholdToValueLow()
 */
void
thresholdToValueLow(l_uint32  *datad,
                    l_int32    w,
                    l_int32    h,
                    l_int32    d,
                  l_int32    wpld,
                l_int32    threshval,
                l_int32    setval)
{
l_int32    i, j, setabove;
l_uint32  *lined;

    if (setval > threshval)
        setabove = TRUE;
    else
        setabove = FALSE;

    for (i = 0; i < h; i++) {
      lined = datad + i * wpld;
      if (setabove == TRUE) {
          if (d == 8) {
            for (j = 0; j < w; j++) {
                if (GET_DATA_BYTE(lined, j) - threshval >= 0)
                  SET_DATA_BYTE(lined, j, setval);
            }
          }
          else if (d == 16) {
            for (j = 0; j < w; j++) {
                if (GET_DATA_TWO_BYTES(lined, j) - threshval >= 0)
                  SET_DATA_TWO_BYTES(lined, j, setval);
            }
          }
          else {  /* d == 32 */
            for (j = 0; j < w; j++) {
                if (*(lined + j) - threshval >= 0)
                  *(lined + j) = setval;
            }
          }
      }
      else  { /* set if below or at threshold */
          if (d == 8) {
            for (j = 0; j < w; j++) {
                if (GET_DATA_BYTE(lined, j) - threshval <= 0)
                  SET_DATA_BYTE(lined, j, setval);
            }
          }
          else if (d == 16) {
            for (j = 0; j < w; j++) {
                if (GET_DATA_TWO_BYTES(lined, j) - threshval <= 0)
                  SET_DATA_TWO_BYTES(lined, j, setval);
            }
          }
          else {  /* d == 32 */
            for (j = 0; j < w; j++) {
                if (*(lined + j) - threshval <= 0)
                  *(lined + j) = setval;
            }
          }
      }
    }
    return;
}



/*-------------------------------------------------------------*
 *          Image accumulator arithmetic operations            *
 *-------------------------------------------------------------*/
/*!
 *  finalAccumulateLow()
 */
void
finalAccumulateLow(l_uint32  *datad,
                   l_int32    w,
                   l_int32    h,
               l_int32    d,
                 l_int32    wpld,
                   l_uint32  *datas,
                   l_int32    wpls,
                 l_uint32   offset)
{
l_int32    i, j;
l_int32    val;
l_uint32  *lines, *lined;

    switch (d)
    {
    case 8:
      for (i = 0; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;
          for (j = 0; j < w; j++) {
            val = lines[j] - offset;
            val = L_MAX(0, val);
            val = L_MIN(255, val);
            SET_DATA_BYTE(lined, j, (l_uint8)val);
          }
      }
      break;
    case 16:
      for (i = 0; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;
          for (j = 0; j < w; j++) {
            val = lines[j] - offset;
            val = L_MAX(0, val);
            val = L_MIN(0xffff, val);
            SET_DATA_TWO_BYTES(lined, j, (l_uint16)val);
          }
      }
      break;
    case 32:
      for (i = 0; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;
          for (j = 0; j < w; j++)
              lined[j] = lines[j] - offset;
      }
      break;
    }
    return;
}
   

/*!
 *  accumulateLow()
 */
void
accumulateLow(l_uint32  *datad,
              l_int32    w,
              l_int32    h,
            l_int32    wpld,
              l_uint32  *datas,
              l_int32    d,
              l_int32    wpls,
              l_int32    op)
{
l_int32    i, j;
l_uint32  *lines, *lined;

    switch (d)
    {
    case 1:
      for (i = 0; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;
          if (op == ARITH_ADD) {
            for (j = 0; j < w; j++)
                lined[j] += GET_DATA_BIT(lines, j);
          }
          else {  /* op == ARITH_SUBTRACT */
            for (j = 0; j < w; j++)
                lined[j] -= GET_DATA_BIT(lines, j);
          }
      }
      break;
    case 8:
      for (i = 0; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;
          if (op == ARITH_ADD) {
            for (j = 0; j < w; j++)
                lined[j] += GET_DATA_BYTE(lines, j);
          }
          else {  /* op == ARITH_SUBTRACT */
            for (j = 0; j < w; j++)
                lined[j] -= GET_DATA_BYTE(lines, j);
          }
      }
      break;
    case 16:
      for (i = 0; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;
          if (op == ARITH_ADD) {
            for (j = 0; j < w; j++)
                lined[j] += GET_DATA_TWO_BYTES(lines, j);
          }
          else {  /* op == ARITH_SUBTRACT */
            for (j = 0; j < w; j++)
                lined[j] -= GET_DATA_TWO_BYTES(lines, j);
          }
      }
      break;
    case 32:
      for (i = 0; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;
          if (op == ARITH_ADD) {
            for (j = 0; j < w; j++)
                lined[j] += lines[j];
          }
          else {  /* op == ARITH_SUBTRACT */
            for (j = 0; j < w; j++)
                lined[j] -= lines[j];
          }
      }
      break;
    }
    return;
}
   

/*!
 *  multConstAccumulateLow()
 */
void
multConstAccumulateLow(l_uint32  *data,
                       l_int32    w,
                       l_int32    h,
                     l_int32    wpl,
                       l_float32  factor,
                   l_uint32   offset)
{
l_int32    i, j;
l_int32    val;
l_uint32  *line;

    for (i = 0; i < h; i++) {
      line = data + i * wpl;
      for (j = 0; j < w; j++) {
          val = line[j] - offset;
          val = (l_int32)(val * factor);
          val += offset;
          line[j] = (l_uint32)val;
        }
    }
    return;
}
   

/*-----------------------------------------------------------------------*
 *              Absolute value of difference, component-wise             *
 *-----------------------------------------------------------------------*/
/*!
 *  absDifferenceLow()
 *
 *  Finds the absolute value of the difference of each pixel,
 *  for 8 and 16 bpp gray and for 32 bpp rgb.  For 32 bpp, the
 *  differences are found for each of the RGB components
 *  separately, and the LSB component is ignored.
 *  The results are written into datad.  
 */
void
absDifferenceLow(l_uint32  *datad,
             l_int32    w,
             l_int32    h,
             l_int32    wpld,
             l_uint32  *datas1,
             l_uint32  *datas2,
             l_int32    d,
               l_int32    wpls)
{
l_int32    i, j, val1, val2, diff;
l_uint32   word1, word2;
l_uint32  *lines1, *lines2, *lined, *pdword;

    PROCNAME("absDifferenceLow");

    switch (d)
    {
    case 8:
      for (i = 0; i < h; i++) {
          lines1 = datas1 + i * wpls;
          lines2 = datas2 + i * wpls;
          lined = datad + i * wpld;
          for (j = 0; j < w; j++) {
              val1 = GET_DATA_BYTE(lines1, j);
              val2 = GET_DATA_BYTE(lines2, j);
            diff = L_ABS(val1 - val2);
            SET_DATA_BYTE(lined, j, diff);
          }
      }
      break;
    case 16:
      for (i = 0; i < h; i++) {
          lines1 = datas1 + i * wpls;
          lines2 = datas2 + i * wpls;
          lined = datad + i * wpld;
          for (j = 0; j < w; j++) {
              val1 = GET_DATA_TWO_BYTES(lines1, j);
              val2 = GET_DATA_TWO_BYTES(lines2, j);
            diff = L_ABS(val1 - val2);
            SET_DATA_TWO_BYTES(lined, j, diff);
          }
      }
      break;
    case 32:
      for (i = 0; i < h; i++) {
          lines1 = datas1 + i * wpls;
          lines2 = datas2 + i * wpls;
          lined = datad + i * wpld;
          for (j = 0; j < w; j++) {
              word1 = lines1[j];
              word2 = lines2[j];
            pdword = lined + j;
              val1 = GET_DATA_BYTE(&word1, COLOR_RED);
              val2 = GET_DATA_BYTE(&word2, COLOR_RED);
            diff = L_ABS(val1 - val2);
            SET_DATA_BYTE(pdword, COLOR_RED, diff);
              val1 = GET_DATA_BYTE(&word1, COLOR_GREEN);
              val2 = GET_DATA_BYTE(&word2, COLOR_GREEN);
            diff = L_ABS(val1 - val2);
            SET_DATA_BYTE(pdword, COLOR_GREEN, diff);
              val1 = GET_DATA_BYTE(&word1, COLOR_BLUE);
              val2 = GET_DATA_BYTE(&word2, COLOR_BLUE);
            diff = L_ABS(val1 - val2);
            SET_DATA_BYTE(pdword, COLOR_BLUE, diff);
          }
      }
      break;
    default:
      ERROR_VOID("source depth must be 8, 16 or 32 bpp", procName);
      break;
    }

    return;
}


Generated by  Doxygen 1.6.0   Back to index