00001 /*!@file Image/c_integer_math_ops.c Fixed-point integer math versions of some of our floating-point Image functions */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/c_integer_math_ops.c $ 00035 // $Id: c_integer_math_ops.c 7848 2007-02-07 17:46:06Z rjpeters $ 00036 // 00037 00038 #ifndef IMAGE_C_INTEGER_MATH_OPS_C_DEFINED 00039 #define IMAGE_C_INTEGER_MATH_OPS_C_DEFINED 00040 00041 #include "Image/c_integer_math_ops.h" 00042 00043 #include "Util/Assert.H" 00044 00045 // ###################################################################### 00046 void c_intg_low_pass_5_x_dec_x_manybits(const int* src, 00047 const int w, const int h, 00048 int* dst, 00049 const int w2) 00050 { 00051 if (w == 2) ////////////////////////////////////////////////// 00052 for (int j = 0; j < h; ++j) 00053 { 00054 // leftmost point [ (6^) 4 ] / 10 00055 *dst++ = (src[0] / 10) * 6 + (src[1] / 10) * 4; 00056 00057 src += 2; // src back to same position as dst 00058 } 00059 else if (w == 3) ////////////////////////////////////////////////// 00060 for (int j = 0; j < h; ++j) 00061 { 00062 // need the left most point in any case 00063 // leftmost point [ (6^) 4 1 ] / 11 00064 *dst++ = 00065 (src[0] / 11) * 6 + 00066 (src[1] / 11) * 4 + 00067 (src[2] / 11) * 1; 00068 00069 src += 3; // src back to same position as dst 00070 } 00071 else ////////////////////////////// general case for width() >= 4 00072 // *** unfolded version (all particular cases treated) for 00073 // max speed. 00074 // notations: in () is the position of dest ptr, and ^ is src ptr 00075 // ########## horizontal pass 00076 for (int j = 0; j < h; ++j) 00077 { 00078 int i1 = 0, i2 = 0; 00079 const int* src2 = src; 00080 00081 // leftmost point [ (6^) 4 1 ] / 11 00082 *dst++ = 00083 (src2[0] / 11) * 6 + 00084 (src2[1] / 11) * 4 + 00085 (src2[2] / 11) * 1; 00086 ++i2; 00087 i1 += 2; 00088 00089 // skip second point 00090 00091 // rest of the line except last 2 points [ 1^ 4 (6) 4 1 ] / 16.0 00092 while ((i1 < (w-2)) && (i2 < w2)) 00093 { 00094 *dst++ = 00095 ((src2[0] >> 4) + (src2[4] >> 4)) * 1 + 00096 ((src2[1] >> 4) + (src2[3] >> 4)) * 4 + 00097 (src2[2] >> 4) * 6; 00098 i1 += 2; src2 += 2; 00099 ++i2; 00100 } 00101 00102 // need special case for second to last point? 00103 if ((i2 < w2) && (i1 == (w-2))) 00104 { 00105 src2 = src + w - 4; 00106 // before last point [ 1^ 4 (6) 4 ] / 15 00107 *dst++ = 00108 (src2[0] / 15) * 1 + 00109 (src2[1] / 15 + src2[3] / 15) * 4 + 00110 (src2[2] / 15) * 6; 00111 i1 += 2; 00112 ++i2; 00113 } 00114 00115 // need special case for last point? 00116 if ((i2 < w2) && (i1 == (w-1))) 00117 { 00118 src2 = src + w - 3; 00119 // last point [ 1^ 4 (6) ] / 11 00120 *dst++ = 00121 (src2[0] / 11) * 1 + 00122 (src2[1] / 11) * 4 + 00123 (src2[2] / 11) * 6; 00124 ++i2; 00125 } 00126 src += w; 00127 } 00128 } 00129 00130 // ###################################################################### 00131 void c_intg_low_pass_5_y_dec_y_manybits(const int* src, 00132 const int w, const int h, 00133 int* dst, 00134 const int h2) 00135 { 00136 const int* const src_end = src + w*h; 00137 00138 // ########## vertical pass (even though we scan horiz for speedup) 00139 const int w2 = w * 2, w3 = w * 3, w4 = w * 4; // speedup 00140 00141 if (h == 2) ////////////////////////////////////////////////// 00142 { 00143 // topmost points ( [ (6^) 4 ] / 10 )^T 00144 for (int i = 0; i < w; ++i) 00145 { 00146 *dst++ = 00147 (src[0] / 10) * 6 + 00148 (src[w] / 10) * 4; 00149 src++; 00150 } 00151 src -= w; // go back to top-left 00152 } 00153 else if (h == 3) ////////////////////////////////////////////////// 00154 { 00155 // topmost points ( [ (6^) 4 1 ] / 11 )^T 00156 for (int i = 0; i < w; ++i) 00157 { 00158 *dst++ = 00159 (src[ 0] / 11) * 6 + 00160 (src[ w] / 11) * 4 + 00161 (src[w2] / 11) * 1; 00162 src++; 00163 } 00164 src -= w; // go back to top-left 00165 } 00166 else ///////////////////////////////// general case for height >= 4 00167 { 00168 int i1 = 0, i2 = 0; 00169 00170 // topmost points ( [ (6^) 4 1 ] / 11 )^T 00171 for (int i = 0; i < w; ++i) 00172 { 00173 *dst++ = 00174 (src[ 0] / 11) * 6 + 00175 (src[ w] / 11) * 4 + 00176 (src[w2] / 11) * 1; 00177 src++; 00178 } 00179 src -= w; // go back to top-left 00180 ++i2; 00181 i1 += 2; 00182 00183 // second point skipped 00184 00185 // rest of the column except last 2 points ( [ 1^ 4 (6) 4 1 ] / 16 )T 00186 while ((i1 < (h-2)) && (i2 < h2)) 00187 { 00188 for (int i = 0; i < w; ++i) 00189 { 00190 *dst++ = 00191 ((src[ 0] >> 4) + (src[w4] >> 4)) * 1 + 00192 ((src[ w] >> 4) + (src[w3] >> 4)) * 4 + 00193 (src[w2] >> 4) * 6; 00194 src++; 00195 } 00196 src += w; 00197 i1 += 2; 00198 ++ i2; 00199 } 00200 00201 // need special case for second to last point? 00202 if ((i2 < h2) && (i1 == (h-2))) 00203 { 00204 src = src_end - w4; 00205 // before last points ( [ 1^ 4 (6) 4 ] / 15 )T 00206 for (int i = 0; i < w; ++i) 00207 { 00208 *dst++ = 00209 (src[ 0] / 15) * 1 + 00210 (src[ w] / 15 + src[w3] / 15) * 4 + 00211 (src[w2] / 15) * 6; 00212 src++; 00213 } 00214 i1 += 2; 00215 ++i2; 00216 } 00217 00218 // need special case for last point? 00219 if ((i2 < h2) && (i1 == (h-1))) 00220 { 00221 src = src_end - w3; 00222 // last points ( [ 1^ 4 (6) ] / 11 )T 00223 for (int i = 0; i < w; ++i) 00224 { 00225 *dst++ = 00226 (src[ 0] / 11) * 1 + 00227 (src[ w] / 11) * 4 + 00228 (src[w2] / 11) * 6; 00229 src++; 00230 } 00231 } 00232 } 00233 } 00234 00235 // ###################################################################### 00236 void c_intg_low_pass_5_x_dec_x_fewbits(const int* src, 00237 const int w, const int h, 00238 int* dst, 00239 const int w2) 00240 { 00241 if (w == 2) ////////////////////////////////////////////////// 00242 for (int j = 0; j < h; ++j) 00243 { 00244 // leftmost point [ (6^) 4 ] / 10 00245 *dst++ = 00246 (src[0] * 6 + 00247 src[1] * 4 00248 ) / 10; 00249 00250 src += 2; // src back to same position as dst 00251 } 00252 else if (w == 3) ////////////////////////////////////////////////// 00253 for (int j = 0; j < h; ++j) 00254 { 00255 // need the left most point in any case 00256 // leftmost point [ (6^) 4 1 ] / 11 00257 *dst++ = 00258 (src[0] * 6 + 00259 src[1] * 4 + 00260 src[2] * 1 00261 ) / 11; 00262 00263 src += 3; // src back to same position as dst 00264 } 00265 else ////////////////////////////// general case for width() >= 4 00266 // *** unfolded version (all particular cases treated) for 00267 // max speed. 00268 // notations: in () is the position of dest ptr, and ^ is src ptr 00269 // ########## horizontal pass 00270 for (int j = 0; j < h; ++j) 00271 { 00272 int i1 = 0, i2 = 0; 00273 const int* src2 = src; 00274 00275 // leftmost point [ (6^) 4 1 ] / 11 00276 *dst++ = 00277 (src2[0] * 6 + 00278 src2[1] * 4 + 00279 src2[2] * 1 00280 ) / 11; 00281 ++i2; 00282 i1 += 2; 00283 00284 // skip second point 00285 00286 // rest of the line except last 2 points [ 1^ 4 (6) 4 1 ] / 16.0 00287 while ((i1 < (w-2)) && (i2 < w2)) 00288 { 00289 *dst++ = 00290 ((src2[0] + src2[4]) * 1 + 00291 (src2[1] + src2[3]) * 4 + 00292 src2[2] * 6 00293 ) >> 4; 00294 i1 += 2; src2 += 2; 00295 ++i2; 00296 } 00297 00298 // need special case for second to last point? 00299 if ((i2 < w2) && (i1 == (w-2))) 00300 { 00301 src2 = src + w - 4; 00302 // before last point [ 1^ 4 (6) 4 ] / 15 00303 *dst++ = 00304 (src2[0] * 1 + 00305 (src2[1] + src2[3]) * 4 + 00306 src2[2] * 6 00307 ) / 15; 00308 i1 += 2; 00309 ++i2; 00310 } 00311 00312 // need special case for last point? 00313 if ((i2 < w2) && (i1 == (w-1))) 00314 { 00315 src2 = src + w - 3; 00316 // last point [ 1^ 4 (6) ] / 11 00317 *dst++ = 00318 (src2[0] * 1 + 00319 src2[1] * 4 + 00320 src2[2] * 6 00321 ) / 11; 00322 ++i2; 00323 } 00324 src += w; 00325 } 00326 } 00327 00328 // ###################################################################### 00329 void c_intg_low_pass_5_y_dec_y_fewbits(const int* src, 00330 const int w, const int h, 00331 int* dst, 00332 const int h2) 00333 { 00334 const int* const src_end = src + w*h; 00335 00336 // ########## vertical pass (even though we scan horiz for speedup) 00337 const int w2 = w * 2, w3 = w * 3, w4 = w * 4; // speedup 00338 00339 if (h == 2) ////////////////////////////////////////////////// 00340 { 00341 // topmost points ( [ (6^) 4 ] / 10 )^T 00342 for (int i = 0; i < w; ++i) 00343 { 00344 *dst++ = 00345 (src[0] * 6 + 00346 src[w] * 4 00347 ) / 10; 00348 src++; 00349 } 00350 src -= w; // go back to top-left 00351 } 00352 else if (h == 3) ////////////////////////////////////////////////// 00353 { 00354 // topmost points ( [ (6^) 4 1 ] / 11 )^T 00355 for (int i = 0; i < w; ++i) 00356 { 00357 *dst++ = 00358 (src[ 0] * 6 + 00359 src[ w] * 4 + 00360 src[w2] * 1 00361 ) / 11; 00362 src++; 00363 } 00364 src -= w; // go back to top-left 00365 } 00366 else ///////////////////////////////// general case for height >= 4 00367 { 00368 int i1 = 0, i2 = 0; 00369 00370 // topmost points ( [ (6^) 4 1 ] / 11 )^T 00371 for (int i = 0; i < w; ++i) 00372 { 00373 *dst++ = 00374 (src[ 0] * 6 + 00375 src[ w] * 4 + 00376 src[w2] * 1 00377 ) / 11; 00378 src++; 00379 } 00380 src -= w; // go back to top-left 00381 ++i2; 00382 i1 += 2; 00383 00384 // second point skipped 00385 00386 // rest of the column except last 2 points ( [ 1^ 4 (6) 4 1 ] / 16 )T 00387 while ((i1 < (h-2)) && (i2 < h2)) 00388 { 00389 for (int i = 0; i < w; ++i) 00390 { 00391 *dst++ = 00392 ((src[ 0] + src[w4]) * 1 + 00393 (src[ w] + src[w3]) * 4 + 00394 src[w2] * 6 00395 ) >> 4; 00396 src++; 00397 } 00398 src += w; 00399 i1 += 2; 00400 ++ i2; 00401 } 00402 00403 // need special case for second to last point? 00404 if ((i2 < h2) && (i1 == (h-2))) 00405 { 00406 src = src_end - w4; 00407 // before last points ( [ 1^ 4 (6) 4 ] / 15 )T 00408 for (int i = 0; i < w; ++i) 00409 { 00410 *dst++ = 00411 (src[ 0] * 1 + 00412 (src[ w] + src[w3]) * 4 + 00413 src[w2] * 6 00414 ) / 15; 00415 src++; 00416 } 00417 i1 += 2; 00418 ++i2; 00419 } 00420 00421 // need special case for last point? 00422 if ((i2 < h2) && (i1 == (h-1))) 00423 { 00424 src = src_end - w3; 00425 // last points ( [ 1^ 4 (6) ] / 11 )T 00426 for (int i = 0; i < w; ++i) 00427 { 00428 *dst++ = 00429 (src[ 0] * 1 + 00430 src[ w] * 4 + 00431 src[w2] * 6 00432 ) / 11; 00433 src++; 00434 } 00435 } 00436 } 00437 } 00438 00439 #define LP5_APPROX_LEVEL 0 00440 00441 #if LP5_APPROX_LEVEL == 0 00442 00443 # define LP5_APPROX_2_3 2 00444 # define LP5_APPROX_1_3 1 00445 # define LP5_DIV_3 / 3 00446 00447 #elif LP5_APPROX_LEVEL == 1 00448 00449 # define LP5_APPROX_2_3 1 00450 # define LP5_APPROX_1_3 1 00451 # define LP5_DIV_3 / 2 00452 00453 #else 00454 #error bogus LP5_APPROX_LEVEL (must be 0 or 1) 00455 #endif 00456 00457 // ###################################################################### 00458 void c_intg_low_pass_5_x_dec_x_fewbits_optim(const int* src, 00459 const int w, const int h, 00460 int* dst, 00461 const int w2) 00462 { 00463 ASSERT(w2 == w/2); 00464 00465 if (w == 2) ////////////////////////////////////////////////// 00466 for (int j = 0; j < h; ++j) 00467 { 00468 // leftmost point [ (6^) 4 ] / 10 00469 *dst++ = 00470 (src[0] * 3 + 00471 src[1] * 2 00472 ) / 5; 00473 00474 src += 2; // src back to same position as dst 00475 } 00476 else if (w == 3) ////////////////////////////////////////////////// 00477 for (int j = 0; j < h; ++j) 00478 { 00479 // need the left most point in any case 00480 // leftmost point [ (6^) 4 1 ] / 11 00481 *dst++ = 00482 (src[0] * 6 + 00483 src[1] * 4 + 00484 src[2] * 1 00485 ) / 11; 00486 00487 src += 3; // src back to same position as dst 00488 } 00489 else ////////////////////////////// general case for width() >= 4 00490 // *** unfolded version (all particular cases treated) for 00491 // max speed. 00492 // notations: in () is the position of dest ptr, and ^ is src ptr 00493 // ########## horizontal pass 00494 for (int j = 0; j < h; ++j) 00495 { 00496 const int* src2 = src; 00497 00498 // leftmost point [ (8^) 4 ] / 12 00499 *dst++ = 00500 (src2[0] * LP5_APPROX_2_3 + 00501 src2[1] * LP5_APPROX_1_3 00502 ) LP5_DIV_3; 00503 00504 // skip second point 00505 00506 // rest of the line except last 2 points [ .^ 4 (8) 4 ] / 16 00507 for (int i = 0; i < w-3; i += 2) 00508 { 00509 *dst++ = 00510 ((src2[1] + src2[3]) + 00511 src2[2] * 2 00512 ) >> 2; 00513 src2 += 2; 00514 } 00515 00516 src += w; 00517 } 00518 } 00519 00520 // ###################################################################### 00521 void c_intg_low_pass_5_y_dec_y_fewbits_optim(const int* src, 00522 const int w, const int h, 00523 int* dst, 00524 const int h2) 00525 { 00526 ASSERT(h2 == h/2); 00527 00528 // ########## vertical pass (even though we scan horiz for speedup) 00529 const int w2 = w * 2, w3 = w * 3; // speedup 00530 00531 if (h == 2) ////////////////////////////////////////////////// 00532 { 00533 // topmost points ( [ (6^) 4 ] / 10 )^T 00534 for (int i = 0; i < w; ++i) 00535 { 00536 *dst++ = 00537 (src[0] * 3 + 00538 src[w] * 2 00539 ) / 5; 00540 src++; 00541 } 00542 src -= w; // go back to top-left 00543 } 00544 else if (h == 3) ////////////////////////////////////////////////// 00545 { 00546 // topmost points ( [ (6^) 4 1 ] / 11 )^T 00547 for (int i = 0; i < w; ++i) 00548 { 00549 *dst++ = 00550 (src[ 0] * 6 + 00551 src[ w] * 4 + 00552 src[w2] * 1 00553 ) / 11; 00554 src++; 00555 } 00556 src -= w; // go back to top-left 00557 } 00558 else ///////////////////////////////// general case for height >= 4 00559 { 00560 // topmost points ( [ (8^) 4 ] / 12 )^T 00561 for (int k = 0; k < w; ++k) 00562 { 00563 *dst++ = 00564 (src[ 0] * LP5_APPROX_2_3 + 00565 src[ w] * LP5_APPROX_1_3 00566 ) LP5_DIV_3; 00567 src++; 00568 } 00569 src -= w; // go back to top-left 00570 00571 // second point skipped 00572 00573 // rest of the column except last 2 points ( [ .^ 4 (8) 4 ] / 16 )T 00574 for (int i = 0; i < h-3; i += 2) 00575 { 00576 for (int k = 0; k < w; ++k) 00577 { 00578 *dst++ = 00579 ((src[ w] + src[w3]) + 00580 src[w2] * 2 00581 ) >> 2; 00582 src++; 00583 } 00584 src += w; 00585 } 00586 } 00587 } 00588 00589 // ###################################################################### 00590 void c_intg_low_pass_9_x_manybits(const int* src, 00591 const int w, const int h, 00592 int* dst) 00593 { 00594 ASSERT(w >= 9); 00595 00596 // boundary conditions: truncated filter 00597 for (int j = 0; j < h; ++j) 00598 { 00599 // leftmost points 00600 *dst++ = 00601 (src[0] / 163) * 70 + 00602 (src[1] / 163) * 56 + 00603 (src[2] / 163) * 28 + 00604 (src[3] / 163) * 8 + 00605 (src[4] / 163) * 1; 00606 *dst++ = 00607 (src[0] / 219 + src[2] / 219) * 56 + 00608 (src[1] / 219) * 70 + 00609 (src[3] / 219) * 28 + 00610 (src[4] / 219) * 8 + 00611 (src[5] / 219) * 1; 00612 *dst++ = 00613 (src[0] / 247 + src[4] / 247) * 28 + 00614 (src[1] / 247 + src[3] / 247) * 56 + 00615 (src[2] / 247) * 70 + 00616 (src[5] / 247) * 8 + 00617 (src[6] / 247) * 1; 00618 *dst++ = 00619 (src[0] / 255 + src[6] / 255) * 8 + 00620 (src[1] / 255 + src[5] / 255) * 28 + 00621 (src[2] / 255 + src[4] / 255) * 56 + 00622 (src[3] / 255) * 70 + 00623 (src[7] / 255) * 1; 00624 00625 // far from the borders 00626 for (int i = 0; i < w - 8; ++i) 00627 { 00628 *dst++ = 00629 ((src[0] >> 8) + (src[8] >> 8)) * 1 + 00630 ((src[1] >> 8) + (src[7] >> 8)) * 8 + 00631 ((src[2] >> 8) + (src[6] >> 8)) * 28 + 00632 ((src[3] >> 8) + (src[5] >> 8)) * 56 + 00633 (src[4] >> 8) * 70; 00634 ++src; 00635 } 00636 00637 // rightmost points 00638 *dst++ = 00639 (src[0] / 255) * 1 + 00640 (src[1] / 255 + src[7] / 255) * 8 + 00641 (src[2] / 255 + src[6] / 255) * 28 + 00642 (src[3] / 255 + src[5] / 255) * 56 + 00643 (src[4] / 255) * 70; 00644 ++src; 00645 *dst++ = 00646 (src[0] / 247) * 1 + 00647 (src[1] / 247) * 8 + 00648 (src[2] / 247 + src[6] / 247) * 28 + 00649 (src[3] / 247 + src[5] / 247) * 56 + 00650 (src[4] / 247) * 70; 00651 ++src; 00652 *dst++ = 00653 (src[0] / 219) * 1 + 00654 (src[1] / 219) * 8 + 00655 (src[2] / 219) * 28 + 00656 (src[3] / 219 + src[5] / 219) * 56 + 00657 (src[4] / 219) * 70; 00658 ++src; 00659 *dst++ = 00660 (src[0] / 163) * 1 + 00661 (src[1] / 163) * 8 + 00662 (src[2] / 163) * 28 + 00663 (src[3] / 163) * 56 + 00664 (src[4] / 163) * 70; 00665 src += 5; // src back to same as dst (start of next line) 00666 } 00667 } 00668 00669 // ###################################################################### 00670 void c_intg_low_pass_9_y_manybits(const int* src, 00671 const int w, const int h, 00672 int* dst) 00673 { 00674 ASSERT(h >= 9); 00675 00676 // *** vertical pass *** 00677 const int w2 = w + w, w3 = w2 + w, w4 = w3 + w, w5 = w4 + w, w6 = w5 + w, 00678 w7 = w6 + w, w8 = w7 + w; // index computation speedup 00679 for (int i = 0; i < w; ++i) 00680 { 00681 *dst++ = 00682 (src[ 0] / 163) * 70 + 00683 (src[ w] / 163) * 56 + 00684 (src[w2] / 163) * 28 + 00685 (src[w3] / 163) * 8 + 00686 (src[w4] / 163) * 1; 00687 ++src; 00688 } 00689 src -= w; // back to top-left 00690 for (int i = 0; i < w; ++i) 00691 { 00692 *dst++ = 00693 (src[ 0] / 219 + src[w2] / 219) * 56 + 00694 (src[ w] / 219) * 70 + 00695 (src[w3] / 219) * 28 + 00696 (src[w4] / 219) * 8 + 00697 (src[w5] / 219) * 1; 00698 ++src; 00699 } 00700 src -= w; // back to top-left 00701 for (int i = 0; i < w; ++i) 00702 { 00703 *dst++ = 00704 (src[ 0] / 247 + src[w4] / 247) * 28 + 00705 (src[ w] / 247 + src[w3] / 247) * 56 + 00706 (src[w2] / 247) * 70 + 00707 (src[w5] / 247) * 8 + 00708 (src[w6] / 247) * 1; 00709 ++src; 00710 } 00711 src -= w; // back to top-left 00712 for (int i = 0; i < w; ++i) 00713 { 00714 *dst++ = 00715 (src[ 0] / 255 + src[w6] / 255) * 8 + 00716 (src[ w] / 255 + src[w5] / 255) * 28 + 00717 (src[w2] / 255 + src[w4] / 255) * 56 + 00718 (src[w3] / 255) * 70 + 00719 (src[w7] / 255) * 1; 00720 ++src; 00721 } 00722 src -= w; // back to top-left 00723 for (int j = 0; j < h - 8; j ++) 00724 for (int i = 0; i < w; ++i) 00725 { 00726 *dst++ = 00727 ((src[ 0] >> 8) + (src[w8] >> 8)) * 1 + 00728 ((src[ w] >> 8) + (src[w7] >> 8)) * 8 + 00729 ((src[w2] >> 8) + (src[w6] >> 8)) * 28 + 00730 ((src[w3] >> 8) + (src[w5] >> 8)) * 56 + 00731 (src[w4] >> 8) * 70; 00732 ++src; 00733 } 00734 for (int i = 0; i < w; ++i) 00735 { 00736 *dst++ = 00737 (src[ 0] / 255) * 1 + 00738 (src[ w] / 255 + src[w7] / 255) * 8 + 00739 (src[w2] / 255 + src[w6] / 255) * 28 + 00740 (src[w3] / 255 + src[w5] / 255) * 56 + 00741 (src[w4] / 255) * 70; 00742 ++src; 00743 } 00744 for (int i = 0; i < w; ++i) 00745 { 00746 *dst++ = 00747 (src[ 0] / 247) * 1 + 00748 (src[ w] / 247) * 8 + 00749 (src[w2] / 247 + src[w6] / 247) * 28 + 00750 (src[w3] / 247 + src[w5] / 247) * 56 + 00751 (src[w4] / 247) * 70; 00752 ++src; 00753 } 00754 for (int i = 0; i < w; ++i) 00755 { 00756 *dst++ = 00757 (src[ 0] / 219) * 1 + 00758 (src[ w] / 219) * 8 + 00759 (src[w2] / 219) * 28 + 00760 (src[w3] / 219 + src[w5] / 219) * 56 + 00761 (src[w4] / 219) * 70; 00762 ++src; 00763 } 00764 for (int i = 0; i < w; ++i) 00765 { 00766 *dst++ = 00767 (src[ 0] / 163) * 1 + 00768 (src[ w] / 163) * 8 + 00769 (src[w2] / 163) * 28 + 00770 (src[w3] / 163) * 56 + 00771 (src[w4] / 163) * 70; 00772 ++src; 00773 } 00774 } 00775 00776 // ###################################################################### 00777 void c_intg_low_pass_9_x_fewbits(const int* src, 00778 const int w, const int h, 00779 int* dst) 00780 { 00781 ASSERT(w >= 9); 00782 00783 // boundary conditions: truncated filter 00784 for (int j = 0; j < h; ++j) 00785 { 00786 // leftmost points 00787 *dst++ = 00788 (src[0] * 70 + 00789 src[1] * 56 + 00790 src[2] * 28 + 00791 src[3] * 8 + 00792 src[4] * 1 00793 ) / 163; 00794 *dst++ = 00795 ((src[0] + src[2]) * 56 + 00796 src[1] * 70 + 00797 src[3] * 28 + 00798 src[4] * 8 + 00799 src[5] * 1 00800 ) / 219; 00801 *dst++ = 00802 ((src[0] + src[4]) * 28 + 00803 (src[1] + src[3]) * 56 + 00804 src[2] * 70 + 00805 src[5] * 8 + 00806 src[6] * 1 00807 ) / 247; 00808 *dst++ = 00809 ((src[0] + src[6]) * 8 + 00810 (src[1] + src[5]) * 28 + 00811 (src[2] + src[4]) * 56 + 00812 src[3] * 70 + 00813 src[7] * 1 00814 ) / 255; 00815 00816 // far from the borders 00817 for (int i = 0; i < w - 8; ++i) 00818 { 00819 *dst++ = 00820 ((src[0] + src[8]) * 1 + 00821 (src[1] + src[7]) * 8 + 00822 (src[2] + src[6]) * 28 + 00823 (src[3] + src[5]) * 56 + 00824 src[4] * 70 00825 ) >> 8; 00826 ++src; 00827 } 00828 00829 // rightmost points 00830 *dst++ = 00831 (src[0] * 1 + 00832 (src[1] + src[7]) * 8 + 00833 (src[2] + src[6]) * 28 + 00834 (src[3] + src[5]) * 56 + 00835 src[4] * 70 00836 ) / 255; 00837 ++src; 00838 *dst++ = 00839 (src[0] * 1 + 00840 src[1] * 8 + 00841 (src[2] + src[6]) * 28 + 00842 (src[3] + src[5]) * 56 + 00843 src[4] * 70 00844 ) / 247; 00845 ++src; 00846 *dst++ = 00847 (src[0] * 1 + 00848 src[1] * 8 + 00849 src[2] * 28 + 00850 (src[3] + src[5]) * 56 + 00851 src[4] * 70 00852 ) / 219; 00853 ++src; 00854 *dst++ = 00855 (src[0] * 1 + 00856 src[1] * 8 + 00857 src[2] * 28 + 00858 src[3] * 56 + 00859 src[4] * 70 00860 ) / 163; 00861 src += 5; // src back to same as dst (start of next line) 00862 } 00863 } 00864 00865 // ###################################################################### 00866 void c_intg_low_pass_9_y_fewbits(const int* src, 00867 const int w, const int h, 00868 int* dst) 00869 { 00870 ASSERT(h >= 9); 00871 00872 // *** vertical pass *** 00873 const int w2 = w + w, w3 = w2 + w, w4 = w3 + w, w5 = w4 + w, w6 = w5 + w, 00874 w7 = w6 + w, w8 = w7 + w; // index computation speedup 00875 for (int i = 0; i < w; ++i) 00876 { 00877 *dst++ = 00878 (src[ 0] * 70 + 00879 src[ w] * 56 + 00880 src[w2] * 28 + 00881 src[w3] * 8 + 00882 src[w4] * 1 00883 ) / 163; 00884 ++src; 00885 } 00886 src -= w; // back to top-left 00887 for (int i = 0; i < w; ++i) 00888 { 00889 *dst++ = 00890 ((src[ 0] + src[w2]) * 56 + 00891 src[ w] * 70 + 00892 src[w3] * 28 + 00893 src[w4] * 8 + 00894 src[w5] * 1 00895 ) / 219; 00896 ++src; 00897 } 00898 src -= w; // back to top-left 00899 for (int i = 0; i < w; ++i) 00900 { 00901 *dst++ = 00902 ((src[ 0] + src[w4]) * 28 + 00903 (src[ w] + src[w3]) * 56 + 00904 src[w2] * 70 + 00905 src[w5] * 8 + 00906 src[w6] * 1 00907 ) / 247; 00908 ++src; 00909 } 00910 src -= w; // back to top-left 00911 for (int i = 0; i < w; ++i) 00912 { 00913 *dst++ = 00914 ((src[ 0] + src[w6]) * 8 + 00915 (src[ w] + src[w5]) * 28 + 00916 (src[w2] + src[w4]) * 56 + 00917 src[w3] * 70 + 00918 src[w7] * 1 00919 ) / 255; 00920 ++src; 00921 } 00922 src -= w; // back to top-left 00923 for (int j = 0; j < h - 8; j ++) 00924 for (int i = 0; i < w; ++i) 00925 { 00926 *dst++ = 00927 ((src[ 0] + src[w8]) * 1 + 00928 (src[ w] + src[w7]) * 8 + 00929 (src[w2] + src[w6]) * 28 + 00930 (src[w3] + src[w5]) * 56 + 00931 src[w4] * 70 00932 ) >> 8; 00933 ++src; 00934 } 00935 for (int i = 0; i < w; ++i) 00936 { 00937 *dst++ = 00938 (src[ 0] * 1 + 00939 (src[ w] + src[w7]) * 8 + 00940 (src[w2] + src[w6]) * 28 + 00941 (src[w3] + src[w5]) * 56 + 00942 src[w4] * 70 00943 ) / 255; 00944 ++src; 00945 } 00946 for (int i = 0; i < w; ++i) 00947 { 00948 *dst++ = 00949 (src[ 0] * 1 + 00950 src[ w] * 8 + 00951 (src[w2] + src[w6]) * 28 + 00952 (src[w3] + src[w5]) * 56 + 00953 src[w4] * 70 00954 ) / 247; 00955 ++src; 00956 } 00957 for (int i = 0; i < w; ++i) 00958 { 00959 *dst++ = 00960 (src[ 0] * 1 + 00961 src[ w] * 8 + 00962 src[w2] * 28 + 00963 (src[w3] + src[w5]) * 56 + 00964 src[w4] * 70 00965 ) / 219; 00966 ++src; 00967 } 00968 for (int i = 0; i < w; ++i) 00969 { 00970 *dst++ = 00971 (src[ 0] * 1 + 00972 src[ w] * 8 + 00973 src[w2] * 28 + 00974 src[w3] * 56 + 00975 src[w4] * 70 00976 ) / 163; 00977 ++src; 00978 } 00979 } 00980 00981 #define LP9_APPROX_LEVEL 0 00982 00983 #if LP9_APPROX_LEVEL == 0 00984 00985 # define LP9_APPROX_72_164 72 00986 # define LP9_APPROX_56_164 56 00987 # define LP9_APPROX_28_164 28 00988 # define LP9_APPROX_8_164 8 00989 # define LP9_DIV_164 / 164 00990 00991 # define LP9_APPROX_72_220 72 00992 # define LP9_APPROX_56_220 56 00993 # define LP9_APPROX_28_220 28 00994 # define LP9_APPROX_8_220 8 00995 # define LP9_DIV_220 / 220 00996 00997 # define LP9_APPROX_72_248 72 00998 # define LP9_APPROX_56_248 56 00999 # define LP9_APPROX_28_248 28 01000 # define LP9_APPROX_8_248 8 01001 # define LP9_DIV_248 / 248 01002 01003 #elif LP9_APPROX_LEVEL == 1 01004 01005 # define LP9_APPROX_72_164 28 01006 # define LP9_APPROX_56_164 22 01007 # define LP9_APPROX_28_164 11 01008 # define LP9_APPROX_8_164 3 01009 # define LP9_DIV_164 >> 6 01010 01011 # define LP9_APPROX_72_220 22 01012 # define LP9_APPROX_56_220 16 01013 # define LP9_APPROX_28_220 8 01014 # define LP9_APPROX_8_220 2 01015 # define LP9_DIV_220 >> 6 01016 01017 # define LP9_APPROX_72_248 20 01018 # define LP9_APPROX_56_248 14 01019 # define LP9_APPROX_28_248 7 01020 # define LP9_APPROX_8_248 2 01021 # define LP9_DIV_248 >> 6 01022 01023 #elif LP9_APPROX_LEVEL == 2 01024 01025 # define LP9_APPROX_72_164 8 01026 # define LP9_APPROX_56_164 (4+1) 01027 # define LP9_APPROX_28_164 2 01028 # define LP9_APPROX_8_164 1 01029 # define LP9_DIV_164 >> 4 01030 01031 # define LP9_APPROX_72_220 (4+1) 01032 # define LP9_APPROX_56_220 4 01033 # define LP9_APPROX_28_220 2 01034 # define LP9_APPROX_8_220 1 01035 # define LP9_DIV_220 >> 4 01036 01037 # define LP9_APPROX_72_248 (4+1) 01038 # define LP9_APPROX_56_248 3 01039 # define LP9_APPROX_28_248 2 01040 # define LP9_APPROX_8_248 1 01041 # define LP9_DIV_248 >> 4 01042 01043 #elif LP9_APPROX_LEVEL == 3 01044 01045 # define LP9_APPROX_72_164 0 01046 # define LP9_APPROX_56_164 0 01047 # define LP9_APPROX_28_164 0 01048 # define LP9_APPROX_8_164 0 01049 # define LP9_DIV_164 01050 01051 # define LP9_APPROX_72_220 0 01052 # define LP9_APPROX_56_220 0 01053 # define LP9_APPROX_28_220 0 01054 # define LP9_APPROX_8_220 0 01055 # define LP9_DIV_220 01056 01057 # define LP9_APPROX_72_248 0 01058 # define LP9_APPROX_56_248 0 01059 # define LP9_APPROX_28_248 0 01060 # define LP9_APPROX_8_248 0 01061 # define LP9_DIV_248 01062 01063 # define LP9_APPROX_SHIFTR 0 01064 01065 #else 01066 #error bogus LP9_APPROX_LEVEL (must be 0, 1, 2, or 3) 01067 #endif 01068 01069 // ###################################################################### 01070 void c_intg_low_pass_9_x_fewbits_optim(const int* src, 01071 const int w, const int h, 01072 int* dst) 01073 { 01074 ASSERT(w >= 9); 01075 01076 // boundary conditions: truncated filter 01077 for (int j = 0; j < h; ++j) 01078 { 01079 // leftmost points 01080 *dst++ = // [ (72^) 56 28 8 ] 01081 (src[0] * LP9_APPROX_72_164 + 01082 src[1] * LP9_APPROX_56_164 + 01083 src[2] * LP9_APPROX_28_164 + 01084 src[3] * LP9_APPROX_8_164 01085 ) LP9_DIV_164; 01086 *dst++ = // [ 56^ (72) 56 28 8 ] 01087 ((src[0] + src[2]) * LP9_APPROX_56_220 + 01088 src[1] * LP9_APPROX_72_220 + 01089 src[3] * LP9_APPROX_28_220 + 01090 src[4] * LP9_APPROX_8_220 01091 ) LP9_DIV_220; 01092 *dst++ = // [ 28^ 56 (72) 56 28 8 ] 01093 ((src[0] + src[4]) * LP9_APPROX_28_248 + 01094 (src[1] + src[3]) * LP9_APPROX_56_248 + 01095 src[2] * LP9_APPROX_72_248 + 01096 src[5] * LP9_APPROX_8_248 01097 ) LP9_DIV_248; 01098 01099 // far from the borders 01100 for (int i = 0; i < w - 6; ++i) 01101 { 01102 *dst++ = // [ 8^ 28 56 (72) 56 28 8 ] 01103 ((src[0] + src[6]) * 8 + 01104 (src[1] + src[5]) * 28 + 01105 (src[2] + src[4]) * 56 + 01106 src[3] * 72 01107 ) >> 8; 01108 ++src; 01109 } 01110 01111 // rightmost points 01112 *dst++ = // [ 8^ 28 56 (72) 56 28 ] 01113 (src[0] * LP9_APPROX_8_248 + 01114 (src[1] + src[5]) * LP9_APPROX_28_248 + 01115 (src[2] + src[4]) * LP9_APPROX_56_248 + 01116 src[3] * LP9_APPROX_72_248 01117 ) LP9_DIV_248; 01118 ++src; 01119 *dst++ = // [ 8^ 28 56 (72) 56 ] 01120 (src[0] * LP9_APPROX_8_220 + 01121 src[1] * LP9_APPROX_28_220 + 01122 (src[2] + src[4]) * LP9_APPROX_56_220 + 01123 src[3] * LP9_APPROX_72_220 01124 ) LP9_DIV_220; 01125 ++src; 01126 *dst++ = // [ 8^ 28 56 (72) ] 01127 (src[0] * LP9_APPROX_8_164 + 01128 src[1] * LP9_APPROX_28_164 + 01129 src[2] * LP9_APPROX_56_164 + 01130 src[3] * LP9_APPROX_72_164 01131 ) LP9_DIV_164; 01132 src += 4; // src back to same as dst (start of next line) 01133 } 01134 } 01135 01136 // ###################################################################### 01137 void c_intg_low_pass_9_y_fewbits_optim(const int* src, 01138 const int w, const int h, 01139 int* dst) 01140 { 01141 ASSERT(h >= 9); 01142 01143 // index computation speedup: 01144 const int w2 = w + w, w3 = w2 + w, w4 = w3 + w, w5 = w4 + w, w6 = w5 + w; 01145 01146 // *** vertical pass *** 01147 for (int i = 0; i < w; ++i) 01148 { 01149 *dst++ = 01150 (src[ 0] * LP9_APPROX_72_164 + 01151 src[ w] * LP9_APPROX_56_164 + 01152 src[w2] * LP9_APPROX_28_164 + 01153 src[w3] * LP9_APPROX_8_164 01154 ) LP9_DIV_164; 01155 ++src; 01156 } 01157 src -= w; // back to top-left 01158 for (int i = 0; i < w; ++i) 01159 { 01160 *dst++ = 01161 ((src[ 0] + src[w2]) * LP9_APPROX_56_220 + 01162 src[ w] * LP9_APPROX_72_220 + 01163 src[w3] * LP9_APPROX_28_220 + 01164 src[w4] * LP9_APPROX_8_220 01165 ) LP9_DIV_220; 01166 ++src; 01167 } 01168 src -= w; // back to top-left 01169 for (int i = 0; i < w; ++i) 01170 { 01171 *dst++ = 01172 ((src[ 0] + src[w4]) * LP9_APPROX_28_248 + 01173 (src[ w] + src[w3]) * LP9_APPROX_56_248 + 01174 src[w2] * LP9_APPROX_72_248 + 01175 src[w5] * LP9_APPROX_8_248 01176 ) LP9_DIV_248; 01177 ++src; 01178 } 01179 src -= w; // back to top-left 01180 01181 for (int j = 0; j < h - 6; j ++) 01182 for (int i = 0; i < w; ++i) 01183 { 01184 *dst++ = 01185 ((src[ 0] + src[w6]) * 8 + 01186 (src[ w] + src[w5]) * 28 + 01187 (src[w2] + src[w4]) * 56 + 01188 src[w3] * 72 01189 ) >> 8; 01190 ++src; 01191 } 01192 01193 for (int i = 0; i < w; ++i) 01194 { 01195 *dst++ = 01196 (src[ 0] * LP9_APPROX_8_248 + 01197 (src[ w] + src[w5]) * LP9_APPROX_28_248 + 01198 (src[w2] + src[w4]) * LP9_APPROX_56_248 + 01199 src[w3] * LP9_APPROX_72_248 01200 ) LP9_DIV_248; 01201 ++src; 01202 } 01203 for (int i = 0; i < w; ++i) 01204 { 01205 *dst++ = 01206 (src[ 0] * LP9_APPROX_8_220 + 01207 src[ w] * LP9_APPROX_28_220 + 01208 (src[w2] + src[w4]) * LP9_APPROX_56_220 + 01209 src[w3] * LP9_APPROX_72_220 01210 ) LP9_DIV_220; 01211 ++src; 01212 } 01213 for (int i = 0; i < w; ++i) 01214 { 01215 *dst++ = 01216 (src[ 0] * LP9_APPROX_8_164 + 01217 src[ w] * LP9_APPROX_28_164 + 01218 src[w2] * LP9_APPROX_56_164 + 01219 src[w3] * LP9_APPROX_72_164 01220 ) LP9_DIV_164; 01221 ++src; 01222 } 01223 } 01224 01225 // ###################################################################### 01226 void c_intg_x_filter_clean_manybits(const int* src, 01227 const int w, const int h, 01228 const int* hf_flipped, const int hfs, 01229 const int shiftbits, 01230 int* dst) 01231 { 01232 ASSERT(w >= hfs); 01233 ASSERT(hfs > 0); 01234 01235 ASSERT(hfs & 1); 01236 const int hfs2 = (hfs - 1) / 2; 01237 01238 for (int jj = 0; jj < h; ++jj) 01239 { 01240 // leftmost points: 01241 for (int j = hfs2; j < hfs - 1; ++j) 01242 { 01243 const int fp = hfs - 1 - j; 01244 int sum = 0; 01245 for (int k = 0; k <= j; k ++) 01246 sum += hf_flipped[fp + k]; 01247 01248 int val = 0; 01249 for (int k = 0; k <= j; k ++) 01250 val += (src[k] / sum) * hf_flipped[fp + k]; 01251 01252 *dst++ = val; 01253 } 01254 01255 // bulk (far from the borders): 01256 for (int i = 0; i < w - hfs + 1; ++i) 01257 { 01258 int val = 0; 01259 for (int k = 0; k < hfs; k ++) 01260 val += (src[k] >> shiftbits) * hf_flipped[k]; 01261 *dst++ = val; 01262 src++; 01263 } 01264 01265 // rightmost points: 01266 for (int j = hfs - 2; j >= hfs2; j --) 01267 { 01268 int sum = 0; 01269 for (int k = 0; k <= j; k ++) 01270 sum += hf_flipped[k]; 01271 01272 int val = 0; 01273 for (int k = 0; k <= j; k ++) 01274 val += (src[k] / sum) * hf_flipped[k]; 01275 01276 *dst++ = val; 01277 src++; 01278 } 01279 src += hfs2; // src back to same as dst (start of next line) 01280 } 01281 } 01282 01283 // ###################################################################### 01284 void c_intg_x_filter_clean_fewbits(const int* src, 01285 const int w, const int h, 01286 const int* hf_flipped, const int hfs, 01287 const int shiftbits, 01288 int* dst) 01289 { 01290 ASSERT(w >= hfs); 01291 ASSERT(hfs > 0); 01292 01293 ASSERT(hfs & 1); 01294 const int hfs2 = (hfs - 1) / 2; 01295 01296 for (int jj = 0; jj < h; ++jj) 01297 { 01298 // leftmost points: 01299 for (int j = hfs2; j < hfs - 1; ++j) 01300 { 01301 const int fp = hfs - 1 - j; 01302 int sum = 0; 01303 int val = 0; 01304 for (int k = 0; k <= j; k ++) 01305 { 01306 val += src[k] * hf_flipped[fp + k]; 01307 sum += hf_flipped[fp + k]; 01308 } 01309 01310 *dst++ = val / sum; 01311 } 01312 01313 // bulk (far from the borders): 01314 for (int i = 0; i < w - hfs + 1; ++i) 01315 { 01316 int val = 0; 01317 for (int k = 0; k < hfs; k ++) 01318 val += src[k] * hf_flipped[k]; 01319 *dst++ = (val >> shiftbits); 01320 src++; 01321 } 01322 01323 // rightmost points: 01324 for (int j = hfs - 2; j >= hfs2; j --) 01325 { 01326 int sum = 0; 01327 int val = 0; 01328 for (int k = 0; k <= j; k ++) 01329 { 01330 val += src[k] * hf_flipped[k]; 01331 sum += hf_flipped[k]; 01332 } 01333 01334 *dst++ = val / sum; 01335 src++; 01336 } 01337 src += hfs2; // src back to same as dst (start of next line) 01338 } 01339 } 01340 01341 // ###################################################################### 01342 void c_intg_x_filter_clean_small_manybits(const int* src, 01343 const int w, const int h, 01344 const int* hf_flipped, const int hfs, 01345 const int shiftbits, 01346 int* dst) 01347 { 01348 ASSERT(w < hfs); 01349 ASSERT(hfs > 0); 01350 01351 ASSERT(hfs & 1); 01352 const int hfs2 = (hfs - 1) / 2; 01353 01354 for (int j = 0; j < h; ++j) 01355 for (int i = 0; i < w; ++i) 01356 { 01357 int sum = 0; 01358 for (int k = 0; k < hfs; k ++) 01359 if (i + k - hfs2 >= 0 && i + k - hfs2 < w) 01360 sum += hf_flipped[k]; 01361 01362 int val = 0; 01363 for (int k = 0; k < hfs; k ++) 01364 if (i + k - hfs2 >= 0 && i + k - hfs2 < w) 01365 val += (src[k - hfs2] / sum) * hf_flipped[k]; 01366 01367 *dst++ = val; 01368 src ++; 01369 } 01370 } 01371 01372 // ###################################################################### 01373 void c_intg_x_filter_clean_small_fewbits(const int* src, 01374 const int w, const int h, 01375 const int* hf_flipped, const int hfs, 01376 const int shiftbits, 01377 int* dst) 01378 { 01379 ASSERT(w < hfs); 01380 ASSERT(hfs > 0); 01381 01382 ASSERT(hfs & 1); 01383 const int hfs2 = (hfs - 1) / 2; 01384 01385 for (int j = 0; j < h; ++j) 01386 for (int i = 0; i < w; ++i) 01387 { 01388 int sum = 0; 01389 int val = 0; 01390 for (int k = 0; k < hfs; k ++) 01391 if (i + k - hfs2 >= 0 && i + k - hfs2 < w) 01392 { 01393 val += src[k - hfs2] * hf_flipped[k]; 01394 sum += hf_flipped[k]; 01395 } 01396 01397 *dst++ = val / sum; 01398 src ++; 01399 } 01400 } 01401 01402 // ###################################################################### 01403 void c_intg_y_filter_clean_manybits(const int* src, 01404 const int w, const int h, 01405 const int* vf_flipped, const int vfs, 01406 const int shiftbits, 01407 int* dst) 01408 { 01409 ASSERT(h >= vfs); 01410 ASSERT(vfs > 0); 01411 01412 ASSERT(vfs & 1); 01413 const int vfs2 = (vfs - 1) / 2; 01414 01415 int ww[vfs]; // precompute row offsets 01416 for (int x = 0; x < vfs; x ++) 01417 ww[x] = w * x; 01418 01419 // top points: 01420 for (int j = vfs2; j < vfs - 1; ++j) 01421 { 01422 int fp = vfs - 1 - j; 01423 for (int i = 0; i < w; ++i) // scan all points of given horiz 01424 { 01425 int sum = 0; 01426 for (int k = 0; k <= j; k ++) 01427 sum += vf_flipped[fp + k]; 01428 01429 int val = 0; 01430 for (int k = 0; k <= j; k ++) 01431 val += (src[ww[k]] / sum) * vf_flipped[fp + k]; 01432 01433 *dst++ = val; 01434 src++; 01435 } 01436 src -= w; // back to top-left corner 01437 } 01438 01439 // bulk (far from edges): 01440 for (int j = 0; j < h - vfs + 1; ++j) 01441 for (int i = 0; i < w; ++i) 01442 { 01443 int val = 0; 01444 for (int k = 0; k < vfs; k ++) 01445 val += (src[ww[k]] >> shiftbits) * vf_flipped[k]; 01446 *dst++ = val; 01447 src++; 01448 } 01449 01450 // bottommost points: 01451 for (int j = vfs - 2; j >= vfs2; j --) 01452 for (int i = 0; i < w; ++i) 01453 { 01454 int sum = 0; 01455 for (int k = 0; k <= j; k ++) 01456 sum += vf_flipped[k]; 01457 01458 int val = 0; 01459 for (int k = 0; k <= j; k ++) 01460 val += (src[ww[k]] / sum) * vf_flipped[k]; 01461 01462 *dst++ = val; 01463 ++src; 01464 } 01465 } 01466 01467 // ###################################################################### 01468 void c_intg_y_filter_clean_fewbits(const int* src, 01469 const int w, const int h, 01470 const int* vf_flipped, const int vfs, 01471 const int shiftbits, 01472 int* dst) 01473 { 01474 ASSERT(h >= vfs); 01475 ASSERT(vfs > 0); 01476 01477 ASSERT(vfs & 1); 01478 const int vfs2 = (vfs - 1) / 2; 01479 01480 int ww[vfs]; // precompute row offsets 01481 for (int x = 0; x < vfs; x ++) 01482 ww[x] = w * x; 01483 01484 // top points: 01485 for (int j = vfs2; j < vfs - 1; ++j) 01486 { 01487 int fp = vfs - 1 - j; 01488 for (int i = 0; i < w; ++i) // scan all points of given horiz 01489 { 01490 int sum = 0; 01491 int val = 0; 01492 for (int k = 0; k <= j; k ++) 01493 { 01494 val += src[ww[k]] * vf_flipped[fp + k]; 01495 sum += vf_flipped[fp + k]; 01496 } 01497 01498 *dst++ = val / sum; 01499 src++; 01500 } 01501 src -= w; // back to top-left corner 01502 } 01503 01504 // bulk (far from edges): 01505 for (int j = 0; j < h - vfs + 1; ++j) 01506 for (int i = 0; i < w; ++i) 01507 { 01508 int val = 0; 01509 for (int k = 0; k < vfs; k ++) 01510 val += src[ww[k]] * vf_flipped[k]; 01511 *dst++ = (val >> shiftbits); 01512 src++; 01513 } 01514 01515 // bottommost points: 01516 for (int j = vfs - 2; j >= vfs2; j --) 01517 for (int i = 0; i < w; ++i) 01518 { 01519 int sum = 0; 01520 int val = 0; 01521 for (int k = 0; k <= j; k ++) 01522 { 01523 val += src[ww[k]] * vf_flipped[k]; 01524 sum += vf_flipped[k]; 01525 } 01526 01527 *dst++ = val / sum; 01528 ++src; 01529 } 01530 } 01531 01532 // ###################################################################### 01533 void c_intg_y_filter_clean_small_manybits(const int* src, 01534 const int w, const int h, 01535 const int* vf_flipped, const int vfs, 01536 const int shiftbits, 01537 int* dst) 01538 { 01539 ASSERT(h < vfs); 01540 ASSERT(vfs > 0); 01541 01542 ASSERT(vfs & 1); 01543 const int vfs2 = (vfs - 1) / 2; 01544 01545 for (int j = 0; j < h; ++j) 01546 for (int i = 0; i < w; ++i) 01547 { 01548 int sum = 0; 01549 for (int k = 0; k < vfs; k ++) 01550 if (j + k - vfs2 >= 0 && j + k - vfs2 < h) 01551 sum += vf_flipped[k]; 01552 01553 int val = 0; 01554 for (int k = 0; k < vfs; k ++) 01555 if (j + k - vfs2 >= 0 && j + k - vfs2 < h) 01556 val += (src[w * (k - vfs2)] / sum) * vf_flipped[k]; 01557 01558 *dst++ = val; 01559 ++src; 01560 } 01561 } 01562 01563 // ###################################################################### 01564 void c_intg_y_filter_clean_small_fewbits(const int* src, 01565 const int w, const int h, 01566 const int* vf_flipped, const int vfs, 01567 const int shiftbits, 01568 int* dst) 01569 { 01570 ASSERT(h < vfs); 01571 ASSERT(vfs > 0); 01572 01573 ASSERT(vfs & 1); 01574 const int vfs2 = (vfs - 1) / 2; 01575 01576 for (int j = 0; j < h; ++j) 01577 for (int i = 0; i < w; ++i) 01578 { 01579 int sum = 0; 01580 int val = 0; 01581 for (int k = 0; k < vfs; k ++) 01582 if (j + k - vfs2 >= 0 && j + k - vfs2 < h) 01583 { 01584 val += src[w * (k - vfs2)] * vf_flipped[k]; 01585 sum += vf_flipped[k]; 01586 } 01587 01588 *dst++ = val / sum; 01589 ++src; 01590 } 01591 } 01592 01593 // ###################################################################### 01594 /* So things look consistent in everyone's emacs... */ 01595 /* Local Variables: */ 01596 /* mode: c++ */ 01597 /* indent-tabs-mode: nil */ 01598 /* End: */ 01599 01600 #endif // IMAGE_C_INTEGER_MATH_OPS_C_DEFINED