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  * \brief       Top-level fast hit-miss transform with auto-generated sels
29  *
30  *             PIX     *pixHMTDwa_1()
31  *             PIX     *pixFHMTGen_1()
32  */
33 
34 #include <string.h>
35 #include "allheaders.h"
36 
37 PIX *pixHMTDwa_1(PIX *pixd, PIX *pixs, const char *selname);
38 PIX *pixFHMTGen_1(PIX *pixd, PIX *pixs, const char *selname);
39 l_int32 fhmtgen_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 = 10;
45 static char  SEL_NAMES[][80] = {
46                              "sel_3hm",
47                              "sel_3de",
48                              "sel_3ue",
49                              "sel_3re",
50                              "sel_3le",
51                              "sel_sl1",
52                              "sel_ulc",
53                              "sel_urc",
54                              "sel_llc",
55                              "sel_lrc"};
56 
57 /*!
58  * \brief   pixHMTDwa_1()
59  *
60  * \param[in]    pixd usual 3 choices: null, == pixs, != pixs
61  * \param[in]    pixs 1 bpp
62  * \param[in]    sel name
63  * \return  pixd
64  *
65  * <pre>
66  * Notes:
67  *      (1) This simply adds a 32 pixel border, calls the appropriate
68  *          pixFHMTGen_*(), and removes the border.
69  *          See notes below for that function.
70  * </pre>
71  */
72 PIX *
pixHMTDwa_1(PIX * pixd,PIX * pixs,const char * selname)73 pixHMTDwa_1(PIX         *pixd,
74             PIX         *pixs,
75             const char  *selname)
76 {
77 PIX  *pixt1, *pixt2, *pixt3;
78 
79     PROCNAME("pixHMTDwa_1");
80 
81     if (!pixs)
82         return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
83     if (pixGetDepth(pixs) != 1)
84         return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);
85 
86     pixt1 = pixAddBorder(pixs, 32, 0);
87     pixt2 = pixFHMTGen_1(NULL, pixt1, selname);
88     pixt3 = pixRemoveBorder(pixt2, 32);
89     pixDestroy(&pixt1);
90     pixDestroy(&pixt2);
91 
92     if (!pixd)
93         return pixt3;
94 
95     pixCopy(pixd, pixt3);
96     pixDestroy(&pixt3);
97     return pixd;
98 }
99 
100 
101 /*!
102  * \brief   pixFHMTGen_1()
103  *
104  * \param[in]    pixd usual 3 choices: null, == pixs, != pixs
105  * \param[in]    pixs 1 bpp
106  * \param[in]    sel name
107  * \return  pixd
108  *
109  * <pre>
110  * Notes:
111  *      (1) This is a dwa implementation of the hit-miss transform
112  *          on pixs by the sel.
113  *      (2) The sel must be limited in size to not more than 31 pixels
114  *          about the origin.  It must have at least one hit, and it
115  *          can have any number of misses.
116  *      (3) This handles all required setting of the border pixels
117  *          before erosion and dilation.
118  * </pre>
119  */
120 PIX *
pixFHMTGen_1(PIX * pixd,PIX * pixs,const char * selname)121 pixFHMTGen_1(PIX         *pixd,
122              PIX         *pixs,
123              const char  *selname)
124 {
125 l_int32    i, index, found, w, h, wpls, wpld;
126 l_uint32  *datad, *datas, *datat;
127 PIX       *pixt;
128 
129     PROCNAME("pixFHMTGen_1");
130 
131     if (!pixs)
132         return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
133     if (pixGetDepth(pixs) != 1)
134         return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);
135 
136     found = FALSE;
137     for (i = 0; i < NUM_SELS_GENERATED; i++) {
138         if (strcmp(selname, SEL_NAMES[i]) == 0) {
139             found = TRUE;
140             index = i;
141             break;
142         }
143     }
144     if (found == FALSE)
145         return (PIX *)ERROR_PTR("sel index not found", procName, pixd);
146 
147     if (!pixd) {
148         if ((pixd = pixCreateTemplate(pixs)) == NULL)
149             return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
150     }
151     else  /* for in-place or pre-allocated */
152         pixResizeImageData(pixd, pixs);
153     wpls = pixGetWpl(pixs);
154     wpld = pixGetWpl(pixd);
155 
156         /*  The images must be surrounded with 32 additional border
157          *  pixels, that we'll read from.  We fabricate a "proper"
158          *  image as the subimage within the border, having the
159          *  following parameters:  */
160     w = pixGetWidth(pixs) - 64;
161     h = pixGetHeight(pixs) - 64;
162     datas = pixGetData(pixs) + 32 * wpls + 1;
163     datad = pixGetData(pixd) + 32 * wpld + 1;
164 
165     if (pixd == pixs) {  /* need temp image if in-place */
166         if ((pixt = pixCopy(NULL, pixs)) == NULL)
167             return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
168         datat = pixGetData(pixt) + 32 * wpls + 1;
169         fhmtgen_low_1(datad, w, h, wpld, datat, wpls, index);
170         pixDestroy(&pixt);
171     }
172     else {  /* not in-place */
173         fhmtgen_low_1(datad, w, h, wpld, datas, wpls, index);
174     }
175 
176     return pixd;
177 }
178