mirror of http://192.168.1.51:8099/lmh188/twain3.0
296 lines
11 KiB
C
296 lines
11 KiB
C
/*====================================================================*
|
|
- Copyright (C) 2001 Leptonica. All rights reserved.
|
|
-
|
|
- Redistribution and use in source and binary forms, with or without
|
|
- modification, are permitted provided that the following conditions
|
|
- are met:
|
|
- 1. Redistributions of source code must retain the above copyright
|
|
- notice, this list of conditions and the following disclaimer.
|
|
- 2. Redistributions in binary form must reproduce the above
|
|
- copyright notice, this list of conditions and the following
|
|
- disclaimer in the documentation and/or other materials
|
|
- provided with the distribution.
|
|
-
|
|
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
|
|
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*====================================================================*/
|
|
|
|
/*!
|
|
* Top-level fast binary morphology with auto-generated sels
|
|
*
|
|
* PIX *pixMorphDwa_2()
|
|
* PIX *pixFMorphopGen_2()
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "allheaders.h"
|
|
|
|
PIX *pixMorphDwa_2(PIX *pixd, PIX *pixs, l_int32 operation, char *selname);
|
|
PIX *pixFMorphopGen_2(PIX *pixd, PIX *pixs, l_int32 operation, char *selname);
|
|
l_int32 fmorphopgen_low_2(l_uint32 *datad, l_int32 w,
|
|
l_int32 h, l_int32 wpld,
|
|
l_uint32 *datas, l_int32 wpls,
|
|
l_int32 index);
|
|
|
|
static l_int32 NUM_SELS_GENERATED = 76;
|
|
static char SEL_NAMES[][80] = {
|
|
"sel_comb_4h",
|
|
"sel_comb_4v",
|
|
"sel_comb_5h",
|
|
"sel_comb_5v",
|
|
"sel_comb_6h",
|
|
"sel_comb_6v",
|
|
"sel_comb_7h",
|
|
"sel_comb_7v",
|
|
"sel_comb_8h",
|
|
"sel_comb_8v",
|
|
"sel_comb_9h",
|
|
"sel_comb_9v",
|
|
"sel_comb_10h",
|
|
"sel_comb_10v",
|
|
"sel_comb_12h",
|
|
"sel_comb_12v",
|
|
"sel_comb_14h",
|
|
"sel_comb_14v",
|
|
"sel_comb_15h",
|
|
"sel_comb_15v",
|
|
"sel_comb_16h",
|
|
"sel_comb_16v",
|
|
"sel_comb_18h",
|
|
"sel_comb_18v",
|
|
"sel_comb_20h",
|
|
"sel_comb_20v",
|
|
"sel_comb_21h",
|
|
"sel_comb_21v",
|
|
"sel_comb_22h",
|
|
"sel_comb_22v",
|
|
"sel_comb_24h",
|
|
"sel_comb_24v",
|
|
"sel_comb_25h",
|
|
"sel_comb_25v",
|
|
"sel_comb_27h",
|
|
"sel_comb_27v",
|
|
"sel_comb_28h",
|
|
"sel_comb_28v",
|
|
"sel_comb_30h",
|
|
"sel_comb_30v",
|
|
"sel_comb_32h",
|
|
"sel_comb_32v",
|
|
"sel_comb_33h",
|
|
"sel_comb_33v",
|
|
"sel_comb_35h",
|
|
"sel_comb_35v",
|
|
"sel_comb_36h",
|
|
"sel_comb_36v",
|
|
"sel_comb_39h",
|
|
"sel_comb_39v",
|
|
"sel_comb_40h",
|
|
"sel_comb_40v",
|
|
"sel_comb_42h",
|
|
"sel_comb_42v",
|
|
"sel_comb_44h",
|
|
"sel_comb_44v",
|
|
"sel_comb_45h",
|
|
"sel_comb_45v",
|
|
"sel_comb_48h",
|
|
"sel_comb_48v",
|
|
"sel_comb_49h",
|
|
"sel_comb_49v",
|
|
"sel_comb_50h",
|
|
"sel_comb_50v",
|
|
"sel_comb_52h",
|
|
"sel_comb_52v",
|
|
"sel_comb_54h",
|
|
"sel_comb_54v",
|
|
"sel_comb_55h",
|
|
"sel_comb_55v",
|
|
"sel_comb_56h",
|
|
"sel_comb_56v",
|
|
"sel_comb_60h",
|
|
"sel_comb_60v",
|
|
"sel_comb_63h",
|
|
"sel_comb_63v"};
|
|
|
|
/*!
|
|
* \brief pixMorphDwa_2()
|
|
*
|
|
* \param[in] pixd usual 3 choices: null, == pixs, != pixs
|
|
* \param[in] pixs 1 bpp
|
|
* \param[in] operation L_MORPH_DILATE, L_MORPH_ERODE,
|
|
* L_MORPH_OPEN, L_MORPH_CLOSE
|
|
* \param[in] sel name
|
|
* \return pixd
|
|
*
|
|
* <pre>
|
|
* Notes:
|
|
* (1) This simply adds a border, calls the appropriate
|
|
* pixFMorphopGen_*(), and removes the border.
|
|
* See the notes for that function.
|
|
* (2) The size of the border depends on the operation
|
|
* and the boundary conditions.
|
|
* </pre>
|
|
*/
|
|
PIX *
|
|
pixMorphDwa_2(PIX *pixd,
|
|
PIX *pixs,
|
|
l_int32 operation,
|
|
char *selname)
|
|
{
|
|
l_int32 bordercolor, bordersize;
|
|
PIX *pixt1, *pixt2, *pixt3;
|
|
|
|
PROCNAME("pixMorphDwa_2");
|
|
|
|
if (!pixs)
|
|
return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
|
|
if (pixGetDepth(pixs) != 1)
|
|
return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);
|
|
|
|
/* Set the border size */
|
|
bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
|
|
bordersize = 32;
|
|
if (bordercolor == 0 && operation == L_MORPH_CLOSE)
|
|
bordersize += 32;
|
|
|
|
pixt1 = pixAddBorder(pixs, bordersize, 0);
|
|
pixt2 = pixFMorphopGen_2(NULL, pixt1, operation, selname);
|
|
pixt3 = pixRemoveBorder(pixt2, bordersize);
|
|
pixDestroy(&pixt1);
|
|
pixDestroy(&pixt2);
|
|
|
|
if (!pixd)
|
|
return pixt3;
|
|
|
|
pixCopy(pixd, pixt3);
|
|
pixDestroy(&pixt3);
|
|
return pixd;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief pixFMorphopGen_2()
|
|
*
|
|
* \param[in] pixd usual 3 choices: null, == pixs, != pixs
|
|
* \param[in] pixs 1 bpp
|
|
* \param[in] operation L_MORPH_DILATE, L_MORPH_ERODE,
|
|
* L_MORPH_OPEN, L_MORPH_CLOSE
|
|
* \param[in] sel name
|
|
* \return pixd
|
|
*
|
|
* <pre>
|
|
* Notes:
|
|
* (1) This is a dwa operation, and the Sels must be limited in
|
|
* size to not more than 31 pixels about the origin.
|
|
* (2) A border of appropriate size (32 pixels, or 64 pixels
|
|
* for safe closing with asymmetric b.c.) must be added before
|
|
* this function is called.
|
|
* (3) This handles all required setting of the border pixels
|
|
* before erosion and dilation.
|
|
* (4) The closing operation is safe; no pixels can be removed
|
|
* near the boundary.
|
|
* </pre>
|
|
*/
|
|
PIX *
|
|
pixFMorphopGen_2(PIX *pixd,
|
|
PIX *pixs,
|
|
l_int32 operation,
|
|
char *selname)
|
|
{
|
|
l_int32 i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop;
|
|
l_uint32 *datad, *datas, *datat;
|
|
PIX *pixt;
|
|
|
|
PROCNAME("pixFMorphopGen_2");
|
|
|
|
if (!pixs)
|
|
return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
|
|
if (pixGetDepth(pixs) != 1)
|
|
return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);
|
|
|
|
/* Get boundary colors to use */
|
|
bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
|
|
if (bordercolor == 1)
|
|
erodeop = PIX_SET;
|
|
else
|
|
erodeop = PIX_CLR;
|
|
|
|
found = FALSE;
|
|
for (i = 0; i < NUM_SELS_GENERATED; i++) {
|
|
if (strcmp(selname, SEL_NAMES[i]) == 0) {
|
|
found = TRUE;
|
|
index = 2 * i;
|
|
break;
|
|
}
|
|
}
|
|
if (found == FALSE)
|
|
return (PIX *)ERROR_PTR("sel index not found", procName, pixd);
|
|
|
|
if (!pixd) {
|
|
if ((pixd = pixCreateTemplate(pixs)) == NULL)
|
|
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
|
|
}
|
|
else /* for in-place or pre-allocated */
|
|
pixResizeImageData(pixd, pixs);
|
|
wpls = pixGetWpl(pixs);
|
|
wpld = pixGetWpl(pixd);
|
|
|
|
/* The images must be surrounded, in advance, with a border of
|
|
* size 32 pixels (or 64, for closing), that we'll read from.
|
|
* Fabricate a "proper" image as the subimage within the 32
|
|
* pixel border, having the following parameters: */
|
|
w = pixGetWidth(pixs) - 64;
|
|
h = pixGetHeight(pixs) - 64;
|
|
datas = pixGetData(pixs) + 32 * wpls + 1;
|
|
datad = pixGetData(pixd) + 32 * wpld + 1;
|
|
|
|
if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) {
|
|
borderop = PIX_CLR;
|
|
if (operation == L_MORPH_ERODE) {
|
|
borderop = erodeop;
|
|
index++;
|
|
}
|
|
if (pixd == pixs) { /* in-place; generate a temp image */
|
|
if ((pixt = pixCopy(NULL, pixs)) == NULL)
|
|
return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
|
|
datat = pixGetData(pixt) + 32 * wpls + 1;
|
|
pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop);
|
|
fmorphopgen_low_2(datad, w, h, wpld, datat, wpls, index);
|
|
pixDestroy(&pixt);
|
|
}
|
|
else { /* not in-place */
|
|
pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop);
|
|
fmorphopgen_low_2(datad, w, h, wpld, datas, wpls, index);
|
|
}
|
|
}
|
|
else { /* opening or closing; generate a temp image */
|
|
if ((pixt = pixCreateTemplate(pixs)) == NULL)
|
|
return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
|
|
datat = pixGetData(pixt) + 32 * wpls + 1;
|
|
if (operation == L_MORPH_OPEN) {
|
|
pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop);
|
|
fmorphopgen_low_2(datat, w, h, wpls, datas, wpls, index+1);
|
|
pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR);
|
|
fmorphopgen_low_2(datad, w, h, wpld, datat, wpls, index);
|
|
}
|
|
else { /* closing */
|
|
pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR);
|
|
fmorphopgen_low_2(datat, w, h, wpls, datas, wpls, index);
|
|
pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop);
|
|
fmorphopgen_low_2(datad, w, h, wpld, datat, wpls, index+1);
|
|
}
|
|
pixDestroy(&pixt);
|
|
}
|
|
|
|
return pixd;
|
|
}
|
|
|