comparison mupdf-source/thirdparty/leptonica/src/fmorphgen.1.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
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 {
130 l_int32 bordercolor, bordersize;
131 PIX *pixt1, *pixt2, *pixt3;
132
133 if (!pixs)
134 return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
135 if (pixGetDepth(pixs) != 1)
136 return (PIX *)ERROR_PTR("pixs must be 1 bpp", __func__, pixd);
137
138 /* Set the border size */
139 bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
140 bordersize = 32;
141 if (bordercolor == 0 && operation == L_MORPH_CLOSE)
142 bordersize += 32;
143
144 pixt1 = pixAddBorder(pixs, bordersize, 0);
145 pixt2 = pixFMorphopGen_1(NULL, pixt1, operation, selname);
146 pixt3 = pixRemoveBorder(pixt2, bordersize);
147 pixDestroy(&pixt1);
148 pixDestroy(&pixt2);
149
150 if (!pixd)
151 return pixt3;
152
153 pixCopy(pixd, pixt3);
154 pixDestroy(&pixt3);
155 return pixd;
156 }
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 {
188 l_int32 i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop;
189 l_uint32 *datad, *datas, *datat;
190 PIX *pixt;
191
192 if (!pixs)
193 return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
194 if (pixGetDepth(pixs) != 1)
195 return (PIX *)ERROR_PTR("pixs must be 1 bpp", __func__, pixd);
196
197 /* Get boundary colors to use */
198 bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
199 if (bordercolor == 1)
200 erodeop = PIX_SET;
201 else
202 erodeop = PIX_CLR;
203
204 found = FALSE;
205 for (i = 0; i < NUM_SELS_GENERATED; i++) {
206 if (strcmp(selname, SEL_NAMES[i]) == 0) {
207 found = TRUE;
208 index = 2 * i;
209 break;
210 }
211 }
212 if (found == FALSE)
213 return (PIX *)ERROR_PTR("sel index not found", __func__, pixd);
214
215 if (!pixd) {
216 if ((pixd = pixCreateTemplate(pixs)) == NULL)
217 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
218 }
219 else /* for in-place or pre-allocated */
220 pixResizeImageData(pixd, pixs);
221 wpls = pixGetWpl(pixs);
222 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 w = pixGetWidth(pixs) - 64;
229 h = pixGetHeight(pixs) - 64;
230 datas = pixGetData(pixs) + 32 * wpls + 1;
231 datad = pixGetData(pixd) + 32 * wpld + 1;
232
233 if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) {
234 borderop = PIX_CLR;
235 if (operation == L_MORPH_ERODE) {
236 borderop = erodeop;
237 index++;
238 }
239 if (pixd == pixs) { /* in-place; generate a temp image */
240 if ((pixt = pixCopy(NULL, pixs)) == NULL)
241 return (PIX *)ERROR_PTR("pixt not made", __func__, pixd);
242 datat = pixGetData(pixt) + 32 * wpls + 1;
243 pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop);
244 fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index);
245 pixDestroy(&pixt);
246 }
247 else { /* not in-place */
248 pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop);
249 fmorphopgen_low_1(datad, w, h, wpld, datas, wpls, index);
250 }
251 }
252 else { /* opening or closing; generate a temp image */
253 if ((pixt = pixCreateTemplate(pixs)) == NULL)
254 return (PIX *)ERROR_PTR("pixt not made", __func__, pixd);
255 datat = pixGetData(pixt) + 32 * wpls + 1;
256 if (operation == L_MORPH_OPEN) {
257 pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop);
258 fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index+1);
259 pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR);
260 fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index);
261 }
262 else { /* closing */
263 pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR);
264 fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index);
265 pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop);
266 fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index+1);
267 }
268 pixDestroy(&pixt);
269 }
270
271 return pixd;
272 }
273