#include "mrilib.h" int main( int argc , char * argv[] ) { int iarg ; THD_3dim_dataset *inset , *outset ; int add_I=0 , add_S=0 , add_A=0 , add_P=0 , add_L=0 , add_R=0 ; int RLsiz=0, APsiz=0, ISsiz=0 ; /* 23 Mar 2004 */ char * prefix="zeropad" ; int add_z=0 ; /* 07 Feb 2001 */ int mm_flag=0 ; /* 13 Feb 2001 */ int flag ; THD_3dim_dataset *mset=NULL ; /* 14 May 2002 */ /*-- help? --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 3dZeropad [options] dataset\n" "Adds planes of zeros to a dataset (i.e., pads it out).\n" "\n" "Options:\n" " -I n = adds 'n' planes of zero at the Inferior edge\n" " -S n = adds 'n' planes of zero at the Superior edge\n" " -A n = adds 'n' planes of zero at the Anterior edge\n" " -P n = adds 'n' planes of zero at the Posterior edge\n" " -L n = adds 'n' planes of zero at the Left edge\n" " -R n = adds 'n' planes of zero at the Right edge\n" " -z n = adds 'n' planes of zeros on EACH of the\n" " dataset z-axis (slice-direction) faces\n" "\n" " -RL a = These options specify that planes should be added/cut\n" " -AP b = symmetrically to make the resulting volume have\n" " -IS c = 'a', 'b', and 'c' slices in the respective directions.\n" "\n" " -mm = pad counts 'n' are in mm instead of slices:\n" " * each 'n' is an integer\n" " * at least 'n' mm of slices will be added/removed:\n" " n = 3 and slice thickness = 2.5 mm ==> 2 slices added\n" " n = -6 and slice thickness = 2.5 mm ==> 3 slices removed\n" "\n" " -master mset = match the volume described in dataset 'mset':\n" " * mset must have the same orientation and grid\n" " spacing as dataset to be padded\n" " * the goal of -master is to make the output dataset\n" " from 3dZeropad match the spatial 'extents' of\n" " mset (cf. 3dinfo output) as much as possible,\n" " by adding/subtracting slices as needed.\n" " * you can't use -I,-S,..., or -mm with -master\n" "\n" " -prefix ppp = write result into dataset with prefix 'ppp'\n" " [default = 'zeropad']\n" "\n" "Nota Bene:\n" " * You can use negative values of n to cut planes off the edges\n" " of a dataset. At least one plane must be added/removed\n" " or the program won't do anything.\n" " * Anat parent and Talairach markers are NOT preserved in the\n" " new dataset.\n" #if 0 " * If the old dataset has z-slice-dependent time offsets, and\n" " if new z-planes are added, all the slice-dependent time\n" " offsets will be removed.\n" #else " * If the old dataset has z-slice-dependent time offsets, and\n" " if new (zero filled) z-planes are added, the time offsets\n" " of the new slices will be set to zero.\n" #endif " * You can use program '3dinfo' to find out how many planes\n" " a dataset has in each direction.\n" " * Program works for byte-, short-, float-, and complex-valued\n" " datasets.\n" " * You can use a sub-brick selector on the input dataset.\n" " * 3dZeropad won't overwrite an existing dataset (I hope).\n" "\n" " Author: RWCox - July 2000\n" ) ; exit(0) ; } mainENTRY("3dZeropad main"); machdep(); AFNI_logger("3dZeropad",argc,argv); PRINT_VERSION("3dZeropad") ; /*-- read command line options --*/ iarg = 1 ; while( iarg < argc && argv[iarg][0] == '-' ){ /*- -I, -S, etc. -*/ if( strlen(argv[iarg]) == 2 ){ switch( argv[iarg][1] ){ case 'I': add_I = (int) strtod(argv[++iarg],NULL) ; break ; case 'S': add_S = (int) strtod(argv[++iarg],NULL) ; break ; case 'A': add_A = (int) strtod(argv[++iarg],NULL) ; break ; case 'P': add_P = (int) strtod(argv[++iarg],NULL) ; break ; case 'L': add_L = (int) strtod(argv[++iarg],NULL) ; break ; case 'R': add_R = (int) strtod(argv[++iarg],NULL) ; break ; /* 07 Feb 2001: slice-direction is special */ case 'z': case 'Z': add_z = (int) strtod(argv[++iarg],NULL) ; break ; default: fprintf(stderr,"** 3dZeropad: Illegal option: %s\n",argv[iarg]) ; exit(1) ; } if( mset != NULL ){ fprintf(stderr,"** 3dZeropad: Can't use %s with -master!\n",argv[iarg-1]) ; exit(1) ; } iarg++ ; continue ; /* skip to next argument */ } /*- -RL, -AP, -IS [23 Mar 2004] -*/ if( strcmp(argv[iarg],"-RL") == 0 || strcmp(argv[iarg],"-LR") == 0 ){ if( add_R || add_L || mset != NULL ){ fprintf(stderr,"** 3dZeropad: Can't use -RL with -R, -L, or -master!\n"); exit(1) ; } RLsiz = (int) strtod(argv[++iarg],NULL) ; if( RLsiz < 1 ){ fprintf(stderr,"** 3dZeropad: value after -RL is illegal!\n") ; exit(1) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-AP") == 0 || strcmp(argv[iarg],"-PA") == 0 ){ if( add_A || add_P || mset != NULL ){ fprintf(stderr,"** 3dZeropad: Can't use -AP with -A, -P, or -master!\n"); exit(1) ; } APsiz = (int) strtod(argv[++iarg],NULL) ; if( APsiz < 1 ){ fprintf(stderr,"** 3dZeropad: value after -AP is illegal!\n") ; exit(1) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-IS") == 0 || strcmp(argv[iarg],"-SI") == 0 ){ if( add_S || add_I || mset != NULL ){ fprintf(stderr,"** 3dZeropad: Can't use -IS with -I, -S, or -master!\n"); exit(1) ; } ISsiz = (int) strtod(argv[++iarg],NULL) ; if( ISsiz < 1 ){ fprintf(stderr,"** 3dZeropad: value after -IS is illegal!\n") ; exit(1) ; } iarg++ ; continue ; } /*- -mm -*/ if( strcmp(argv[iarg],"-mm") == 0 ){ if( mset != NULL ){ fprintf(stderr,"** 3dZeropad: Can't use %s with -master!\n",argv[iarg]) ; exit(1) ; } mm_flag = 1 ; iarg++ ; continue ; } /*- -prefix -*/ if( strcmp(argv[iarg],"-prefix") == 0 ){ prefix = argv[++iarg] ; if( !THD_filename_ok(prefix) ){ fprintf(stderr,"** 3dZeropad: Illegal string after -prefix!\n"); exit(1) ; } iarg++ ; continue ; } /*-- -master [14 May 2002] --*/ if( strcmp(argv[iarg],"-master") == 0 ){ if( add_I || add_S || add_A || mm_flag || add_P || add_R || add_L || add_z || RLsiz || APsiz || ISsiz ){ fprintf(stderr,"** 3dZeropad: Can't use -master with -I,-S,-A,-P,-R,-L, or -mm!\n"); exit(1) ; } if( mset != NULL ){ fprintf(stderr,"** 3dZeropad: Can't use -master twice!\n"); exit(1); } mset = THD_open_dataset( argv[++iarg] ) ; if( !ISVALID_DSET(mset) ){ fprintf(stderr,"** 3dZeropad: Can't open -master %s\n",argv[iarg]); exit(1); } iarg++ ; continue ; } /*- what the hell? -*/ fprintf(stderr,"** 3dZeropad: Illegal option: %s\n",argv[iarg]) ; exit(1) ; } /*- check to see if the user asked for something, anything -*/ if( mset == NULL ){ if( add_I==0 && add_S==0 && add_P==0 && add_A==0 && add_L==0 && add_R==0 && add_z==0 && RLsiz==0 && APsiz==0 && ISsiz==0 ){ fprintf(stderr,"++ 3dZeropad: All inputs are zero? Making a copy!\n") ; } } /* check for conflicts [23 Mar 2004] */ if( RLsiz > 0 && (add_R || add_L || add_z) ){ fprintf(stderr,"** 3dZeropad: Can't use -R or -L or -z with -RL!\n"); exit(1); } if( APsiz > 0 && (add_A || add_P || add_z) ){ fprintf(stderr,"** 3dZeropad: Can't use -A or -P or -z with -AP!\n"); exit(1); } if( ISsiz > 0 && (add_I || add_S || add_z) ){ fprintf(stderr,"** 3dZeropad: Can't use -I or -S or -z with -IS!\n"); exit(1); } /*-- read the input dataset --*/ if( iarg >= argc ){ fprintf(stderr,"** 3dZeropad: No input dataset on command line!\n"); exit(1); } #if 0 if( strncmp(argv[iarg],"3dcalc(",7) == 0 ){ fprintf(stderr,"** 3dZeropad: Can't use '3dcalc()' input datasets here!\n"); exit(1); } #endif inset = THD_open_dataset( argv[iarg] ) ; if( inset == NULL ){ fprintf(stderr,"** 3dZeropad: Can't open dataset %s\n",argv[iarg]); exit(1); } #if 0 if( DSET_IS_MASTERED(inset) ){ fprintf(stderr,"** 3dZeropad: Can't use partial datasets!\n"); exit(1); } #endif /*-- 14 May 2002: use master dataset now? --*/ if( mset != NULL ){ THD_dataxes *max=mset->daxes, *iax=inset->daxes ; int nerr=0 ; float mxbot,mybot,mzbot , mxtop,mytop,mztop , mdx,mdy,mdz ; float ixbot,iybot,izbot , ixtop,iytop,iztop , idx,idy,idz ; int mnx,mny,mnz , inx,iny,inz ; int add_xb,add_xt , add_yb,add_yt , add_zb,add_zt ; /* check if datasets are oriented the same */ if( max->xxorient != iax->xxorient || max->yyorient != iax->yyorient || max->zzorient != iax->zzorient ){ fprintf(stderr,"** 3dZeropad: Master and Input datasets not oriented the same!\n"); nerr++ ; } /* check if datasets have same voxel dimensions */ mdx = max->xxdel ; mdy = max->yydel ; mdz = max->zzdel ; idx = iax->xxdel ; idy = iax->yydel ; idz = iax->zzdel ; mnx = max->nxx ; mny = max->nyy ; mnz = max->nzz ; inx = iax->nxx ; iny = iax->nyy ; inz = iax->nzz ; if( fabs(mdx-idx) > 0.01*fabs(mdx) || fabs(mdy-idy) > 0.01*fabs(mdy) || fabs(mdz-idz) > 0.01*fabs(mdz) ){ fprintf(stderr,"** 3dZeropad: Master and Input datasets don't have same voxel size!\n"); nerr++ ; } if( nerr ) exit(1) ; /* calculate coords at top and bottom of each dataset */ mxbot = max->xxorg ; mxtop = mxbot + mnx*mdx ; mybot = max->yyorg ; mytop = mybot + mny*mdy ; mzbot = max->zzorg ; mztop = mzbot + mnz*mdz ; ixbot = iax->xxorg ; ixtop = ixbot + inx*idx ; iybot = iax->yyorg ; iytop = iybot + iny*idy ; izbot = iax->zzorg ; iztop = izbot + inz*idz ; /* calculate amount to add/trim at each face */ add_xb = (int) rint((ixbot-mxbot)/idx) ; add_xt = (int) rint((mxtop-ixtop)/idx) ; add_yb = (int) rint((iybot-mybot)/idy) ; add_yt = (int) rint((mytop-iytop)/idy) ; add_zb = (int) rint((izbot-mzbot)/idz) ; add_zt = (int) rint((mztop-iztop)/idz) ; /* map trims from x,y,z to RL,AP,IS coords */ switch( iax->xxorient ){ case ORI_R2L_TYPE: add_R = add_xb ; add_L = add_xt ; break ; case ORI_L2R_TYPE: add_L = add_xb ; add_R = add_xt ; break ; case ORI_I2S_TYPE: add_I = add_xb ; add_S = add_xt ; break ; case ORI_S2I_TYPE: add_S = add_xb ; add_I = add_xt ; break ; case ORI_A2P_TYPE: add_A = add_xb ; add_P = add_xt ; break ; case ORI_P2A_TYPE: add_P = add_xb ; add_A = add_xt ; break ; } switch( iax->yyorient ){ case ORI_R2L_TYPE: add_R = add_yb ; add_L = add_yt ; break ; case ORI_L2R_TYPE: add_L = add_yb ; add_R = add_yt ; break ; case ORI_I2S_TYPE: add_I = add_yb ; add_S = add_yt ; break ; case ORI_S2I_TYPE: add_S = add_yb ; add_I = add_yt ; break ; case ORI_A2P_TYPE: add_A = add_yb ; add_P = add_yt ; break ; case ORI_P2A_TYPE: add_P = add_yb ; add_A = add_yt ; break ; } switch( iax->zzorient ){ case ORI_R2L_TYPE: add_R = add_zb ; add_L = add_zt ; break ; case ORI_L2R_TYPE: add_L = add_zb ; add_R = add_zt ; break ; case ORI_I2S_TYPE: add_I = add_zb ; add_S = add_zt ; break ; case ORI_S2I_TYPE: add_S = add_zb ; add_I = add_zt ; break ; case ORI_A2P_TYPE: add_A = add_zb ; add_P = add_zt ; break ; case ORI_P2A_TYPE: add_P = add_zb ; add_A = add_zt ; break ; } fprintf(stderr,"++ 3dZeropad -master => -I %d -S %d -A %d -P %d -R %d -L %d\n", add_I,add_S,add_A,add_P,add_R,add_L ) ; DSET_delete(mset) ; } /*-- 07 Feb 2001: if -z was used, fix that now --*/ if( add_z != 0 ){ switch( inset->daxes->zzorient ){ case ORI_R2L_TYPE: case ORI_L2R_TYPE: if( add_R != 0 && add_R != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -R\n"); if( add_L != 0 && add_L != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -L\n"); add_R = add_L = add_z ; break ; case ORI_P2A_TYPE: case ORI_A2P_TYPE: if( add_P != 0 && add_P != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -P\n"); if( add_A != 0 && add_A != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -A\n"); add_P = add_A = add_z ; break ; case ORI_I2S_TYPE: case ORI_S2I_TYPE: if( add_I != 0 && add_I != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -I\n"); if( add_I != 0 && add_S != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -S\n"); add_I = add_S = add_z ; break ; } } /*-- 23 Mar 2004: expand/contract if ordered --*/ if( RLsiz > 0 ){ int nold=0 ; if( inset->daxes->xxorient == ORI_R2L_TYPE || inset->daxes->xxorient == ORI_L2R_TYPE ) nold = inset->daxes->nxx ; else if( inset->daxes->yyorient == ORI_R2L_TYPE || inset->daxes->yyorient == ORI_L2R_TYPE ) nold = inset->daxes->nyy ; else if( inset->daxes->zzorient == ORI_R2L_TYPE || inset->daxes->zzorient == ORI_L2R_TYPE ) nold = inset->daxes->nzz ; if( nold > 0 ){ add_R = (RLsiz-nold) / 2 ; add_L = RLsiz-(nold+add_R) ; } } if( APsiz > 0 ){ int nold=0 ; if( inset->daxes->xxorient == ORI_A2P_TYPE || inset->daxes->xxorient == ORI_P2A_TYPE ) nold = inset->daxes->nxx ; else if( inset->daxes->yyorient == ORI_A2P_TYPE || inset->daxes->yyorient == ORI_P2A_TYPE ) nold = inset->daxes->nyy ; else if( inset->daxes->zzorient == ORI_A2P_TYPE || inset->daxes->zzorient == ORI_P2A_TYPE ) nold = inset->daxes->nzz ; if( nold > 0 ){ add_A = (APsiz-nold) / 2 ; add_P = APsiz-(nold+add_A) ; } } if( ISsiz > 0 ){ int nold=0 ; if( inset->daxes->xxorient == ORI_I2S_TYPE || inset->daxes->xxorient == ORI_S2I_TYPE ) nold = inset->daxes->nxx ; else if( inset->daxes->yyorient == ORI_I2S_TYPE || inset->daxes->yyorient == ORI_S2I_TYPE ) nold = inset->daxes->nyy ; else if( inset->daxes->zzorient == ORI_I2S_TYPE || inset->daxes->zzorient == ORI_S2I_TYPE ) nold = inset->daxes->nzz ; if( nold > 0 ){ add_I = (ISsiz-nold) / 2 ; add_S = ISsiz-(nold+add_I) ; } } /*-- 04 Oct 2000: all the real work is now in thd_zeropad.c --*/ flag = ZPAD_PURGE ; if( mm_flag ) flag |= ZPAD_MM ; outset = THD_zeropad( inset , add_I, add_S, add_A, add_P, add_L, add_R, prefix , flag ) ; if( THD_deathcon() && THD_is_file(DSET_HEADNAME(outset)) ){ fprintf(stderr, "** 3dZeropad: output file %s already exists - FATAL ERROR!\n", DSET_HEADNAME(outset) ) ; exit(1) ; } if( outset == NULL ){ fprintf(stderr,"** 3dZeropad: Some error occurred in processing!\n") ; exit(1) ; } tross_Copy_History( inset , outset ) ; /* 31 Jan 2001 - RWCox */ tross_Make_History( "3dZeropad" , argc,argv , outset ) ; DSET_write(outset) ; fprintf(stderr,"++ output dataset: %s\n",DSET_BRIKNAME(outset)) ; exit(0) ; }