TPCCLIB
Loading...
Searching...
No Matches
img_ana.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6#include "libtpcimgio.h"
7/*****************************************************************************/
8
9/*****************************************************************************/
24int imgReadAnalyze(const char *dbname, IMG *img) {
25 FILE *fp;
26 int ret;
27 float *fdata=NULL, *fptr;
28 ANALYZE_DSR dsr;
29 char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
30 int dimNr, dimx, dimy, dimz=1, dimt=1;
31 SIF sif;
32
33
34 if(IMG_TEST) printf("imgReadAnalyze(%s, *img)\n", dbname);
35
36 /* Check the arguments */
37 imgSetStatus(img, STATUS_OK);
38 if(img==NULL || img->status!=IMG_STATUS_INITIALIZED) {
39 imgSetStatus(img, STATUS_FAULT); return(2);}
40 if(dbname==NULL || !dbname[0]) {imgSetStatus(img, STATUS_FAULT); return(1);}
41
42 /* Make the image and header filenames */
43 ret=anaExistsNew(dbname, hdrfile, datfile, siffile);
44 if(ret==0) {imgSetStatus(img, STATUS_NOHEADERFILE); return(3);}
45 if(ret==1 && IMG_TEST>0) printf("no SIF found for %s\n", dbname);
46
47 /* Read Analyze header file */
48 ret=anaReadHeader(hdrfile, &dsr);
49 if(ret) {
50 if(ret==1) imgSetStatus(img, STATUS_FAULT);
51 else if(ret==2) imgSetStatus(img, STATUS_NOHEADERFILE);
52 else imgSetStatus(img, STATUS_UNSUPPORTED);
53 return(3);
54 }
55 if(IMG_TEST) anaPrintHeader(&dsr, stdout);
56
57 /* Open image datafile */
58 if(IMG_TEST) fprintf(stdout, "reading image data %s\n", datfile);
59 if((fp=fopen(datfile, "rb")) == NULL) {
60 imgSetStatus(img, STATUS_NOIMGDATA); return(5);}
61
62 /* Prepare IMG for Analyze image */
63 /* Get the image dimensions from header */
64 dimNr=dsr.dime.dim[0];
65 if(dimNr<2) {fclose(fp); imgSetStatus(img, STATUS_INVALIDHEADER); return(4);}
66 dimx=dsr.dime.dim[1]; dimy=dsr.dime.dim[2];
67 if(dimNr>2) {dimz=dsr.dime.dim[3]; if(dimNr>3) dimt=dsr.dime.dim[4];}
68 long long pxlNr=dimx*dimy*dimz;
69 if(pxlNr<1) {fclose(fp); imgSetStatus(img, STATUS_INVALIDHEADER); return(4);}
70 /* Allocate memory for IMG */
71 ret=imgAllocate(img, dimz, dimy, dimx, dimt);
72 if(ret) {fclose(fp); imgSetStatus(img, STATUS_NOMEMORY); return(11);}
73 /* Copy information from Analyze header */
76 if(strcmp(img->studyNr, ".")==0) strcpy(img->studyNr, "");
77 strcpy(img->patientName, dsr.hist.patient_id);
78 img->sizex=dsr.dime.pixdim[1];
79 img->sizey=dsr.dime.pixdim[2];
80 img->sizez=dsr.dime.pixdim[3];
81 img->xform[0]=NIFTI_XFORM_UNKNOWN; // qform
82 img->xform[1]=NIFTI_XFORM_SCANNER_ANAT; // sform
83 /*if(dsr.dime.funused2>1.E-5) img->zoom=dsr.dime.funused2;*/
84 if(dsr.dime.funused3>1.E-5) img->isotopeHalflife=dsr.dime.funused3;
85 for(int pi=0; pi<dimz; pi++) img->planeNumber[pi]=pi+1;
86 if(dsr.little) img->_fileFormat=IMG_ANA_L; else img->_fileFormat=IMG_ANA;
87 /* Decay correction */
88 if(strstr(dsr.hist.descrip, "Decay corrected.")!=NULL)
90 else if(strstr(dsr.hist.descrip, "No decay correction.")!=NULL)
92 else
93 img->decayCorrection=IMG_DC_CORRECTED; // just assumed so
94
95 /* Allocate memory for one image frame */
96 fdata=malloc(pxlNr*sizeof(float));
97 if(fdata==NULL) {fclose(fp); imgSetStatus(img, STATUS_NOMEMORY); return(12);}
98
99 /* Read one image frame at a time */
100 for(int fi=0; fi<dimt; fi++) {
101 fptr=fdata;
102 ret=anaReadImagedata(fp, &dsr, fi+1, fptr);
103 if(ret) {
104 free(fdata); fclose(fp); imgSetStatus(img, STATUS_NOIMGDATA); return(7);}
105 /* Copy pixel values to IMG */
106 fptr=fdata;
107 if(anaFlipping()==0) { /* no flipping in z-direction */
108 for(int pi=0; pi<img->dimz; pi++)
109 for(int yi=dimy-1; yi>=0; yi--)
110 for(int xi=dimx-1; xi>=0; xi--)
111 img->m[pi][yi][xi][fi]=*fptr++;
112 } else {
113 for(int pi=dimz-1; pi>=0; pi--)
114 for(int yi=dimy-1; yi>=0; yi--)
115 for(int xi=dimx-1; xi>=0; xi--)
116 img->m[pi][yi][xi][fi]=*fptr++;
117 }
118 } /* next frame */
119 free(fdata);
120 fclose(fp);
121
122 /* Try to read frame time information from SIF file */
123 /* Check if SIF file is found */
124 if(siffile[0]) {
125 if(IMG_TEST) printf("reading SIF file %s\n", siffile);
126 if(access(siffile, 0) == -1) {
127 if(IMG_TEST) printf(" No SIF file; therefore unknown frame times.\n");
128 return(0);
129 }
130 }
131 /* If found, then read it */
132 sifInit(&sif); ret=sifRead(siffile, &sif);
133 if(ret) {imgSetStatus(img, STATUS_NOSIFDATA); return(21);}
134
135 /* Copy SIF contents */
136 ret=sif2img(&sif, img, 1, 1, 1, IMG_TEST-2);
137 sifEmpty(&sif);
138 if(ret!=0) {imgSetStatus(img, STATUS_WRONGSIFDATA); return(22);}
139
140 return(0);
141}
142/*****************************************************************************/
143
144/*****************************************************************************/
162int imgWriteAnalyze(const char *dbname, IMG *img) {
163 FILE *fp;
164 int ret, little;
165 float g;
166 ANALYZE_DSR dsr;
167 char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
168 const char *cptr;
169 struct tm tm; //*st;
170 short int *sdata, *sptr, smin, smax;
171 SIF sif;
172
173
174 if(IMG_TEST) printf("imgWriteAnalyze(%s, *img)\n", dbname);
175
176 /* Check the arguments */
177 imgSetStatus(img, STATUS_OK);
178 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) {
179 imgSetStatus(img, STATUS_FAULT); return(2);}
180 if(dbname==NULL || !dbname[0]) {imgSetStatus(img, STATUS_FAULT); return(1);}
181
182 /* Make the image and header filenames */
183 strcpy(datfile, dbname); strcat(datfile, ".img");
184 strcpy(hdrfile, dbname); strcat(hdrfile, ".hdr");
185 strcpy(siffile, dbname); strcat(siffile, ".sif");
186
187
188 /*
189 * Fill Analyze header
190 */
191 if(img->_fileFormat==IMG_ANA_L) dsr.little=1; else dsr.little=0;
192 /* Header key */
193 memset(&dsr.hk, 0, sizeof(ANALYZE_HEADER_KEY));
194 memset(&dsr.dime, 0, sizeof(ANALYZE_HEADER_IMGDIM));
195 memset(&dsr.hist, 0, sizeof(ANALYZE_HEADER_HISTORY));
196 dsr.hk.sizeof_hdr=348;
197 strcpy(dsr.hk.data_type, "");
198 cptr=strrchr(dbname, '/'); if(cptr==NULL) cptr=strrchr(dbname, '\\');
199 if(cptr!=NULL) cptr++;
200 if(cptr==NULL) cptr=dbname;
201 strncpy(dsr.hk.db_name, cptr, 17);
202 dsr.hk.extents=16384;
203 dsr.hk.regular='r';
204 /* Image dimension */
205 dsr.dime.dim[0]=4;
206 dsr.dime.dim[1]=img->dimx;
207 dsr.dime.dim[2]=img->dimy;
208 dsr.dime.dim[3]=img->dimz;
209 dsr.dime.dim[4]=img->dimt;
211 dsr.dime.bitpix=16;
212 dsr.dime.pixdim[0]=0.0;
213 dsr.dime.pixdim[1]=img->sizex;
214 dsr.dime.pixdim[2]=img->sizey;
215 dsr.dime.pixdim[3]=img->sizez;
216 dsr.dime.pixdim[4]=0.0;
217 dsr.dime.funused1=0.0; /* Scale factor is set later */
218 /* dsr.dime.funused2=img->zoom; */ /* Reconstruction zoom */
220 /* Data history */
222 strcpy(dsr.hist.descrip, "Decay corrected.");
224 strcpy(dsr.hist.descrip, "No decay correction.");
225 else
226 strcpy(dsr.hist.descrip, "");
227 if(strlen(img->studyNr)>0 && strcmp(img->studyNr, ".")!=0)
228 memcpy(dsr.hist.scannum, img->studyNr, 10);
229 else
230 strcpy(dsr.hist.scannum, "");
231 gmtime_r((time_t*)&img->scanStart, &tm);
232 if(!strftime(dsr.hist.exp_date, 10, "%Y-%m-%d", &tm))
233 memcpy(dsr.hist.exp_date, "1900-01-01", 10);
234 if(!strftime(dsr.hist.exp_time, 10, "%H:%M:%S", &tm))
235 strlcpy(dsr.hist.exp_time, "00:00:00", 10);
236
237 /*
238 * Scale data to short int range
239 * Determine and set scale factor and cal_min & cal_max
240 */
241 if(IMG_TEST) printf("scaling data to short ints\n");
242 ret=imgMinMax(img, &dsr.dime.cal_min, &dsr.dime.cal_max);
243 if(ret) {imgSetStatus(img, STATUS_FAULT); return(3);}
244 if(IMG_TEST) printf("min=%g max=%g\n", dsr.dime.cal_min, dsr.dime.cal_max);
245 if(fabs(dsr.dime.cal_min)>fabs(dsr.dime.cal_max)) g=fabs(dsr.dime.cal_min);
246 else g=fabs(dsr.dime.cal_max);
247 if(isnan(g)) {imgSetStatus(img, STATUS_FAULT); return 3;}
248 if(g<1E-20) g=1.0; else g=32767./g; dsr.dime.funused1=1.0/g;
249 if(IMG_TEST) printf("scale_factor=%g\n", dsr.dime.funused1);
250
251 /* Allocate memory for short int array */
252 size_t pxlNr=(img->dimx)*(img->dimy)*(img->dimz);
253 sdata=malloc(pxlNr*sizeof(short int));
254 if(sdata==NULL) {imgSetStatus(img, STATUS_NOMEMORY); return 12;}
255
256 /* Open image data file for write */
257 if((fp=fopen(datfile, "wb")) == NULL) {
258 imgSetStatus(img, STATUS_CANTWRITEIMGFILE);
259 free(sdata);
260 return 14;
261 }
262
263 /* Copy and write image matrix data to short int array */
264 /* Data is written one frame at a time */
265 smin=smax=temp_roundf(g*img->m[0][0][0][0]);
266 for(int fi=0; fi<img->dimt; fi++) {
267 sptr=sdata;
268 if(anaFlipping()==0) {
269 for(int pi=0; pi<img->dimz; pi++)
270 for(int yi=img->dimy-1; yi>=0; yi--)
271 for(int xi=img->dimx-1; xi>=0; xi--) {
272 *sptr=temp_roundf(g*img->m[pi][yi][xi][fi]);
273 if(*sptr>smax) smax=*sptr; else if(*sptr<smin) smin=*sptr;
274 sptr++;
275 }
276 } else {
277 for(int pi=img->dimz-1; pi>=0; pi--)
278 for(int yi=img->dimy-1; yi>=0; yi--)
279 for(int xi=img->dimx-1; xi>=0; xi--) {
280 *sptr=temp_roundf(g*img->m[pi][yi][xi][fi]);
281 if(*sptr>smax) smax=*sptr; else if(*sptr<smin) smin=*sptr;
282 sptr++;
283 }
284 }
285 /* Change byte order if necessary */
286 little=little_endian();
287 if(little!=dsr.little)
288 swabip(sdata, pxlNr*sizeof(short int));
289 /* Write image data */
290 if(fwrite(sdata, 2, pxlNr, fp) != pxlNr) {
291 imgSetStatus(img, STATUS_CANTWRITEIMGFILE);
292 free(sdata); fclose(fp);
293 return 15;
294 }
295 }
296 /* Done writing */
297 fclose(fp);
298 free(sdata);
299
300 if(IMG_TEST) printf("smin=%d smax=%d\n", smin, smax);
301
302 /* Set header glmin & glmax */
303 dsr.dime.glmin=smin; dsr.dime.glmax=smax;
304
305 /* Write Analyze header */
306 ret=anaWriteHeader(hdrfile, &dsr);
307 if(ret) {
308 imgSetStatus(img, STATUS_CANTWRITEHEADERFILE);
309 return 21;
310 }
311 imgSetStatus(img, STATUS_OK);
312
313 /* Otherwise ready, but check if SIF should/can be written */
314 sifInit(&sif);
315 /* Try to read existing SIF */
316 ret=sifRead(siffile, &sif);
317 if(ret==0) { // SIF could be read
318 if(sif.frameNr==img->dimt) {
319 /* If size matches, then update the contents, but keep counts, in case
320 previous SIF comes with actual count info from scanner */
321 ret=img2sif(img, &sif, 1, 1, 0, IMG_TEST-2);
322 } else {
323 /* otherwise create SIF contents */
324 ret=img2sif(img, &sif, 1, 1, 2, IMG_TEST-2);
325 }
326 } else {
327 /* otherwise create SIF contents */
328 ret=img2sif(img, &sif, 1, 1, 2, IMG_TEST-2);
329 }
330 if(ret!=0) {
331 /* SIF data could not be made: do not give error, just do not write it */
332 if(IMG_TEST>0) printf("SIF contents could not be filled.\n");
333 return 0;
334 }
335 /* Write SIF */
336 ret=sifWrite(&sif, siffile);
337 if(ret!=0) {
338 /* SIF could not be written: do not give error, just do not write it */
339 if(IMG_TEST>0)
340 fprintf(stderr, "Error: SIF could not be written (%d).\n", ret);
341 }
342
343 imgSetStatus(img, STATUS_OK);
344 return 0;
345}
346/*****************************************************************************/
347
348/*****************************************************************************/
360int imgReadAnalyzeHeader(const char *dbname, IMG *img) {
361 char hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
362 ANALYZE_DSR ana_header;
363 SIF sif;
364 double f;
365 int ret;
366
367 if(IMG_TEST) printf("\nimgReadAnalyzeHeader(%s, *img)\n", dbname);
368
369 /* Check the input */
370 if(img==NULL) return STATUS_FAULT;
371 if(img->status!=IMG_STATUS_INITIALIZED) return STATUS_FAULT;
372 imgSetStatus(img, STATUS_FAULT);
373 if(dbname==NULL) return STATUS_FAULT;
374
375 /* Determine the names of hdr and sif files */
376 ret=anaDatabaseExists(dbname, hdrfile, NULL, siffile);
377 if(ret==0) return STATUS_NOFILE;
378
379 /* Read Analyze header file */
380 ret=anaReadHeader(hdrfile, &ana_header);
381 if(ret!=0) {
382 if(IMG_TEST>1) printf("anaReadHeader() return value := %d\n", ret);
383 if(ret==1) return STATUS_FAULT;
384 else if(ret==2) return STATUS_NOHEADERFILE;
385 else return STATUS_UNSUPPORTED;
386 return(STATUS_FAULT);
387 }
388 /* and set IMG contents */
389 ret=imgGetAnalyzeHeader(img, &ana_header);
390 if(ret!=0) {
391 imgSetStatus(img, ret);
392 return(ret);
393 }
394
395 /* If SIF does not exist, then that's it */
396 if(!siffile[0]) {
397 imgSetStatus(img, STATUS_OK);
398 return STATUS_OK;
399 }
400
401 /* SIF is available, so read that too */
402 sifInit(&sif); ret=0;
403 if(sifRead(siffile, &sif)!=0) return STATUS_OK;
404 /* Copy scan time */
405 img->scanStart=sif.scantime;
406 /* Study number, if not yet defined */
407 if(!img->studyNr[0] && strlen(sif.studynr)>1 )
409 /* Isotope half-life, if not yet defined */
411 if(img->isotopeHalflife<=0.0 && f>0.0) img->isotopeHalflife=60.0*f;
412 sifEmpty(&sif);
413
414 return STATUS_OK;
415}
416/*****************************************************************************/
417
418/*****************************************************************************/
428{
429 int dimNr, dimx, dimy, dimz=1, dimt=1;
430
431 if(IMG_TEST) printf("\nimgGetAnalyzeHeader(*img, *dsr)\n");
432
433 /* Check the input */
434
435 if(img==NULL) return STATUS_FAULT;
437 return STATUS_FAULT;
438 imgSetStatus(img, STATUS_FAULT);
439 if(h==NULL) return STATUS_FAULT;
440
441 imgSetStatus(img, STATUS_INVALIDHEADER);
442
443 /* Get the image dimensions from header */
444 dimNr=h->dime.dim[0];
445 if(dimNr<2) return STATUS_INVALIDHEADER;
446 dimx=h->dime.dim[1]; dimy=h->dime.dim[2];
447 if(dimNr>2) {dimz=h->dime.dim[3]; if(dimNr>3) dimt=h->dime.dim[4];}
448 long long pxlNr=dimx*dimy*dimz;
449 if(pxlNr<1) return STATUS_INVALIDHEADER;
450 img->dimx=dimx; img->dimy=dimy; img->dimz=dimz; img->dimt=dimt;
451
452 /* Copy information from Analyze header */
453 img->type=IMG_TYPE_IMAGE;
455 if(strcmp(img->studyNr, ".")==0) strcpy(img->studyNr, "");
456 strcpy(img->patientName, h->hist.patient_id);
457 img->sizex=h->dime.pixdim[1];
458 img->sizey=h->dime.pixdim[2];
459 img->sizez=h->dime.pixdim[3];
460 /*if(h->dime.funused2>1.E-5) img->zoom=h->dime.funused2;*/
461 if(h->dime.funused3>1.E-5) img->isotopeHalflife=h->dime.funused3;
462 if(h->little) img->_fileFormat=IMG_ANA_L; else img->_fileFormat=IMG_ANA;
463
464 /* Decay correction */
465 if(strstr(h->hist.descrip, "Decay corrected.")!=NULL)
467 else if(strstr(h->hist.descrip, "No decay correction.")!=NULL)
469 else
470 img->decayCorrection=IMG_DC_CORRECTED; // just assumed so
471
472 imgSetStatus(img, STATUS_OK);
473 return STATUS_OK;
474}
475/*****************************************************************************/
476
477/*****************************************************************************/
488 IMG *img,
490 const char *dbname,
492 ANALYZE_DSR *dsr,
494 float fmin,
496 float fmax
497) {
498 struct tm tm; //*st;
499 char *cptr;
500 float g;
501
502 if(IMG_TEST) printf("\nimgSetAnalyzeHeader(*img, %s, *dsr, %g, %g)\n",
503 dbname, fmin, fmax);
504
505 /* Check the input */
506 if(img==NULL) return STATUS_FAULT;
508 return STATUS_FAULT;
509 imgSetStatus(img, STATUS_FAULT);
510 if(dsr==NULL) return STATUS_FAULT;
511
512 /* Byte order */
513 if(img->_fileFormat==IMG_ANA_L) dsr->little=1; else dsr->little=0;
514 /* Header key */
515 memset(&dsr->hk, 0, sizeof(ANALYZE_HEADER_KEY));
516 memset(&dsr->dime, 0, sizeof(ANALYZE_HEADER_IMGDIM));
517 memset(&dsr->hist, 0, sizeof(ANALYZE_HEADER_HISTORY));
518 dsr->hk.sizeof_hdr=348;
519 strcpy(dsr->hk.data_type, "");
520 cptr=strrchr(dbname, '/'); if(cptr==NULL) cptr=strrchr(dbname, '\\');
521 if(cptr!=NULL) cptr++;
522 if(cptr==NULL) cptr=(char*)dbname;
523 strncpy(dsr->hk.db_name, cptr, 17);
524 dsr->hk.extents=16384;
525 dsr->hk.regular='r';
526 /* Image dimension */
527 dsr->dime.dim[0]=4;
528 dsr->dime.dim[1]=img->dimx;
529 dsr->dime.dim[2]=img->dimy;
530 dsr->dime.dim[3]=img->dimz;
531 dsr->dime.dim[4]=img->dimt;
533 dsr->dime.bitpix=16;
534 dsr->dime.pixdim[0]=0.0;
535 dsr->dime.pixdim[1]=img->sizex;
536 dsr->dime.pixdim[2]=img->sizey;
537 dsr->dime.pixdim[3]=img->sizez;
538 dsr->dime.pixdim[4]=0.0;
539 dsr->dime.funused1=0.0; /* Scale factor is set later */
540 /* dsr.dime.funused2=img->zoom; */ /* Reconstruction zoom */
541 dsr->dime.funused3=img->isotopeHalflife;
542 /* Data history */
544 strcpy(dsr->hist.descrip, "Decay corrected.");
546 strcpy(dsr->hist.descrip, "No decay correction.");
547 else
548 strcpy(dsr->hist.descrip, "");
549 if(strlen(img->studyNr)>0 && strcmp(img->studyNr, ".")!=0)
550 memcpy(dsr->hist.scannum, img->studyNr, 10);
551 else
552 strcpy(img->studyNr, "");
553 gmtime_r((time_t*)&img->scanStart, &tm);
554 if(!strftime(dsr->hist.exp_date, 10, "%Y%m%d", &tm))
555 strcpy(dsr->hist.exp_date, "19000101");
556 if(!strftime(dsr->hist.exp_time, 10, "%H:%M:%S", &tm))
557 strncpy(dsr->hist.exp_time, "00:00:00", 10);
558
559 /* Determine and set scale factor and cal_min & cal_max */
560 if(fmin<fmax) {
561 dsr->dime.cal_min=fmin; dsr->dime.cal_max=fmax;
562 } else { /* not given in function call, try to find those here */
563 if(img->status==IMG_STATUS_OCCUPIED &&
564 imgMinMax(img, &dsr->dime.cal_min, &dsr->dime.cal_max)==0) {}
565 else return STATUS_FAULT;
566 }
567 if(fabs(dsr->dime.cal_min) > fabs(dsr->dime.cal_max)) g=fabs(dsr->dime.cal_min);
568 else g = fabs(dsr->dime.cal_max);
569 /* if(fabs(dsr->dime.cal_min)>fabs(dsr->dime.cal_max))
570 g=fabs(dsr->dime.cal_min); */
571 /* else g=fabs(dsr->dime.cal_max); */
572 if(g<1E-20) g=1.0; else g=32767./g; dsr->dime.funused1=1.0/g;
573 /* Set header glmin & glmax */
574 dsr->dime.glmin=temp_roundf(fmin*g); dsr->dime.glmax=temp_roundf(fmax*g);
575 /* printf("glmin=%d\n", dsr->dime.glmin); */
576 /* printf("glmax=%d\n", dsr->dime.glmax); */
577
578 imgSetStatus(img, STATUS_OK);
579 return STATUS_OK;
580}
581/*****************************************************************************/
582
583/*****************************************************************************/
592int imgReadAnalyzeFirstFrame(const char *fname, IMG *img) {
593 int ret=0;
594
595 if(IMG_TEST) printf("\nimgReadAnalyzeFirstFrame(%s, *img)\n", fname);
596 /* Check the input */
597 if(img==NULL) return STATUS_FAULT;
598 if(img->status!=IMG_STATUS_INITIALIZED) return STATUS_FAULT;
599 imgSetStatus(img, STATUS_FAULT);
600 if(fname==NULL) return STATUS_FAULT;
601
602 /* Read header information from file */
603 ret=imgReadAnalyzeHeader(fname, img); if(ret) return(ret);
604 if(IMG_TEST>3) imgInfo(img);
605
606 /* Allocate memory for one frame */
607 img->dimt=1;
608 ret=imgAllocate(img, img->dimz, img->dimy, img->dimx, img->dimt);
609 if(ret) return STATUS_NOMEMORY;
610
611 /* Read the first frame */
612 ret=imgReadAnalyzeFrame(fname, 1, img, 0); if(ret) return(ret);
613
614 /* All went well */
615 imgSetStatus(img, STATUS_OK);
616 return STATUS_OK;
617}
618/*****************************************************************************/
619
620/*****************************************************************************/
640 const char *fname, int frame_to_read, IMG *img, int frame_index
641) {
642 FILE *fp;
643 int ret;
644 float *fdata=NULL, *fptr;
645 ANALYZE_DSR dsr;
646 char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
647 SIF sif;
648
649
650 if(IMG_TEST) printf("\nimgReadAnalyzeFrame(%s, %d, *img, %d)\n",
651 fname, frame_to_read, frame_index);
652
653 /* Check the input */
654 if(img==NULL) return STATUS_FAULT;
655 if(img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT;
656 if(fname==NULL) return STATUS_FAULT;
657 if(frame_index<0 || frame_index>img->dimt-1) return STATUS_FAULT;
658 if(frame_to_read<1) return STATUS_FAULT;
659 imgSetStatus(img, STATUS_FAULT);
660
661 /* Determine the names of hdr, data and sif files */
662 ret=anaDatabaseExists(fname, hdrfile, datfile, siffile);
663 if(ret==0) return STATUS_NOFILE;
664
665 /* Read Analyze header file */
666 ret=anaReadHeader(hdrfile, &dsr);
667 if(ret!=0) {
668 if(ret==1) return STATUS_FAULT;
669 else if(ret==2) return STATUS_NOHEADERFILE;
670 else return STATUS_UNSUPPORTED;
671 return(STATUS_FAULT);
672 }
673
674 /* Open image datafile */
675 if(IMG_TEST>2) fprintf(stdout, "reading image data %s\n", datfile);
676 if((fp=fopen(datfile, "rb")) == NULL) return STATUS_NOIMGDATA;
677
678 /* Allocate memory for one image frame */
679 fdata=malloc((size_t)img->dimx*img->dimy*img->dimz*sizeof(float));
680 if(fdata==NULL) {fclose(fp); return STATUS_NOMEMORY;}
681
682 /* Read the required image frame */
683 fptr=fdata;
684 ret=anaReadImagedata(fp, &dsr, frame_to_read, fptr);
685 fclose(fp);
686 if(ret==3) {free(fdata); return STATUS_NOMATRIX;} /* no more frames */
687 if(ret!=0) {free(fdata); return STATUS_UNSUPPORTED;}
688
689 /* Copy pixel values to IMG */
690 fptr=fdata;
691 if(anaFlipping()==0) { /* no flipping in z-direction */
692 for(int pi=0; pi<img->dimz; pi++)
693 for(int yi=img->dimy-1; yi>=0; yi--)
694 for(int xi=img->dimx-1; xi>=0; xi--)
695 img->m[pi][yi][xi][frame_index]=*fptr++;
696 } else {
697 for(int pi=img->dimz-1; pi>=0; pi--)
698 for(int yi=img->dimy-1; yi>=0; yi--)
699 for(int xi=img->dimx-1; xi>=0; xi--)
700 img->m[pi][yi][xi][frame_index]=*fptr++;
701 }
702 free(fdata);
703
704 /* Set decay correction factor to zero */
705 img->decayCorrFactor[frame_index]=0.0;
706
707 imgSetStatus(img, STATUS_OK); /* If the rest is failed, no problem */
708
709 /*
710 * Try to read frame time information from SIF file
711 */
712 sifInit(&sif);
713 if(sifRead(siffile, &sif)!=0) return STATUS_OK;
714 /* Frame information */
715 if(sif.frameNr>=frame_to_read) {
716 img->start[frame_index]=sif.x1[frame_to_read-1];
717 img->end[frame_index]=sif.x2[frame_to_read-1];
718 img->mid[frame_index]=0.5*(img->start[frame_index]+img->end[frame_index]);
719 img->prompts[frame_index]=sif.prompts[frame_to_read-1];
720 img->randoms[frame_index]=sif.randoms[frame_to_read-1];
721 }
722 sifEmpty(&sif);
723
724 return STATUS_OK;
725}
726/*****************************************************************************/
727
728/*****************************************************************************/
752 const char *dbname, int frame_to_write, IMG *img, int frame_index,
753 float fmin, float fmax
754) {
755 IMG test_img;
756 int ret=0, little;
757 FILE *fp;
758 short int *sdata=NULL, *sptr;
759 char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
760 ANALYZE_DSR dsr;
761 float scale_factor=1.0;
762
763
764 if(IMG_TEST) printf("\nimgWriteAnalyzeFrame(%s, %d, *img, %d, %g, %g)\n",
765 dbname, frame_to_write, frame_index, fmin, fmax);
766
767 /*
768 * Check the input
769 */
770 if(dbname==NULL) return STATUS_FAULT;
771 if(img==NULL) return STATUS_FAULT;
772 if(img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT;
773 if(frame_to_write<0) return STATUS_FAULT;
774 if(frame_index<0 || frame_index>=img->dimt) return STATUS_FAULT;
775 if(img->_fileFormat!=IMG_ANA_L && img->_fileFormat!=IMG_ANA)
776 return STATUS_FAULT;
777
778 /*
779 * If database does not exist, then create it with new header,
780 * and if it does exist, then read and check header information.
781 * Create or edit header to contain correct frame nr.
782 * Determine the global scaling factor.
783 */
784 imgInit(&test_img);
785 if(anaDatabaseExists(dbname, hdrfile, datfile, siffile)==0) { // not existing
786
787 /* Create database filenames */
788 sprintf(hdrfile, "%s.hdr", dbname);
789 sprintf(datfile, "%s.img", dbname);
790 sprintf(siffile, "%s.sif", dbname);
791
792 /* Set main header */
793 imgSetAnalyzeHeader(img, dbname, &dsr, fmin, fmax);
794 if(frame_to_write==0) frame_to_write=1;
795 dsr.dime.dim[4]=frame_to_write;
796 scale_factor=dsr.dime.funused1;
797 if(fabs(scale_factor)>1.0E-20) scale_factor=1.0/scale_factor;
798
799 /* Write Analyze header */
800 ret=anaWriteHeader(hdrfile, &dsr);
801 if(ret && IMG_TEST) printf("anaWriteHeader() := %d\n", ret);
802 if(ret) return STATUS_CANTWRITEHEADERFILE;
803
804 /* Remove datafile if necessary */
805 if(access(datfile, 0) != -1) remove(datfile);
806
807 } else { /* database does exist */
808
809 /* Read header information for checking */
810 ret=imgReadAnalyzeHeader(dbname, &test_img);
811 if(ret!=0) {imgEmpty(&test_img); return ret;}
812 /* Check that file format is the same */
813 if(img->_fileFormat!=test_img._fileFormat || img->type!=test_img.type) {
814 imgEmpty(&test_img); return STATUS_WRONGFILETYPE;}
815 /* Check that matrix sizes are the same */
816 if(img->dimz!=test_img.dimz || img->dimx!=test_img.dimx ||
817 img->dimy!=test_img.dimy) {
818 imgEmpty(&test_img); return STATUS_VARMATSIZE;}
819 imgEmpty(&test_img);
820
821 /* Read the header, set new frame number, and write it back */
822 /* Get also the scale factor */
823 if((ret=anaReadHeader(hdrfile, &dsr))!=0) return STATUS_NOMAINHEADER;
824 scale_factor=1.0/dsr.dime.funused1;
825 if(frame_to_write==0) frame_to_write=dsr.dime.dim[4]+1;
826 if(dsr.dime.dim[4]<frame_to_write) {
827 if(dsr.dime.dim[4]+1<frame_to_write) return STATUS_MISSINGMATRIX;
828 dsr.dime.dim[4]=frame_to_write;
829 }
830 if((ret=anaWriteHeader(hdrfile, &dsr))!=0) return STATUS_NOWRITEPERM;
831 }
832 if(IMG_TEST>2) {
833 printf("frame_to_write := %d\n", frame_to_write);
834 printf("hdrfile := %s\n", hdrfile);
835 printf("datfile := %s\n", datfile);
836 printf("siffile := %s\n", siffile);
837 }
838
839 /* Allocate memory for matrix short int data (one plane) */
840 size_t pxlNr=img->dimx*img->dimy;
841 sdata=(short int*)malloc(pxlNr*sizeof(short int));
842 if(sdata==NULL) return STATUS_NOMEMORY;
843
844 /* Open datafile, not removing possible old contents */
845 if(frame_to_write==1) fp=fopen(datfile, "wb"); else fp=fopen(datfile, "r+b");
846 if(fp==NULL) {free(sdata); return STATUS_CANTWRITEIMGFILE;}
847 /* Move file pointer to the place of current frame */
848 if(fseeko(fp, (frame_to_write-1)*pxlNr*img->dimz*sizeof(short int),
849 SEEK_SET)!=0) {
850 free(sdata); fclose(fp); return STATUS_MISSINGMATRIX;}
851 little=little_endian();
852 /* Copy, scale and write data plane-by-plane */
853 if(anaFlipping()==0) {
854 for(int zi=0; zi<img->dimz; zi++) {
855 sptr=sdata;
856 /*printf("plane := %d\n scale_factor := %g\n", zi+1, scale_factor);*/
857 for(int yi=img->dimy-1; yi>=0; yi--)
858 for(int xi=img->dimx-1; xi>=0; xi--) {
859 *sptr=temp_roundf(scale_factor*img->m[zi][yi][xi][frame_index]);
860 sptr++;
861 }
862 /* Change byte order if necessary */
863 sptr=sdata; if(little!=dsr.little) swabip(sptr, pxlNr*sizeof(short int));
864 /* Write image data */
865 sptr=sdata;
866 if(fwrite(sptr, sizeof(short int), pxlNr, fp) != pxlNr) {
867 free(sdata); fclose(fp); return STATUS_CANTWRITEIMGFILE;
868 }
869 }
870 } else {
871 for(int zi=img->dimz-1; zi>=0; zi--) {
872 sptr=sdata;
873 for(int yi=img->dimy-1; yi>=0; yi--)
874 for(int xi=img->dimx-1; xi>=0; xi--) {
875 *sptr=temp_roundf(scale_factor*img->m[zi][yi][xi][frame_index]);
876 sptr++;
877 }
878 /* Change byte order if necessary */
879 sptr=sdata; if(little!=dsr.little) swabip(sptr, pxlNr*sizeof(short int));
880 /* Write image data */
881 sptr=sdata;
882 if(fwrite(sptr, sizeof(short int), pxlNr, fp) != pxlNr) {
883 free(sdata); fclose(fp); return STATUS_CANTWRITEIMGFILE;
884 }
885 }
886 }
887 free(sdata);
888 fclose(fp);
889
890 return STATUS_OK;
891}
892/*****************************************************************************/
893
894/*****************************************************************************/
int anaWriteHeader(char *filename, ANALYZE_DSR *h)
Definition analyze.c:282
int anaExistsNew(const char *filename, char *hdrfile, char *imgfile, char *siffile)
Definition analyze.c:45
int anaFlipping()
Definition analyze.c:635
int anaPrintHeader(ANALYZE_DSR *h, FILE *fp)
Definition analyze.c:380
int anaDatabaseExists(const char *dbname, char *hdrfile, char *imgfile, char *siffile)
Definition analyze.c:704
int anaReadHeader(char *filename, ANALYZE_DSR *h)
Definition analyze.c:131
int anaReadImagedata(FILE *fp, ANALYZE_DSR *h, int frame, float *data)
Definition analyze.c:454
struct tm * gmtime_r(const time_t *t, struct tm *tm)
Convert time_t to GMT struct tm.
Definition datetime.c:22
double hlFromIsotope(char *isocode)
Definition halflife.c:55
int IMG_TEST
Definition img.c:6
void imgInfo(IMG *image)
Definition img.c:359
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
void imgSetStatus(IMG *img, int status_index)
Definition img.c:345
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgWriteAnalyze(const char *dbname, IMG *img)
Definition img_ana.c:162
int imgGetAnalyzeHeader(IMG *img, ANALYZE_DSR *h)
Definition img_ana.c:427
int imgReadAnalyzeFirstFrame(const char *fname, IMG *img)
Definition img_ana.c:592
int imgReadAnalyzeFrame(const char *fname, int frame_to_read, IMG *img, int frame_index)
Definition img_ana.c:639
int imgReadAnalyzeHeader(const char *dbname, IMG *img)
Definition img_ana.c:360
int imgSetAnalyzeHeader(IMG *img, const char *dbname, ANALYZE_DSR *dsr, float fmin, float fmax)
Definition img_ana.c:486
int imgWriteAnalyzeFrame(const char *dbname, int frame_to_write, IMG *img, int frame_index, float fmin, float fmax)
Definition img_ana.c:751
int imgReadAnalyze(const char *dbname, IMG *img)
Definition img_ana.c:24
int img2sif(IMG *img, SIF *sif, int copy_header, int copy_frames, int copy_counts, int verbose)
Definition img_sif.c:71
int sif2img(SIF *sif, IMG *img, int copy_header, int copy_frames, int copy_counts, int verbose)
Definition img_sif.c:13
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Definition imgminmax.c:154
Header file for libtpcimgio.
#define NIFTI_XFORM_UNKNOWN
int sifWrite(SIF *data, char *filename)
Definition sifio.c:145
#define IMG_STATUS_OCCUPIED
#define IMG_ANA_L
#define IMG_DC_CORRECTED
#define ANALYZE_DT_SIGNED_SHORT
Definition libtpcimgio.h:55
void sifInit(SIF *data)
Definition sif.c:17
#define IMG_STATUS_INITIALIZED
#define IMG_DC_NONCORRECTED
#define IMG_ANA
#define NIFTI_XFORM_SCANNER_ANAT
void sifEmpty(SIF *data)
Definition sif.c:33
int sifRead(char *filename, SIF *data)
Definition sifio.c:21
#define IMG_TYPE_IMAGE
void swabip(void *buf, long long int size)
Definition swap.c:72
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
int little_endian()
Definition swap.c:14
#define MAX_STUDYNR_LEN
Definition libtpcmisc.h:163
int temp_roundf(float e)
Definition petc99.c:20
ANALYZE_HEADER_HISTORY hist
ANALYZE_HEADER_KEY hk
ANALYZE_HEADER_IMGDIM dime
float sizex
unsigned short int dimx
char type
char patientName[32]
float **** m
char decayCorrection
short int xform[2]
char status
time_t scanStart
int _fileFormat
float * prompts
unsigned short int dimt
int * planeNumber
float sizey
float * start
unsigned short int dimz
unsigned short int dimy
float * end
float * decayCorrFactor
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float * randoms
float * mid
float sizez
double * x1
double * prompts
int frameNr
double * x2
char studynr[MAX_STUDYNR_LEN+1]
time_t scantime
char isotope_name[8]
double * randoms