/*! * Write ECAT 6.3 matrix data to a specified file position. * Data does not need to be allocated for full blocks. * Data must be represented in current machines byte order, and it is * always saved in big endian byte order. * Give also nr of pixels and byte size of one pixel. * * @param fp target file pointer * @param strtblk starting image block [>=1] * @param data pointer to data that is written * @param pxlNr number of items to be written [>=1] * @param pxlSize size of one data item in bytes [>=1] * @return 0 if ok, 1 invalid input, 2 failed to find starting block, * 3 failed to write data */ int ecat63WriteMatdata(FILE *fp, int strtblk, char *data, int pxlNr, int pxlSize) { unsigned char buf[MatBLKSIZE]; char *dptr; int i, blkNr, dataSize, byteNr; if(ECAT63_TEST) printf("ecat63WriteMatdata(fp, %d, data, %d, %d)\n", strtblk, pxlNr, pxlSize); if(fp==NULL || strtblk<1 || data==NULL || pxlNr<1 || pxlSize<1) return(1); memset(buf, 0, MatBLKSIZE); dataSize=pxlNr*pxlSize; if(dataSize<1) return(1); /* block nr taken by all pixels */ blkNr=(dataSize+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) return(1); if(ECAT63_TEST>1) printf(" blkNr=%d\n", blkNr); /* Search the place for writing */ fseek(fp, (strtblk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(strtblk-1)*MatBLKSIZE) return(2); /* Save blocks one at a time */ for(i=0, dptr=data; i<blkNr && dataSize>0; i++) { byteNr=(dataSize<MatBLKSIZE)?dataSize:MatBLKSIZE; memcpy(buf, dptr, byteNr); /* Change matrix byte order in big endian platforms */ if(!little_endian()) { if(pxlSize==2) swabip(buf, byteNr); else if(pxlSize==4) swawbip(buf, byteNr); } /* Write block */ if(fwrite(buf, 1, MatBLKSIZE, fp)!=MatBLKSIZE) return(3); /* Prepare for the next block */ dptr+=byteNr; dataSize-=byteNr; } /* next block */ return(0); }
/*! * Write ECAT 6.3 image header * * @param fp target file pointer * @param block block number [>= 3] * @param h Ecat 6.3 image header * @return 0, if ok, 1 invalid input, 2 failed to find block, * 3 failed to write block */ int ecat63WriteImageheader(FILE *fp, int block, ECAT63_imageheader *h) { char buf[MatBLKSIZE]; int i, little, tovax; if(ECAT63_TEST) printf("ecat63WriteImageheader(fp, %d, ih)\n", block); little=little_endian(); /* Clear buf */ memset(buf, 0, MatBLKSIZE); /* Check arguments */ if(fp==NULL || block<3 || h->data_type<1 || h->data_type>7) return(1); if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4) tovax=1; else tovax=0; /* Copy short ints to buf */ memcpy(buf+126, &h->data_type, 2); memcpy(buf+128, &h->num_dimensions, 2); memcpy(buf+132, &h->dimension_1, 2); memcpy(buf+134, &h->dimension_2, 2); memcpy(buf+176, &h->image_min, 2); memcpy(buf+178, &h->image_max, 2); memcpy(buf+200, &h->slice_location, 2); memcpy(buf+202, &h->recon_start_hour, 2); memcpy(buf+204, &h->recon_start_min, 2); memcpy(buf+206, &h->recon_start_sec, 2); memcpy(buf+236, &h->filter_code, 2); memcpy(buf+376, &h->processing_code, 2); memcpy(buf+380, &h->quant_units, 2); memcpy(buf+382, &h->recon_start_day, 2); memcpy(buf+384, &h->recon_start_month, 2); memcpy(buf+386, &h->recon_start_year, 2); memcpy(buf+460, h->fill2, 52); /* big to little endian if necessary */ if(!little) swabip(buf, MatBLKSIZE); /* Copy floats to buf */ ecat63wFloat(&h->x_origin, buf+160, tovax, little); ecat63wFloat(&h->y_origin, buf+164, tovax, little); ecat63wFloat(&h->recon_scale, buf+168, tovax, little); ecat63wFloat(&h->quant_scale, buf+172, tovax, little); ecat63wFloat(&h->pixel_size, buf+184, tovax, little); ecat63wFloat(&h->slice_width, buf+188, tovax, little); ecat63wFloat(&h->image_rotation, buf+296, tovax, little); ecat63wFloat(&h->plane_eff_corr_fctr, buf+300, tovax, little); ecat63wFloat(&h->decay_corr_fctr, buf+304, tovax, little); ecat63wFloat(&h->loss_corr_fctr, buf+308, tovax, little); ecat63wFloat(&h->intrinsic_tilt, buf+312, tovax, little); ecat63wFloat(&h->ecat_calibration_fctr, buf+388, tovax, little); ecat63wFloat(&h->well_counter_cal_fctr, buf+392, tovax, little); for(i=0; i<6; i++) ecat63wFloat(&h->filter_params[i], buf+396+4*i, tovax, little); /* Copy ints to buf */ ecat63wInt(&h->frame_duration, buf+192, tovax, little); ecat63wInt(&h->frame_start_time, buf+196, tovax, little); ecat63wInt(&h->scan_matrix_num, buf+238, tovax, little); ecat63wInt(&h->norm_matrix_num, buf+242, tovax, little); ecat63wInt(&h->atten_cor_mat_num, buf+246, tovax, little); /* Copy chars */ memcpy(buf+0, h->fill1, 126); memcpy(buf+420, h->annotation, 40); /* Write subheader */ fseek(fp, (block-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(block-1)*MatBLKSIZE) return(2); if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3); return(0); }
/*! * Read ECAT 6.3 matrix data and convert byte order if necessary * Remember to allocate memory for full blocks! * There are differences here when compared to ecat7.c * * @param fp file pointer from where data is read * @param strtblk starting block [>= 1] * @param blkNr number of block to be read [>= 0] * @param data pointer to block where data is read * @param dtype data type code * @return 0 if ok, 1 invalid input, 2 failed to read data, * 9 failed to find starting block from file, */ int ecat63ReadMatdata(FILE *fp, int strtblk, int blkNr, char *data, int dtype) { int i, n, little, err=0; char *cptr; float f; if(ECAT63_TEST) printf("ecat63ReadMatdata(fp, %d, %d, data, %d)\n", strtblk, blkNr, dtype); /* Check the arguments */ if(blkNr<=0 || strtblk<1 || data==NULL) return(1); /* Seek the first data block */ fseek(fp, (strtblk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(strtblk-1)*MatBLKSIZE) return(9); /* Read the data blocks */ if(fread(data, MatBLKSIZE, blkNr, fp) < blkNr) return(2); /* Translate data if necessary */ little=little_endian(); switch(dtype) { case BYTE_TYPE: /* byte format...no translation necessary */ break; case VAX_I2: /* byte conversion necessary on big endian platform */ if(!little) {cptr=data; swabip(cptr, blkNr*MatBLKSIZE);} break; case VAX_I4: for(i=0, cptr=data; i<blkNr*MatBLKSIZE; i+=4, cptr+=4) { n=ecat63rInt(cptr, 1, little); memcpy(cptr, &n, 4); } break; case VAX_R4: for(i=0, cptr=data; i<blkNr*MatBLKSIZE; i+=4, cptr+=4) { f=ecat63rFloat(cptr, 1, little); memcpy(cptr, &f, 4); } break; case IEEE_R4: /* IEEE float ; byte conversion necessary on big end platforms */ case SUN_I4: /* SUN int ; byte conversion necessary on big end platforms */ if(!little) swawbip(data, blkNr*MatBLKSIZE); break; case SUN_I2: /* SUN short ; byte conversion necessary on big end platforms */ if(!little) swabip(data, blkNr*MatBLKSIZE); break; default: /* if something else, for now think it as an error */ err=2; break; } return(err); }
/*! * Read ECAT 6.3 attenuation header * * @param fp file pointer * @param blk block number [2..number of blocks] * @param h Ecat 6.3 attenuation header * @return 0 if ok, 1 failed to find block, 3 failed to read block, * 4 invalid data type, 5 invalid scale factor */ int ecat63ReadAttnheader(FILE *fp, int blk, ECAT63_attnheader *h) { unsigned char buf[MatBLKSIZE]; int little; /* 1 if current platform is little endian (i386), else 0 */ int vaxdata=1; /* 1 if data is in VAX format, else 0 */ if(ECAT63_TEST) printf("ecat63ReadAttnheader(fp, %d, ah)\n", blk); if(fp==NULL || blk<2 || h==NULL) return(1); little=little_endian(); /* Seek the subheader block */ fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(2); /* Read the subheader block */ if(fread(buf, MatBLKSIZE, 1, fp)<1) return(3); /* Copy short ints */ /* in big endian platform, change byte order temporarily */ if(!little) swabip(buf, MatBLKSIZE); memcpy(&h->data_type, buf+126, 2); if(h->data_type>4) vaxdata=0; /*printf("data_type=%d\n", h->data_type);*/ memcpy(&h->attenuation_type, buf+128, 2); memcpy(&h->dimension_1, buf+132, 2); memcpy(&h->dimension_2, buf+134, 2); /* Change back the byte order */ if(!little) swabip(buf, MatBLKSIZE); /* Copy floats */ h->scale_factor=ecat63rFloat(buf+182, vaxdata, little); h->x_origin=ecat63rFloat(buf+186, vaxdata, little); h->y_origin=ecat63rFloat(buf+190, vaxdata, little); h->x_radius=ecat63rFloat(buf+194, vaxdata, little); h->y_radius=ecat63rFloat(buf+198, vaxdata, little); h->tilt_angle=ecat63rFloat(buf+202, vaxdata, little); h->attenuation_coeff=ecat63rFloat(buf+206, vaxdata, little); h->sample_distance=ecat63rFloat(buf+210, vaxdata, little); /* Check that most important contents are ok */ if(h->data_type<BYTE_TYPE || h->data_type>SUN_I4) { if(ECAT63_TEST) printf("Invalid data types; probable conversion error.\n"); return(4); } if(h->scale_factor<=0.0 || h->scale_factor>1.0e8) { if(ECAT63_TEST) printf("Invalid scale factor; probable conversion error.\n"); return(5); } return(0); }
/*! * Write ECAT 6.3 scan header * * @param fp target file pointer * @param block block number [>=3] * @param h Ecat 6.3 scan header * @return 0 if ok, 1 invalid input, 2 failed to find block, * 3 failed to write block */ int ecat63WriteScanheader(FILE *fp, int block, ECAT63_scanheader *h) { unsigned char buf[MatBLKSIZE]; int i, little, tovax; if(ECAT63_TEST) printf("ecat63WriteScanheader(fp, %d, ih)\n", block); little=little_endian(); /* Clear buf */ memset(buf, 0, MatBLKSIZE); /* Check arguments */ if(fp==NULL || block<3 || h->data_type<1 || h->data_type>7) return(1); if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4) tovax=1; else tovax=0; /* Copy short ints to buf */ memcpy(buf+126, &h->data_type, 2); memcpy(buf+132, &h->dimension_1, 2); memcpy(buf+134, &h->dimension_2, 2); memcpy(buf+136, &h->smoothing, 2); memcpy(buf+138, &h->processing_code, 2); memcpy(buf+170, &h->frame_duration_sec, 2); memcpy(buf+192, &h->scan_min, 2); memcpy(buf+194, &h->scan_max, 2); memcpy(buf+468, h->fill2, 44); /* big to little endian if necessary */ if(!little) swabip(buf, MatBLKSIZE); /* Copy floats to buf */ ecat63wFloat(&h->sample_distance, buf+146, tovax, little); ecat63wFloat(&h->isotope_halflife, buf+166, tovax, little); ecat63wFloat(&h->scale_factor, buf+182, tovax, little); for(i=0; i<16; i++) { ecat63wFloat(&h->cor_singles[i], buf+316+4*i, tovax, little); ecat63wFloat(&h->uncor_singles[i], buf+380+4*i, tovax, little); } ecat63wFloat(&h->tot_avg_cor, buf+444, tovax, little); ecat63wFloat(&h->tot_avg_uncor, buf+448, tovax, little); ecat63wFloat(&h->loss_correction_fctr, buf+464, tovax, little); /* Copy ints to buf */ ecat63wInt(&h->gate_duration, buf+172, tovax, little); ecat63wInt(&h->r_wave_offset, buf+176, tovax, little); ecat63wInt(&h->prompts, buf+196, tovax, little); ecat63wInt(&h->delayed, buf+200, tovax, little); ecat63wInt(&h->multiples, buf+204, tovax, little); ecat63wInt(&h->net_trues, buf+208, tovax, little); ecat63wInt(&h->total_coin_rate, buf+452, tovax, little); ecat63wInt(&h->frame_start_time, buf+456, tovax, little); ecat63wInt(&h->frame_duration, buf+460, tovax, little); /* Copy chars */ memcpy(buf+0, h->fill1, 126); /* Write subheader */ fseek(fp, (block-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(block-1)*MatBLKSIZE) return(2); if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3); return(0); }/*****************************************************************************/
/*! * Read ECAT 6.3 normalization header * * @param fp file pointer * @param blk block number [2..number of blocks] * @param h Ecat 6.3 normalization header * @return 0 if ok, 1 invalid input, 2 failed to find block, * 3 failed to read block, 4 invalid data type, 5 invalid scale factor */ int ecat63ReadNormheader(FILE *fp, int blk, ECAT63_normheader *h) { unsigned char buf[MatBLKSIZE]; int little; /* 1 if current platform is little endian (i386), else 0 */ int vaxdata=1; /* 1 if data is in VAX format, else 0 */ if(ECAT63_TEST) printf("ecat63ReadNormheader(fp, %d, nh)\n", blk); if(fp==NULL || blk<2 || h==NULL) return(1); little=little_endian(); /* Seek the subheader block */ fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(2); /* Read the subheader block */ if(fread(buf, MatBLKSIZE, 1, fp)<1) return(3); /* Copy short ints */ /* in big endian platform, change byte order temporarily */ if(!little) swabip(buf, MatBLKSIZE); memcpy(&h->data_type, buf+126, 2); if(h->data_type>4) vaxdata=0; /*printf("data_type=%d\n", h->data_type);*/ memcpy(&h->dimension_1, buf+132, 2); memcpy(&h->dimension_2, buf+134, 2); memcpy(&h->norm_hour, buf+186, 2); memcpy(&h->norm_minute, buf+188, 2); memcpy(&h->norm_second, buf+190, 2); memcpy(&h->norm_day, buf+192, 2); memcpy(&h->norm_month, buf+194, 2); memcpy(&h->norm_year, buf+196, 2); /* Change back the byte order */ if(!little) swabip(buf, MatBLKSIZE); /* Copy floats */ h->scale_factor=ecat63rFloat(buf+182, vaxdata, little); h->fov_source_width=ecat63rFloat(buf+198, vaxdata, little); /* Check that most important contents are ok */ if(h->data_type<BYTE_TYPE && h->data_type>SUN_I4) { if(ECAT63_TEST) printf("Invalid data types; probable conversion error.\n"); return(4); } if(h->scale_factor<=0.0 || h->scale_factor>1.0e8) { if(ECAT63_TEST) printf("Invalid scale factor; probable conversion error.\n"); return(5); } return(0); }
/*! * Reading ECAT 6.3 floats * * @param bufi pointer to 32-bit long data block * @param isvax 1 for VAX format * @param islittle 1 for little endian * @return read float value */ float ecat63rFloat(void *bufi, int isvax, int islittle) { union {unsigned int ul; float f;} t; memcpy(&t.ul, bufi, 4); if(t.ul==0) {return(0.0);} if(isvax) { /* if input is in VAX format */ /* Swap words on i386 and bytes on SUN */ if(islittle) swawip(&t.ul, 4); else swabip(&t.ul, 4); t.ul-=(2L<<23); /* subtract 2 from exp */ } else { /* input is in i386 format */ if(!islittle) swawbip(&t.ul, 4); /* Switch words and bytes on SUN */ } return(t.f); }
/*! * Writing ECAT 6.3 floats * * @param bufi pointer to 4-byte long input (float data) * @param bufo pointer to 4-byte long output * @param tovax 1 for VAX format * @param islittle 1 for little endian */ void ecat63wFloat(float *bufi, void *bufo, int tovax, int islittle) { unsigned int ul; memcpy(&ul, bufi, 4); if(ul==0) {memcpy(bufo, bufi, 4); return;} if(tovax) { /* If VAX format is needed */ ul+=(2L<<23); /* increase exp by 2 */ /* Swap words on i386 and bytes on SUN */ if(islittle) swawip(&ul, 4); else swabip(&ul, 4); } else { if(!islittle) swawbip(&ul, 4); /* Switch words and bytes on SUN */ } memcpy(bufo, &ul, 4); }
/*! * Write ECAT 6.3 normalization header * * @param fp target file pointer * @param block block number [>=3] * @param h Ecat 6.3 normalization header * @return 0 if ok, 1 invalid input, 2 failed to find block, * 3 failed to write block */ int ecat63WriteNormheader(FILE *fp, int block, ECAT63_normheader *h) { unsigned char buf[MatBLKSIZE]; int little, tovax; if(ECAT63_TEST) printf("ecat63WriteNormheader(fp, %d, nh)\n", block); little=little_endian(); /* Clear buf */ memset(buf, 0, MatBLKSIZE); /* Check arguments */ if(fp==NULL || block<3 || h->data_type<1 || h->data_type>7) return(1); if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4) tovax=1; else tovax=0; /* Copy short ints to buf */ memcpy(buf+126, &h->data_type, 2); memcpy(buf+132, &h->dimension_1, 2); memcpy(buf+134, &h->dimension_2, 2); memcpy(buf+372, &h->norm_hour, 2); memcpy(buf+376, &h->norm_minute, 2); memcpy(buf+380, &h->norm_second, 2); memcpy(buf+384, &h->norm_day, 2); memcpy(buf+388, &h->norm_month, 2); memcpy(buf+392, &h->norm_year, 2); /* big to little endian if necessary */ if(!little) swabip(buf, MatBLKSIZE); /* Copy floats to buf */ ecat63wFloat(&h->scale_factor, buf+182, tovax, little); ecat63wFloat(&h->fov_source_width, buf+198, tovax, little); /* Write subheader */ fseek(fp, (block-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(block-1)*MatBLKSIZE) return(2); if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3); return(0); }
/*! * Write ECAT 6.3 attenuation header * * @param fp target file pointer * @param block block number [>=3] * @param h Ecat 6.3 attenuation header * @return 0 if ok, 1 invalid input, 2 failed to find block, * 3 failed to write block */ int ecat63WriteAttnheader(FILE *fp, int block, ECAT63_attnheader *h) { unsigned char buf[MatBLKSIZE]; int little, tovax; if(ECAT63_TEST) printf("ecat63WriteAttnheader(fp, %d, ah)\n", block); little=little_endian(); /* Clear buf */ memset(buf, 0, MatBLKSIZE); /* Check arguments */ if(fp==NULL || block<3 || h->data_type<1 || h->data_type>7) return(1); if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4) tovax=1; else tovax=0; /* Copy short ints to buf */ memcpy(buf+126, &h->data_type, 2); memcpy(buf+128, &h->attenuation_type, 2); memcpy(buf+132, &h->dimension_1, 2); memcpy(buf+134, &h->dimension_2, 2); /* big to little endian if necessary */ if(!little) swabip(buf, MatBLKSIZE); /* Copy floats to buf */ ecat63wFloat(&h->scale_factor, buf+182, tovax, little); ecat63wFloat(&h->x_origin, buf+186, tovax, little); ecat63wFloat(&h->y_origin, buf+190, tovax, little); ecat63wFloat(&h->x_radius, buf+194, tovax, little); ecat63wFloat(&h->y_radius, buf+198, tovax, little); ecat63wFloat(&h->tilt_angle, buf+202, tovax, little); ecat63wFloat(&h->attenuation_coeff, buf+206, tovax, little); ecat63wFloat(&h->sample_distance, buf+210, tovax, little); /* Write subheader */ fseek(fp, (block-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(block-1)*MatBLKSIZE) return(2); if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3); return(0); }
int anaReadHeader(const char *filename, ANALYZE_DSR *h) { unsigned char buf1[ANALYZE_HEADER_KEY_SIZE]; unsigned char buf2[ANALYZE_HEADER_IMGDIM_SIZE]; unsigned char buf3[ANALYZE_HEADER_HISTORY_SIZE]; int little; /* 1 if current platform is little endian (i386), else 0 */ FILE *fp; int ret, nr, s1, s2, same_order; if(ANALYZE_TEST) printf("anaReadHeader(%s, *dsr)\n", filename); /* Check arguments */ if(strlen(filename)<1 || h==NULL) { printf("could not open file : %s, or the ANALYZE_DSR is not allocated", filename); return 1; } little = little_endian(); /* Open file */ fp=fopen(filename, "rb"); if(fp==NULL) { printf("could not open file : %s", filename); return 2; } /* Get file size */ nr=0; while((ret=fgetc(fp))!=EOF) nr++; rewind(fp); if(nr<1) { fclose(fp); return(3); } /* Read Analyze header key */ if(fread(buf1, ANALYZE_HEADER_KEY_SIZE, 1, fp)<1) return(3); /* Read Analyze header image dimension */ if(fread(buf2, ANALYZE_HEADER_IMGDIM_SIZE, 1, fp)<1) return(3); /* Read Analyze header image data history */ memset(buf3, 0, sizeof(data_history)); ret=fread(buf3, ANALYZE_HEADER_HISTORY_SIZE, 1, fp); if(ANALYZE_TEST>1 && ret<1) printf(" complete data_history not found.\n"); /* Close file */ fclose(fp); /* Compare file size from header contents to the calculated value */ /* to determine whether Analyze file is in little or big endian */ memcpy(&s1, buf1+0, 4); s2=s1; swawbip(&s2, 4); if( abs(s1 - nr) < abs(s2 - nr)) { same_order=1; } else { same_order=0; } if(ANALYZE_TEST>1) printf("same byte order: %d (s1=%d s2=%d nr=%d)\n", same_order, s1, s2, nr); if(same_order) h->little=little; else {if(little) h->little=0; else h->little=1;} /* Set key header structure contents */ if(!same_order) swawbip(buf1+0, 4); memcpy(&h->hk.sizeof_hdr, buf1+0, 4); memcpy(h->hk.data_type, buf1+4, 10); memcpy(h->hk.db_name, buf1+14, 18); if(!same_order) swawbip(buf1+32, 4); memcpy(&h->hk.extents, buf1+32, 4); if(!same_order) swabip(buf1+36, 2); memcpy(&h->hk.session_error, buf1+36, 2); memcpy(&h->hk.regular, buf1+38, 1); memcpy(&h->hk.hkey_un0, buf1+39, 1); /* Set image dimension header structure contents */ if(!same_order) swabip(buf2+0, 16); memcpy(h->dime.dim, buf2+0, 16); if(!same_order) swabip(buf2+16, 2); memcpy(&h->dime.unused8, buf2+16, 2); if(!same_order) swabip(buf2+18, 2); memcpy(&h->dime.unused9, buf2+18, 2); if(!same_order) swabip(buf2+20, 2); memcpy(&h->dime.unused10, buf2+20, 2); if(!same_order) swabip(buf2+22, 2); memcpy(&h->dime.unused11, buf2+22, 2); if(!same_order) swabip(buf2+24, 2); memcpy(&h->dime.unused12, buf2+24, 2); if(!same_order) swabip(buf2+26, 2); memcpy(&h->dime.unused13, buf2+26, 2); if(!same_order) swabip(buf2+28, 2); memcpy(&h->dime.unused14, buf2+28, 2); if(!same_order) swabip(buf2+30, 2); memcpy(&h->dime.datatype, buf2+30, 2); if(!same_order) swabip(buf2+32, 2); memcpy(&h->dime.bitpix, buf2+32, 2); if(!same_order) swabip(buf2+34, 2); memcpy(&h->dime.dim_un0, buf2+34, 2); if(!same_order) swawbip(buf2+36, 32); memcpy(h->dime.pixdim, buf2+36, 32); if(!same_order) swawbip(buf2+68, 4); memcpy(&h->dime.vox_offset, buf2+68, 4); if(!same_order) swawbip(buf2+72, 4); memcpy(&h->dime.funused1, buf2+72, 4); if(!same_order) swawbip(buf2+76, 4); memcpy(&h->dime.funused2, buf2+76, 4); if(!same_order) swawbip(buf2+80, 4); memcpy(&h->dime.funused3, buf2+80, 4); if(!same_order) swawbip(buf2+84, 4); memcpy(&h->dime.cal_max, buf2+84, 4); if(!same_order) swawbip(buf2+88, 4); memcpy(&h->dime.cal_min, buf2+88, 4); if(!same_order) swawbip(buf2+92, 4); memcpy(&h->dime.compressed, buf2+92, 4); if(!same_order) swawbip(buf2+96, 4); memcpy(&h->dime.verified, buf2+96, 4); if(!same_order) swawbip(buf2+100, 4); memcpy(&h->dime.glmax, buf2+100, 4); if(!same_order) swawbip(buf2+104, 4); memcpy(&h->dime.glmin, buf2+104, 4); /* Set data history header structure contents */ memcpy(h->hist.descrip, buf3+0, 80); memcpy(h->hist.aux_file, buf3+80, 24); memcpy(&h->hist.orient, buf3+104, 1); memcpy(h->hist.originator, buf3+105, 10); memcpy(h->hist.generated, buf3+115, 10); memcpy(h->hist.scannum, buf3+125, 10); memcpy(h->hist.patient_id, buf3+135, 10); memcpy(h->hist.exp_date, buf3+145, 10); memcpy(h->hist.exp_time, buf3+155, 10); memcpy(h->hist.hist_un0, buf3+165, 3); if(!same_order) swawbip(buf3+168, 4); memcpy(&h->hist.views, buf3+168, 4); if(!same_order) swawbip(buf3+172, 4); memcpy(&h->hist.vols_added, buf3+172, 4); if(!same_order) swawbip(buf3+176, 4); memcpy(&h->hist.start_field, buf3+176,4); if(!same_order) swawbip(buf3+180, 4); memcpy(&h->hist.field_skip, buf3+180, 4); if(!same_order) swawbip(buf3+184, 4); memcpy(&h->hist.omax, buf3+184, 4); if(!same_order) swawbip(buf3+188, 4); memcpy(&h->hist.omin, buf3+188, 4); if(!same_order) swawbip(buf3+192, 4); memcpy(&h->hist.smax, buf3+192, 4); if(!same_order) swawbip(buf3+196, 4); memcpy(&h->hist.smin, buf3+196, 4); /* Check header contents */ if(h->hk.extents!=16384 && h->hk.extents!=0) { if(ANALYZE_TEST>1) printf("hk.extents := %d\n", h->hk.extents); return(11); } if(h->hk.regular!='r') { if(ANALYZE_TEST>1) printf("hk.regular := %c\n", h->hk.regular); return(12); } return(0); }
int anaWriteHeader( const char *filename, const ANALYZE_DSR *h ) { unsigned char buf1[ANALYZE_HEADER_KEY_SIZE]; unsigned char buf2[ANALYZE_HEADER_IMGDIM_SIZE]; unsigned char buf3[ANALYZE_HEADER_HISTORY_SIZE]; FILE *fp; int same_order, little; if(ANALYZE_TEST) printf("anaWriteHeader(%s, *dsr)\n", filename); /* Check arguments */ if(strlen(filename)<1 || h==NULL) return(1); little=little_endian(); if(little==h->little) same_order=1; else same_order=0; /* Copy header contents into buffers */ /* Header key */ memset(buf1, 0, ANALYZE_HEADER_KEY_SIZE); memcpy(buf1+0, &h->hk.sizeof_hdr, 4); if(!same_order) swawbip(buf1+0, 4); memcpy(buf1+4, &h->hk.data_type, 10); memcpy(buf1+14, &h->hk.db_name, 18); memcpy(buf1+32, &h->hk.extents, 4); if(!same_order) swawbip(buf1+32, 4); memcpy(buf1+36, &h->hk.session_error, 2); if(!same_order) swabip(buf1+36, 2); memcpy(buf1+38, &h->hk.regular, 1); memcpy(buf1+39, &h->hk.hkey_un0, 1); /* Image dimension */ memset(buf2, 0, ANALYZE_HEADER_IMGDIM_SIZE); memcpy(buf2+0, h->dime.dim, 16); if(!same_order) swabip(buf2+0, 16); memcpy(buf2+16, &h->dime.unused8, 2); if(!same_order) swabip(buf2+16, 2); memcpy(buf2+18, &h->dime.unused9, 2); if(!same_order) swabip(buf2+18, 2); memcpy(buf2+20, &h->dime.unused10, 2); if(!same_order) swabip(buf2+20, 2); memcpy(buf2+22, &h->dime.unused11, 2); if(!same_order) swabip(buf2+22, 2); memcpy(buf2+24, &h->dime.unused12, 2); if(!same_order) swabip(buf2+24, 2); memcpy(buf2+26, &h->dime.unused13, 2); if(!same_order) swabip(buf2+26, 2); memcpy(buf2+28, &h->dime.unused14, 2); if(!same_order) swabip(buf2+28, 2); memcpy(buf2+30, &h->dime.datatype, 2); if(!same_order) swabip(buf2+30, 2); memcpy(buf2+32, &h->dime.bitpix, 2); if(!same_order) swabip(buf2+32, 2); memcpy(buf2+34, &h->dime.dim_un0, 2); if(!same_order) swabip(buf2+34, 2); memcpy(buf2+36, h->dime.pixdim, 32); if(!same_order) swawbip(buf2+36, 32); memcpy(buf2+68, &h->dime.vox_offset, 4); if(!same_order) swawbip(buf2+68, 4); memcpy(buf2+72, &h->dime.funused1, 4); if(!same_order) swawbip(buf2+72, 4); memcpy(buf2+76, &h->dime.funused2, 4); if(!same_order) swawbip(buf2+76, 4); memcpy(buf2+80, &h->dime.funused3, 4); if(!same_order) swawbip(buf2+80, 4); memcpy(buf2+84, &h->dime.cal_max, 4); if(!same_order) swawbip(buf2+84, 4); memcpy(buf2+88, &h->dime.cal_min, 4); if(!same_order) swawbip(buf2+88, 4); memcpy(buf2+92, &h->dime.compressed, 4); if(!same_order) swawbip(buf2+92, 4); memcpy(buf2+96, &h->dime.verified, 4); if(!same_order) swawbip(buf2+96, 4); memcpy(buf2+100, &h->dime.glmax, 4); if(!same_order) swawbip(buf2+100, 4); memcpy(buf2+104, &h->dime.glmin, 4); if(!same_order) swawbip(buf2+104, 4); /* Data history */ memset(buf3, 0, ANALYZE_HEADER_HISTORY_SIZE); memcpy(buf3+0, &h->hist.descrip, 80); memcpy(buf3+80, &h->hist.aux_file, 24); memcpy(buf3+104, &h->hist.orient, 1); memcpy(buf3+105, &h->hist.originator, 10); memcpy(buf3+115, &h->hist.generated, 10); memcpy(buf3+125, &h->hist.scannum, 10); memcpy(buf3+135, &h->hist.patient_id, 10); memcpy(buf3+145, &h->hist.exp_date, 10); memcpy(buf3+155, &h->hist.exp_time, 10); memcpy(buf3+165, &h->hist.hist_un0, 3); memcpy(buf3+168, &h->hist.views, 4); if(!same_order) swawbip(buf3+168, 4); memcpy(buf3+172, &h->hist.vols_added,4); if(!same_order) swawbip(buf3+172, 4); memcpy(buf3+176, &h->hist.start_field,4); if(!same_order) swawbip(buf3+176,4); memcpy(buf3+180, &h->hist.field_skip,4); if(!same_order) swawbip(buf3+180, 4); memcpy(buf3+184, &h->hist.omax, 4); if(!same_order) swawbip(buf3+184, 4); memcpy(buf3+188, &h->hist.omin, 4); if(!same_order) swawbip(buf3+188, 4); memcpy(buf3+192, &h->hist.smax, 4); if(!same_order) swawbip(buf3+192, 4); memcpy(buf3+196, &h->hist.smin, 4); if(!same_order) swawbip(buf3+196, 4); /* Open header file for write */ fp=fopen(filename, "wb"); if(fp==NULL) return(2); /* Write header key */ if(fwrite(buf1, 1, ANALYZE_HEADER_KEY_SIZE, fp) != ANALYZE_HEADER_KEY_SIZE) { fclose(fp); return(3); } /* Write image dimension */ if(fwrite(buf2, 1, ANALYZE_HEADER_IMGDIM_SIZE, fp) != ANALYZE_HEADER_IMGDIM_SIZE) { fclose(fp); return(4); } /* Write data history */ if(fwrite(buf3, 1, ANALYZE_HEADER_HISTORY_SIZE, fp) != ANALYZE_HEADER_HISTORY_SIZE) { fclose(fp); return(5); } fclose(fp); return(0); }
int anaReadImagedata(const char *filename, const ANALYZE_DSR *h, int frame, char *data) { int dimNr, dimx, dimy, dimz=1, dimt=1, pxlNr=0; int i, n, little, start_pos, rawSize; char *mdata, *mptr; char *fptr; float f; short int *sptr; int *iptr; double d; FILE *fp; /* Open file */ fp=fopen(filename, "rb"); if(fp==NULL) { printf("could not open Image File: %s", filename); return 2; } if(ANALYZE_TEST) printf("anaReadImagedata(fp, h, %d, data)\n", frame); /* Check the arguments */ if(frame<=0 || h==NULL || data==NULL) { printf("frame must be positive integer, Analyze header filled and the data allocated"); return 1; } /* Get the image dimensions from header */ dimNr=h->dime.dim[0]; if(dimNr<2) return(2); dimx=h->dime.dim[1]; dimy=h->dime.dim[2]; if(dimNr>2) dimz=h->dime.dim[3]; if(dimNr>3) dimt=h->dime.dim[4]; if(frame>dimt) return(3); pxlNr=dimx*dimy*dimz; if(pxlNr<1) return(4); /* Allocate memory for the binary data */ if(h->dime.bitpix<8) return(5); /* We don't support bit data */ rawSize=pxlNr*(h->dime.bitpix/8); if(rawSize<1) return(5); if(ANALYZE_TEST>0) printf(" pxlNr=%d rawSize=%d\n", pxlNr, rawSize); mdata=(char*)malloc(rawSize); if(mdata==NULL) return(11); /* Seek the start of current frame data */ start_pos=(frame-1)*rawSize; n=(int)h->dime.vox_offset; if((n>0 && frame==1) || (n<0)) start_pos+=abs(n); if(ANALYZE_TEST>2) printf("start_pos=%d\n", start_pos); fseek(fp, start_pos, SEEK_SET); if(ftell(fp)!=start_pos) { if(ANALYZE_TEST>5) printf("could not move to start_pos\n"); free(mdata); return(7); } /* Read the data */ mptr=mdata; if((n=fread(mptr, rawSize, 1, fp)) < 1) { if(ANALYZE_TEST>5) printf("could read only %d bytes when request was %d\n", n, rawSize); free(mdata); return(8); } /* Convert byte order if necessary */ little=little_endian(); mptr=mdata; if(little!=h->little) { if(ANALYZE_TEST>0) printf("byte conversion\n"); switch(h->dime.bitpix) { case 8: /* no conversion needed */ break; case 16: swabip(mptr, rawSize); break; case 32: swawbip(mptr, rawSize); break; case 64: swawbip(mptr, rawSize); break; default: if(ANALYZE_TEST>5) printf("unsupported anahdr.dime.bitpix := %d\n", h->dime.bitpix); free(mdata); return(5); } } /* Get scale factor */ f=1.0; if(h->dime.funused1>0.0) f*=h->dime.funused1; /* Copy data to float pixel values */ mptr=mdata; fptr=data; switch(h->dime.datatype) { case ANALYZE_DT_UNSIGNED_CHAR: if(h->dime.bitpix!=8) { if(ANALYZE_TEST>5) printf("invalid combination of datatype and bitpix (%d, %d)\n", h->dime.datatype, h->dime.bitpix); free(mdata); return(5); } for(i=0; i<pxlNr; i++, mptr++, fptr++) *fptr=f*(char)(*mptr); break; case ANALYZE_DT_SIGNED_SHORT: if(h->dime.bitpix!=16) { if(ANALYZE_TEST>5) printf("invalid combination of datatype and bitpix (%d, %d)\n", h->dime.datatype, h->dime.bitpix); free(mdata); return(5); } for(i=0; i<pxlNr; i++, mptr+=2, fptr++) { sptr=(short int*)mptr; *fptr=f*(float)(*sptr); } break; case ANALYZE_DT_SIGNED_INT: if(h->dime.bitpix!=16 && h->dime.bitpix!=32) { if(ANALYZE_TEST>5) printf("invalid combination of datatype and bitpix (%d, %d)\n", h->dime.datatype, h->dime.bitpix); free(mdata); return(5); } if(h->dime.bitpix==16) { for(i=0; i<pxlNr; i++, mptr+=4, fptr++) { iptr=(int*)mptr; *fptr=f*(float)(*iptr); } } else if(h->dime.bitpix==32) { for(i=0; i<pxlNr; i++, mptr+=4, fptr++) { iptr=(int*)mptr; *fptr=f*(float)(*iptr); } } break; case ANALYZE_DT_FLOAT: if(h->dime.bitpix!=16 && h->dime.bitpix!=32) { if(ANALYZE_TEST>5) printf("invalid combination of datatype and bitpix (%d, %d)\n", h->dime.datatype, h->dime.bitpix); free(mdata); return(5); } if(h->dime.bitpix==16) { memcpy(fptr, mptr, pxlNr*4); for(i=0; i<pxlNr; i++, fptr++) *fptr*=f; } else if(h->dime.bitpix==32) { memcpy(fptr, mptr, pxlNr*4); for(i=0; i<pxlNr; i++, fptr++) *fptr*=f; } break; case ANALYZE_DT_COMPLEX: if(h->dime.bitpix!=32) { if(ANALYZE_TEST>5) printf("invalid combination of datatype and bitpix (%d, %d)\n", h->dime.datatype, h->dime.bitpix); free(mdata); return(5); } if(h->dime.bitpix==32) { memcpy(fptr, mptr, pxlNr*4); for(i=0; i<pxlNr; i++, fptr++) *fptr*=f; } break; case ANALYZE_DT_DOUBLE: if(h->dime.bitpix!=32) { if(ANALYZE_TEST>5) printf("invalid combination of datatype and bitpix (%d, %d)\n", h->dime.datatype, h->dime.bitpix); free(mdata); return(5); } for(i=0; i<pxlNr; i++, mptr+=8, fptr++) { memcpy(&d, mptr, 8); *fptr=f*d; } break; default: if(ANALYZE_TEST>5) printf("unsupported anahdr.dime.datatype := %d\n", h->dime.datatype); free(mdata); return(5); } fclose(fp); free(mdata); if(ANALYZE_TEST>1) printf("anaReadImagedata() succeeded\n"); return(0); }
/*! * Read ECAT 6.3 scan header * * @param fp file pointer * @param blk block number [2..number of blocks] * @param h Ecat 6.3 scan header * @return 0 if ok, 1 invalid input, 2 failed to find block, * 3 failed to read block, 4 invalid data type, 5 invalid scale factor, * 6 invalid frame duration */ int ecat63ReadScanheader(FILE *fp, int blk, ECAT63_scanheader *h) { unsigned char buf[MatBLKSIZE]; int i; int little; /* 1 if current platform is little endian (i386), else 0 */ int vaxdata=1; /* 1 if data is in VAX format, else 0 */ if(ECAT63_TEST) printf("ecat63ReadScanheader(fp, %d, sh)\n", blk); if(fp==NULL || blk<2 || h==NULL) return(1); little=little_endian(); /* Seek the subheader block */ fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(2); /* Read the subheader block */ if(fread(buf, MatBLKSIZE, 1, fp)<1) return(3); /* Copy char data to header structure */ memcpy(h->fill1, buf+0, 126); /* Copy short ints */ /* in big endian platform, change byte order temporarily */ if(!little) swabip(buf, MatBLKSIZE); memcpy(&h->data_type, buf+126, 2); if(h->data_type>4) vaxdata=0; /*printf("data_type=%d\n", h->data_type);*/ memcpy(&h->dimension_1, buf+132, 2); memcpy(&h->dimension_2, buf+134, 2); memcpy(&h->smoothing, buf+136, 2); memcpy(&h->processing_code, buf+138, 2); memcpy(&h->frame_duration_sec, buf+170, 2); memcpy(&h->scan_min, buf+192, 2); memcpy(&h->scan_max, buf+194, 2); memcpy(h->fill2, buf+468, 44); /* Change back the byte order */ if(!little) swabip(buf, MatBLKSIZE); /* Copy ints */ h->gate_duration=ecat63rInt(buf+172, vaxdata, little); h->r_wave_offset=ecat63rInt(buf+176, vaxdata, little); h->prompts=ecat63rInt(buf+196, vaxdata, little); h->delayed=ecat63rInt(buf+200, vaxdata, little); h->multiples=ecat63rInt(buf+204, vaxdata, little); h->net_trues=ecat63rInt(buf+208, vaxdata, little); h->total_coin_rate=ecat63rInt(buf+452, vaxdata, little); h->frame_start_time=ecat63rInt(buf+456, vaxdata, little); h->frame_duration=ecat63rInt(buf+460, vaxdata, little); /* Copy floats */ h->sample_distance=ecat63rFloat(buf+146, vaxdata, little); h->isotope_halflife=ecat63rFloat(buf+166, vaxdata, little); h->scale_factor=ecat63rFloat(buf+182, vaxdata, little); for(i=0; i<16; i++) h->cor_singles[i]=ecat63rFloat(buf+316+i*4, vaxdata, little); for(i=0; i<16; i++) h->uncor_singles[i]=ecat63rFloat(buf+380+i*4, vaxdata, little); h->tot_avg_cor=ecat63rFloat(buf+444, vaxdata, little); h->tot_avg_uncor=ecat63rFloat(buf+448, vaxdata, little); h->loss_correction_fctr=ecat63rFloat(buf+464, vaxdata, little); /* Check that most important contents are ok */ if(h->data_type<BYTE_TYPE || h->data_type>SUN_I4) { if(ECAT63_TEST) printf("Invalid data types; probable conversion error.\n"); return(4); } if(h->scale_factor<=0.0 || h->scale_factor>1.0e8) { if(ECAT63_TEST) printf("Invalid scale factor; probable conversion error.\n"); return(5); } if(h->frame_duration<0.0 || h->frame_duration>1.0e12) { if(ECAT63_TEST) printf("Invalid frame duration; probable conversion error.\n"); return(6); } return(0); }
/*! * Write ECAT 6.3 main header. * * @param fp target file pointer * @param h Ecat 6.3 main header * @return 0, if ok, 1 invalid input, 2 failed to find block, * 3 failed to write block */ int ecat63WriteMainheader(FILE *fp, ECAT63_mainheader *h) { char buf[MatBLKSIZE]; int i, little, tovax; if(ECAT63_TEST) printf("ecat63WriteMainheader()\n"); little=little_endian(); /* Clear buf */ memset(buf, 0, MatBLKSIZE); /* Check arguments */ if(fp==NULL || h->data_type<1 || h->data_type>7) return(1); if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4) tovax=1; else tovax=0; /* Copy short ints to buf */ memcpy(buf+50, &h->data_type, 2); memcpy(buf+48, &h->sw_version, 2); memcpy(buf+52, &h->system_type, 2); memcpy(buf+54, &h->file_type, 2); memcpy(buf+66, &h->scan_start_day, 2); memcpy(buf+68, &h->scan_start_month, 2); memcpy(buf+70, &h->scan_start_year, 2); memcpy(buf+72, &h->scan_start_hour, 2); memcpy(buf+74, &h->scan_start_minute, 2); memcpy(buf+76, &h->scan_start_second, 2); memcpy(buf+134, &h->rot_source_speed, 2); memcpy(buf+136, &h->wobble_speed, 2); memcpy(buf+138, &h->transm_source_type, 2); memcpy(buf+148, &h->transaxial_samp_mode, 2); memcpy(buf+150, &h->coin_samp_mode, 2); memcpy(buf+152, &h->axial_samp_mode, 2); memcpy(buf+158, &h->calibration_units, 2); memcpy(buf+160, &h->compression_code, 2); memcpy(buf+350, &h->acquisition_type, 2); memcpy(buf+352, &h->bed_type, 2); memcpy(buf+354, &h->septa_type, 2); memcpy(buf+376, &h->num_planes, 2); memcpy(buf+378, &h->num_frames, 2); memcpy(buf+380, &h->num_gates, 2); memcpy(buf+382, &h->num_bed_pos, 2); memcpy(buf+452, &h->lwr_sctr_thres, 2); memcpy(buf+454, &h->lwr_true_thres, 2); memcpy(buf+456, &h->upr_true_thres, 2); memcpy(buf+472, h->fill2, 40); /* big to little endian if necessary */ if(!little) swabip(buf, MatBLKSIZE); /* Copy floats to buf */ ecat63wFloat(&h->isotope_halflife, buf+86, tovax, little); ecat63wFloat(&h->gantry_tilt, buf+122, tovax, little); ecat63wFloat(&h->gantry_rotation, buf+126, tovax, little); ecat63wFloat(&h->bed_elevation, buf+130, tovax, little); ecat63wFloat(&h->axial_fov, buf+140, tovax, little); ecat63wFloat(&h->transaxial_fov, buf+144, tovax, little); ecat63wFloat(&h->calibration_factor, buf+154, tovax, little); ecat63wFloat(&h->init_bed_position, buf+384, tovax, little); for(i=0; i<15; i++) ecat63wFloat(&h->bed_offset[i], buf+388+4*i, tovax, little); ecat63wFloat(&h->plane_separation, buf+448, tovax, little); ecat63wFloat(&h->init_bed_position, buf+458, tovax, little); /* Copy chars */ /*memcpy(buf+0, h->ecat_format, 14);*/ memcpy(buf+14, h->fill1, 14); memcpy(buf+28, h->original_file_name, 20); memcpy(buf+56, h->node_id, 10); memcpy(buf+78, h->isotope_code, 8); memcpy(buf+90, h->radiopharmaceutical, 32); memcpy(buf+162, h->study_name, 12); memcpy(buf+174, h->patient_id, 16); memcpy(buf+190, h->patient_name, 32); buf[222]=h->patient_sex; memcpy(buf+223, h->patient_age, 10); memcpy(buf+233, h->patient_height, 10); memcpy(buf+243, h->patient_weight, 10); buf[253]=h->patient_dexterity; memcpy(buf+254, h->physician_name, 32); memcpy(buf+286, h->operator_name, 32); memcpy(buf+318, h->study_description, 32); memcpy(buf+356, h->facility_name, 20); memcpy(buf+462, h->user_process_code, 10); /* Write main header */ fseek(fp, 0*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=0*MatBLKSIZE) return(2); if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3); return(0); }
/*! * Read ECAT 6.3 main header * * @param fp file pointer * @param h target Ecat 6.3 main header struture * @return 0 if ok, 1 invalid input, 2 failed to find subheader block, * 3 invalid magic number (should be "ECAT63") at start of file, * 5 invalid data type, 6 invalid calibration factor, 7 invalid file type */ int ecat63ReadMainheader(FILE *fp, ECAT63_mainheader *h) { unsigned char buf[MatBLKSIZE]; int i; int little; /* 1 if current platform is little endian (i386), else 0 */ int vaxdata=1; /* 1 if data is in VAX format, else 0 */ if(ECAT63_TEST) printf("ecat63ReadMainheader()\n"); if(fp==NULL || h==NULL) return(1); little=little_endian(); /* Seek the first block */ fseek(fp, 0, SEEK_SET); if(ftell(fp)!=0) return(1); /* Read the subheader block */ if(fread(buf, MatBLKSIZE, 1, fp)<1) return(2); /* Copy char data to header structure */ memcpy(h->ecat_format, buf+0, 14); memcpy(h->fill1, buf+14, 14); memcpy(h->original_file_name, buf+28, 20); memcpy(h->node_id, buf+56, 10); memcpy(h->isotope_code, buf+78, 8); memcpy(h->radiopharmaceutical, buf+90, 32); memcpy(h->study_name, buf+162, 12); memcpy(h->patient_id, buf+174, 16); memcpy(h->patient_name, buf+190, 32); h->patient_sex=buf[222]; memcpy(h->patient_age, buf+223, 10); memcpy(h->patient_height, buf+233, 10); memcpy(h->patient_weight, buf+243, 10); h->patient_dexterity=buf[253]; memcpy(h->physician_name, buf+254, 32); memcpy(h->operator_name, buf+286, 32); memcpy(h->study_description, buf+318, 32); memcpy(h->facility_name, buf+356, 20); memcpy(h->user_process_code, buf+462, 10); /* Copy short ints */ /* in big endian platform, change byte order temporarily */ if(!little) swabip(buf, MatBLKSIZE); memcpy(&h->data_type, buf+50, 2); if(h->data_type>4) vaxdata=0; /*printf("main_header.data_type=%d\n", h->data_type);*/ memcpy(&h->sw_version, buf+48, 2); memcpy(&h->system_type, buf+52, 2); memcpy(&h->file_type, buf+54, 2); memcpy(&h->scan_start_day, buf+66, 2); memcpy(&h->scan_start_month, buf+68, 2); memcpy(&h->scan_start_year, buf+70, 2); memcpy(&h->scan_start_hour, buf+72, 2); memcpy(&h->scan_start_minute, buf+74, 2); memcpy(&h->scan_start_second, buf+76, 2); memcpy(&h->rot_source_speed, buf+134, 2); memcpy(&h->wobble_speed, buf+136, 2); memcpy(&h->transm_source_type, buf+138, 2); memcpy(&h->transaxial_samp_mode, buf+148, 2); memcpy(&h->coin_samp_mode, buf+150, 2); memcpy(&h->axial_samp_mode, buf+152, 2); memcpy(&h->calibration_units, buf+158, 2); memcpy(&h->compression_code, buf+160, 2); memcpy(&h->acquisition_type, buf+350, 2); memcpy(&h->bed_type, buf+352, 2); memcpy(&h->septa_type, buf+354, 2); memcpy(&h->num_planes, buf+376, 2); memcpy(&h->num_frames, buf+378, 2); memcpy(&h->num_gates, buf+380, 2); memcpy(&h->num_bed_pos, buf+382, 2); memcpy(&h->lwr_sctr_thres, buf+452, 2); memcpy(&h->lwr_true_thres, buf+454, 2); memcpy(&h->upr_true_thres, buf+456, 2); memcpy(h->fill2, buf+472, 40); /* Change back the byte order */ if(!little) swabip(buf, MatBLKSIZE); /* Copy floats */ h->isotope_halflife=ecat63rFloat(buf+86, vaxdata, little); h->gantry_tilt=ecat63rFloat(buf+122, vaxdata, little); h->gantry_rotation=ecat63rFloat(buf+126, vaxdata, little); h->bed_elevation=ecat63rFloat(buf+130, vaxdata, little); h->axial_fov=ecat63rFloat(buf+140, vaxdata, little); h->transaxial_fov=ecat63rFloat(buf+144, vaxdata, little); h->calibration_factor=ecat63rFloat(buf+154, vaxdata, little); h->init_bed_position=ecat63rFloat(buf+384, vaxdata, little); for(i=0; i<15; i++) h->bed_offset[i]=ecat63rFloat(buf+388+i*4, vaxdata, little); h->plane_separation=ecat63rFloat(buf+448, vaxdata, little); h->collimator=ecat63rFloat(buf+458, vaxdata, little); /* Check file format and platform */ if(ECAT63_TEST) printf("ecat_format='%.14s'\n", h->ecat_format); /* if format is not specified, ECAT63 is assumed */ if(h->ecat_format[0]==(char)0) { strcpy(h->ecat_format, "ECAT63"); } /* only ECAT63 format is approved here */ if(ECAT63_TEST) printf("ecat_format='%.14s'\n", h->ecat_format); if(strncmp(h->ecat_format, "ECAT63", 6)!=0) return(3); /* Check that most important contents are ok */ if(h->data_type<BYTE_TYPE || h->data_type>SUN_I4) { if(ECAT63_TEST) printf("Invalid data types; probable conversion error.\n"); return(5); } if(h->calibration_factor<0.0 || h->calibration_factor>1.0e12) { if(ECAT63_TEST) printf("Invalid calibration factor; possible conversion error.\n"); return(6); } if(h->file_type!=RAW_DATA && h->file_type!=IMAGE_DATA && h->file_type!=ATTN_DATA && h->file_type!=NORM_DATA) { if(ECAT63_TEST) printf("Invalid file types; probable conversion error.\n"); return(7); } return(0); }
/*! * Write Analyze 7.5 image. * Analyze database name must be given with path. Path must exist. * Image and header files with .img and .hdr extensions are created. * Existing files are overwritten. * anaFlipping() determines whether image is flipped in z-direction; * image is always flipped in x,y-directions. * Byte order is determined based on _fileFormat field. * * @param dbname analyze database name with path, without extension * @param img pointer to IMG data * @return 0 if ok, 1 invalid input, 2 invalid image status (image not occupied), * 3 failed to resolve extreme values (min and max), * 12 failed to allocate temp memory, 14 failed to open file for writing, * 15 failed to write data, 21 failed to write header, and * sets IMG->statmsg in case of error */ int imgWriteAnalyze(const char *dbname, IMG *img) { FILE *fp; int ret, fi, pi, xi, yi, little; float g; ANALYZE_DSR dsr; char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX]; const char *cptr; int pxlNr=0; struct tm *st; short int *sdata, *sptr, smin, smax; SIF sif; if(IMG_TEST) printf("imgWriteAnalyze(%s, *img)\n", dbname); /* Check the arguments */ imgSetStatus(img, STATUS_OK); if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) { imgSetStatus(img, STATUS_FAULT); return(2);} if(dbname==NULL || !dbname[0]) {imgSetStatus(img, STATUS_FAULT); return(1);} /* Make the image and header filenames */ strcpy(datfile, dbname); strcat(datfile, ".img"); strcpy(hdrfile, dbname); strcat(hdrfile, ".hdr"); strcpy(siffile, dbname); strcat(siffile, ".sif"); /* * Fill Analyze header */ if(img->_fileFormat==IMG_ANA_L) dsr.little=1; else dsr.little=0; /* Header key */ memset(&dsr.hk, 0, sizeof(ANALYZE_HEADER_KEY)); memset(&dsr.dime, 0, sizeof(ANALYZE_HEADER_IMGDIM)); memset(&dsr.hist, 0, sizeof(ANALYZE_HEADER_HISTORY)); dsr.hk.sizeof_hdr=348; strcpy(dsr.hk.data_type, ""); cptr=strrchr(dbname, '/'); if(cptr==NULL) cptr=strrchr(dbname, '\\'); if(cptr!=NULL) cptr++; if(cptr==NULL) cptr=dbname; strncpy(dsr.hk.db_name, cptr, 17); dsr.hk.extents=16384; dsr.hk.regular='r'; /* Image dimension */ dsr.dime.dim[0]=4; dsr.dime.dim[1]=img->dimx; dsr.dime.dim[2]=img->dimy; dsr.dime.dim[3]=img->dimz; dsr.dime.dim[4]=img->dimt; dsr.dime.datatype=ANALYZE_DT_SIGNED_SHORT; dsr.dime.bitpix=16; dsr.dime.pixdim[0]=0.0; dsr.dime.pixdim[1]=img->sizex; dsr.dime.pixdim[2]=img->sizey; dsr.dime.pixdim[3]=img->sizez; dsr.dime.pixdim[4]=0.0; dsr.dime.funused1=0.0; /* Scale factor is set later */ /* dsr.dime.funused2=img->zoom; */ /* Reconstruction zoom */ dsr.dime.funused3=img->isotopeHalflife; /* Data history */ if(img->decayCorrection==IMG_DC_CORRECTED) strcpy(dsr.hist.descrip, "Decay corrected."); else if(img->decayCorrection==IMG_DC_NONCORRECTED) strcpy(dsr.hist.descrip, "No decay correction."); else strcpy(dsr.hist.descrip, ""); if(strlen(img->studyNr)>0 && strcmp(img->studyNr, ".")!=0) strncpy(dsr.hist.scannum, img->studyNr, 10); else strcpy(dsr.hist.scannum, ""); st=localtime(&img->scanStart); if(st!=NULL) { strftime(dsr.hist.exp_date, 10, "%Y-%m-%d", st); strftime(dsr.hist.exp_time, 10, "%H:%M:%S", st); } else { strncpy(dsr.hist.exp_date, "1900-01-01", 10); strncpy(dsr.hist.exp_time, "00:00:00", 10); } /* * Scale data to short int range * Determine and set scale factor and cal_min & cal_max */ if(IMG_TEST) printf("scaling data to short ints\n"); ret=imgMinMax(img, &dsr.dime.cal_min, &dsr.dime.cal_max); if(ret) {imgSetStatus(img, STATUS_FAULT); return(3);} if(fabs(dsr.dime.cal_min)>fabs(dsr.dime.cal_max)) g=fabs(dsr.dime.cal_min); else g=fabs(dsr.dime.cal_max); if(g<1E-20) g=1.0; else g=32767./g; dsr.dime.funused1=1.0/g; if(IMG_TEST) printf("min=%g max=%g scale_factor=%g\n", dsr.dime.cal_min, dsr.dime.cal_max, dsr.dime.funused1); /* Allocate memory for short int array */ pxlNr=(img->dimx)*(img->dimy)*(img->dimz); sdata=malloc(pxlNr*sizeof(short int)); if(sdata==NULL) { imgSetStatus(img, STATUS_NOMEMORY); return 12; } /* Open image data file for write */ if((fp=fopen(datfile, "wb")) == NULL) { imgSetStatus(img, STATUS_CANTWRITEIMGFILE); free(sdata); return 14; } /* Copy and write image matrix data to short int array */ /* Data is written one frame at a time */ smin=smax=temp_roundf(g*img->m[0][0][0][0]); for(fi=0; fi<img->dimt; fi++) { sptr=sdata; if(anaFlipping()==0) { for(pi=0; pi<img->dimz; pi++) for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) { *sptr=temp_roundf(g*img->m[pi][yi][xi][fi]); if(*sptr>smax) smax=*sptr; else if(*sptr<smin) smin=*sptr; sptr++; } } else { for(pi=img->dimz-1; pi>=0; pi--) for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) { *sptr=temp_roundf(g*img->m[pi][yi][xi][fi]); if(*sptr>smax) smax=*sptr; else if(*sptr<smin) smin=*sptr; sptr++; } } /* Change byte order if necessary */ little=little_endian(); if(little!=dsr.little) swabip(sdata, pxlNr*sizeof(short int)); /* Write image data */ if(fwrite(sdata, 2, pxlNr, fp) != pxlNr) { imgSetStatus(img, STATUS_CANTWRITEIMGFILE); free(sdata); fclose(fp); return 15; } } /* Done writing */ fclose(fp); free(sdata); if(IMG_TEST) printf("smin=%d smax=%d\n", smin, smax); /* Set header glmin & glmax */ dsr.dime.glmin=smin; dsr.dime.glmax=smax; /* Write Analyze header */ ret=anaWriteHeader(hdrfile, &dsr); if(ret) { imgSetStatus(img, STATUS_CANTWRITEHEADERFILE); return 21; } imgSetStatus(img, STATUS_OK); /* Otherwise ready, but check if SIF should/can be written */ sifInit(&sif); /* Try to read existing SIF */ ret=sifRead(siffile, &sif); if(ret==0) { // SIF could be read if(sif.frameNr==img->dimt) { /* If size matches, then update the contents, but keep counts, in case previous SIF comes with actual count info from scanner */ ret=img2sif(img, &sif, 1, 1, 0, IMG_TEST-2); } else { /* otherwise create SIF contents */ ret=img2sif(img, &sif, 1, 1, 2, IMG_TEST-2); } } else { /* otherwise create SIF contents */ ret=img2sif(img, &sif, 1, 1, 2, IMG_TEST-2); } if(ret!=0) { /* SIF data could not be made: do not give error, just do not write it */ if(IMG_TEST>0) printf("SIF contents could not be filled.\n"); return 0; } /* Write SIF */ ret=sifWrite(&sif, siffile); if(ret!=0) { /* SIF could not be written: do not give error, just do not write it */ if(IMG_TEST>0) fprintf(stderr, "Error: SIF could not be written (%d).\n", ret); } imgSetStatus(img, STATUS_OK); return 0; }
/*! * Read ECAT 6.3 image header * * @param fp file pointer * @param blk block number [2..number of blocks] * @param h Ecat 6.3 image header * @return 0 if ok, 1 invalid input, 2 failed to find block, * 3 failed to read block, 4 invalid data type, 5 invalid calibration factor, * 6 invalid frame duration */ int ecat63ReadImageheader(FILE *fp, int blk, ECAT63_imageheader *h) { unsigned char buf[MatBLKSIZE]; int i; int little; /* 1 if current platform is little endian (i386), else 0 */ int vaxdata=1; /* 1 if data is in VAX format, else 0 */ if(ECAT63_TEST) printf("ecat63ReadImageheader(fp, %d ih)\n", blk); if(fp==NULL || blk<2 || h==NULL) return(1); little=little_endian(); /* Seek the subheader block */ fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(2); /* Read the subheader block */ if(fread(buf, MatBLKSIZE, 1, fp)<1) return(3); /* Copy char data to header structure */ memcpy(h->fill1, buf+0, 126); memcpy(h->annotation, buf+420, 40); /* Copy short ints */ /* in big endian platform, change byte order temporarily */ if(!little) swabip(buf, MatBLKSIZE); memcpy(&h->data_type, buf+126, 2); if(h->data_type>4) vaxdata=0; /*printf("data_type=%d\n", h->data_type);*/ memcpy(&h->num_dimensions, buf+128, 2); memcpy(&h->dimension_1, buf+132, 2); memcpy(&h->dimension_2, buf+134, 2); memcpy(&h->image_min, buf+176, 2); memcpy(&h->image_max, buf+178, 2); memcpy(&h->slice_location, buf+200, 2); memcpy(&h->recon_start_hour, buf+202, 2); memcpy(&h->recon_start_min, buf+204, 2); memcpy(&h->recon_start_sec, buf+206, 2); memcpy(&h->filter_code, buf+236, 2); memcpy(&h->processing_code, buf+376, 2); memcpy(&h->quant_units, buf+380, 2); memcpy(&h->recon_start_day, buf+382, 2); memcpy(&h->recon_start_month, buf+384, 2); memcpy(&h->recon_start_year, buf+386, 2); memcpy(h->fill2, buf+460, 52); /* Change back the byte order */ if(!little) swabip(buf, MatBLKSIZE); /* Copy ints */ h->frame_duration=ecat63rInt(buf+192, vaxdata, little); h->frame_start_time=ecat63rInt(buf+196, vaxdata, little); h->recon_duration=ecat63rInt(buf+208, vaxdata, little); h->scan_matrix_num=ecat63rInt(buf+238, vaxdata, little); h->norm_matrix_num=ecat63rInt(buf+242, vaxdata, little); h->atten_cor_mat_num=ecat63rInt(buf+246, vaxdata, little); /* Copy floats */ h->x_origin=ecat63rFloat(buf+160, vaxdata, little); h->y_origin=ecat63rFloat(buf+164, vaxdata, little); h->recon_scale=ecat63rFloat(buf+168, vaxdata, little); h->quant_scale=ecat63rFloat(buf+172, vaxdata, little); h->pixel_size=ecat63rFloat(buf+184, vaxdata, little); h->slice_width=ecat63rFloat(buf+188, vaxdata, little); h->image_rotation=ecat63rFloat(buf+296, vaxdata, little); h->plane_eff_corr_fctr=ecat63rFloat(buf+300, vaxdata, little); h->decay_corr_fctr=ecat63rFloat(buf+304, vaxdata, little); h->loss_corr_fctr=ecat63rFloat(buf+308, vaxdata, little); h->intrinsic_tilt=ecat63rFloat(buf+312, vaxdata, little); h->ecat_calibration_fctr=ecat63rFloat(buf+388, vaxdata, little); h->well_counter_cal_fctr=ecat63rFloat(buf+392, vaxdata, little); for(i=0; i<6; i++) h->filter_params[i]=ecat63rFloat(buf+396+i*4, vaxdata, little); /* Check that most important contents are ok */ if(h->data_type<BYTE_TYPE || h->data_type>SUN_I4) { if(ECAT63_TEST) printf("Invalid data types; probable conversion error.\n"); return(4); } if(h->ecat_calibration_fctr<0.0 || h->ecat_calibration_fctr>1.0e10) { if(ECAT63_TEST) printf("Invalid calibration factor; probable conversion error.\n"); return(5); } if(h->frame_duration<0.0 || h->frame_duration>1.0e12) { if(ECAT63_TEST) printf("Invalid frame duration; probable conversion error.\n"); return(6); } return(0); }
/*! * Write one PET frame from IMG data struct into Analyze 7.5 database file. * This function can be called repeatedly to write all frames one at a time * to conserve memory. This function does not write SIF. * * @param dbname name of file where IMG contents will be written. * If file does not exist, it is created. * Make sure to delete existing file, unless you want to add data * @param frame_to_write PET frame number (1..frameNr) which will be written: * If set to 0, frame data will be written to an existing or new PET file as * a new frame, never overwriting existing data. * If >0, then frame data is written as specified frame number, overwriting * any data existing with the same frame number * @param img pointer to the IMG data struct * @param frame_index IMG frame index (0..dimt-1) which will be written * @param fmin minimum pixel value in all frames that will be written; * used only when writing the first frame * @param fmax maximum pixel value in all frames that will be written; * used only when writing the first frame * @return errstatus, which is STATUS_OK (0) when call was successful, * and >0 in case of an error. */ int imgWriteAnalyzeFrame( const char *dbname, int frame_to_write, IMG *img, int frame_index, float fmin, float fmax ) { IMG test_img; int ret=0, pxlNr, zi, xi, yi, little; FILE *fp; short int *sdata=NULL, *sptr; char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX]; ANALYZE_DSR dsr; float scale_factor=1.0; if(IMG_TEST) printf("\nimgWriteAnalyzeFrame(%s, %d, *img, %d, %g, %g)\n", dbname, frame_to_write, frame_index, fmin, fmax); /* * Check the input */ if(dbname==NULL) return STATUS_FAULT; if(img==NULL) return STATUS_FAULT; if(img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT; if(frame_to_write<0) return STATUS_FAULT; if(frame_index<0 || frame_index>=img->dimt) return STATUS_FAULT; if(img->_fileFormat!=IMG_ANA_L && img->_fileFormat!=IMG_ANA) return STATUS_FAULT; /* * If database does not exist, then create it with new header, * and if it does exist, then read and check header information. * Create or edit header to contain correct frame nr. * Determine the global scaling factor. */ imgInit(&test_img); if(anaDatabaseExists(dbname, hdrfile, datfile, siffile)==0) { // not existing /* Create database filenames */ sprintf(hdrfile, "%s.hdr", dbname); sprintf(datfile, "%s.img", dbname); sprintf(siffile, "%s.sif", dbname); /* Set main header */ imgSetAnalyzeHeader(img, dbname, &dsr, fmin, fmax); if(frame_to_write==0) frame_to_write=1; dsr.dime.dim[4]=frame_to_write; scale_factor=dsr.dime.funused1; if(fabs(scale_factor)>1.0E-20) scale_factor=1.0/scale_factor; /* Write Analyze header */ ret=anaWriteHeader(hdrfile, &dsr); if(ret && IMG_TEST) printf("anaWriteHeader() := %d\n", ret); if(ret) return STATUS_CANTWRITEHEADERFILE; /* Remove datafile if necessary */ if(access(datfile, 0) != -1) remove(datfile); } else { /* database does exist */ /* Read header information for checking */ ret=imgReadAnalyzeHeader(dbname, &test_img); if(ret!=0) {imgEmpty(&test_img); return ret;} /* Check that file format is the same */ if(img->_fileFormat!=test_img._fileFormat || img->type!=test_img.type) { imgEmpty(&test_img); return STATUS_WRONGFILETYPE;} /* Check that matrix sizes are the same */ if(img->dimz!=test_img.dimz || img->dimx!=test_img.dimx || img->dimy!=test_img.dimy) { imgEmpty(&test_img); return STATUS_VARMATSIZE;} imgEmpty(&test_img); /* Read the header, set new frame number, and write it back */ /* Get also the scale factor */ if((ret=anaReadHeader(hdrfile, &dsr))!=0) return STATUS_NOMAINHEADER; scale_factor=1.0/dsr.dime.funused1; if(frame_to_write==0) frame_to_write=dsr.dime.dim[4]+1; if(dsr.dime.dim[4]<frame_to_write) { if(dsr.dime.dim[4]+1<frame_to_write) return STATUS_MISSINGMATRIX; dsr.dime.dim[4]=frame_to_write; } if((ret=anaWriteHeader(hdrfile, &dsr))!=0) return STATUS_NOWRITEPERM; } if(IMG_TEST>2) { printf("frame_to_write := %d\n", frame_to_write); printf("hdrfile := %s\n", hdrfile); printf("datfile := %s\n", datfile); printf("siffile := %s\n", siffile); } /* Allocate memory for matrix short int data (one plane) */ pxlNr=img->dimx*img->dimy; sdata=(short int*)malloc(pxlNr*sizeof(short int)); if(sdata==NULL) return STATUS_NOMEMORY; /* Open datafile, not removing possible old contents */ if(frame_to_write==1) fp=fopen(datfile, "wb"); else fp=fopen(datfile, "r+b"); if(fp==NULL) {free(sdata); return STATUS_CANTWRITEIMGFILE;} /* Move file pointer to the place of current frame */ if(fseek(fp, (frame_to_write-1)*pxlNr*img->dimz*sizeof(short int), SEEK_SET)!=0) { free(sdata); fclose(fp); return STATUS_MISSINGMATRIX;} little=little_endian(); /* Copy, scale and write data plane-by-plane */ if(anaFlipping()==0) { for(zi=0; zi<img->dimz; zi++) { sptr=sdata; /*printf("plane := %d\n scale_factor := %g\n", zi+1, scale_factor);*/ for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) { *sptr=temp_roundf(scale_factor*img->m[zi][yi][xi][frame_index]); sptr++; } /* Change byte order if necessary */ sptr=sdata; if(little!=dsr.little) swabip(sptr, pxlNr*sizeof(short int)); /* Write image data */ sptr=sdata; if(fwrite(sptr, sizeof(short int), pxlNr, fp) != pxlNr) { free(sdata); fclose(fp); return STATUS_CANTWRITEIMGFILE; } } } else { for(zi=img->dimz-1; zi>=0; zi--) { sptr=sdata; for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) { *sptr=temp_roundf(scale_factor*img->m[zi][yi][xi][frame_index]); sptr++; } /* Change byte order if necessary */ sptr=sdata; if(little!=dsr.little) swabip(sptr, pxlNr*sizeof(short int)); /* Write image data */ sptr=sdata; if(fwrite(sptr, sizeof(short int), pxlNr, fp) != pxlNr) { free(sdata); fclose(fp); return STATUS_CANTWRITEIMGFILE; } } } free(sdata); fclose(fp); return STATUS_OK; }
/** Reads microPET image data, scaling values to floats if necessary. * Reads only one frame at a time! \returns 0 when successful, otherwise <>0. */ int upetReadImagedata( /** file opened previously in binary mode */ FILE *fp, /** microPET header in IFT struct */ IFT *ift, /** frame number to read [1..number of frames] */ int frame, /** pointer to image float data allocated previously */ float *data ) { int dimx, dimy, dimz=1, dimt=1, pxlNr=0; int i, fi, n, data_type, data_bytes, little, start_pos, rawSize; char *mdata, *mptr; float f, cf, bf, *fptr; short int *sptr; int *iptr; char key[MAX_MICROPET_LINE_LEN], value[MAX_MICROPET_LINE_LEN]; if(MICROPET_TEST) printf("upetReadImagedata(fp, ift, %d, data)\n", frame); /* Check the arguments */ if(frame<=0 || fp==NULL || ift==NULL || data==NULL) return(1); /* Get the image dimensions from header */ i=iftGetIntValue(ift, 0, "total_frames", &dimt); if(i<0 || dimt<1) return 4; i=iftGetIntValue(ift, 0, "x_dimension", &dimx); if(i<0 || dimx<1) return 4; i=iftGetIntValue(ift, 0, "y_dimension", &dimy); if(i<0 || dimy<1) return 4; i=iftGetIntValue(ift, 0, "z_dimension", &dimz); if(i<0 || dimz<1) return 4; pxlNr=dimx*dimy*dimz; if(pxlNr<1) return(4); if(frame>dimt) return(3); // do not change this return value /* Get the data type */ i=iftGetIntValue(ift, 0, "data_type", &data_type); if(i<0 || data_type<1) return 5; switch(data_type) { case 1: data_bytes=1; little=little_endian(); break; case 2: data_bytes=2; little=1; break; case 3: data_bytes=4; little=1; break; case 4: data_bytes=4; little=1; break; case 5: data_bytes=4; little=0; break; case 6: data_bytes=2; little=0; break; case 7: data_bytes=4; little=0; break; default: return 5; } rawSize=data_bytes*pxlNr; if(MICROPET_TEST>0) { printf(" data_type=%d\n data_bytes=%d\n", data_type, data_bytes); printf(" pxlNr=%d\n rawSize=%d\n", pxlNr, rawSize); } /* Allocate memory for the binary data */ mdata=(char*)malloc(rawSize); if(mdata==NULL) return(11); /* Seek the start of current frame data */ start_pos=(frame-1)*rawSize; if(MICROPET_TEST>2) printf(" start_pos=%d\n", start_pos); fseek(fp, start_pos, SEEK_SET); if(ftell(fp)!=start_pos) { if(MICROPET_TEST>5) printf("could not move to start_pos\n"); free(mdata); return(7); } /* Read the data */ mptr=mdata; if((n=fread(mptr, rawSize, 1, fp)) < 1) { if(MICROPET_TEST>5) printf("could read only %d bytes when request was %d\n", n, rawSize); free(mdata); return(8); } /* Convert byte order if necessary */ mptr=mdata; if(little!=little_endian()) { if(MICROPET_TEST>0) {printf("byte conversion\n"); fflush(stdout);} switch(data_bytes) { case 1: /* no conversion needed */ break; case 2: swabip(mptr, rawSize); break; case 4: swawbip(mptr, rawSize); break; default: if(MICROPET_TEST>5) printf("unsupported data_type := %d\n", data_type); free(mdata); return(5); } } /* Get scale factor for this frame */ strcpy(key, "frame"); sprintf(value, "%d", frame-1); fi=iftGetFullmatchFrom(ift, 0, key, value); if(fi<0) {free(mdata); return(6);} i=iftGetFloatValue(ift, fi+1, "scale_factor", &f); if(i<0 || f<=0.0) {free(mdata); return(6);} if(MICROPET_TEST>5) printf(" scale_factor := %g\n", f); /* calibration factor */ i=iftGetFloatValue(ift, 0, "calibration_factor", &cf); if(i<0 || cf<0.0) {free(mdata); return 7;} if(MICROPET_TEST>5) printf(" calibration_factor := %g\n", cf); /* branching_fraction */ i=iftGetFloatValue(ift, 0, "isotope_branching_fraction", &bf); if(i<0 || bf<0.0) {free(mdata); return 7;} if(MICROPET_TEST>5) printf(" branching_fraction := %g\n", bf); if(cf>0.0) {f=cf; if(bf>0.0) f/=bf;} if(MICROPET_TEST>5) printf(" f := %g\n", f); /* Copy data to float pixel values */ mptr=mdata; fptr=data; switch(data_type) { case 1: // unsigned char for(i=0; i<pxlNr; i++, mptr++, fptr++) *fptr=f*(float)(*mptr); break; case 2: // short int case 6: for(i=0; i<pxlNr; i++, mptr+=2, fptr++) { sptr=(short int*)mptr; *fptr=f*(float)(*sptr); } break; case 3: // int case 7: for(i=0; i<pxlNr; i++, mptr+=4, fptr++) { iptr=(int*)mptr; *fptr=f*(float)(*iptr); } break; case 4: // float case 5: memcpy(fptr, mptr, pxlNr*data_bytes); for(i=0; i<pxlNr; i++, fptr++) *fptr*=f; break; default: if(MICROPET_TEST>5) printf("unsupported data_type := %d\n", data_type); free(mdata); return(5); } free(mdata); if(MICROPET_TEST>1) printf("anaReadImagedata() succeeded\n"); return(0); }