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

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


/*
 *  graymorph.c
 *
 *      Top-level binary morphological operations
 *
 *            PIX     *pixErodeGray()
 *            PIX     *pixDilateGray()
 *            PIX     *pixOpenGray()
 *            PIX     *pixCloseGray()
 *
 *
 *      Method: Algorithm by van Herk and Gil and Werman, 1992
 *
 *      Measured speed is about 1 output pixel per 120 PIII clock cycles,
 *      for a horizontal or vertical erosion or dilation.  The 
 *      computation time doubles for opening or closing, or for a
 *      square SE, as expected, and is independent of the size of the SE.
 *      
 */

#include <stdio.h>
#include <stdlib.h>

#include "allheaders.h"



/*-----------------------------------------------------------------*
 *              Top-level gray morphological operations            *
 *-----------------------------------------------------------------*/
/*!
 *  pixErodeGray()
 *
 *     Input: pixs
 *            size  (of SEL; must be odd; center implicitly in center)
 *            shape  (MORPH_HORIZ, MORPH_VERT, MORPH_SQUARE)
 *     Return: pixd
 *
 */
PIX *
pixErodeGray(PIX     *pixs,
             l_int32  size,
           l_int32  shape)
{
l_uint8   *buffer, *minarray;
l_int32    w, h, wplb, wplt;
l_int32    leftpix, rightpix, toppix, bottompix;
l_uint32  *datab, *datat;
PIX       *pixb, *pixt, *pixd;

    PROCNAME("pixErodeGray");

    if (!pixs)
      return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 8)
      return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (shape != MORPH_HORIZ && shape != MORPH_VERT && shape != MORPH_SQUARE)
      return (PIX *)ERROR_PTR("shape not in MORPH_{HORIZ, VERT, SQUARE}",
           procName, NULL);
    if ((size & 1) == 0) {
      L_WARNING("SEL size must be odd; increasing by 1", procName);
      size++;
    }

    if (shape == MORPH_HORIZ) {
      leftpix = (size + 1) / 2;
      rightpix = (3 * size + 1) / 2;
      toppix = 0;
      bottompix = 0;
    }
    else if (shape == MORPH_VERT) {
      leftpix = 0;
      rightpix = 0;
      toppix = (size + 1) / 2;
      bottompix = (3 * size + 1) / 2;
    }
    else {  /* shape == MORPH_SQUARE */
      leftpix = (size + 1) / 2;
      rightpix = (3 * size + 1) / 2;
      toppix = (size + 1) / 2;
      bottompix = (3 * size + 1) / 2;
    }

    if ((pixb = pixAddBorderGeneral(pixs,
            leftpix, rightpix, toppix, bottompix, 255)) == NULL)
      return (PIX *)ERROR_PTR("pixb not made", procName, NULL);
    if ((pixt = pixCreateTemplate(pixb)) == NULL)
      return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
    
    w = pixGetWidth(pixt);
    h = pixGetHeight(pixt);
    datab = pixGetData(pixb);
    datat = pixGetData(pixt);
    wplb = pixGetWpl(pixb);
    wplt = pixGetWpl(pixt);

    if ((buffer = (l_uint8 *)CALLOC(L_MAX(w, h), sizeof(l_uint8))) == NULL)
      return (PIX *)ERROR_PTR("buffer not made", procName, NULL);

    if ((minarray = (l_uint8 *)CALLOC(2 * size, sizeof(l_uint8))) == NULL)
      return (PIX *)ERROR_PTR("minarray not made", procName, NULL);

    if (shape == MORPH_HORIZ)
      erodeGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                 buffer, minarray);
    else if (shape == MORPH_VERT)
      erodeGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_VERT,
                 buffer, minarray);
    else {  /* shape == MORPH_SQUARE */
      erodeGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                 buffer, minarray);
      pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
                          PIX_SET);
      erodeGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_VERT,
                 buffer, minarray);
      pixDestroy(&pixt);
      pixt = pixClone(pixb);
    }

    if ((pixd = pixRemoveBorderGeneral(pixt,
            leftpix, rightpix, toppix, bottompix)) == NULL)
      return (PIX *)ERROR_PTR("pixd not made", procName, NULL);

    FREE((void *)buffer);
    FREE((void *)minarray);

    pixDestroy(&pixb);
    pixDestroy(&pixt);
    return pixd;
}


/*!
 *  pixDilateGray()
 *
 *     Input: pixs
 *            size  (of SEL; must be odd; center implicitly in center)
 *            shape  (MORPH_HORIZ, MORPH_VERT, MORPH_SQUARE)
 *     Return: pixd
 *
 */
PIX *
pixDilateGray(PIX     *pixs,
              l_int32  size,
            l_int32  shape)
{
l_uint8   *buffer, *maxarray;
l_int32    w, h, wplb, wplt;
l_int32    leftpix, rightpix, toppix, bottompix;
l_uint32  *datab, *datat;
PIX       *pixb, *pixt, *pixd;

    PROCNAME("pixDilateGray");

    if (!pixs)
      return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 8)
      return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (shape != MORPH_HORIZ && shape != MORPH_VERT && shape != MORPH_SQUARE)
      return (PIX *)ERROR_PTR("shape not in MORPH_{HORIZ, VERT, SQUARE}",
           procName, NULL);
    if ((size & 1) == 0) {
      L_WARNING("SEL size must be odd; increasing by 1", procName);
      size++;
    }

    if (shape == MORPH_HORIZ) {
      leftpix = (size + 1) / 2;
      rightpix = (3 * size + 1) / 2;
      toppix = 0;
      bottompix = 0;
    }
    else if (shape == MORPH_VERT) {
      leftpix = 0;
      rightpix = 0;
      toppix = (size + 1) / 2;
      bottompix = (3 * size + 1) / 2;
    }
    else {  /* shape == MORPH_SQUARE */
      leftpix = (size + 1) / 2;
      rightpix = (3 * size + 1) / 2;
      toppix = (size + 1) / 2;
      bottompix = (3 * size + 1) / 2;
    }

    if ((pixb = pixAddBorderGeneral(pixs,
            leftpix, rightpix, toppix, bottompix, 0)) == NULL)
      return (PIX *)ERROR_PTR("pixb not made", procName, NULL);
    if ((pixt = pixCreateTemplate(pixb)) == NULL)
      return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
    
    w = pixGetWidth(pixt);
    h = pixGetHeight(pixt);
    datab = pixGetData(pixb);
    datat = pixGetData(pixt);
    wplb = pixGetWpl(pixb);
    wplt = pixGetWpl(pixt);

    if ((buffer = (l_uint8 *)CALLOC(L_MAX(w, h), sizeof(l_uint8))) == NULL)
      return (PIX *)ERROR_PTR("buffer not made", procName, NULL);

    if ((maxarray = (l_uint8 *)CALLOC(2 * size, sizeof(l_uint8))) == NULL)
      return (PIX *)ERROR_PTR("buffer not made", procName, NULL);

    if (shape == MORPH_HORIZ)
      dilateGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                  buffer, maxarray);
    else if (shape == MORPH_VERT)
      dilateGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_VERT,
                  buffer, maxarray);
    else {  /* shape == MORPH_SQUARE */
      dilateGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                  buffer, maxarray);
      dilateGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_VERT,
                  buffer, maxarray);
      pixDestroy(&pixt);
      pixt = pixClone(pixb);
    }

    if ((pixd = pixRemoveBorderGeneral(pixt,
            leftpix, rightpix, toppix, bottompix)) == NULL)
      return (PIX *)ERROR_PTR("pixd not made", procName, NULL);

    FREE((void *)buffer);
    FREE((void *)maxarray);

    pixDestroy(&pixb);
    pixDestroy(&pixt);
    return pixd;
}


/*!
 *  pixOpenGray()
 *
 *     Input: pixs
 *            size  (of SEL; must be odd; center implicitly in center)
 *            shape  (MORPH_HORIZ, MORPH_VERT, MORPH_SQUARE)
 *     Return: pixd
 *
 */
PIX *
pixOpenGray(PIX     *pixs,
            l_int32  size,
          l_int32  shape)
{
l_uint8   *buffer, *minarray;
l_int32    w, h, wplb, wplt;
l_int32    leftpix, rightpix, toppix, bottompix;
l_uint32  *datab, *datat;
PIX       *pixb, *pixt, *pixd;

    PROCNAME("pixOpenGray");

    if (!pixs)
      return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 8)
      return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (shape != MORPH_HORIZ && shape != MORPH_VERT && shape != MORPH_SQUARE)
      return (PIX *)ERROR_PTR("shape not in MORPH_{HORIZ, VERT, SQUARE}",
           procName, NULL);
    if ((size & 1) == 0) {
      L_WARNING("SEL size must be odd; increasing by 1", procName);
      size++;
    }

    if (shape == MORPH_HORIZ) {
      leftpix = (size + 1) / 2;
      rightpix = (3 * size + 1) / 2;
      toppix = 0;
      bottompix = 0;
    }
    else if (shape == MORPH_VERT) {
      leftpix = 0;
      rightpix = 0;
      toppix = (size + 1) / 2;
      bottompix = (3 * size + 1) / 2;
    }
    else {  /* shape == MORPH_SQUARE */
      leftpix = (size + 1) / 2;
      rightpix = (3 * size + 1) / 2;
      toppix = (size + 1) / 2;
      bottompix = (3 * size + 1) / 2;
    }

    if ((pixb = pixAddBorderGeneral(pixs,
            leftpix, rightpix, toppix, bottompix, 255)) == NULL)
      return (PIX *)ERROR_PTR("pixb not made", procName, NULL);
    if ((pixt = pixCreateTemplate(pixb)) == NULL)
      return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
    
    w = pixGetWidth(pixt);
    h = pixGetHeight(pixt);
    datab = pixGetData(pixb);
    datat = pixGetData(pixt);
    wplb = pixGetWpl(pixb);
    wplt = pixGetWpl(pixt);

    if ((buffer = (l_uint8 *)CALLOC(L_MAX(w, h), sizeof(l_uint8))) == NULL)
      return (PIX *)ERROR_PTR("buffer not made", procName, NULL);

    if ((minarray = (l_uint8 *)CALLOC(2 * size, sizeof(l_uint8))) == NULL)
      return (PIX *)ERROR_PTR("minarray not made", procName, NULL);

    if (shape == MORPH_HORIZ) {
      erodeGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                 buffer, minarray);
      dilateGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_HORIZ,
                  buffer, minarray);
    }
    else if (shape == MORPH_VERT) {
      erodeGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_VERT,
                 buffer, minarray);
      dilateGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_VERT,
                  buffer, minarray);
    }
    else {  /* shape == MORPH_SQUARE */
      erodeGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                 buffer, minarray);
      pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
                          PIX_SET);
      erodeGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_VERT,
                 buffer, minarray);
      pixSetOrClearBorder(pixb, leftpix, rightpix, toppix, bottompix,
                          PIX_CLR);
      dilateGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                  buffer, minarray);
      pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
                          PIX_CLR);
      dilateGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_VERT,
                  buffer, minarray);
    }

    if ((pixd = pixRemoveBorderGeneral(pixb,
            leftpix, rightpix, toppix, bottompix)) == NULL)
      return (PIX *)ERROR_PTR("pixd not made", procName, NULL);

    FREE((void *)buffer);
    FREE((void *)minarray);

    pixDestroy(&pixb);
    pixDestroy(&pixt);
    return pixd;
}


/*!
 *  pixCloseGray()
 *
 *     Input: pixs
 *            size  (of SEL; must be odd; center implicitly in center)
 *            shape  (MORPH_HORIZ, MORPH_VERT, MORPH_SQUARE)
 *     Return: pixd
 *
 */
PIX *
pixCloseGray(PIX     *pixs,
             l_int32  size,
           l_int32  shape)
{
l_uint8   *buffer, *minarray;
l_int32    w, h, wplb, wplt;
l_int32    leftpix, rightpix, toppix, bottompix;
l_uint32  *datab, *datat;
PIX       *pixb, *pixt, *pixd;

    PROCNAME("pixCloseGray");

    if (!pixs)
      return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 8)
      return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (shape != MORPH_HORIZ && shape != MORPH_VERT && shape != MORPH_SQUARE)
      return (PIX *)ERROR_PTR("shape not in MORPH_{HORIZ, VERT, SQUARE}",
           procName, NULL);
    if ((size & 1) == 0) {
      L_WARNING("SEL size must be odd; increasing by 1", procName);
      size++;
    }

    if (shape == MORPH_HORIZ) {
      leftpix = (size + 1) / 2;
      rightpix = (3 * size + 1) / 2;
      toppix = 0;
      bottompix = 0;
    }
    else if (shape == MORPH_VERT) {
      leftpix = 0;
      rightpix = 0;
      toppix = (size + 1) / 2;
      bottompix = (3 * size + 1) / 2;
    }
    else {  /* shape == MORPH_SQUARE */
      leftpix = (size + 1) / 2;
      rightpix = (3 * size + 1) / 2;
      toppix = (size + 1) / 2;
      bottompix = (3 * size + 1) / 2;
    }

    if ((pixb = pixAddBorderGeneral(pixs,
            leftpix, rightpix, toppix, bottompix, 0)) == NULL)
      return (PIX *)ERROR_PTR("pixb not made", procName, NULL);
    if ((pixt = pixCreateTemplate(pixb)) == NULL)
      return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
    
    w = pixGetWidth(pixt);
    h = pixGetHeight(pixt);
    datab = pixGetData(pixb);
    datat = pixGetData(pixt);
    wplb = pixGetWpl(pixb);
    wplt = pixGetWpl(pixt);

    if ((buffer = (l_uint8 *)CALLOC(L_MAX(w, h), sizeof(l_uint8))) == NULL)
      return (PIX *)ERROR_PTR("buffer not made", procName, NULL);

    if ((minarray = (l_uint8 *)CALLOC(2 * size, sizeof(l_uint8))) == NULL)
      return (PIX *)ERROR_PTR("minarray not made", procName, NULL);

    if (shape == MORPH_HORIZ) {
      dilateGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                 buffer, minarray);
      pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
                          PIX_SET);
      erodeGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_HORIZ,
                  buffer, minarray);
    }
    else if (shape == MORPH_VERT) {
      dilateGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_VERT,
                 buffer, minarray);
      pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
                          PIX_SET);
      erodeGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_VERT,
                  buffer, minarray);
    }
    else {  /* shape == MORPH_SQUARE */
      dilateGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                  buffer, minarray);
      dilateGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_VERT,
                  buffer, minarray);
      pixSetOrClearBorder(pixb, leftpix, rightpix, toppix, bottompix,
                          PIX_SET);
      erodeGrayLow(datat, w, h, wplt, datab, wplb, size, MORPH_HORIZ,
                 buffer, minarray);
      pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
                          PIX_SET);
      erodeGrayLow(datab, w, h, wplb, datat, wplt, size, MORPH_VERT,
                 buffer, minarray);
    }

    if ((pixd = pixRemoveBorderGeneral(pixb,
            leftpix, rightpix, toppix, bottompix)) == NULL)
      return (PIX *)ERROR_PTR("pixd not made", procName, NULL);

    FREE((void *)buffer);
    FREE((void *)minarray);

    pixDestroy(&pixb);
    pixDestroy(&pixt);
    return pixd;
}



Generated by  Doxygen 1.6.0   Back to index