00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "thd_shear3d.h"
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 typedef void (*shift_func)(int,int,float,float *,float,float *) ;
00023 static shift_func shifter = fft_shift2 ;
00024 static int shift_method = MRI_FOURIER ;
00025
00026 void THD_rota_method( int mode )
00027 {
00028 shift_method = mode ;
00029 switch( mode ){
00030 case MRI_NN: shifter = nn_shift2 ; break ;
00031 case MRI_TSSHIFT: shifter = ts_shift2 ; break ;
00032
00033 case MRI_LINEAR: shifter = lin_shift2 ; break ;
00034 case MRI_FOURIER: shifter = fft_shift2 ; break ;
00035 default:
00036 case MRI_CUBIC: shifter = cub_shift2 ; break ;
00037 case MRI_QUINTIC: shifter = quint_shift2 ; break ;
00038 case MRI_HEPTIC: shifter = hept_shift2 ; break ;
00039
00040 case MRI_FOURIER_NOPAD: shifter = fft_shift2 ; break ;
00041 }
00042 return ;
00043 }
00044
00045
00046
00047
00048
00049
00050 #define VV(i,j,k) v[(i)+(j)*nx+(k)*nxy]
00051 #define SX(i) (nx1-(i))
00052 #define SY(j) (ny1-(j))
00053 #define SZ(k) (nz1-(k))
00054
00055 static void flip_xy( int nx , int ny , int nz , float * v )
00056 {
00057 int ii,jj,kk ;
00058 int nx1=nx-1,nx2=nx/2, ny1=ny-1,ny2=ny/2, nz1=nz-1,nz2=nz/2, nxy=nx*ny ;
00059 float * r1 ;
00060
00061 r1 = (float *) malloc(sizeof(float)*nx) ;
00062
00063 for( kk=0 ; kk < nz ; kk++ ){
00064 for( jj=0 ; jj < ny2 ; jj++ ){
00065
00066
00067
00068 for( ii=0 ; ii < nx ; ii++ ) r1[ii] = VV(SX(ii),SY(jj),kk) ;
00069 for( ii=0 ; ii < nx ; ii++ ) VV(ii,SY(jj),kk) = VV(SX(ii),jj ,kk) ;
00070 for( ii=0 ; ii < nx ; ii++ ) VV(ii,jj ,kk) = r1[ii] ;
00071 }
00072 if( ny%2 == 1 ){
00073 for( ii=0 ; ii < nx ; ii++ ) r1[ii] = VV(SX(ii),jj,kk) ;
00074 for( ii=0 ; ii < nx ; ii++ ) VV(ii,jj,kk) = r1[ii] ;
00075 }
00076 }
00077
00078 free(r1) ; return ;
00079 }
00080
00081
00082
00083
00084
00085
00086 static void flip_yz( int nx , int ny , int nz , float * v )
00087 {
00088 int ii,jj,kk ;
00089 int nx1=nx-1,nx2=nx/2, ny1=ny-1,ny2=ny/2, nz1=nz-1,nz2=nz/2, nxy=nx*ny ;
00090 float * r1 ;
00091
00092 r1 = (float *) malloc(sizeof(float)*ny) ;
00093
00094 for( ii=0 ; ii < nx ; ii++ ){
00095 for( kk=0 ; kk < nz2 ; kk++ ){
00096 for( jj=0 ; jj < ny ; jj++ ) r1[jj] = VV(ii,SY(jj),SZ(kk)) ;
00097 for( jj=0 ; jj < ny ; jj++ ) VV(ii,jj,SZ(kk)) = VV(ii,SY(jj),kk ) ;
00098 for( jj=0 ; jj < ny ; jj++ ) VV(ii,jj,kk ) = r1[jj] ;
00099 }
00100 if( nz%2 == 1 ){
00101 for( jj=0 ; jj < ny ; jj++ ) r1[jj] = VV(ii,SY(jj),kk) ;
00102 for( jj=0 ; jj < ny ; jj++ ) VV(ii,jj,kk) = r1[jj] ;
00103 }
00104 }
00105
00106 free(r1) ; return ;
00107 }
00108
00109
00110
00111
00112
00113
00114 static void flip_xz( int nx , int ny , int nz , float * v )
00115 {
00116 int ii,jj,kk ;
00117 int nx1=nx-1,nx2=nx/2, ny1=ny-1,ny2=ny/2, nz1=nz-1,nz2=nz/2, nxy=nx*ny ;
00118 float * r1 ;
00119
00120 r1 = (float *) malloc(sizeof(float)*nx) ;
00121
00122 for( jj=0 ; jj < ny ; jj++ ){
00123 for( kk=0 ; kk < nz2 ; kk++ ){
00124 for( ii=0 ; ii < nx ; ii++ ) r1[ii] = VV(SX(ii),jj,SZ(kk)) ;
00125 for( ii=0 ; ii < nx ; ii++ ) VV(ii,jj,SZ(kk)) = VV(SX(ii),jj,kk ) ;
00126 for( ii=0 ; ii < nx ; ii++ ) VV(ii,jj,kk ) = r1[ii] ;
00127 }
00128 if( nz%2 == 1 ){
00129 for( ii=0 ; ii < nx ; ii++ ) r1[ii] = VV(SX(ii),jj,kk) ;
00130 for( ii=0 ; ii < nx ; ii++ ) VV(ii,jj,kk) = r1[ii] ;
00131 }
00132 }
00133
00134 free(r1) ; return ;
00135 }
00136
00137
00138
00139
00140
00141
00142 static void apply_xshear( float a , float b , float s ,
00143 int nx , int ny , int nz , float * v )
00144 {
00145 float * fj0 , * fj1 ;
00146 int nx1=nx-1 , ny1=ny-1 , nz1=nz-1 , nxy=nx*ny ;
00147 float nx2=0.5*nx1 , ny2=0.5*ny1 , nz2=0.5*nz1 ;
00148 int ii,jj,kk , nup,nst ;
00149 float a0 , a1 , st ;
00150
00151 ENTRY("apply_xshear") ;
00152
00153
00154
00155 st = fabs(a)*ny2 + fabs(b)*nz2 + fabs(s) ; if( st < 1.e-3 ) EXRETURN ;
00156
00157 if( shift_method == MRI_FOURIER ){
00158 nst = nx + 0.5*st ;
00159 nup = csfft_nextup_one35(nst) ;
00160 } else if( shift_method == MRI_FOURIER_NOPAD ){
00161 nup = csfft_nextup_even(nx) ;
00162 }
00163
00164 for( kk=0 ; kk < nz ; kk++ ){
00165 for( jj=0 ; jj < ny ; jj+=2 ){
00166 fj0 = v + (jj*nx + kk*nxy) ;
00167 fj1 = (jj < ny1) ? (fj0 + nx) : NULL ;
00168 a0 = a*(jj-ny2) + b*(kk-nz2) + s ;
00169 a1 = a0 + a ;
00170 shifter( nx , nup , a0 , fj0 , a1 , fj1 ) ;
00171 }
00172 }
00173
00174 EXRETURN ;
00175 }
00176
00177
00178
00179
00180
00181 static void apply_yshear( float a , float b , float s ,
00182 int nx , int ny , int nz , float * v )
00183 {
00184 float * fj0 , * fj1 ;
00185 int nx1=nx-1 , ny1=ny-1 , nz1=nz-1 , nxy=nx*ny ;
00186 float nx2=0.5*nx1 , ny2=0.5*ny1 , nz2=0.5*nz1 ;
00187 int ii,jj,kk , nup,nst ;
00188 float a0 , a1 , st ;
00189
00190 ENTRY("apply_yshear") ;
00191
00192
00193
00194 st = fabs(a)*nx2 + fabs(b)*nz2 + fabs(s) ; if( st < 1.e-3 ) EXRETURN ;
00195
00196 if( shift_method == MRI_FOURIER ){
00197 nst = ny + 0.5*st ;
00198 nup = csfft_nextup_one35(nst) ;
00199 } else if( shift_method == MRI_FOURIER_NOPAD ){
00200 nup = csfft_nextup_even(ny) ;
00201 }
00202
00203 fj0 = (float *) malloc( sizeof(float) * 2*ny ) ; fj1 = fj0 + ny ;
00204
00205 for( kk=0 ; kk < nz ; kk++ ){
00206 for( ii=0 ; ii < nx1 ; ii+=2 ){
00207 for( jj=0; jj < ny; jj++ ){ fj0[jj] = VV(ii,jj,kk) ; fj1[jj] = VV(ii+1,jj,kk) ; }
00208 a0 = a*(ii-nx2) + b*(kk-nz2) + s ;
00209 a1 = a0 + a ;
00210 shifter( ny , nup , a0 , fj0 , a1 , fj1 ) ;
00211 for( jj=0; jj < ny; jj++ ){ VV(ii,jj,kk) = fj0[jj] ; VV(ii+1,jj,kk) = fj1[jj] ; }
00212 }
00213
00214 if( ii == nx1 ){
00215 for( jj=0; jj < ny; jj++ ) fj0[jj] = VV(ii,jj,kk) ;
00216 a0 = a*(ii-nx2) + b*(kk-nz2) + s ;
00217 shifter( ny , nup , a0 , fj0 , a1 , NULL ) ;
00218 for( jj=0; jj < ny; jj++ ) VV(ii,jj,kk) = fj0[jj] ;
00219 }
00220 }
00221
00222 free(fj0) ; EXRETURN ;
00223 }
00224
00225
00226
00227
00228
00229 static void apply_zshear( float a , float b , float s ,
00230 int nx , int ny , int nz , float * v )
00231 {
00232 float * fj0 , * fj1 ;
00233 int nx1=nx-1 , ny1=ny-1 , nz1=nz-1 , nxy=nx*ny ;
00234 float nx2=0.5*nx1 , ny2=0.5*ny1 , nz2=0.5*nz1 ;
00235 int ii,jj,kk , nup,nst ;
00236 float a0 , a1 , st ;
00237
00238 ENTRY("apply_zshear") ;
00239
00240
00241
00242 st = fabs(a)*nx2 + fabs(b)*ny2 + fabs(s) ; if( st < 1.e-3 ) EXRETURN ;
00243
00244 if( shift_method == MRI_FOURIER ){
00245 nst = nz + 0.5*st ;
00246 nup = csfft_nextup_one35(nst) ;
00247 } else if( shift_method == MRI_FOURIER_NOPAD ){
00248 nup = csfft_nextup_even(nz) ;
00249 }
00250
00251 fj0 = (float *) malloc( sizeof(float) * 2*nz ) ; fj1 = fj0 + nz ;
00252
00253 for( jj=0 ; jj < ny ; jj++ ){
00254 for( ii=0 ; ii < nx1 ; ii+=2 ){
00255 for( kk=0; kk < nz; kk++ ){ fj0[kk] = VV(ii,jj,kk) ; fj1[kk] = VV(ii+1,jj,kk) ; }
00256 a0 = a*(ii-nx2) + b*(jj-ny2) + s ;
00257 a1 = a0 + a ;
00258 shifter( nz , nup , a0 , fj0 , a1 , fj1 ) ;
00259 for( kk=0; kk < nz; kk++ ){ VV(ii,jj,kk) = fj0[kk] ; VV(ii+1,jj,kk) = fj1[kk] ; }
00260 }
00261
00262 if( ii == nx1 ){
00263 for( kk=0; kk < nz; kk++ ) fj0[kk] = VV(ii,jj,kk) ;
00264 a0 = a*(ii-nx2) + b*(jj-ny2) + s ;
00265 shifter( nz , nup , a0 , fj0 , a1 , NULL ) ;
00266 for( kk=0; kk < nz; kk++ ) VV(ii,jj,kk) = fj0[kk] ;
00267 }
00268 }
00269
00270 free(fj0) ; EXRETURN ;
00271 }
00272
00273
00274
00275
00276
00277
00278 static void apply_3shear( MCW_3shear shr ,
00279 int nx , int ny , int nz , float * vol )
00280 {
00281 int qq ;
00282 float a , b , s ;
00283
00284 ENTRY("apply_3shear") ;
00285
00286 if( ! ISVALID_3SHEAR(shr) ) EXRETURN ;
00287
00288
00289
00290 if( shr.flip0 >= 0 ){
00291 switch( shr.flip0 + shr.flip1 ){
00292 case 1: flip_xy( nx,ny,nz,vol ) ; break ;
00293 case 2: flip_xz( nx,ny,nz,vol ) ; break ;
00294 case 3: flip_yz( nx,ny,nz,vol ) ; break ;
00295 default: EXRETURN ;
00296 }
00297 }
00298
00299
00300
00301 for( qq=0 ; qq < 4 ; qq++ ){
00302 switch( shr.ax[qq] ){
00303 case 0:
00304 a = shr.scl[qq][1] ;
00305 b = shr.scl[qq][2] ;
00306 s = shr.sft[qq] ;
00307 apply_xshear( a,b,s , nx,ny,nz , vol ) ;
00308 break ;
00309
00310 case 1:
00311 a = shr.scl[qq][0] ;
00312 b = shr.scl[qq][2] ;
00313 s = shr.sft[qq] ;
00314 apply_yshear( a,b,s , nx,ny,nz , vol ) ;
00315 break ;
00316
00317 case 2:
00318 a = shr.scl[qq][0] ;
00319 b = shr.scl[qq][1] ;
00320 s = shr.sft[qq] ;
00321 apply_zshear( a,b,s , nx,ny,nz , vol ) ;
00322 break ;
00323 }
00324 }
00325
00326 EXRETURN ;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 static int rotpx=0 , rotpy=0 , rotpz = 0 ;
00336 static int rotpset=0 ;
00337
00338 void THD_rota_setpad( int px , int py , int pz )
00339 {
00340 rotpx = (px > 0) ? px : 0 ;
00341 rotpy = (py > 0) ? py : 0 ;
00342 rotpz = (pz > 0) ? pz : 0 ;
00343 rotpset = 1 ;
00344 return ;
00345 }
00346
00347
00348
00349 void THD_rota_clearpad(void)
00350 {
00351 rotpx=rotpy=rotpz=0; rotpset=1; return;
00352 }
00353
00354 static void THD_rota_envpad(void)
00355 {
00356 char * eee = my_getenv("AFNI_ROTA_ZPAD") ;
00357 int ppp ;
00358
00359 if( rotpset ) return ;
00360 eee = my_getenv("AFNI_ROTA_ZPAD") ;
00361 if( eee != NULL ){
00362 ppp = strtol( eee , NULL , 10 ) ;
00363 THD_rota_setpad(ppp,ppp,ppp) ;
00364 }
00365 rotpset = 1 ; return ;
00366 }
00367
00368
00369
00370
00371
00372 #undef CLIPIT
00373
00374 void THD_rota_vol( int nx , int ny , int nz ,
00375 float xdel , float ydel , float zdel , float * vol ,
00376 int ax1,float th1, int ax2,float th2, int ax3,float th3,
00377 int dcode , float dx , float dy , float dz )
00378 {
00379 MCW_3shear shr ;
00380
00381 #ifdef CLIPIT
00382 register float bot , top ;
00383 register int nxyz=nx*ny*nz , ii ;
00384 #endif
00385
00386 ENTRY("THD_rota_vol") ;
00387
00388 if( nx < 2 || ny < 2 || nz < 2 || vol == NULL ) EXRETURN ;
00389
00390 if( xdel == 0.0 ) xdel = 1.0 ;
00391 if( ydel == 0.0 ) ydel = 1.0 ;
00392 if( zdel == 0.0 ) zdel = 1.0 ;
00393
00394 if( th1 == 0.0 && th2 == 0.0 && th3 == 0.0 ){
00395 th1 = 1.e-6 ; th2 = 1.1e-6 ; th3 = 0.9e-6 ;
00396 }
00397
00398 #if 0
00399 fprintf(stderr,"THD_rota_vol:\n") ;
00400 fprintf(stderr," th1=%g th2=%g th3=%g\n",th1,th2,th3) ;
00401 fprintf(stderr," dx=%g dy=%g dz=%g\n",dx,dy,dz) ;
00402 fprintf(stderr," xdel=%g ydel=%g zdel=%g\n",xdel,ydel,zdel) ;
00403 #endif
00404
00405 shr = rot_to_shear( ax1,-th1 , ax2,-th2 , ax3,-th3 ,
00406 dcode,dx,dy,dz , xdel,ydel,zdel ) ;
00407
00408 if( ! ISVALID_3SHEAR(shr) ){
00409 fprintf(stderr,"*** THD_rota_vol: can't compute shear transformation!\n") ;
00410 EXRETURN ;
00411 }
00412
00413 #if 0
00414 if( MRILIB_verbose )
00415 DUMP_3SHEAR("Computed shear",shr) ;
00416 #endif
00417
00418 #ifdef CLIPIT
00419 bot = top = vol[0] ;
00420 for( ii=1 ; ii < nxyz ; ii++ ){
00421 if( vol[ii] < bot ) bot = vol[ii] ;
00422 else if( vol[ii] > top ) top = vol[ii] ;
00423 }
00424 if( bot >= top ) EXRETURN ;
00425 #endif
00426
00427
00428
00429
00430 { float * vvv , *www ;
00431 int nxp , nyp , nzp ;
00432
00433 THD_rota_envpad() ;
00434
00435 nxp=nx+2*rotpx ; nyp=ny+2*rotpy ; nzp=nz+2*rotpz ;
00436
00437 if( rotpx > 0 && rotpy > 0 && rotpz > 0 )
00438 vvv = EDIT_volpad_even( rotpx,rotpy,rotpz , nx,ny,nz , MRI_float,vol ) ;
00439 else
00440 vvv = vol ;
00441
00442 apply_3shear( shr , nxp,nyp,nzp , vvv ) ;
00443
00444 if( vvv != vol ){
00445 www = EDIT_volpad_even( -rotpx,-rotpy,-rotpz , nxp,nyp,nzp , MRI_float,vvv ) ;
00446 free(vvv) ;
00447 memcpy( vol , www , sizeof(float)*nx*ny*nz ) ; free(www) ;
00448 }
00449 }
00450
00451
00452
00453 #ifdef CLIPIT
00454 for( ii=0 ; ii < nxyz ; ii++ ){
00455 if( vol[ii] < bot ) vol[ii] = bot ;
00456 else if( vol[ii] > top ) vol[ii] = top ;
00457 }
00458 #endif
00459
00460 EXRETURN ;
00461 }
00462
00463
00464
00465
00466
00467
00468 MRI_IMAGE * THD_rota3D( MRI_IMAGE * im ,
00469 int ax1,float th1, int ax2,float th2, int ax3,float th3,
00470 int dcode , float dx , float dy , float dz )
00471 {
00472 MRI_IMAGE * jm ;
00473 float * jvol ;
00474
00475 if( ! MRI_IS_3D(im) ){
00476 fprintf(stderr,"\n*** THD_rota3D: non-3D image input!\n") ;
00477 return NULL ;
00478 }
00479
00480 jm = mri_new_vol( im->nx , im->ny , im->nz , MRI_float ) ;
00481 MRI_COPY_AUX(jm,im) ;
00482 jvol = MRI_FLOAT_PTR(jm) ;
00483
00484 EDIT_coerce_type( im->nvox ,
00485 im->kind , mri_data_pointer(im) , MRI_float , jvol ) ;
00486
00487 THD_rota_vol( im->nx , im->ny , im->nz ,
00488 fabs(im->dx) , fabs(im->dy) , fabs(im->dz) , jvol ,
00489 ax1,th1 , ax2,th2 , ax3,th3 , dcode , dx,dy,dz ) ;
00490
00491 return jm ;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 #undef CLIPIT
00504
00505 void THD_rota_vol_matvec( int nx , int ny , int nz ,
00506 float xdel , float ydel , float zdel , float * vol ,
00507 THD_dmat33 rmat , THD_dfvec3 tvec )
00508 {
00509 MCW_3shear shr ;
00510 int dcode ;
00511
00512 #ifdef CLIPIT
00513 register float bot , top ;
00514 register int nxyz=nx*ny*nz , ii ;
00515 #endif
00516
00517 if( nx < 2 || ny < 2 || nz < 2 || vol == NULL ) return ;
00518
00519 if( xdel == 0.0 ) xdel = 1.0 ;
00520 if( ydel == 0.0 ) ydel = 1.0 ;
00521 if( zdel == 0.0 ) zdel = 1.0 ;
00522
00523 shr = rot_to_shear_matvec( rmat , tvec , xdel,ydel,zdel ) ;
00524
00525 if( ! ISVALID_3SHEAR(shr) ){
00526 fprintf(stderr,"*** THD_rota_vol: can't compute shear transformation!\n") ;
00527 return ;
00528 }
00529
00530 #if 0
00531 if( MRILIB_verbose )
00532 DUMP_3SHEAR("Computed shear",shr) ;
00533 #endif
00534
00535 #ifdef CLIPIT
00536 bot = top = vol[0] ;
00537 for( ii=1 ; ii < nxyz ; ii++ ){
00538 if( vol[ii] < bot ) bot = vol[ii] ;
00539 else if( vol[ii] > top ) top = vol[ii] ;
00540 }
00541 if( bot >= top ) return ;
00542 #endif
00543
00544
00545
00546
00547 { float * vvv , *www ;
00548 int nxp , nyp , nzp ;
00549
00550 THD_rota_envpad() ;
00551
00552 nxp=nx+2*rotpx ; nyp=ny+2*rotpy ; nzp=nz+2*rotpz ;
00553
00554 if( rotpx > 0 && rotpy > 0 && rotpz > 0 )
00555 vvv = EDIT_volpad_even( rotpx,rotpy,rotpz , nx,ny,nz , MRI_float,vol ) ;
00556 else
00557 vvv = vol ;
00558
00559 apply_3shear( shr , nxp,nyp,nzp , vvv ) ;
00560
00561 if( vvv != vol ){
00562 www = EDIT_volpad_even( -rotpx,-rotpy,-rotpz , nxp,nyp,nzp , MRI_float,vvv ) ;
00563 free(vvv) ;
00564 memcpy( vol , www , sizeof(float)*nx*ny*nz ) ; free(www) ;
00565 }
00566 }
00567
00568
00569
00570 #ifdef CLIPIT
00571 for( ii=0 ; ii < nxyz ; ii++ ){
00572 if( vol[ii] < bot ) vol[ii] = bot ;
00573 else if( vol[ii] > top ) vol[ii] = top ;
00574 }
00575 #endif
00576
00577 return ;
00578 }
00579
00580
00581
00582
00583
00584
00585
00586 MRI_IMAGE * THD_rota3D_matvec( MRI_IMAGE * im, THD_dmat33 rmat,THD_dfvec3 tvec )
00587 {
00588 MRI_IMAGE * jm ;
00589 float * jvol ;
00590
00591 if( ! MRI_IS_3D(im) ){
00592 fprintf(stderr,"\n*** THD_rota3D_matvec: non-3D image input!\n") ;
00593 return NULL ;
00594 }
00595
00596 jm = mri_new_vol( im->nx , im->ny , im->nz , MRI_float ) ;
00597 MRI_COPY_AUX(jm,im) ;
00598 jvol = MRI_FLOAT_PTR(jm) ;
00599
00600 EDIT_coerce_type( im->nvox ,
00601 im->kind , mri_data_pointer(im) , MRI_float , jvol ) ;
00602
00603 THD_rota_vol_matvec( im->nx , im->ny , im->nz ,
00604 fabs(im->dx) , fabs(im->dy) , fabs(im->dz) , jvol ,
00605 rmat , tvec ) ;
00606 return jm ;
00607 }