Doxygen Source Code Documentation
mri_read_dicom.c File Reference
#include "mrilib.h"
Go to the source code of this file.
Define Documentation
|
|
|
Definition at line 110 of file mri_read_dicom.c. |
|
Definition at line 97 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 98 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 95 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 85 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 104 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 108 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 109 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 89 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 88 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 93 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 87 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 102 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 103 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 96 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 83 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 99 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 100 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 101 of file mri_read_dicom.c. |
|
Definition at line 94 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 92 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 112 of file mri_read_dicom.c. |
|
Definition at line 113 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 90 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 84 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 82 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 105 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
Definition at line 106 of file mri_read_dicom.c. Referenced by mri_read_dicom(). |
|
|
|
Definition at line 5 of file mri_read_dicom.c. Referenced by get_siemens_extra_info(). |
|
Definition at line 80 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
|
Function Documentation
|
Read some bytes from an open file at a given offset. Return them in a newly malloc()-ed array. If return value is NULL, something bad happened. ---------------------------------------------------------------------------------- Definition at line 1318 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom().
01319 { 01320 char *ar ; 01321 size_t nn , ii ; 01322 01323 if( fp == NULL || len == 0 ) return NULL ; /* bad inputs? */ 01324 ar = AFMALL(char, len+1) ; /* make space for data */ 01325 lseek( fileno(fp) , start , SEEK_SET ) ; /* set file position */ 01326 nn = fread( ar , 1 , len , fp ) ; /* read data */ 01327 if( nn == 0 ){ free(ar); return NULL; } /* bad read? */ 01328 01329 if( strize ){ /* convert to C string? */ 01330 for( ii=0 ; ii < nn ; ii++ ) /* scan for NULs and */ 01331 if( ar[ii] == '\0' ) ar[ii] = ' ' ; /* replace with blanks */ 01332 } 01333 return ar ; 01334 } |
|
Parse the Siemens extra stuff for mosaic information. Ad hoc, based on sample data and no documentation. ---------------------------------------------------------------------------------- Definition at line 1341 of file mri_read_dicom.c. References Siemens_extra_info::good, Siemens_extra_info::have_data, Siemens_extra_info::mosaic_num, name, NMOMAX, and Siemens_extra_info::slice_xyz. Referenced by mri_imcount_dicom(), and mri_read_dicom().
01342 { 01343 char *cpt , *dpt ; 01344 int nn , mm , snum , last_snum=-1 ; 01345 int have_x[2] = {0,0}, 01346 have_y[2] = {0,0}, 01347 have_z[2] = {0,0}; 01348 float x,y,z , val ; 01349 char name[1024] ; 01350 01351 /*-- check for good inputs --*/ 01352 01353 if( mi == NULL ) return ; 01354 01355 mi->good = 0 ; 01356 for( snum=0 ; snum < NMOMAX ; snum++ ) 01357 mi->slice_xyz[snum][0] = mi->slice_xyz[snum][1] = mi->slice_xyz[snum][2] = 0.0 ; 01358 01359 if( str == NULL || *str == '\0' ) return ; 01360 01361 /*-- find string that starts the slice information array --*/ 01362 /* 04 Mar 2003 reworked this section to skip "fake matches" * 01363 * of the target string present in some mosaic files in the * 01364 * binary section --KRH */ 01365 nn = 0; 01366 while (nn == 0) { 01367 01368 cpt = strstr( str , "sSliceArray.asSlice[" ) ; 01369 if( cpt == NULL ) return ; 01370 /* interepret next string into 01371 snum = slice subscript (0,1,...) 01372 name = variable name 01373 val = number of RHS of '=' sign 01374 mm = # of bytes used in scanning the above */ 01375 01376 nn = sscanf( cpt , "sSliceArray.asSlice[%d].%1022s =%f%n" , 01377 &snum , name , &val , &mm ) ; 01378 str += 20; /* skip to end of "false match" string KRH */ 01379 } 01380 01381 01382 /*-- scan for coordinates, until can't find a good string to scan --*/ 01383 01384 #if 0 01385 /* 25 Feb 2003 Changed logic here KRH */ 01386 have_x = have_y = have_z = 0 ; 01387 #endif 01388 01389 while(1){ 01390 01391 01392 01393 if( nn < 3 ) break ; /* bad conversion set */ 01394 if( snum < 0 || snum >= NMOMAX ) break ; /* slice number out of range */ 01395 01396 /* 21 Feb 2003 rework this section to allow for missing coordinates in 01397 * some mosaic files --KRH */ 01398 #if 0 01399 /* assign val based on name */ 01400 01401 if( strcmp(name,"sPosition.dSag") == 0 ){ x = val; have_x = 1; } 01402 else if( strcmp(name,"sPosition.dCor") == 0 ){ y = val; have_y = 1; } 01403 else if( strcmp(name,"sPosition.dTra") == 0 ){ z = val; have_z = 1; } 01404 01405 /* if now have all 3 coordinates, save them */ 01406 01407 if( have_x && have_y && have_z ){ 01408 mi->slice_xyz[snum][0] = x; mi->slice_xyz[snum][1] = y; mi->slice_xyz[snum][2] = z; 01409 last_snum = snum ; 01410 have_x = have_y = have_z = 0 ; 01411 } 01412 #endif 01413 01414 if( strcmp(name,"sPosition.dSag") == 0 ){ 01415 mi->slice_xyz[snum][0] = val; 01416 if (snum < 2) have_x[snum] = 1; 01417 last_snum = snum; 01418 } else if( strcmp(name,"sPosition.dCor") == 0 ){ 01419 mi->slice_xyz[snum][1] = val; 01420 if (snum < 2) have_y[snum] = 1; 01421 last_snum = snum; 01422 } else if( strcmp(name,"sPosition.dTra") == 0 ){ 01423 mi->slice_xyz[snum][2] = val; 01424 if (snum < 2) have_z[snum] = 1; 01425 last_snum = snum; 01426 } 01427 01428 /* skip to next slice array assignment string (which may not be a coordinate) */ 01429 01430 dpt = cpt + mm ; /* just after 'val' */ 01431 cpt = dpt ; 01432 while( isspace(*cpt) ) cpt++ ; /* skip over whitespace */ 01433 if( cpt-dpt > 16 ) break ; /* too much space */ 01434 if( strncmp(cpt,"sSliceArray.asSlice[",20) != 0 ) break ; /* bad next line */ 01435 /* 04 Mar 2003 moved this stuff around to allow for locating "fake matches" * 01436 * of the target text in some mosaic files' binary sections */ 01437 01438 /* interpret next string into 01439 snum = slice subscript (0,1,...) 01440 name = variable name 01441 val = number of RHS of '=' sign 01442 mm = # of bytes used in scanning the above */ 01443 01444 nn = sscanf( cpt , "sSliceArray.asSlice[%d].%1022s =%f%n" , 01445 &snum , name , &val , &mm ) ; 01446 01447 } 01448 01449 /* if got at least 1 slice info, mark data as being good */ 01450 01451 if( last_snum >= 0 ){ 01452 mi->good = 1 ; 01453 if (have_x[0] && have_x[1]) mi->have_data[0] = 1; 01454 if (have_y[0] && have_y[1]) mi->have_data[1] = 1; 01455 if (have_z[0] && have_z[1]) mi->have_data[2] = 1; 01456 mi->mosaic_num = last_snum+1 ; 01457 } 01458 01459 return ; 01460 } |
|
Definition at line 23 of file mri_read_dicom.c. References str_sexinfo. Referenced by main().
00023 { return str_sexinfo; } /* 23 Dec 2002 */ |
|
Count images in a DICOM file, if possible. -------------------------------------------------------------------------------- Definition at line 1146 of file mri_read_dicom.c. References AFMALL, E_BITS_ALLOCATED, E_COLUMNS, E_ID_IMAGE_TYPE, E_ID_MANUFACTURER, E_NUMBER_OF_FRAMES, E_PHOTOMETRIC_INTERPRETATION, E_ROWS, E_SAMPLES_PER_PIXEL, E_SIEMENS_2, elist, ENTRY, extract_bytes_from_file(), free, get_siemens_extra_info(), Siemens_extra_info::good, Siemens_extra_info::mosaic_num, mri_dicom_header(), mri_dicom_nohex(), mri_dicom_noname(), mri_dicom_pxlarr(), mri_possibly_dicom(), NUM_ELIST, nz, RETURN, str_sexinfo, and THD_filesize(). Referenced by main(), and mri_imcount().
01147 { 01148 char *ppp , *ddd ; 01149 off_t poff ; 01150 unsigned int plen ; 01151 char *epos[NUM_ELIST] ; 01152 int ii , ee , bpp , datum ; 01153 int nx,ny,nz ; 01154 01155 int mosaic=0 , mos_nx,mos_ny , mos_ix,mos_iy,mos_nz ; /* 28 Oct 2002 */ 01156 Siemens_extra_info sexinfo ; /* 02 Dec 2002 */ 01157 01158 char *sexi_start; /* KRH 25 Jul 2003 */ 01159 char *sexi_end; 01160 01161 ENTRY("mri_imcount_dicom") ; 01162 01163 if( str_sexinfo != NULL ){ free(str_sexinfo); str_sexinfo=NULL; } 01164 01165 if( !mri_possibly_dicom(fname) ) RETURN(0) ; /* 07 May 2003 */ 01166 01167 /* extract the header from the file (cf. mri_dicom_hdr.[ch]) */ 01168 01169 mri_dicom_nohex(1) ; mri_dicom_noname(1) ; 01170 ppp = mri_dicom_header( fname ) ; 01171 if( ppp == NULL ) RETURN(0); 01172 01173 /* find out where the pixel array is in the file */ 01174 01175 mri_dicom_pxlarr( &poff , &plen ) ; 01176 if( plen <= 0 ){ free(ppp) ; RETURN(0); } 01177 01178 /* check if file is actually this big */ 01179 01180 { unsigned int psiz , fsiz ; 01181 fsiz = THD_filesize( fname ) ; 01182 psiz = (unsigned int)(poff) + plen ; 01183 if( fsiz < psiz ){ free(ppp) ; RETURN(0); } 01184 } 01185 01186 /* find positions in header of elements we care about */ 01187 01188 for( ee=0 ; ee < NUM_ELIST ; ee++ ) 01189 epos[ee] = strstr(ppp,elist[ee]) ; 01190 01191 /* see if the header has the elements we absolutely need */ 01192 01193 if( epos[E_ROWS] == NULL || 01194 epos[E_COLUMNS] == NULL || 01195 epos[E_BITS_ALLOCATED] == NULL ){ free(ppp) ; RETURN(0); } 01196 01197 /* check if we have 1 sample per pixel (can't deal with 3 or 4 now) */ 01198 01199 if( epos[E_SAMPLES_PER_PIXEL] != NULL ){ 01200 ddd = strstr(epos[E_SAMPLES_PER_PIXEL],"//") ; 01201 if( ddd == NULL ){ free(ppp) ; RETURN(0); } 01202 ii = 0 ; sscanf(ddd+2,"%d",&ii) ; 01203 if( ii != 1 ){ free(ppp) ; RETURN(0); } 01204 } 01205 01206 /* check if photometric interpretation is MONOCHROME (don't like PALETTE) */ 01207 01208 if( epos[E_PHOTOMETRIC_INTERPRETATION] != NULL ){ 01209 ddd = strstr(epos[E_PHOTOMETRIC_INTERPRETATION],"MONOCHROME") ; 01210 if( ddd == NULL ){ free(ppp) ; RETURN(0); } 01211 } 01212 01213 /* check if we have 8, 16, or 32 bits per pixel */ 01214 01215 ddd = strstr(epos[E_BITS_ALLOCATED],"//") ; 01216 if( ddd == NULL ){ free(ppp); RETURN(0); } 01217 bpp = 0 ; sscanf(ddd+2,"%d",&bpp) ; 01218 switch( bpp ){ 01219 default: free(ppp) ; RETURN(0); /* bad value */ 01220 case 8: datum = MRI_byte ; break ; 01221 case 16: datum = MRI_short; break ; 01222 case 32: datum = MRI_int ; break ; 01223 } 01224 bpp /= 8 ; /* now bytes per pixel, instead of bits */ 01225 01226 /* get nx, ny, nz */ 01227 01228 ddd = strstr(epos[E_ROWS],"//") ; 01229 if( ddd == NULL ){ free(ppp) ; RETURN(0); } 01230 nx = 0 ; sscanf(ddd+2,"%d",&nx) ; 01231 if( nx < 2 ){ free(ppp) ; RETURN(0); } 01232 01233 ddd = strstr(epos[E_COLUMNS],"//") ; 01234 if( ddd == NULL ){ free(ppp) ; RETURN(0); } 01235 ny = 0 ; sscanf(ddd+2,"%d",&ny) ; 01236 if( ny < 2 ){ free(ppp) ; RETURN(0); } 01237 01238 nz = 0 ; 01239 if( epos[E_NUMBER_OF_FRAMES] != NULL ){ 01240 ddd = strstr(epos[E_NUMBER_OF_FRAMES],"//") ; 01241 if( ddd != NULL ) sscanf(ddd+2,"%d",&nz) ; 01242 } 01243 if( nz == 0 ) nz = plen / (bpp*nx*ny) ; 01244 01245 /*-- 28 Oct 2002: Check if this is a Siemens mosaic. --*/ 01246 /*-- 02 Dec 2002: Don't use Acquisition Matrix anymore; 01247 instead, use the Siemens extra info 01248 in epos[E_SIEMENS_2]. --*/ 01249 /*-- 24 Dec 2002: Extract str_sexinfo even if not a mosaic. --*/ 01250 01251 if( epos[E_ID_MANUFACTURER] != NULL && 01252 strstr(epos[E_ID_MANUFACTURER],"SIEMENS") != NULL && 01253 epos[E_SIEMENS_2] != NULL ){ 01254 01255 int len=0,loc=0 , aa,bb ; 01256 sscanf(epos[E_SIEMENS_2],"%x%x%d [%d" , &aa,&bb , &len,&loc ) ; 01257 if( len > 0 && loc > 0 ){ 01258 FILE *fp = fopen( fname , "rb" ) ; 01259 if( fp != NULL ){ 01260 str_sexinfo = extract_bytes_from_file( fp, (off_t)loc, (size_t)len, 1 ) ; 01261 fclose(fp) ; 01262 } 01263 } 01264 } 01265 01266 if( epos[E_ID_IMAGE_TYPE] != NULL && 01267 strstr(epos[E_ID_IMAGE_TYPE],"MOSAIC") != NULL && 01268 str_sexinfo != NULL ){ 01269 01270 /* 31 Oct 2002: extract extra Siemens info from file */ 01271 01272 /* KRH 25 Jul 2003 if start and end markers are present for 01273 * Siemens extra info, cut string down to those boundaries */ 01274 01275 sexi_start = strstr(str_sexinfo, "### ASCCONV BEGIN ###"); 01276 sexi_end = strstr(str_sexinfo, "### ASCCONV END ###"); 01277 if ((sexi_start != NULL) && (sexi_end != NULL)) { 01278 char *sexi_tmp; 01279 int sexi_size; 01280 01281 sexi_size = sexi_end - sexi_start + 19 ; 01282 sexi_tmp = AFMALL( char, sexi_size ); 01283 memcpy(sexi_tmp,sexi_start,sexi_size); 01284 free(str_sexinfo); 01285 str_sexinfo = sexi_tmp; 01286 } 01287 /* end KRH 25 Jul 2003 change */ 01288 01289 sexinfo.good = 0 ; /* start by marking it as bad */ 01290 get_siemens_extra_info( str_sexinfo , &sexinfo ) ; 01291 01292 if( sexinfo.good ){ /* if data is good */ 01293 01294 nz = sexinfo.mosaic_num ; 01295 01296 } /* end of if sexinfo was good */ 01297 01298 else { /* warn if sexinfo was bad */ 01299 static int nwarn=0 ; 01300 if( nwarn < NWMAX ) 01301 fprintf(stderr,"++ DICOM WARNING: indecipherable SIEMENS MOSAIC info (%s) in file %s\n", 01302 elist[E_SIEMENS_2] , fname ) ; 01303 if( nwarn == NWMAX ) 01304 fprintf(stderr,"++ DICOM NOTICE: no more SIEMENS MOSAIC info messages will be printed\n"); 01305 nwarn++ ; 01306 } 01307 01308 } /* end of if a Siemens mosaic */ 01309 01310 free(ppp) ; RETURN(nz); 01311 } |
|
Test if a file is possibly a DICOM file. -- RWCox - 07 May 2003 ---------------------------------------------------------------------------- Definition at line 1466 of file mri_read_dicom.c.
01467 { 01468 #undef BSIZ 01469 #define BSIZ 4096 01470 FILE *fp ; 01471 unsigned char buf[BSIZ] , *cpt ; 01472 int nn , ii ; 01473 01474 if( fname == NULL || *fname == '\0' ) return 0 ; 01475 fp = fopen( fname , "rb" ) ; if( fp == NULL ) return 0 ; 01476 01477 /* read 1st buffer */ 01478 01479 nn = fread( buf , 1 , BSIZ , fp ) ; 01480 if( nn < 256 ){ fclose(fp) ; return 0 ; } /* too short */ 01481 01482 /* easy: check if has 'DICM' marker at offset 128..131 */ 01483 01484 if( buf[128]=='D' && buf[129]=='I' && buf[130]=='C' && buf[131]=='M' ){ 01485 fclose(fp) ; return 1 ; 01486 } 01487 01488 /* hard: scan file for sequence: E0 7F 10 00 (image data attribute) */ 01489 01490 while(1){ 01491 01492 cpt = memchr( buf, 0xe0, nn ) ; /* look for E0 */ 01493 01494 if( cpt == NULL ){ /* skip this buffer */ 01495 nn = fread( buf , 1 , BSIZ , fp ) ; /* and get another */ 01496 if( nn < 256 ){ fclose(fp) ; return 0 ; } 01497 continue ; 01498 } 01499 01500 ii = nn - (cpt-buf) ; /* num char to end of buf */ 01501 if( ii <= 4 ){ /* too close to end of buf */ 01502 memmove( buf , cpt , ii ) ; 01503 nn = fread( buf+ii , 1 , BSIZ-ii , fp ) ; nn += ii ; 01504 if( nn < 256 ){ fclose(fp) ; return 0 ; } 01505 cpt = buf ; ii = nn ; 01506 } 01507 01508 /* see if we got what we want */ 01509 01510 if( *cpt==0xe0 && *(cpt+1)==0x7f && *(cpt+2)==0x10 && *(cpt+3)==0x00 ){ 01511 fclose(fp) ; return 1 ; 01512 } 01513 01514 /* no? start again at next char in buf */ 01515 01516 memmove( buf , cpt+1 , ii-1 ) ; nn = ii-1 ; 01517 } 01518 } |
|
Read image(s) from a DICOM file, if possible. ------------------------------------------------------------------------------------- Definition at line 119 of file mri_read_dicom.c. References abs, ADDTO_IMARR, AFMALL, calloc, dt, MRI_IMAGE::dt, MRI_IMAGE::dw, MRI_IMAGE::dx, MRI_IMAGE::dy, MRI_IMAGE::dz, E_BITS_ALLOCATED, E_BITS_STORED, E_COLUMNS, E_FIELD_OF_VIEW, E_HIGH_BIT, E_ID_IMAGE_TYPE, E_ID_MANUFACTURER, E_IMAGE_ORIENTATION, E_IMAGE_POSITION, E_NUMBER_OF_FRAMES, E_PATIENT_ORIENTATION, E_PHOTOMETRIC_INTERPRETATION, E_PIXEL_REPRESENTATION, E_PIXEL_SPACING, E_REPETITION_TIME, E_RESCALE_INTERCEPT, E_RESCALE_SLOPE, E_ROWS, E_SAMPLES_PER_PIXEL, E_SIEMENS_2, E_SLICE_LOCATION, E_SLICE_SPACING, E_SLICE_THICKNESS, E_WINDOW_CENTER, E_WINDOW_WIDTH, elist, ENTRY, extract_bytes_from_file(), free, get_siemens_extra_info(), getenv(), Siemens_extra_info::good, Siemens_extra_info::have_data, IMARR_COUNT, IMARR_SUBIM, INIT_IMARR, MRI_IMAGE::kind, LITTLE_ENDIAN_ARCHITECTURE, MAX, MIN, Siemens_extra_info::mosaic_num, mri_data_pointer(), mri_dicom_header(), mri_dicom_nohex(), mri_dicom_noname(), mri_dicom_pxlarr(), mri_new(), mri_possibly_dicom(), NUM_ELIST, MRI_IMAGE::nvox, nz, MRI_IMAGE::pixel_size, RETURN, RWC_set_endianosity(), Siemens_extra_info::slice_xyz, str_sexinfo, swap, swap_fourbytes(), swap_twobytes(), THD_filesize(), TRUNCATE_IMARR, MRI_IMAGE::was_swapped, xc, xn, yc, yn, z0, and z1. Referenced by main(), mri_read_file(), and mri_read_file_delay().
00120 { 00121 char *ppp , *ddd ; 00122 off_t poff ; 00123 unsigned int plen ; 00124 char *epos[NUM_ELIST] ; 00125 int ii,jj , ee , bpp , datum ; 00126 int nx,ny,nz , swap , shift=0 ; 00127 float dx,dy,dz,dt ; 00128 MRI_IMARR *imar ; 00129 MRI_IMAGE *im ; 00130 void *iar ; 00131 FILE *fp ; 00132 short sbot,stop ; 00133 int have_orients=0 ; 00134 int ior,jor,kor ; 00135 static int nzoff=0 ; /* for determining z-axis orientation/offset from multiple calls */ 00136 00137 int mosaic=0 , mos_nx,mos_ny , mos_ix,mos_iy,mos_nz ; /* 28 Oct 2002 */ 00138 Siemens_extra_info sexinfo ; /* 31 Oct 2002 */ 00139 float xcen,ycen,zcen ; 00140 int use_xycen=0 ; 00141 float dxx,dyy,dzz ; 00142 00143 char *eee ; 00144 float rescale_slope=0.0 , rescale_inter=0.0 ; /* 23 Dec 2002 */ 00145 float window_center=0.0 , window_width =0.0 ; 00146 00147 char *sexi_start; /* KRH 25 Jul 2003 */ 00148 char *sexi_end; 00149 00150 ENTRY("mri_read_dicom") ; 00151 00152 if( str_sexinfo != NULL ){ free(str_sexinfo); str_sexinfo=NULL; } 00153 00154 if( !mri_possibly_dicom(fname) ) RETURN(NULL) ; /* 07 May 2003 */ 00155 00156 /* extract header info from file into a string 00157 - cf. mri_dicom_hdr.[ch] 00158 - run 'dicom_hdr -noname fname' to see the string format */ 00159 00160 mri_dicom_nohex(1) ; /* don't print ints in hex mode */ 00161 mri_dicom_noname(1) ; /* don't print names, just tags */ 00162 ppp = mri_dicom_header( fname ) ; /* print header to malloc()-ed string */ 00163 if( ppp == NULL ) RETURN(NULL); /* didn't work; not a DICOM file? */ 00164 00165 /* find out where the pixel array is in the file */ 00166 00167 mri_dicom_pxlarr( &poff , &plen ) ; 00168 if( plen <= 0 ){ free(ppp) ; RETURN(NULL); } 00169 00170 /* check if file is actually this big (maybe it was truncated) */ 00171 00172 { unsigned int psiz , fsiz ; 00173 fsiz = THD_filesize( fname ) ; 00174 psiz = (unsigned int)(poff) + plen ; 00175 if( fsiz < psiz ){ free(ppp) ; RETURN(NULL); } 00176 } 00177 00178 /* find positions in header of elements we care about */ 00179 00180 for( ee=0 ; ee < NUM_ELIST ; ee++ ) 00181 epos[ee] = strstr(ppp,elist[ee]) ; 00182 00183 /* see if the header has the elements we absolutely need */ 00184 00185 if( epos[E_ROWS] == NULL || 00186 epos[E_COLUMNS] == NULL || 00187 epos[E_BITS_ALLOCATED] == NULL ){ free(ppp) ; RETURN(NULL); } 00188 00189 /* check if we have 1 sample per pixel (can't deal with 3 or 4 now) */ 00190 00191 if( epos[E_SAMPLES_PER_PIXEL] != NULL ){ 00192 ddd = strstr(epos[E_SAMPLES_PER_PIXEL],"//") ; 00193 if( ddd == NULL ){ free(ppp) ; RETURN(NULL); } 00194 ii = 0 ; sscanf(ddd+2,"%d",&ii) ; 00195 if( ii != 1 ){ free(ppp) ; RETURN(NULL); } 00196 } 00197 00198 /* check if photometric interpretation is MONOCHROME (don't like PALETTE) */ 00199 00200 if( epos[E_PHOTOMETRIC_INTERPRETATION] != NULL ){ 00201 ddd = strstr(epos[E_PHOTOMETRIC_INTERPRETATION],"MONOCHROME") ; 00202 if( ddd == NULL ){ free(ppp) ; RETURN(NULL); } 00203 } 00204 00205 /* check if we have 8, 16, or 32 bits per pixel */ 00206 00207 ddd = strstr(epos[E_BITS_ALLOCATED],"//") ; 00208 if( ddd == NULL ){ free(ppp); RETURN(NULL); } 00209 bpp = 0 ; sscanf(ddd+2,"%d",&bpp) ; 00210 switch( bpp ){ 00211 default: free(ppp); RETURN(NULL); /* bad value */ 00212 case 8: datum = MRI_byte ; break ; 00213 case 16: datum = MRI_short; break ; 00214 case 32: datum = MRI_int ; break ; /* probably not present in DICOM? */ 00215 } 00216 bpp /= 8 ; /* now bytes per pixel, instead of bits */ 00217 00218 /*** Print some warnings if appropriate ***/ 00219 00220 /* check if BITS_STORED and HIGH_BIT are aligned */ 00221 00222 #define NWMAX 2 00223 if( epos[E_BITS_STORED] != NULL && epos[E_HIGH_BIT] != NULL ){ 00224 int bs=0 , hb=0 ; 00225 ddd = strstr(epos[E_BITS_STORED],"//") ; sscanf(ddd+2,"%d",&bs) ; 00226 ddd = strstr(epos[E_HIGH_BIT],"//") ; sscanf(ddd+2,"%d",&hb) ; 00227 if( bs != hb+1 ){ 00228 static int nwarn=0 ; 00229 if( nwarn < NWMAX ) 00230 fprintf(stderr, 00231 "++ DICOM WARNING: file %s has Bits_Stored=%d and High_Bit=%d\n", 00232 fname,bs,hb) ; 00233 if( nwarn == NWMAX ) 00234 fprintf(stderr,"++ DICOM WARNING: no more Bits_Stored messages will be printed\n") ; 00235 nwarn++ ; 00236 } 00237 } 00238 00239 /* check if Rescale is ordered */ 00240 /* 23 Dec 2002: actually get the rescale params, if environment says to */ 00241 00242 eee = getenv("AFNI_DICOM_RESCALE") ; 00243 if( epos[E_RESCALE_INTERCEPT] != NULL && epos[E_RESCALE_SLOPE] != NULL ){ 00244 if( eee == NULL || toupper(*eee) != 'Y' ){ 00245 static int nwarn=0 ; 00246 if( nwarn < NWMAX ) 00247 fprintf(stderr, 00248 "++ DICOM WARNING: file %s has Rescale tags; setenv AFNI_DICOM_RESCALE YES to enforce them\n", 00249 fname ) ; 00250 if( nwarn == NWMAX ) 00251 fprintf(stderr,"++ DICOM WARNING: no more Rescale tags messages will be printed\n") ; 00252 nwarn++ ; 00253 } else { 00254 ddd = strstr(epos[E_RESCALE_INTERCEPT],"//") ; sscanf(ddd+2,"%f",&rescale_inter) ; 00255 ddd = strstr(epos[E_RESCALE_SLOPE ],"//") ; sscanf(ddd+2,"%f",&rescale_slope) ; 00256 } 00257 } 00258 00259 /* check if Window is ordered */ 00260 /* 23 Dec 2002: actually get the window params, if environment says to */ 00261 00262 eee = getenv("AFNI_DICOM_WINDOW") ; 00263 if( epos[E_WINDOW_CENTER] != NULL && epos[E_WINDOW_WIDTH] != NULL ){ 00264 if( eee == NULL || toupper(*eee) != 'Y' ){ 00265 static int nwarn=0 ; 00266 if( nwarn < NWMAX ) 00267 fprintf(stderr, 00268 "++ DICOM WARNING: file %s has Window tags; setenv AFNI_DICOM_WINDOW YES to enforce them\n", 00269 fname ) ; 00270 if( nwarn == NWMAX ) 00271 fprintf(stderr,"++ DICOM WARNING: no more Window tags messages will be printed\n") ; 00272 nwarn++ ; 00273 } else { 00274 ddd = strstr(epos[E_WINDOW_CENTER],"//") ; sscanf(ddd+2,"%f",&window_center) ; 00275 ddd = strstr(epos[E_WINDOW_WIDTH ],"//") ; sscanf(ddd+2,"%f",&window_width ) ; 00276 } 00277 } 00278 00279 /*** extract attributes of the image(s) to be read in ***/ 00280 00281 /* get image nx & ny */ 00282 00283 ddd = strstr(epos[E_ROWS],"//") ; /* 31 Oct 2002: */ 00284 if( ddd == NULL ){ free(ppp) ; RETURN(NULL); } /* Oops: ROWS is ny and */ 00285 ny = 0 ; sscanf(ddd+2,"%d",&ny) ; /* COLUMNS is nx! */ 00286 if( ny < 2 ){ free(ppp) ; RETURN(NULL); } 00287 00288 ddd = strstr(epos[E_COLUMNS],"//") ; 00289 if( ddd == NULL ){ free(ppp) ; RETURN(NULL); } 00290 nx = 0 ; sscanf(ddd+2,"%d",&nx) ; 00291 if( nx < 2 ){ free(ppp) ; RETURN(NULL); } 00292 00293 /* get number of slices */ 00294 00295 nz = 0 ; 00296 if( epos[E_NUMBER_OF_FRAMES] != NULL ){ 00297 ddd = strstr(epos[E_NUMBER_OF_FRAMES],"//") ; 00298 if( ddd != NULL ) sscanf(ddd+2,"%d",&nz) ; 00299 } 00300 00301 /* if didn't get nz above, make up a value */ 00302 00303 if( nz == 0 ) nz = plen / (bpp*nx*ny) ; /* compute from image array size */ 00304 if( nz == 0 ){ free(ppp) ; RETURN(NULL); } 00305 00306 /*-- 28 Oct 2002: Check if this is a Siemens mosaic. --*/ 00307 /*-- 02 Dec 2002: Don't use Acquisition Matrix anymore; 00308 instead, use the Siemens extra info 00309 in epos[E_SIEMENS_2]. --*/ 00310 /*-- 24 Dec 2002: Extract str_sexinfo even if not a mosaic. --*/ 00311 00312 if( epos[E_ID_MANUFACTURER] != NULL && 00313 strstr(epos[E_ID_MANUFACTURER],"SIEMENS") != NULL && 00314 epos[E_SIEMENS_2] != NULL ){ 00315 00316 int len=0,loc=0 , aa,bb ; 00317 sscanf(epos[E_SIEMENS_2],"%x%x%d [%d" , &aa,&bb , &len,&loc ) ; 00318 if( len > 0 && loc > 0 ){ 00319 fp = fopen( fname , "rb" ) ; 00320 if( fp != NULL ){ 00321 str_sexinfo = extract_bytes_from_file( fp, (off_t)loc, (size_t)len, 1 ) ; 00322 fclose(fp) ; 00323 } 00324 } 00325 } 00326 00327 /*-- process str_sexinfo only if this is marked as a mosaic image --*/ 00328 00329 if( epos[E_ID_IMAGE_TYPE] != NULL && 00330 strstr(epos[E_ID_IMAGE_TYPE],"MOSAIC") != NULL && 00331 str_sexinfo != NULL ){ 00332 00333 /* 31 Oct 2002: extract extra Siemens info from str_sexinfo */ 00334 00335 /* KRH 25 Jul 2003 if start and end markers are present for 00336 * Siemens extra info, cut string down to those boundaries */ 00337 00338 sexi_start = strstr(str_sexinfo, "### ASCCONV BEGIN ###"); 00339 sexi_end = strstr(str_sexinfo, "### ASCCONV END ###"); 00340 if ((sexi_start != NULL) && (sexi_end != NULL)) { 00341 char *sexi_tmp; 00342 int sexi_size; 00343 00344 sexi_size = sexi_end - sexi_start + 19 ; 00345 sexi_tmp = AFMALL( char, sexi_size ); 00346 memcpy(sexi_tmp,sexi_start,sexi_size); 00347 free(str_sexinfo); 00348 str_sexinfo = sexi_tmp; 00349 } 00350 /* end KRH 25 Jul 2003 change */ 00351 00352 sexinfo.good = 0 ; /* start by marking it as bad */ 00353 for(ii = 0; ii < 3; ii++) sexinfo.have_data[ii] = 0; /* 25 Feb 03 Initialize new member KRH */ 00354 00355 get_siemens_extra_info( str_sexinfo , &sexinfo ) ; 00356 00357 if( sexinfo.good ){ /* if data is good */ 00358 00359 /* compute size of mosaic layout 00360 as 1st integer whose square is >= # of images in mosaic */ 00361 00362 for( mos_ix=1 ; mos_ix*mos_ix < sexinfo.mosaic_num ; mos_ix++ ) ; /* nada */ 00363 mos_iy = mos_ix ; 00364 00365 mos_nx = nx / mos_ix ; mos_ny = ny / mos_iy ; /* sub-image dimensions */ 00366 00367 if( mos_ix*mos_nx == nx && /* Sub-images must fit nicely */ 00368 mos_iy*mos_ny == ny ){ /* into super-image layout. */ 00369 00370 static int nwarn=0 ; 00371 00372 /* should be tagged as a 1 slice image thus far */ 00373 00374 if( nz > 1 ){ 00375 fprintf(stderr, 00376 "** DICOM ERROR: %dx%d Mosaic of %dx%d images in file %s, but also have nz=%d\n", 00377 mos_ix,mos_iy,mos_nx,mos_ny,fname,nz) ; 00378 free(ppp) ; RETURN(NULL) ; 00379 } 00380 00381 /* mark as a mosaic */ 00382 00383 mosaic = 1 ; 00384 mos_nz = mos_ix * mos_iy ; /* number of slices in mosaic */ 00385 if( nwarn < NWMAX ) 00386 fprintf(stderr,"++ DICOM NOTICE: %dx%d Siemens Mosaic of %d %dx%d images in file %s\n", 00387 mos_ix,mos_iy,sexinfo.mosaic_num,mos_nx,mos_ny,fname) ; 00388 if( nwarn == NWMAX ) 00389 fprintf(stderr,"++ DICOM NOTICE: no more Siemens Mosiac messages will be printed\n") ; 00390 nwarn++ ; 00391 00392 } /* end of if mosaic sizes are reasonable */ 00393 00394 else { /* warn about bad mosaic sizes */ 00395 static int nwarn=0 ; 00396 if( nwarn < NWMAX ) 00397 fprintf(stderr, 00398 "++ DICOM WARNING: bad Siemens Mosaic params: nx=%d ny=%d ix=%d iy=%d imx=%d imy=%d\n", 00399 mos_nx,mos_ny , mos_ix,mos_iy , nx,ny ) ; 00400 if( nwarn == NWMAX ) 00401 fprintf(stderr,"++ DICOM NOTICE: no more Siemens Mosaic param messages will be printed\n"); 00402 nwarn++ ; 00403 } 00404 00405 } /* end of if sexinfo was good */ 00406 00407 else { /* warn if sexinfo was bad */ 00408 static int nwarn=0 ; 00409 if( nwarn < NWMAX ) 00410 fprintf(stderr,"++ DICOM WARNING: indecipherable Siemens Mosaic info (%s) in file %s\n", 00411 elist[E_SIEMENS_2] , fname ) ; 00412 if( nwarn == NWMAX ) 00413 fprintf(stderr,"++ DICOM NOTICE: no more Siemens Mosaic info messages will be printed\n"); 00414 nwarn++ ; 00415 } 00416 00417 } /* end of if a Siemens mosaic */ 00418 00419 /*-- try to get dx, dy, dz, dt --*/ 00420 00421 dx = dy = dz = dt = 0.0 ; 00422 00423 /* dx,dy first */ 00424 00425 if( epos[E_PIXEL_SPACING] != NULL ){ 00426 ddd = strstr(epos[E_PIXEL_SPACING],"//") ; 00427 if( ddd != NULL ) sscanf( ddd+2 , "%f\\%f" , &dx , &dy ) ; 00428 if( dy == 0.0 && dx > 0.0 ) dy = dx ; 00429 } 00430 if( dx == 0.0 && epos[E_FIELD_OF_VIEW] != NULL ){ 00431 ddd = strstr(epos[E_FIELD_OF_VIEW],"//") ; 00432 if( ddd != NULL ) sscanf( ddd+2 , "%f\\%f" , &dx , &dy ) ; 00433 if( dx > 0.0 ){ 00434 if( dy == 0.0 ) dy = dx ; 00435 dx /= nx ; dy /= ny ; 00436 } 00437 } 00438 00439 /*-- 27 Nov 2002: fix stupid GE error, 00440 where the slice spacing is really the slice gap --*/ 00441 00442 { int stupid_ge_fix , no_stupidity ; 00443 float sp=0.0 , th=0.0 ; 00444 static int nwarn=0 ; 00445 00446 eee = getenv("AFNI_SLICE_SPACING_IS_GAP") ; 00447 stupid_ge_fix = (eee != NULL && (*eee=='Y' || *eee=='y') ) ; 00448 no_stupidity = (eee != NULL && (*eee=='N' || *eee=='n') ) ; /* 03 Mar 2003 */ 00449 00450 if( epos[E_SLICE_SPACING] != NULL ){ /* get reported slice spacing */ 00451 ddd = strstr(epos[E_SLICE_SPACING],"//") ; 00452 if( ddd != NULL ) sscanf( ddd+2 , "%f" , &sp ) ; 00453 } 00454 if( epos[E_SLICE_THICKNESS] != NULL ){ /* get reported slice thickness */ 00455 ddd = strstr(epos[E_SLICE_THICKNESS],"//") ; 00456 if( ddd != NULL ) sscanf( ddd+2 , "%f" , &th ) ; 00457 } 00458 00459 th = fabs(th) ; sp = fabs(sp) ; /* we don't use the sign */ 00460 00461 if( stupid_ge_fix ){ /* always be stupid */ 00462 dz = sp+th ; 00463 } else { 00464 00465 if( no_stupidity && sp > 0.0 ) /* 13 Jan 2004: if 'NO', then */ 00466 dz = sp ; /* always use spacing if present */ 00467 else 00468 dz = (sp > th) ? sp : th ; /* the correct-ish DICOM way */ 00469 00470 #define GFAC 0.99 00471 00472 if( !no_stupidity ){ /* unless stupidity is turned off */ 00473 if( sp > 0.0 && sp < GFAC*th ) dz = sp+th ; /* the stupid GE way again */ 00474 00475 if( sp > 0.0 && sp < GFAC*th && nwarn < NWMAX ){ 00476 fprintf(stderr, 00477 "++ DICOM WARNING: file %s has Slice_Spacing=%f smaller than Slice_Thickness=%f\n", 00478 fname , sp , th ) ; 00479 if( nwarn == 0 ) 00480 fprintf(stderr, 00481 "\n" 00482 "++ Setting environment variable AFNI_SLICE_SPACING_IS_GAP ++\n" 00483 "++ to YES will make the center-to-center slice distance ++\n" 00484 "++ be set to Slice_Spacing+Slice_Thickness=%6.3f. ++\n" 00485 "++ This is against the DICOM standard [attribute (0018,0088) ++\n" 00486 "++ is defined as the center-to-center spacing between slices, ++\n" 00487 "++ NOT as the edge-to-edge gap between slices], but it seems ++\n" 00488 "++ to be necessary for some GE scanners. ++\n" 00489 "++ ++\n" 00490 "++ This correction has been made on this data: dz=%6.3f. ++\n" 00491 "++ ++\n" 00492 "++ Setting AFNI_SLICE_SPACING_IS_GAP to NO means that the ++\n" 00493 "++ DICOM Slice_Spacing variable will be used for dz, replacing ++\n" 00494 "++ the Slice_Thickness variable. This usage may be required ++\n" 00495 "++ for some pulse sequences on Phillips scanners. ++\n" 00496 "\n\a" , 00497 sp+th , dz ) ; 00498 } 00499 if( sp > 0.0 && sp < th && nwarn == NWMAX ) 00500 fprintf(stderr,"++ DICOM WARNING: no more Slice_Spacing messages will be printed\n") ; 00501 nwarn++ ; 00502 } 00503 } 00504 if( dz == 0.0 && dx != 0.0 ) dz = 1.0 ; /* nominal dz */ 00505 00506 } /*-- end of dz code, with all its stupidities --*/ 00507 00508 /* get dt */ 00509 00510 if( epos[E_REPETITION_TIME] != NULL ){ 00511 ddd = strstr(epos[E_REPETITION_TIME],"//") ; 00512 if( ddd != NULL ){ 00513 sscanf( ddd+2 , "%f" , &dt ) ; 00514 dt *= 0.001 ; /* ms to s */ 00515 } 00516 } 00517 00518 /* check if we might have 16 bit unsigned data that fills all bits */ 00519 00520 #if 0 00521 if( bpp == 2 ){ 00522 if( epos[E_PIXEL_REPRESENTATION] != NULL ){ 00523 ddd = strstr(epos[E_PIXEL_REPRESENTATION],"//") ; 00524 if( ddd != NULL ){ 00525 ii = 0 ; sscanf( ddd+2 , "%d" , &ii ) ; 00526 if( ii == 1 ) shift = -1 ; 00527 } 00528 } 00529 if( shift == 0 && epos[E_HIGH_BIT] != NULL ){ 00530 ddd = strstr(epos[E_HIGH_BIT],"//") ; 00531 if( ddd != NULL ){ 00532 ii = 0 ; sscanf( ddd+2 , "%d" , &ii ) ; 00533 if( ii == 15 ) shift = 1 ; 00534 } 00535 } 00536 sbot = 32767 ; stop = -32767 ; 00537 } 00538 #endif 00539 00540 /** Finally! Read images from file. **/ 00541 00542 fp = fopen( fname , "rb" ) ; 00543 if( fp == NULL ){ free(ppp) ; RETURN(NULL); } 00544 lseek( fileno(fp) , poff , SEEK_SET ) ; 00545 00546 INIT_IMARR(imar) ; 00547 00548 /* DICOM files are stored in LSB first (little endian) mode */ 00549 00550 RWC_set_endianosity() ; swap = !LITTLE_ENDIAN_ARCHITECTURE ; 00551 00552 /* 28 Oct 2002: must allow for 2D mosaic mode */ 00553 00554 if( !mosaic ){ /*-- 28 Oct 2002: old method, not a mosaic --*/ 00555 00556 for( ii=0 ; ii < nz ; ii++ ){ 00557 im = mri_new( nx , ny , datum ) ; /* new MRI_IMAGE struct */ 00558 iar = mri_data_pointer( im ) ; /* data array in struct */ 00559 fread( iar , bpp , nx*ny , fp ) ; /* read data directly into it */ 00560 00561 if( swap ){ /* swap bytes? */ 00562 switch( im->pixel_size ){ 00563 default: break ; 00564 case 2: swap_twobytes ( im->nvox, iar ) ; break ; /* short */ 00565 case 4: swap_fourbytes( im->nvox, iar ) ; break ; /* int, float */ 00566 case 8: swap_fourbytes( 2*im->nvox, iar ) ; break ; /* complex */ 00567 } 00568 im->was_swapped = 1 ; 00569 } 00570 00571 #if 0 00572 if( shift == 1 ){ 00573 switch( datum ){ 00574 case MRI_short:{ 00575 short * sar = (short *) iar ; 00576 for( jj=0 ; jj < im->nvox ; jj++ ){ 00577 sbot = MIN( sar[jj] , sbot ) ; 00578 stop = MAX( sar[jj] , stop ) ; 00579 } 00580 } 00581 break ; 00582 } 00583 } 00584 #endif 00585 00586 /* store auxiliary data in image struct */ 00587 00588 if( dx > 0.0 && dy > 0.0 && dz > 0.0 ){ 00589 im->dx = dx; im->dy = dy; im->dz = dz; im->dw = 1.0; 00590 } 00591 if( dt > 0.0 ) im->dt = dt ; 00592 00593 ADDTO_IMARR(imar,im) ; 00594 } 00595 00596 } else { /*-- 28 Oct 2002: is a 2D mosaic --*/ 00597 00598 char *dar , *iar ; 00599 int last_ii=-1 , nvox , yy,xx,nxx ; 00600 00601 nvox = mos_nx*mos_ny*mos_nz ; /* total number of voxels */ 00602 dar = (char*)calloc(bpp,nvox) ; /* make space for super-image */ 00603 fread( dar , bpp , nvox , fp ) ; /* read data directly into it */ 00604 if( swap ){ /* swap bytes? */ 00605 switch( bpp ){ 00606 default: break ; 00607 case 2: swap_twobytes ( nvox, dar ) ; break ; /* short */ 00608 case 4: swap_fourbytes( nvox, dar ) ; break ; /* int, float */ 00609 case 8: swap_fourbytes( 2*nvox, dar ) ; break ; /* complex */ 00610 } 00611 } 00612 00613 /* load data from dar into images */ 00614 00615 nxx = mos_nx * mos_ix ; /* # pixels per mosaic line */ 00616 00617 for( yy=0 ; yy < mos_iy ; yy++ ){ /* loop over sub-images in mosaic */ 00618 for( xx=0 ; xx < mos_ix ; xx++ ){ 00619 00620 im = mri_new( mos_nx , mos_ny , datum ) ; 00621 iar = mri_data_pointer( im ) ; /* sub-image array */ 00622 00623 /* copy data rows from dar into iar */ 00624 00625 for( jj=0 ; jj < mos_ny ; jj++ ) /* loop over rows inside sub-image */ 00626 memcpy( iar + jj*mos_nx*bpp , 00627 dar + xx*mos_nx*bpp + (jj+yy*mos_ny)*nxx*bpp , 00628 mos_nx*bpp ) ; 00629 00630 if( dx > 0.0 && dy > 0.0 && dz > 0.0 ){ 00631 im->dx = dx; im->dy = dy; im->dz = dz; im->dw = 1.0; 00632 } 00633 if( dt > 0.0 ) im->dt = dt ; 00634 if( swap ) im->was_swapped = 1 ; 00635 00636 ADDTO_IMARR(imar,im) ; 00637 } 00638 } 00639 free(dar) ; /* don't need no more; copied all data out of it now */ 00640 00641 /* truncate zero images out of tail of mosaic */ 00642 00643 if( sexinfo.good ){ /* the new way: use the mosaic count from Siemens extra info */ 00644 00645 if( sexinfo.mosaic_num < IMARR_COUNT(imar) ) 00646 TRUNCATE_IMARR(imar,sexinfo.mosaic_num) ; 00647 00648 } else { /* the old way: find the last image with a nonzero value inside */ 00649 00650 for( ii=mos_nz-1 ; ii >= 0 ; ii-- ){ /* loop backwards over images */ 00651 im = IMARR_SUBIM(imar,ii) ; 00652 switch( im->kind ){ 00653 case MRI_short:{ 00654 short *ar = mri_data_pointer( im ) ; 00655 for( jj=0 ; jj < im->nvox ; jj++ ) if( ar[jj] != 0 ) break ; 00656 if( jj < im->nvox ) last_ii = ii ; 00657 } 00658 break ; 00659 00660 case MRI_byte:{ 00661 byte *ar = mri_data_pointer( im ) ; 00662 for( jj=0 ; jj < im->nvox ; jj++ ) if( ar[jj] != 0 ) break ; 00663 if( jj < im->nvox ) last_ii = ii ; 00664 } 00665 break ; 00666 00667 case MRI_int:{ 00668 int *ar = mri_data_pointer( im ) ; 00669 for( jj=0 ; jj < im->nvox ; jj++ ) if( ar[jj] != 0 ) break ; 00670 if( jj < im->nvox ) last_ii = ii ; 00671 } 00672 break ; 00673 } 00674 if( last_ii >= 0 ) break ; 00675 } 00676 00677 if( last_ii <= 0 ) last_ii = 1 ; 00678 if( last_ii+1 < IMARR_COUNT(imar) ) TRUNCATE_IMARR(imar,last_ii+1) ; 00679 00680 } /* end of truncating off all zero images at end */ 00681 00682 #if 0 00683 fprintf(stderr,"\nmri_read_dicom Mosaic: mos_nx=%d mos_ny=%d mos_ix=%d mos_iy=%d slices=%d\n", 00684 mos_nx,mos_ny,mos_ix,mos_iy,IMARR_COUNT(imar)) ; 00685 MCHECK ; 00686 #endif 00687 00688 } /* end of mosaic input mode */ 00689 00690 fclose(fp) ; /* 10 Sep 2002: oopsie - forgot to close file */ 00691 00692 /*-- 23 Dec 2002: implement Rescale, if ordered --*/ 00693 00694 if( rescale_slope > 0.0 ){ 00695 for( ii=0 ; ii < IMARR_COUNT(imar) ; ii++ ){ 00696 im = IMARR_SUBIM(imar,ii) ; 00697 switch( im->kind ){ 00698 case MRI_byte:{ 00699 byte *ar = mri_data_pointer( im ) ; 00700 for( jj=0 ; jj < im->nvox ; jj++ ) 00701 ar[jj] = rescale_slope*ar[jj] + rescale_inter ; 00702 } 00703 break ; 00704 00705 case MRI_short:{ 00706 short *ar = mri_data_pointer( im ) ; 00707 for( jj=0 ; jj < im->nvox ; jj++ ) 00708 ar[jj] = rescale_slope*ar[jj] + rescale_inter ; 00709 } 00710 break ; 00711 00712 case MRI_int:{ 00713 int *ar = mri_data_pointer( im ) ; 00714 for( jj=0 ; jj < im->nvox ; jj++ ) 00715 ar[jj] = rescale_slope*ar[jj] + rescale_inter ; 00716 } 00717 break ; 00718 } 00719 } 00720 } /* end of Rescale */ 00721 00722 /*-- 23 Dec 2002: implement Window, if ordered --*/ 00723 /* section C.11.2.1.2 (page 503) */ 00724 00725 if( window_width >= 1.0 ){ 00726 float wbot,wtop,wfac ; 00727 int ymax=0 ; 00728 00729 /* get output range */ 00730 00731 ddd = strstr(epos[E_BITS_STORED],"//") ; 00732 if( ddd != NULL ){ 00733 ymax = 0 ; sscanf(ddd+2,"%d",&ymax) ; 00734 if( ymax > 0 ) ymax = (1 << ymax) - 1 ; 00735 } 00736 if( ymax <= 0 ){ 00737 switch( IMARR_SUBIM(imar,0)->kind ){ 00738 case MRI_byte: ymax = MRI_maxbyte ; break ; 00739 case MRI_short: ymax = MRI_maxshort ; break ; 00740 case MRI_int: ymax = MRI_maxint ; break ; 00741 } 00742 } 00743 /** window_width == 1 is special **/ 00744 if( window_width == 1.0 ){ /** binary threshold case **/ 00745 00746 wbot = window_center - 0.5 ; /* the threshold */ 00747 00748 for( ii=0 ; ii < IMARR_COUNT(imar) ; ii++ ){ 00749 im = IMARR_SUBIM(imar,ii) ; 00750 switch( im->kind ){ 00751 case MRI_byte:{ 00752 byte *ar = mri_data_pointer( im ) ; 00753 for( jj=0 ; jj < im->nvox ; jj++ ) 00754 ar[jj] = (ar[jj] <= wbot) ? 0 : ymax ; 00755 } 00756 break ; 00757 00758 case MRI_short:{ 00759 short *ar = mri_data_pointer( im ) ; 00760 for( jj=0 ; jj < im->nvox ; jj++ ) 00761 ar[jj] = (ar[jj] <= wbot) ? 0 : ymax ; 00762 } 00763 break ; 00764 00765 case MRI_int:{ 00766 int *ar = mri_data_pointer( im ) ; 00767 for( jj=0 ; jj < im->nvox ; jj++ ) 00768 ar[jj] = (ar[jj] <= wbot) ? 0 : ymax ; 00769 } 00770 break ; 00771 } 00772 } 00773 00774 } else { /** linear windowing case **/ 00775 00776 wbot = (window_center - 0.5) - 0.5*(window_width-1.0) ; 00777 wtop = (window_center - 0.5) + 0.5*(window_width-1.0) ; 00778 wfac = ymax / (window_width-1.0) ; 00779 00780 for( ii=0 ; ii < IMARR_COUNT(imar) ; ii++ ){ 00781 im = IMARR_SUBIM(imar,ii) ; 00782 switch( im->kind ){ 00783 case MRI_byte:{ 00784 byte *ar = mri_data_pointer( im ) ; 00785 for( jj=0 ; jj < im->nvox ; jj++ ) 00786 ar[jj] = (ar[jj] <= wbot) ? 0 00787 :(ar[jj] > wtop) ? ymax 00788 : wfac*(ar[jj]-wbot)+0.499 ; 00789 } 00790 break ; 00791 00792 case MRI_short:{ 00793 short *ar = mri_data_pointer( im ) ; 00794 for( jj=0 ; jj < im->nvox ; jj++ ) 00795 ar[jj] = (ar[jj] <= wbot) ? 0 00796 :(ar[jj] > wtop) ? ymax 00797 : wfac*(ar[jj]-wbot)+0.499 ; 00798 } 00799 break ; 00800 00801 case MRI_int:{ 00802 int *ar = mri_data_pointer( im ) ; 00803 for( jj=0 ; jj < im->nvox ; jj++ ) 00804 ar[jj] = (ar[jj] <= wbot) ? 0 00805 :(ar[jj] > wtop) ? ymax 00806 : wfac*(ar[jj]-wbot)+0.499 ; 00807 } 00808 break ; 00809 } 00810 } 00811 } 00812 } /* end of Window */ 00813 00814 /*-- store some extra information in MRILIB globals, too? --*/ 00815 00816 if( dt > 0.0 && MRILIB_tr <= 0.0 ) MRILIB_tr = dt ; /* TR */ 00817 00818 /*-- try to get image orientation fields (also, set ior,jor,kor) --*/ 00819 00820 if( epos[E_IMAGE_ORIENTATION] != NULL ){ /* direction cosines of image plane */ 00821 00822 ddd = strstr(epos[E_IMAGE_ORIENTATION],"//") ; 00823 if( ddd != NULL ){ 00824 float xc1=0.0,xc2=0.0,xc3=0.0 , yc1=0.0,yc2=0.0,yc3=0.0 ; 00825 float xn,yn ; int qq ; 00826 qq = sscanf(ddd+2,"%f\\%f\\%f\\%f\\%f\\%f",&xc1,&xc2,&xc3,&yc1,&yc2,&yc3) ; 00827 xn = sqrt( xc1*xc1 + xc2*xc2 + xc3*xc3 ) ; /* vector norms */ 00828 yn = sqrt( yc1*yc1 + yc2*yc2 + yc3*yc3 ) ; 00829 if( qq == 6 && xn > 0.0 && yn > 0.0 ){ /* both vectors OK */ 00830 00831 xc1 /= xn ; xc2 /= xn ; xc3 /= xn ; /* normalize vectors */ 00832 yc1 /= yn ; yc2 /= yn ; yc3 /= yn ; 00833 00834 if( !use_MRILIB_xcos ){ 00835 MRILIB_xcos[0] = xc1 ; MRILIB_xcos[1] = xc2 ; /* save direction */ 00836 MRILIB_xcos[2] = xc3 ; use_MRILIB_xcos = 1 ; /* cosine vectors */ 00837 } 00838 00839 if( !use_MRILIB_ycos ){ 00840 MRILIB_ycos[0] = yc1 ; MRILIB_ycos[1] = yc2 ; 00841 MRILIB_ycos[2] = yc3 ; use_MRILIB_ycos = 1 ; 00842 } 00843 00844 /* x-axis orientation */ 00845 /* ior determines which spatial direction is x-axis */ 00846 /* and is the direction that has the biggest change */ 00847 00848 dxx = fabs(xc1) ; ior = 1 ; 00849 dyy = fabs(xc2) ; if( dyy > dxx ){ ior=2; dxx=dyy; } 00850 dzz = fabs(xc3) ; if( dzz > dxx ){ ior=3; } 00851 dxx = MRILIB_xcos[ior-1] ; if( dxx < 0. ) ior = -ior; 00852 00853 if( MRILIB_orients[0] == '\0' ){ 00854 switch( ior ){ 00855 case -1: MRILIB_orients[0] = 'L'; MRILIB_orients[1] = 'R'; break; 00856 case 1: MRILIB_orients[0] = 'R'; MRILIB_orients[1] = 'L'; break; 00857 case -2: MRILIB_orients[0] = 'P'; MRILIB_orients[1] = 'A'; break; 00858 case 2: MRILIB_orients[0] = 'A'; MRILIB_orients[1] = 'P'; break; 00859 case 3: MRILIB_orients[0] = 'I'; MRILIB_orients[1] = 'S'; break; 00860 case -3: MRILIB_orients[0] = 'S'; MRILIB_orients[1] = 'I'; break; 00861 default: MRILIB_orients[0] ='\0'; MRILIB_orients[1] ='\0'; break; 00862 } 00863 } 00864 00865 /* y-axis orientation */ 00866 /* jor determines which spatial direction is y-axis */ 00867 /* and is the direction that has the biggest change */ 00868 00869 dxx = fabs(yc1) ; jor = 1 ; 00870 dyy = fabs(yc2) ; if( dyy > dxx ){ jor=2; dxx=dyy; } 00871 dzz = fabs(yc3) ; if( dzz > dxx ){ jor=3; } 00872 dyy = MRILIB_ycos[jor-1] ; if( dyy < 0. ) jor = -jor; 00873 if( MRILIB_orients[2] == '\0' ){ 00874 switch( jor ){ 00875 case -1: MRILIB_orients[2] = 'L'; MRILIB_orients[3] = 'R'; break; 00876 case 1: MRILIB_orients[2] = 'R'; MRILIB_orients[3] = 'L'; break; 00877 case -2: MRILIB_orients[2] = 'P'; MRILIB_orients[3] = 'A'; break; 00878 case 2: MRILIB_orients[2] = 'A'; MRILIB_orients[3] = 'P'; break; 00879 case 3: MRILIB_orients[2] = 'I'; MRILIB_orients[3] = 'S'; break; 00880 case -3: MRILIB_orients[2] = 'S'; MRILIB_orients[3] = 'I'; break; 00881 default: MRILIB_orients[2] ='\0'; MRILIB_orients[3] ='\0'; break; 00882 } 00883 } 00884 00885 MRILIB_orients[6] = '\0' ; /* terminate orientation string */ 00886 00887 kor = 6 - abs(ior)-abs(jor) ; /* which spatial direction is z-axis */ 00888 /* where 1=L-R, 2=P-A, 3=I-S */ 00889 have_orients = 1 ; 00890 #if 0 00891 fprintf(stderr,"MRILIB_orients=%s (from IMAGE_ORIENTATION)\n",MRILIB_orients) ; 00892 #endif 00893 } 00894 } 00895 00896 } else if( epos[E_PATIENT_ORIENTATION] != NULL ){ /* symbolic orientation of image */ 00897 /* [not so useful, or common] */ 00898 ddd = strstr(epos[E_PATIENT_ORIENTATION],"//") ; 00899 if( ddd != NULL ){ 00900 char xc='\0' , yc='\0' ; 00901 sscanf(ddd+2,"%c\\%c",&xc,&yc) ; /* e.g., "L\P" */ 00902 switch( toupper(xc) ){ 00903 case 'L': MRILIB_orients[0] = 'L'; MRILIB_orients[1] = 'R'; ior=-1; break; 00904 case 'R': MRILIB_orients[0] = 'R'; MRILIB_orients[1] = 'L'; ior= 1; break; 00905 case 'P': MRILIB_orients[0] = 'P'; MRILIB_orients[1] = 'A'; ior=-2; break; 00906 case 'A': MRILIB_orients[0] = 'A'; MRILIB_orients[1] = 'P'; ior= 2; break; 00907 case 'F': MRILIB_orients[0] = 'I'; MRILIB_orients[1] = 'S'; ior= 3; break; /* F = foot */ 00908 case 'H': MRILIB_orients[0] = 'S'; MRILIB_orients[1] = 'I'; ior=-3; break; /* H = head */ 00909 default: MRILIB_orients[0] ='\0'; MRILIB_orients[1] ='\0'; ior= 0; break; 00910 } 00911 switch( toupper(yc) ){ 00912 case 'L': MRILIB_orients[2] = 'L'; MRILIB_orients[3] = 'R'; jor=-1; break; 00913 case 'R': MRILIB_orients[2] = 'R'; MRILIB_orients[3] = 'L'; jor= 1; break; 00914 case 'P': MRILIB_orients[2] = 'P'; MRILIB_orients[3] = 'A'; jor=-2; break; 00915 case 'A': MRILIB_orients[2] = 'A'; MRILIB_orients[3] = 'P'; jor= 2; break; 00916 case 'F': MRILIB_orients[2] = 'I'; MRILIB_orients[3] = 'S'; jor= 3; break; 00917 case 'H': MRILIB_orients[2] = 'S'; MRILIB_orients[3] = 'I'; jor=-3; break; 00918 default: MRILIB_orients[2] ='\0'; MRILIB_orients[3] ='\0'; jor= 0; break; 00919 } 00920 MRILIB_orients[6] = '\0' ; /* terminate orientation string */ 00921 kor = 6 - abs(ior)-abs(jor) ; /* which spatial direction is z-axis */ 00922 have_orients = (ior != 0 && jor != 0) ; 00923 } 00924 00925 } /* end of 2D image orientation */ 00926 00927 /*-- try to get image offset (position), if have orientation from above --*/ 00928 00929 if( nzoff == 0 && have_orients && mosaic && sexinfo.good ){ /* 01 Nov 2002: use Siemens mosaic info */ 00930 int qq ; 00931 float z0, z1 ; 00932 /* 25 Feb 2003 changing error checking for mosaics missing one or more * 00933 * dimension of slice coordinates KRH */ 00934 if (sexinfo.have_data[kor-1]) { 00935 z0 = sexinfo.slice_xyz[0][kor-1] ; /* kor from orients above */ 00936 z1 = sexinfo.slice_xyz[1][kor-1] ; /* z offsets of 1st 2 slices */ 00937 } else { /* warn if sexinfo was bad */ 00938 static int nwarn=0 ; 00939 if( nwarn < NWMAX ) 00940 fprintf(stderr,"++ DICOM WARNING: Unusable coord. in Siemens Mosaic info (%s) in file %s\n", 00941 elist[E_SIEMENS_2] , fname ) ; 00942 if( nwarn == NWMAX ) 00943 fprintf(stderr,"++ DICOM NOTICE: no more Siemens Mosaic info messages will be printed\n"); 00944 nwarn++ ; 00945 } 00946 00947 00948 #if 0 00949 /* Save x,y center of this 1st slice */ 00950 00951 xcen = sexinfo.slice_xyz[0][abs(ior)-1] ; 00952 ycen = sexinfo.slice_xyz[0][abs(jor)-1] ; use_xycen = 1 ; 00953 #endif 00954 00955 /* finish z orientation now */ 00956 00957 if( z1-z0 < 0.0 ) kor = -kor ; /* reversed orientation */ 00958 if( MRILIB_orients[4] == '\0' ){ 00959 switch( kor ){ 00960 case 1: MRILIB_orients[4] = 'R'; MRILIB_orients[5] = 'L'; break; 00961 case -1: MRILIB_orients[4] = 'L'; MRILIB_orients[5] = 'R'; break; 00962 case 2: MRILIB_orients[4] = 'A'; MRILIB_orients[5] = 'P'; break; 00963 case -2: MRILIB_orients[4] = 'P'; MRILIB_orients[5] = 'A'; break; 00964 case 3: MRILIB_orients[4] = 'I'; MRILIB_orients[5] = 'S'; break; 00965 case -3: MRILIB_orients[4] = 'S'; MRILIB_orients[5] = 'I'; break; 00966 default: MRILIB_orients[4] ='\0'; MRILIB_orients[5] ='\0'; break; 00967 } 00968 } 00969 MRILIB_orients[6] = '\0' ; 00970 00971 #if 0 00972 fprintf(stderr,"z0=%f z1=%f kor=%d MRILIB_orients=%s\n",z0,z1,kor,MRILIB_orients) ; 00973 #endif 00974 00975 MRILIB_zoff = z0 ; use_MRILIB_zoff = 1 ; 00976 if( kor > 0 ) MRILIB_zoff = -MRILIB_zoff ; 00977 } 00978 00979 /** use image position vector to set offsets, 00980 and (2cd time in) the z-axis orientation **/ 00981 00982 if( nzoff < 2 && epos[E_IMAGE_POSITION] != NULL && have_orients ){ 00983 ddd = strstr(epos[E_IMAGE_POSITION],"//") ; 00984 if( ddd != NULL ){ 00985 float xyz[3] ; int qq ; 00986 qq = sscanf(ddd+2,"%f\\%f\\%f",xyz,xyz+1,xyz+2) ; 00987 if( qq == 3 ){ 00988 static float zoff ; /* saved from nzoff=0 case */ 00989 float zz = xyz[kor-1] ; /* kor from orients above */ 00990 00991 #if 0 00992 fprintf(stderr,"IMAGE_POSITION=%f %f %f kor=%d\n",xyz[0],xyz[1],xyz[2],kor) ; 00993 #endif 00994 00995 if( nzoff == 0 ){ /* 1st DICOM image */ 00996 00997 zoff = zz ; /* save this for 2nd image calculation */ 00998 00999 /* 01 Nov 2002: in mosaic case, may have set this already */ 01000 01001 if( MRILIB_orients[4] == '\0' ){ 01002 switch( kor ){ /* may be changed on second image */ 01003 case 1: MRILIB_orients[4] = 'L'; MRILIB_orients[5] = 'R'; break; 01004 case 2: MRILIB_orients[4] = 'P'; MRILIB_orients[5] = 'A'; break; 01005 case 3: MRILIB_orients[4] = 'I'; MRILIB_orients[5] = 'S'; break; 01006 default: MRILIB_orients[4] ='\0'; MRILIB_orients[5] ='\0'; break; 01007 } 01008 MRILIB_orients[6] = '\0' ; 01009 } 01010 01011 /* Save x,y offsets of this 1st slice */ 01012 01013 qq = abs(ior) ; 01014 MRILIB_xoff = xyz[qq-1] ; use_MRILIB_xoff = 1 ; 01015 if( ior > 0 ) MRILIB_xoff = -MRILIB_xoff ; 01016 01017 qq = abs(jor) ; 01018 MRILIB_yoff = xyz[qq-1] ; use_MRILIB_yoff = 1 ; 01019 if( jor > 0 ) MRILIB_yoff = -MRILIB_yoff ; 01020 01021 /* 01 Nov 2002: adjust x,y offsets for mosaic */ 01022 01023 if( mosaic ){ 01024 if( MRILIB_xoff < 0.0 ) MRILIB_xoff += 0.5*dx*mos_nx*(mos_ix-1) ; 01025 else MRILIB_xoff -= 0.5*dx*mos_nx*(mos_ix-1) ; 01026 if( MRILIB_yoff < 0.0 ) MRILIB_yoff += 0.5*dy*mos_ny*(mos_iy-1) ; 01027 else MRILIB_yoff -= 0.5*dy*mos_ny*(mos_iy-1) ; 01028 } 01029 01030 } else if( nzoff == 1 && !use_MRILIB_zoff ){ /* 2nd DICOM image */ 01031 01032 float qoff = zz - zoff ; /* vive la difference */ 01033 if( qoff < 0 ) kor = -kor ; /* kor determines z-axis orientation */ 01034 #if 0 01035 fprintf(stderr," nzoff=1 kor=%d qoff=%f\n",kor,qoff) ; 01036 #endif 01037 switch( kor ){ 01038 case 1: MRILIB_orients[4] = 'R'; MRILIB_orients[5] = 'L'; break; 01039 case -1: MRILIB_orients[4] = 'L'; MRILIB_orients[5] = 'R'; break; 01040 case 2: MRILIB_orients[4] = 'A'; MRILIB_orients[5] = 'P'; break; 01041 case -2: MRILIB_orients[4] = 'P'; MRILIB_orients[5] = 'A'; break; 01042 case 3: MRILIB_orients[4] = 'I'; MRILIB_orients[5] = 'S'; break; 01043 case -3: MRILIB_orients[4] = 'S'; MRILIB_orients[5] = 'I'; break; 01044 default: MRILIB_orients[4] ='\0'; MRILIB_orients[5] ='\0'; break; 01045 } 01046 MRILIB_orients[6] = '\0' ; 01047 01048 /* save spatial offset of first slice */ 01049 /* [this needs to be positive in the direction of] */ 01050 /* [the -z axis, so may need to change its sign ] */ 01051 01052 MRILIB_zoff = zoff ; use_MRILIB_zoff = 1 ; 01053 if( kor > 0 ) MRILIB_zoff = -MRILIB_zoff ; 01054 } 01055 nzoff++ ; /* 3rd and later images don't count for z-orientation */ 01056 } 01057 } 01058 } /* end of using image position */ 01059 01060 /** 23 Dec 2002: 01061 use slice location value to set z-offset, 01062 and (2cd time in) the z-axis orientation 01063 -- only try this if image position vector (code above) isn't present 01064 AND if we don't have a mosaic image (which already did this stuff) 01065 -- shouldn't be necessary, since slice location is deprecated **/ 01066 01067 else if( nzoff < 2 && epos[E_SLICE_LOCATION] != NULL && have_orients && !mosaic ){ 01068 ddd = strstr(epos[E_SLICE_LOCATION],"//") ; 01069 if( ddd != NULL ){ 01070 float zz ; int qq ; 01071 qq = sscanf(ddd+2,"%f",&zz) ; 01072 if( qq == 1 ){ 01073 static float zoff ; /* saved from nzoff=0 case */ 01074 01075 #if 0 01076 fprintf(stderr,"SLICE_LOCATION = %f\n",zz) ; 01077 #endif 01078 01079 if( nzoff == 0 ){ /* 1st DICOM image */ 01080 01081 zoff = zz ; /* save this for 2nd image calculation */ 01082 01083 if( MRILIB_orients[4] == '\0' ){ 01084 switch( kor ){ /* may be changed on second image */ 01085 case 1: MRILIB_orients[4] = 'L'; MRILIB_orients[5] = 'R'; break; 01086 case 2: MRILIB_orients[4] = 'P'; MRILIB_orients[5] = 'A'; break; 01087 case 3: MRILIB_orients[4] = 'I'; MRILIB_orients[5] = 'S'; break; 01088 default: MRILIB_orients[4] ='\0'; MRILIB_orients[5] ='\0'; break; 01089 } 01090 MRILIB_orients[6] = '\0' ; 01091 } 01092 01093 } else if( nzoff == 1 && !use_MRILIB_zoff ){ /* 2nd DICOM image */ 01094 01095 float qoff = zz - zoff ; /* vive la difference */ 01096 if( qoff < 0 ) kor = -kor ; /* kor determines z-axis orientation */ 01097 switch( kor ){ 01098 case 1: MRILIB_orients[4] = 'R'; MRILIB_orients[5] = 'L'; break; 01099 case -1: MRILIB_orients[4] = 'L'; MRILIB_orients[5] = 'R'; break; 01100 case 2: MRILIB_orients[4] = 'A'; MRILIB_orients[5] = 'P'; break; 01101 case -2: MRILIB_orients[4] = 'P'; MRILIB_orients[5] = 'A'; break; 01102 case 3: MRILIB_orients[4] = 'I'; MRILIB_orients[5] = 'S'; break; 01103 case -3: MRILIB_orients[4] = 'S'; MRILIB_orients[5] = 'I'; break; 01104 default: MRILIB_orients[4] ='\0'; MRILIB_orients[5] ='\0'; break; 01105 } 01106 MRILIB_orients[6] = '\0' ; 01107 01108 /* save spatial offset of first slice */ 01109 /* [this needs to be positive in the direction of] */ 01110 /* [the -z axis, so may need to change its sign ] */ 01111 01112 MRILIB_zoff = zoff ; use_MRILIB_zoff = 1 ; 01113 if( kor > 0 ) MRILIB_zoff = -MRILIB_zoff ; 01114 } 01115 nzoff++ ; /* 3rd and later images don't count for z-orientation */ 01116 } 01117 } 01118 } /* end of using slice location */ 01119 01120 /* perhaps shift data shorts */ 01121 01122 #if 0 01123 if( shift == 1 ){ 01124 switch( datum ){ 01125 case MRI_short:{ 01126 if( sbot < 0 ){ 01127 unsigned short *sar ; int nvox = IMARR_SUBIM(imar,0)->nvox ; 01128 for( ii=0 ; ii < nz ; ii++ ){ 01129 sar = mri_data_pointer( IMARR_SUBIM(imar,ii) ) ; 01130 for( jj=0 ; jj < nvox ; jj++ ) sar[jj] >>= 1 ; 01131 } 01132 } 01133 } 01134 break ; 01135 } 01136 } 01137 #endif 01138 01139 RETURN( imar ); 01140 } |
|
Definition at line 29 of file mri_read_dicom.c. References LITTLE_ENDIAN_ARCHITECTURE.
00030 { 00031 union { unsigned char bb[2] ; 00032 short ss ; } fred ; 00033 00034 if( LITTLE_ENDIAN_ARCHITECTURE < 0 ){ 00035 fred.bb[0] = 1 ; fred.bb[1] = 0 ; 00036 00037 LITTLE_ENDIAN_ARCHITECTURE = (fred.ss == 1) ; 00038 } 00039 } |
Variable Documentation
|
Definition at line 43 of file mri_read_dicom.c. Referenced by mri_imcount_dicom(), and mri_read_dicom(). |
|
Definition at line 27 of file mri_read_dicom.c. Referenced by mri_read_dicom(), and RWC_set_endianosity(). |
|
Definition at line 21 of file mri_read_dicom.c. Referenced by mri_dicom_sexinfo(), mri_imcount_dicom(), and mri_read_dicom(). |