TPCCLIB
Loading...
Searching...
No Matches
img_nii.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "libtpcimgio.h"
11/*****************************************************************************/
12
13/*****************************************************************************/
25 const char *filename,
27 IMG *img,
29 int verbose
30) {
31 if(verbose>0) {printf("imgReadNifti(%s, ...)\n", filename); fflush(stdout);}
32
33 /* Check the arguments */
34 if(img==NULL || img->status!=IMG_STATUS_INITIALIZED) {
35 if(img!=NULL) imgSetStatus(img, STATUS_FAULT);
36 if(verbose>0) fprintf(stderr, "Error: invalid IMG argument\n");
37 return(STATUS_FAULT);
38 }
39 if(filename==NULL || !filename[0]) {
40 imgSetStatus(img, STATUS_FAULT);
41 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
42 return(STATUS_FAULT);
43 }
44 imgSetStatus(img, STATUS_OK);
45
46 /* Read header information from file */
47 int ret=imgReadNiftiHeader(filename, img, verbose-1); if(ret) {return(ret);}
48 if(verbose>10) imgInfo(img);
49
50 /* Allocate memory for all frames */
51 ret=imgAllocate(img, img->dimz, img->dimy, img->dimx, img->dimt);
52 if(ret) {
53 imgSetStatus(img, STATUS_OK);
54 return STATUS_NOMEMORY;
55 }
56
57 /* Read one frame at a time */
58 for(int fi=0; fi<img->dimt; fi++) {
59 ret=imgReadNiftiFrame(filename, 1+fi, img, fi, verbose-1);
60 if(ret) return(ret);
61 }
62
63 /* All went well */
64 imgSetStatus(img, STATUS_OK);
65 return(STATUS_OK);
66}
67/*****************************************************************************/
68
69/*****************************************************************************/
80 const char *filename,
82 IMG *img,
84 int verbose
85) {
86 if(verbose>0) {printf("imgReadNiftiFirstFrame(%s, ...)\n", filename); fflush(stdout);}
87
88 /* Check the arguments */
89 if(img==NULL || img->status!=IMG_STATUS_INITIALIZED) {
90 if(img!=NULL) imgSetStatus(img, STATUS_FAULT);
91 if(verbose>0) fprintf(stderr, "Error: invalid IMG argument\n");
92 return(STATUS_FAULT);
93 }
94 if(filename==NULL || !filename[0]) {
95 imgSetStatus(img, STATUS_FAULT);
96 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
97 return(STATUS_FAULT);
98 }
99 imgSetStatus(img, STATUS_OK);
100
101 /* Read header information from file */
102 int ret=imgReadNiftiHeader(filename, img, verbose-1); if(ret) {return(ret);}
103 if(verbose>10) imgInfo(img);
104
105 /* Allocate memory for one frame */
106 img->dimt=1;
107 ret=imgAllocate(img, img->dimz, img->dimy, img->dimx, img->dimt);
108 if(ret) {
109 imgSetStatus(img, STATUS_OK);
110 return STATUS_NOMEMORY;
111 }
112
113 /* Read the first frame */
114 ret=imgReadNiftiFrame(filename, 1, img, 0, verbose-1); if(ret) return(ret);
115
116 /* All went well */
117 imgSetStatus(img, STATUS_OK);
118 return(STATUS_OK);
119}
120/*****************************************************************************/
121
122/*****************************************************************************/
136 const char *filename,
138 IMG *img,
140 int verbose
141) {
142 char basefile[FILENAME_MAX], tmp[256];
143 char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
144 NIFTI_DSR dsr;
145 int ret;
146 SIF sif;
147 double f;
148
149 if(verbose>0) {printf("imgReadNiftiHeader(%s, ...)\n", filename); fflush(stdout);}
150
151 /* Check the arguments */
152 if(img==NULL || img->status!=IMG_STATUS_INITIALIZED) {
153 if(img!=NULL) imgSetStatus(img, STATUS_FAULT);
154 if(verbose>0) fprintf(stderr, "Error: invalid IMG argument\n");
155 return(STATUS_FAULT);
156 }
157 if(filename==NULL || !filename[0]) {
158 imgSetStatus(img, STATUS_FAULT);
159 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
160 return(STATUS_FAULT);
161 }
162 imgSetStatus(img, STATUS_OK);
163
164 /* Extract the base file name without extensions */
165 strcpy(basefile, filename); niftiRemoveFNameExtension(basefile);
166 if(strlen(basefile)<1) {
167 imgSetStatus(img, STATUS_FAULT);
168 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
169 return(STATUS_FAULT);
170 }
171
172 /* Make the image and header filenames, and read Nifti header */
173 ret=niftiExists(basefile, hdrfile, datfile, siffile, &dsr, verbose-2, tmp);
174 if(ret==0) {
175 imgSetStatus(img, STATUS_NOFILE);
176 if(verbose>0) fprintf(stderr, "Error: %s\n", tmp);
177 return(STATUS_NOFILE);
178 }
179 if(ret==1 && verbose>1) printf("no SIF found for %s\n", basefile);
180
181 /* and set IMG contents */
182 ret=imgGetNiftiHeader(img, &dsr, verbose-2);
183 if(ret!=0) {
184 imgSetStatus(img, ret);
185 return(ret);
186 }
187
188 /* If SIF does not exist, then that's it */
189 if(!siffile[0]) {
190 imgSetStatus(img, STATUS_OK);
191 return STATUS_OK;
192 }
193
194 /* SIF is available, so read that too */
195 if(verbose>1) {printf("reading SIF %s\n", siffile); fflush(stdout);}
196 sifInit(&sif); ret=0;
197 if(sifRead(siffile, &sif)!=0) return STATUS_OK;
198 /* Copy scan time */
199 img->scanStart=sif.scantime;
200 /* Study number, if not yet defined */
201 if(!img->studyNr[0] && strlen(sif.studynr)>1 )
203 /* Isotope half-life, if not yet defined */
205 if(img->isotopeHalflife<=0.0 && f>0.0) img->isotopeHalflife=60.0*f;
206 sifEmpty(&sif);
207
208 return(STATUS_OK);
209}
210/*****************************************************************************/
211
212/*****************************************************************************/
220 IMG *img,
222 NIFTI_DSR *dsr,
224 int verbose
225) {
226 if(verbose>0) {printf("imgGetNiftiHeader()\n"); fflush(stdout);}
227
228 /* Check the input */
229 if(img==NULL) return STATUS_FAULT;
231 return STATUS_FAULT;
232 imgSetStatus(img, STATUS_FAULT);
233 if(dsr==NULL) return STATUS_FAULT;
234
235 imgSetStatus(img, STATUS_INVALIDHEADER);
236
237 /* Get the image dimensions from header */
238 int dimNr=dsr->h.dim[0];
239 if(dimNr<2 || dimNr>4) {
240 if(verbose>0)
241 fprintf(stderr, "Error: Nifti image dimension %d is not supported\n", dimNr);
242 return STATUS_UNSUPPORTED;
243 }
244 int dimx, dimy, dimz=1, dimt=1;
245 dimx=dsr->h.dim[1]; dimy=dsr->h.dim[2];
246 if(dimNr>2) {dimz=dsr->h.dim[3]; if(dimNr>3) dimt=dsr->h.dim[4];}
247 long long pxlNr=dimx*dimy*dimz;
248 if(pxlNr<1) {
249 if(verbose>0) fprintf(stderr, "Error: invalid Nifti image dimensions.\n");
250 return STATUS_INVALIDHEADER;
251 }
252 img->dimx=dimx; img->dimy=dimy; img->dimz=dimz; img->dimt=dimt;
253
254 /* Copy information from header */
255 img->type=IMG_TYPE_IMAGE;
256 strcpy(img->studyNr, "");
257 strcpy(img->patientName, "");
258 /* NIfTI file format */
259 if(strcmp(dsr->h.magic, "ni1")==0) img->_fileFormat=IMG_NIFTI_1D;
260 else if(strcmp(dsr->h.magic, "n+1")==0) img->_fileFormat=IMG_NIFTI_1S;
261 else {
262 if(verbose>0) fprintf(stderr, "Error: invalid Nifti magic number.\n");
263 return STATUS_INVALIDHEADER;
264 }
265 /* NIfTI datatype is not needed, because currently saved as floats anyway */
266 //img->_dataType=dsr->h.datatype;
267 /* Pixel x,y,z sizes, converting units if necessary */
268 float f=1.0;
269 if(dsr->h.xyzt_units & NIFTI_UNITS_METER) f=1000.;
270 else if(dsr->h.xyzt_units & NIFTI_UNITS_MICRON) f=0.001;
271 else if(dsr->h.xyzt_units & NIFTI_UNITS_MM) f=1.0;
272 if(verbose>2) printf("pixel size conversion factor := %g\n", f);
273 for(int i=1; i<=3; i++) {
274 if(i==1) img->sizex=f*dsr->h.pixdim[i];
275 else if(i==2) img->sizey=f*dsr->h.pixdim[i];
276 else if(i==3) img->sizez=f*dsr->h.pixdim[i];
277 }
278 /* Orientation, quaternion, and transformation parameters */
279 img->xform[0]=dsr->h.qform_code;
280 img->xform[1]=dsr->h.sform_code;
281 img->quatern[0]=dsr->h.quatern_b;
282 img->quatern[1]=dsr->h.quatern_c;
283 img->quatern[2]=dsr->h.quatern_d;
284 img->quatern[3]=dsr->h.qoffset_x;
285 img->quatern[4]=dsr->h.qoffset_y;
286 img->quatern[5]=dsr->h.qoffset_z;
287 for(int i=0; i<4; i++) img->quatern[6+i]=dsr->h.srow_x[i];
288 for(int i=0; i<4; i++) img->quatern[10+i]=dsr->h.srow_y[i];
289 for(int i=0; i<4; i++) img->quatern[14+i]=dsr->h.srow_z[i];
290
291 /* Assumptions */
293
294 imgSetStatus(img, STATUS_OK);
295 return STATUS_OK;
296}
297/*****************************************************************************/
298
299/*****************************************************************************/
318 const char *filename,
320 int frame_to_read,
322 IMG *img,
324 int frame_index,
326 int verbose
327) {
328 char basefile[FILENAME_MAX], tmp[256];
329 char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
330 NIFTI_DSR dsr;
331 int ret;
332 SIF sif;
333 FILE *fp;
334 float *fdata=NULL, *fptr;
335
336
337 if(verbose>0) {
338 printf("\nimgReadNiftiFrame(%s, %d, *img, %d, %d)\n",
339 filename, frame_to_read, frame_index, verbose);
340 fflush(stdout);
341 }
342
343 /* Check the input */
344 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) {
345 if(img!=NULL) imgSetStatus(img, STATUS_FAULT);
346 if(verbose>0) fprintf(stderr, "Error: invalid IMG argument\n");
347 return(STATUS_FAULT);
348 }
349 if(filename==NULL || !filename[0]) {
350 imgSetStatus(img, STATUS_FAULT);
351 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
352 return(STATUS_FAULT);
353 }
354 if(frame_index<0 || frame_index>img->dimt-1 || frame_to_read<1) {
355 imgSetStatus(img, STATUS_FAULT);
356 if(verbose>0) fprintf(stderr, "Error: invalid frame settings\n");
357 return STATUS_FAULT;
358 }
359
360 /* Extract the base file name without extensions */
361 strcpy(basefile, filename); niftiRemoveFNameExtension(basefile);
362 if(strlen(basefile)<1) {
363 imgSetStatus(img, STATUS_FAULT);
364 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
365 return(STATUS_FAULT);
366 }
367
368 /* Make the image and header filenames, and read Nifti header */
369 ret=niftiExists(basefile, hdrfile, datfile, siffile, &dsr, verbose-2, tmp);
370 if(ret==0) {
371 imgSetStatus(img, STATUS_NOFILE);
372 if(verbose>0) fprintf(stderr, "Error: %s\n", tmp);
373 return(STATUS_NOFILE);
374 }
375 if(ret==1 && verbose>1) {
376 printf("no SIF found for %s\n", basefile); fflush(stdout);}
377
378 /* Open image datafile */
379 if(verbose>2) {fprintf(stdout, "reading image data %s\n", datfile); fflush(stdout);}
380 if((fp=fopen(datfile, "rb")) == NULL) {
381 imgSetStatus(img, STATUS_NOIMGDATAFILE);
382 return STATUS_NOIMGDATAFILE;
383 }
384
385 /* Allocate memory for one image frame */
386 imgSetStatus(img, STATUS_NOMEMORY);
387 fdata=calloc((size_t)img->dimx*img->dimy*img->dimz, sizeof(float));
388 if(fdata==NULL) {fclose(fp); return STATUS_NOMEMORY;}
389
390 /* Read the required image frame */
391 fptr=fdata;
392 ret=niftiReadImagedata(fp, &dsr, frame_to_read, fptr, verbose-1, tmp);
393 if(verbose>1) printf("niftiReadImagedata() -> %s\n", tmp);
394 fclose(fp);
395 if(ret==-1) { /* no more frames */
396 free(fdata); imgSetStatus(img, STATUS_NOMATRIX);
397 return STATUS_NOMATRIX;
398 }
399 if(ret!=0) {
400 free(fdata); imgSetStatus(img, STATUS_UNSUPPORTED);
401 return STATUS_UNSUPPORTED;
402 }
403
404 if(0) { // Call imgNaNs(IMG, 1) instead
405 /* Check for invalid pixel values and set to zero.
406 SPM can write lots of NaNs on image borders.
407 Remove this later, if/when all image processing functions support NaN and Inf. */
408 long long int goodNr=0;
409 fptr=fdata;
410 for(int zi=0; zi<img->dimz; zi++)
411 for(int yi=0; yi<img->dimy; yi++)
412 for(int xi=0; xi<img->dimx; xi++) {
413 if(isfinite(*fptr)) goodNr++; else *fptr=0.0;
414 fptr++;
415 }
416 if(goodNr==0) {
417 free(fdata);
418 imgSetStatus(img, STATUS_NOIMGDATA);
419 return STATUS_NOIMGDATA;
420 }
421 }
422
423 /* Copy pixel values to IMG */
424 fptr=fdata;
425 for(int zi=0; zi<img->dimz; zi++)
426 for(int yi=0; yi<img->dimy; yi++)
427 for(int xi=0; xi<img->dimx; xi++)
428 img->m[zi][yi][xi][frame_index]=*fptr++;
429 free(fdata);
430
431 /* Set decay correction factor to zero */
432 img->decayCorrFactor[frame_index]=0.0;
433
434 /* Set plane numbers */
435 for(int fi=0; fi<img->dimz; fi++) img->planeNumber[fi]=fi+1;
436
437 /*
438 * Try to read frame time information from SIF file
439 */
440 imgSetStatus(img, STATUS_OK); /* If the rest is failed, no problem */
441 sifInit(&sif);
442 if(sifRead(siffile, &sif)!=0) {
443 if(verbose>1) {fprintf(stdout, " cannot read SIF (%s)\n", siffile); fflush(stdout);}
444 return STATUS_OK;
445 }
446 /* Frame information */
447 if(verbose>3) {fprintf(stdout, " setting frame times\n"); fflush(stdout);}
448 if(sif.frameNr>=frame_to_read) {
449 img->start[frame_index]=sif.x1[frame_to_read-1];
450 img->end[frame_index]=sif.x2[frame_to_read-1];
451 img->mid[frame_index]=0.5*(img->start[frame_index]+img->end[frame_index]);
452 img->prompts[frame_index]=sif.prompts[frame_to_read-1];
453 img->randoms[frame_index]=sif.randoms[frame_to_read-1];
454 }
455 sifEmpty(&sif);
456
457 imgSetStatus(img, STATUS_OK);
458 return STATUS_OK;
459}
460/*****************************************************************************/
461
462/*****************************************************************************/
473 IMG *img,
475 const char *dbname,
477 NIFTI_DSR *dsr,
479 float fmin,
481 float fmax,
483 int verbose
484) {
485 if(verbose>0) {
486 printf("\nimgSetNiftiHeader(*img, %s, *dsr, %g, %g, ...)\n", dbname, fmin, fmax);
487 fflush(stdout);
488 }
489 /* Check the input */
490 if(dbname==NULL || !dbname[0]) {
491 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
492 return(STATUS_FAULT);
493 }
494 if(img==NULL || (img->status!=IMG_STATUS_INITIALIZED && img->status!=IMG_STATUS_OCCUPIED)) {
495 if(verbose>0) fprintf(stderr, "Error: invalid IMG argument\n");
496 return(STATUS_FAULT);
497 }
498 if(dsr==NULL) {
499 if(verbose>0) fprintf(stderr, "Error: invalid header struct\n");
500 return STATUS_FAULT;
501 }
502
503 /* Set NIfTI byte order to current machines byte order */
505
506 /* Initiate header struct with zeroes */
507 memset(&dsr->h, 0, sizeof(NIFTI_1_HEADER));
508 memset(&dsr->e, 0, sizeof(NIFTI_EXTENDER));
509
510 /* Set header */
512 strcpy(dsr->h.data_type, "");
513 char *cptr=strrchr(dbname, '/'); if(cptr==NULL) cptr=strrchr(dbname, '\\');
514 if(cptr!=NULL) cptr++;
515 if(cptr==NULL) cptr=(char*)dbname;
516 strncpy(dsr->h.db_name, cptr, 17);
517 dsr->h.extents=16384; // not used in NIfTI, but required for Analyze compatibility
518 dsr->h.regular='r'; // not used in NIfTI, but required for Analyze compatibility
519 dsr->h.dim_info='\0'; // MRI slice ordering
520
521 /* Image dimension */
522 for(int i=0; i<8; i++) dsr->h.dim[i]=1;
523 dsr->h.dim[0]=4;
524 dsr->h.dim[1]=img->dimx;
525 dsr->h.dim[2]=img->dimy;
526 dsr->h.dim[3]=img->dimz;
527 dsr->h.dim[4]=img->dimt;
528 dsr->h.intent_p1=0.0;
529 dsr->h.intent_p2=0.0;
530 dsr->h.intent_p3=0.0;
532 dsr->h.datatype=NIFTI_DT_FLOAT; // data as floats, so no need to scale
533 dsr->h.bitpix=32;
534 dsr->h.slice_start=0;
535 for(int i=0; i<8; i++) dsr->h.pixdim[i]=0.0;
536 // https://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/qsform.html
537 dsr->h.pixdim[0]=1.0; // Set to either 1.0 or -1.0
538 dsr->h.pixdim[1]=img->sizex;
539 dsr->h.pixdim[2]=img->sizey;
540 dsr->h.pixdim[3]=img->sizez;
541 if(img->_fileFormat==IMG_NIFTI_1D)
542 dsr->h.vox_offset=0;
543 else
544 dsr->h.vox_offset=352;
545 dsr->h.scl_slope=1.0; // data as floats, so no need to scale
546 dsr->h.scl_inter=0.0; // data as floats, so no need to scale
547 dsr->h.slice_end=0;
548 dsr->h.slice_code=0;
550 dsr->h.cal_max=fmax;
551 dsr->h.cal_min=0.0; // scale display colours to have black at zero
552 dsr->h.slice_duration=0.0;
553 dsr->h.toffset=0.0;
554 dsr->h.glmax=fmax; // unused in NIfTI
555 dsr->h.glmin=fmin; // unused in NIfTI
556
557 strlcpy(dsr->h.descrip, img->studyNr, 80);
558 strcpy(dsr->h.aux_file, "");
559
560 dsr->h.qform_code=img->xform[0];
561 dsr->h.sform_code=img->xform[1];
562 dsr->h.quatern_b=img->quatern[0];
563 dsr->h.quatern_c=img->quatern[1];
564 dsr->h.quatern_d=img->quatern[2];
565 dsr->h.qoffset_x=img->quatern[3];
566 dsr->h.qoffset_y=img->quatern[4];
567 dsr->h.qoffset_z=img->quatern[5];
568 for(int i=0; i<4; i++) dsr->h.srow_x[i]=img->quatern[6+i];
569 for(int i=0; i<4; i++) dsr->h.srow_y[i]=img->quatern[10+i];
570 for(int i=0; i<4; i++) dsr->h.srow_z[i]=img->quatern[14+i];
571 strcpy(dsr->h.intent_name, "");
572
573 if(img->_fileFormat==IMG_NIFTI_1D) strcpy(dsr->h.magic, "ni1");
574 else strcpy(dsr->h.magic, "n+1");
575
576 /* Extension is left as 0 0 0 0 */
577
578 return STATUS_OK;
579}
580/*****************************************************************************/
581
582/*****************************************************************************/
598 const char *dbname,
604 int frame_to_write,
606 IMG *img,
608 int frame_index,
611 float fmin,
614 float fmax,
616 int verbose
617) {
618 IMG test_img;
619 NIFTI_DSR dsr;
620 int ret=0, fileis=0;
621 char imgfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
622 char tmp[256];
623 FILE *fp;
624 float *fdata=NULL, *fptr;
625
626
627 if(verbose>0) {
628 printf("\nimgWriteNiftiFrame(%s, %d, *img, %d, %g, %g, ...)\n",
629 dbname, frame_to_write, frame_index, fmin, fmax);
630 fflush(stdout);
631 }
632 /*
633 * Check the input
634 */
635 if(dbname==NULL || !dbname[0]) {
636 imgSetStatus(img, STATUS_FAULT);
637 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
638 return(STATUS_FAULT);
639 }
640 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) {
641 if(img!=NULL) imgSetStatus(img, STATUS_FAULT);
642 if(verbose>0) fprintf(stderr, "Error: invalid IMG argument\n");
643 return(STATUS_FAULT);
644 }
645 if(frame_index<0 || frame_index>img->dimt-1 || frame_to_write<0) {
646 imgSetStatus(img, STATUS_FAULT);
647 if(verbose>0) fprintf(stderr, "Error: invalid frame settings\n");
648 return STATUS_FAULT;
649 }
651 imgSetStatus(img, STATUS_FAULT);
652 if(verbose>0) fprintf(stderr, "Error: invalid file format setting\n");
653 return STATUS_FAULT;
654 }
655
656 /*
657 * If NIfTI does not exist, then create it with new header,
658 * and if it does exist, then read and check header information.
659 * Create or edit header to contain correct frame nr.
660 * Determine the global scaling factors.
661 */
662 imgInit(&test_img);
663 fileis=niftiExists(dbname, hdrfile, imgfile, siffile, &dsr, verbose-2, NULL);
664 if(fileis==0) { // not existing
665 if(verbose>1) {
666 printf(" writing 1st frame to a new file\n"); fflush(stdout);}
667
668 /* Create database filenames */
669 niftiCreateFNames(dbname, hdrfile, imgfile, siffile, img->_fileFormat);
670
671 /* Set main header */
672 ret=imgSetNiftiHeader(img, dbname, &dsr, fmin, fmax, verbose-1);
673 if(ret!=0) {
674 if(verbose>0) fprintf(stderr, "Error: cannot read NIfTI header\n");
675 return STATUS_INVALIDHEADER;
676 }
677 if(frame_to_write==0) frame_to_write=1;
678 dsr.h.dim[4]=1;
679
680 /* Write NIfTI header */
681 ret=niftiWriteHeader(hdrfile, &dsr, verbose-1, tmp);
682 if(ret!=0) {
683 if(verbose>0) fprintf(stderr, "Error in niftiWriteHeader(): %s\n", tmp);
684 return STATUS_CANTWRITEHEADERFILE;
685 }
686
687 /* Remove dual format datafile if necessary */
688 if(img->_fileFormat==IMG_NIFTI_1D)
689 if(access(imgfile, 0) != -1) {
690 if(verbose>0) printf(" removing %s\n", imgfile);
691 remove(imgfile);
692 }
693
694 } else { /* NIfTI exists */
695 if(verbose>1) printf(" adding frame to an existing file\n");
696
697 /* Read header information for checking */
698 ret=imgGetNiftiHeader(&test_img, &dsr, verbose-1);
699 if(ret!=0) {
700 if(verbose>0) fprintf(stderr, "Error: cannot read NIfTI header\n");
701 imgEmpty(&test_img); return ret;
702 }
703 /* Check that file format is the same */
704 if(img->_fileFormat!=test_img._fileFormat) {
705 if(verbose>0) {
706 fprintf(stderr, "Error: different file format\n");
707 printf(" new._fileFormat:=%d\n", img->_fileFormat);
708 printf(" prev._fileFormat:=%d\n", test_img._fileFormat);
709 }
710 imgEmpty(&test_img); return STATUS_WRONGFILETYPE;
711 }
712 /* Check also data type, if available */
713 if(img->_dataType>0 && test_img._dataType>0 &&
714 img->_dataType!=test_img._dataType)
715 {
716 if(verbose>0) {
717 fprintf(stderr, "Error: different datatype\n");
718 printf(" new._dataType:=%d\n", img->_dataType);
719 printf(" prev._dataType:=%d\n", test_img._dataType);
720 }
721 imgEmpty(&test_img); return STATUS_WRONGFILETYPE;
722 }
723 /* Check that matrix sizes are the same */
724 if(img->dimz!=test_img.dimz || img->dimx!=test_img.dimx ||
725 img->dimy!=test_img.dimy) {
726 if(verbose>0) fprintf(stderr, "Error: different matrix size\n");
727 imgEmpty(&test_img); return STATUS_VARMATSIZE;}
728 imgEmpty(&test_img);
729
730 /* Set new frame number in NIfTI header */
731 if(frame_to_write==0) frame_to_write=dsr.h.dim[4]+1;
732 if(dsr.h.dim[4]<frame_to_write) {
733 if(dsr.h.dim[4]+1<frame_to_write) {
734 if(verbose>0) fprintf(stderr, "Error: missing matrix\n");
735 return STATUS_MISSINGMATRIX;
736 }
737 dsr.h.dim[4]=frame_to_write;
738 }
739 /* and save the updated header */
740 if((ret=niftiWriteHeader(hdrfile, &dsr, verbose-1, tmp))!=0) {
741 if(verbose>0) fprintf(stderr, "Error: %s.\n", tmp);
742 return STATUS_NOWRITEPERM;
743 }
744 }
745 if(verbose>2) {
746 printf("frame_to_write := %d\n", frame_to_write);
747 printf("vox_offset := %d\n", (int)dsr.h.vox_offset);
748 printf("hdrfile := %s\n", hdrfile);
749 printf("imgfile := %s\n", imgfile);
750 printf("siffile := %s\n", siffile);
751 printf("magic := %s\n", dsr.h.magic);
752 }
753
754 /* Open voxel data file, not removing possible old contents like header */
755 if(img->_fileFormat==IMG_NIFTI_1D && frame_to_write==1)
756 fp=fopen(imgfile, "wb");
757 else
758 fp=fopen(imgfile, "r+b");
759 if(fp==NULL) {
760 if(verbose>0) fprintf(stderr, "Error: cannot open %s for write.\n",imgfile);
761 return STATUS_CANTWRITEIMGFILE;
762 }
763
764 /* Move file pointer to the place of current frame */
765 long long voxNr=img->dimz*img->dimy*img->dimx;
766 if(fseeko(fp, (int)dsr.h.vox_offset+(frame_to_write-1)*voxNr*sizeof(float),
767 SEEK_SET)!=0)
768 {
769 if(verbose>0) fprintf(stderr, "Error: invalid file write position.\n");
770 fclose(fp); return STATUS_MISSINGMATRIX;
771 }
772
773 /* Allocate memory for matrix float data (one plane) */
774 fdata=(float*)calloc(voxNr, sizeof(float));
775 if(fdata==NULL) {
776 if(verbose>0) fprintf(stderr, "Error: out of memory.\n");
777 fclose(fp); return STATUS_NOMEMORY;
778 }
779
780 /* Write voxel values as floats */
781 fptr=fdata;
782 for(int zi=0; zi<img->dimz; zi++)
783 for(int yi=0; yi<img->dimy; yi++)
784 for(int xi=0; xi<img->dimx; xi++, fptr++)
785 *fptr=img->m[zi][yi][xi][frame_index];
786 fptr=fdata;
787 if(fwrite(fptr, sizeof(float), voxNr, fp) != (unsigned int)voxNr) {
788 if(verbose>0) fprintf(stderr, "Error: disk full or no write permission.\n");
789 free(fdata); fclose(fp); return STATUS_CANTWRITEIMGFILE;
790 }
791 free(fdata);
792 fclose(fp);
793
794 return STATUS_OK;
795}
796/*****************************************************************************/
797
798/*****************************************************************************/
813 const char *dbname,
815 IMG *img,
817 int save_sif,
819 int verbose
820) {
821 int ret;
822 char imgfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
823 float fmin, fmax;
824 SIF sif;
825
826 if(verbose>0) {
827 printf("imgWriteNifti(%s, *img, %d, ...)\n", dbname, save_sif);
828 fflush(stdout);
829 }
830
831 /*
832 * Check the input
833 */
834 if(dbname==NULL || !dbname[0]) {
835 imgSetStatus(img, STATUS_FAULT);
836 if(verbose>0) fprintf(stderr, "Error: invalid filename\n");
837 return(STATUS_FAULT);
838 }
839 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) {
840 if(img!=NULL) imgSetStatus(img, STATUS_FAULT);
841 if(verbose>0) fprintf(stderr, "Error: invalid IMG argument\n");
842 return(STATUS_FAULT);
843 }
845 imgSetStatus(img, STATUS_FAULT);
846 if(verbose>0) fprintf(stderr, "Error: invalid file format setting\n");
847 return STATUS_FAULT;
848 }
849
850 /* Create the NIfTI filename(s) */
851 ret=niftiCreateFNames(dbname, hdrfile, imgfile, siffile, img->_fileFormat);
852 if(ret!=0) {
853 if(verbose>0) fprintf(stderr, " Error: invalid NIfTI name %s\n", dbname);
854 imgSetStatus(img, STATUS_FAULT);
855 return STATUS_FAULT;
856 }
857 /* Delete previous NIfTI */
858 ret=niftiRemove(dbname, 0, verbose-1);
859 if(ret!=0) {
860 if(verbose>0) fprintf(stderr, " Error: cannot delete previous NIfTI.\n");
861 imgSetStatus(img, STATUS_CANNOTERASE);
862 return STATUS_CANNOTERASE;
863 }
864
865 /*
866 * Get the global min and max pixel values;
867 * those are currently only saved in header, but may be later
868 * needed for scaling pixels to short ints
869 */
870 if(verbose>1) {fprintf(stdout, " searching min and max\n"); fflush(stdout);}
871 ret=imgMinMax(img, &fmin, &fmax);
872 if(ret) {
873 if(verbose>0) fprintf(stderr, " Error: %s\n", imgStatus(ret));
874 imgSetStatus(img, STATUS_NOIMGDATA);
875 return STATUS_NOIMGDATA;
876 }
877 if(verbose>1) {
878 printf(" global_min := %g\n global_max := %g\n", fmin, fmax);
879 fflush(stdout);
880 }
881 /*
882 * Write the image frames
883 */
884 for(int fi=0, ret=0; fi<img->dimt; fi++) {
885 ret=imgWriteNiftiFrame(dbname, fi+1, img, fi, fmin, fmax, verbose-2);
886 if(ret!=STATUS_OK) break;
887 if(verbose>4) {printf(" frame written.\n"); fflush(stdout);}
888 } // next frame
889 //printf("ret := %d\n", ret);
890 if(ret!=STATUS_OK) {
891 niftiRemove(dbname, img->_fileFormat, verbose-3);
892 if(verbose>0) fprintf(stderr, "Error: %s.\n", imgStatus(ret));
893 return ret;
894 }
895
896 /* If SIF is not needed, then that's it */
897 if(save_sif==0) {
898 imgSetStatus(img, STATUS_OK);
899 return 0;
900 }
901
902 /* Copy contents from IMG to SIF and save SIF */
903 sifInit(&sif);
904 /* Try to read existing SIF */
905 ret=sifRead(siffile, &sif);
906 if(ret==0) { // SIF could be read
907 if(sif.frameNr==img->dimt) {
908 /* If size matches, then update the contents, but keep counts, in case
909 previous SIF comes with actual count info from scanner */
910 ret=img2sif(img, &sif, 1, 1, 0, verbose-3);
911 } else {
912 /* otherwise create SIF contents */
913 ret=img2sif(img, &sif, 1, 1, 2, verbose-3);
914 }
915 } else {
916 /* otherwise create SIF contents */
917 ret=img2sif(img, &sif, 1, 1, 2, verbose-3);
918 }
919 if(ret!=0) {
920 if(verbose>0) fprintf(stderr, " Error: cannot create SIF contents.\n");
921 imgSetStatus(img, STATUS_CANNOTWRITE);
922 sifEmpty(&sif);
923 return STATUS_CANNOTWRITE;
924 }
925 /* Write SIF */
926 ret=sifWrite(&sif, siffile);
927 if(ret!=0) {
928 if(verbose>0) fprintf(stderr, " Error: cannot write %s\n", siffile);
929 imgSetStatus(img, STATUS_CANNOTWRITE);
930 sifEmpty(&sif);
931 return STATUS_CANNOTWRITE;
932 }
933 sifEmpty(&sif);
934
935 imgSetStatus(img, STATUS_OK);
936 return 0;
937}
938/*****************************************************************************/
939
940/*****************************************************************************/
double hlFromIsotope(char *isocode)
Definition halflife.c:55
void imgInfo(IMG *image)
Definition img.c:359
char * imgStatus(int status_index)
Definition img.c:330
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 imgSetNiftiHeader(IMG *img, const char *dbname, NIFTI_DSR *dsr, float fmin, float fmax, int verbose)
Definition img_nii.c:471
int imgReadNiftiFirstFrame(const char *filename, IMG *img, int verbose)
Definition img_nii.c:78
int imgReadNiftiHeader(const char *filename, IMG *img, int verbose)
Definition img_nii.c:134
int imgReadNifti(const char *filename, IMG *img, int verbose)
Definition img_nii.c:23
int imgReadNiftiFrame(const char *filename, int frame_to_read, IMG *img, int frame_index, int verbose)
Definition img_nii.c:311
int imgWriteNiftiFrame(const char *dbname, int frame_to_write, IMG *img, int frame_index, float fmin, float fmax, int verbose)
Definition img_nii.c:594
int imgWriteNifti(const char *dbname, IMG *img, int save_sif, int verbose)
Definition img_nii.c:811
int imgGetNiftiHeader(IMG *img, NIFTI_DSR *dsr, int verbose)
Definition img_nii.c:218
int img2sif(IMG *img, SIF *sif, int copy_header, int copy_frames, int copy_counts, int verbose)
Definition img_sif.c:71
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Definition imgminmax.c:154
Header file for libtpcimgio.
int sifWrite(SIF *data, char *filename)
Definition sifio.c:145
#define IMG_STATUS_OCCUPIED
#define IMG_NIFTI_1S
int niftiWriteHeader(char *filename, NIFTI_DSR *dsr, int verbose, char *status)
Definition nifti.c:844
#define NIFTI_DT_FLOAT
int niftiCreateFNames(const char *filename, char *hdrfile, char *imgfile, char *siffile, int fileformat)
Definition nifti.c:44
#define IMG_DC_CORRECTED
#define NIFTI_UNITS_METER
void niftiRemoveFNameExtension(char *fname)
Definition nifti.c:23
void sifInit(SIF *data)
Definition sif.c:17
int niftiReadImagedata(FILE *fp, NIFTI_DSR *h, int frame, float *data, int verbose, char *status)
Definition nifti.c:619
#define IMG_STATUS_INITIALIZED
int niftiExists(const char *dbname, char *hdrfile, char *imgile, char *siffile, NIFTI_DSR *header, int verbose, char *status)
Definition nifti.c:160
#define NIFTI_UNITS_MICRON
#define NIFTI_HEADER_SIZE
#define IMG_NIFTI_1D
#define NIFTI_INTENT_NONE
void sifEmpty(SIF *data)
Definition sif.c:33
int niftiRemove(const char *dbname, int fileformat, int verbose)
Definition nifti.c:100
#define NIFTI_UNITS_SEC
#define NIFTI_UNITS_MM
int sifRead(char *filename, SIF *data)
Definition sifio.c:21
#define IMG_TYPE_IMAGE
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
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 _dataType
int * planeNumber
float sizey
float * start
unsigned short int dimz
unsigned short int dimy
float * end
float quatern[18]
float * decayCorrFactor
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float * randoms
float * mid
float sizez
short int qform_code
short int slice_start
short int slice_end
short int datatype
char aux_file[24]
char intent_name[16]
short int bitpix
char data_type[10]
short int sform_code
short int dim[8]
short int intent_code
NIFTI_1_HEADER h
NIFTI_EXTENDER e
double * x1
double * prompts
int frameNr
double * x2
char studynr[MAX_STUDYNR_LEN+1]
time_t scantime
char isotope_name[8]
double * randoms