From dfce355491595891585576bfa351788244e9d848 Mon Sep 17 00:00:00 2001 From: Chris Rorden Date: Wed, 26 Apr 2017 14:52:10 -0400 Subject: [PATCH] Further work on ECAT --- console/nii_dicom.cpp | 2 +- console/nii_dicom.h | 1 + console/nii_dicom_batch.cpp | 12 +- console/nii_foreign.cpp | 333 ++++++++++++++++++++++++++++++++---- console/nii_foreign.h | 5 +- 5 files changed, 312 insertions(+), 41 deletions(-) diff --git a/console/nii_dicom.cpp b/console/nii_dicom.cpp index d5aeb397..cedac14b 100644 --- a/console/nii_dicom.cpp +++ b/console/nii_dicom.cpp @@ -1612,7 +1612,7 @@ size_t nii_SliceBytes(struct nifti_1_header hdr) { if (hdr.dim[i] > 1) imgsz = imgsz * hdr.dim[i]; return imgsz; -} //nii_ImgBytes() +} //nii_SliceBytes() size_t nii_ImgBytes(struct nifti_1_header hdr) { size_t imgsz = hdr.bitpix/8; diff --git a/console/nii_dicom.h b/console/nii_dicom.h index 7250ab53..820c81d9 100644 --- a/console/nii_dicom.h +++ b/console/nii_dicom.h @@ -95,6 +95,7 @@ static const int kCompress50 = 3; //obsolete JPEG lossy unsigned char * nii_planar2rgb(unsigned char* bImg, struct nifti_1_header *hdr, int isPlanar); int isDICOMfile(const char * fname); //0=not DICOM, 1=DICOM, 2=NOTSURE(not part 10 compliant) int headerDcm2Nii2(struct TDICOMdata d, struct TDICOMdata d2, struct nifti_1_header *h); + int headerDcm2Nii(struct TDICOMdata d, struct nifti_1_header *h) ; //unsigned char * nii_loadImgX(char* imgname, struct nifti_1_header *hdr, struct TDICOMdata dcm, bool iVaries); unsigned char * nii_loadImgXL(char* imgname, struct nifti_1_header *hdr, struct TDICOMdata dcm, bool iVaries, int compressFlag, int isVerbose); //int foo (float vx); diff --git a/console/nii_dicom_batch.cpp b/console/nii_dicom_batch.cpp index 4c961106..bdc9571b 100755 --- a/console/nii_dicom_batch.cpp +++ b/console/nii_dicom_batch.cpp @@ -411,7 +411,7 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts, //printf("-%02d-%02dT%02d:%02d:%02.6f\",\n", amonth, aday, ahour, amin, asec); if (count) { // ISO 8601 specifies a sign must exist for distant years. //report time of the day only format, https://www.cs.tut.fi/~jkorpela/iso8601.html - fprintf(fp, "\t\"AcquisitionTime\": %02d:%02d:%02.6f\",\n",ahour, amin, asec); + fprintf(fp, "\t\"AcquisitionTime\": \"%02d:%02d:%02.6f\",\n",ahour, amin, asec); //report date and time together if (!opts.isAnonymizeBIDS) { fprintf(fp, "\t\"AcquisitionDateTime\": "); @@ -722,7 +722,7 @@ bool intensityScaleVaries(int nConvert, struct TDCMsort dcmSort[],struct TDICOMd sliceOffsetR += sliceBytes8; } //for each slice return bImg; - } //nii_ImgBytes()*/ + } */ bool niiExists(const char*pathoutname) { char niiname[2048] = {""}; @@ -1092,6 +1092,10 @@ void nii_saveAttributes (struct TDICOMdata &data, struct nifti_1_header &header, int nii_saveNII(char * niiFilename, struct nifti_1_header hdr, unsigned char* im, struct TDCMopts opts) { hdr.vox_offset = 352; size_t imgsz = nii_ImgBytes(hdr); + if (imgsz < 1) { + printMessage("Error: Image size is zero bytes %s\n", niiFilename); + return EXIT_FAILURE; + } #ifndef myDisableZLib if ((opts.isGz) && (strlen(opts.pigzname) < 1) && ((imgsz+hdr.vox_offset) < 2147483647) ) { //use internal compressor writeNiiGz (niiFilename, hdr, im, imgsz, opts.gzLevel); @@ -2111,8 +2115,8 @@ int nii_loadDir(struct TDCMopts* opts) { }*/ getFileName(opts->indirParent, opts->indir); if (isFile && ( (isExt(indir, ".v"))) ) { - //open_foreign(opts->indir); - return open_foreign (indir); + //return open_foreign (indir); + return open_foreign (indir, *opts); } if (isFile && ( (isExt(indir, ".par")) || (isExt(indir, ".rec"))) ) { diff --git a/console/nii_foreign.cpp b/console/nii_foreign.cpp index 9066a4e5..a0768772 100644 --- a/console/nii_foreign.cpp +++ b/console/nii_foreign.cpp @@ -1,4 +1,6 @@ #include "nii_foreign.h" +#include "nii_dicom.h" +#include "nii_dicom_batch.h" #include "nifti1.h" #include "nifti1_io_core.h" #include @@ -13,8 +15,8 @@ #define chdir _chrdir #include "io.h" #include - //#define snprintf _snprintf - //#define vsnprintf _vsnprintf + //#define snprintMessage _snprintMessage + //#define vsnprintMessage _vsnprintMessage #define strcasecmp _stricmp #define strncasecmp _strnicmp #else @@ -46,7 +48,7 @@ //TO DO: // currently only reads first 3D volume: for multiple volumes we need to handle num_frames num_bed_pos // SForm and QForm copy SPM and do not account for slice angulation or orientation -int nii_readEcat7(const char * fname, struct nifti_1_header *nhdr, bool * swapEndian, unsigned char **img) { +unsigned char * nii_readEcat7x(const char * fname, struct nifti_1_header *nhdr) { //data type #define ECAT7_BYTE 1 #define ECAT7_VAXI2 2 @@ -132,7 +134,7 @@ int nii_readEcat7(const char * fname, struct nifti_1_header *nhdr, bool * swapEn //r21[4],r22[4],r23[4],r24[4],r25[4],r26[4],r27[4],r28[4],r29[4],r30[4], //r31[4]; }) ecat_list_hdr; - * swapEndian = false; + bool swapEndian = false; size_t n; FILE *f; ecat_main_hdr mhdr; @@ -140,63 +142,67 @@ int nii_readEcat7(const char * fname, struct nifti_1_header *nhdr, bool * swapEn if (f) n = fread(&mhdr, sizeof(mhdr), 1, f); if(!f || n!=1) { - printf("Problem reading ECAT7 file!\n"); + printMessage("Problem reading ECAT7 file!\n"); fclose(f); - return EXIT_FAILURE; + return NULL; } if ((mhdr.magic[0] != 'M') || (mhdr.magic[1] != 'A') || (mhdr.magic[2] != 'T') || (mhdr.magic[3] != 'R') || (mhdr.magic[4] != 'I') || (mhdr.magic[5] != 'X') ) { - printf("Signature not 'MATRIX' (ECAT7)\n"); + printMessage("Signature not 'MATRIX' (ECAT7)\n"); fclose(f); - return EXIT_FAILURE; + return NULL; } - * swapEndian = mhdr.file_type > 255; - if (*swapEndian) { + swapEndian = mhdr.file_type > 255; + if (swapEndian) { nifti_swap_2bytes(1, &mhdr.sw_version); nifti_swap_2bytes(1, &mhdr.file_type); nifti_swap_2bytes(1, &mhdr.num_frames); nifti_swap_4bytes(1, &mhdr.ecat_calibration_factor); } if ((mhdr.file_type < ECAT7_2DSCAN) || (mhdr.file_type > ECAT7_3DSCANFIT)) { - printf("Unknown ECAT file type %d\n", mhdr.file_type); + printMessage("Unknown ECAT file type %d\n", mhdr.file_type); fclose(f); - return EXIT_FAILURE; + return NULL; } if (mhdr.num_frames < 1) mhdr.num_frames = 1; if (mhdr.num_bed_pos < 1) mhdr.num_bed_pos = 1; /*int num_vol = mhdr.num_frames * mhdr.num_bed_pos; //unfortunately, frames and bed positions not reliable if (num_vol > 1) //to do: multi-volume files - printf("Only reading first volume from ECAT file with %d frames and %d bed positions\n", mhdr.num_frames, mhdr.num_bed_pos); + printMessage("Only reading first volume from ECAT file with %d frames and %d bed positions\n", mhdr.num_frames, mhdr.num_bed_pos); */ //read list matrix ecat_list_hdr lhdr; fseek(f, 512, SEEK_SET); fread(&lhdr, sizeof(lhdr), 1, f); - if (*swapEndian) nifti_swap_4bytes(128, &lhdr.hdr[0]); + if (swapEndian) nifti_swap_4bytes(128, &lhdr.hdr[0]); //offset to first image int img_StartBytes = lhdr.r[0][1] * 512; //load image header for first image fseek(f, img_StartBytes - 512, SEEK_SET); //image header is block immediately before image ecat_img_hdr ihdr; fread(&ihdr, sizeof(ihdr), 1, f); - if (*swapEndian) { + if (swapEndian) { nifti_swap_2bytes(5, &ihdr.data_type); nifti_swap_4bytes(7, &ihdr.x_resolution); nifti_swap_4bytes(3, &ihdr.x_pixel_size); } if ((ihdr.data_type != ECAT7_BYTE) && (ihdr.data_type != ECAT7_SUNI2) && (ihdr.data_type != ECAT7_SUNI4)) { - printf("Unknown or unsupported ECAT data type %d\n", ihdr.data_type); + printMessage("Unknown or unsupported ECAT data type %d\n", ihdr.data_type); fclose(f); - return EXIT_FAILURE; + return NULL; } //cm -> mm ihdr.x_pixel_size *= 10.0; ihdr.y_pixel_size *= 10.0; ihdr.z_pixel_size *= 10.0; + //fill NIfTI header + nhdr->sizeof_hdr = 348; //used to signify header does not need to be byte-swapped nhdr->dim[0]=3;//3D nhdr->dim[1]=ihdr.x_dimension; nhdr->dim[2]=ihdr.y_dimension; nhdr->dim[3]=ihdr.z_dimension; //slices per volume + nhdr->scl_slope = 1.0; + nhdr->scl_inter = 0.0; nhdr->dim[4]=1; //volumes nhdr->pixdim[1]=ihdr.x_pixel_size; nhdr->pixdim[2]=ihdr.y_pixel_size; @@ -204,6 +210,11 @@ int nii_readEcat7(const char * fname, struct nifti_1_header *nhdr, bool * swapEn nhdr->datatype = DT_INT16; if (ihdr.data_type == ECAT7_BYTE) nhdr->datatype = DT_UINT8; if (ihdr.data_type == ECAT7_SUNI4) nhdr->datatype = DT_INT32; + int bytesPerVoxel = 2; + if (ihdr.data_type == ECAT7_BYTE) bytesPerVoxel = 1; + if (ihdr.data_type == ECAT7_SUNI4) bytesPerVoxel = 4; + nhdr->bitpix = bytesPerVoxel * 8; //8 bits per byte + nhdr->vox_offset = img_StartBytes; nhdr->sform_code = NIFTI_XFORM_UNKNOWN; //NIFTI_XFORM_SCANNER_ANAT; nhdr->scl_slope = ihdr.scale_factor * mhdr.ecat_calibration_factor; @@ -221,24 +232,24 @@ int nii_readEcat7(const char * fname, struct nifti_1_header *nhdr, bool * swapEn if (num_vol > 0) { //read the next list fseek(f, 512 * (lhdr.hdr[1] -1), SEEK_SET); fread(&lhdr, 512, 1, f); - if (*swapEndian) nifti_swap_4bytes(128, &lhdr.hdr[0]); + if (swapEndian) nifti_swap_4bytes(128, &lhdr.hdr[0]); } if ((lhdr.hdr[0]+lhdr.hdr[3]) != 31) break; //if valid list if (lhdr.hdr[3] < 1) break; for (int k = 0; k < lhdr.hdr[3]; k++) { - //printf("%d --> %d \n", num_vol,lhdr.r[k][1]); + //printMessage("%d --> %d \n", num_vol,lhdr.r[k][1]); //check images' ecat_img_hdr matches first fseek(f, (lhdr.r[k][1]-1) * 512, SEEK_SET); //image header is block immediately before image ecat_img_hdr ihdrN; fread(&ihdrN, sizeof(ihdrN), 1, f); - if (*swapEndian) { + if (swapEndian) { nifti_swap_2bytes(5, &ihdrN.data_type); nifti_swap_4bytes(7, &ihdrN.x_resolution); nifti_swap_4bytes(3, &ihdrN.x_pixel_size); } if ((ihdr.data_type != ihdrN.data_type) || (ihdr.x_dimension != ihdrN.x_dimension) || (ihdr.y_dimension != ihdrN.y_dimension) || (ihdr.z_dimension != ihdrN.z_dimension)) { - printf("Error: ECAT volumes have varying image dimensions\n"); + printMessage("Error: ECAT volumes have varying image dimensions\n"); isAbort = true; } if (num_vol < kMaxVols) @@ -246,35 +257,287 @@ int nii_readEcat7(const char * fname, struct nifti_1_header *nhdr, bool * swapEn num_vol ++; } if ((lhdr.hdr[0] > 0) || (isAbort)) break; //this list contains empty volumes: all lists have been read - } //while (lhdr.hdr[3] == 31); - printf("%d >>> \n", num_vol); + } //read all image offsets + //report error reading image offsets if ((num_vol < 1) || (isAbort) || (num_vol >= kMaxVols)) { - printf("Failure to extract ECAT7 images\n"); - if (num_vol >= kMaxVols) printf("Increase kMaxVols"); + printMessage("Failure to extract ECAT7 images\n"); + if (num_vol >= kMaxVols) printMessage("Increase kMaxVols"); fclose(f); free (imgOffsets); - return EXIT_FAILURE; + return NULL; } + //load image data + num_vol = 1; //666 + nhdr->dim[4]=num_vol; //volumes + if (num_vol > 1) nhdr->dim[0]=4; //volumes + + + size_t bytesPerVolume = ihdr.x_dimension * ihdr.y_dimension * ihdr.z_dimension * bytesPerVoxel; + unsigned char * img = (unsigned char*)malloc(bytesPerVolume * num_vol); for (int v = 0; v < num_vol; v++) { - printf("%d --> %lu\n", v, imgOffsets[v]); + //printMessage("%d --> %lu\n", v, imgOffsets[v]); + fseek(f, imgOffsets[v] * 512, SEEK_SET); + size_t sz = fread( &img[v * bytesPerVolume], 1, bytesPerVolume, f); } - printf("ECAT not (yet) supported\n"); + if ((swapEndian) && (bytesPerVoxel == 2)) nifti_swap_2bytes(ihdr.x_dimension * ihdr.y_dimension * ihdr.z_dimension * num_vol, img); + if ((swapEndian) && (bytesPerVoxel == 4)) nifti_swap_4bytes(ihdr.x_dimension * ihdr.y_dimension * ihdr.z_dimension * num_vol, img); + printMessage("ECAT support VERY experimental (Spatial transforms unknown)\n"); free (imgOffsets); fclose(f); //convertForeignToNifti(nhdr); - return EXIT_SUCCESS; + return img; +} + +unsigned char * nii_readEcat7(const char *fname, struct TDICOMdata *dcm, struct nifti_1_header *hdr) { +//data type +#define ECAT7_BYTE 1 +#define ECAT7_VAXI2 2 +#define ECAT7_VAXI4 3 +#define ECAT7_VAXR4 4 +#define ECAT7_IEEER4 5 +#define ECAT7_SUNI2 6 +#define ECAT7_SUNI4 7 +//file types +//#define ECAT7_UNKNOWN 0 +#define ECAT7_2DSCAN 1 +#define ECAT7_IMAGE16 2 +#define ECAT7_ATTEN 3 +#define ECAT7_2DNORM 4 +#define ECAT7_POLARMAP 5 +#define ECAT7_VOLUME8 6 +#define ECAT7_VOLUME16 7 +#define ECAT7_PROJ 8 +#define ECAT7_PROJ16 9 +#define ECAT7_IMAGE8 10 +#define ECAT7_3DSCAN 11 +#define ECAT7_3DSCAN8 12 +#define ECAT7_3DNORM 13 +#define ECAT7_3DSCANFIT 14 + PACK( typedef struct { + char magic[14],original_filename[32]; + uint16_t sw_version, system_type, file_type; + char serial_number[10]; + uint32 scan_start_time; + char isotope_name[8]; + Float32 isotope_halflife; + char radiopharmaceutical[32]; + Float32 gantry_tilt, gantry_rotation, bed_elevation, intrinsic_tilt; + int16_t wobble_speed, transm_source_type; + Float32 distance_scanned, transaxial_fov; + uint16_t angular_compression, coin_samp_mode, axial_samp_mode; + Float32 ecat_calibration_factor; + uint16_t calibration_unitS, calibration_units_type, compression_code; + char study_type[12], patient_id[16], patient_name[32], patient_sex, patient_dexterity; + Float32 patient_age, patient_height, patient_weight; + uint32 patient_birth_date; + char physician_name[32], operator_name[32], study_description[32]; + uint16_t acquisition_type, patient_orientation; + char facility_name[20]; + uint16_t num_planes, num_frames, num_gates, num_bed_pos; + Float32 init_bed_position; + Float32 bed_position[15]; + Float32 plane_separation; + uint16_t lwr_sctr_thres, lwr_true_thres, upr_true_thres; + char user_process_code[10]; + uint16_t acquisition_mode; + Float32 bin_size, branching_fraction; + uint32 dose_start_time; + Float32 dosage, well_counter_corr_factor; + char data_units[32]; + uint16_t septa_state; + char fill[12]; + }) ecat_main_hdr; + PACK( typedef struct { + int16_t data_type, num_dimensions, x_dimension, y_dimension, z_dimension; + Float32 x_offset, y_offset, z_offset, recon_zoom, scale_factor; + int16_t image_min, image_max; + Float32 x_pixel_size, y_pixel_size, z_pixel_size; + int32_t frame_duration, frame_start_time; + int16_t filter_code; + Float32 x_resolution, y_resolution, z_resolution, num_r_elements, num_angles, z_rotation_angle, decay_corr_fctr; + int32_t processing_code, gate_duration, r_wave_offset, num_accepted_beats; + Float32 filter_cutoff_frequenc, filter_resolution, filter_ramp_slope; + int16_t filter_order; + Float32 filter_scatter_fraction, filter_scatter_slope; + char annotation[40]; + Float32 mtx[9], rfilter_cutoff, rfilter_resolution; + int16_t rfilter_code, rfilter_order; + Float32 zfilter_cutoff, zfilter_resolution; + int16_t zfilter_code, zfilter_order; + Float32 mtx_1_4, mtx_2_4, mtx_3_4; + int16_t scatter_type, recon_type, recon_views, fill_cti[87], fill_user[49]; + }) ecat_img_hdr; + PACK( typedef struct { + int32_t hdr[4], r[31][4]; + //r01[4],r02[4],r03[4],r04[4],r05[4],r06[4],r07[4],r08[4],r09[4],r10[4], + //r11[4],r12[4],r13[4],r14[4],r15[4],r16[4],r17[4],r18[4],r19[4],r20[4], + //r21[4],r22[4],r23[4],r24[4],r25[4],r26[4],r27[4],r28[4],r29[4],r30[4], + //r31[4]; + }) ecat_list_hdr; + bool swapEndian = false; + size_t n; + FILE *f; + ecat_main_hdr mhdr; + f = fopen(fname, "rb"); + if (f) + n = fread(&mhdr, sizeof(mhdr), 1, f); + if(!f || n!=1) { + printMessage("Problem reading ECAT7 file!\n"); + fclose(f); + return NULL; + } + if ((mhdr.magic[0] != 'M') || (mhdr.magic[1] != 'A') || (mhdr.magic[2] != 'T') + || (mhdr.magic[3] != 'R') || (mhdr.magic[4] != 'I') || (mhdr.magic[5] != 'X') ) { + printMessage("Signature not 'MATRIX' (ECAT7)\n"); + fclose(f); + return NULL; + } + swapEndian = mhdr.file_type > 255; + if (swapEndian) { + nifti_swap_2bytes(1, &mhdr.sw_version); + nifti_swap_2bytes(1, &mhdr.file_type); + nifti_swap_2bytes(1, &mhdr.num_frames); + nifti_swap_4bytes(1, &mhdr.ecat_calibration_factor); + } + if ((mhdr.file_type < ECAT7_2DSCAN) || (mhdr.file_type > ECAT7_3DSCANFIT)) { + printMessage("Unknown ECAT file type %d\n", mhdr.file_type); + fclose(f); + return NULL; + } + if (mhdr.num_frames < 1) mhdr.num_frames = 1; + if (mhdr.num_bed_pos < 1) mhdr.num_bed_pos = 1; + /*int num_vol = mhdr.num_frames * mhdr.num_bed_pos; //unfortunately, frames and bed positions not reliable + if (num_vol > 1) //to do: multi-volume files + printMessage("Only reading first volume from ECAT file with %d frames and %d bed positions\n", mhdr.num_frames, mhdr.num_bed_pos); + */ + //read list matrix + ecat_list_hdr lhdr; + fseek(f, 512, SEEK_SET); + fread(&lhdr, sizeof(lhdr), 1, f); + if (swapEndian) nifti_swap_4bytes(128, &lhdr.hdr[0]); + //offset to first image + int img_StartBytes = lhdr.r[0][1] * 512; + //load image header for first image + fseek(f, img_StartBytes - 512, SEEK_SET); //image header is block immediately before image + ecat_img_hdr ihdr; + fread(&ihdr, sizeof(ihdr), 1, f); + if (swapEndian) { + nifti_swap_2bytes(5, &ihdr.data_type); + nifti_swap_4bytes(7, &ihdr.x_resolution); + nifti_swap_4bytes(3, &ihdr.x_pixel_size); + } + if ((ihdr.data_type != ECAT7_BYTE) && (ihdr.data_type != ECAT7_SUNI2) && (ihdr.data_type != ECAT7_SUNI4)) { + printMessage("Unknown or unsupported ECAT data type %d\n", ihdr.data_type); + fclose(f); + return NULL; + } + //cm -> mm + int bytesPerVoxel = 2; + if (ihdr.data_type == ECAT7_BYTE) bytesPerVoxel = 1; + if (ihdr.data_type == ECAT7_SUNI4) bytesPerVoxel = 4; + //next: read offsets for each volume: data not saved sequentially (each volume preceded by its own ecat_img_hdr) + int num_vol = 0; + bool isAbort = false; + #define kMaxVols 16000 + size_t * imgOffsets = (size_t *)malloc(sizeof(size_t) * (kMaxVols)); + while ((lhdr.hdr[0]+lhdr.hdr[3]) == 31) { //while valid list + if (num_vol > 0) { //read the next list + fseek(f, 512 * (lhdr.hdr[1] -1), SEEK_SET); + fread(&lhdr, 512, 1, f); + if (swapEndian) nifti_swap_4bytes(128, &lhdr.hdr[0]); + } + if ((lhdr.hdr[0]+lhdr.hdr[3]) != 31) break; //if valid list + if (lhdr.hdr[3] < 1) break; + for (int k = 0; k < lhdr.hdr[3]; k++) { + //printMessage("%d --> %d \n", num_vol,lhdr.r[k][1]); + + //check images' ecat_img_hdr matches first + fseek(f, (lhdr.r[k][1]-1) * 512, SEEK_SET); //image header is block immediately before image + ecat_img_hdr ihdrN; + fread(&ihdrN, sizeof(ihdrN), 1, f); + if (swapEndian) { + nifti_swap_2bytes(5, &ihdrN.data_type); + nifti_swap_4bytes(7, &ihdrN.x_resolution); + nifti_swap_4bytes(3, &ihdrN.x_pixel_size); + } + if ((ihdr.data_type != ihdrN.data_type) || (ihdr.x_dimension != ihdrN.x_dimension) || (ihdr.y_dimension != ihdrN.y_dimension) || (ihdr.z_dimension != ihdrN.z_dimension)) { + printMessage("Error: ECAT volumes have varying image dimensions\n"); + isAbort = true; + } + if (num_vol < kMaxVols) + imgOffsets[num_vol] = lhdr.r[k][1]; + num_vol ++; + } + if ((lhdr.hdr[0] > 0) || (isAbort)) break; //this list contains empty volumes: all lists have been read + } //read all image offsets + //report error reading image offsets + if ((num_vol < 1) || (isAbort) || (num_vol >= kMaxVols)) { + printMessage("Failure to extract ECAT7 images\n"); + if (num_vol >= kMaxVols) printMessage("Increase kMaxVols"); + fclose(f); + free (imgOffsets); + return NULL; + } + //load image data + + + size_t bytesPerVolume = ihdr.x_dimension * ihdr.y_dimension * ihdr.z_dimension * bytesPerVoxel; + unsigned char * img = (unsigned char*)malloc(bytesPerVolume * num_vol); + for (int v = 0; v < num_vol; v++) { + //printMessage("%d --> %lu\n", v, imgOffsets[v]); + fseek(f, imgOffsets[v] * 512, SEEK_SET); + size_t sz = fread( &img[v * bytesPerVolume], 1, bytesPerVolume, f); + } + + if ((swapEndian) && (bytesPerVoxel == 2)) nifti_swap_2bytes(ihdr.x_dimension * ihdr.y_dimension * ihdr.z_dimension * num_vol, img); + if ((swapEndian) && (bytesPerVoxel == 4)) nifti_swap_4bytes(ihdr.x_dimension * ihdr.y_dimension * ihdr.z_dimension * num_vol, img); + printMessage("ECAT support VERY experimental (Spatial transforms unknown)\n"); + free (imgOffsets); + fclose(f); + //fill DICOM header + dcm->bitsAllocated = bytesPerVoxel * 8; + dcm->samplesPerPixel = 1; + dcm->xyzMM[1] = ihdr.x_pixel_size * 10.0; //cm -> mm + dcm->xyzMM[2] = ihdr.y_pixel_size * 10.0; //cm -> mm + dcm->xyzMM[3] = ihdr.z_pixel_size * 10.0; //cm -> mm + dcm->xyzMM[4] = 123; //TR: TO DO + dcm->xyzDim[1] = ihdr.x_dimension; + dcm->xyzDim[2] = ihdr.y_dimension; + dcm->xyzDim[3] = ihdr.z_dimension; + dcm->xyzDim[4] = num_vol; + strcpy(dcm->patientName, mhdr.patient_name);//patient_id[16], patient_name[32] + strcpy(dcm->patientID, mhdr.patient_name); + strcpy(dcm->seriesDescription, mhdr.study_description); + strcpy(dcm->protocolName, mhdr.study_type); + strcpy(dcm->imageComments, mhdr.isotope_name); + headerDcm2Nii(*dcm, hdr); + if (mhdr.gantry_tilt != 0.0) printMessage("Warning: ECAT gantry tilt not supported %g\n", mhdr.gantry_tilt); + + //convertForeignToNifti(nhdr); + return img; } +int nii_createFilename(char * niiFilename, struct TDCMopts opts) { + char pathoutname[1024] = {"/Users/rorden/Documents/Cocoa/dcm2niix/console/mega"}; + strcpy(niiFilename,pathoutname); + return EXIT_SUCCESS; +} -int open_foreign (const char *fn){ - struct nifti_1_header nhdr; - bool swapEndian; +int open_foreign (const char *fn, struct TDCMopts opts){ + printMessage("ECAT images not yet supported\n"); return EXIT_FAILURE; + struct nifti_1_header hdr; + struct TDICOMdata dcm = clear_dicom_data(); + //bool swapEndian; unsigned char * img = NULL; - int ret = nii_readEcat7(fn, &nhdr, &swapEndian, &img); - if (ret == EXIT_SUCCESS) - printf("!\n"); + char niiFilename[1024] = {"/usr/myFolder/dicom.dcm"}; + int ret = nii_createFilename(niiFilename, opts); + if (ret != EXIT_SUCCESS) return ret; + //img = nii_readEcat7(fn, &hdr); + img = nii_readEcat7(fn, &dcm, &hdr); + if (!img) return EXIT_FAILURE; + ret = nii_saveNII(niiFilename, hdr, img, opts); free(img); return ret; }// open_foreign() diff --git a/console/nii_foreign.h b/console/nii_foreign.h index 0af9d130..db7eeb9e 100644 --- a/console/nii_foreign.h +++ b/console/nii_foreign.h @@ -7,7 +7,10 @@ extern "C" { #endif -int open_foreign (const char *fn); +#include "nii_dicom_batch.h" + +//int open_foreign (const char *fn); +int open_foreign (const char *fn, struct TDCMopts opts); #ifdef __cplusplus }