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

I/O routines for IMG data from/to Analyze 7.5 format. More...

#include "libtpcimgio.h"

Go to the source code of this file.

Functions

int imgReadAnalyze (const char *dbname, IMG *img)
int imgWriteAnalyze (const char *dbname, IMG *img)
int imgReadAnalyzeHeader (const char *dbname, IMG *img)
int imgGetAnalyzeHeader (IMG *img, ANALYZE_DSR *h)
int imgSetAnalyzeHeader (IMG *img, const char *dbname, ANALYZE_DSR *dsr, float fmin, float fmax)
int imgReadAnalyzeFirstFrame (const char *fname, IMG *img)
int imgReadAnalyzeFrame (const char *fname, int frame_to_read, IMG *img, int frame_index)
int imgWriteAnalyzeFrame (const char *dbname, int frame_to_write, IMG *img, int frame_index, float fmin, float fmax)

Detailed Description

I/O routines for IMG data from/to Analyze 7.5 format.

Author
Vesa Oikonen

Definition in file img_ana.c.

Function Documentation

◆ imgGetAnalyzeHeader()

int imgGetAnalyzeHeader ( IMG * img,
ANALYZE_DSR * h )

Copy Analyze 7.5 header information into IMG.

Parameters
imgimage structure
hAnalyze header structure
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 427 of file img_ana.c.

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}
int IMG_TEST
Definition img.c:6
void imgSetStatus(IMG *img, int status_index)
Definition img.c:345
#define IMG_STATUS_OCCUPIED
#define IMG_ANA_L
#define IMG_DC_CORRECTED
#define IMG_STATUS_INITIALIZED
#define IMG_DC_NONCORRECTED
#define IMG_ANA
#define IMG_TYPE_IMAGE
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
#define MAX_STUDYNR_LEN
Definition libtpcmisc.h:163
ANALYZE_HEADER_HISTORY hist
ANALYZE_HEADER_IMGDIM dime
float sizex
unsigned short int dimx
char type
char patientName[32]
char decayCorrection
char status
int _fileFormat
unsigned short int dimt
float sizey
unsigned short int dimz
unsigned short int dimy
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float sizez

Referenced by imgReadAnalyzeHeader().

◆ imgReadAnalyze()

int imgReadAnalyze ( const char * dbname,
IMG * img )

Read Analyze 7.5 image.

Analyze database name must be given with path. Image and header files with .img and .hdr extensions must exist. Also SIF file with .sif extension is used, if it exists. anaFlipping() determines whether image is flipped in z-direction; image is always flipped in x,y-directions.

Parameters
dbnameAnalyze database name with path, with or without extension
imgPointer to initialized IMG structure
Returns
0 if ok, and otherwise IMG status code; sets IMG->statmsg in case of error.

Definition at line 24 of file img_ana.c.

24 {
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}
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 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
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
int sif2img(SIF *sif, IMG *img, int copy_header, int copy_frames, int copy_counts, int verbose)
Definition img_sif.c:13
#define NIFTI_XFORM_UNKNOWN
void sifInit(SIF *data)
Definition sif.c:17
#define NIFTI_XFORM_SCANNER_ANAT
void sifEmpty(SIF *data)
Definition sif.c:33
int sifRead(char *filename, SIF *data)
Definition sifio.c:21
float **** m
short int xform[2]
int * planeNumber

Referenced by imgRead().

◆ imgReadAnalyzeFirstFrame()

int imgReadAnalyzeFirstFrame ( const char * fname,
IMG * img )

Read the first frame from an Analyze 7.5 database into IMG data structure.

Parameters
fnameName of Analyze database from which IMG contents will be read
imgpointer to the initiated but not preallocated IMG data
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 592 of file img_ana.c.

592 {
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}
void imgInfo(IMG *image)
Definition img.c:359
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

Referenced by imgAnalyzeToEcat().

◆ imgReadAnalyzeFrame()

int imgReadAnalyzeFrame ( const char * fname,
int frame_to_read,
IMG * img,
int frame_index )

Read a specified frame from an Analyze 7.5 database into preallocated IMG data structure.

Analyze database consists of two or three files in the same directory: fname.hdr, fname.img, and optionally fname.sif. IMG header is assumed to be filled correctly before calling this function, except for information concerning separate planes and this frame, which is filled here. If frame does not exist, then and only then STATUS_NOMATRIX is returned.

Parameters
fnamename of Analyze database from which IMG contents will be read
frame_to_readframe which will be read [1..frameNr]
imgpointer to the IMG data. Place for the frame must be preallocated
frame_indexIMG frame index [0..dimt-1] where data will be placed
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 639 of file img_ana.c.

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}
int anaDatabaseExists(const char *dbname, char *hdrfile, char *imgfile, char *siffile)
Definition analyze.c:704
float * prompts
float * start
float * end
float * decayCorrFactor
float * randoms
float * mid
double * x1
double * prompts
int frameNr
double * x2
double * randoms

Referenced by imgAnalyzeToEcat(), imgReadAnalyzeFirstFrame(), and imgReadFrame().

◆ imgReadAnalyzeHeader()

int imgReadAnalyzeHeader ( const char * dbname,
IMG * img )

Fill IMG struct header information from Analyze 7.5 database files.

SIF file is read if available. Information concerning separate frames or planes is not filled though.

Parameters
dbnamename of Analyze database, may contain filename extension
imgpointer to the initiated IMG data
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 360 of file img_ana.c.

360 {
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}
double hlFromIsotope(char *isocode)
Definition halflife.c:55
int imgGetAnalyzeHeader(IMG *img, ANALYZE_DSR *h)
Definition img_ana.c:427
time_t scanStart
char studynr[MAX_STUDYNR_LEN+1]
time_t scantime
char isotope_name[8]

Referenced by imgFormatDetermine(), imgReadAnalyzeFirstFrame(), imgReadHeader(), and imgWriteAnalyzeFrame().

◆ imgSetAnalyzeHeader()

int imgSetAnalyzeHeader ( IMG * img,
const char * dbname,
ANALYZE_DSR * dsr,
float fmin,
float fmax )

Copy header information in IMG struct into Analyze 7.5 header struct.

Min, max, and scale factor are set here and they apply to all frames.

Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.
Parameters
imgpointer to IMG struct from which header information is read
dbnameAnalyze 7.5 database name
dsrpointer to Analyze header struct to be filled
fminminimum pixel value in all frames that will be written
fmaxmaximum pixel value in all frames that will be written

Definition at line 486 of file img_ana.c.

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}
struct tm * gmtime_r(const time_t *t, struct tm *tm)
Convert time_t to GMT struct tm.
Definition datetime.c:22
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Definition imgminmax.c:154
#define ANALYZE_DT_SIGNED_SHORT
Definition libtpcimgio.h:55
int temp_roundf(float e)
Definition petc99.c:20
ANALYZE_HEADER_KEY hk

Referenced by imgWriteAnalyzeFrame().

◆ imgWriteAnalyze()

int imgWriteAnalyze ( const char * dbname,
IMG * img )

Write Analyze 7.5 image.

Analyze database name must be given with path. Path must exist. Image and header files with .img and .hdr extensions are created. Existing files are overwritten. anaFlipping() determines whether image is flipped in z-direction; image is always flipped in x,y-directions. Byte order is determined based on _fileFormat field.

Parameters
dbnameanalyze database name with path, without extension
imgpointer to IMG data
Returns
0 if ok, 1 invalid input, 2 invalid image status (image not occupied), 3 failed to resolve extreme values (min and max), 12 failed to allocate temp memory, 14 failed to open file for writing, 15 failed to write data, 21 failed to write header, and sets IMG->statmsg in case of error

Definition at line 162 of file img_ana.c.

162 {
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}
int anaWriteHeader(char *filename, ANALYZE_DSR *h)
Definition analyze.c:282
int img2sif(IMG *img, SIF *sif, int copy_header, int copy_frames, int copy_counts, int verbose)
Definition img_sif.c:71
int sifWrite(SIF *data, char *filename)
Definition sifio.c:145
void swabip(void *buf, long long int size)
Definition swap.c:72
int little_endian()
Definition swap.c:14

Referenced by imgWrite().

◆ imgWriteAnalyzeFrame()

int imgWriteAnalyzeFrame ( const char * dbname,
int frame_to_write,
IMG * img,
int frame_index,
float fmin,
float fmax )

Write one PET frame from IMG data struct into Analyze 7.5 database file. This function can be called repeatedly to write all frames one at a time to conserve memory. This function does not write SIF.

Parameters
dbnamename of file where IMG contents will be written. If file does not exist, it is created. Make sure to delete existing file, unless you want to add data
frame_to_writePET frame number (1..frameNr) which will be written: If set to 0, frame data will be written to an existing or new PET file as a new frame, never overwriting existing data. If >0, then frame data is written as specified frame number, overwriting any data existing with the same frame number.
imgpointer to the IMG data struct
frame_indexIMG frame index (0..dimt-1) which will be written
fminminimum pixel value in all frames that will be written; used only when writing the first frame
fmaxmaximum pixel value in all frames that will be written; used only when writing the first frame
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 751 of file img_ana.c.

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}
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgSetAnalyzeHeader(IMG *img, const char *dbname, ANALYZE_DSR *dsr, float fmin, float fmax)
Definition img_ana.c:486