Leptonica 1.68
C Image Processing Library

fmorphgen.1.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*!
00017  *      Top-level fast binary morphology with auto-generated sels
00018  *
00019  *             PIX     *pixMorphDwa_1()
00020  *             PIX     *pixFMorphopGen_1()
00021  */
00022 
00023 #include <string.h>
00024 #include "allheaders.h"
00025 
00026 PIX *pixMorphDwa_1(PIX *pixd, PIX *pixs, l_int32 operation, char *selname);
00027 PIX *pixFMorphopGen_1(PIX *pixd, PIX *pixs, l_int32 operation, char *selname);
00028 l_int32 fmorphopgen_low_1(l_uint32 *datad, l_int32 w,
00029                           l_int32 h, l_int32 wpld,
00030                           l_uint32 *datas, l_int32 wpls,
00031                           l_int32 index);
00032 
00033 static l_int32   NUM_SELS_GENERATED = 58;
00034 static char  SEL_NAMES[][80] = {
00035                              "sel_2h",
00036                              "sel_3h",
00037                              "sel_4h",
00038                              "sel_5h",
00039                              "sel_6h",
00040                              "sel_7h",
00041                              "sel_8h",
00042                              "sel_9h",
00043                              "sel_10h",
00044                              "sel_11h",
00045                              "sel_12h",
00046                              "sel_13h",
00047                              "sel_14h",
00048                              "sel_15h",
00049                              "sel_20h",
00050                              "sel_21h",
00051                              "sel_25h",
00052                              "sel_30h",
00053                              "sel_31h",
00054                              "sel_35h",
00055                              "sel_40h",
00056                              "sel_41h",
00057                              "sel_45h",
00058                              "sel_50h",
00059                              "sel_51h",
00060                              "sel_2v",
00061                              "sel_3v",
00062                              "sel_4v",
00063                              "sel_5v",
00064                              "sel_6v",
00065                              "sel_7v",
00066                              "sel_8v",
00067                              "sel_9v",
00068                              "sel_10v",
00069                              "sel_11v",
00070                              "sel_12v",
00071                              "sel_13v",
00072                              "sel_14v",
00073                              "sel_15v",
00074                              "sel_20v",
00075                              "sel_21v",
00076                              "sel_25v",
00077                              "sel_30v",
00078                              "sel_31v",
00079                              "sel_35v",
00080                              "sel_40v",
00081                              "sel_41v",
00082                              "sel_45v",
00083                              "sel_50v",
00084                              "sel_51v",
00085                              "sel_2",
00086                              "sel_3",
00087                              "sel_4",
00088                              "sel_5",
00089                              "sel_2dp",
00090                              "sel_2dm",
00091                              "sel_5dp",
00092                              "sel_5dm"};
00093 
00094 /*!
00095  *  pixMorphDwa_1()
00096  *
00097  *      Input:  pixd (usual 3 choices: null, == pixs, != pixs)
00098  *              pixs (1 bpp)
00099  *              operation  (L_MORPH_DILATE, L_MORPH_ERODE,
00100  *                          L_MORPH_OPEN, L_MORPH_CLOSE)
00101  *              sel name
00102  *      Return: pixd
00103  *
00104  *  Notes:
00105  *      (1) This simply adds a border, calls the appropriate
00106  *          pixFMorphopGen_*(), and removes the border.
00107  *          See the notes for that function.
00108  *      (2) The size of the border depends on the operation
00109  *          and the boundary conditions.
00110  */
00111 PIX *
00112 pixMorphDwa_1(PIX     *pixd,
00113               PIX     *pixs,
00114               l_int32  operation,
00115               char    *selname)
00116 {
00117 l_int32  bordercolor, bordersize;
00118 PIX     *pixt1, *pixt2, *pixt3;
00119 
00120     PROCNAME("pixMorphDwa_1");
00121 
00122     if (!pixs)
00123         return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
00124     if (pixGetDepth(pixs) != 1)
00125         return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);
00126 
00127         /* Set the border size */
00128     bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
00129     bordersize = 32;
00130     if (bordercolor == 0 && operation == L_MORPH_CLOSE)
00131         bordersize += 32;
00132 
00133     pixt1 = pixAddBorder(pixs, bordersize, 0);
00134     pixt2 = pixFMorphopGen_1(NULL, pixt1, operation, selname);
00135     pixt3 = pixRemoveBorder(pixt2, bordersize);
00136     pixDestroy(&pixt1);
00137     pixDestroy(&pixt2);
00138 
00139     if (!pixd)
00140         return pixt3;
00141 
00142     pixCopy(pixd, pixt3);
00143     pixDestroy(&pixt3);
00144     return pixd;
00145 }
00146 
00147 
00148 /*!
00149  *  pixFMorphopGen_1()
00150  *
00151  *      Input:  pixd (usual 3 choices: null, == pixs, != pixs)
00152  *              pixs (1 bpp)
00153  *              operation  (L_MORPH_DILATE, L_MORPH_ERODE,
00154  *                          L_MORPH_OPEN, L_MORPH_CLOSE)
00155  *              sel name
00156  *      Return: pixd
00157  *
00158  *  Notes:
00159  *      (1) This is a dwa operation, and the Sels must be limited in
00160  *          size to not more than 31 pixels about the origin.
00161  *      (2) A border of appropriate size (32 pixels, or 64 pixels
00162  *          for safe closing with asymmetric b.c.) must be added before
00163  *          this function is called.
00164  *      (3) This handles all required setting of the border pixels
00165  *          before erosion and dilation.
00166  *      (4) The closing operation is safe; no pixels can be removed
00167  *          near the boundary.
00168  */
00169 PIX *
00170 pixFMorphopGen_1(PIX     *pixd,
00171                  PIX     *pixs,
00172                  l_int32  operation,
00173                  char    *selname)
00174 {
00175 l_int32    i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop;
00176 l_uint32  *datad, *datas, *datat;
00177 PIX       *pixt;
00178 
00179     PROCNAME("pixFMorphopGen_1");
00180 
00181     if (!pixs)
00182         return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
00183     if (pixGetDepth(pixs) != 1)
00184         return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);
00185 
00186         /* Get boundary colors to use */
00187     bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
00188     if (bordercolor == 1)
00189         erodeop = PIX_SET;
00190     else
00191         erodeop = PIX_CLR;
00192 
00193     found = FALSE;
00194     for (i = 0; i < NUM_SELS_GENERATED; i++) {
00195         if (strcmp(selname, SEL_NAMES[i]) == 0) {
00196             found = TRUE;
00197             index = 2 * i;
00198             break;
00199         }
00200     }
00201     if (found == FALSE)
00202         return (PIX *)ERROR_PTR("sel index not found", procName, pixd);
00203 
00204     if (!pixd) {
00205         if ((pixd = pixCreateTemplate(pixs)) == NULL)
00206             return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00207     }
00208     else  /* for in-place or pre-allocated */
00209         pixResizeImageData(pixd, pixs);
00210     wpls = pixGetWpl(pixs);
00211     wpld = pixGetWpl(pixd);
00212 
00213         /* The images must be surrounded, in advance, with a border of
00214          * size 32 pixels (or 64, for closing), that we'll read from.
00215          * Fabricate a "proper" image as the subimage within the 32
00216          * pixel border, having the following parameters:  */
00217     w = pixGetWidth(pixs) - 64;
00218     h = pixGetHeight(pixs) - 64;
00219     datas = pixGetData(pixs) + 32 * wpls + 1;
00220     datad = pixGetData(pixd) + 32 * wpld + 1;
00221 
00222     if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) {
00223         borderop = PIX_CLR;
00224         if (operation == L_MORPH_ERODE) {
00225             borderop = erodeop;
00226             index++;
00227         }
00228         if (pixd == pixs) {  /* in-place; generate a temp image */
00229             if ((pixt = pixCopy(NULL, pixs)) == NULL)
00230                 return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
00231             datat = pixGetData(pixt) + 32 * wpls + 1;
00232             pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop);
00233             fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index);
00234             pixDestroy(&pixt);
00235         }
00236         else { /* not in-place */
00237             pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop);
00238             fmorphopgen_low_1(datad, w, h, wpld, datas, wpls, index);
00239         }
00240     }
00241     else {  /* opening or closing; generate a temp image */
00242         if ((pixt = pixCreateTemplate(pixs)) == NULL)
00243             return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
00244         datat = pixGetData(pixt) + 32 * wpls + 1;
00245         if (operation == L_MORPH_OPEN) {
00246             pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop);
00247             fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index+1);
00248             pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR);
00249             fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index);
00250         }
00251         else {  /* closing */
00252             pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR);
00253             fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index);
00254             pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop);
00255             fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index+1);
00256         }
00257         pixDestroy(&pixt);
00258     }
00259 
00260     return pixd;
00261 }
00262 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines