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