Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 00017 /* 00018 * arithlow.c 00019 * 00020 * One image grayscale arithmetic (8, 16 or 32 bpp) 00021 * void addConstantGrayLow() 00022 * void multConstantGrayLow() 00023 * 00024 * Two image grayscale arithmetic (8, 16 or 32 bpp) 00025 * void addGrayLow() 00026 * void subtractGrayLow() 00027 * 00028 * Grayscale threshold operation (8, 16 or 32 bpp) 00029 * void thresholdToValueLow() 00030 * 00031 * Image accumulator arithmetic operations (8, 16, 32 bpp) 00032 * void finalAccumulateLow() 00033 * void finalAccumulateThreshLow() 00034 * void accumulateLow() 00035 * void multConstAccumulateLow() 00036 * 00037 * Absolute value of difference, component-wise. 00038 * void absDifferenceLow() 00039 */ 00040 00041 00042 #include <stdio.h> 00043 #include <stdlib.h> 00044 #include <string.h> 00045 #include <math.h> 00046 #include "allheaders.h" 00047 00048 00049 /*------------------------------------------------------------------* 00050 * One image grayscale arithmetic (8, 16 or 32 bpp) * 00051 *------------------------------------------------------------------*/ 00052 /*! 00053 * addConstantGrayLow() 00054 */ 00055 void 00056 addConstantGrayLow(l_uint32 *data, 00057 l_int32 w, 00058 l_int32 h, 00059 l_int32 d, 00060 l_int32 wpl, 00061 l_int32 val) 00062 { 00063 l_int32 i, j, pval; 00064 l_uint32 *line; 00065 00066 for (i = 0; i < h; i++) { 00067 line = data + i * wpl; 00068 if (d == 8) { 00069 if (val < 0) { 00070 for (j = 0; j < w; j++) { 00071 pval = GET_DATA_BYTE(line, j); 00072 pval = L_MAX(0, pval + val); 00073 SET_DATA_BYTE(line, j, pval); 00074 } 00075 } 00076 else { /* val >= 0 */ 00077 for (j = 0; j < w; j++) { 00078 pval = GET_DATA_BYTE(line, j); 00079 pval = L_MIN(255, pval + val); 00080 SET_DATA_BYTE(line, j, pval); 00081 } 00082 } 00083 } 00084 else if (d == 16) { 00085 if (val < 0) { 00086 for (j = 0; j < w; j++) { 00087 pval = GET_DATA_TWO_BYTES(line, j); 00088 pval = L_MAX(0, pval + val); 00089 SET_DATA_TWO_BYTES(line, j, pval); 00090 } 00091 } 00092 else { /* val >= 0 */ 00093 for (j = 0; j < w; j++) { 00094 pval = GET_DATA_TWO_BYTES(line, j); 00095 pval = L_MIN(0xffff, pval + val); 00096 SET_DATA_TWO_BYTES(line, j, pval); 00097 } 00098 } 00099 } 00100 else { /* d == 32; no check for overflow (< 0 or > 0xffffffff) */ 00101 for (j = 0; j < w; j++) 00102 *(line + j) += val; 00103 } 00104 } 00105 return; 00106 } 00107 00108 00109 /*! 00110 * multConstantGrayLow() 00111 */ 00112 void 00113 multConstantGrayLow(l_uint32 *data, 00114 l_int32 w, 00115 l_int32 h, 00116 l_int32 d, 00117 l_int32 wpl, 00118 l_float32 val) 00119 { 00120 l_int32 i, j, pval; 00121 l_uint32 upval; 00122 l_uint32 *line; 00123 00124 for (i = 0; i < h; i++) { 00125 line = data + i * wpl; 00126 if (d == 8) { 00127 for (j = 0; j < w; j++) { 00128 pval = GET_DATA_BYTE(line, j); 00129 pval = (l_int32)(val * pval); 00130 pval = L_MIN(255, pval); 00131 SET_DATA_BYTE(line, j, pval); 00132 } 00133 } 00134 else if (d == 16) { 00135 for (j = 0; j < w; j++) { 00136 pval = GET_DATA_TWO_BYTES(line, j); 00137 pval = (l_int32)(val * pval); 00138 pval = L_MIN(0xffff, pval); 00139 SET_DATA_TWO_BYTES(line, j, pval); 00140 } 00141 } 00142 else { /* d == 32; no clipping */ 00143 for (j = 0; j < w; j++) { 00144 upval = *(line + j); 00145 upval = (l_uint32)(val * upval); 00146 *(line + j) = upval; 00147 } 00148 } 00149 } 00150 return; 00151 } 00152 00153 00154 /*------------------------------------------------------------------* 00155 * Two image grayscale arithmetic (8, 16 or 32 bpp) * 00156 *------------------------------------------------------------------*/ 00157 /*! 00158 * addGrayLow() 00159 */ 00160 void 00161 addGrayLow(l_uint32 *datad, 00162 l_int32 w, 00163 l_int32 h, 00164 l_int32 d, 00165 l_int32 wpld, 00166 l_uint32 *datas, 00167 l_int32 wpls) 00168 { 00169 l_int32 i, j, val, sum; 00170 l_uint32 *lines, *lined; 00171 00172 00173 for (i = 0; i < h; i++) { 00174 lined = datad + i * wpld; 00175 lines = datas + i * wpls; 00176 if (d == 8) { 00177 for (j = 0; j < w; j++) { 00178 sum = GET_DATA_BYTE(lines, j) + GET_DATA_BYTE(lined, j); 00179 val = L_MIN(sum, 255); 00180 SET_DATA_BYTE(lined, j, val); 00181 } 00182 } 00183 else if (d == 16) { 00184 for (j = 0; j < w; j++) { 00185 sum = GET_DATA_TWO_BYTES(lines, j) 00186 + GET_DATA_TWO_BYTES(lined, j); 00187 val = L_MIN(sum, 0xffff); 00188 SET_DATA_TWO_BYTES(lined, j, val); 00189 } 00190 } 00191 else { /* d == 32; no clipping */ 00192 for (j = 0; j < w; j++) 00193 *(lined + j) += *(lines + j); 00194 } 00195 } 00196 00197 return; 00198 } 00199 00200 00201 /*! 00202 * subtractGrayLow() 00203 */ 00204 void 00205 subtractGrayLow(l_uint32 *datad, 00206 l_int32 w, 00207 l_int32 h, 00208 l_int32 d, 00209 l_int32 wpld, 00210 l_uint32 *datas, 00211 l_int32 wpls) 00212 { 00213 l_int32 i, j, val, diff; 00214 l_uint32 *lines, *lined; 00215 00216 for (i = 0; i < h; i++) { 00217 lined = datad + i * wpld; 00218 lines = datas + i * wpls; 00219 if (d == 8) { 00220 for (j = 0; j < w; j++) { 00221 diff = GET_DATA_BYTE(lined, j) - GET_DATA_BYTE(lines, j); 00222 val = L_MAX(diff, 0); 00223 SET_DATA_BYTE(lined, j, val); 00224 } 00225 } 00226 else if (d == 16) { 00227 for (j = 0; j < w; j++) { 00228 diff = GET_DATA_TWO_BYTES(lined, j) 00229 - GET_DATA_TWO_BYTES(lines, j); 00230 val = L_MAX(diff, 0); 00231 SET_DATA_TWO_BYTES(lined, j, val); 00232 } 00233 } 00234 else { /* d == 32; no clipping */ 00235 for (j = 0; j < w; j++) 00236 *(lined + j) -= *(lines + j); 00237 } 00238 } 00239 00240 return; 00241 } 00242 00243 00244 /*-------------------------------------------------------------* 00245 * Grayscale threshold operation * 00246 *-------------------------------------------------------------*/ 00247 /*! 00248 * thresholdToValueLow() 00249 */ 00250 void 00251 thresholdToValueLow(l_uint32 *datad, 00252 l_int32 w, 00253 l_int32 h, 00254 l_int32 d, 00255 l_int32 wpld, 00256 l_int32 threshval, 00257 l_int32 setval) 00258 { 00259 l_int32 i, j, setabove; 00260 l_uint32 *lined; 00261 00262 if (setval > threshval) 00263 setabove = TRUE; 00264 else 00265 setabove = FALSE; 00266 00267 for (i = 0; i < h; i++) { 00268 lined = datad + i * wpld; 00269 if (setabove == TRUE) { 00270 if (d == 8) { 00271 for (j = 0; j < w; j++) { 00272 if (GET_DATA_BYTE(lined, j) - threshval >= 0) 00273 SET_DATA_BYTE(lined, j, setval); 00274 } 00275 } 00276 else if (d == 16) { 00277 for (j = 0; j < w; j++) { 00278 if (GET_DATA_TWO_BYTES(lined, j) - threshval >= 0) 00279 SET_DATA_TWO_BYTES(lined, j, setval); 00280 } 00281 } 00282 else { /* d == 32 */ 00283 for (j = 0; j < w; j++) { 00284 if (*(lined + j) >= threshval) 00285 *(lined + j) = setval; 00286 } 00287 } 00288 } 00289 else { /* set if below or at threshold */ 00290 if (d == 8) { 00291 for (j = 0; j < w; j++) { 00292 if (GET_DATA_BYTE(lined, j) - threshval <= 0) 00293 SET_DATA_BYTE(lined, j, setval); 00294 } 00295 } 00296 else if (d == 16) { 00297 for (j = 0; j < w; j++) { 00298 if (GET_DATA_TWO_BYTES(lined, j) - threshval <= 0) 00299 SET_DATA_TWO_BYTES(lined, j, setval); 00300 } 00301 } 00302 else { /* d == 32 */ 00303 for (j = 0; j < w; j++) { 00304 if (*(lined + j) <= threshval) 00305 *(lined + j) = setval; 00306 } 00307 } 00308 } 00309 } 00310 return; 00311 } 00312 00313 00314 00315 /*-------------------------------------------------------------* 00316 * Image accumulator arithmetic operations * 00317 *-------------------------------------------------------------*/ 00318 /*! 00319 * finalAccumulateLow() 00320 */ 00321 void 00322 finalAccumulateLow(l_uint32 *datad, 00323 l_int32 w, 00324 l_int32 h, 00325 l_int32 d, 00326 l_int32 wpld, 00327 l_uint32 *datas, 00328 l_int32 wpls, 00329 l_uint32 offset) 00330 { 00331 l_int32 i, j; 00332 l_int32 val; 00333 l_uint32 *lines, *lined; 00334 00335 switch (d) 00336 { 00337 case 8: 00338 for (i = 0; i < h; i++) { 00339 lines = datas + i * wpls; 00340 lined = datad + i * wpld; 00341 for (j = 0; j < w; j++) { 00342 val = lines[j] - offset; 00343 val = L_MAX(0, val); 00344 val = L_MIN(255, val); 00345 SET_DATA_BYTE(lined, j, (l_uint8)val); 00346 } 00347 } 00348 break; 00349 case 16: 00350 for (i = 0; i < h; i++) { 00351 lines = datas + i * wpls; 00352 lined = datad + i * wpld; 00353 for (j = 0; j < w; j++) { 00354 val = lines[j] - offset; 00355 val = L_MAX(0, val); 00356 val = L_MIN(0xffff, val); 00357 SET_DATA_TWO_BYTES(lined, j, (l_uint16)val); 00358 } 00359 } 00360 break; 00361 case 32: 00362 for (i = 0; i < h; i++) { 00363 lines = datas + i * wpls; 00364 lined = datad + i * wpld; 00365 for (j = 0; j < w; j++) 00366 lined[j] = lines[j] - offset; 00367 } 00368 break; 00369 } 00370 return; 00371 } 00372 00373 00374 void 00375 finalAccumulateThreshLow(l_uint32 *datad, 00376 l_int32 w, 00377 l_int32 h, 00378 l_int32 wpld, 00379 l_uint32 *datas, 00380 l_int32 wpls, 00381 l_uint32 offset, 00382 l_uint32 threshold) 00383 { 00384 l_int32 i, j; 00385 l_int32 val; 00386 l_uint32 *lines, *lined; 00387 00388 for (i = 0; i < h; i++) { 00389 lines = datas + i * wpls; 00390 lined = datad + i * wpld; 00391 00392 for (j = 0; j < w; j++) { 00393 val = lines[j] - offset; 00394 if (val >= threshold) { 00395 SET_DATA_BIT(lined, j); 00396 } 00397 } 00398 } 00399 } 00400 00401 00402 /*! 00403 * accumulateLow() 00404 */ 00405 void 00406 accumulateLow(l_uint32 *datad, 00407 l_int32 w, 00408 l_int32 h, 00409 l_int32 wpld, 00410 l_uint32 *datas, 00411 l_int32 d, 00412 l_int32 wpls, 00413 l_int32 op) 00414 { 00415 l_int32 i, j; 00416 l_uint32 *lines, *lined; 00417 00418 switch (d) 00419 { 00420 case 1: 00421 for (i = 0; i < h; i++) { 00422 lines = datas + i * wpls; 00423 lined = datad + i * wpld; 00424 if (op == L_ARITH_ADD) { 00425 for (j = 0; j < w; j++) 00426 lined[j] += GET_DATA_BIT(lines, j); 00427 } 00428 else { /* op == L_ARITH_SUBTRACT */ 00429 for (j = 0; j < w; j++) 00430 lined[j] -= GET_DATA_BIT(lines, j); 00431 } 00432 } 00433 break; 00434 case 8: 00435 for (i = 0; i < h; i++) { 00436 lines = datas + i * wpls; 00437 lined = datad + i * wpld; 00438 if (op == L_ARITH_ADD) { 00439 for (j = 0; j < w; j++) 00440 lined[j] += GET_DATA_BYTE(lines, j); 00441 } 00442 else { /* op == L_ARITH_SUBTRACT */ 00443 for (j = 0; j < w; j++) 00444 lined[j] -= GET_DATA_BYTE(lines, j); 00445 } 00446 } 00447 break; 00448 case 16: 00449 for (i = 0; i < h; i++) { 00450 lines = datas + i * wpls; 00451 lined = datad + i * wpld; 00452 if (op == L_ARITH_ADD) { 00453 for (j = 0; j < w; j++) 00454 lined[j] += GET_DATA_TWO_BYTES(lines, j); 00455 } 00456 else { /* op == L_ARITH_SUBTRACT */ 00457 for (j = 0; j < w; j++) 00458 lined[j] -= GET_DATA_TWO_BYTES(lines, j); 00459 } 00460 } 00461 break; 00462 case 32: 00463 for (i = 0; i < h; i++) { 00464 lines = datas + i * wpls; 00465 lined = datad + i * wpld; 00466 if (op == L_ARITH_ADD) { 00467 for (j = 0; j < w; j++) 00468 lined[j] += lines[j]; 00469 } 00470 else { /* op == L_ARITH_SUBTRACT */ 00471 for (j = 0; j < w; j++) 00472 lined[j] -= lines[j]; 00473 } 00474 } 00475 break; 00476 } 00477 return; 00478 } 00479 00480 00481 /*! 00482 * multConstAccumulateLow() 00483 */ 00484 void 00485 multConstAccumulateLow(l_uint32 *data, 00486 l_int32 w, 00487 l_int32 h, 00488 l_int32 wpl, 00489 l_float32 factor, 00490 l_uint32 offset) 00491 { 00492 l_int32 i, j; 00493 l_int32 val; 00494 l_uint32 *line; 00495 00496 for (i = 0; i < h; i++) { 00497 line = data + i * wpl; 00498 for (j = 0; j < w; j++) { 00499 val = line[j] - offset; 00500 val = (l_int32)(val * factor); 00501 val += offset; 00502 line[j] = (l_uint32)val; 00503 } 00504 } 00505 return; 00506 } 00507 00508 00509 /*-----------------------------------------------------------------------* 00510 * Absolute value of difference, component-wise * 00511 *-----------------------------------------------------------------------*/ 00512 /*! 00513 * absDifferenceLow() 00514 * 00515 * Finds the absolute value of the difference of each pixel, 00516 * for 8 and 16 bpp gray and for 32 bpp rgb. For 32 bpp, the 00517 * differences are found for each of the RGB components 00518 * separately, and the LSB component is ignored. 00519 * The results are written into datad. 00520 */ 00521 void 00522 absDifferenceLow(l_uint32 *datad, 00523 l_int32 w, 00524 l_int32 h, 00525 l_int32 wpld, 00526 l_uint32 *datas1, 00527 l_uint32 *datas2, 00528 l_int32 d, 00529 l_int32 wpls) 00530 { 00531 l_int32 i, j, val1, val2, diff; 00532 l_uint32 word1, word2; 00533 l_uint32 *lines1, *lines2, *lined, *pdword; 00534 00535 PROCNAME("absDifferenceLow"); 00536 00537 switch (d) 00538 { 00539 case 8: 00540 for (i = 0; i < h; i++) { 00541 lines1 = datas1 + i * wpls; 00542 lines2 = datas2 + i * wpls; 00543 lined = datad + i * wpld; 00544 for (j = 0; j < w; j++) { 00545 val1 = GET_DATA_BYTE(lines1, j); 00546 val2 = GET_DATA_BYTE(lines2, j); 00547 diff = L_ABS(val1 - val2); 00548 SET_DATA_BYTE(lined, j, diff); 00549 } 00550 } 00551 break; 00552 case 16: 00553 for (i = 0; i < h; i++) { 00554 lines1 = datas1 + i * wpls; 00555 lines2 = datas2 + i * wpls; 00556 lined = datad + i * wpld; 00557 for (j = 0; j < w; j++) { 00558 val1 = GET_DATA_TWO_BYTES(lines1, j); 00559 val2 = GET_DATA_TWO_BYTES(lines2, j); 00560 diff = L_ABS(val1 - val2); 00561 SET_DATA_TWO_BYTES(lined, j, diff); 00562 } 00563 } 00564 break; 00565 case 32: 00566 for (i = 0; i < h; i++) { 00567 lines1 = datas1 + i * wpls; 00568 lines2 = datas2 + i * wpls; 00569 lined = datad + i * wpld; 00570 for (j = 0; j < w; j++) { 00571 word1 = lines1[j]; 00572 word2 = lines2[j]; 00573 pdword = lined + j; 00574 val1 = GET_DATA_BYTE(&word1, COLOR_RED); 00575 val2 = GET_DATA_BYTE(&word2, COLOR_RED); 00576 diff = L_ABS(val1 - val2); 00577 SET_DATA_BYTE(pdword, COLOR_RED, diff); 00578 val1 = GET_DATA_BYTE(&word1, COLOR_GREEN); 00579 val2 = GET_DATA_BYTE(&word2, COLOR_GREEN); 00580 diff = L_ABS(val1 - val2); 00581 SET_DATA_BYTE(pdword, COLOR_GREEN, diff); 00582 val1 = GET_DATA_BYTE(&word1, COLOR_BLUE); 00583 val2 = GET_DATA_BYTE(&word2, COLOR_BLUE); 00584 diff = L_ABS(val1 - val2); 00585 SET_DATA_BYTE(pdword, COLOR_BLUE, diff); 00586 } 00587 } 00588 break; 00589 default: 00590 L_ERROR("source depth must be 8, 16 or 32 bpp", procName); 00591 break; 00592 } 00593 00594 return; 00595 } 00596