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 664 of file ecat63w.c.

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

Referenced by ecat63_is_scaling_needed(), 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 int buf[MatBLKSIZE/4];
370
371 if(ECAT63_TEST) printf("ecat63Create()\n");
372 /* Check the arguments */
373 if(fname==NULL || h==NULL) return(NULL);
374#if(0)
375 /* Check if file exists; backup, if necessary */
376 if(access(fname, 0) != -1) {
377 char tmp[FILENAME_MAX];
378 strcpy(tmp, fname); strcat(tmp, BACKUP_EXTENSION);
379 if(access(tmp, 0) != -1) remove(tmp);
380 if(ECAT63_TEST) printf("Renaming %s -> %s\n", fname, tmp);
381 rename(fname, tmp);
382 }
383#endif
384 /* Open file */
385 fp=fopen(fname, "wb+"); if(fp==NULL) return(fp);
386 /* Write main header */
387 if(ecat63WriteMainheader(fp, h)) return(NULL);
388 /* Construct an empty matrix list ; convert to little endian if necessary */
389 memset(buf, 0, MatBLKSIZE);
390 buf[0]=31; buf[1]=2; if(!little_endian()) swawbip(buf, MatBLKSIZE);
391 /* Write data buffer */
392 fseek(fp, (MatFirstDirBlk-1)*MatBLKSIZE, SEEK_SET);
393 if(ftell(fp)!=(MatFirstDirBlk-1)*MatBLKSIZE) return(NULL);
394 if(fwrite(buf, 4, MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(NULL);
395 /* OK, then return file pointer */
396 return(fp);
397}
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(), ecat63Create(), 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 927 of file ecat63w.c.

930 {
931 if(h==NULL) return((time_t)-1);
932 struct tm tm;
933 tm.tm_mday=h->scan_start_day;
934 tm.tm_mon=h->scan_start_month-1;
935 tm.tm_year=h->scan_start_year-1900;
936 tm.tm_hour=h->scan_start_hour;
937 tm.tm_min=h->scan_start_minute;
938 tm.tm_sec=h->scan_start_second;
939 tm.tm_isdst=-1;
940 return(timegm(&tm));
941}
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(), ecat63Scanstarttime(), 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 902 of file ecat63w.c.

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

Referenced by ecat63ScanstarttimeToTm().

◆ 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 862 of file ecat63w.c.

864 {
865 unsigned int ul;
866
867 memcpy(&ul, bufi, 4); if(ul==0) {memcpy(bufo, bufi, 4); return;}
868 if(tovax) { /* If VAX format is needed */
869 ul+=(2L<<23); /* increase exp by 2 */
870 /* Swap words on i386 and bytes on SUN */
871 if(islittle) swawip(&ul, 4); else swabip(&ul, 4);
872 } else {
873 if(!islittle) swawbip(&ul, 4); /* Switch words and bytes on SUN */
874 }
875 memcpy(bufo, &ul, 4);
876}
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 ecat63wFloat(), 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 886 of file ecat63w.c.

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

Referenced by ecat63wInt(), 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 565 of file ecat63w.c.

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

◆ 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:862
short int attenuation_type

Referenced by ecat63WriteAttn(), and ecat63WriteAttnheader().

◆ 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 412 of file ecat63w.c.

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

Referenced by ecat63AddImg(), ecat63WriteAllImg(), and ecat63WriteImage().

◆ 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:886
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(), ecat63WriteImageheader(), 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 699 of file ecat63w.c.

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

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

Referenced by ecat63WriteAttn(), ecat63WriteImage(), ecat63WriteImageMatrix(), ecat63WriteMatdata(), 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 514 of file ecat63w.c.

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

Referenced by ecat63WriteNorm().

◆ 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(), and ecat63WriteNormheader().

◆ 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 463 of file ecat63w.c.

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

Referenced by ecat63AddImg(), ecat63WriteAllImg(), and ecat63WriteScan().

◆ 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(), ecat63WriteScanheader(), 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 783 of file ecat63w.c.

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

Referenced by ecat63WriteScanMatrix(), and imgWriteEcat63Frame().