TPCCLIB
Loading...
Searching...
No Matches
ecat63w.c File Reference

Procedures for writing ECAT 6.3 matrix data. More...

#include "libtpcimgio.h"

Go to the source code of this file.

Functions

int ecat63WriteMainheader (FILE *fp, ECAT63_mainheader *h)
int ecat63WriteImageheader (FILE *fp, int block, ECAT63_imageheader *h)
int ecat63WriteAttnheader (FILE *fp, int block, ECAT63_attnheader *h)
int ecat63WriteScanheader (FILE *fp, int block, ECAT63_scanheader *h)
int ecat63WriteNormheader (FILE *fp, int block, ECAT63_normheader *h)
FILE * ecat63Create (const char *fname, ECAT63_mainheader *h)
int ecat63WriteImage (FILE *fp, int matnum, ECAT63_imageheader *h, void *data)
int ecat63WriteScan (FILE *fp, int matnum, ECAT63_scanheader *h, void *data)
int ecat63WriteNorm (FILE *fp, int matnum, ECAT63_normheader *h, void *data)
int ecat63WriteAttn (FILE *fp, int matnum, ECAT63_attnheader *h, void *data)
int ecat63WriteMatdata (FILE *fp, int strtblk, char *data, long long pxlNr, int pxlSize)
int ecat63_is_scaling_needed (float amax, float *data, long long nr)
int ecat63WriteImageMatrix (FILE *fp, int matnum, ECAT63_imageheader *h, float *fdata)
int ecat63WriteScanMatrix (FILE *fp, int matnum, ECAT63_scanheader *h, float *fdata)
void ecat63wFloat (float *bufi, void *bufo, int tovax, int islittle)
void ecat63wInt (int *bufi, void *bufo, int tovax, int islittle)
struct tm * ecat63ScanstarttimeToTm (const ECAT63_mainheader *h, struct tm *tm)
 Convert scan_start_time in ECAT 6.3 main header into a struct tm.
time_t ecat63Scanstarttime (const ECAT63_mainheader *h)
 Get calendar time from ECAT 6.3 main header.

Detailed Description

Procedures for writing ECAT 6.3 matrix data.

Author
Vesa Oikonen

Assumptions:

  1. All data is always saved in little endian byte order (i386 and VAX).
  2. Data is automatically saved in one of the little endian formats as specified in header data_type.
  3. VAX data can be saved correctly only in 2-byte formats.

Definition in file ecat63w.c.

Function Documentation

◆ ecat63_is_scaling_needed()

int ecat63_is_scaling_needed ( float amax,
float * data,
long long nr )

Check if pixel float values need to be scaled to be saved as short ints, or if they are already all very close to integers.

Returns
1 if scaling is necessary, and 0 if not.
Parameters
amaxAbsolute maximum value.
dataFloat array.
nrNumber of float values in float array.

Definition at line 662 of file ecat63w.c.

669 {
670 double d;
671
672 if(nr<1 || data==NULL) return(0);
673 /* scaling is necessary if all values are between -1 - 1 */
674 if(amax<0.9999) return(1);
675 /* Lets check first if at least the max value is close to integers or not */
676 if(modf(amax, &d)>0.0001) return(1);
677 /* if it is, then check all pixels */
678 for(long long i=0; i<nr; i++) if(modf(*data++, &d)>0.0001) return(1);
679 return(0);
680}

Referenced by ecat63WriteImageMatrix(), and ecat63WriteScanMatrix().

◆ ecat63Create()

FILE * ecat63Create ( const char * fname,
ECAT63_mainheader * h )

Create a new ECAT 6.3 file and return file pointer or NULL in case of an error. If file exists, it is renamed as fname% if possible. Directory list is written in big endian byte order.

Parameters
fnamefile name
hEcat 6.3 main header
Returns
opened file pointer, or NULL in case of failure

Definition at line 365 of file ecat63w.c.

367 {
368 FILE *fp;
369 char tmp[FILENAME_MAX];
370 int buf[MatBLKSIZE/4];
371
372 if(ECAT63_TEST) printf("ecat63Create()\n");
373 /* Check the arguments */
374 if(fname==NULL || h==NULL) return(NULL);
375 /* Check if file exists; backup, if necessary */
376 if(access(fname, 0) != -1) {
377 strcpy(tmp, fname); strcat(tmp, BACKUP_EXTENSION);
378 if(access(tmp, 0) != -1) remove(tmp);
379 if(ECAT63_TEST) printf("Renaming %s -> %s\n", fname, tmp);
380 rename(fname, tmp);
381 }
382 /* Open file */
383 fp=fopen(fname, "wb+"); if(fp==NULL) return(fp);
384 /* Write main header */
385 if(ecat63WriteMainheader(fp, h)) return(NULL);
386 /* Construct an empty matrix list ; convert to little endian if necessary */
387 memset(buf, 0, MatBLKSIZE);
388 buf[0]=31; buf[1]=2; if(!little_endian()) swawbip(buf, MatBLKSIZE);
389 /* Write data buffer */
390 fseek(fp, (MatFirstDirBlk-1)*MatBLKSIZE, SEEK_SET);
391 if(ftell(fp)!=(MatFirstDirBlk-1)*MatBLKSIZE) return(NULL);
392 if(fwrite(buf, 4, MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(NULL);
393 /* OK, then return file pointer */
394 return(fp);
395}
int ECAT63_TEST
Definition ecat63h.c:6
int ecat63WriteMainheader(FILE *fp, ECAT63_mainheader *h)
Definition ecat63w.c:24
#define BACKUP_EXTENSION
#define MatFirstDirBlk
#define MatBLKSIZE
void swawbip(void *buf, long long int size)
Definition swap.c:93
int little_endian()
Definition swap.c:14

Referenced by atnMake(), ecat63AddImg(), ecat63CopyFile(), ecat63WriteAllImg(), and imgWriteEcat63Frame().

◆ ecat63Scanstarttime()

time_t ecat63Scanstarttime ( const ECAT63_mainheader * h)

Get calendar time from ECAT 6.3 main header.

Author
Vesa Oikonen
Returns
Returns time_t, or -1 in case of an error.
Parameters
hPointer to ECAT 6.3 main header

Definition at line 925 of file ecat63w.c.

928 {
929 if(h==NULL) return((time_t)-1);
930 struct tm tm;
931 tm.tm_mday=h->scan_start_day;
932 tm.tm_mon=h->scan_start_month-1;
933 tm.tm_year=h->scan_start_year-1900;
934 tm.tm_hour=h->scan_start_hour;
935 tm.tm_min=h->scan_start_minute;
936 tm.tm_sec=h->scan_start_second;
937 tm.tm_isdst=-1;
938 return(timegm(&tm));
939}
time_t timegm(struct tm *tm)
Inverse of gmtime, converting struct tm to time_t.
Definition datetime.c:69
short int scan_start_month
short int scan_start_second
short int scan_start_year
short int scan_start_day
short int scan_start_minute
short int scan_start_hour

Referenced by atnMake(), ecat63ReadAllToImg(), ecat63ReadPlaneToImg(), ecatCopy63to7mainheader(), and imgGetEcat63MHeader().

◆ ecat63ScanstarttimeToTm()

struct tm * ecat63ScanstarttimeToTm ( const ECAT63_mainheader * h,
struct tm * tm )

Convert scan_start_time in ECAT 6.3 main header into a struct tm.

Author
Vesa Oikonen
Returns
Returns pointer to the struct_tm, or null in case of an error.
Parameters
hPointer to ECAT 6.3 main header
tmPointer to pre-allocated struct tm.

Definition at line 900 of file ecat63w.c.

905 {
906 if(tm==NULL || h==NULL) return(NULL);
907 memset(tm, 0, sizeof(struct tm));
908 tm->tm_mday=h->scan_start_day;
909 tm->tm_mon=h->scan_start_month-1;
910 tm->tm_year=h->scan_start_year-1900;
911 tm->tm_hour=h->scan_start_hour;
912 tm->tm_min=h->scan_start_minute;
913 tm->tm_sec=h->scan_start_second;
914 tm->tm_isdst=-1;
915 if(timegm(tm)==-1) return(NULL);
916 return(tm);
917}

◆ ecat63wFloat()

void ecat63wFloat ( float * bufi,
void * bufo,
int tovax,
int islittle )

Writing ECAT 6.3 floats

Parameters
bufipointer to 4-byte long input (float data)
bufopointer to 4-byte long output
tovax1 for VAX format
islittle1 for little endian

Definition at line 860 of file ecat63w.c.

862 {
863 unsigned int ul;
864
865 memcpy(&ul, bufi, 4); if(ul==0) {memcpy(bufo, bufi, 4); return;}
866 if(tovax) { /* If VAX format is needed */
867 ul+=(2L<<23); /* increase exp by 2 */
868 /* Swap words on i386 and bytes on SUN */
869 if(islittle) swawip(&ul, 4); else swabip(&ul, 4);
870 } else {
871 if(!islittle) swawbip(&ul, 4); /* Switch words and bytes on SUN */
872 }
873 memcpy(bufo, &ul, 4);
874}
void swawip(void *buf, long long int size)
Definition swap.c:114
void swabip(void *buf, long long int size)
Definition swap.c:72

Referenced by ecat63WriteAttnheader(), ecat63WriteImageheader(), ecat63WriteMainheader(), ecat63WriteNormheader(), and ecat63WriteScanheader().

◆ ecat63wInt()

void ecat63wInt ( int * bufi,
void * bufo,
int tovax,
int islittle )

Writing ECAT 6.3 32-bit ints. 32-bit int format is same in VAX and i386

Parameters
bufipointer to 4-byte long input (integer data)
bufopointer to 4-byte long output
tovax1 for VAX format
islittle1 for little endian

Definition at line 884 of file ecat63w.c.

884 {
885 int i;
886
887 if(tovax==0) {} // to prevent compiler warning
888 /* Swap both words and bytes on SUN */
889 memcpy(&i, bufi, 4); if(!islittle) swawbip(&i, 4);
890 memcpy(bufo, &i, 4);
891}

Referenced by ecat63WriteImageheader(), and ecat63WriteScanheader().

◆ ecat63WriteAttn()

int ecat63WriteAttn ( FILE * fp,
int matnum,
ECAT63_attnheader * h,
void * data )

Write ECAT 6.3 attenuation matrix header and data

Parameters
fptarget file pointer
matnummatrix number [1..number of matrixes]
hEcat 6.3 attenuation header
datapointer to data that is written
Returns
0 if ok, 1 invalid input or invalid image dimensions, 2 failed to resolve data type 3 too little data size, 4 failed to resolve next block size in file

Definition at line 563 of file ecat63w.c.

565 {
566 int nxtblk, blkNr, pxlSize, ret;
567
568 if(ECAT63_TEST) printf("ecat63WriteAttn(fp, %d, ah, data)\n", matnum);
569 if(fp==NULL || matnum<1 || h==NULL || data==NULL) return(1);
570 /* nr of pixels */
571 long long pxlNr=h->dimension_1*h->dimension_2; if(pxlNr<1) return(1);
572 /* mem taken by one pixel */
573 switch(h->data_type) {
574 case BYTE_TYPE: pxlSize=1;
575 break;
576 case VAX_I2:
577 case SUN_I2: pxlSize=2;
578 break;
579 case VAX_I4: return(3);
580 case VAX_R4: return(3);
581 case IEEE_R4:
582 case SUN_I4: pxlSize=4;
583 break;
584 default: return(2);
585 }
586 /* mem taken by all pixels */
587 long long data_size=pxlNr*pxlSize;
588 /* block nr taken by all pixels */
589 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) return(3);
590 /* Get block number for matrix header and data */
591 nxtblk=ecat63Matenter(fp, matnum, blkNr); if(nxtblk<1) return(4);
592 if(ECAT63_TEST) printf(" block=%d\n", nxtblk);
593 /* Write header */
594 ret=ecat63WriteAttnheader(fp, nxtblk, h); if(ret) return(40+ret);
595 /* Write matrix data */
596 ret=ecat63WriteMatdata(fp, nxtblk+1, data, pxlNr, pxlSize);
597 if(ret) return(50+ret);
598 return 0;
599}
int ecat63Matenter(FILE *fp, int matnum, int blkNr)
Definition ecat63ml.c:159
int ecat63WriteMatdata(FILE *fp, int strtblk, char *data, long long pxlNr, int pxlSize)
Definition ecat63w.c:618
int ecat63WriteAttnheader(FILE *fp, int block, ECAT63_attnheader *h)
Definition ecat63w.c:190
#define SUN_I4
#define VAX_R4
#define IEEE_R4
#define BYTE_TYPE
#define VAX_I4
#define VAX_I2
#define SUN_I2
short int dimension_1
short int dimension_2

Referenced by atnMake().

◆ ecat63WriteAttnheader()

int ecat63WriteAttnheader ( FILE * fp,
int block,
ECAT63_attnheader * h )

Write ECAT 6.3 attenuation header

Parameters
fptarget file pointer
blockblock number [>=3]
hEcat 6.3 attenuation header
Returns
0 if ok, 1 invalid input, 2 failed to find block, 3 failed to write block

Definition at line 190 of file ecat63w.c.

192 {
193 unsigned char buf[MatBLKSIZE];
194 int little, tovax;
195
196 if(ECAT63_TEST) printf("ecat63WriteAttnheader(fp, %d, ah)\n", block);
197 little=little_endian();
198 /* Clear buf */
199 memset(buf, 0, MatBLKSIZE);
200 /* Check arguments */
201 if(fp==NULL || block<3 || h->data_type<1 || h->data_type>7) return(1);
202 if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4)
203 tovax=1; else tovax=0;
204
205 /* Copy short ints to buf */
206 memcpy(buf+126, &h->data_type, 2);
207 memcpy(buf+128, &h->attenuation_type, 2);
208 memcpy(buf+132, &h->dimension_1, 2);
209 memcpy(buf+134, &h->dimension_2, 2);
210 /* big to little endian if necessary */
211 if(!little) swabip(buf, MatBLKSIZE);
212
213 /* Copy floats to buf */
214 ecat63wFloat(&h->scale_factor, buf+182, tovax, little);
215 ecat63wFloat(&h->x_origin, buf+186, tovax, little);
216 ecat63wFloat(&h->y_origin, buf+190, tovax, little);
217 ecat63wFloat(&h->x_radius, buf+194, tovax, little);
218 ecat63wFloat(&h->y_radius, buf+198, tovax, little);
219 ecat63wFloat(&h->tilt_angle, buf+202, tovax, little);
220 ecat63wFloat(&h->attenuation_coeff, buf+206, tovax, little);
221 ecat63wFloat(&h->sample_distance, buf+210, tovax, little);
222
223 /* Write subheader */
224 fseeko(fp, (block-1)*MatBLKSIZE, SEEK_SET);
225 if(ftello(fp)!=(block-1)*MatBLKSIZE) return(2);
226 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3);
227
228 return(0);
229}
void ecat63wFloat(float *bufi, void *bufo, int tovax, int islittle)
Definition ecat63w.c:860
short int attenuation_type

Referenced by ecat63WriteAttn().

◆ ecat63WriteImage()

int ecat63WriteImage ( FILE * fp,
int matnum,
ECAT63_imageheader * h,
void * data )

Write ECAT 6.3 image matrix header and data

Parameters
fptarget file pointer
matnummatrix number [1..number of matrixes]
hEcat 6.3 image header
datapointer to data that is written
Returns
0 if ok, 1 invalid input or invalid image dimensions, 2 failed to resolve data type 3 too little data size, 4 failed to resolve next block size in file

Definition at line 410 of file ecat63w.c.

412 {
413 int nxtblk, blkNr, pxlSize, ret;
414
415 if(ECAT63_TEST) printf("ecat63WriteImage(fp, %d, ih, data)\n", matnum);
416 if(fp==NULL || matnum<1 || h==NULL || data==NULL) return(1);
417 /* nr of pixels */
418 long long pxlNr=h->dimension_1*h->dimension_2; if(pxlNr<1) return(2);
419 /* mem taken by one pixel */
420 switch(h->data_type) {
421 case BYTE_TYPE: pxlSize=1;
422 break;
423 case VAX_I2:
424 case SUN_I2: pxlSize=2;
425 break;
426 case VAX_I4: return(3);
427 case VAX_R4: return(3);
428 case IEEE_R4:
429 case SUN_I4: pxlSize=4;
430 break;
431 default: return(2);
432 }
433 /* mem taken by all pixels */
434 long long data_size=pxlNr*pxlSize;
435 /* block nr taken by all pixels */
436 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) return(3);
437 /* Get block number for matrix header and data */
438 nxtblk=ecat63Matenter(fp, matnum, blkNr); if(nxtblk<1) return(4);
439 if(ECAT63_TEST) printf(" block=%d\n", nxtblk);
440 /* Write header */
441 ret=ecat63WriteImageheader(fp, nxtblk, h); if(ret) return(40+ret);
442 /* Write matrix data */
443 ret=ecat63WriteMatdata(fp, nxtblk+1, data, pxlNr, pxlSize);
444 if(ret) return(50+ret);
445 return 0;
446}
int ecat63WriteImageheader(FILE *fp, int block, ECAT63_imageheader *h)
Definition ecat63w.c:106

Referenced by ecat63AddImg(), and ecat63WriteAllImg().

◆ ecat63WriteImageheader()

int ecat63WriteImageheader ( FILE * fp,
int block,
ECAT63_imageheader * h )

Write ECAT 6.3 image header

Parameters
fptarget file pointer
blockblock number [>= 3]
hEcat 6.3 image header
Returns
0, if ok, 1 invalid input, 2 failed to find block, 3 failed to write block

Definition at line 106 of file ecat63w.c.

108 {
109 char buf[MatBLKSIZE];
110 int little, tovax;
111
112
113 if(ECAT63_TEST) printf("ecat63WriteImageheader(fp, %d, ih)\n", block);
114 little=little_endian();
115 /* Clear buf */
116 memset(buf, 0, MatBLKSIZE);
117 /* Check arguments */
118 if(fp==NULL || block<3 || h->data_type<1 || h->data_type>7) return(1);
119 if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4)
120 tovax=1; else tovax=0;
121
122 /* Copy short ints to buf */
123 memcpy(buf+126, &h->data_type, 2);
124 memcpy(buf+128, &h->num_dimensions, 2);
125 memcpy(buf+132, &h->dimension_1, 2);
126 memcpy(buf+134, &h->dimension_2, 2);
127 memcpy(buf+176, &h->image_min, 2);
128 memcpy(buf+178, &h->image_max, 2);
129 memcpy(buf+200, &h->slice_location, 2);
130 memcpy(buf+202, &h->recon_start_hour, 2);
131 memcpy(buf+204, &h->recon_start_min, 2);
132 memcpy(buf+206, &h->recon_start_sec, 2);
133 memcpy(buf+236, &h->filter_code, 2);
134 memcpy(buf+376, &h->processing_code, 2);
135 memcpy(buf+380, &h->quant_units, 2);
136 memcpy(buf+382, &h->recon_start_day, 2);
137 memcpy(buf+384, &h->recon_start_month, 2);
138 memcpy(buf+386, &h->recon_start_year, 2);
139 memcpy(buf+460, h->fill2, 52);
140 /* big to little endian if necessary */
141 if(!little) swabip(buf, MatBLKSIZE);
142
143 /* Copy floats to buf */
144 ecat63wFloat(&h->x_origin, buf+160, tovax, little);
145 ecat63wFloat(&h->y_origin, buf+164, tovax, little);
146 ecat63wFloat(&h->recon_scale, buf+168, tovax, little);
147 ecat63wFloat(&h->quant_scale, buf+172, tovax, little);
148 ecat63wFloat(&h->pixel_size, buf+184, tovax, little);
149 ecat63wFloat(&h->slice_width, buf+188, tovax, little);
150 ecat63wFloat(&h->image_rotation, buf+296, tovax, little);
151 ecat63wFloat(&h->plane_eff_corr_fctr, buf+300, tovax, little);
152 ecat63wFloat(&h->decay_corr_fctr, buf+304, tovax, little);
153 ecat63wFloat(&h->loss_corr_fctr, buf+308, tovax, little);
154 ecat63wFloat(&h->intrinsic_tilt, buf+312, tovax, little);
155 ecat63wFloat(&h->ecat_calibration_fctr, buf+388, tovax, little);
156 ecat63wFloat(&h->well_counter_cal_fctr, buf+392, tovax, little);
157 for(int i=0; i<6; i++)
158 ecat63wFloat(&h->filter_params[i], buf+396+4*i, tovax, little);
159
160 /* Copy ints to buf */
161 ecat63wInt(&h->frame_duration, buf+192, tovax, little);
162 ecat63wInt(&h->frame_start_time, buf+196, tovax, little);
163 ecat63wInt(&h->scan_matrix_num, buf+238, tovax, little);
164 ecat63wInt(&h->norm_matrix_num, buf+242, tovax, little);
165 ecat63wInt(&h->atten_cor_mat_num, buf+246, tovax, little);
166
167 /* Copy chars */
168 memcpy(buf+0, h->fill1, 126);
169 memcpy(buf+420, h->annotation, 40);
170
171 /* Write subheader */
172 fseeko(fp, (block-1)*MatBLKSIZE, SEEK_SET);
173 if(ftello(fp)!=(block-1)*MatBLKSIZE) return(2);
174 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3);
175
176 return(0);
177}
void ecat63wInt(int *bufi, void *bufo, int tovax, int islittle)
Definition ecat63w.c:884
short int recon_start_month
short int fill2[26]
short int recon_start_day
short int slice_location
short int processing_code
short int recon_start_min
short int recon_start_year
short int num_dimensions
short int recon_start_hour
short int recon_start_sec

Referenced by ecat63WriteImage(), and ecat63WriteImageMatrix().

◆ ecat63WriteImageMatrix()

int ecat63WriteImageMatrix ( FILE * fp,
int matnum,
ECAT63_imageheader * h,
float * fdata )

Write ECAT 6.3 image matrix header and data

Parameters
fptarget file pointer
matnum
hEcat 6.3 image header
fdata
Returns
0 if ok, 1 invalid input, 3 invalid matrix dimensions, 4 invalid block number, 5 failed to allocate memory, 8 failed to resolve new matrix block number, 10 failed to write image sub header, 13 failed to write matrix data

Definition at line 697 of file ecat63w.c.

699 {
700 int nxtblk, blkNr, ret;
701 float *fptr, fmin, fmax, g, f;
702 char *mdata, *mptr;
703 short int *sptr;
704
705
706
707 if(ECAT63_TEST) printf("ecat63WriteImageMatrix(fp, %d, h, data)\n", matnum);
708 if(fp==NULL || matnum<1 || h==NULL || fdata==NULL) {
709 sprintf(ecat63errmsg, "invalid function parameter.\n");
710 return(1);
711 }
712 /* nr of pixels */
713 long long pxlNr=h->dimension_1*h->dimension_2;
714 if(pxlNr<1) {
715 sprintf(ecat63errmsg, "invalid matrix dimension.\n");
716 return(3);
717 }
718 /* How much memory is needed for ALL pixels */
719 long long data_size=pxlNr*ecat63pxlbytes(h->data_type);
720 /* block nr taken by all pixels */
721 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) {
722 sprintf(ecat63errmsg, "invalid block number.\n");
723 return(4);
724 }
725 /* Allocate memory for matrix data */
726 mdata=(char*)calloc(blkNr, MatBLKSIZE); if(mdata==NULL) {
727 sprintf(ecat63errmsg, "out of memory.\n");
728 return(5);
729 }
730 /* Search for min and max for calculation of scale factor */
731 fMinMaxFin(fdata, pxlNr, &fmin, &fmax);
732 if(fabs(fmin)>fabs(fmax)) g=fabs(fmin); else g=fabs(fmax);
733 if(g>0) f=32766./g; else f=1.0;
734 /* Check if pixels values can be left as such with scale_factor = 1 */
735 fptr=fdata;
736 if(f>=1.0 && ecat63_is_scaling_needed(g, fptr, pxlNr)==0) f=1.0;
737 /* Scale matrix data to shorts */
738 h->quant_scale=1.0/f;
739 sptr=(short int*)mdata; fptr=fdata;
740 for(long long i=0; i<pxlNr; i++, sptr++, fptr++)
741 *sptr=(short int)temp_roundf(f*(*fptr));
742 /* Set header short min & max */
743 h->image_min=(short int)temp_roundf(f*fmin);
744 h->image_max=(short int)temp_roundf(f*fmax);
745 /* Get block number for matrix header and data */
746 nxtblk=ecat63Matenter(fp, matnum, blkNr); if(nxtblk<1) {
747 sprintf(ecat63errmsg, "cannot determine matrix block (%d).\n", -nxtblk);
748 free(mdata); return(8);
749 }
750 if(ECAT63_TEST>2) printf(" block=%d fmin=%g fmax=%g\n", nxtblk, fmin, fmax);
751 /* Write header */
752 ret=ecat63WriteImageheader(fp, nxtblk, h); if(ret) {
753 sprintf(ecat63errmsg, "cannot write subheader (%d).\n", ret);
754 free(mdata); return(10);
755 }
756 /* Write matrix data */
757 mptr=mdata;
758 ret=ecat63WriteMatdata(fp, nxtblk+1, mptr, pxlNr, ecat63pxlbytes(h->data_type));
759 free(mdata);
760 if(ret) {
761 sprintf(ecat63errmsg, "cannot write matrix data (%d).\n", ret);
762 return(13);
763 }
764 return(0);
765}
char ecat63errmsg[128]
Definition ecat63h.c:7
int ecat63pxlbytes(short int data_type)
Definition ecat63r.c:973
int ecat63_is_scaling_needed(float amax, float *data, long long nr)
Definition ecat63w.c:662
void fMinMaxFin(float *data, long long int n, float *fmin, float *fmax)
Definition imgminmax.c:649
int temp_roundf(float e)
Definition petc99.c:20

Referenced by atnMake(), and imgWriteEcat63Frame().

◆ ecat63WriteMainheader()

int ecat63WriteMainheader ( FILE * fp,
ECAT63_mainheader * h )

Write ECAT 6.3 main header.

Parameters
fptarget file pointer
hEcat 6.3 main header
Returns
0, if ok, 1 invalid input, 2 failed to find block, 3 failed to write block

Definition at line 24 of file ecat63w.c.

26 {
27 char buf[MatBLKSIZE];
28 int little, tovax;
29
30
31 if(ECAT63_TEST) printf("ecat63WriteMainheader()\n");
32 little=little_endian();
33 /* Clear buf */
34 memset(buf, 0, MatBLKSIZE);
35 /* Check arguments */
36 if(fp==NULL || h->data_type<1 || h->data_type>7) return(1);
37 if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4)
38 tovax=1; else tovax=0;
39
40 /* Copy short ints to buf */
41 memcpy(buf+50, &h->data_type, 2); memcpy(buf+48, &h->sw_version, 2);
42 memcpy(buf+52, &h->system_type, 2); memcpy(buf+54, &h->file_type, 2);
43 memcpy(buf+66, &h->scan_start_day, 2); memcpy(buf+68, &h->scan_start_month, 2);
44 memcpy(buf+70, &h->scan_start_year, 2); memcpy(buf+72, &h->scan_start_hour, 2);
45 memcpy(buf+74, &h->scan_start_minute, 2);
46 memcpy(buf+76, &h->scan_start_second, 2);
47 memcpy(buf+134, &h->rot_source_speed, 2); memcpy(buf+136, &h->wobble_speed, 2);
48 memcpy(buf+138, &h->transm_source_type, 2);
49 memcpy(buf+148, &h->transaxial_samp_mode, 2);
50 memcpy(buf+150, &h->coin_samp_mode, 2); memcpy(buf+152, &h->axial_samp_mode, 2);
51 memcpy(buf+158, &h->calibration_units, 2);
52 memcpy(buf+160, &h->compression_code, 2);
53 memcpy(buf+350, &h->acquisition_type, 2); memcpy(buf+352, &h->bed_type, 2);
54 memcpy(buf+354, &h->septa_type, 2); memcpy(buf+376, &h->num_planes, 2);
55 memcpy(buf+378, &h->num_frames, 2); memcpy(buf+380, &h->num_gates, 2);
56 memcpy(buf+382, &h->num_bed_pos, 2); memcpy(buf+452, &h->lwr_sctr_thres, 2);
57 memcpy(buf+454, &h->lwr_true_thres, 2); memcpy(buf+456, &h->upr_true_thres, 2);
58 memcpy(buf+472, h->fill2, 40);
59 /* big to little endian if necessary */
60 if(!little) swabip(buf, MatBLKSIZE);
61
62 /* Copy floats to buf */
63 ecat63wFloat(&h->isotope_halflife, buf+86, tovax, little);
64 ecat63wFloat(&h->gantry_tilt, buf+122, tovax, little);
65 ecat63wFloat(&h->gantry_rotation, buf+126, tovax, little);
66 ecat63wFloat(&h->bed_elevation, buf+130, tovax, little);
67 ecat63wFloat(&h->axial_fov, buf+140, tovax, little);
68 ecat63wFloat(&h->transaxial_fov, buf+144, tovax, little);
69 ecat63wFloat(&h->calibration_factor, buf+154, tovax, little);
70 ecat63wFloat(&h->init_bed_position, buf+384, tovax, little);
71 for(int i=0; i<15; i++) ecat63wFloat(&h->bed_offset[i], buf+388+4*i, tovax, little);
72 ecat63wFloat(&h->plane_separation, buf+448, tovax, little);
73 ecat63wFloat(&h->init_bed_position, buf+458, tovax, little);
74
75 /* Copy chars */
76 /*memcpy(buf+0, h->ecat_format, 14);*/
77 memcpy(buf+14, h->fill1, 14);
78 memcpy(buf+28, h->original_file_name, 20); memcpy(buf+56, h->node_id, 10);
79 memcpy(buf+78, h->isotope_code, 8); memcpy(buf+90, h->radiopharmaceutical, 32);
80 memcpy(buf+162, h->study_name, 12); memcpy(buf+174, h->patient_id, 16);
81 memcpy(buf+190, h->patient_name, 32); buf[222]=h->patient_sex;
82 memcpy(buf+223, h->patient_age, 10); memcpy(buf+233, h->patient_height, 10);
83 memcpy(buf+243, h->patient_weight, 10); buf[253]=h->patient_dexterity;
84 memcpy(buf+254, h->physician_name, 32); memcpy(buf+286, h->operator_name, 32);
85 memcpy(buf+318, h->study_description, 32); memcpy(buf+356, h->facility_name, 20);
86 memcpy(buf+462, h->user_process_code, 10);
87
88 /* Write main header */
89 fseek(fp, 0*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=0*MatBLKSIZE) return(2);
90 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3);
91
92 return(0);
93}
char radiopharmaceutical[32]
short int coin_samp_mode
short int lwr_true_thres
short int compression_code
char patient_height[10]
short int fill2[20]
short int wobble_speed
short int num_bed_pos
short int transaxial_samp_mode
short int rot_source_speed
short int acquisition_type
short int calibration_units
char original_file_name[20]
char study_description[32]
short int transm_source_type
char user_process_code[10]
char patient_weight[10]
short int lwr_sctr_thres
short int axial_samp_mode
short int upr_true_thres
char physician_name[32]
short int system_type

Referenced by ecat63AddImg(), ecat63Create(), and imgWriteEcat63Frame().

◆ ecat63WriteMatdata()

int ecat63WriteMatdata ( FILE * fp,
int strtblk,
char * data,
long long pxlNr,
int pxlSize )

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.

Parameters
fptarget file pointer
strtblkstarting image block [>=1]
datapointer to data that is written
pxlNrnumber of items to be written [>=1]
pxlSizesize of one data item in bytes [>=1]
Returns
0 if ok, 1 invalid input, 2 failed to find starting block, 3 failed to write data

Definition at line 618 of file ecat63w.c.

620 {
621 unsigned char buf[MatBLKSIZE];
622 char *dptr;
623 int blkNr, byteNr;
624
625 if(ECAT63_TEST)
626 printf("ecat63WriteMatdata(fp, %d, data, %lld, %d)\n", strtblk, pxlNr, pxlSize);
627 if(fp==NULL || strtblk<1 || data==NULL || pxlNr<1 || pxlSize<1) return(1);
628 memset(buf, 0, MatBLKSIZE);
629 long long dataSize=pxlNr*pxlSize; if(dataSize<1) return(1);
630 /* block nr taken by all pixels */
631 blkNr=(dataSize+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) return(1);
632 if(ECAT63_TEST>1) printf(" blkNr=%d\n", blkNr);
633 /* Search the place for writing */
634 fseeko(fp, (strtblk-1)*MatBLKSIZE, SEEK_SET);
635 if(ftello(fp)!=(strtblk-1)*MatBLKSIZE) return(2);
636 /* Save blocks one at a time */
637 dptr=data;
638 for(int i=0; i<blkNr && dataSize>0; i++) {
639 byteNr=(dataSize<MatBLKSIZE)?dataSize:MatBLKSIZE;
640 memcpy(buf, dptr, byteNr);
641 /* Change matrix byte order in big endian platforms */
642 if(!little_endian()) {
643 if(pxlSize==2) swabip(buf, byteNr);
644 else if(pxlSize==4) swawbip(buf, byteNr);
645 }
646 /* Write block */
647 if(fwrite(buf, 1, MatBLKSIZE, fp)!=MatBLKSIZE) return(3);
648 /* Prepare for the next block */
649 dptr+=byteNr;
650 dataSize-=byteNr;
651 } /* next block */
652 return(0);
653}

Referenced by ecat63WriteAttn(), ecat63WriteImage(), ecat63WriteImageMatrix(), ecat63WriteNorm(), ecat63WriteScan(), and ecat63WriteScanMatrix().

◆ ecat63WriteNorm()

int ecat63WriteNorm ( FILE * fp,
int matnum,
ECAT63_normheader * h,
void * data )

Write ECAT 6.3 normalization matrix header and data

Parameters
fptarget file pointer
matnummatrix number [1..number of matrixes]
hEcat 6.3 normalization header
datapointer to data that is written
Returns
0 if ok, 1 invalid input or invalid image dimensions, 2 failed to resolve data type 3 too little data size, 4 failed to resolve next block size in file

Definition at line 512 of file ecat63w.c.

514 {
515 int nxtblk, blkNr, pxlSize, ret;
516
517 if(ECAT63_TEST) printf("ecat63WriteNorm(fp, %d, nh, data)\n", matnum);
518 if(fp==NULL || matnum<1 || h==NULL || data==NULL) return(1);
519 /* nr of pixels */
520 long long pxlNr=h->dimension_1*h->dimension_2; if(pxlNr<1) return(1);
521 /* mem taken by one pixel */
522 switch(h->data_type) {
523 case BYTE_TYPE: pxlSize=1;
524 break;
525 case VAX_I2:
526 case SUN_I2: pxlSize=2;
527 break;
528 case VAX_I4: return(3);
529 case VAX_R4: return(3);
530 case IEEE_R4:
531 case SUN_I4: pxlSize=4;
532 break;
533 default: return(2);
534 }
535 /* mem taken by all pixels */
536 long long data_size=pxlNr*pxlSize;
537 /* block nr taken by all pixels */
538 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) return(3);
539 /* Get block number for matrix header and data */
540 nxtblk=ecat63Matenter(fp, matnum, blkNr); if(nxtblk<1) return(4);
541 if(ECAT63_TEST) printf(" block=%d\n", nxtblk);
542 /* Write header */
543 ret=ecat63WriteNormheader(fp, nxtblk, h); if(ret) return(40+ret);
544 /* Write matrix data */
545 ret=ecat63WriteMatdata(fp, nxtblk+1, data, pxlNr, pxlSize);
546 if(ret) return(50+ret);
547 return 0;
548}
int ecat63WriteNormheader(FILE *fp, int block, ECAT63_normheader *h)
Definition ecat63w.c:313
short int dimension_1
short int dimension_2

◆ ecat63WriteNormheader()

int ecat63WriteNormheader ( FILE * fp,
int block,
ECAT63_normheader * h )

Write ECAT 6.3 normalization header

Parameters
fptarget file pointer
blockblock number [>=3]
hEcat 6.3 normalization header
Returns
0 if ok, 1 invalid input, 2 failed to find block, 3 failed to write block

Definition at line 313 of file ecat63w.c.

315 {
316 unsigned char buf[MatBLKSIZE];
317 int little, tovax;
318
319 if(ECAT63_TEST) printf("ecat63WriteNormheader(fp, %d, nh)\n", block);
320 little=little_endian();
321 /* Clear buf */
322 memset(buf, 0, MatBLKSIZE);
323 /* Check arguments */
324 if(fp==NULL || block<3 || h->data_type<1 || h->data_type>7) return(1);
325 if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4)
326 tovax=1; else tovax=0;
327
328 /* Copy short ints to buf */
329 memcpy(buf+126, &h->data_type, 2);
330 memcpy(buf+132, &h->dimension_1, 2);
331 memcpy(buf+134, &h->dimension_2, 2);
332 memcpy(buf+372, &h->norm_hour, 2);
333 memcpy(buf+376, &h->norm_minute, 2);
334 memcpy(buf+380, &h->norm_second, 2);
335 memcpy(buf+384, &h->norm_day, 2);
336 memcpy(buf+388, &h->norm_month, 2);
337 memcpy(buf+392, &h->norm_year, 2);
338 /* big to little endian if necessary */
339 if(!little) swabip(buf, MatBLKSIZE);
340
341 /* Copy floats to buf */
342 ecat63wFloat(&h->scale_factor, buf+182, tovax, little);
343 ecat63wFloat(&h->fov_source_width, buf+198, tovax, little);
344
345 /* Write subheader */
346 fseeko(fp, (block-1)*MatBLKSIZE, SEEK_SET);
347 if(ftello(fp)!=(block-1)*MatBLKSIZE) return(2);
348 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3);
349
350 return(0);
351}
short int norm_second
short int norm_minute

Referenced by ecat63WriteNorm().

◆ ecat63WriteScan()

int ecat63WriteScan ( FILE * fp,
int matnum,
ECAT63_scanheader * h,
void * data )

Write ECAT 6.3 sinogram matrix header and data

Parameters
fptarget file pointer
matnummatrix number [1..number of matrixes]
hEcat 6.3 scan header
datapointer to data that is written
Returns
0 if ok, 1 invalid input or invalid image dimensions, 2 failed to resolve data type 3 too little data size, 4 failed to resolve next block size in file

Definition at line 461 of file ecat63w.c.

463 {
464 int nxtblk, blkNr, pxlSize, ret;
465
466 if(ECAT63_TEST) printf("ecat63WriteScan(fp, %d, sh, data)\n", matnum);
467 if(fp==NULL || matnum<1 || h==NULL || data==NULL) return(1);
468 /* nr of pixels */
469 long long pxlNr=h->dimension_1*h->dimension_2; if(pxlNr<1) return(1);
470 /* mem taken by one pixel */
471 switch(h->data_type) {
472 case BYTE_TYPE: pxlSize=1;
473 break;
474 case VAX_I2:
475 case SUN_I2: pxlSize=2;
476 break;
477 case VAX_I4: return(3);
478 case VAX_R4: return(3);
479 case IEEE_R4:
480 case SUN_I4: pxlSize=4;
481 break;
482 default: return(2);
483 }
484 /* mem taken by all pixels */
485 long long data_size=pxlNr*pxlSize;
486 /* block nr taken by all pixels */
487 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) return(3);
488 /* Get block number for matrix header and data */
489 nxtblk=ecat63Matenter(fp, matnum, blkNr); if(nxtblk<1) return(4);
490 if(ECAT63_TEST) printf(" block=%d\n", nxtblk);
491 /* Write header */
492 ret=ecat63WriteScanheader(fp, nxtblk, h); if(ret) return(40+ret);
493 /* Write matrix data */
494 ret=ecat63WriteMatdata(fp, nxtblk+1, data, pxlNr, pxlSize);
495 if(ret) return(50+ret);
496 return 0;
497}
int ecat63WriteScanheader(FILE *fp, int block, ECAT63_scanheader *h)
Definition ecat63w.c:242
short int dimension_2
short int dimension_1

Referenced by ecat63AddImg(), and ecat63WriteAllImg().

◆ ecat63WriteScanheader()

int ecat63WriteScanheader ( FILE * fp,
int block,
ECAT63_scanheader * h )

Write ECAT 6.3 scan header

Parameters
fptarget file pointer
blockblock number [>=3]
hEcat 6.3 scan header
Returns
0 if ok, 1 invalid input, 2 failed to find block, 3 failed to write block

Definition at line 242 of file ecat63w.c.

244 {
245 unsigned char buf[MatBLKSIZE];
246 int little, tovax;
247
248
249 if(ECAT63_TEST) printf("ecat63WriteScanheader(fp, %d, ih)\n", block);
250 little=little_endian();
251 /* Clear buf */
252 memset(buf, 0, MatBLKSIZE);
253 /* Check arguments */
254 if(fp==NULL || block<3 || h->data_type<1 || h->data_type>7) return(1);
255 if(h->data_type==VAX_I2 || h->data_type==VAX_I4 || h->data_type==VAX_R4)
256 tovax=1; else tovax=0;
257
258 /* Copy short ints to buf */
259 memcpy(buf+126, &h->data_type, 2);
260 memcpy(buf+132, &h->dimension_1, 2); memcpy(buf+134, &h->dimension_2, 2);
261 memcpy(buf+136, &h->smoothing, 2); memcpy(buf+138, &h->processing_code, 2);
262 memcpy(buf+170, &h->frame_duration_sec, 2);
263 memcpy(buf+192, &h->scan_min, 2); memcpy(buf+194, &h->scan_max, 2);
264 memcpy(buf+468, h->fill2, 44);
265 /* big to little endian if necessary */
266 if(!little) swabip(buf, MatBLKSIZE);
267
268 /* Copy floats to buf */
269 ecat63wFloat(&h->sample_distance, buf+146, tovax, little);
270 ecat63wFloat(&h->isotope_halflife, buf+166, tovax, little);
271 ecat63wFloat(&h->scale_factor, buf+182, tovax, little);
272 for(int i=0; i<16; i++) {
273 ecat63wFloat(&h->cor_singles[i], buf+316+4*i, tovax, little);
274 ecat63wFloat(&h->uncor_singles[i], buf+380+4*i, tovax, little);
275 }
276 ecat63wFloat(&h->tot_avg_cor, buf+444, tovax, little);
277 ecat63wFloat(&h->tot_avg_uncor, buf+448, tovax, little);
278 ecat63wFloat(&h->loss_correction_fctr, buf+464, tovax, little);
279
280 /* Copy ints to buf */
281 ecat63wInt(&h->gate_duration, buf+172, tovax, little);
282 ecat63wInt(&h->r_wave_offset, buf+176, tovax, little);
283 ecat63wInt(&h->prompts, buf+196, tovax, little);
284 ecat63wInt(&h->delayed, buf+200, tovax, little);
285 ecat63wInt(&h->multiples, buf+204, tovax, little);
286 ecat63wInt(&h->net_trues, buf+208, tovax, little);
287 ecat63wInt(&h->total_coin_rate, buf+452, tovax, little);
288 ecat63wInt(&h->frame_start_time, buf+456, tovax, little);
289 ecat63wInt(&h->frame_duration, buf+460, tovax, little);
290
291 /* Copy chars */
292 memcpy(buf+0, h->fill1, 126);
293
294 /* Write subheader */
295 fseeko(fp, (block-1)*MatBLKSIZE, SEEK_SET);
296 if(ftello(fp)!=(block-1)*MatBLKSIZE) return(2);
297 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(3);
298
299 return(0);
300}
float uncor_singles[16]
short int processing_code
short int fill2[22]
short int frame_duration_sec
float cor_singles[16]

Referenced by ecat63WriteScan(), and ecat63WriteScanMatrix().

◆ ecat63WriteScanMatrix()

int ecat63WriteScanMatrix ( FILE * fp,
int matnum,
ECAT63_scanheader * h,
float * fdata )

Write ECAT 6.3 sinogram matrix header and data

Parameters
fptarget file pointer
matnummatrix number [1..number of matrixes]
hEcat 6.3 scan header
fdatamatrix data
Returns
0 if ok, 1 invalid input, 3 invalid matrix dimension, 4 invalid block number, 5 failed to allocate memory for data, 8 failed to resolve next block number, 10 cannot write sub header, 13 failed to write data

Definition at line 781 of file ecat63w.c.

783 {
784 int nxtblk, blkNr, ret;
785 float *fptr, fmin, fmax, g, f;
786 char *mdata, *mptr;
787 short int *sptr;
788
789
790 if(ECAT63_TEST) printf("ecat63WriteScanMatrix(fp, %d, h, data)\n", matnum);
791 if(fp==NULL || matnum<1 || h==NULL || fdata==NULL) {
792 sprintf(ecat63errmsg, "invalid function parameter.\n");
793 return(1);
794 }
795 /* nr of pixels */
796 long long pxlNr=h->dimension_1*h->dimension_2;
797 if(pxlNr<1) {
798 sprintf(ecat63errmsg, "invalid matrix dimension.\n");
799 return(3);
800 }
801 /* How much memory is needed for ALL pixels */
802 long long data_size=pxlNr*ecat63pxlbytes(h->data_type);
803 /* block nr taken by all pixels */
804 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) {
805 sprintf(ecat63errmsg, "invalid block number.\n");
806 return(4);
807 }
808 /* Allocate memory for matrix data */
809 mdata=(char*)calloc(blkNr, MatBLKSIZE); if(mdata==NULL) {
810 sprintf(ecat63errmsg, "out of memory.\n");
811 return(5);
812 }
813 /* Search for min and max for calculation of scale factor */
814 fMinMaxFin(fdata, pxlNr, &fmin, &fmax);
815 if(fabs(fmin)>fabs(fmax)) g=fabs(fmin); else g=fabs(fmax);
816 if(g>0) f=32766./g; else f=1.0;
817 /* Check if pixels values can be left as such with scale_factor = 1 */
818 fptr=fdata;
819 if(f>=1.0 && ecat63_is_scaling_needed(g, fptr, pxlNr)==0) f=1.0;
820 /* Scale matrix data to shorts */
821 h->scale_factor=1.0/f;
822 sptr=(short int*)mdata; fptr=fdata;
823 for(long long i=0; i<pxlNr; i++, sptr++, fptr++)
824 *sptr=(short int)temp_roundf(f*(*fptr));
825 /* Set header short min & max */
826 h->scan_min=(short int)temp_roundf(f*fmin);
827 h->scan_max=(short int)temp_roundf(f*fmax);
828 /* Get block number for matrix header and data */
829 nxtblk=ecat63Matenter(fp, matnum, blkNr); if(nxtblk<1) {
830 sprintf(ecat63errmsg, "cannot determine matrix block (%d).\n", -nxtblk);
831 free(mdata); return(8);
832 }
833 if(ECAT63_TEST>2) printf(" block=%d fmin=%g fmax=%g\n", nxtblk, fmin, fmax);
834 /* Write header */
835 ret=ecat63WriteScanheader(fp, nxtblk, h); if(ret) {
836 sprintf(ecat63errmsg, "cannot write subheader (%d).\n", ret);
837 free(mdata); return(10);
838 }
839 /* Write matrix data */
840 mptr=mdata;
841 ret=ecat63WriteMatdata(fp, nxtblk+1, mptr, pxlNr, ecat63pxlbytes(h->data_type));
842 free(mdata);
843 if(ret) {
844 sprintf(ecat63errmsg, "cannot write matrix data (%d).\n", ret);
845 return(13);
846 }
847 return(0);
848}

Referenced by imgWriteEcat63Frame().