Coverage Report

Created: 2024-07-27 06:27

/src/leptonica/src/fmorphgen.1.c
Line
Count
Source (jump to first uncovered line)
1
/*====================================================================*
2
 -  Copyright (C) 2001 Leptonica.  All rights reserved.
3
 -
4
 -  Redistribution and use in source and binary forms, with or without
5
 -  modification, are permitted provided that the following conditions
6
 -  are met:
7
 -  1. Redistributions of source code must retain the above copyright
8
 -     notice, this list of conditions and the following disclaimer.
9
 -  2. Redistributions in binary form must reproduce the above
10
 -     copyright notice, this list of conditions and the following
11
 -     disclaimer in the documentation and/or other materials
12
 -     provided with the distribution.
13
 -
14
 -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15
 -  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16
 -  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17
 -  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ANY
18
 -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19
 -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20
 -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21
 -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22
 -  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23
 -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
 -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 *====================================================================*/
26
27
/*!
28
 *      Top-level fast binary morphology with auto-generated sels
29
 *
30
 *             PIX     *pixMorphDwa_1()
31
 *             PIX     *pixFMorphopGen_1()
32
 */
33
34
#include <string.h>
35
#include "allheaders.h"
36
37
PIX *pixMorphDwa_1(PIX *pixd, PIX *pixs, l_int32 operation, char *selname);
38
PIX *pixFMorphopGen_1(PIX *pixd, PIX *pixs, l_int32 operation, char *selname);
39
l_int32 fmorphopgen_low_1(l_uint32 *datad, l_int32 w,
40
                          l_int32 h, l_int32 wpld,
41
                          l_uint32 *datas, l_int32 wpls,
42
                          l_int32 index);
43
44
static l_int32   NUM_SELS_GENERATED = 58;
45
static char  SEL_NAMES[][80] = {
46
                             "sel_2h",
47
                             "sel_3h",
48
                             "sel_4h",
49
                             "sel_5h",
50
                             "sel_6h",
51
                             "sel_7h",
52
                             "sel_8h",
53
                             "sel_9h",
54
                             "sel_10h",
55
                             "sel_11h",
56
                             "sel_12h",
57
                             "sel_13h",
58
                             "sel_14h",
59
                             "sel_15h",
60
                             "sel_20h",
61
                             "sel_21h",
62
                             "sel_25h",
63
                             "sel_30h",
64
                             "sel_31h",
65
                             "sel_35h",
66
                             "sel_40h",
67
                             "sel_41h",
68
                             "sel_45h",
69
                             "sel_50h",
70
                             "sel_51h",
71
                             "sel_2v",
72
                             "sel_3v",
73
                             "sel_4v",
74
                             "sel_5v",
75
                             "sel_6v",
76
                             "sel_7v",
77
                             "sel_8v",
78
                             "sel_9v",
79
                             "sel_10v",
80
                             "sel_11v",
81
                             "sel_12v",
82
                             "sel_13v",
83
                             "sel_14v",
84
                             "sel_15v",
85
                             "sel_20v",
86
                             "sel_21v",
87
                             "sel_25v",
88
                             "sel_30v",
89
                             "sel_31v",
90
                             "sel_35v",
91
                             "sel_40v",
92
                             "sel_41v",
93
                             "sel_45v",
94
                             "sel_50v",
95
                             "sel_51v",
96
                             "sel_2",
97
                             "sel_3",
98
                             "sel_4",
99
                             "sel_5",
100
                             "sel_2dp",
101
                             "sel_2dm",
102
                             "sel_5dp",
103
                             "sel_5dm"};
104
105
/*!
106
 * \brief   pixMorphDwa_1()
107
 *
108
 * \param[in]    pixd         usual 3 choices: null, == pixs, != pixs
109
 * \param[in]    pixs         1 bpp
110
 * \param[in]    operation    L_MORPH_DILATE, L_MORPH_ERODE,
111
 *                            L_MORPH_OPEN, L_MORPH_CLOSE
112
 * \param[in]    sel          name
113
 * \return    pixd
114
 *
115
 * <pre>
116
 * Notes:
117
 *      (1) This simply adds a border, calls the appropriate
118
 *          pixFMorphopGen_*(), and removes the border.
119
 *          See the notes for that function.
120
 *      (2) The size of the border depends on the operation
121
 *          and the boundary conditions.
122
 * </pre>
123
 */
124
PIX *
125
pixMorphDwa_1(PIX     *pixd,
126
              PIX     *pixs,
127
              l_int32  operation,
128
              char    *selname)
129
0
{
130
0
l_int32  bordercolor, bordersize;
131
0
PIX     *pixt1, *pixt2, *pixt3;
132
133
0
    if (!pixs)
134
0
        return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
135
0
    if (pixGetDepth(pixs) != 1)
136
0
        return (PIX *)ERROR_PTR("pixs must be 1 bpp", __func__, pixd);
137
138
        /* Set the border size */
139
0
    bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
140
0
    bordersize = 32;
141
0
    if (bordercolor == 0 && operation == L_MORPH_CLOSE)
142
0
        bordersize += 32;
143
144
0
    pixt1 = pixAddBorder(pixs, bordersize, 0);
145
0
    pixt2 = pixFMorphopGen_1(NULL, pixt1, operation, selname);
146
0
    pixt3 = pixRemoveBorder(pixt2, bordersize);
147
0
    pixDestroy(&pixt1);
148
0
    pixDestroy(&pixt2);
149
150
0
    if (!pixd)
151
0
        return pixt3;
152
153
0
    pixCopy(pixd, pixt3);
154
0
    pixDestroy(&pixt3);
155
0
    return pixd;
156
0
}
157
158
159
/*!
160
 * \brief   pixFMorphopGen_1()
161
 *
162
 * \param[in]    pixd        usual 3 choices: null, == pixs, != pixs
163
 * \param[in]    pixs        1 bpp
164
 * \param[in]    operation   L_MORPH_DILATE, L_MORPH_ERODE,
165
 *                           L_MORPH_OPEN, L_MORPH_CLOSE
166
 * \param[in]    sel name
167
 * \return     pixd
168
 *
169
 * <pre>
170
 * Notes:
171
 *      (1) This is a dwa operation, and the Sels must be limited in
172
 *          size to not more than 31 pixels about the origin.
173
 *      (2) A border of appropriate size (32 pixels, or 64 pixels
174
 *          for safe closing with asymmetric b.c.) must be added before
175
 *          this function is called.
176
 *      (3) This handles all required setting of the border pixels
177
 *          before erosion and dilation.
178
 *      (4) The closing operation is safe; no pixels can be removed
179
 *          near the boundary.
180
 * </pre>
181
 */
182
PIX *
183
pixFMorphopGen_1(PIX     *pixd,
184
                 PIX     *pixs,
185
                 l_int32  operation,
186
                 char    *selname)
187
0
{
188
0
l_int32    i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop;
189
0
l_uint32  *datad, *datas, *datat;
190
0
PIX       *pixt;
191
192
0
    if (!pixs)
193
0
        return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
194
0
    if (pixGetDepth(pixs) != 1)
195
0
        return (PIX *)ERROR_PTR("pixs must be 1 bpp", __func__, pixd);
196
197
        /* Get boundary colors to use */
198
0
    bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
199
0
    if (bordercolor == 1)
200
0
        erodeop = PIX_SET;
201
0
    else
202
0
        erodeop = PIX_CLR;
203
204
0
    found = FALSE;
205
0
    for (i = 0; i < NUM_SELS_GENERATED; i++) {
206
0
        if (strcmp(selname, SEL_NAMES[i]) == 0) {
207
0
            found = TRUE;
208
0
            index = 2 * i;
209
0
            break;
210
0
        }
211
0
    }
212
0
    if (found == FALSE)
213
0
        return (PIX *)ERROR_PTR("sel index not found", __func__, pixd);
214
215
0
    if (!pixd) {
216
0
        if ((pixd = pixCreateTemplate(pixs)) == NULL)
217
0
            return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
218
0
    }
219
0
    else  /* for in-place or pre-allocated */
220
0
        pixResizeImageData(pixd, pixs);
221
0
    wpls = pixGetWpl(pixs);
222
0
    wpld = pixGetWpl(pixd);
223
224
        /* The images must be surrounded, in advance, with a border of
225
         * size 32 pixels (or 64, for closing), that we'll read from.
226
         * Fabricate a "proper" image as the subimage within the 32
227
         * pixel border, having the following parameters:  */
228
0
    w = pixGetWidth(pixs) - 64;
229
0
    h = pixGetHeight(pixs) - 64;
230
0
    datas = pixGetData(pixs) + 32 * wpls + 1;
231
0
    datad = pixGetData(pixd) + 32 * wpld + 1;
232
233
0
    if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) {
234
0
        borderop = PIX_CLR;
235
0
        if (operation == L_MORPH_ERODE) {
236
0
            borderop = erodeop;
237
0
            index++;
238
0
        }
239
0
        if (pixd == pixs) {  /* in-place; generate a temp image */
240
0
            if ((pixt = pixCopy(NULL, pixs)) == NULL)
241
0
                return (PIX *)ERROR_PTR("pixt not made", __func__, pixd);
242
0
            datat = pixGetData(pixt) + 32 * wpls + 1;
243
0
            pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop);
244
0
            fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index);
245
0
            pixDestroy(&pixt);
246
0
        }
247
0
        else { /* not in-place */
248
0
            pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop);
249
0
            fmorphopgen_low_1(datad, w, h, wpld, datas, wpls, index);
250
0
        }
251
0
    }
252
0
    else {  /* opening or closing; generate a temp image */
253
0
        if ((pixt = pixCreateTemplate(pixs)) == NULL)
254
0
            return (PIX *)ERROR_PTR("pixt not made", __func__, pixd);
255
0
        datat = pixGetData(pixt) + 32 * wpls + 1;
256
0
        if (operation == L_MORPH_OPEN) {
257
0
            pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop);
258
0
            fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index+1);
259
0
            pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR);
260
0
            fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index);
261
0
        }
262
0
        else {  /* closing */
263
0
            pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR);
264
0
            fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index);
265
0
            pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop);
266
0
            fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index+1);
267
0
        }
268
0
        pixDestroy(&pixt);
269
0
    }
270
271
0
    return pixd;
272
0
}
273