/src/leptonica/src/binexpand.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 | | * \file binexpand.c |
29 | | * <pre> |
30 | | * |
31 | | * Replicated expansion (integer scaling) |
32 | | * PIX *pixExpandBinaryReplicate() |
33 | | * |
34 | | * Special case: power of 2 replicated expansion |
35 | | * PIX *pixExpandBinaryPower2() |
36 | | * |
37 | | * Expansion tables for power of 2 expansion |
38 | | * static l_uint16 *makeExpandTab2x() |
39 | | * static l_uint32 *makeExpandTab4x() |
40 | | * static l_uint32 *makeExpandTab8x() |
41 | | * </pre> |
42 | | */ |
43 | | |
44 | | #ifdef HAVE_CONFIG_H |
45 | | #include <config_auto.h> |
46 | | #endif /* HAVE_CONFIG_H */ |
47 | | |
48 | | #include <string.h> |
49 | | #include "allheaders.h" |
50 | | |
51 | | /* Static table functions and tables */ |
52 | | static l_uint16 * makeExpandTab2x(void); |
53 | | static l_uint32 * makeExpandTab4x(void); |
54 | | static l_uint32 * makeExpandTab8x(void); |
55 | | static l_uint32 expandtab16[] = { |
56 | | 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff}; |
57 | | |
58 | | /*------------------------------------------------------------------* |
59 | | * Replicated expansion (integer scaling) * |
60 | | *------------------------------------------------------------------*/ |
61 | | /*! |
62 | | * \brief pixExpandBinaryReplicate() |
63 | | * |
64 | | * \param[in] pixs 1 bpp |
65 | | * \param[in] xfact integer scale factor for horiz. replicative expansion |
66 | | * \param[in] yfact integer scale factor for vertical replicative expansion |
67 | | * \return pixd scaled up, or NULL on error |
68 | | */ |
69 | | PIX * |
70 | | pixExpandBinaryReplicate(PIX *pixs, |
71 | | l_int32 xfact, |
72 | | l_int32 yfact) |
73 | 0 | { |
74 | 0 | l_int32 w, h, d, wd, hd, wpls, wpld, i, j, k, start; |
75 | 0 | l_uint32 *datas, *datad, *lines, *lined; |
76 | 0 | PIX *pixd; |
77 | |
|
78 | 0 | if (!pixs) |
79 | 0 | return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL); |
80 | 0 | pixGetDimensions(pixs, &w, &h, &d); |
81 | 0 | if (d != 1) |
82 | 0 | return (PIX *)ERROR_PTR("pixs not binary", __func__, NULL); |
83 | 0 | if (xfact <= 0 || yfact <= 0) |
84 | 0 | return (PIX *)ERROR_PTR("invalid scale factor: <= 0", __func__, NULL); |
85 | | |
86 | 0 | if (xfact == yfact) { |
87 | 0 | if (xfact == 1) |
88 | 0 | return pixCopy(NULL, pixs); |
89 | 0 | if (xfact == 2 || xfact == 4 || xfact == 8 || xfact == 16) |
90 | 0 | return pixExpandBinaryPower2(pixs, xfact); |
91 | 0 | } |
92 | | |
93 | 0 | wpls = pixGetWpl(pixs); |
94 | 0 | datas = pixGetData(pixs); |
95 | 0 | wd = xfact * w; |
96 | 0 | hd = yfact * h; |
97 | 0 | if ((pixd = pixCreate(wd, hd, 1)) == NULL) |
98 | 0 | return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); |
99 | 0 | pixCopyResolution(pixd, pixs); |
100 | 0 | pixScaleResolution(pixd, (l_float32)xfact, (l_float32)yfact); |
101 | 0 | wpld = pixGetWpl(pixd); |
102 | 0 | datad = pixGetData(pixd); |
103 | |
|
104 | 0 | for (i = 0; i < h; i++) { |
105 | 0 | lines = datas + i * wpls; |
106 | 0 | lined = datad + yfact * i * wpld; |
107 | 0 | for (j = 0; j < w; j++) { /* replicate pixels on a single line */ |
108 | 0 | if (GET_DATA_BIT(lines, j)) { |
109 | 0 | start = xfact * j; |
110 | 0 | for (k = 0; k < xfact; k++) |
111 | 0 | SET_DATA_BIT(lined, start + k); |
112 | 0 | } |
113 | 0 | } |
114 | 0 | for (k = 1; k < yfact; k++) /* replicate the line */ |
115 | 0 | memcpy(lined + k * wpld, lined, 4 * wpld); |
116 | 0 | } |
117 | |
|
118 | 0 | return pixd; |
119 | 0 | } |
120 | | |
121 | | |
122 | | /*------------------------------------------------------------------* |
123 | | * Power of 2 expansion * |
124 | | *------------------------------------------------------------------*/ |
125 | | /*! |
126 | | * \brief pixExpandBinaryPower2() |
127 | | * |
128 | | * \param[in] pixs 1 bpp |
129 | | * \param[in] factor expansion factor: 1, 2, 4, 8, 16 |
130 | | * \return pixd expanded 1 bpp by replication, or NULL on error |
131 | | */ |
132 | | PIX * |
133 | | pixExpandBinaryPower2(PIX *pixs, |
134 | | l_int32 factor) |
135 | 0 | { |
136 | 0 | l_uint8 sval; |
137 | 0 | l_uint16 *tab2; |
138 | 0 | l_int32 i, j, k, w, h, d, wd, hd, wpls, wpld, sdibits, sqbits, sbytes; |
139 | 0 | l_uint32 *datas, *datad, *lines, *lined, *tab4, *tab8; |
140 | 0 | PIX *pixd; |
141 | |
|
142 | 0 | if (!pixs) |
143 | 0 | return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL); |
144 | 0 | pixGetDimensions(pixs, &w, &h, &d); |
145 | 0 | if (d != 1) |
146 | 0 | return (PIX *)ERROR_PTR("pixs not binary", __func__, NULL); |
147 | 0 | if (factor == 1) |
148 | 0 | return pixCopy(NULL, pixs); |
149 | 0 | if (factor != 2 && factor != 4 && factor != 8 && factor != 16) |
150 | 0 | return (PIX *)ERROR_PTR("factor must be in {2,4,8,16}", __func__, NULL); |
151 | | |
152 | 0 | wpls = pixGetWpl(pixs); |
153 | 0 | datas = pixGetData(pixs); |
154 | 0 | wd = factor * w; |
155 | 0 | hd = factor * h; |
156 | 0 | if ((pixd = pixCreate(wd, hd, 1)) == NULL) |
157 | 0 | return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); |
158 | 0 | pixCopyResolution(pixd, pixs); |
159 | 0 | pixScaleResolution(pixd, (l_float32)factor, (l_float32)factor); |
160 | 0 | wpld = pixGetWpl(pixd); |
161 | 0 | datad = pixGetData(pixd); |
162 | 0 | if (factor == 2) { |
163 | 0 | tab2 = makeExpandTab2x(); |
164 | 0 | sbytes = (w + 7) / 8; |
165 | 0 | for (i = 0; i < h; i++) { |
166 | 0 | lines = datas + i * wpls; |
167 | 0 | lined = datad + 2 * i * wpld; |
168 | 0 | for (j = 0; j < sbytes; j++) { |
169 | 0 | sval = GET_DATA_BYTE(lines, j); |
170 | 0 | SET_DATA_TWO_BYTES(lined, j, tab2[sval]); |
171 | 0 | } |
172 | 0 | memcpy(lined + wpld, lined, 4 * wpld); |
173 | 0 | } |
174 | 0 | LEPT_FREE(tab2); |
175 | 0 | } else if (factor == 4) { |
176 | 0 | tab4 = makeExpandTab4x(); |
177 | 0 | sbytes = (w + 7) / 8; |
178 | 0 | for (i = 0; i < h; i++) { |
179 | 0 | lines = datas + i * wpls; |
180 | 0 | lined = datad + 4 * i * wpld; |
181 | 0 | for (j = 0; j < sbytes; j++) { |
182 | 0 | sval = GET_DATA_BYTE(lines, j); |
183 | 0 | lined[j] = tab4[sval]; |
184 | 0 | } |
185 | 0 | for (k = 1; k < 4; k++) |
186 | 0 | memcpy(lined + k * wpld, lined, 4 * wpld); |
187 | 0 | } |
188 | 0 | LEPT_FREE(tab4); |
189 | 0 | } else if (factor == 8) { |
190 | 0 | tab8 = makeExpandTab8x(); |
191 | 0 | sqbits = (w + 3) / 4; |
192 | 0 | for (i = 0; i < h; i++) { |
193 | 0 | lines = datas + i * wpls; |
194 | 0 | lined = datad + 8 * i * wpld; |
195 | 0 | for (j = 0; j < sqbits; j++) { |
196 | 0 | sval = GET_DATA_QBIT(lines, j); |
197 | 0 | lined[j] = tab8[sval]; |
198 | 0 | } |
199 | 0 | for (k = 1; k < 8; k++) |
200 | 0 | memcpy(lined + k * wpld, lined, 4 * wpld); |
201 | 0 | } |
202 | 0 | LEPT_FREE(tab8); |
203 | 0 | } else { /* factor == 16 */ |
204 | 0 | sdibits = (w + 1) / 2; |
205 | 0 | for (i = 0; i < h; i++) { |
206 | 0 | lines = datas + i * wpls; |
207 | 0 | lined = datad + 16 * i * wpld; |
208 | 0 | for (j = 0; j < sdibits; j++) { |
209 | 0 | sval = GET_DATA_DIBIT(lines, j); |
210 | 0 | lined[j] = expandtab16[sval]; |
211 | 0 | } |
212 | 0 | for (k = 1; k < 16; k++) |
213 | 0 | memcpy(lined + k * wpld, lined, 4 * wpld); |
214 | 0 | } |
215 | 0 | } |
216 | |
|
217 | 0 | return pixd; |
218 | 0 | } |
219 | | |
220 | | |
221 | | /*-------------------------------------------------------------------* |
222 | | * Expansion tables for 2x, 4x and 8x expansion * |
223 | | *-------------------------------------------------------------------*/ |
224 | | static l_uint16 * |
225 | | makeExpandTab2x(void) |
226 | 0 | { |
227 | 0 | l_uint16 *tab; |
228 | 0 | l_int32 i; |
229 | |
|
230 | 0 | tab = (l_uint16 *) LEPT_CALLOC(256, sizeof(l_uint16)); |
231 | 0 | for (i = 0; i < 256; i++) { |
232 | 0 | if (i & 0x01) |
233 | 0 | tab[i] = 0x3; |
234 | 0 | if (i & 0x02) |
235 | 0 | tab[i] |= 0xc; |
236 | 0 | if (i & 0x04) |
237 | 0 | tab[i] |= 0x30; |
238 | 0 | if (i & 0x08) |
239 | 0 | tab[i] |= 0xc0; |
240 | 0 | if (i & 0x10) |
241 | 0 | tab[i] |= 0x300; |
242 | 0 | if (i & 0x20) |
243 | 0 | tab[i] |= 0xc00; |
244 | 0 | if (i & 0x40) |
245 | 0 | tab[i] |= 0x3000; |
246 | 0 | if (i & 0x80) |
247 | 0 | tab[i] |= 0xc000; |
248 | 0 | } |
249 | 0 | return tab; |
250 | 0 | } |
251 | | |
252 | | |
253 | | static l_uint32 * |
254 | | makeExpandTab4x(void) |
255 | 0 | { |
256 | 0 | l_uint32 *tab; |
257 | 0 | l_int32 i; |
258 | |
|
259 | 0 | tab = (l_uint32 *) LEPT_CALLOC(256, sizeof(l_uint32)); |
260 | 0 | for (i = 0; i < 256; i++) { |
261 | 0 | if (i & 0x01) |
262 | 0 | tab[i] = 0xf; |
263 | 0 | if (i & 0x02) |
264 | 0 | tab[i] |= 0xf0; |
265 | 0 | if (i & 0x04) |
266 | 0 | tab[i] |= 0xf00; |
267 | 0 | if (i & 0x08) |
268 | 0 | tab[i] |= 0xf000; |
269 | 0 | if (i & 0x10) |
270 | 0 | tab[i] |= 0xf0000; |
271 | 0 | if (i & 0x20) |
272 | 0 | tab[i] |= 0xf00000; |
273 | 0 | if (i & 0x40) |
274 | 0 | tab[i] |= 0xf000000; |
275 | 0 | if (i & 0x80) |
276 | 0 | tab[i] |= 0xf0000000; |
277 | 0 | } |
278 | 0 | return tab; |
279 | 0 | } |
280 | | |
281 | | |
282 | | static l_uint32 * |
283 | | makeExpandTab8x(void) |
284 | 0 | { |
285 | 0 | l_uint32 *tab; |
286 | 0 | l_int32 i; |
287 | |
|
288 | 0 | tab = (l_uint32 *) LEPT_CALLOC(16, sizeof(l_uint32)); |
289 | 0 | for (i = 0; i < 16; i++) { |
290 | 0 | if (i & 0x01) |
291 | 0 | tab[i] = 0xff; |
292 | 0 | if (i & 0x02) |
293 | 0 | tab[i] |= 0xff00; |
294 | 0 | if (i & 0x04) |
295 | 0 | tab[i] |= 0xff0000; |
296 | 0 | if (i & 0x08) |
297 | 0 | tab[i] |= 0xff000000; |
298 | 0 | } |
299 | 0 | return tab; |
300 | 0 | } |