/*====================================================================* - 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 #include #include #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; }