Coverage Report

Created: 2024-06-18 06:05

/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
}