blob: 2c4d8b37a09555cd32c8758bdbdea024988d7532 [file] [log] [blame]
/*====================================================================*
- 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.
*====================================================================*/
/*
* Top-level fast binary morphology with auto-generated sels
*
* PIX *pixMorphDwa_1()
* PIX *pixFMorphopGen_1()
*/
#include <stdio.h>
#include <string.h>
#include "allheaders.h"
PIX *pixMorphDwa_1(PIX *pixd, PIX *pixs, l_int32 operation, char *selname);
PIX *pixFMorphopGen_1(PIX *pixd, PIX *pixs, l_int32 operation, char *selname);
l_int32 fmorphopgen_low_1(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 = 58;
static char SEL_NAMES[][80] = {
"sel_2h",
"sel_3h",
"sel_4h",
"sel_5h",
"sel_6h",
"sel_7h",
"sel_8h",
"sel_9h",
"sel_10h",
"sel_11h",
"sel_12h",
"sel_13h",
"sel_14h",
"sel_15h",
"sel_20h",
"sel_21h",
"sel_25h",
"sel_30h",
"sel_31h",
"sel_35h",
"sel_40h",
"sel_41h",
"sel_45h",
"sel_50h",
"sel_51h",
"sel_2v",
"sel_3v",
"sel_4v",
"sel_5v",
"sel_6v",
"sel_7v",
"sel_8v",
"sel_9v",
"sel_10v",
"sel_11v",
"sel_12v",
"sel_13v",
"sel_14v",
"sel_15v",
"sel_20v",
"sel_21v",
"sel_25v",
"sel_30v",
"sel_31v",
"sel_35v",
"sel_40v",
"sel_41v",
"sel_45v",
"sel_50v",
"sel_51v",
"sel_2",
"sel_3",
"sel_4",
"sel_5",
"sel_2dp",
"sel_2dm",
"sel_5dp",
"sel_5dm"};
/*
* pixMorphDwa_1()
*
* Input: pixd (usual 3 choices: null, == pixs, != pixs)
* pixs (1 bpp)
* operation (L_MORPH_DILATE, L_MORPH_ERODE,
* L_MORPH_OPEN, L_MORPH_CLOSE)
* sel name
* Return: pixd
*
* 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.
*/
PIX *
pixMorphDwa_1(PIX *pixd,
PIX *pixs,
l_int32 operation,
char *selname)
{
l_int32 bordercolor, bordersize;
PIX *pixt1, *pixt2, *pixt3;
PROCNAME("pixMorphDwa_1");
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_1(NULL, pixt1, operation, selname);
pixt3 = pixRemoveBorder(pixt2, bordersize);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
if (!pixd)
return pixt3;
pixCopy(pixd, pixt3);
pixDestroy(&pixt3);
return pixd;
}
/*
* pixFMorphopGen_1()
*
* Input: pixd (usual 3 choices: null, == pixs, != pixs)
* pixs (1 bpp)
* operation (L_MORPH_DILATE, L_MORPH_ERODE,
* L_MORPH_OPEN, L_MORPH_CLOSE)
* sel name
* Return: pixd
*
* 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.
*/
PIX *
pixFMorphopGen_1(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_1");
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_1(datad, w, h, wpld, datat, wpls, index);
pixDestroy(&pixt);
}
else { /* not in-place */
pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop);
fmorphopgen_low_1(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_1(datat, w, h, wpls, datas, wpls, index+1);
pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR);
fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index);
}
else { /* closing */
pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR);
fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index);
pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop);
fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index+1);
}
pixDestroy(&pixt);
}
return pixd;
}