1 #include "mrilib.h"
2 
3 /*----------------------------------------------------------------------------*/
4 static int  use_padval =  0 ;
5 static int  typ_padval = -1 ;
6 static char     padval[32] ;
7 
EDIT_set_padval(int ftype,char * pval)8 void EDIT_set_padval( int ftype , char *pval )
9 {
10    int dsiz = mri_datum_size(ftype) ;
11    if( pval == NULL || dsiz == 0 ){ use_padval = 0; typ_padval = -1; return; }
12    memcpy( padval , pval , dsiz ) ;
13    use_padval = 1 ; typ_padval = ftype ;
14    return ;
15 }
16 
17 /*----------------------------------------------------------------------------*/
18 /***** pad a volume by adding/subtracting planes of zeros:
19         nxbot = # to add on -x side (can be negative, to remove planes)
20         nxtop = # to add on +x side, etc.
21        If all n?bot,n?top values are zero, just returns a copy
22        of the input.  If too much is cut off, or something else
23        bad happens, returns NULL.
24 
25        Adapted from thd_zeropad.c       -- 02 Feb 2001 -- RWCox
26        Modified to allow uneven padding -- 09 Feb 2001 -- RWCox *****/
27 
EDIT_volpad(int nxbot,int nxtop,int nybot,int nytop,int nzbot,int nztop,int nx,int ny,int nz,int ftype,void * fim)28 void * EDIT_volpad( int nxbot , int nxtop ,
29                     int nybot , int nytop ,
30                     int nzbot , int nztop ,
31                     int nx, int ny, int nz, int ftype, void *fim )
32 {
33    int nxold,nyold,nzold , nxnew,nynew,nznew , nxyold,nxynew ;
34    int ii,jj,kk , iv , iibot,iitop , jjbot,jjtop , kkbot,kktop ;
35    void *vnew ;
36 
37 ENTRY("EDIT_volpad") ;
38 
39    /*- check for user stupidity -*/
40 
41    if( nx <= 0 || ny <= 0 || nz <= 0 || fim == NULL ) RETURN(NULL) ;
42 
43    /*- special case: just copy input -*/
44 
45    if( nxbot == 0 && nybot == 0 && nzbot == 0 &&
46        nxtop == 0 && nytop == 0 && nztop == 0   ){
47 
48       vnew = malloc( mri_datum_size(ftype) * nx*ny*nz ) ;
49       memcpy( vnew , fim , mri_datum_size(ftype) * nx*ny*nz ) ;
50       RETURN(vnew) ;
51    }
52 
53    nxold = nx ; nxnew = nxold + nxbot + nxtop ;  /* dimensions */
54    nyold = ny ; nynew = nyold + nybot + nytop ;
55    nzold = nz ; nznew = nzold + nzbot + nztop ;
56 
57    nxyold = nxold * nyold ; /* for computing 3D subscripts */
58    nxynew = nxnew * nynew ;
59 
60    iibot = MAX(0,-nxbot) ; iitop = MIN(nxold,nxold+nxtop) ;  /* range of data  */
61    jjbot = MAX(0,-nybot) ; jjtop = MIN(nyold,nyold+nytop) ;  /* in old dataset */
62    kkbot = MAX(0,-nzbot) ; kktop = MIN(nzold,nzold+nztop) ;  /* to copy to new */
63 
64    if( nxnew < 2 || iibot >= iitop ||   /* check for reasonable sizes */
65        nynew < 2 || jjbot >= jjtop ||   /* and ranges of dataset     */
66        nznew < 2 || kkbot >= kktop   ){
67 
68       ERROR_message("EDIT_volpad: can't cut volume down to nothing!") ;
69       RETURN(NULL) ;
70    }
71 
72    vnew = calloc( nxnew*nynew*nznew , mri_datum_size(ftype) ) ; /* new brick */
73    if( vnew == NULL ){
74       ERROR_message("EDIT_volpad: Can't malloc space for new array") ;
75       RETURN(NULL) ;
76    }
77 
78    /* non-zero pad value was set? copy it over all the data [22 Sep 2020]  */
79 
80    if( use_padval && typ_padval == ftype ){
81      int dsiz = mri_datum_size(ftype) , nvox = nxnew*nynew*nznew ;
82      char *cnew = (char *)vnew ;
83      if( dsiz == 1 ){
84        memset( cnew , nvox , padval[0] ) ;
85      } else {
86        for( ii=0 ; ii < nvox ; ii++ )
87          memcpy( cnew + ii*dsiz , padval , dsiz ) ;
88      }
89    }
90 
91    /* macros for computing 1D subscripts from 3D indices */
92 
93 #undef  SNEW  /* in case was defined in some stupid .h file */
94 #undef  SOLD
95 #define SNEW(i,j,k) ((i+nxbot)+(j+nybot)*nxnew+(k+nzbot)*nxynew)
96 #define SOLD(i,j,k) (i+j*nxold+k*nxyold)
97 
98    switch( ftype ){  /* copy rows of old into new */
99 
100       default:
101          ERROR_message("EDIT_volpad: unknown input datum=%d",ftype) ;
102          free(vnew) ;
103       RETURN(NULL) ;
104 
105       case MRI_byte:{
106          byte *bnew = (byte *) vnew, *bold = (byte *) fim ;
107          for( kk=kkbot ; kk < kktop ; kk++ )
108             for( jj=jjbot ; jj < jjtop ; jj++ )
109                for( ii=iibot ; ii < iitop ; ii++ )
110                   bnew[SNEW(ii,jj,kk)] = bold[SOLD(ii,jj,kk)] ;
111       }
112       break ;
113 
114       case MRI_rgb:{
115          byte *bnew = (byte *) vnew, *bold = (byte *) fim ;
116          for( kk=kkbot ; kk < kktop ; kk++ )
117             for( jj=jjbot ; jj < jjtop ; jj++ )
118                for( ii=iibot ; ii < iitop ; ii++ ){
119                   bnew[3*SNEW(ii,jj,kk)  ] = bold[3*SOLD(ii,jj,kk)  ] ;
120                   bnew[3*SNEW(ii,jj,kk)+1] = bold[3*SOLD(ii,jj,kk)+1] ;
121                   bnew[3*SNEW(ii,jj,kk)+2] = bold[3*SOLD(ii,jj,kk)+2] ;
122                }
123       }
124       break ;
125 
126       case MRI_short:{
127          short *bnew = (short *) vnew, *bold = (short *) fim ;
128          for( kk=kkbot ; kk < kktop ; kk++ )
129             for( jj=jjbot ; jj < jjtop ; jj++ )
130                for( ii=iibot ; ii < iitop ; ii++ )
131                   bnew[SNEW(ii,jj,kk)] = bold[SOLD(ii,jj,kk)] ;
132       }
133       break ;
134 
135       case MRI_int:{
136          int *bnew = (int *) vnew, *bold = (int *) fim ;
137          for( kk=kkbot ; kk < kktop ; kk++ )
138             for( jj=jjbot ; jj < jjtop ; jj++ )
139                for( ii=iibot ; ii < iitop ; ii++ )
140                   bnew[SNEW(ii,jj,kk)] = bold[SOLD(ii,jj,kk)] ;
141       }
142       break ;
143 
144       case MRI_float:{
145          float *bnew = (float *) vnew, *bold = (float *) fim ;
146          for( kk=kkbot ; kk < kktop ; kk++ )
147             for( jj=jjbot ; jj < jjtop ; jj++ )
148                for( ii=iibot ; ii < iitop ; ii++ )
149                   bnew[SNEW(ii,jj,kk)] = bold[SOLD(ii,jj,kk)] ;
150       }
151       break ;
152 
153       case MRI_double:{
154          double *bnew = (double *) vnew, *bold = (double *) fim ;
155          for( kk=kkbot ; kk < kktop ; kk++ )
156             for( jj=jjbot ; jj < jjtop ; jj++ )
157                for( ii=iibot ; ii < iitop ; ii++ )
158                   bnew[SNEW(ii,jj,kk)] = bold[SOLD(ii,jj,kk)] ;
159       }
160       break ;
161 
162       case MRI_complex:{
163          complex *bnew = (complex *) vnew, *bold = (complex *) fim ;
164          for( kk=kkbot ; kk < kktop ; kk++ )
165             for( jj=jjbot ; jj < jjtop ; jj++ )
166                for( ii=iibot ; ii < iitop ; ii++ )
167                   bnew[SNEW(ii,jj,kk)] = bold[SOLD(ii,jj,kk)] ;
168       }
169       break ;
170 
171    } /* end of switch on datum type */
172 
173    RETURN(vnew) ;
174 }
175 
176 /*------------------------------------------------------------------
177   14 Feb 2001: do the above to an image struct, just for fun
178 --------------------------------------------------------------------*/
179 
mri_zeropad_3D(int nxbot,int nxtop,int nybot,int nytop,int nzbot,int nztop,MRI_IMAGE * im)180 MRI_IMAGE * mri_zeropad_3D( int nxbot , int nxtop ,
181                             int nybot , int nytop ,
182                             int nzbot , int nztop , MRI_IMAGE *im )
183 {
184    MRI_IMAGE *jm ;
185    void *var ;
186 
187 ENTRY("mri_zeropad_3D") ;
188 
189    if( im == NULL ) RETURN(NULL) ; /* bad */
190 
191    if( !MRI_IS_3D(im) ){
192      jm = mri_zeropad_2D( nxbot,nxtop , nybot,nytop , im ) ;
193      RETURN(jm) ;
194    }
195 
196    /* do the padding work */
197 
198    var = EDIT_volpad( nxbot,nxtop,nybot,nytop,nzbot,nztop ,
199                       im->nx , im->ny , im->nz ,
200                       im->kind , mri_data_pointer(im) ) ;
201 
202    if( var == NULL ) RETURN(NULL) ; /* bad */
203 
204    /* put padded data into new image */
205 
206    jm = mri_new_vol_empty( im->nx + nxbot + nxtop ,
207                            im->ny + nybot + nytop ,
208                            im->nz + nzbot + nztop , im->kind ) ;
209    MRI_COPY_AUX(jm,im) ;
210    mri_fix_data_pointer( var , jm ) ;
211    RETURN( jm );
212 }
213