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 * pixarith.c 00019 * 00020 * One-image grayscale arithmetic operations (8, 16, 32 bpp) 00021 * l_int32 pixAddConstantGray() 00022 * l_int32 pixMultConstantGray() 00023 * 00024 * Two-image grayscale arithmetic operations (8, 16, 32 bpp) 00025 * PIX *pixAddGray() 00026 * PIX *pixSubtractGray() 00027 * 00028 * Grayscale threshold operation (8, 16, 32 bpp) 00029 * PIX *pixThresholdToValue() 00030 * 00031 * Image accumulator arithmetic operations 00032 * PIX *pixInitAccumulate() 00033 * PIX *pixFinalAccumulate() 00034 * PIX *pixFinalAccumulateThreshold() 00035 * l_int32 pixAccumulate() 00036 * l_int32 pixMultConstAccumulate() 00037 * 00038 * Absolute value of difference 00039 * PIX *pixAbsDifference() 00040 * 00041 * Two-image min and max operations (8 and 16 bpp) 00042 * PIX *pixMinOrMax() 00043 * 00044 * Scale pix for maximum dynamic range in 8 bpp image: 00045 * PIX *pixMaxDynamicRange() 00046 * 00047 * Log base2 lookup 00048 * l_float32 *makeLogBase2Tab() 00049 * l_float32 getLogBase2() 00050 * 00051 * The image accumulator operations are used when you expect 00052 * overflow from 8 bits on intermediate results. For example, 00053 * you might want a tophat contrast operator which is 00054 * 3*I - opening(I,S) - closing(I,S) 00055 * To use these operations, first use the init to generate 00056 * a 16 bpp image, use the accumulate to add or subtract 8 bpp 00057 * images from that, or the multiply constant to multiply 00058 * by a small constant (much less than 256 -- we don't want 00059 * overflow from the 16 bit images!), and when you're finished 00060 * use final to bring the result back to 8 bpp, clipped 00061 * if necessary. There is also a divide function, which 00062 * can be used to divide one image by another, scaling the 00063 * result for maximum dynamic range, and giving back the 00064 * 8 bpp result. 00065 * 00066 * A simpler interface to the arithmetic operations is 00067 * provided in pixacc.c. 00068 */ 00069 00070 00071 #include <stdio.h> 00072 #include <stdlib.h> 00073 #include <string.h> 00074 #include <math.h> 00075 #include "allheaders.h" 00076 00077 00078 /*-------------------------------------------------------------* 00079 * One-image grayscale arithmetic operations * 00080 *-------------------------------------------------------------*/ 00081 /*! 00082 * pixAddConstantGray() 00083 * 00084 * Input: pixs (8, 16 or 32 bpp) 00085 * val (amount to add to each pixel) 00086 * Return: 0 if OK, 1 on error 00087 * 00088 * Notes: 00089 * (1) In-place operation. 00090 * (2) No clipping for 32 bpp. 00091 * (3) For 8 and 16 bpp, if val > 0 the result is clipped 00092 * to 0xff and 0xffff, rsp. 00093 * (4) For 8 and 16 bpp, if val < 0 the result is clipped to 0. 00094 */ 00095 l_int32 00096 pixAddConstantGray(PIX *pixs, 00097 l_int32 val) 00098 { 00099 l_int32 w, h, d, wpl; 00100 l_uint32 *data; 00101 00102 PROCNAME("pixAddConstantGray"); 00103 00104 if (!pixs) 00105 return ERROR_INT("pixs not defined", procName, 1); 00106 pixGetDimensions(pixs, &w, &h, &d); 00107 if (d != 8 && d != 16 && d != 32) 00108 return ERROR_INT("pixs not 8, 16 or 32 bpp", procName, 1); 00109 00110 data = pixGetData(pixs); 00111 wpl = pixGetWpl(pixs); 00112 addConstantGrayLow(data, w, h, d, wpl, val); 00113 00114 return 0; 00115 } 00116 00117 00118 /*! 00119 * pixMultConstantGray() 00120 * 00121 * Input: pixs (8, 16 or 32 bpp) 00122 * val (>= 0.0; amount to multiply by each pixel) 00123 * Return: 0 if OK, 1 on error 00124 * 00125 * Notes: 00126 * (1) In-place operation; val must be >= 0. 00127 * (2) No clipping for 32 bpp. 00128 * (3) For 8 and 16 bpp, the result is clipped to 0xff and 0xffff, rsp. 00129 */ 00130 l_int32 00131 pixMultConstantGray(PIX *pixs, 00132 l_float32 val) 00133 { 00134 l_int32 w, h, d, wpl; 00135 l_uint32 *data; 00136 00137 PROCNAME("pixMultConstantGray"); 00138 00139 if (!pixs) 00140 return ERROR_INT("pixs not defined", procName, 1); 00141 pixGetDimensions(pixs, &w, &h, &d); 00142 if (d != 8 && d != 16 && d != 32) 00143 return ERROR_INT("pixs not 8, 16 or 32 bpp", procName, 1); 00144 if (val < 0.0) 00145 return ERROR_INT("val < 0.0", procName, 1); 00146 00147 data = pixGetData(pixs); 00148 wpl = pixGetWpl(pixs); 00149 multConstantGrayLow(data, w, h, d, wpl, val); 00150 00151 return 0; 00152 } 00153 00154 00155 /*-------------------------------------------------------------* 00156 * Two-image grayscale arithmetic ops * 00157 *-------------------------------------------------------------*/ 00158 /*! 00159 * pixAddGray() 00160 * 00161 * Input: pixd (<optional>; this can be null, equal to pixs1, or 00162 * different from pixs1) 00163 * pixs1 (can be == to pixd) 00164 * pixs2 00165 * Return: pixd always 00166 * 00167 * Notes: 00168 * (1) Arithmetic addition of two 8, 16 or 32 bpp images. 00169 * (2) For 8 and 16 bpp, we do explicit clipping to 0xff and 0xffff, 00170 * respectively. 00171 * (3) Alignment is to UL corner. 00172 * (4) There are 3 cases. The result can go to a new dest, 00173 * in-place to pixs1, or to an existing input dest: 00174 * * pixd == null: (src1 + src2) --> new pixd 00175 * * pixd == pixs1: (src1 + src2) --> src1 (in-place) 00176 * * pixd != pixs1: (src1 + src2) --> input pixd 00177 * (5) pixs2 must be different from both pixd and pixs1. 00178 */ 00179 PIX * 00180 pixAddGray(PIX *pixd, 00181 PIX *pixs1, 00182 PIX *pixs2) 00183 { 00184 l_int32 d, ws, hs, w, h, wpls, wpld; 00185 l_uint32 *datas, *datad; 00186 00187 PROCNAME("pixAddGray"); 00188 00189 if (!pixs1) 00190 return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd); 00191 if (!pixs2) 00192 return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd); 00193 if (pixs2 == pixs1) 00194 return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", procName, pixd); 00195 if (pixs2 == pixd) 00196 return (PIX *)ERROR_PTR("pixs2 and pixd must differ", procName, pixd); 00197 d = pixGetDepth(pixs1); 00198 if (d != 8 && d != 16 && d != 32) 00199 return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", procName, pixd); 00200 if (pixGetDepth(pixs2) != d) 00201 return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", procName, pixd); 00202 if (pixd && (pixGetDepth(pixd) != d)) 00203 return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", procName, pixd); 00204 00205 if (!pixSizesEqual(pixs1, pixs2)) 00206 L_WARNING("pixs1 and pixs2 not equal in size", procName); 00207 if (pixd && !pixSizesEqual(pixs1, pixd)) 00208 L_WARNING("pixs1 and pixd not equal in size", procName); 00209 00210 if (pixs1 != pixd) 00211 pixd = pixCopy(pixd, pixs1); 00212 00213 /* pixd + pixs2 ==> pixd */ 00214 datas = pixGetData(pixs2); 00215 datad = pixGetData(pixd); 00216 wpls = pixGetWpl(pixs2); 00217 wpld = pixGetWpl(pixd); 00218 pixGetDimensions(pixs2, &ws, &hs, NULL); 00219 pixGetDimensions(pixd, &w, &h, NULL); 00220 w = L_MIN(ws, w); 00221 h = L_MIN(hs, h); 00222 addGrayLow(datad, w, h, d, wpld, datas, wpls); 00223 00224 return pixd; 00225 } 00226 00227 00228 /*! 00229 * pixSubtractGray() 00230 * 00231 * Input: pixd (<optional>; this can be null, equal to pixs1, or 00232 * different from pixs1) 00233 * pixs1 (can be == to pixd) 00234 * pixs2 00235 * Return: pixd always 00236 * 00237 * Notes: 00238 * (1) Arithmetic subtraction of two 8, 16 or 32 bpp images. 00239 * (2) Source pixs2 is always subtracted from source pixs1. 00240 * (3) Do explicit clipping to 0. 00241 * (4) Alignment is to UL corner. 00242 * (5) There are 3 cases. The result can go to a new dest, 00243 * in-place to pixs1, or to an existing input dest: 00244 * (a) pixd == null (src1 - src2) --> new pixd 00245 * (b) pixd == pixs1 (src1 - src2) --> src1 (in-place) 00246 * (d) pixd != pixs1 (src1 - src2) --> input pixd 00247 * (6) pixs2 must be different from both pixd and pixs1. 00248 */ 00249 PIX * 00250 pixSubtractGray(PIX *pixd, 00251 PIX *pixs1, 00252 PIX *pixs2) 00253 { 00254 l_int32 w, h, ws, hs, d, wpls, wpld; 00255 l_uint32 *datas, *datad; 00256 00257 PROCNAME("pixSubtractGray"); 00258 00259 if (!pixs1) 00260 return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd); 00261 if (!pixs2) 00262 return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd); 00263 if (pixs2 == pixs1) 00264 return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", procName, pixd); 00265 if (pixs2 == pixd) 00266 return (PIX *)ERROR_PTR("pixs2 and pixd must differ", procName, pixd); 00267 d = pixGetDepth(pixs1); 00268 if (d != 8 && d != 16 && d != 32) 00269 return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", procName, pixd); 00270 if (pixGetDepth(pixs2) != d) 00271 return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", procName, pixd); 00272 if (pixd && (pixGetDepth(pixd) != d)) 00273 return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", procName, pixd); 00274 00275 if (!pixSizesEqual(pixs1, pixs2)) 00276 L_WARNING("pixs1 and pixs2 not equal in size", procName); 00277 if (pixd && !pixSizesEqual(pixs1, pixd)) 00278 L_WARNING("pixs1 and pixd not equal in size", procName); 00279 00280 if (pixs1 != pixd) 00281 pixd = pixCopy(pixd, pixs1); 00282 00283 /* pixd - pixs2 ==> pixd */ 00284 datas = pixGetData(pixs2); 00285 datad = pixGetData(pixd); 00286 wpls = pixGetWpl(pixs2); 00287 wpld = pixGetWpl(pixd); 00288 pixGetDimensions(pixs2, &ws, &hs, NULL); 00289 pixGetDimensions(pixd, &w, &h, NULL); 00290 w = L_MIN(ws, w); 00291 h = L_MIN(hs, h); 00292 subtractGrayLow(datad, w, h, d, wpld, datas, wpls); 00293 00294 return pixd; 00295 } 00296 00297 00298 /*-------------------------------------------------------------* 00299 * Grayscale threshold operation * 00300 *-------------------------------------------------------------*/ 00301 /*! 00302 * pixThresholdToValue() 00303 * 00304 * Input: pixd (<optional>; if not null, must be equal to pixs) 00305 * pixs (8, 16, 32 bpp) 00306 * threshval 00307 * setval 00308 * Return: pixd always 00309 * 00310 * Notes: 00311 * - operation can be in-place (pixs == pixd) or to a new pixd 00312 * - if setval > threshval, sets pixels with a value >= threshval to setval 00313 * - if setval < threshval, sets pixels with a value <= threshval to setval 00314 * - if setval == threshval, no-op 00315 */ 00316 PIX * 00317 pixThresholdToValue(PIX *pixd, 00318 PIX *pixs, 00319 l_int32 threshval, 00320 l_int32 setval) 00321 { 00322 l_int32 w, h, d, wpld; 00323 l_uint32 *datad; 00324 00325 PROCNAME("pixThresholdToValue"); 00326 00327 if (!pixs) 00328 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); 00329 d = pixGetDepth(pixs); 00330 if (d != 8 && d != 16 && d != 32) 00331 return (PIX *)ERROR_PTR("pixs not 8, 16 or 32 bpp", procName, pixd); 00332 if (pixd && (pixs != pixd)) 00333 return (PIX *)ERROR_PTR("pixd exists and is not pixs", procName, pixd); 00334 if (threshval < 0 || setval < 0) 00335 return (PIX *)ERROR_PTR("threshval & setval not < 0", procName, pixd); 00336 if (d == 8 && setval > 255) 00337 return (PIX *)ERROR_PTR("setval > 255 for 8 bpp", procName, pixd); 00338 if (d == 16 && setval > 0xffff) 00339 return (PIX *)ERROR_PTR("setval > 0xffff for 16 bpp", procName, pixd); 00340 00341 if (!pixd) 00342 pixd = pixCopy(NULL, pixs); 00343 if (setval == threshval) { 00344 L_WARNING("setval == threshval; no operation", procName); 00345 return pixd; 00346 } 00347 00348 datad = pixGetData(pixd); 00349 pixGetDimensions(pixd, &w, &h, NULL); 00350 wpld = pixGetWpl(pixd); 00351 00352 thresholdToValueLow(datad, w, h, d, wpld, threshval, setval); 00353 return pixd; 00354 } 00355 00356 00357 00358 /*-------------------------------------------------------------* 00359 * Image accumulator arithmetic operations * 00360 *-------------------------------------------------------------*/ 00361 /*! 00362 * pixInitAccumulate() 00363 * 00364 * Input: w, h (of accumulate array) 00365 * offset (initialize the 32 bpp to have this 00366 * value; not more than 0x40000000) 00367 * Return: pixd (32 bpp), or null on error 00368 * 00369 * Notes: 00370 * (1) The offset must be >= 0. 00371 * (2) The offset is used so that we can do arithmetic 00372 * with negative number results on l_uint32 data; it 00373 * prevents the l_uint32 data from going negative. 00374 * (3) Because we use l_int32 intermediate data results, 00375 * these should never exceed the max of l_int32 (0x7fffffff). 00376 * We do not permit the offset to be above 0x40000000, 00377 * which is half way between 0 and the max of l_int32. 00378 * (4) The same offset should be used for initialization, 00379 * multiplication by a constant, and final extraction! 00380 * (5) If you're only adding positive values, offset can be 0. 00381 */ 00382 PIX * 00383 pixInitAccumulate(l_int32 w, 00384 l_int32 h, 00385 l_uint32 offset) 00386 { 00387 PIX *pixd; 00388 00389 PROCNAME("pixInitAccumulate"); 00390 00391 if ((pixd = pixCreate(w, h, 32)) == NULL) 00392 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00393 if (offset > 0x40000000) 00394 offset = 0x40000000; 00395 pixSetAllArbitrary(pixd, offset); 00396 return pixd; 00397 } 00398 00399 00400 /*! 00401 * pixFinalAccumulate() 00402 * 00403 * Input: pixs (32 bpp) 00404 * offset (same as used for initialization) 00405 * depth (8, 16 or 32 bpp, of destination) 00406 * Return: pixd (8, 16 or 32 bpp), or null on error 00407 * 00408 * Notes: 00409 * (1) The offset must be >= 0 and should not exceed 0x40000000. 00410 * (2) The offset is subtracted from the src 32 bpp image 00411 * (3) For 8 bpp dest, the result is clipped to [0, 0xff] 00412 * (4) For 16 bpp dest, the result is clipped to [0, 0xffff] 00413 */ 00414 PIX * 00415 pixFinalAccumulate(PIX *pixs, 00416 l_uint32 offset, 00417 l_int32 depth) 00418 { 00419 l_int32 w, h, wpls, wpld; 00420 l_uint32 *datas, *datad; 00421 PIX *pixd; 00422 00423 PROCNAME("pixFinalAccumulate"); 00424 00425 if (!pixs) 00426 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00427 if (pixGetDepth(pixs) != 32) 00428 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL); 00429 if (depth != 8 && depth != 16 && depth != 32) 00430 return (PIX *)ERROR_PTR("dest depth not 8, 16, 32 bpp", procName, NULL); 00431 if (offset > 0x40000000) 00432 offset = 0x40000000; 00433 00434 pixGetDimensions(pixs, &w, &h, NULL); 00435 if ((pixd = pixCreate(w, h, depth)) == NULL) 00436 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00437 pixCopyResolution(pixd, pixs); /* but how did pixs get it initially? */ 00438 datas = pixGetData(pixs); 00439 datad = pixGetData(pixd); 00440 wpls = pixGetWpl(pixs); 00441 wpld = pixGetWpl(pixd); 00442 00443 finalAccumulateLow(datad, w, h, depth, wpld, datas, wpls, offset); 00444 return pixd; 00445 } 00446 00447 00448 /*! 00449 * pixFinalAccumulateThreshold() 00450 * 00451 * Input: pixs (32 bpp) 00452 * offset (same as used for initialization) 00453 * threshold (values less than this are set in the destination) 00454 * Return: pixd (1 bpp), or null on error 00455 * 00456 * Notes: 00457 * (1) The offset must be >= 0 and should not exceed 0x40000000. 00458 * (2) The offset is subtracted from the src 32 bpp image 00459 */ 00460 PIX * 00461 pixFinalAccumulateThreshold(PIX *pixs, 00462 l_uint32 offset, 00463 l_uint32 threshold) 00464 { 00465 l_int32 w, h, wpls, wpld; 00466 l_uint32 *datas, *datad; 00467 PIX *pixd; 00468 00469 PROCNAME("pixFinalAccumulateThreshold"); 00470 00471 if (!pixs) 00472 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00473 if (pixGetDepth(pixs) != 32) 00474 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL); 00475 if (offset > 0x40000000) 00476 offset = 0x40000000; 00477 00478 pixGetDimensions(pixs, &w, &h, NULL); 00479 if ((pixd = pixCreate(w, h, 1)) == NULL) 00480 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00481 pixCopyResolution(pixd, pixs); /* but how did pixs get it initially? */ 00482 datas = pixGetData(pixs); 00483 datad = pixGetData(pixd); 00484 wpls = pixGetWpl(pixs); 00485 wpld = pixGetWpl(pixd); 00486 00487 finalAccumulateThreshLow(datad, w, h, wpld, datas, wpls, offset, threshold); 00488 return pixd; 00489 } 00490 00491 00492 /*! 00493 * pixAccumulate() 00494 * 00495 * Input: pixd (32 bpp) 00496 * pixs (1, 8, 16 or 32 bpp) 00497 * op (L_ARITH_ADD or L_ARITH_SUBTRACT) 00498 * Return: 0 if OK; 1 on error 00499 * 00500 * Notes: 00501 * (1) This adds or subtracts each pixs value from pixd. 00502 * (2) This clips to the minimum of pixs and pixd, so they 00503 * do not need to be the same size. 00504 * (3) The alignment is to the origin (UL corner) of pixs & pixd. 00505 */ 00506 l_int32 00507 pixAccumulate(PIX *pixd, 00508 PIX *pixs, 00509 l_int32 op) 00510 { 00511 l_int32 w, h, d, wd, hd, wpls, wpld; 00512 l_uint32 *datas, *datad; 00513 00514 PROCNAME("pixAccumulate"); 00515 00516 if (!pixd || (pixGetDepth(pixd) != 32)) 00517 return ERROR_INT("pixd not defined or not 32 bpp", procName, 1); 00518 if (!pixs) 00519 return ERROR_INT("pixs not defined", procName, 1); 00520 d = pixGetDepth(pixs); 00521 if (d != 1 && d != 8 && d != 16 && d != 32) 00522 return ERROR_INT("pixs not 1, 8, 16 or 32 bpp", procName, 1); 00523 if (op != L_ARITH_ADD && op != L_ARITH_SUBTRACT) 00524 return ERROR_INT("op must be in {L_ARITH_ADD, L_ARITH_SUBTRACT}", 00525 procName, 1); 00526 00527 datas = pixGetData(pixs); 00528 datad = pixGetData(pixd); 00529 wpls = pixGetWpl(pixs); 00530 wpld = pixGetWpl(pixd); 00531 pixGetDimensions(pixs, &w, &h, NULL); 00532 pixGetDimensions(pixd, &wd, &hd, NULL); 00533 w = L_MIN(w, wd); 00534 h = L_MIN(h, hd); 00535 00536 accumulateLow(datad, w, h, wpld, datas, d, wpls, op); 00537 return 0; 00538 } 00539 00540 00541 /*! 00542 * pixMultConstAccumulate() 00543 * 00544 * Input: pixs (32 bpp) 00545 * factor 00546 * offset (same as used for initialization) 00547 * Return: 0 if OK; 1 on error 00548 * 00549 * Notes: 00550 * (1) The offset must be >= 0 and should not exceed 0x40000000. 00551 * (2) This multiplies each pixel, relative to offset, by the input factor 00552 * (3) The result is returned with the offset back in place. 00553 */ 00554 l_int32 00555 pixMultConstAccumulate(PIX *pixs, 00556 l_float32 factor, 00557 l_uint32 offset) 00558 { 00559 l_int32 w, h, wpl; 00560 l_uint32 *data; 00561 00562 PROCNAME("pixMultConstAccumulate"); 00563 00564 if (!pixs) 00565 return ERROR_INT("pixs not defined", procName, 1); 00566 if (pixGetDepth(pixs) != 32) 00567 return ERROR_INT("pixs not 32 bpp", procName, 1); 00568 if (offset > 0x40000000) 00569 offset = 0x40000000; 00570 00571 pixGetDimensions(pixs, &w, &h, NULL); 00572 data = pixGetData(pixs); 00573 wpl = pixGetWpl(pixs); 00574 00575 multConstAccumulateLow(data, w, h, wpl, factor, offset); 00576 return 0; 00577 } 00578 00579 00580 /*-----------------------------------------------------------------------* 00581 * Absolute value of difference * 00582 *-----------------------------------------------------------------------*/ 00583 /*! 00584 * pixAbsDifference() 00585 * 00586 * Input: pixs1, pixs2 (both either 8 or 16 bpp gray, or 32 bpp RGB) 00587 * Return: pixd, or null on error 00588 * 00589 * Notes: 00590 * (1) The depth of pixs1 and pixs2 must be equal. 00591 * (2) Clips computation to the min size, aligning the UL corners 00592 * (3) For 8 and 16 bpp, assumes one gray component. 00593 * (4) For 32 bpp, assumes 3 color components, and ignores the 00594 * LSB of each word (the alpha channel) 00595 * (5) Computes the absolute value of the difference between 00596 * each component value. 00597 */ 00598 PIX * 00599 pixAbsDifference(PIX *pixs1, 00600 PIX *pixs2) 00601 { 00602 l_int32 w, h, w2, h2, d, wpls, wpld; 00603 l_uint32 *datas1, *datas2, *datad; 00604 PIX *pixd; 00605 00606 PROCNAME("pixAbsDifference"); 00607 00608 if (!pixs1) 00609 return (PIX *)ERROR_PTR("pixs1 not defined", procName, NULL); 00610 if (!pixs2) 00611 return (PIX *)ERROR_PTR("pixs2 not defined", procName, NULL); 00612 d = pixGetDepth(pixs1); 00613 if (d != pixGetDepth(pixs2)) 00614 return (PIX *)ERROR_PTR("src1 and src2 depths unequal", procName, NULL); 00615 if (d != 8 && d != 16 && d != 32) 00616 return (PIX *)ERROR_PTR("depths not in {8, 16, 32}", procName, NULL); 00617 00618 pixGetDimensions(pixs1, &w, &h, NULL); 00619 pixGetDimensions(pixs2, &w2, &h2, NULL); 00620 w = L_MIN(w, w2); 00621 h = L_MIN(h, h2); 00622 if ((pixd = pixCreate(w, h, d)) == NULL) 00623 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00624 pixCopyResolution(pixd, pixs1); 00625 datas1 = pixGetData(pixs1); 00626 datas2 = pixGetData(pixs2); 00627 datad = pixGetData(pixd); 00628 wpls = pixGetWpl(pixs1); 00629 wpld = pixGetWpl(pixd); 00630 00631 absDifferenceLow(datad, w, h, wpld, datas1, datas2, d, wpls); 00632 00633 return pixd; 00634 } 00635 00636 00637 /*-----------------------------------------------------------------------* 00638 * Two-image min and max operations (8 and 16 bpp) * 00639 *-----------------------------------------------------------------------*/ 00640 /*! 00641 * pixMinOrMax() 00642 * 00643 * Input: pixd (<optional> destination: this can be null, 00644 * equal to pixs1, or different from pixs1) 00645 * pixs1 (can be == to pixd) 00646 * pixs2 00647 * type (L_CHOOSE_MIN, L_CHOOSE_MAX) 00648 * Return: pixd always 00649 * 00650 * Notes: 00651 * (1) This gives the min or max of two images. 00652 * (2) The depth can be 8 or 16 bpp. 00653 * (3) There are 3 cases: 00654 * - if pixd == null, Min(src1, src2) --> new pixd 00655 * - if pixd == pixs1, Min(src1, src2) --> src1 (in-place) 00656 * - if pixd != pixs1, Min(src1, src2) --> input pixd 00657 */ 00658 PIX * 00659 pixMinOrMax(PIX *pixd, 00660 PIX *pixs1, 00661 PIX *pixs2, 00662 l_int32 type) 00663 { 00664 l_int32 d, ws, hs, w, h, wpls, wpld, i, j; 00665 l_int32 vals, vald, val; 00666 l_uint32 *datas, *datad, *lines, *lined; 00667 00668 PROCNAME("pixMinOrMax"); 00669 00670 if (!pixs1) 00671 return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd); 00672 if (!pixs2) 00673 return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd); 00674 if (pixs1 == pixs2) 00675 return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd); 00676 if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX) 00677 return (PIX *)ERROR_PTR("invalid type", procName, pixd); 00678 d = pixGetDepth(pixs1); 00679 if (pixGetDepth(pixs2) != d) 00680 return (PIX *)ERROR_PTR("depths unequal", procName, pixd); 00681 if (d != 8 && d != 16) 00682 return (PIX *)ERROR_PTR("depth not 8 or 16 bpp", procName, pixd); 00683 00684 if (pixs1 != pixd) 00685 pixd = pixCopy(pixd, pixs1); 00686 00687 pixGetDimensions(pixs2, &ws, &hs, NULL); 00688 pixGetDimensions(pixd, &w, &h, NULL); 00689 w = L_MIN(w, ws); 00690 h = L_MIN(h, hs); 00691 datas = pixGetData(pixs2); 00692 datad = pixGetData(pixd); 00693 wpls = pixGetWpl(pixs2); 00694 wpld = pixGetWpl(pixd); 00695 for (i = 0; i < h; i++) { 00696 lines = datas + i * wpls; 00697 lined = datad + i * wpld; 00698 if (d == 8) { 00699 if (type == L_CHOOSE_MIN) { 00700 for (j = 0; j < w; j++) { 00701 vals = GET_DATA_BYTE(lines, j); 00702 vald = GET_DATA_BYTE(lined, j); 00703 val = L_MIN(vals, vald); 00704 SET_DATA_BYTE(lined, j, val); 00705 } 00706 } else { /* type == L_CHOOSE_MAX */ 00707 for (j = 0; j < w; j++) { 00708 vals = GET_DATA_BYTE(lines, j); 00709 vald = GET_DATA_BYTE(lined, j); 00710 val = L_MAX(vals, vald); 00711 SET_DATA_BYTE(lined, j, val); 00712 } 00713 } 00714 } else { /* d == 16 */ 00715 if (type == L_CHOOSE_MIN) { 00716 for (j = 0; j < w; j++) { 00717 vals = GET_DATA_TWO_BYTES(lines, j); 00718 vald = GET_DATA_TWO_BYTES(lined, j); 00719 val = L_MIN(vals, vald); 00720 SET_DATA_TWO_BYTES(lined, j, val); 00721 } 00722 } else { /* type == L_CHOOSE_MAX */ 00723 for (j = 0; j < w; j++) { 00724 vals = GET_DATA_TWO_BYTES(lines, j); 00725 vald = GET_DATA_TWO_BYTES(lined, j); 00726 val = L_MAX(vals, vald); 00727 SET_DATA_TWO_BYTES(lined, j, val); 00728 } 00729 } 00730 } 00731 } 00732 00733 return pixd; 00734 } 00735 00736 00737 /*-----------------------------------------------------------------------* 00738 * Scale for maximum dynamic range in 8 bpp image * 00739 *-----------------------------------------------------------------------*/ 00740 /*! 00741 * pixMaxDynamicRange() 00742 * 00743 * Input: pixs (4, 8, 16 or 32 bpp source) 00744 * type (L_LINEAR_SCALE or L_LOG_SCALE) 00745 * Return: pixd (8 bpp), or null on error 00746 * 00747 * Notes: 00748 * (1) Scales pixel values to fit maximally within the dest 8 bpp pixd 00749 * (2) Uses a LUT for log scaling 00750 */ 00751 PIX * 00752 pixMaxDynamicRange(PIX *pixs, 00753 l_int32 type) 00754 { 00755 l_uint8 dval; 00756 l_int32 i, j, w, h, d, wpls, wpld, max, sval; 00757 l_uint32 *datas, *datad; 00758 l_uint32 word; 00759 l_uint32 *lines, *lined; 00760 l_float32 factor; 00761 l_float32 *tab; 00762 PIX *pixd; 00763 00764 PROCNAME("pixMaxDynamicRange"); 00765 00766 if (!pixs) 00767 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00768 d = pixGetDepth(pixs); 00769 if (d != 4 && d != 8 && d != 16 && d != 32) 00770 return (PIX *)ERROR_PTR("pixs not in {4,8,16,32} bpp", procName, NULL); 00771 if (type != L_LINEAR_SCALE && type != L_LOG_SCALE) 00772 return (PIX *)ERROR_PTR("invalid type", procName, NULL); 00773 00774 pixGetDimensions(pixs, &w, &h, NULL); 00775 if ((pixd = pixCreate(w, h, 8)) == NULL) 00776 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00777 pixCopyResolution(pixd, pixs); 00778 datas = pixGetData(pixs); 00779 datad = pixGetData(pixd); 00780 wpls = pixGetWpl(pixs); 00781 wpld = pixGetWpl(pixd); 00782 00783 /* Get max */ 00784 max = 0; 00785 for (i = 0; i < h; i++) { 00786 lines = datas + i * wpls; 00787 for (j = 0; j < wpls; j++) { 00788 word = *(lines + j); 00789 if (d == 4) { 00790 max = L_MAX(max, word >> 28); 00791 max = L_MAX(max, (word >> 24) & 0xf); 00792 max = L_MAX(max, (word >> 20) & 0xf); 00793 max = L_MAX(max, (word >> 16) & 0xf); 00794 max = L_MAX(max, (word >> 12) & 0xf); 00795 max = L_MAX(max, (word >> 8) & 0xf); 00796 max = L_MAX(max, (word >> 4) & 0xf); 00797 max = L_MAX(max, word & 0xf); 00798 } else if (d == 8) { 00799 max = L_MAX(max, word >> 24); 00800 max = L_MAX(max, (word >> 16) & 0xff); 00801 max = L_MAX(max, (word >> 8) & 0xff); 00802 max = L_MAX(max, word & 0xff); 00803 } else if (d == 16) { 00804 max = L_MAX(max, word >> 16); 00805 max = L_MAX(max, word & 0xffff); 00806 } else { /* d == 32 */ 00807 max = L_MAX(max, word); 00808 } 00809 } 00810 } 00811 00812 /* Map to the full dynamic range of 8 bpp output */ 00813 if (d == 4) { 00814 if (type == L_LINEAR_SCALE) { 00815 factor = 255. / (l_float32)max; 00816 for (i = 0; i < h; i++) { 00817 lines = datas + i * wpls; 00818 lined = datad + i * wpld; 00819 for (j = 0; j < w; j++) { 00820 sval = GET_DATA_QBIT(lines, j); 00821 dval = (l_uint8)(factor * (l_float32)sval + 0.5); 00822 SET_DATA_QBIT(lined, j, dval); 00823 } 00824 } 00825 } else { /* type == L_LOG_SCALE) */ 00826 tab = makeLogBase2Tab(); 00827 factor = 255. / getLogBase2(max, tab); 00828 for (i = 0; i < h; i++) { 00829 lines = datas + i * wpls; 00830 lined = datad + i * wpld; 00831 for (j = 0; j < w; j++) { 00832 sval = GET_DATA_QBIT(lines, j); 00833 dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5); 00834 SET_DATA_BYTE(lined, j, dval); 00835 } 00836 } 00837 FREE(tab); 00838 } 00839 } else if (d == 8) { 00840 if (type == L_LINEAR_SCALE) { 00841 factor = 255. / (l_float32)max; 00842 for (i = 0; i < h; i++) { 00843 lines = datas + i * wpls; 00844 lined = datad + i * wpld; 00845 for (j = 0; j < w; j++) { 00846 sval = GET_DATA_BYTE(lines, j); 00847 dval = (l_uint8)(factor * (l_float32)sval + 0.5); 00848 SET_DATA_BYTE(lined, j, dval); 00849 } 00850 } 00851 } else { /* type == L_LOG_SCALE) */ 00852 tab = makeLogBase2Tab(); 00853 factor = 255. / getLogBase2(max, tab); 00854 for (i = 0; i < h; i++) { 00855 lines = datas + i * wpls; 00856 lined = datad + i * wpld; 00857 for (j = 0; j < w; j++) { 00858 sval = GET_DATA_BYTE(lines, j); 00859 dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5); 00860 SET_DATA_BYTE(lined, j, dval); 00861 } 00862 } 00863 FREE(tab); 00864 } 00865 } else if (d == 16) { 00866 if (type == L_LINEAR_SCALE) { 00867 factor = 255. / (l_float32)max; 00868 for (i = 0; i < h; i++) { 00869 lines = datas + i * wpls; 00870 lined = datad + i * wpld; 00871 for (j = 0; j < w; j++) { 00872 sval = GET_DATA_TWO_BYTES(lines, j); 00873 dval = (l_uint8)(factor * (l_float32)sval + 0.5); 00874 SET_DATA_BYTE(lined, j, dval); 00875 } 00876 } 00877 } else { /* type == L_LOG_SCALE) */ 00878 tab = makeLogBase2Tab(); 00879 factor = 255. / getLogBase2(max, tab); 00880 for (i = 0; i < h; i++) { 00881 lines = datas + i * wpls; 00882 lined = datad + i * wpld; 00883 for (j = 0; j < w; j++) { 00884 sval = GET_DATA_TWO_BYTES(lines, j); 00885 dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5); 00886 SET_DATA_BYTE(lined, j, dval); 00887 } 00888 } 00889 FREE(tab); 00890 } 00891 } else { /* d == 32 */ 00892 if (type == L_LINEAR_SCALE) { 00893 factor = 255. / (l_float32)max; 00894 for (i = 0; i < h; i++) { 00895 lines = datas + i * wpls; 00896 lined = datad + i * wpld; 00897 for (j = 0; j < w; j++) { 00898 sval = lines[j]; 00899 dval = (l_uint8)(factor * (l_float32)sval + 0.5); 00900 SET_DATA_BYTE(lined, j, dval); 00901 } 00902 } 00903 } else { /* type == L_LOG_SCALE) */ 00904 tab = makeLogBase2Tab(); 00905 factor = 255. / getLogBase2(max, tab); 00906 for (i = 0; i < h; i++) { 00907 lines = datas + i * wpls; 00908 lined = datad + i * wpld; 00909 for (j = 0; j < w; j++) { 00910 sval = lines[j]; 00911 dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5); 00912 SET_DATA_BYTE(lined, j, dval); 00913 } 00914 } 00915 FREE(tab); 00916 } 00917 } 00918 00919 return pixd; 00920 } 00921 00922 00923 /*-----------------------------------------------------------------------* 00924 * Log base2 lookup * 00925 *-----------------------------------------------------------------------*/ 00926 /* 00927 * makeLogBase2Tab() 00928 * 00929 * Input: void 00930 * Return: table (giving the log[base 2] of val) 00931 */ 00932 l_float32 * 00933 makeLogBase2Tab(void) 00934 { 00935 l_int32 i; 00936 l_float32 log2; 00937 l_float32 *tab; 00938 00939 PROCNAME("makeLogBase2Tab"); 00940 00941 if ((tab = (l_float32 *)CALLOC(256, sizeof(l_float32))) == NULL) 00942 return (l_float32 *)ERROR_PTR("tab not made", procName, NULL); 00943 00944 log2 = (l_float32)log((l_float32)2); 00945 for (i = 0; i < 256; i++) 00946 tab[i] = (l_float32)log((l_float32)i) / log2; 00947 00948 return tab; 00949 } 00950 00951 00952 /* 00953 * getLogBase2() 00954 * 00955 * Input: val 00956 * logtab (256-entry table of logs) 00957 * Return: logdist, or 0 on error 00958 */ 00959 l_float32 00960 getLogBase2(l_int32 val, 00961 l_float32 *logtab) 00962 { 00963 PROCNAME("getLogBase2"); 00964 00965 if (!logtab) 00966 return ERROR_INT("logtab not defined", procName, 0); 00967 00968 if (val < 0x100) 00969 return logtab[val]; 00970 else if (val < 0x10000) 00971 return 8.0 + logtab[val >> 8]; 00972 else if (val < 0x1000000) 00973 return 16.0 + logtab[val >> 16]; 00974 else 00975 return 24.0 + logtab[val >> 24]; 00976 } 00977