blob: 3740d74d415a58e862247276578eb4a13db8f7d9 [file] [log] [blame]
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
- This software is distributed in the hope that it will be
- useful, but with NO WARRANTY OF ANY KIND.
- No author or distributor accepts responsibility to anyone for the
- consequences of using this software, or for whether it serves any
- particular purpose or works at all, unless he or she says so in
- writing. Everyone is granted permission to copy, modify and
- redistribute this source code, for commercial or non-commercial
- purposes, with the following restrictions: (1) the origin of this
- source code must not be misrepresented; (2) modified versions must
- be plainly marked as such; and (3) this notice may not be removed
- or altered from any source or modified source distribution.
*====================================================================*/
/*
* binreduce.c
*
* Subsampled reduction
*
* PIX *pixReduceBinary2()
*
* Rank filtered reductions
*
* PIX *pixReduceRankBinaryCascade()
* PIX *pixReduceRankBinary2()
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "allheaders.h"
/*------------------------------------------------------------------*
* Subsampled reduction *
*------------------------------------------------------------------*/
/*!
* pixReduceBinary2()
*
* Input: pixs
* tab (<optional>; if null, a table is made here
* and destroyed before exit)
* Return: pixd (2x subsampled), or null on error
*/
PIX *
pixReduceBinary2(PIX *pixs,
l_uint8 *intab)
{
l_uint8 *tab;
l_int32 ws, hs, wpls, wpld;
l_uint32 *datas, *datad;
PIX *pixd;
PROCNAME("pixReduceBinary2");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
if (pixGetDepth(pixs) != 1)
return (PIX *)ERROR_PTR("pixs not binary", procName, NULL);
if (intab) /* use input table */
tab = intab;
else {
if ((tab = makeSubsampleTab2x()) == NULL)
return (PIX *)ERROR_PTR("tab not made", procName, NULL);
}
ws = pixGetWidth(pixs);
hs = pixGetHeight(pixs);
if (hs <= 1)
return (PIX *)ERROR_PTR("hs must be at least 2", procName, NULL);
wpls = pixGetWpl(pixs);
datas = pixGetData(pixs);
if ((pixd = pixCreate(ws / 2, hs / 2, 1)) == NULL)
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
pixCopyResolution(pixd, pixs);
pixScaleResolution(pixd, 0.5, 0.5);
wpld = pixGetWpl(pixd);
datad = pixGetData(pixd);
reduceBinary2Low(datad, wpld, datas, hs, wpls, tab);
if (intab == NULL)
FREE(tab);
return pixd;
}
/*------------------------------------------------------------------*
* Rank filtered binary reductions *
*------------------------------------------------------------------*/
/*!
* pixReduceRankBinaryCascade()
*
* Input: pixs (1 bpp)
* level1, ... level 4 (thresholds, in the set {0, 1, 2, 3, 4})
* Return: pixd, or null on error
*
* Notes:
* (1) This performs up to four cascaded 2x rank reductions.
* (2) Use level = 0 to truncate the cascade.
*/
PIX *
pixReduceRankBinaryCascade(PIX *pixs,
l_int32 level1,
l_int32 level2,
l_int32 level3,
l_int32 level4)
{
PIX *pix1, *pix2, *pix3, *pix4;
l_uint8 *tab;
PROCNAME("pixReduceRankBinaryCascade");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
if (pixGetDepth(pixs) != 1)
return (PIX *)ERROR_PTR("pixs must be binary", procName, NULL);
if (level1 > 4 || level2 > 4 || level3 > 4 || level4 > 4)
return (PIX *)ERROR_PTR("levels must not exceed 4", procName, NULL);
if (level1 <= 0) {
L_WARNING("no reduction because level1 not > 0", procName);
return pixCopy(NULL, pixs);
}
if ((tab = makeSubsampleTab2x()) == NULL)
return (PIX *)ERROR_PTR("tab not made", procName, NULL);
pix1 = pixReduceRankBinary2(pixs, level1, tab);
if (level2 <= 0) {
FREE(tab);
return pix1;
}
pix2 = pixReduceRankBinary2(pix1, level2, tab);
pixDestroy(&pix1);
if (level3 <= 0) {
FREE(tab);
return pix2;
}
pix3 = pixReduceRankBinary2(pix2, level3, tab);
pixDestroy(&pix2);
if (level4 <= 0) {
FREE(tab);
return pix3;
}
pix4 = pixReduceRankBinary2(pix3, level4, tab);
pixDestroy(&pix3);
FREE(tab);
return pix4;
}
/*!
* pixReduceRankBinary2()
*
* Input: pixs (1 bpp)
* level (rank threshold: 1, 2, 3, 4)
* intab (<optional>; if null, a table is made here
* and destroyed before exit)
* Return: pixd (1 bpp, 2x rank threshold reduced), or null on error
*
* Notes:
* (1) pixd is downscaled by 2x from pixs.
* (2) The rank threshold specifies the minimum number of ON
* pixels in each 2x2 region of pixs that are required to
* set the corresponding pixel ON in pixd.
*/
PIX *
pixReduceRankBinary2(PIX *pixs,
l_int32 level,
l_uint8 *intab)
{
l_uint8 *tab;
l_int32 ws, hs, wpls, wpld;
l_uint32 *datas, *datad;
PIX *pixd;
PROCNAME("pixReduceRankBinary2");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
if (pixGetDepth(pixs) != 1)
return (PIX *)ERROR_PTR("pixs not binary", procName, NULL);
if (level < 1 || level > 4)
return (PIX *)ERROR_PTR("level must be in set {1,2,3,4}",
procName, NULL);
if (intab) /* use input table */
tab = intab;
else {
if ((tab = makeSubsampleTab2x()) == NULL)
return (PIX *)ERROR_PTR("tab not made", procName, NULL);
}
ws = pixGetWidth(pixs);
hs = pixGetHeight(pixs);
if (hs <= 1)
return (PIX *)ERROR_PTR("hs must be at least 2", procName, NULL);
wpls = pixGetWpl(pixs);
datas = pixGetData(pixs);
if ((pixd = pixCreate(ws / 2, hs / 2, 1)) == NULL)
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
pixCopyResolution(pixd, pixs);
pixScaleResolution(pixd, 0.5, 0.5);
wpld = pixGetWpl(pixd);
datad = pixGetData(pixd);
reduceRankBinary2Low(datad, wpld, datas, hs, wpls, tab, level);
if (!intab)
FREE(tab);
return pixd;
}