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

convolvelow.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.
 *====================================================================*/


/*
 *  convolvelow.c
 *
 *      Grayscale block convolution
 *          void      blockconvLow()
 *          void      blockconvAccumLow()
 *
 *      Binary block sum and rank filter
 *          void      blocksumLow()
 */

#include <stdio.h>
#include "allheaders.h"


/*----------------------------------------------------------------------*
 *                     Grayscale Block Convolution                      *
 *----------------------------------------------------------------------*/
/*!
 *  blockconvLow()
 *
 *      Input:  data   (data of input image, to be convolved)
 *              w, h, wpl
 *              dataa    (data of 32 bpp accumulator)
 *              wpla     (accumulator)
 *              wc      (convolution "half-width")
 *              hc      (convolution "half-height")
 *      Return: void
 *
 *      Action: compute sums, normalized as if there were no reduced
 *              area at the boundary.  This under-estimates the value
 *              of the boundary pixels, so we multiply them by another
 *              normalization factor that is greater than 1.
 *
 *              This second normalization is done first for the first
 *              hc + 1 lines; then for the last hc lines; and finally
 *              for the first wc + 1 and last wc columns in the intermediate
 *              lines.
 *
 *      Notes: (1) The full width and height of the convolution kernel
 *                 are (2 * wc + 1) and (2 * hc + 1).
 *             (2) The lack of symmetry between the handling of the
 *                 first (hc + 1) lines and the last (hc) lines,
 *                 and similarly with the columns, is due to fact that
 *                 for the pixel at (x,y), the accumulator values are
 *                 taken at (x + wc, y + hc), (x - wc - 1, y + hc),
 *                 (x + wc, y - hc - 1) and (x - wc - 1, y - hc - 1).
 */
void
blockconvLow(l_uint32  *data,
           l_int32    w,
           l_int32    h,
           l_int32    wpl,
           l_uint32  *dataa,
           l_int32    wpla,
           l_int32    wc,
           l_int32    hc)
{
l_int32    i, j, imax, imin, jmax, jmin;
l_int32    wn, hn, fwc, fhc, wmwc, hmhc;
l_float32  norm, normh, normw;
l_uint32   val;
l_uint32  *linemina, *linemaxa, *line;

    wmwc = w - wc;
    hmhc = h - hc;
    fwc = 2 * wc + 1;
    fhc = 2 * hc + 1;
    norm = 1. / (fwc * fhc);

      /*------------------------------------------------------------*
       *  compute, using b.c. only to set limits on the accum image *
       *------------------------------------------------------------*/
    for (i = 0; i < h; i++) {
      imin = L_MAX(i - 1 - hc, 0);
      imax = L_MIN(i + hc, h - 1);
      line = data + wpl * i;
      linemina = dataa + wpla * imin;
      linemaxa = dataa + wpla * imax;
      for (j = 0; j < w; j++) {
          jmin = L_MAX(j - 1 - wc, 0);
          jmax = L_MIN(j + wc, w - 1);
          val = linemaxa[jmax] - linemaxa[jmin]
              - linemina[jmax] + linemina[jmin];
          val = (l_uint8)(norm * val);
          SET_DATA_BYTE(line, j, val);
      }
    }

      /*------------------------------------------------------------*
       *          now fix normalization for boundary pixels         *
       *------------------------------------------------------------*/
    for (i = 0; i <= hc; i++) {    /* first hc + 1 lines */
      hn = hc + i;
      normh = (l_float32)fhc / (l_float32)hn;   /* > 1 */
      line = data + wpl * i;
      for (j = 0; j <= wc; j++) {
          wn = wc + j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(line, j);
          val = (l_uint8)(val * normh * normw);
          SET_DATA_BYTE(line, j, val);
      }
      for (j = wc + 1; j < wmwc; j++) {
          val = GET_DATA_BYTE(line, j);
          val = (l_uint8)(val * normh);
          SET_DATA_BYTE(line, j, val);
      }
      for (j = wmwc; j < w; j++) {
          wn = wc + w - j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(line, j);
          val = (l_uint8)(val * normh * normw);
          SET_DATA_BYTE(line, j, val);
      }
    }

    for (i = hmhc; i < h; i++) {  /* last hc lines */
      hn = hc + h - i;
      normh = (l_float32)fhc / (l_float32)hn;   /* > 1 */
      line = data + wpl * i;
      for (j = 0; j <= wc; j++) {
          wn = wc + j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(line, j);
          val = (l_uint8)(val * normh * normw);
          SET_DATA_BYTE(line, j, val);
      }
      for (j = wc + 1; j < wmwc; j++) {
          val = GET_DATA_BYTE(line, j);
          val = (l_uint8)(val * normh);
          SET_DATA_BYTE(line, j, val);
      }
      for (j = wmwc; j < w; j++) {
          wn = wc + w - j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(line, j);
          val = (l_uint8)(val * normh * normw);
          SET_DATA_BYTE(line, j, val);
      }
    }

    for (i = hc + 1; i < hmhc; i++) {    /* intermediate lines */
      line = data + wpl * i;
      for (j = 0; j <= wc; j++) {   /* first wc + 1 columns */
          wn = wc + j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(line, j);
          val = (l_uint8)(val * normw);
          SET_DATA_BYTE(line, j, val);
      }
      for (j = wmwc; j < w; j++) {   /* last wc columns */
          wn = wc + w - j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(line, j);
          val = (l_uint8)(val * normw);
          SET_DATA_BYTE(line, j, val);
      }
    }

    return;
}



/*
 *   blockconvAccumLow()
 *
 *       Input:  datad  (of 32 bpp dest)
 *               w, h, wpld (of 32 bpp dest)
 *               datas (of 1 or 8 bpp src)
 *               d (bpp of src)
 *               wpls (of src)
 *       Return: void
 *
 *       Action:  The general recursion relation is
 *                   a(i,j) = v(i,j) + a(i-1, j) + a(i, j-1) - a(i-1, j-1)
 *                For the first line, this reduces to the special case
 *                   a(i,j) = v(i,j) + a(i, j-1)
 *                For the first column, the special case is
 *                   a(i,j) = v(i,j) + a(i-1, j)
 */
void
blockconvAccumLow(l_uint32  *datad,
                  l_int32    w,
                  l_int32    h,
                  l_int32    wpld,
                  l_uint32  *datas,
                  l_int32    d,
                  l_int32    wpls)
{
l_uint8    val;
l_int32    i, j;
l_uint32  *lines, *lined, *linedp;

    PROCNAME("blockconvAccumLow");

    lines = datas;
    lined = datad;

    if (d == 1) {
          /* do the first line */
      for (j = 0; j < w; j++) {
          val = GET_DATA_BIT(lines, j);
          if (j == 0)
            lined[0] = val;
          else
            lined[j] = lined[j - 1] + val;
      }

          /* do the other lines */
      for (i = 1; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;  /* curr dest line */
          linedp = lined - wpld;   /* prev dest line */
          for (j = 0; j < w; j++) {
            val = GET_DATA_BIT(lines, j);
            if (j == 0)
                lined[0] = val + linedp[0];
            else 
                lined[j] = val + lined[j - 1] + linedp[j] - linedp[j - 1];
          }
      }
    }
    else if (d == 8) {
          /* do the first line */
      for (j = 0; j < w; j++) {
          val = GET_DATA_BYTE(lines, j);
          if (j == 0)
            lined[0] = val;
          else
            lined[j] = lined[j - 1] + val;
      }

          /* do the other lines */
      for (i = 1; i < h; i++) {
          lines = datas + i * wpls;
          lined = datad + i * wpld;  /* curr dest line */
          linedp = lined - wpld;   /* prev dest line */
          for (j = 0; j < w; j++) {
            val = GET_DATA_BYTE(lines, j);
            if (j == 0)
                lined[0] = val + linedp[0];
            else 
                lined[j] = val + lined[j - 1] + linedp[j] - linedp[j - 1];
          }
      }
    }
    else
        ERROR_VOID("depth not 1 or 8 bpp", procName);

    return;
}


/*----------------------------------------------------------------------*
 *                        Binary Block Sum/Rank                         *
 *----------------------------------------------------------------------*/
/*!
 *  blocksumLow()
 *
 *       Input:  datad  (of 8 bpp dest)
 *               w, h, wpl  (of 8 bpp dest)
 *               dataa (of 32 bpp accum)
 *               wpla  (of 32 bpp accum)
 *               wc, hc  (convolution "half-width" and "half-height")
 *       Return: void
 *
 *       Action: compute sums of ON pixels within the block filter size,
 *               normalized between 0 and 255, as if there were no reduced
 *               area at the boundary.  This under-estimates the value
 *               of the boundary pixels, so we multiply them by another
 *               normalization factor that is greater than 1.
 *
 *               This second normalization is done first for the first
 *               hc + 1 lines; then for the last hc lines; and finally
 *               for the first wc + 1 and last wc columns in the intermediate
 *               lines.
 *
 *          Notes:
 *             (1) The full width and height of the convolution kernel
 *                 are (2 * wc + 1) and (2 * hc + 1).
 *             (2) The lack of symmetry between the handling of the
 *                 first (hc + 1) lines and the last (hc) lines,
 *                 and similarly with the columns, is due to fact that
 *                 for the pixel at (x,y), the accumulator values are
 *                 taken at (x + wc, y + hc), (x - wc - 1, y + hc),
 *                 (x + wc, y - hc - 1) and (x - wc - 1, y - hc - 1).
 */
void
blocksumLow(l_uint32  *datad,
          l_int32    w,
          l_int32    h,
          l_int32    wpl,
          l_uint32  *dataa,
          l_int32    wpla,
          l_int32    wc,
          l_int32    hc)
{
l_int32    i, j, imax, imin, jmax, jmin;
l_int32    wn, hn, fwc, fhc, wmwc, hmhc;
l_float32  norm, normh, normw;
l_uint32   val;
l_uint32  *linemina, *linemaxa, *lined;

    wmwc = w - wc;
    hmhc = h - hc;
    fwc = 2 * wc + 1;
    fhc = 2 * hc + 1;
    norm = 255. / (fwc * fhc);

      /*------------------------------------------------------------*
       *  compute, using b.c. only to set limits on the accum image *
       *------------------------------------------------------------*/
    for (i = 0; i < h; i++) {
      imin = L_MAX(i - 1 - hc, 0);
      imax = L_MIN(i + hc, h - 1);
      lined = datad + wpl * i;
      linemina = dataa + wpla * imin;
      linemaxa = dataa + wpla * imax;
      for (j = 0; j < w; j++) {
          jmin = L_MAX(j - 1 - wc, 0);
          jmax = L_MIN(j + wc, w - 1);
          val = linemaxa[jmax] - linemaxa[jmin]
              - linemina[jmax] + linemina[jmin];
          val = (l_uint8)(norm * val);
          SET_DATA_BYTE(lined, j, val);
      }
    }

      /*------------------------------------------------------------*
       *          now fix normalization for boundary pixels         *
       *------------------------------------------------------------*/
    for (i = 0; i <= hc; i++) {    /* first hc + 1 lines */
      hn = hc + i;
      normh = (l_float32)fhc / (l_float32)hn;   /* > 1 */
      lined = datad + wpl * i;
      for (j = 0; j <= wc; j++) {
          wn = wc + j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(lined, j);
          val = (l_uint8)(val * normh * normw);
          SET_DATA_BYTE(lined, j, val);
      }
      for (j = wc + 1; j < wmwc; j++) {
          val = GET_DATA_BYTE(lined, j);
          val = (l_uint8)(val * normh);
          SET_DATA_BYTE(lined, j, val);
      }
      for (j = wmwc; j < w; j++) {
          wn = wc + w - j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(lined, j);
          val = (l_uint8)(val * normh * normw);
          SET_DATA_BYTE(lined, j, val);
      }
    }

    for (i = hmhc; i < h; i++) {  /* last hc lines */
      hn = hc + h - i;
      normh = (l_float32)fhc / (l_float32)hn;   /* > 1 */
      lined = datad + wpl * i;
      for (j = 0; j <= wc; j++) {
          wn = wc + j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(lined, j);
          val = (l_uint8)(val * normh * normw);
          SET_DATA_BYTE(lined, j, val);
      }
      for (j = wc + 1; j < wmwc; j++) {
          val = GET_DATA_BYTE(lined, j);
          val = (l_uint8)(val * normh);
          SET_DATA_BYTE(lined, j, val);
      }
      for (j = wmwc; j < w; j++) {
          wn = wc + w - j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(lined, j);
          val = (l_uint8)(val * normh * normw);
          SET_DATA_BYTE(lined, j, val);
      }
    }

    for (i = hc + 1; i < hmhc; i++) {    /* intermediate lines */
      lined = datad + wpl * i;
      for (j = 0; j <= wc; j++) {   /* first wc + 1 columns */
          wn = wc + j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(lined, j);
          val = (l_uint8)(val * normw);
          SET_DATA_BYTE(lined, j, val);
      }
      for (j = wmwc; j < w; j++) {   /* last wc columns */
          wn = wc + w - j;
          normw = (l_float32)fwc / (l_float32)wn;   /* > 1 */
          val = GET_DATA_BYTE(lined, j);
          val = (l_uint8)(val * normw);
          SET_DATA_BYTE(lined, j, val);
      }
    }

    return;
}


Generated by  Doxygen 1.6.0   Back to index