blob: a8bb309493e35304b546ae34f298a2f417235b09 [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.
*====================================================================*/
/*
* binreducelow.c
*
* Low-level subsampled reduction
* void reduceBinary2Low()
*
* Low-level threshold reduction
* void reduceRankBinary2Low()
* l_uint8 *makeSubsampleTab2x()
*
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "allheaders.h"
/*-------------------------------------------------------------------*
* Low-level subsampled reduction *
*-------------------------------------------------------------------*/
/*!
* reduceBinary2Low()
*
* After folding, the data is in bytes 0 and 2 of the word,
* and the bits in each byte are in the following order
* (with 0 being the leftmost originating pair and 7 being
* the rightmost originating pair):
*
* 0 4 1 5 2 6 3 7
*
* These need to be permuted to
*
* 0 1 2 3 4 5 6 7
*
* which is done with an 8-bit table generated by
* makeSubsampleTab2x().
*
*/
void
reduceBinary2Low(l_uint32 *datad,
l_int32 wpld,
l_uint32 *datas,
l_int32 hs,
l_int32 wpls,
l_uint8 *tab)
{
l_int32 i, id, j, wplsi;
l_uint8 byte0, byte1;
l_uint16 shortd;
l_uint32 word;
l_uint32 *lines, *lined;
/* e.g., if ws = 65: wd = 32, wpls = 3, wpld = 1 --> trouble */
wplsi = L_MIN(wpls, 2 * wpld); /* iterate over this number of words */
for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
lines = datas + i * wpls;
lined = datad + id * wpld;
for (j = 0; j < wplsi; j++) {
word = *(lines + j);
word = word & 0xaaaaaaaa; /* mask */
word = word | (word << 7); /* fold; data in bytes 0 & 2 */
byte0 = word >> 24;
byte1 = (word >> 8) & 0xff;
shortd = (tab[byte0] << 8) | tab[byte1];
SET_DATA_TWO_BYTES(lined, j, shortd);
}
}
return;
}
/*-------------------------------------------------------------------*
* Low-level rank filtered reduction *
*-------------------------------------------------------------------*/
/*!
* reduceRankBinary2Low()
*
* Rank filtering is done to the UL corner of each 2x2 pixel block,
* using only logical operations.
*
* Then these pixels are chosen in the 2x subsampling process,
* subsampled, as described above in reduceBinary2Low().
*/
void
reduceRankBinary2Low(l_uint32 *datad,
l_int32 wpld,
l_uint32 *datas,
l_int32 hs,
l_int32 wpls,
l_uint8 *tab,
l_int32 level)
{
l_int32 i, id, j, wplsi;
l_uint8 byte0, byte1;
l_uint16 shortd;
l_uint32 word1, word2, word3, word4;
l_uint32 *lines, *lined;
/* e.g., if ws = 65: wd = 32, wpls = 3, wpld = 1 --> trouble */
wplsi = L_MIN(wpls, 2 * wpld); /* iterate over this number of words */
switch (level)
{
case 1:
for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
lines = datas + i * wpls;
lined = datad + id * wpld;
for (j = 0; j < wplsi; j++) {
word1 = *(lines + j);
word2 = *(lines + wpls + j);
/* OR/OR */
word2 = word1 | word2;
word2 = word2 | (word2 << 1);
word2 = word2 & 0xaaaaaaaa; /* mask */
word1 = word2 | (word2 << 7); /* fold; data in bytes 0 & 2 */
byte0 = word1 >> 24;
byte1 = (word1 >> 8) & 0xff;
shortd = (tab[byte0] << 8) | tab[byte1];
SET_DATA_TWO_BYTES(lined, j, shortd);
}
}
break;
case 2:
for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
lines = datas + i * wpls;
lined = datad + id * wpld;
for (j = 0; j < wplsi; j++) {
word1 = *(lines + j);
word2 = *(lines + wpls + j);
/* (AND/OR) OR (OR/AND) */
word3 = word1 & word2;
word3 = word3 | (word3 << 1);
word4 = word1 | word2;
word4 = word4 & (word4 << 1);
word2 = word3 | word4;
word2 = word2 & 0xaaaaaaaa; /* mask */
word1 = word2 | (word2 << 7); /* fold; data in bytes 0 & 2 */
byte0 = word1 >> 24;
byte1 = (word1 >> 8) & 0xff;
shortd = (tab[byte0] << 8) | tab[byte1];
SET_DATA_TWO_BYTES(lined, j, shortd);
}
}
break;
case 3:
for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
lines = datas + i * wpls;
lined = datad + id * wpld;
for (j = 0; j < wplsi; j++) {
word1 = *(lines + j);
word2 = *(lines + wpls + j);
/* (AND/OR) AND (OR/AND) */
word3 = word1 & word2;
word3 = word3 | (word3 << 1);
word4 = word1 | word2;
word4 = word4 & (word4 << 1);
word2 = word3 & word4;
word2 = word2 & 0xaaaaaaaa; /* mask */
word1 = word2 | (word2 << 7); /* fold; data in bytes 0 & 2 */
byte0 = word1 >> 24;
byte1 = (word1 >> 8) & 0xff;
shortd = (tab[byte0] << 8) | tab[byte1];
SET_DATA_TWO_BYTES(lined, j, shortd);
}
}
break;
case 4:
for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
lines = datas + i * wpls;
lined = datad + id * wpld;
for (j = 0; j < wplsi; j++) {
word1 = *(lines + j);
word2 = *(lines + wpls + j);
/* AND/AND */
word2 = word1 & word2;
word2 = word2 & (word2 << 1);
word2 = word2 & 0xaaaaaaaa; /* mask */
word1 = word2 | (word2 << 7); /* fold; data in bytes 0 & 2 */
byte0 = word1 >> 24;
byte1 = (word1 >> 8) & 0xff;
shortd = (tab[byte0] << 8) | tab[byte1];
SET_DATA_TWO_BYTES(lined, j, shortd);
}
}
break;
}
return;
}
/*!
* makeSubsampleTab2x()
*
* This table permutes the bits in a byte, from
* 0 4 1 5 2 6 3 7
* to
* 0 1 2 3 4 5 6 7
*/
l_uint8 *
makeSubsampleTab2x(void)
{
l_uint8 *tab;
l_int32 i;
PROCNAME("makeSubsampleTab2x");
if ((tab = (l_uint8 *) CALLOC(256, sizeof(l_uint8))) == NULL)
return (l_uint8 *)ERROR_PTR("tab not made", procName, NULL);
for (i = 0; i < 256; i++)
tab[i] = ((i & 0x01) ) | /* 7 */
((i & 0x04) >> 1) | /* 6 */
((i & 0x10) >> 2) | /* 5 */
((i & 0x40) >> 3) | /* 4 */
((i & 0x02) << 3) | /* 3 */
((i & 0x08) << 2) | /* 2 */
((i & 0x20) << 1) | /* 1 */
((i & 0x80) ); /* 0 */
return tab;
}