00001 #include <assert.h>
00002 #include <stdlib.h>
00003
00004 #include <string.h>
00005
00010 #define assure(x) assert(x)
00011
00012 #ifdef bool
00013 #define mybool bool
00014 #else
00015 #define mybool unsigned char
00016 #endif
00017
00018 #ifdef true
00019 #define mytrue true
00020 #else
00021 #define mytrue 1
00022 #endif
00023
00024 #ifdef false
00025 #define myfalse false
00026 #else
00027 #define myfalse 0
00028 #endif
00029
00030 #ifndef OUT_TYPE
00031 #define OUT_TYPE IN_TYPE
00032 #endif
00033
00035 typedef struct dheap {
00036 unsigned *heaps;
00037
00038
00039
00040
00041
00042
00043
00044
00045 unsigned *B;
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 unsigned *SCA;
00057
00058
00059
00060
00061
00062
00063 const IN_TYPE *image;
00064 unsigned rx;
00065 unsigned ry;
00066 unsigned Nx;
00067 unsigned Ny;
00068 unsigned m;
00069 unsigned Rx;
00070 unsigned Ry;
00071 } dheap;
00075 #define S_SWAP(SCA, i, j) \
00076 do { \
00077 const unsigned SCAi = SCA[i]; \
00078 const unsigned SCAj = SCA[j]; \
00079 SCA[i] = SCAj; \
00080 SCA[j] = SCAi; \
00081 } while(0)
00082
00083
00084 #define BITS 64
00085
00093 static void
00094 qsort_int(unsigned *SCA,
00095 unsigned n, const IN_TYPE *image)
00096 {
00097 int i, ir, j, k, l;
00098 int i_stack[BITS];
00099 int j_stack ;
00100 int a;
00101
00102 IN_TYPE ia;
00103
00104
00105
00106
00107 ir = n ;
00108 l = 1 ;
00109 j_stack = 0 ;
00110 while (1) {
00111 if (ir-l < 7) {
00112 for (j=l+1 ; j<=ir ; j++) {
00113 a = SCA[j-1];
00114 ia = image[a];
00115 for (i=j-1 ; i>=1 ; i--) {
00116 if (image[SCA[i-1]] <= ia) break;
00117 SCA[i] = SCA[i-1];
00118 }
00119 SCA[i] = a;
00120 }
00121 if (j_stack == 0) break;
00122 ir = i_stack[j_stack-- -1];
00123 l = i_stack[j_stack-- -1];
00124 } else {
00125
00126
00127
00128
00129
00130 k = (l+ir) >> 1;
00131 S_SWAP(SCA, k-1, l);
00132 if (image[SCA[l]] > image[SCA[ir-1]]) {
00133 S_SWAP(SCA, l, ir-1);
00134 }
00135 if (image[SCA[l-1]] > image[SCA[ir-1]]) {
00136 S_SWAP(SCA, l-1, ir-1);
00137 }
00138 if (image[SCA[l]] > image[SCA[l-1]]) {
00139 S_SWAP(SCA, l, l-1);
00140 }
00141
00142 i = l+1;
00143 j = ir;
00144 a = SCA[l-1];
00145 ia = image[a];
00146 for (;;) {
00147 do i++; while (image[SCA[i-1]] < ia);
00148 do j--; while (image[SCA[j-1]] > ia);
00149 if (j < i) break;
00150 S_SWAP(SCA, i-1, j-1);
00151 }
00152 SCA[l-1] = SCA[j-1];
00153 SCA[j-1] = a;
00154 j_stack += 2;
00155
00156 assert( j_stack <= BITS );
00157
00158 if (ir-i+1 >= j-l) {
00159 i_stack[j_stack-1] = ir;
00160 i_stack[j_stack-2] = i;
00161 ir = j-1;
00162 } else {
00163 i_stack[j_stack-1] = j-1;
00164 i_stack[j_stack-2] = l;
00165 l = i;
00166 }
00167 }
00168 }
00169
00170 return;
00171 }
00172
00178 static void
00179 SCA_init(dheap *dh, unsigned x)
00180 {
00181 unsigned y;
00182 unsigned *SCAx = dh->SCA + (dh->Ry)*x;
00183
00184 for (y = 0; y < dh->Ry; y++) {
00185 SCAx[y] = x + y*dh->Nx;
00186 }
00187
00188 qsort_int(SCAx,
00189 dh->Ry,
00190 dh->image);
00191
00192 return;
00193 }
00194
00202 static void
00203 SCA_replace(dheap *dh, unsigned x,
00204 unsigned yold, unsigned ynew)
00205 {
00206 unsigned n = dh->Ry;
00207 unsigned *SCAx = dh->SCA + n*x;
00208 const IN_TYPE *im = dh->image;
00209
00210 unsigned i;
00211 unsigned aold = x + yold*dh->Nx;
00212 unsigned anew = x + ynew*dh->Nx;
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 for (i = 0; i < n; i++) {
00223 if (SCAx[i] == aold) break;
00224 }
00225 SCAx[i] = anew;
00226
00227
00228
00229
00230 if (i+1 < n &&
00231 im[SCAx[i ]] >
00232 im[SCAx[i+1]]) {
00233
00234 S_SWAP(SCAx, i , i+1);
00235 i++;
00236
00237 while (i+1 < n &&
00238 im[SCAx[i ]] >
00239 im[SCAx[i+1]]) {
00240 S_SWAP(SCAx, i , i+1);
00241 i++;
00242 }
00243 }
00244 else {
00245 while (i >= 1 &&
00246 im[SCAx[i ]] <
00247 im[SCAx[i-1]]) {
00248 S_SWAP(SCAx, i , i-1);
00249 i--;
00250 }
00251 }
00252
00253 return;
00254 }
00255
00256
00264 static void
00265 HEAP_SWAP(unsigned i,
00266 unsigned j,
00267 unsigned int *B,
00268 unsigned int *heaps)
00269 {
00270 unsigned ai = heaps[i];
00271 unsigned aj = heaps[j];
00272 heaps[i] = aj;
00273 heaps[j] = ai;
00274
00275 B[aj] = i;
00276 B[ai] = j;
00277
00278 return;
00279 }
00280
00285 static void
00286 median(dheap *dh)
00287 {
00288 unsigned n = 2 * dh->m + 1;
00289
00290 const unsigned k = (n-1)/2;
00291 IN_TYPE pivot;
00292 unsigned i, j, lo, hi;
00293
00294 lo = 0;
00295 hi = n - 1;
00296
00297 while (lo < hi) {
00298
00299
00300 pivot = dh->image[dh->heaps[k]];
00301 i = lo;
00302 j = hi;
00303 do {
00304 while (dh->image[dh->heaps[i]] < pivot) i++;
00305 while (dh->image[dh->heaps[j]] > pivot) j--;
00306 if (i <= j) {
00307 if (i != j) HEAP_SWAP(i, j, dh->B, dh->heaps);
00308 i++;
00309 j--;
00310 }
00311 } while (i <= j);
00312
00313 if (j < k) lo = i;
00314 if (k < i) hi = j;
00315 }
00316
00317 return;
00318 }
00319
00320
00331 static unsigned
00332 bubble_down_gt(const IN_TYPE *image,
00333 unsigned *B,
00334 unsigned *heaps,
00335 unsigned m,
00336 unsigned m1,
00337 unsigned root)
00338 {
00339 unsigned child;
00340 unsigned end = m-1;
00341
00342 while (root * 2 + 1 <= end) {
00343 child = root*2 + 1;
00344
00345 if (child < end &&
00346 image[heaps[m1 + child]] >
00347 image[heaps[m1 + child + 1]]) {
00348 child = child + 1;
00349 }
00350 if (image[heaps[m1 + root]] >
00351 image[heaps[m1 + child]]) {
00352 HEAP_SWAP(m1 + root, m1 + child, B, heaps);
00353 root = child;
00354 }
00355 else {
00356 return root;
00357 }
00358 }
00359 return root;
00360 }
00361
00371 static unsigned
00372 bubble_up_gt(const IN_TYPE *image,
00373 unsigned *B,
00374 unsigned *heaps,
00375 unsigned m1,
00376 unsigned child)
00377 {
00378 unsigned parent;
00379
00380 while (child > 0) {
00381 parent = (child - 1) / 2;
00382
00383 if (image[heaps[m1 + parent]] >
00384 image[heaps[m1 + child]]) {
00385 HEAP_SWAP(m1 + parent, m1 + child, B, heaps);
00386 child = parent;
00387 }
00388 else return child;
00389 }
00390 return child;
00391 }
00392
00397 static void
00398 heapify_gt(dheap *dh)
00399 {
00400 int start = dh->m/2-1;
00401
00402 while (start >= 0) {
00403 bubble_down_gt(dh->image,
00404 dh->B,
00405 dh->heaps,
00406 dh->m,
00407 dh->m+1, start);
00408 start = start - 1;
00409 }
00410 return;
00411 }
00412
00422 static unsigned
00423 bubble_down_lt(const IN_TYPE *image,
00424 unsigned *B,
00425 unsigned *heaps,
00426 unsigned end, unsigned root)
00427 {
00428 unsigned child;
00429
00430 while (root * 2 + 1 <= end) {
00431 child = root*2 + 1;
00432
00433 if (child < end &&
00434 image[heaps[child]] <
00435 image[heaps[child + 1]]) {
00436 child = child + 1;
00437 }
00438 if (image[heaps[root]] <
00439 image[heaps[child]]) {
00440 HEAP_SWAP(root, child, B, heaps);
00441 root = child;
00442 }
00443 else {
00444 return root;
00445 }
00446 }
00447 return root;
00448 }
00449
00458 static unsigned
00459 bubble_up_lt(const IN_TYPE *image,
00460 unsigned *B,
00461 unsigned *heaps, unsigned child)
00462 {
00463 unsigned parent;
00464
00465 while (child > 0) {
00466 parent = (child - 1) / 2;
00467
00468 if (image[heaps[parent]] <
00469 image[heaps[child]]) {
00470 HEAP_SWAP(parent, child, B, heaps);
00471 child = parent;
00472 }
00473 else return child;
00474 }
00475 return child;
00476 }
00477
00482 static void
00483 heapify_lt(dheap *dh)
00484 {
00485 int start = dh->m/2-1;
00486
00487 while (start >= 0) {
00488 bubble_down_lt(dh->image,
00489 dh->B,
00490 dh->heaps,
00491 dh->m-1, start);
00492 start = start - 1;
00493 }
00494 return;
00495 }
00496
00501 static void
00502 dheap_establish(dheap *dh)
00503 {
00504 median(dh);
00505
00506 heapify_lt(dh);
00507 heapify_gt(dh);
00508
00509 return;
00510 }
00511
00524 static dheap *
00525 dheap_new(const IN_TYPE *image, unsigned Nx, unsigned Ny, unsigned rx, unsigned ry)
00526 {
00527 dheap *dh = malloc(sizeof(*dh));
00528 assure( dh != NULL );
00529 assure( rx > 0 || ry > 0 );
00530
00531 dh->heaps = malloc( (2*rx+1)*(2*ry+1) * sizeof(*dh->heaps));
00532 dh->B = malloc( Nx*Ny * sizeof(*dh->B));
00533 dh->SCA = malloc( Nx*(2*ry+1) * sizeof(*dh->SCA));
00534 assure( dh->heaps != NULL );
00535 assure( dh->B != NULL );
00536 assure( dh->SCA != NULL );
00537
00538 dh->image = image;
00539 dh->m = ((2*rx+1)*(2*ry+1))/2;
00540 dh->Nx = Nx;
00541 dh->Ny = Ny;
00542 dh->rx = rx;
00543 dh->ry = ry;
00544 dh->Rx = 2*rx+1;
00545 dh->Ry = 2*ry+1;
00546
00547 {
00548 unsigned k = 0;
00549 unsigned x, y;
00550
00551 for (y = 0; y < dh->Ry; y++) {
00552 for (x = 0; x < dh->Rx; x++) {
00553 unsigned ai = x + y * dh->Nx;
00554 dh->heaps[k] = ai;
00555 dh->B[ai] = k;
00556 k++;
00557 }
00558 }
00559 }
00560 dheap_establish(dh);
00561
00562 {
00563 unsigned x;
00564 for (x = 0; x < 2*dh->rx; x++)
00565 {
00566 SCA_init(dh, x);
00567 }
00568 }
00569
00570 return dh;
00571 }
00572
00577 static void
00578 dheap_delete(dheap *dh)
00579 {
00580 free(dh->SCA);
00581 free(dh->B);
00582 free(dh->heaps);
00583 free(dh);
00584
00585 return;
00586 }
00587
00593 static IN_TYPE
00594 dheap_median(const dheap *dh)
00595 {
00596 return dh->image[dh->heaps[dh->m]];
00597 }
00598
00616 static void
00617 dheap_replace(const IN_TYPE *image,
00618 unsigned *B,
00619 unsigned *heaps,
00620 unsigned m,
00621 unsigned m1,
00622 unsigned anew,
00623 unsigned aold)
00624 {
00625 static mybool prev_was_larger = myfalse;
00626 static mybool prev_was_smaller = myfalse;
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 unsigned pos;
00640
00641
00642
00643 unsigned ci = B[aold];
00644 heaps[ci] = anew;
00645 B[anew] = ci;
00646
00647
00648
00649 if (ci < m) {
00650
00651 if (prev_was_smaller) {
00652 pos = bubble_down_lt(image, B, heaps, m-1,
00653 ci);
00654 if (pos == ci) pos = bubble_up_lt(image, B, heaps, ci);
00655 }
00656 else
00657
00658 {
00659
00660
00661
00662
00663 pos = bubble_up_lt(image, B, heaps, ci);
00664 if (pos == ci) pos = bubble_down_lt(image, B, heaps, m-1, ci);
00665 }
00666
00667 if (pos == 0 &&
00668 image[heaps[0]] > image[heaps[m]]) {
00669 HEAP_SWAP(0, m, B, heaps);
00670
00671 if (image[heaps[m1]] <
00672 image[heaps[m]]) {
00673 HEAP_SWAP(m1, m, B, heaps);
00674 bubble_down_gt(image, B, heaps, m, m1, 0);
00675 }
00676 }
00677
00678
00679
00680
00681
00682
00683
00684 prev_was_larger = (pos < ci);
00685 prev_was_smaller = (pos > ci);
00686 return;
00687 }
00688 else if (ci >= m1) {
00689
00690 if (prev_was_larger) {
00691 pos = bubble_down_gt(image, B, heaps, m, m1, ci-(m1));
00692 if (pos == ci-(m1))
00693 pos = bubble_up_gt(image, B, heaps, m1, ci-(m1));
00694 }
00695 else {
00696 pos = bubble_up_gt(image, B, heaps, m1, ci-(m1));
00697 if (pos == ci-(m1))
00698 pos = bubble_down_gt(image, B, heaps, m, m1, ci-(m1));
00699 }
00700
00701 if (pos == 0 &&
00702 image[heaps[m1]] < image[heaps[m]]) {
00703 HEAP_SWAP(m1, m, B, heaps);
00704
00705 if (image[heaps[0]] > image[heaps[m]]) {
00706 HEAP_SWAP(0, m, B, heaps);
00707 bubble_down_lt(image, B, heaps, m-1, 0);
00708 }
00709 }
00710
00711 prev_was_smaller = (pos < ci-(m1));
00712 prev_was_larger = (pos > ci-(m1));
00713 return;
00714 }
00715 else {
00716
00717 if (prev_was_smaller) {
00718 if (image[heaps[0]] > image[heaps[m]]) {
00719 HEAP_SWAP(0, m, B, heaps);
00720 bubble_down_lt(image, B, heaps, m-1, 0);
00721 prev_was_smaller = mytrue;
00722 prev_was_larger = myfalse;
00723 return;
00724 }
00725 else if (image[heaps[m1]] <
00726 image[heaps[m]]) {
00727 HEAP_SWAP(m1, m, B, heaps);
00728 bubble_down_gt(image, B, heaps, m, m1, 0);
00729 prev_was_smaller = myfalse;
00730 prev_was_larger = mytrue;
00731 return;
00732 } else {
00733 prev_was_smaller = myfalse;
00734 prev_was_larger = myfalse;
00735 return;
00736 }
00737 } else {
00738 if (image[heaps[m1]] <
00739 image[heaps[m]]) {
00740 HEAP_SWAP(m1, m, B, heaps);
00741 bubble_down_gt(image, B, heaps, m, m1, 0);
00742 prev_was_smaller = myfalse;
00743 prev_was_larger = mytrue;
00744 return;
00745 } else if (image[heaps[0]] > image[heaps[m]]) {
00746 HEAP_SWAP(0, m, B, heaps);
00747 bubble_down_lt(image, B, heaps, m-1, 0);
00748 prev_was_smaller = mytrue;
00749 prev_was_larger = myfalse;
00750 return;
00751 } else {
00752 prev_was_smaller = myfalse;
00753 prev_was_larger = myfalse;
00754 return;
00755 }
00756 }
00757 }
00758 }
00759
00760 static
00761 IN_TYPE get_kth(IN_TYPE * a, unsigned n, int k)
00762 {
00763 IN_TYPE x;
00764 int i, j, l, m;
00765
00766 l=0; m=n-1;
00767 while (l<m) {
00768 x=a[k];
00769 i=l;
00770 j=m;
00771 do {
00772 while (a[i]<x) i++;
00773 while (x<a[j]) j--;
00774 if (i<=j) {
00775 const IN_TYPE temp = a[i];
00776 a[i] = a[j];
00777 a[j] = temp;
00778 i++; j--;
00779 }
00780 } while (i<=j);
00781 if (j<k) l=i;
00782 if (k<i) m=j;
00783 }
00784 return a[k];
00785 }
00786
00796 static inline IN_TYPE
00797 max3(IN_TYPE p0,
00798 IN_TYPE p1,
00799 IN_TYPE p2)
00800 {
00801 return (p0 > p1)
00802 ?
00803 ((p0 > p2) ? p0 : p2)
00804 :
00805 ((p1 > p2) ? p1 : p2);
00806 }
00807
00817 static inline IN_TYPE
00818 min3(IN_TYPE p0,
00819 IN_TYPE p1,
00820 IN_TYPE p2)
00821 {
00822 return (p0 < p1)
00823 ?
00824 ((p0 < p2) ? p0 : p2)
00825 :
00826 ((p1 < p2) ? p1 : p2);
00827 }
00828
00845 static inline IN_TYPE
00846 median5(IN_TYPE p0,
00847 IN_TYPE p1,
00848 IN_TYPE p2,
00849 IN_TYPE p3,
00850 IN_TYPE p4)
00851 {
00852
00853
00854
00855
00856
00857
00858
00859 return (p3 < p1)
00860 ?
00861 ((p4 >= p1) ? p1 : max3(p3, p4, p0))
00862 :
00863 ((p4 <= p1) ? p1 : min3(p3, p4, p2));
00864 }
00865
00890 static inline IN_TYPE
00891 median9_2(IN_TYPE p0,
00892 IN_TYPE p1,
00893 IN_TYPE p2,
00894 IN_TYPE p3,
00895 IN_TYPE p4,
00896 IN_TYPE p5,
00897 IN_TYPE p6,
00898 IN_TYPE p7,
00899 IN_TYPE p8)
00900 {
00901 return (p4 <= p7)
00902 ?
00903 median5(p3, p4, p5, p2, p6)
00904 :
00905 ((p1 < p7) ? median5(p6, p7, p8, p2, p3)
00906 : median5(p0, p1, p2, p8, p3));
00907 }
00928 static inline IN_TYPE
00929 median9_1(IN_TYPE p0,
00930 IN_TYPE p1,
00931 IN_TYPE p2,
00932 IN_TYPE p3,
00933 IN_TYPE p4,
00934 IN_TYPE p5,
00935 IN_TYPE p6,
00936 IN_TYPE p7,
00937 IN_TYPE p8)
00938 {
00939 return (p1 < p4) ? median9_2(p0, p1, p2, p3, p4, p5, p6, p7, p8)
00940 : median9_2(p3, p4, p5, p0, p1, p2, p6, p7, p8);
00941 }
00942
00956 #define sort3(p0, p1, p2, i0, i1, i2) \
00957 do { \
00958 if (i0 <= i1) { \
00959 if (i1 <= i2) { \
00960 p0 = i0; p1 = i1; p2 = i2; \
00961 } else if (i0 <= i2) { \
00962 \
00963 p0 = i0; p1 = i2; p2 = i1; \
00964 } else { \
00965 \
00966 p0 = i2; p1 = i0; p2 = i1; \
00967 } \
00968 } else { \
00969 if (i0 <= i2) { \
00970 \
00971 p0 = i1; p1 = i0; p2 = i2; \
00972 } else if (i1 < i2) { \
00973 \
00974 p0 = i1; p1 = i2; p2 = i0; \
00975 } else { \
00976 \
00977 p0 = i2; p1=i1; p2 = i0; \
00978 } \
00979 } \
00980 } while(0)
00981
00993 static void
00994 filter_median_1(const IN_TYPE *in, OUT_TYPE *out,
00995 unsigned Nx, unsigned Ny, unsigned border_mode)
00996 {
00997 register IN_TYPE p0, p1, p2, p3, p4, p5;
00998 register IN_TYPE p6 = (IN_TYPE)0;
00999 register IN_TYPE p7 = (IN_TYPE)0;
01000 register IN_TYPE p8 = (IN_TYPE)0;
01001 const IN_TYPE * i0 = in;
01002 const IN_TYPE * i1 = i0 + Nx;
01003 const IN_TYPE * i2 = i1 + Nx;
01004 const IN_TYPE * istop = in + Nx*Ny;
01005
01006
01007 assure( Nx >= 3 );
01008 assure( Ny >= 3 );
01009
01010 switch (border_mode) {
01011 case IRPLIB_FILTER_BORDER_FILTER: {
01012 IN_TYPE buf6[6];
01013 unsigned j = 0;
01014
01015 buf6[0] = i0[0];
01016 buf6[1] = i0[1];
01017 buf6[2] = i1[0];
01018 buf6[3] = i1[1];
01019 out[j++] = get_kth(buf6, 4, 1);
01020
01021 for (; j < Nx-1; j++) {
01022 memcpy(buf6, i0+j-1, 3*sizeof(*buf6));
01023 memcpy(buf6+3, i1+j-1, 3*sizeof(*buf6));
01024 out[j] = get_kth(buf6, 6, 2);
01025 }
01026 buf6[0] = i0[Nx-2];
01027 buf6[1] = i0[Nx-1];
01028 buf6[2] = i1[Nx-2];
01029 buf6[3] = i1[Nx-1];
01030 out[j] = get_kth(buf6, 4, 1);
01031 out += Nx;
01032
01033 break;
01034 }
01035 case IRPLIB_FILTER_BORDER_COPY: {
01036
01037 if (sizeof(IN_TYPE) == sizeof(OUT_TYPE)) {
01038 (void)memcpy(out, in, (Nx-1)*sizeof(*out));
01039 } else {
01040 unsigned i;
01041 for (i=0; i < Nx-1; i++) out[i] = (OUT_TYPE)in[i];
01042 }
01043 }
01044 case IRPLIB_FILTER_BORDER_EXTRAPOL_OUT:
01045 case IRPLIB_FILTER_BORDER_NOP:
01046 out += Nx-1;
01047 break;
01048 default:
01049 case IRPLIB_FILTER_BORDER_CROP:
01050 break;
01051 }
01052
01053 for (;i2 < istop; i0 += Nx, i1 += Nx, i2 += Nx, out += Nx) {
01054
01055 unsigned char k = 2;
01056 unsigned j = 0;
01057
01058
01059
01060 switch (border_mode) {
01061 case IRPLIB_FILTER_BORDER_FILTER: {
01062 IN_TYPE buf6[6];
01063
01064 buf6[0] = i0[0];
01065 buf6[1] = i1[0];
01066 buf6[2] = i2[0];
01067 buf6[3] = i0[1];
01068 buf6[4] = i1[1];
01069 buf6[5] = i2[1];
01070 out[0] = get_kth(buf6, 6, 2);
01071
01072
01073
01074 out--;
01075
01076 break;
01077 }
01078 case IRPLIB_FILTER_BORDER_CROP:
01079 out -= 2;
01080 break;
01081 case IRPLIB_FILTER_BORDER_COPY: {
01082
01083
01084 out[0] = (IN_TYPE)i0[Nx-1];
01085 out[1] = (IN_TYPE)i0[Nx];
01086 break;
01087 }
01088 default:
01089 break;
01090 }
01091
01092 sort3(p0, p1, p2, i0[j], i1[j], i2[j]);
01093 j++;
01094
01095 sort3(p3, p4, p5, i0[j], i1[j], i2[j]);
01096 j++;
01097
01098 for (; j < Nx; j++) {
01099
01100 if (k == 0) {
01101 k = 1;
01102 sort3(p0, p1, p2, i0[j], i1[j], i2[j]);
01103 }
01104 else if (k == 1) {
01105 k = 2;
01106 sort3(p3, p4, p5, i0[j], i1[j], i2[j]);
01107 }
01108 else {
01109 k = 0;
01110 sort3(p6, p7, p8, i0[j], i1[j], i2[j]);
01111 }
01112
01113 out[j]
01114 = (OUT_TYPE)median9_1(p0, p1, p2, p3, p4, p5, p6, p7, p8);
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 }
01138
01139 if (border_mode == IRPLIB_FILTER_BORDER_FILTER) {
01140 IN_TYPE buf6[6];
01141
01142 buf6[0] = i0[j-2];
01143 buf6[1] = i1[j-2];
01144 buf6[2] = i2[j-2];
01145 buf6[3] = i0[j-1];
01146 buf6[4] = i1[j-1];
01147 buf6[5] = i2[j-1];
01148
01149 out[j] = get_kth(buf6, 6, 2);
01150
01151
01152 out++;
01153 } else if (border_mode == IRPLIB_FILTER_BORDER_EXTRAPOL_OUT) {
01154
01155 out[1] = out[2];
01156 out[Nx] = out[Nx-1];
01157
01158 if (i0 == in) {
01159
01160 (void)memcpy(out-(Nx-1), out+1, Nx*sizeof(*out));
01161 }
01162 }
01163 }
01164
01165 switch (border_mode) {
01166 case IRPLIB_FILTER_BORDER_FILTER: {
01167 IN_TYPE buf6[6];
01168 unsigned j = 0;
01169
01170 buf6[0] = i0[0];
01171 buf6[1] = i0[1];
01172 buf6[2] = i1[0];
01173 buf6[3] = i1[1];
01174 out[j++] = get_kth(buf6, 4, 1);
01175
01176 for (; j < Nx-1; j++) {
01177 memcpy(buf6, i0+j-1, 3*sizeof(*buf6));
01178 memcpy(buf6+3, i1+j-1, 3*sizeof(*buf6));
01179 out[j] = get_kth(buf6, 6, 2);
01180 }
01181 buf6[0] = i0[Nx-2];
01182 buf6[1] = i0[Nx-1];
01183 buf6[2] = i1[Nx-2];
01184 buf6[3] = i1[Nx-1];
01185 out[j] = get_kth(buf6, 4, 1);
01186
01187 break;
01188 }
01189 default:
01190 case IRPLIB_FILTER_BORDER_CROP:
01191 break;
01192 case IRPLIB_FILTER_BORDER_COPY: {
01193
01194
01195 if (sizeof(IN_TYPE) == sizeof(OUT_TYPE)) {
01196 (void)memcpy(out, istop-(Nx+1), (Nx+1)*sizeof(*out));
01197 } else {
01198 unsigned i;
01199 istop -= (Nx+1);
01200 for (i=0; i < Nx+1; i++) out[i] = (OUT_TYPE)istop[i];
01201 }
01202 break;
01203 }
01204 case IRPLIB_FILTER_BORDER_EXTRAPOL_OUT: {
01205
01206
01207 (void)memcpy(out+1, out-(Nx-1), Nx*sizeof(*out));
01208 break;
01209 }
01210 }
01211
01212 return;
01213 }
01214
01215
01310 static void
01311 filter_median(const IN_TYPE *in, OUT_TYPE *out,
01312 unsigned Nx, unsigned Ny,
01313 unsigned rx, unsigned ry,
01314 unsigned border_mode)
01315 {
01316 dheap *dh;
01317 unsigned y;
01318 unsigned x;
01319 int dx;
01320
01321 assure( 2*rx + 1 <= Nx );
01322 assure( 2*ry + 1 <= Ny );
01323
01324 border_mode &= IRPLIB_FILTER_BORDER_MODE;
01325
01326 if (rx == 1 && ry == 1) {
01327 filter_median_1(in, out, Nx, Ny, border_mode);
01328
01329 return;
01330 }
01331
01332 assure( border_mode == 0 );
01333
01334 if (rx == 0 && ry == 0) {
01335
01336
01337
01338
01339
01340 unsigned i;
01341 for (i = 0; i < Nx * Ny; i++) out[i] = (OUT_TYPE)in[i];
01342 return;
01343 }
01344
01345 dh = dheap_new(in, Nx, Ny, rx, ry);
01346
01347
01348
01349
01350
01351
01352
01353 for (y = 0 + dh->ry, dx = 1;
01354 y < dh->Ny - dh->ry;
01355 y++, dx = -dx) {
01356
01357 unsigned xfirst = (dx == 1) ? dh->rx : dh->Nx-1 - dh->rx;
01358 unsigned xlast = (dx == -1) ? dh->rx : dh->Nx-1 - dh->rx;
01359
01360 for (x = xfirst; x != xlast + dx; x += dx) {
01361
01362 if (y == dh->ry) {
01363 SCA_init(dh, x + dx * dh->rx);
01364 }
01365 else {
01366
01367 SCA_replace(dh, x + dx * dh->rx,
01368 y - dh->ry - 1,
01369 y + dh->ry);
01370 }
01371
01372 if (x == xfirst) {
01373 if (y != dh->ry) {
01374
01375
01376 unsigned i;
01377 for (i = x - dx*dh->rx;
01378 i != x + dx*dh->rx; i += dx) {
01379 SCA_replace(dh, i,
01380 y - dh->ry - 1,
01381 y + dh->ry);
01382
01383 dheap_replace(dh->image,
01384 dh->B,
01385 dh->heaps,
01386 dh->m,
01387 dh->m+1,
01388 i + ((y + dh->ry ) * dh->Nx),
01389 i + ((y - dh->ry - 1) * dh->Nx));
01390 }
01391
01392 dheap_replace(dh->image,
01393 dh->B,
01394 dh->heaps,
01395 dh->m,
01396 dh->m+1,
01397 i + ((y + dh->ry ) * dh->Nx),
01398 i + ((y - dh->ry - 1) * dh->Nx));
01399 }
01400 }
01401 else {
01402
01403
01404 unsigned xnew = x + dx * dh->rx;
01405 unsigned xold = x - dx * (dh->rx+1);
01406 unsigned *SCAxnew = dh->SCA + dh->Ry*xnew;
01407 unsigned *SCAxold = dh->SCA + dh->Ry*xold;
01408
01409 const IN_TYPE *image = dh->image;
01410 unsigned *B = dh->B;
01411 unsigned *heaps = dh->heaps;
01412 unsigned m = dh->m;
01413 unsigned m1 = m+1;
01414 unsigned anew, aold;
01415 unsigned i;
01416
01417
01418
01419
01420
01421
01422
01423
01424 for (i = 0; i < dh->Ry; i++) {
01425 anew = SCAxnew[i];
01426 aold = SCAxold[i];
01427
01428 dheap_replace(image, B, heaps, m, m1,
01429 anew, aold);
01430 }
01431 }
01432 out[x + y*Nx] = (OUT_TYPE)dheap_median(dh);
01433 }
01434 }
01435
01436 dheap_delete(dh);
01437 return;
01438 }
01439