twain3.0/3rdparty/hgOCR/leptonica/binexpand.c

304 lines
9.6 KiB
C

/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*!
* \file binexpand.c
* <pre>
*
* Replicated expansion (integer scaling)
* PIX *pixExpandBinaryReplicate()
*
* Special case: power of 2 replicated expansion
* PIX *pixExpandBinaryPower2()
*
* Expansion tables for power of 2 expansion
* static l_uint16 *makeExpandTab2x()
* static l_uint32 *makeExpandTab4x()
* static l_uint32 *makeExpandTab8x()
* </pre>
*/
#include <string.h>
#include "allheaders.h"
/* Static table functions and tables */
static l_uint16 * makeExpandTab2x(void);
static l_uint32 * makeExpandTab4x(void);
static l_uint32 * makeExpandTab8x(void);
static l_uint32 expandtab16[] = {
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff};
/*------------------------------------------------------------------*
* Replicated expansion (integer scaling) *
*------------------------------------------------------------------*/
/*!
* \brief pixExpandBinaryReplicate()
*
* \param[in] pixs 1 bpp
* \param[in] xfact integer scale factor for horiz. replicative expansion
* \param[in] yfact integer scale factor for vertical replicative expansion
* \return pixd scaled up, or NULL on error
*/
PIX *
pixExpandBinaryReplicate(PIX *pixs,
l_int32 xfact,
l_int32 yfact)
{
l_int32 w, h, d, wd, hd, wpls, wpld, i, j, k, start;
l_uint32 *datas, *datad, *lines, *lined;
PIX *pixd;
PROCNAME("pixExpandBinaryReplicate");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
pixGetDimensions(pixs, &w, &h, &d);
if (d != 1)
return (PIX *)ERROR_PTR("pixs not binary", procName, NULL);
if (xfact <= 0 || yfact <= 0)
return (PIX *)ERROR_PTR("invalid scale factor: <= 0", procName, NULL);
if (xfact == yfact) {
if (xfact == 1)
return pixCopy(NULL, pixs);
if (xfact == 2 || xfact == 4 || xfact == 8 || xfact == 16)
return pixExpandBinaryPower2(pixs, xfact);
}
wpls = pixGetWpl(pixs);
datas = pixGetData(pixs);
wd = xfact * w;
hd = yfact * h;
if ((pixd = pixCreate(wd, hd, 1)) == NULL)
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
pixCopyResolution(pixd, pixs);
pixScaleResolution(pixd, (l_float32)xfact, (l_float32)yfact);
wpld = pixGetWpl(pixd);
datad = pixGetData(pixd);
for (i = 0; i < h; i++) {
lines = datas + i * wpls;
lined = datad + yfact * i * wpld;
for (j = 0; j < w; j++) { /* replicate pixels on a single line */
if (GET_DATA_BIT(lines, j)) {
start = xfact * j;
for (k = 0; k < xfact; k++)
SET_DATA_BIT(lined, start + k);
}
}
for (k = 1; k < yfact; k++) /* replicate the line */
memcpy(lined + k * wpld, lined, 4 * wpld);
}
return pixd;
}
/*------------------------------------------------------------------*
* Power of 2 expansion *
*------------------------------------------------------------------*/
/*!
* \brief pixExpandBinaryPower2()
*
* \param[in] pixs 1 bpp
* \param[in] factor expansion factor: 1, 2, 4, 8, 16
* \return pixd expanded 1 bpp by replication, or NULL on error
*/
PIX *
pixExpandBinaryPower2(PIX *pixs,
l_int32 factor)
{
l_uint8 sval;
l_uint16 *tab2;
l_int32 i, j, k, w, h, d, wd, hd, wpls, wpld, sdibits, sqbits, sbytes;
l_uint32 *datas, *datad, *lines, *lined, *tab4, *tab8;
PIX *pixd;
PROCNAME("pixExpandBinaryPower2");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
pixGetDimensions(pixs, &w, &h, &d);
if (d != 1)
return (PIX *)ERROR_PTR("pixs not binary", procName, NULL);
if (factor == 1)
return pixCopy(NULL, pixs);
if (factor != 2 && factor != 4 && factor != 8 && factor != 16)
return (PIX *)ERROR_PTR("factor must be in {2,4,8,16}", procName, NULL);
wpls = pixGetWpl(pixs);
datas = pixGetData(pixs);
wd = factor * w;
hd = factor * h;
if ((pixd = pixCreate(wd, hd, 1)) == NULL)
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
pixCopyResolution(pixd, pixs);
pixScaleResolution(pixd, (l_float32)factor, (l_float32)factor);
wpld = pixGetWpl(pixd);
datad = pixGetData(pixd);
if (factor == 2) {
tab2 = makeExpandTab2x();
sbytes = (w + 7) / 8;
for (i = 0; i < h; i++) {
lines = datas + i * wpls;
lined = datad + 2 * i * wpld;
for (j = 0; j < sbytes; j++) {
sval = GET_DATA_BYTE(lines, j);
SET_DATA_TWO_BYTES(lined, j, tab2[sval]);
}
memcpy(lined + wpld, lined, 4 * wpld);
}
LEPT_FREE(tab2);
} else if (factor == 4) {
tab4 = makeExpandTab4x();
sbytes = (w + 7) / 8;
for (i = 0; i < h; i++) {
lines = datas + i * wpls;
lined = datad + 4 * i * wpld;
for (j = 0; j < sbytes; j++) {
sval = GET_DATA_BYTE(lines, j);
lined[j] = tab4[sval];
}
for (k = 1; k < 4; k++)
memcpy(lined + k * wpld, lined, 4 * wpld);
}
LEPT_FREE(tab4);
} else if (factor == 8) {
tab8 = makeExpandTab8x();
sqbits = (w + 3) / 4;
for (i = 0; i < h; i++) {
lines = datas + i * wpls;
lined = datad + 8 * i * wpld;
for (j = 0; j < sqbits; j++) {
sval = GET_DATA_QBIT(lines, j);
if (sval > 15)
L_WARNING("sval = %d; should be < 16\n", procName, sval);
lined[j] = tab8[sval];
}
for (k = 1; k < 8; k++)
memcpy(lined + k * wpld, lined, 4 * wpld);
}
LEPT_FREE(tab8);
} else { /* factor == 16 */
sdibits = (w + 1) / 2;
for (i = 0; i < h; i++) {
lines = datas + i * wpls;
lined = datad + 16 * i * wpld;
for (j = 0; j < sdibits; j++) {
sval = GET_DATA_DIBIT(lines, j);
lined[j] = expandtab16[sval];
}
for (k = 1; k < 16; k++)
memcpy(lined + k * wpld, lined, 4 * wpld);
}
}
return pixd;
}
/*-------------------------------------------------------------------*
* Expansion tables for 2x, 4x and 8x expansion *
*-------------------------------------------------------------------*/
static l_uint16 *
makeExpandTab2x(void)
{
l_uint16 *tab;
l_int32 i;
tab = (l_uint16 *) LEPT_CALLOC(256, sizeof(l_uint16));
for (i = 0; i < 256; i++) {
if (i & 0x01)
tab[i] = 0x3;
if (i & 0x02)
tab[i] |= 0xc;
if (i & 0x04)
tab[i] |= 0x30;
if (i & 0x08)
tab[i] |= 0xc0;
if (i & 0x10)
tab[i] |= 0x300;
if (i & 0x20)
tab[i] |= 0xc00;
if (i & 0x40)
tab[i] |= 0x3000;
if (i & 0x80)
tab[i] |= 0xc000;
}
return tab;
}
static l_uint32 *
makeExpandTab4x(void)
{
l_uint32 *tab;
l_int32 i;
tab = (l_uint32 *) LEPT_CALLOC(256, sizeof(l_uint32));
for (i = 0; i < 256; i++) {
if (i & 0x01)
tab[i] = 0xf;
if (i & 0x02)
tab[i] |= 0xf0;
if (i & 0x04)
tab[i] |= 0xf00;
if (i & 0x08)
tab[i] |= 0xf000;
if (i & 0x10)
tab[i] |= 0xf0000;
if (i & 0x20)
tab[i] |= 0xf00000;
if (i & 0x40)
tab[i] |= 0xf000000;
if (i & 0x80)
tab[i] |= 0xf0000000;
}
return tab;
}
static l_uint32 *
makeExpandTab8x(void)
{
l_uint32 *tab;
l_int32 i;
tab = (l_uint32 *) LEPT_CALLOC(16, sizeof(l_uint32));
for (i = 0; i < 16; i++) {
if (i & 0x01)
tab[i] = 0xff;
if (i & 0x02)
tab[i] |= 0xff00;
if (i & 0x04)
tab[i] |= 0xff0000;
if (i & 0x08)
tab[i] |= 0xff000000;
}
return tab;
}