TPCCLIB
Loading...
Searching...
No Matches
tpcimage.h File Reference

Header file for libtpcimage. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "tpcextensions.h"
#include "tpcift.h"
#include "tpcisotope.h"
#include "tpctac.h"
#include "tpcecat.h"
#include "tpcdcm.h"
#include "tpcnifti.h"

Go to the source code of this file.

Data Structures

struct  IMG

Enumerations

enum  imgformat {
  IMG_FORMAT_UNKNOWN , IMG_FORMAT_DICOM , IMG_FORMAT_E63 , IMG_FORMAT_E7 ,
  IMG_FORMAT_E7_2D , IMG_FORMAT_POLARMAP , IMG_FORMAT_ANA , IMG_FORMAT_ANA_L ,
  IMG_FORMAT_INTERFILE , IMG_FORMAT_NIFTI_1D , IMG_FORMAT_NIFTI_1S , IMG_FORMAT_NIFTI_2D ,
  IMG_FORMAT_NIFTI_2S , IMG_FORMAT_MICROPET , IMG_FORMAT_FLAT , IMG_FORMAT_LAST
}
enum  imgmodality {
  IMG_MODALITY_UNKNOWN , IMG_MODALITY_PET , IMG_MODALITY_SPECT , IMG_MODALITY_CT ,
  IMG_MODALITY_MRI , IMG_MODALITY_LAST
}
enum  imgcontent {
  IMG_CONTENT_UNKNOWN , IMG_CONTENT_IMAGE , IMG_CONTENT_RAW , IMG_CONTENT_ATTN ,
  IMG_CONTENT_POLARMAP , IMG_CONTENT_LAST
}

Functions

void imgInit (IMG *image)
void imgFree (IMG *image)
int imgAllocate (IMG *img, const unsigned int dimz, const unsigned int dimy, const unsigned int dimx, const unsigned int dimt, TPCSTATUS *status)
char * imgContentDescr (imgcontent c)
char * imgModalityDescr (imgmodality c)
int imgHasData (IMG *img)
int imgHasTimes (IMG *img)
int imgHasCounts (IMG *img)
int imgHasWeights (IMG *img)
void imgContents (IMG *img, FILE *fp)
unsigned long long imgNaNs (IMG *img, int fix)
int imgMinMax (IMG *img, float *minvalue, float *maxvalue)
int imgXRange (IMG *img, double *xmin, double *xmax)
int imgXUnitConvert (IMG *img, const int u)
int imgCopyHeader (IMG *img1, IMG *img2)
int imgFillOHeader (IMG *img, TPCSTATUS *status)
char * imgFormatDescr (imgformat c)
char * imgDefaultExtension (imgformat c)
int imgRead (IMG *img, const char *fname, TPCSTATUS *status)
int imgWrite (IMG *img, const char *fname, TPCSTATUS *status)
imgformat imgFormatFromFName (const char *fname, TPCSTATUS *status)
imgformat imgFormatIdentify (const char *s)
int imgReadDICOM (IMG *img, const char *fname, TPCSTATUS *status)
int imgWriteDICOM (IMG *img, const char *fname, TPCSTATUS *status)
int niftiCreateFNames (const char *filename, char *hdrfile, char *imgfile, char *siffile, int fileformat)
int imgReadNifti (IMG *img, const char *fname, TPCSTATUS *status)
int imgWriteNifti (IMG *img, const char *fname, TPCSTATUS *status)
int imgSetNiftiHeader (IMG *img, NIFTI_DSR *dsr, int verbose)
int imgGetNiftiHeader (IMG *img, NIFTI_DSR *dsr, int verbose)
int imgToSIF (IMG *img, TAC *sif, int copy_header, int copy_frames, int copy_counts, int verbose)
int imgFromSIF (IMG *img, TAC *sif, int copy_header, int copy_frames, int copy_counts, int verbose)
int imgCompareMatrixSize (IMG *d1, IMG *d2)
int imgCompareUnit (IMG *d1, IMG *d2, TPCSTATUS *status)
int imgCompareConc (IMG *d1, IMG *d2, const float test_abs, const float test_rel, TPCSTATUS *status)
int imgCompareTimes (IMG *d1, IMG *d2, const float test_abs, const float test_rel, TPCSTATUS *status)

Detailed Description

Header file for libtpcimage.

Header file for image data processing library libtpcimage.

Author
Vesa Oikonen

Definition in file tpcimage.h.

Enumeration Type Documentation

◆ imgcontent

enum imgcontent

Image data content codes for IMG data structure.

See also
img_content, image.c
Enumerator
IMG_CONTENT_UNKNOWN 

Unknown data content.

IMG_CONTENT_IMAGE 

Image data.

IMG_CONTENT_RAW 

Sinogram, normalization.

IMG_CONTENT_ATTN 

Attenuation data.

IMG_CONTENT_POLARMAP 

Polarmap.

IMG_CONTENT_LAST 

End of list.

Definition at line 70 of file tpcimage.h.

70 {
imgcontent
Definition tpcimage.h:70
@ IMG_CONTENT_LAST
End of list.
Definition tpcimage.h:76
@ IMG_CONTENT_RAW
Sinogram, normalization.
Definition tpcimage.h:73
@ IMG_CONTENT_UNKNOWN
Unknown data content.
Definition tpcimage.h:71
@ IMG_CONTENT_POLARMAP
Polarmap.
Definition tpcimage.h:75
@ IMG_CONTENT_IMAGE
Image data.
Definition tpcimage.h:72
@ IMG_CONTENT_ATTN
Attenuation data.
Definition tpcimage.h:74

◆ imgformat

enum imgformat

Image file format codes for IMG data structure.

See also
img_format, image.c
Enumerator
IMG_FORMAT_UNKNOWN 

Unknown format.

IMG_FORMAT_DICOM 

DICOM.

IMG_FORMAT_E63 

ECAT 6.3.

IMG_FORMAT_E7 

ECAT 7.* 3D.

IMG_FORMAT_E7_2D 

ECAT 7.* 2D.

IMG_FORMAT_POLARMAP 

ECAT polar map.

IMG_FORMAT_ANA 

Analyze big-endian.

IMG_FORMAT_ANA_L 

Analyze little-endian.

IMG_FORMAT_INTERFILE 

Interfile.

IMG_FORMAT_NIFTI_1D 

NIfTI-1 dual-file format.

IMG_FORMAT_NIFTI_1S 

NIfTI-1 single-file format.

IMG_FORMAT_NIFTI_2D 

NIfTI-2 dual-file format.

IMG_FORMAT_NIFTI_2S 

NIfTI-2 single-file format.

IMG_FORMAT_MICROPET 

MicroPET.

IMG_FORMAT_FLAT 

Flat format.

IMG_FORMAT_LAST 

End of list.

Definition at line 32 of file tpcimage.h.

32 {
49} imgformat;
imgformat
Definition tpcimage.h:32
@ IMG_FORMAT_POLARMAP
ECAT polar map.
Definition tpcimage.h:38
@ IMG_FORMAT_E7
ECAT 7.* 3D.
Definition tpcimage.h:36
@ IMG_FORMAT_ANA_L
Analyze little-endian.
Definition tpcimage.h:40
@ IMG_FORMAT_DICOM
DICOM.
Definition tpcimage.h:34
@ IMG_FORMAT_E63
ECAT 6.3.
Definition tpcimage.h:35
@ IMG_FORMAT_INTERFILE
Interfile.
Definition tpcimage.h:41
@ IMG_FORMAT_ANA
Analyze big-endian.
Definition tpcimage.h:39
@ IMG_FORMAT_NIFTI_1D
NIfTI-1 dual-file format.
Definition tpcimage.h:42
@ IMG_FORMAT_NIFTI_2S
NIfTI-2 single-file format.
Definition tpcimage.h:45
@ IMG_FORMAT_UNKNOWN
Unknown format.
Definition tpcimage.h:33
@ IMG_FORMAT_LAST
End of list.
Definition tpcimage.h:48
@ IMG_FORMAT_E7_2D
ECAT 7.* 2D.
Definition tpcimage.h:37
@ IMG_FORMAT_NIFTI_1S
NIfTI-1 single-file format.
Definition tpcimage.h:43
@ IMG_FORMAT_MICROPET
MicroPET.
Definition tpcimage.h:46
@ IMG_FORMAT_FLAT
Flat format.
Definition tpcimage.h:47
@ IMG_FORMAT_NIFTI_2D
NIfTI-2 dual-file format.
Definition tpcimage.h:44

◆ imgmodality

Image modality codes for IMG data structure.

See also
img_modality, image.c
Enumerator
IMG_MODALITY_UNKNOWN 

Unknown modality.

IMG_MODALITY_PET 

PET.

IMG_MODALITY_SPECT 

SPECT.

IMG_MODALITY_CT 

CT.

IMG_MODALITY_MRI 

MRI.

IMG_MODALITY_LAST 

End of list.

Definition at line 56 of file tpcimage.h.

56 {
imgmodality
Definition tpcimage.h:56
@ IMG_MODALITY_MRI
MRI.
Definition tpcimage.h:61
@ IMG_MODALITY_CT
CT.
Definition tpcimage.h:60
@ IMG_MODALITY_SPECT
SPECT.
Definition tpcimage.h:59
@ IMG_MODALITY_LAST
End of list.
Definition tpcimage.h:62
@ IMG_MODALITY_UNKNOWN
Unknown modality.
Definition tpcimage.h:57
@ IMG_MODALITY_PET
PET.
Definition tpcimage.h:58

Function Documentation

◆ imgAllocate()

int imgAllocate ( IMG * img,
const unsigned int dimz,
const unsigned int dimy,
const unsigned int dimx,
const unsigned int dimt,
TPCSTATUS * status )
extern

Allocates memory for image data. Old contents are not saved.

See also
imgInit, imgFree, imgWrite, imgHasData, imgCopyHeader
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to initialized image structure; old contents are deleted.
Precondition
Initialize structure using imgInit() before this.
Parameters
dimzNr of image planes to allocate.
dimyNr of image rows to allocate.
dimxNr of image columns to allocate.
dimtNr of image time frames (samples) to allocate.
statusPointer to status data; enter NULL if not needed.

Definition at line 126 of file image.c.

140 {
141 int verbose=0; if(status!=NULL) verbose=status->verbose;
142 if(verbose>0) {
143 printf("%s(img, %u, %u, %u, %u)\n", __func__, dimz, dimy, dimx, dimt); fflush(stdout);}
144
145 if(img==NULL || dimz<1 || dimy<1 || dimx<1 || dimt<1) {
146 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
147 return(TPCERROR_FAIL);
148 }
149
150 /* Remove any previous contents */
151 imgFree(img);
152
153 /* Memory for frame times */
154 int ret=0; {img->x1=calloc(dimt, sizeof(float)); if(img->x1==NULL) ret++;}
155 if(!ret) {img->x2=calloc(dimt, sizeof(float)); if(img->x2==NULL) ret++;}
156 if(!ret) {img->x=calloc(dimt, sizeof(float)); if(img->x==NULL) ret++;}
157 if(ret) {
158 imgFree(img);
159 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
161 }
162
163 /* Memory for weights */
164 ret=0; {img->weight=calloc(dimt, sizeof(float)); if(img->weight==NULL) ret++;}
165 if(!ret) {img->prompts=calloc(dimt, sizeof(float)); if(img->prompts==NULL) ret++;}
166 if(!ret) {img->randoms=calloc(dimt, sizeof(float)); if(img->randoms==NULL) ret++;}
167 if(ret) {
168 imgFree(img);
169 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
171 }
172
173 /* Memory for pixel matrix */
174 ret=0; {img->_t=(float*)malloc((size_t)dimz*dimy*dimx*dimt*sizeof(float)); if(img->_t==NULL) ret++;}
175 if(!ret) {img->_x=(float**)malloc((size_t)dimz*dimy*dimx*sizeof(float*)); if(img->_x==NULL) ret++;}
176 if(!ret) {img->_y=(float***)malloc((size_t)dimz*dimy*sizeof(float**)); if(img->_y==NULL) ret++;}
177 if(!ret) {img->_z=(float****)malloc((size_t)dimz*sizeof(float***)); if(img->_z==NULL) ret++;}
178 if(ret) {
179 imgFree(img);
180 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
182 }
183 /* Set matrix data pointers */
184 {
185 float ***yptr, **xptr, *tptr;
186 yptr=img->_y; xptr=img->_x; tptr=img->_t;
187 for(unsigned int zi=0; zi<dimz; zi++) {
188 img->_z[zi]=yptr;
189 for(unsigned int yi=0; yi<dimy; yi++) {
190 *yptr++=xptr;
191 for(unsigned int xi=0; xi<dimx; xi++) {
192 *xptr++=tptr; tptr+=dimt;
193 }
194 }
195 }
196 }
197 img->m=img->_z;
198 img->p=img->_t;
199 /* Set all pixel values to zero */
200 for(unsigned int zi=0; zi<dimz; zi++)
201 for(unsigned int yi=0; yi<dimy; yi++)
202 for(unsigned int xi=0; xi<dimx; xi++)
203 for(unsigned int ti=0; ti<dimt; ti++)
204 img->m[zi][yi][xi][ti]=(float)0.0;
205 /* Set matrix dimensions */
206 img->dimz=dimz; img->dimy=dimy; img->dimx=dimx; img->dimt=dimt;
207
208 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
209 return(TPCERROR_OK);
210}
void imgFree(IMG *img)
Definition image.c:107
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
unsigned short int dimx
Definition tpcimage.h:112
float * x1
Definition tpcimage.h:180
float **** m
Definition tpcimage.h:161
float * x2
Definition tpcimage.h:182
float * prompts
Definition tpcimage.h:195
unsigned short int dimt
Definition tpcimage.h:110
float * weight
Definition tpcimage.h:193
unsigned short int dimz
Definition tpcimage.h:116
unsigned short int dimy
Definition tpcimage.h:114
float * p
Definition tpcimage.h:174
float * x
Definition tpcimage.h:184
float * randoms
Definition tpcimage.h:197
int verbose
Verbose level, used by statusPrint() etc.
@ TPCERROR_FAIL
General error.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_OK
No error.

Referenced by imgReadDICOM(), and imgReadNifti().

◆ imgCompareConc()

int imgCompareConc ( IMG * d1,
IMG * d2,
const float test_abs,
const float test_rel,
TPCSTATUS * status )
extern

Check whether IMG pixel concentrations are the same. Note that units are ignored here.

If either absolute or relative difference is below the limit, the test is reported as passed.

See also
tacCompareConc, imgCompareUnit, imgCompareTimes.
Returns
0 in case of match, and >0 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to IMG structure.
d2Pointer to IMG structure.
test_absLimit for accepted absolute difference; obligatory.
test_relOptional limit for accepted relative difference |2*(x1-x2)/(x1+x2)| ; set to negative value to not test this; in case of zero mean, this test is assumed to fail, but test for absolute difference may still pass.
statusPointer to status data; enter NULL if not needed.

Definition at line 79 of file imagecomp.c.

92 {
93 int verbose=0; if(status!=NULL) verbose=status->verbose;
94 if(verbose>1) printf("%s()\n", __func__);
95
96 /* Check that required data exists */
97 if(d1==NULL || d2==NULL || d1->dimz<1 || d2->dimz<1 || d1->dimy<1 || d2->dimy<1
98 || d1->dimx<1 || d2->dimx<1 || d1->dimt<1 || d2->dimt<1) {
99 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
100 return 1;
101 }
102
103 /* Dimensions must match */
104 if(d1->dimz!=d2->dimz || d1->dimy!=d2->dimy || d1->dimx!=d2->dimx || d1->dimt!=d2->dimt) {
105 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
106 if(verbose>0) printf("different IMG dimension.\n");
107 return(2);
108 }
109
110 /* Compare */
111 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
112 for(int zi=0; zi<d1->dimz; zi++)
113 for(int yi=0; yi<d1->dimy; yi++)
114 for(int xi=0; xi<d1->dimx; xi++)
115 for(int ti=0; ti<d1->dimt; ti++) {
116 if(floatMatch(d1->m[zi][yi][xi][ti], d2->m[zi][yi][xi][ti], test_abs)==1)
117 continue;
118 if(test_rel>0.0 && floatMatchRel(d1->m[zi][yi][xi][ti], d2->m[zi][yi][xi][ti], test_rel)==1)
119 continue;
120 if(verbose>0) {
121 float s;
122 s=fabsf(d1->m[zi][yi][xi][ti] - d2->m[zi][yi][xi][ti]);
123 printf("img1.m[%d][%d][%d][%d] := %g\n", zi, yi, xi, ti, d1->m[zi][yi][xi][ti]);
124 printf("img2.m[%d][%d][%d][%d] := %g\n", zi, yi, xi, ti, d2->m[zi][yi][xi][ti]);
125 printf("|diff| := %g\n", s);
126 printf("diff_limit := %g\n", test_abs);
127 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
128 }
129 return(10);
130 }
131 return(0);
132}
int floatMatch(const float v1, const float v2, const float lim)
Definition floatutil.c:27
int floatMatchRel(const float v1, const float v2, const float lim)
Definition floatutil.c:54
@ TPCERROR_NO_DATA
File contains no data.

◆ imgCompareMatrixSize()

int imgCompareMatrixSize ( IMG * d1,
IMG * d2 )
extern

Check whether two IMG data have the same matrix (x,y,z) size.

Returns
0 in case of match, 1 otherwise.
See also
imgCompareConc, imgCompareTimes
Author
Vesa Oikonen
Parameters
d1Pointer to IMG structure.
d2Pointer to IMG structure.

Definition at line 18 of file imagecomp.c.

23 {
24 if(d1==NULL || d2==NULL) return(1);
25 if(d1->dimz!=d2->dimz) return(1);
26 if(d1->dimy!=d2->dimy) return(1);
27 if(d1->dimx!=d2->dimx) return(1);
28 return(0);
29}

◆ imgCompareTimes()

int imgCompareTimes ( IMG * d1,
IMG * d2,
const float test_abs,
const float test_rel,
TPCSTATUS * status )
extern

Check whether IMG frame times (x values) are the same. Note that units are ignored here.

If either absolute or relative difference is below the limit, the test is reported as passed.

See also
tacCompareTimes, imgCompareConc, imgCompareUnit, tacimgXMatch.
Returns
0 in case of match, and >0 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to IMG structure.
d2Pointer to IMG structure.
test_absLimit for accepted absolute difference.
test_relOptional limit for accepted relative difference |2*(x1-x2)/(x1+x2)| ; set to negative value to not test this; in case of zero mean, this test is assumed to fail, but test for absolute difference may still pass.
statusPointer to status data; enter NULL if not needed.

Definition at line 144 of file imagecomp.c.

157 {
158 int verbose=0; if(status!=NULL) verbose=status->verbose;
159 if(verbose>1) printf("%s()\n", __func__);
160
161 /* Check that required data exists */
162 if(d1==NULL || d2==NULL || d1->dimt<1 || d2->dimt<1) {
163 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
164 return 1;
165 }
166
167 /* Frame nr must match */
168 if(d1->dimt!=d2->dimt) {
169 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
170 if(verbose>0) printf("different frame nr.\n");
171 return(3);
172 }
173
174 /* Compare */
175 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
176 for(int fi=0; fi<d1->dimt; fi++) {
177 if(floatMatch(d1->x[fi], d2->x[fi], test_abs)==1)
178 continue;
179 if(floatMatch(d1->x1[fi], d2->x1[fi], test_abs)==1)
180 continue;
181 if(floatMatch(d1->x2[fi], d2->x2[fi], test_abs)==1)
182 continue;
183 if(test_rel>0.0 &&
184 floatMatchRel(d1->x[fi], d2->x[fi], test_rel)==1 &&
185 floatMatchRel(d1->x1[fi], d2->x1[fi], test_rel)==1 &&
186 floatMatchRel(d1->x2[fi], d2->x2[fi], test_rel)==1)
187 continue;
188 if(verbose>0) {
189 printf("img1.x1[%d] := %g\n", fi, d1->x1[fi]);
190 printf("img2.x1[%d] := %g\n", fi, d2->x1[fi]);
191 printf("|diff| := %g\n", fabsf(d1->x1[fi]-d2->x1[fi]));
192 printf("img1.x2[%d] := %g\n", fi, d1->x2[fi]);
193 printf("img2.x2[%d] := %g\n", fi, d2->x2[fi]);
194 printf("|diff| := %g\n", fabsf(d1->x2[fi]-d2->x2[fi]));
195 printf("img1.x[%d] := %g\n", fi, d1->x[fi]);
196 printf("img2.x[%d] := %g\n", fi, d2->x[fi]);
197 printf("|diff| := %g\n", fabsf(d1->x[fi]-d2->x[fi]));
198 printf("diff_limit := %g\n", test_abs);
199 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
200 }
201 return(11);
202 }
203 return(0);
204}

◆ imgCompareUnit()

int imgCompareUnit ( IMG * d1,
IMG * d2,
TPCSTATUS * status )
extern

Check whether time and concentration units are the same in two IMG data.

Returns
0 in case of match, 1 if y (concentration) unit is not matching, 2 if x (time) unit is not matching, and 3 if neither is matching.
See also
tacCompareUnit, imgCompareConc, imgCompareTimes
Author
Vesa Oikonen
Parameters
d1Pointer to IMG structure.
d2Pointer to IMG structure.
statusPointer to status data; enter NULL if not needed

Definition at line 39 of file imagecomp.c.

46 {
47 int verbose=0; if(status!=NULL) verbose=status->verbose;
48 if(verbose>1) printf("%s()\n", __func__);
49
50 /* Check that required data exists */
51 if(d1==NULL || d2==NULL) {
52 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
53 return(3);
54 }
55
56 int ret=0;
57 if(d1->cunit!=d2->cunit) ret+=1;
58 if(d1->tunit!=d2->tunit) ret+=2;
59 if(ret>0 && verbose>0) {
60 printf("img1.cunit := %s\n", unitName(d1->cunit));
61 printf("img2.cunit := %s\n", unitName(d2->cunit));
62 printf("img1.tunit := %s\n", unitName(d1->tunit));
63 printf("img2.tunit := %s\n", unitName(d2->tunit));
64 }
65 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
66 return(ret);
67}
unit cunit
Definition tpcimage.h:203
unit tunit
Definition tpcimage.h:205
char * unitName(int unit_code)
Definition units.c:143

◆ imgContentDescr()

char * imgContentDescr ( imgcontent c)
extern

Return pointer to content type of the image data.

Returns
pointer to the data content type string.
See also
imgdata
Parameters
cIMG content code

Definition at line 51 of file image.c.

54 {
55 if(c<IMG_CONTENT_UNKNOWN || c>=IMG_CONTENT_LAST) return NULL;
56 return (char*)img_content[c];
57}

Referenced by imgContents(), and imgFillOHeader().

◆ imgContents()

void imgContents ( IMG * img,
FILE * fp )
extern

Print general information on the contents of the IMG data structure.

See also
imgInit, imgRead, imgHasData, imgHasTimes
Parameters
imgPointer to IMG structure.
fpFile pointer for output; usually stdout.

Definition at line 293 of file image.c.

298 {
299 if(fp==NULL) return;
300 if(img==NULL) {fprintf(fp, "IMG pointer is NULL\n"); fflush(fp); return;}
301
302 fprintf(fp, "modality: %s\n", imgModalityDescr(img->modality));
303 fprintf(fp, "content: %s\n", imgContentDescr(img->content));
304 fprintf(fp, "format: %s\n", imgFormatDescr(img->format));
306 fprintf(fp, "output_format: %s\n", imgFormatDescr(img->oformat));
307
308 fprintf(fp, "hasData := %d\n", imgHasData(img));
309 fprintf(fp, "hasTimes := %d\n", imgHasTimes(img));
310 fprintf(fp, "hasCounts := %d\n", imgHasCounts(img));
311
312 if(img->scanStart[0]) fprintf(fp, "scanStart: %s\n", img->scanStart);
313
314 fprintf(fp, "dimensions: %u x %u x %u x %u\n", img->dimx, img->dimy, img->dimz, img->dimt);
315 if(img->sizex!=0.0 || img->sizey!=0.0 || img->sizez!=0.0)
316 fprintf(fp, "voxel_size: %g x %g x %g\n", img->sizex, img->sizey, img->sizez);
317 if(img->gapx!=0.0 || img->gapy!=0.0 || img->gapz!=0.0)
318 fprintf(fp, "voxel_gaps: %g x %g x %g\n", img->gapx, img->gapy, img->gapz);
319
320 fprintf(fp, "qform := %d\n", img->xform[0]);
321 fprintf(fp, "sform := %d\n", img->xform[1]);
322 if(floatNonzeroes(img->quatern, 6)>0) {
323 fprintf(fp, "quatern_b := %g\n", img->quatern[0]);
324 fprintf(fp, "quatern_c := %g\n", img->quatern[1]);
325 fprintf(fp, "quatern_d := %g\n", img->quatern[2]);
326 fprintf(fp, "quatern_x_shift := %g\n", img->quatern[3]);
327 fprintf(fp, "quatern_y_shift := %g\n", img->quatern[4]);
328 fprintf(fp, "quatern_z_shift := %g\n", img->quatern[5]);
329 }
330 if(floatNonzeroes(img->srow, 12)>0) {
331 for(int i=0; i<4; i++) fprintf(fp, "srow_x[%d] := %g\n", i, img->srow[i]);
332 for(int i=0; i<4; i++) fprintf(fp, "srow_y[%d] := %g\n", i, img->srow[4+i]);
333 for(int i=0; i<4; i++) fprintf(fp, "srow_z[%d] := %g\n", i, img->srow[8+i]);
334 }
335 if(floatNonzeroes(img->iop, 6)>0) {
336 fprintf(fp, "image_orientation_patient := %g", img->iop[0]);
337 for(int i=1; i<6; i++) fprintf(fp, ", %g", img->iop[i]);
338 fprintf(fp, "\n");
339 }
340 if(floatNonzeroes(img->ipp, 3)>0) {
341 fprintf(fp, "image_position_patient := %g", img->ipp[0]);
342 for(int i=1; i<3; i++) fprintf(fp, ", %g", img->ipp[i]);
343 fprintf(fp, "\n");
344 }
345 if(floatNonzeroes(img->mt, 3)>0) {
346 fprintf(fp, "image_matrix_transformation_parameters := %g", img->mt[0]);
347 for(int i=1; i<12; i++) fprintf(fp, ", %g", img->mt[i]);
348 fprintf(fp, "\n");
349 }
350
351 if(img->isot!=ISOTOPE_UNKNOWN) fprintf(fp, "isotope: %s\n", isotopeName(img->isot));
352 if(img->decayCorrection==DECAY_CORRECTED) fprintf(fp, "physical_decay: corrected\n");
353 else if(img->decayCorrection==DECAY_NOTCORRECTED) fprintf(fp, "physical_decay: not corrected\n");
354
355 if(imgHasWeights(img)) fprintf(fp, "weighting: no\n");
356 else fprintf(fp, "weighting: yes\n");
357
358 if(img->cunit!=UNIT_UNKNOWN) fprintf(fp, "pixel_unit := %s\n", unitName(img->cunit));
359 if(img->tunit!=UNIT_UNKNOWN) fprintf(fp, "time_unit := %s\n", unitName(img->tunit));
360
361 fprintf(fp, "original header: %d items\n", img->ih.keyNr);
362
363 fflush(fp);
364 return;
365}
unsigned int floatNonzeroes(float *a, const unsigned int n)
Definition floatutil.c:247
int imgHasData(IMG *img)
Definition image.c:218
char * imgModalityDescr(imgmodality c)
Definition image.c:27
int imgHasWeights(IMG *img)
Definition image.c:278
char * imgContentDescr(imgcontent c)
Definition image.c:51
int imgHasTimes(IMG *img)
Definition image.c:235
int imgHasCounts(IMG *img)
Definition image.c:251
char * imgFormatDescr(imgformat c)
Definition imageio.c:36
char * isotopeName(int isotope_code)
Definition isotope.c:101
int keyNr
Definition tpcift.h:47
float sizex
Definition tpcimage.h:119
imgmodality modality
Definition tpcimage.h:100
float gapx
Definition tpcimage.h:126
imgformat format
Definition tpcimage.h:103
float ipp[3]
Definition tpcimage.h:141
short int xform[2]
Definition tpcimage.h:133
float quatern[6]
Definition tpcimage.h:135
float iop[6]
Definition tpcimage.h:139
float srow[12]
Definition tpcimage.h:137
float sizey
Definition tpcimage.h:121
IFT ih
Definition tpcimage.h:208
imgcontent content
Definition tpcimage.h:97
char scanStart[20]
Definition tpcimage.h:94
float mt[12]
Definition tpcimage.h:144
decaycorrection decayCorrection
Definition tpcimage.h:91
float gapy
Definition tpcimage.h:128
isotope isot
Definition tpcimage.h:88
float gapz
Definition tpcimage.h:130
imgformat oformat
Definition tpcimage.h:105
float sizez
Definition tpcimage.h:123
@ UNIT_UNKNOWN
Unknown unit.
@ DECAY_NOTCORRECTED
Data is not corrected for physical decay.
Definition tpcisotope.h:80
@ DECAY_CORRECTED
Data is corrected for physical decay.
Definition tpcisotope.h:81
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51

◆ imgCopyHeader()

int imgCopyHeader ( IMG * img1,
IMG * img2 )
extern

Copy information fields from one IMG to another. Image dimensions, pixel data, and frame information are not copied.

See also
imgAllocate, imgInit, imgFree
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
img1Pointer to source image structure.
img2Pointer to initiated target image structure.

Definition at line 18 of file imageheader.c.

23 {
24 if(img1==NULL || img2==NULL) return(TPCERROR_FAIL);
25 if(!imgHasData(img1) || !imgHasData(img2)) return(TPCERROR_FAIL);
26
27 strlcpy(img2->studyNr, img1->studyNr, MAX_STUDYNR_LEN+1);
28 img2->isot=img1->isot;
30 strlcpy(img2->scanStart, img1->scanStart, 20);
31 img2->content=img1->content;
32 img2->modality=img1->modality;
33 img2->format=img1->format;
34 img2->oformat=img1->oformat;
35 img2->sizex=img1->sizex;
36 img2->sizey=img1->sizey;
37 img2->sizez=img1->sizez;
38 img2->gapx=img1->gapx;
39 img2->gapy=img1->gapy;
40 img2->gapz=img1->gapz;
41 img2->xform[0]=img1->xform[0];
42 img2->xform[1]=img1->xform[1];
43 for(int i=0; i<6; i++) img2->quatern[i]=img1->quatern[i];
44 for(int i=0; i<12; i++) img2->srow[i]=img1->srow[i];
45 for(int i=0; i<6; i++) img2->iop[i]=img1->iop[i];
46 for(int i=0; i<3; i++) img2->ipp[i]=img1->ipp[i];
47 for(int i=0; i<12; i++) img2->mt[i]=img1->mt[i];
48 img2->cunit=img1->cunit;
49 img2->tunit=img1->tunit;
50
51 return(TPCERROR_OK);
52}
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
char studyNr[MAX_STUDYNR_LEN+1]
Definition tpcimage.h:85
#define MAX_STUDYNR_LEN
Define max study number length.

◆ imgDefaultExtension()

char * imgDefaultExtension ( imgformat c)
extern

Return pointer to default image file name extension based on the format code.

Remarks
No extension for most formats.
Returns
pointer to the file name extension starting with '.', or empty string.
See also
imgformat
Parameters
cIMG format code

Definition at line 67 of file imageio.c.

70 {
71 if(c<IMG_FORMAT_UNKNOWN || c>=IMG_FORMAT_LAST) return NULL;
72 return (char*)img_fn_ext[c];
73}

◆ imgFillOHeader()

int imgFillOHeader ( IMG * img,
TPCSTATUS * status )
extern

Fill/edit IMG output header.

Remarks
Stub function.
See also
imgInit, imgWrite, imgFree
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to image structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 61 of file imageheader.c.

66 {
67 int verbose=0; if(status!=NULL) verbose=status->verbose;
68 if(verbose>0) {printf("%s(img)\n", __func__); fflush(stdout);}
69
70 if(img==NULL || !imgHasData(img)) {
71 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
72 return(TPCERROR_NO_DATA);
73 }
74
75 /* If output header is empty then copy input header;
76 if file formats match, copy directly, otherwise convert contents */
77 if(img->oh.keyNr==0 && img->ih.keyNr>0) {
78 if(img->format==img->oformat) {
79 if(verbose>1) printf("copying header\n");
80 if(iftDuplicate(&img->ih, &img->oh)!=TPCERROR_OK) {
81 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_HEADER);
83 }
84 } else {
85 if(verbose>1) printf("converting header\n");
86
87 }
88 }
89
90 /* Set fields from IMG structure */
91
92 iftDeleteKey(&img->oh, "dimx");
93 if(iftPutUInt(&img->oh, "dimx", img->dimz, 0, NULL)!=0) return(TPCERROR_INVALID_HEADER);
94 iftDeleteKey(&img->oh, "dimy");
95 if(iftPutUInt(&img->oh, "dimy", img->dimz, 0, NULL)!=0) return(TPCERROR_INVALID_HEADER);
96 iftDeleteKey(&img->oh, "dimz");
97 if(iftPutUInt(&img->oh, "dimz", img->dimz, 0, NULL)!=0) return(TPCERROR_INVALID_HEADER);
98 iftDeleteKey(&img->oh, "dimt");
99 if(iftPutUInt(&img->oh, "dimt", img->dimz, 0, NULL)!=0) return(TPCERROR_INVALID_HEADER);
100
102 iftDeleteKey(&img->oh, "modality");
103 if(iftPut(&img->oh, "modality", imgModalityDescr(img->modality), 0, NULL)!=0)
105 }
106 if(img->content!=IMG_CONTENT_UNKNOWN) {
107 iftDeleteKey(&img->oh, "content");
108 if(iftPut(&img->oh, "content", imgContentDescr(img->content), 0, NULL)!=0)
110 }
111 if(img->format!=IMG_FORMAT_UNKNOWN) {
112 iftDeleteKey(&img->oh, "format");
113 if(iftPut(&img->oh, "format", imgFormatDescr(img->format), 0, NULL)!=0)
115 }
116 if(img->isot!=ISOTOPE_UNKNOWN) {
117 iftDeleteKey(&img->oh, "isotope");
118 if(iftPut(&img->oh, "isotope", isotopeName(img->isot), 0, NULL)!=0)
120 }
122 iftDeleteKey(&img->oh, "decay_correction");
123 char buf[8];
124 if(img->decayCorrection==DECAY_CORRECTED) strcpy(buf, "y"); else strcpy(buf, "n");
125 if(iftPut(&img->oh, "decay_correction", buf, 0, NULL)!=0)
127 }
128 if(img->cunit!=UNIT_UNKNOWN) {
129 iftDeleteKey(&img->oh, "pixel_unit");
130 if(iftPut(&img->oh, "pixel_unit", unitName(img->cunit), 0, NULL)!=0)
132 }
133 if(img->tunit!=UNIT_UNKNOWN) {
134 iftDeleteKey(&img->oh, "time_unit");
135 if(iftPut(&img->oh, "time_unit", unitName(img->tunit), 0, NULL)!=0)
137 }
138
139 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
140 return(TPCERROR_OK);
141}
int iftPutUInt(IFT *ift, const char *key, const unsigned int value, char comment, TPCSTATUS *status)
Definition ift.c:180
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
Definition ift.c:63
int iftDuplicate(IFT *ift1, IFT *ift2)
Definition ift.c:236
void iftDeleteKey(IFT *ift, const char *key)
Definition iftfind.c:169
IFT oh
Definition tpcimage.h:210
@ TPCERROR_INVALID_HEADER
Invalid header contents.
@ DECAY_UNKNOWN
Not known; usually assumed that data is corrected.
Definition tpcisotope.h:79

Referenced by imgWrite().

◆ imgFormatDescr()

char * imgFormatDescr ( imgformat c)
extern

Return pointer to image file format description with the format code.

Returns
pointer to the image file format string.
See also
imgformat
Parameters
cIMG format code

Definition at line 36 of file imageio.c.

39 {
40 if(c<IMG_FORMAT_UNKNOWN || c>=IMG_FORMAT_LAST) return NULL;
41 return (char*)img_format[c];
42}

Referenced by imgContents(), imgFillOHeader(), imgReadNifti(), and imgWrite().

◆ imgFormatFromFName()

imgformat imgFormatFromFName ( const char * fname,
TPCSTATUS * status )
extern

Determine IMG file format from file name.

If file name is actually name of an existing path, then DICOM is assumed. Non-existing path can be identified as path only if it ends with '/'.

Note that NIfTI dual file format, Analyze, and microPET files can not be separated by file naming.

Returns
enum imgformat (IMG_FORMAT_DICOM, ...), and IMG_FORMAT_UNKNOWN, when not certain.
See also
imgFormatIdentify, imgRead, imgWrite, micropetExists, niftiExists, anaExists
Parameters
fnameName of file that is used to determine format.
statusPointer to status data; enter NULL if not needed.

Definition at line 394 of file imageio.c.

399 {
400 int verbose=0; if(status!=NULL) verbose=status->verbose;
401 if(verbose>0) {printf("%s(%s)\n", __func__, fname); fflush(stdout);}
402
403 /* Empty name? */
404 if(fname==NULL || strnlen(fname, 2)<1) return(IMG_FORMAT_UNKNOWN);
405
406 /* Path as file name? */
407 if(pathExist(fname)) {
408 if(verbose>1) printf("%s is an existing path\n", fname);
409 return(IMG_FORMAT_DICOM);
410 }
411 if(fname[strlen(fname)-1]=='/' || fname[strlen(fname)-1]=='\\') {
412 if(verbose>1) printf("%s is a non-existing path\n", fname);
413 return(IMG_FORMAT_DICOM);
414 }
415
416 /* Get the extension(s) */
417 char *exts=filenameGetExtensions(fname);
418 if(exts==NULL) {
419 if(verbose>1) printf("file name has no extension\n");
420 /* Probably NIfTI, Analyze, or MicroPET, but we cannot be sure */
421 return(IMG_FORMAT_UNKNOWN);
422 }
423 if(verbose>1) printf("file name extension: '%s'\n", exts);
424
425 /* Check certain common extensions */
426 if(strcasecmp(exts, ".dcm")==0) return(IMG_FORMAT_DICOM);
427 if(strcasecmp(exts, ".dicom")==0) return(IMG_FORMAT_DICOM);
428
429 if(strcasecmp(exts, ".nii")==0) return(IMG_FORMAT_NIFTI_1S);
430
431 if(strcasecmp(exts, ".v")==0) return(IMG_FORMAT_E7);
432 if(strcasecmp(exts, ".s")==0) return(IMG_FORMAT_E7);
433 if(strcasecmp(exts, ".n")==0) return(IMG_FORMAT_E7);
434 if(strcasecmp(exts, ".a")==0) return(IMG_FORMAT_E7);
435 if(strcasecmp(exts, ".scn")==0) return(IMG_FORMAT_E63);
436 if(strcasecmp(exts, ".nrm")==0) return(IMG_FORMAT_E63);
437 if(strcasecmp(exts, ".atn")==0) return(IMG_FORMAT_E63);
438 if(strcasestr(exts, "polarmap")!=NULL) return(IMG_FORMAT_POLARMAP);
439
440 if(strcasecmp(exts, ".if")==0) return(IMG_FORMAT_INTERFILE);
441 if(strcasestr(exts, ".i.hdr")!=NULL) return(IMG_FORMAT_INTERFILE);
442 if(strcasestr(exts, ".i.img")!=NULL) return(IMG_FORMAT_INTERFILE);
443 if(strcasecmp(exts, ".i")==0) return(IMG_FORMAT_INTERFILE);
444
445 if(strcasecmp(exts, ".img")==0) return(IMG_FORMAT_E63);
446
447 if(strcasecmp(exts, ".pet.img")==0) return(IMG_FORMAT_MICROPET);
448 if(strcasecmp(exts, ".pet.img.hdr")==0) return(IMG_FORMAT_MICROPET);
449 if(strcasecmp(exts, ".ct.img")==0) return(IMG_FORMAT_MICROPET);
450 if(strcasecmp(exts, ".ct.img.hdr")==0) return(IMG_FORMAT_MICROPET);
451
452 /* Check certain in-house extensions */
453 if(strcasecmp(exts, ".bin")==0) return(IMG_FORMAT_FLAT);
454 if(strcasecmp(exts, ".mif")==0) return(IMG_FORMAT_FLAT);
455
456 return(IMG_FORMAT_UNKNOWN);
457}
char * filenameGetExtensions(const char *s)
Get all extensions of a file name.
Definition filename.c:203
int pathExist(const char *pathname)
Definition pathexist.c:17
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
char * strcasestr(const char *haystack, const char *needle)
Definition stringext.c:155

Referenced by imgWrite().

◆ imgFormatIdentify()

imgformat imgFormatIdentify ( const char * s)
extern

Identify the string representation of the IMG file format.

Returns
enum imgformat, or 0 (enum IMG_FORMAT_UNKNOWN) if not identified.
See also
imgFormatFromFName
Author
Vesa Oikonen
Parameters
sIMG format as a string

Definition at line 466 of file imageio.c.

469 {
470 if(s==NULL || strlen(s)<1) return IMG_FORMAT_UNKNOWN;
471 /* Try if string can be found directly in the table */
472 for(int i=0; i<IMG_FORMAT_LAST; i++) {
473 if(strcasecmp(img_format[i], s)==0) return i;
474 }
475 /* Format string is not following TPC standard, lets try something else */
476 if( strcasecmp(s, "bin")==0) return IMG_FORMAT_FLAT;
477 else if(strcasecmp(s, "v")==0) return IMG_FORMAT_E7;
478 else if(strcasecmp(s, "dcm")==0) return IMG_FORMAT_DICOM;
479 else if(strcasecmp(s, "ana")==0) return IMG_FORMAT_ANA_L;
480 else if(strcasecmp(s, "nii")==0) return IMG_FORMAT_NIFTI_1S;
481 else if(strcasecmp(s, "nifti")==0) return IMG_FORMAT_NIFTI_1S;
482
483 return IMG_FORMAT_UNKNOWN;
484}

◆ imgFree()

void imgFree ( IMG * img)
extern

Free memory allocated for IMG. All data is cleared.

See also
imgInit, imgAllocate, imgRead
Parameters
imgPointer to IMG structure.

Definition at line 107 of file image.c.

110 {
111 if(img==NULL) return;
112 iftFree(&img->ih);
113 iftFree(&img->oh);
114 free(img->weight); free(img->prompts); free(img->randoms);
115 free(img->x1); free(img->x2); free(img->x);
116 free(img->_t); free(img->_z); free(img->_x); free(img->_y);
117 imgInit(img);
118}
void iftFree(IFT *ift)
Definition ift.c:37
void imgInit(IMG *img)
Definition image.c:64

Referenced by imgAllocate(), imgRead(), imgReadDICOM(), and imgReadNifti().

◆ imgFromSIF()

int imgFromSIF ( IMG * img,
TAC * sif,
int copy_header,
int copy_frames,
int copy_counts,
int verbose )
extern

Copy information from SIF into IMG.

Todo
Add tests.
See also
imgToSIF, imgInit, tacInit, imgWrite, imgRead, tacWriteSIF
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to IMG struct into which content is copied from SIF.
sifPointer to SIF, which actually is stored as a TAC format.
copy_headerSelect whether header contents are copied (1) or not copied (0) from SIF.
copy_framesSelect whether frame times are copied (1) or not copied (0) from SIF.
copy_countsSelect whether counts are copied (1) or not copied (0) from SIF.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 126 of file imagesif.c.

139 {
140 if(verbose>0) {
141 printf("%s(img, sif, %d, %d, %d, ...)\n", __func__, copy_header, copy_frames, copy_counts);
142 fflush(stdout);
143 }
144
145 if(sif==NULL || img==NULL) return(TPCERROR_FAIL);
146
147 if(copy_header) {
148 if(verbose>1) printf(" copying header.\n");
149 int ret=tacGetHeaderScanstarttime(&sif->h, img->scanStart, NULL);
150 if(ret!=TPCERROR_OK && verbose>0) fprintf(stderr, "Warning: cannot read scan start time in SIF\n");
151 img->isot=tacGetIsotope(sif);
152 if(img->isot==ISOTOPE_UNKNOWN && verbose>0) fprintf(stderr, "Warning: cannot read isotope in SIF\n");
153 ret=tacGetHeaderStudynr(&sif->h, img->studyNr, NULL);
154 }
155
156 if(copy_frames) {
157 if(verbose>1) printf(" copying frame times.\n");
158 if(!sif->isframe || sif->sampleNr!=img->dimt) return(TPCERROR_INVALID_FORMAT);
159 for(int fi=0; fi<img->dimt; fi++) {
160 img->x1[fi]=sif->x1[fi];
161 img->x2[fi]=sif->x2[fi];
162 img->x[fi]=0.5*(img->x1[fi]+img->x2[fi]);
163 }
164 img->tunit=sif->tunit;
165 }
166
167 if(copy_counts) {
168 if(verbose>1) printf(" copying count data.\n");
169 if(sif->format!=TAC_FORMAT_SIF || !sif->isframe || sif->sampleNr!=img->dimt)
171 if(sif->tacNr<4) return(TPCERROR_INVALID_FORMAT);
172 for(int fi=0; fi<img->dimt; fi++) {
173 img->prompts[fi]=sif->c[0].y[fi];
174 img->randoms[fi]=sif->c[1].y[fi];
175 }
178 for(int fi=0; fi<img->dimt; fi++)
179 img->weight[fi]=sif->w[fi];
180 img->weighting=sif->weighting;
181 }
182 }
183
184 return(TPCERROR_OK);
185}
weights weighting
Definition tpcimage.h:191
double * y
Definition tpctac.h:75
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
double * w
Definition tpctac.h:111
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
weights weighting
Definition tpctac.h:115
double * x2
Definition tpctac.h:101
unit tunit
Definition tpctac.h:109
double * x1
Definition tpctac.h:99
int tacNr
Definition tpctac.h:91
int tacGetIsotope(TAC *tac)
Definition tacdc.c:25
int tacGetHeaderScanstarttime(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:372
int tacGetHeaderStudynr(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:26
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ WEIGHTING_UNKNOWN
Not known; usually assumed that not weighted.
@ TPCERROR_INVALID_FORMAT
Invalid file format.
@ TAC_FORMAT_SIF
Scan information file.
Definition tpctac.h:43

Referenced by imgReadNifti().

◆ imgGetNiftiHeader()

int imgGetNiftiHeader ( IMG * img,
NIFTI_DSR * dsr,
int verbose )
extern

Copy header information from NIfTI into IMG.

Todo
Add tests.
See also
imgSetNiftiHeader, niftiExists, imgReadNifti
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to IMG structure to be filled.
dsrPointer to NIfTI header structure from which information is read.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 794 of file imagenii.c.

801 {
802 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
803
804 /* Check the input */
805 if(dsr==NULL || img==NULL) return(TPCERROR_FAIL);
806 if(dsr->n!=1 && dsr->n!=2) return(TPCERROR_FAIL);
807
808 /* NIfTI file format */
809 if(dsr->n==1) {
810 if(strcmp(dsr->h1.magic, "ni1")==0) img->format=IMG_FORMAT_NIFTI_1D;
811 else if(strcmp(dsr->h1.magic, "n+1")==0) img->format=IMG_FORMAT_NIFTI_1S;
812 else return(TPCERROR_INVALID_FORMAT);
813 } else if (dsr->n==2) {
814 if(strcmp(dsr->h2.magic, "ni2")==0) img->format=IMG_FORMAT_NIFTI_2D;
815 else if(strcmp(dsr->h2.magic, "n+2")==0) img->format=IMG_FORMAT_NIFTI_2S;
816 else return(TPCERROR_INVALID_FORMAT);
817 } else {
818 return(TPCERROR_FAIL);
819 }
820
821 /* Get the image dimensions */
822 int dimNr;
823 if(dsr->n==1) dimNr=dsr->h1.dim[0]; else dimNr=dsr->h2.dim[0];
824 if(dimNr<2 || dimNr>8) return(TPCERROR_INVALID_HEADER);
825 if(dimNr>4) {
826 if(verbose>0) fprintf(stderr, "Error: NIfTI image dimension %d is not supported\n", dimNr);
827 return(TPCERROR_UNSUPPORTED);
828 }
829
830 long long dimx, dimy, dimz=1, dimt=1;
831 if(dsr->n==1) {
832 dimx=dsr->h1.dim[1];
833 dimy=dsr->h1.dim[2];
834 if(dimNr>2) {dimz=dsr->h1.dim[3]; if(dimNr>3) dimt=dsr->h1.dim[4];}
835 } else {
836 dimx=dsr->h2.dim[1];
837 dimy=dsr->h2.dim[2];
838 if(dimNr>2) {dimz=dsr->h2.dim[3]; if(dimNr>3) dimt=dsr->h2.dim[4];}
839 }
840 long long pxlNr=dimx*dimy*dimz;
841 if(pxlNr<1 || dimt<0) {
842 if(verbose>0) fprintf(stderr, "Error: invalid NIfTI image dimensions.\n");
844 }
845 if(dimt==0) dimt=1;
846 img->dimx=dimx; img->dimy=dimy; img->dimz=dimz; img->dimt=dimt;
847
848 /* Pixel x,y,z sizes, converting units if necessary */
849 int xyzt_units=0;
850 if(dsr->n==1) xyzt_units=dsr->h1.xyzt_units; else xyzt_units=dsr->h2.xyzt_units;
851 float f=1.0;
852 if(xyzt_units & NIFTI_UNITS_METER) f=1000.;
853 else if(xyzt_units & NIFTI_UNITS_MICRON) f=0.001;
854 else if(xyzt_units & NIFTI_UNITS_MM) f=1.0;
855 if(verbose>2) printf("pixel size conversion factor := %g\n", f);
856 if(dsr->n==1) {
857 img->sizex=dsr->h1.pixdim[1]; img->sizey=dsr->h1.pixdim[2]; img->sizez=dsr->h1.pixdim[3];
858 } else {
859 img->sizex=dsr->h2.pixdim[1]; img->sizey=dsr->h2.pixdim[2]; img->sizez=dsr->h2.pixdim[3];
860 }
861 img->sizex*=f; img->sizey*=f; img->sizez*=f;
862
863 /* Orientation, quaternion, and transformation parameters */
864 if(dsr->n==1) {
865 img->xform[0]=dsr->h1.qform_code;
866 img->xform[1]=dsr->h1.sform_code;
867 img->quatern[0]=dsr->h1.quatern_b;
868 img->quatern[1]=dsr->h1.quatern_c;
869 img->quatern[2]=dsr->h1.quatern_d;
870 img->quatern[3]=dsr->h1.qoffset_x;
871 img->quatern[4]=dsr->h1.qoffset_y;
872 img->quatern[5]=dsr->h1.qoffset_z;
873 for(int i=0; i<4; i++) img->srow[i]=dsr->h1.srow_x[i];
874 for(int i=0; i<4; i++) img->srow[4+i]=dsr->h1.srow_y[i];
875 for(int i=0; i<4; i++) img->srow[8+i]=dsr->h1.srow_z[i];
876 } else {
877 img->xform[0]=dsr->h2.qform_code;
878 img->xform[1]=dsr->h2.sform_code;
879 img->quatern[0]=dsr->h2.quatern_b;
880 img->quatern[1]=dsr->h2.quatern_c;
881 img->quatern[2]=dsr->h2.quatern_d;
882 img->quatern[3]=dsr->h2.qoffset_x;
883 img->quatern[4]=dsr->h2.qoffset_y;
884 img->quatern[5]=dsr->h2.qoffset_z;
885 for(int i=0; i<4; i++) img->srow[i]=dsr->h2.srow_x[i];
886 for(int i=0; i<4; i++) img->srow[4+i]=dsr->h2.srow_y[i];
887 for(int i=0; i<4; i++) img->srow[8+i]=dsr->h2.srow_z[i];
888 }
889
890 /* Assumptions etc */
892 strcpy(img->studyNr, "");
894 img->cunit=UNIT_UNKNOWN;
895
896 /* Check if unit can be found in description field */
897 char *cptr;
898 if(dsr->n==1) cptr=dsr->h1.descrip; else cptr=dsr->h2.descrip;
899 img->cunit=unitIdentify(cptr);
900
901 return(TPCERROR_OK);
902}
float quatern_d
Definition tpcnifti.h:289
float quatern_c
Definition tpcnifti.h:287
short int qform_code
Definition tpcnifti.h:281
float qoffset_x
Definition tpcnifti.h:291
float srow_z[4]
Definition tpcnifti.h:301
float srow_x[4]
Definition tpcnifti.h:297
float pixdim[8]
Definition tpcnifti.h:249
short int sform_code
Definition tpcnifti.h:283
float srow_y[4]
Definition tpcnifti.h:299
float qoffset_y
Definition tpcnifti.h:293
char descrip[80]
Definition tpcnifti.h:276
char magic[4]
Definition tpcnifti.h:306
float qoffset_z
Definition tpcnifti.h:295
short int dim[8]
Definition tpcnifti.h:233
float quatern_b
Definition tpcnifti.h:285
double srow_x[4]
Definition tpcnifti.h:372
char magic[8]
Definition tpcnifti.h:315
int64_t dim[8]
Definition tpcnifti.h:323
double pixdim[8]
Definition tpcnifti.h:331
double qoffset_y
Definition tpcnifti.h:368
double srow_y[4]
Definition tpcnifti.h:374
double quatern_d
Definition tpcnifti.h:364
double qoffset_z
Definition tpcnifti.h:370
double qoffset_x
Definition tpcnifti.h:366
char descrip[80]
Definition tpcnifti.h:351
double quatern_c
Definition tpcnifti.h:362
double srow_z[4]
Definition tpcnifti.h:376
double quatern_b
Definition tpcnifti.h:360
NIFTI_2_HEADER h2
Definition tpcnifti.h:406
NIFTI_1_HEADER h1
Definition tpcnifti.h:404
@ TPCERROR_UNSUPPORTED
Unsupported file type.
int unitIdentify(const char *s)
Definition units.c:162
#define NIFTI_UNITS_METER
Definition tpcnifti.h:46
#define NIFTI_UNITS_MICRON
Definition tpcnifti.h:50
#define NIFTI_UNITS_MM
Definition tpcnifti.h:48

Referenced by imgReadNifti().

◆ imgHasCounts()

int imgHasCounts ( IMG * img)
extern

Verify that IMG contains prompts and randoms.

See also
imgHasData, imgHasTimes, imgHasWeights, imgInit, imgFree, imgRead, imgWrite, imgContents
Returns
0, if no prompts or randoms, 1 if prompts exist, 2 if randoms exist, and 3 if both prompts and randoms exist.
Parameters
imgPointer to image structure.

Definition at line 251 of file image.c.

254 {
255 if(img==NULL || img->dimt<1) return(0);
256 int p=0, r=0;
257 /* If image has only one frame, then any value > 0 is fine */
258 if(img->dimt==1) {
259 if(img->prompts[0]>0.000000001) p=1;
260 if(img->randoms[0]>0.000000001) r=2;
261 return(p+r);
262 }
263 /* When more frames, we check that frames have different count level */
264 for(unsigned short int i=1; i<img->dimt; i++) {
265 if(fabsf(img->prompts[i]-img->prompts[i-1])>0.001) p=1;
266 if(fabsf(img->randoms[i]-img->randoms[i-1])>0.001) r=2;
267 if((p+r)>2) break;
268 }
269 return(p+r);
270}

Referenced by imgContents(), and imgToSIF().

◆ imgHasData()

int imgHasData ( IMG * img)
extern

Verify that image data actually contains pixel data.

See also
imgHasTimes, imgNaNs, imgRead, imgWrite, imgContents
Returns
0, if no data, 1 if contains data.
Parameters
imgPointer to image structure.

Definition at line 218 of file image.c.

221 {
222 if(img==NULL) return(0);
223 if(img->dimz<1 || img->dimy<1 || img->dimx<1 || img->dimz<1) return(0);
224 if(img->m==NULL || img->p==NULL) return(0);
225 if(img->x1==NULL || img->x2==NULL) return(0);
226 return(1);
227}

Referenced by imgContents(), imgCopyHeader(), imgFillOHeader(), imgHasTimes(), imgMinMax(), imgSetNiftiHeader(), imgWrite(), imgWriteNifti(), and imgXRange().

◆ imgHasTimes()

int imgHasTimes ( IMG * img)
extern

Verify that IMG contains frame times.

See also
imgHasData, imgInit, imgFree, imgRead, imgWrite, imgContents
Returns
0, if no frame times, 1 if frame times exist.
Parameters
imgPointer to image structure.

Definition at line 235 of file image.c.

238 {
239 if(imgHasData(img)==0) return(0);
240 for(int i=0; i<img->dimt; i++) if(img->x2[i]>0.00000001) return(1);
241 return(0);
242}

Referenced by imgContents(), imgToSIF(), and imgWriteNifti().

◆ imgHasWeights()

int imgHasWeights ( IMG * img)
extern

Check if image contains weights as indicated by the 'weighting' field.

See also
imgHasCounts, imgHasData, imgHasTimes, imgInit, tacIsWeighted
Returns
Returns 1 if weighted, and 0 if not or in case of an error.
Parameters
imgPointer to image structure.

Definition at line 278 of file image.c.

281 {
282 if(img==NULL || img->dimt<1) return(0);
283 if(img->weighting==WEIGHTING_UNKNOWN || img->weighting==WEIGHTING_OFF) return(0);
284 if(img->weighting<WEIGHTING_LAST) return(1);
285 return(0);
286}

Referenced by imgContents().

◆ imgInit()

void imgInit ( IMG * img)
extern

Initiate the IMG structure before any use.

See also
imgFree, imgAllocate, imgRead
Parameters
imgPointer to IMG structure.

Definition at line 64 of file image.c.

67 {
68 if(img==NULL) return;
69 img->dimt=img->dimx=img->dimy=img->dimz=0;
70 iftInit(&img->ih);
71 iftInit(&img->oh);
75
76 for(int i=0; i<20; i++) img->scanStart[i]=(char)0;
77 for(int i=0; i<MAX_STUDYNR_LEN+1; i++) img->studyNr[i]=(char)0;
78
79
80 img->sizex=img->sizey=img->sizez=0.0;
81 img->gapx=img->gapy=img->gapz=0.0;
82 img->xform[0]=img->xform[1]=0;
83 for(int i=0; i<6; i++) img->quatern[i]=0.0;
84 for(int i=0; i<12; i++) img->srow[i]=0.0;
85 for(int i=0; i<6; i++) img->iop[i]=0.0;
86 for(int i=0; i<3; i++) img->ipp[i]=0.0;
87 for(int i=0; i<12; i++) img->mt[i]=0.0;
88
91
93 img->weight=img->prompts=img->randoms=NULL;
94
95 img->cunit=img->tunit=UNIT_UNKNOWN;
96
97 img->x1=img->x2=img->x=NULL;
98 img->m=(float****)0; img->p=0;
99 img->_z=(float****)0; img->_y=(float***)0; img->_x=(float**)0; img->_t=(float*)0;
100}
void iftInit(IFT *ift)
Definition ift.c:21

Referenced by imgFree().

◆ imgMinMax()

int imgMinMax ( IMG * img,
float * minvalue,
float * maxvalue )
extern

Searches the min and max pixel value in the image data.

See also
imgXRange, imgInit, imgFree, imgHasData
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to IMG structure from where min and max pixel values are searched.
minvaluePointer to min pixel value; Enter NULL if not needed.
maxvaluePointer to max pixel value; Enter NULL if not needed.

Definition at line 396 of file image.c.

403 {
404 if(img==NULL || !imgHasData(img)) return(TPCERROR_FAIL);
405 float f1, f2;
406 f1=f2=nanf("");
407 if(minvalue!=NULL) *minvalue=f1;
408 if(maxvalue!=NULL) *maxvalue=f2;
409 unsigned long long i, n=img->dimt*img->dimz*img->dimy*img->dimx;
410 // search first valid number
411 for(i=0; i<n; i++) if(isfinite(img->p[i])) break;
412 if(i==n) return(TPCERROR_MISSING_DATA);
413 f1=f2=img->p[i++];
414 for(; i<n; i++) {
415 if(img->p[i]>f2) f2=img->p[i];
416 else if(img->p[i]<f1) f1=img->p[i];
417 }
418 if(minvalue!=NULL) *minvalue=f1;
419 if(maxvalue!=NULL) *maxvalue=f2;
420 return(TPCERROR_OK);
421}
@ TPCERROR_MISSING_DATA
File contains missing values.

Referenced by imgSetNiftiHeader().

◆ imgModalityDescr()

char * imgModalityDescr ( imgmodality c)
extern

Return pointer to modality of the image data.

Returns
pointer to the modality string.
See also
imgmodality
Parameters
cIMG modality code

Definition at line 27 of file image.c.

30 {
31 if(c<IMG_MODALITY_UNKNOWN || c>=IMG_MODALITY_LAST) return NULL;
32 return (char*)img_modality[c];
33}

Referenced by imgContents(), and imgFillOHeader().

◆ imgNaNs()

unsigned long long imgNaNs ( IMG * img,
int fix )
extern

Searches the image data for missing pixel values, optionally setting those to zero.

See also
imgHasData
Returns
the number of missing pixel values.
Parameters
imgPointer to IMG structure.
fixSet (1) or do not set (0) missing pixels to zero.

Definition at line 373 of file image.c.

378 {
379 if(img==NULL) return(0);
380 unsigned long long i, n=0, pxlNr=img->dimt*img->dimz*img->dimy*img->dimx;
381 for(i=0; i<pxlNr; i++) {
382 if(!isfinite(img->p[i])) {
383 n++;
384 if(fix!=0) img->p[i]=0.0;
385 }
386 }
387 return(n);
388}

◆ imgRead()

int imgRead ( IMG * img,
const char * fname,
TPCSTATUS * status )
extern

Read image file into IMG structure.

Remarks
Stub function, mostly.
See also
imgInit, imgWrite, imgFree
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to initialized image structure; old contents are deleted.
Precondition
Initialize structure using imgInit() before this.
Parameters
fnamePointer to the file name, possibly path in case of DICOM.
statusPointer to status data; enter NULL if not needed.

Definition at line 82 of file imageio.c.

90 {
91 int verbose=0; if(status!=NULL) verbose=status->verbose;
92 if(verbose>0) {printf("%s(img, %s)\n", __func__, fname); fflush(stdout);}
93
94 if(img==NULL || strnlen(fname, 2)<1) {
95 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
96 return(TPCERROR_FAIL);
97 }
98
99 /* Delete any old contents in data structure */
100 imgFree(img);
101
102 /* What kind of data are we supposed to read? */
103 if(pathExist(fname)) {
104
105 if(verbose>2) printf("%s is a path\n", fname);
106 unsigned short int fileNr=pathFileNr(fname);
107 if(verbose>2) printf("%s contains %u file(s)\n", fname, fileNr);
108 if(fileNr==0) {
109 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_FILE);
110 return(TPCERROR_NO_FILE);
111 }
112 /* Check if this is a DICOM folder */
113 IFT fl; iftInit(&fl);
114 int ret=dcmFileList(fname, &fl, status);
115 if(ret==TPCERROR_OK) {
116 if(verbose>2) printf("%s is DICOM folder.\n", fname);
118 } else {
119 if(verbose>2) printf("%s is not a DICOM folder.\n", fname);
120 fileNr=pathFileList(fname, &fl); // just read the file list
121 }
122 if(fileNr==0) {
123 iftFree(&fl);
124 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_FILE);
125 return(TPCERROR_NO_FILE);
126 }
127 /* It would be too risky to just open random file from the folder */
128 iftFree(&fl);
129 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
130 return(TPCERROR_UNSUPPORTED);
131
132 } else if(fileExist(fname)) {
133
134 if(verbose>2) printf("%s is a file\n", fname);
135 /* Check if this is DICOM file */
136 if(dcmVerifyMagic(fname, NULL)) {
137 /*if(verbose>2)*/ printf("%s is in DICOM format.\n", fname);
139 /* This may be a single-file DICOM, or user just gave the name of one file in DICOM folder */
140 IFT fl; iftInit(&fl);
141 int ret=dcmFileList(fname, &fl, status);
142 if(ret!=TPCERROR_OK) {iftFree(&fl); return(ret);}
143 if(fl.keyNr==1) {
144 if(verbose>2) printf(" %s is a single DICOM file\n", fname);
145 iftFree(&fl);
146 ret=imgReadDICOM(img, fname, status);
147 if(verbose>2) printf(" imgReadDICOM() := %s\n", errorMsg(status->error));
148 return(ret);
149 } else {
150 if(verbose>2) printf(" %s is one of %d DICOM files\n", fname, fl.keyNr);
151
152 iftFree(&fl);
153 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
154 return(TPCERROR_UNSUPPORTED);
155 }
156 }
157 /* Check if we have NIfTI file, which may be in single file format,
158 or dual file format which has similar names as microPET and Analyze */
159 if(niftiExists(fname, NULL, NULL, NULL, NULL, status)==1) {
160 if(verbose>2) printf("%s is in NIfTI format.\n", fname);
161 /* Read NIfTI image */
162 return(imgReadNifti(img, fname, status));
163 /*statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
164 return(TPCERROR_UNSUPPORTED);*/
165 }
166 /* Check if we have Analyze file, which may be in dual file format which
167 has similar names as microPET and dual-file NIfTI */
168 if(anaExists(fname, NULL, NULL, NULL, NULL, status)==1) {
169 /* Read Analyze image */
170 /*if(verbose>2)*/ printf("%s is in Analyze format.\n", fname);
171 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
172 return(TPCERROR_UNSUPPORTED);
173 }
174
175 } else { // Not a folder, neither an existing file
176
177 /* Check if this is base name of an image, without extension(s) */
178 /* Check if we have NIfTI file, which may be in single file format,
179 or dual file format which has similar names as microPET and Analyze */
180 if(niftiExists(fname, NULL, NULL, NULL, NULL, status)==1) {
181 /* Read NIfTI image */
182 /*if(verbose>2)*/ printf("%s is in NIfTI format.\n", fname);
183 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
184 return(TPCERROR_UNSUPPORTED);
185 }
186 /* Check if we have Analyze file, which may be in dual file format which
187 has similar names as microPET and dual-file NIfTI */
188 if(anaExists(fname, NULL, NULL, NULL, NULL, status)==1) {
189 /* Read Analyze image */
190 /*if(verbose>2)*/ printf("%s is in Analyze format.\n", fname);
191 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
192 return(TPCERROR_UNSUPPORTED);
193 }
194 /* Check for microPET */
195
196
197 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_FILE);
198 return(TPCERROR_NO_FILE);
199 }
200
201
202
203 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
204 return(TPCERROR_OK);
205}
int anaExists(const char *filename, char *hdrfile, char *imgfile, char *siffile, ANALYZE_DSR *header, TPCSTATUS *status)
Definition analyzeio.c:16
int dcmFileList(const char *filename, IFT *ift, TPCSTATUS *status)
List DICOM files belonging to one image.
Definition dcmfile.c:123
int dcmVerifyMagic(const char *filename, FILE *fp)
Definition dcmio.c:25
unsigned short int pathFileNr(const char *pathname)
Definition filexist.c:33
unsigned short int pathFileList(const char *pathname, IFT *ift)
Definition filexist.c:83
int fileExist(const char *filename)
Definition filexist.c:17
int imgReadDICOM(IMG *img, const char *fname, TPCSTATUS *status)
Definition imagedcm.c:23
int imgReadNifti(IMG *img, const char *fname, TPCSTATUS *status)
Definition imagenii.c:72
int niftiExists(const char *filename, char *hdrfile, char *imgfile, char *siffile, NIFTI_DSR *header, TPCSTATUS *status)
Definition niftiio.c:17
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
Definition tpcift.h:43
tpcerror error
Error code.
@ TPCERROR_NO_FILE
File does not exist.

◆ imgReadDICOM()

int imgReadDICOM ( IMG * img,
const char * fname,
TPCSTATUS * status )
extern

Read DICOM PET image into IMG data structure.

Remarks
Only few header fields are read.
Todo
Add tests.
See also
imgInit, imgRead, imgWrite, imgFree, imgWriteDICOM
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to image structure. Any previous contents removed.
fnamePointer to the DICOM file name. Path not accepted.
statusPointer to status data; enter NULL if not needed.

Definition at line 23 of file imagedcm.c.

30 {
31 int verbose=0; if(status!=NULL) verbose=status->verbose;
32 if(verbose>0) {printf("%s(..., %s, ...)\n", __func__, fname); fflush(stdout);}
33
34 if(img==NULL || strnlen(fname, 2)<1) {
35 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
36 return(TPCERROR_FAIL);
37 }
38
39 /* Delete any old contents in data structure */
40 imgFree(img);
41
42 /* Read DICOM file */
43 DCMFILE dcm; dcmfileInit(&dcm);
44 int ret=dcmFileRead(fname, &dcm, 0, status);
45 if(ret!=TPCERROR_OK) {dcmfileFree(&dcm); return(ret);}
46
47//verbose=20;
48
49 /* Get modality */
51 {
52 DCMTAG tag; dcmTagSet(&tag, 0x0008, 0x0060); DCMITEM *iptr=dcmFindTag(dcm.item, 0, &tag, 0);
53 if(iptr==NULL) {
54 if(verbose>0) {fprintf(stderr, "Error: cannot find modality.\n"); fflush(stderr);}
55 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
56 dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
57 }
58 char *buf=dcmValueString(iptr);
59 if(verbose>12) printf("Modality := '%s'\n", buf);
60 if(strncmp(buf, "PT", 2)==0) modality=IMG_MODALITY_PET;
61 else if(strncmp(buf, "CT", 2)==0) modality=IMG_MODALITY_CT;
62 else if(strncmp(buf, "MR", 2)==0) modality=IMG_MODALITY_MRI;
63 else if(strncmp(buf, "NM", 2)==0) modality=IMG_MODALITY_SPECT;
64 else if(verbose>0) fprintf(stderr, "Warning: modality '%s' not supported.\n", buf);
65 free(buf);
66 }
67
68 /* Get the number of frames and planes */
69 if(verbose>10) {printf("reading matrix dimensions\n"); fflush(stdout);}
70 unsigned short int imgdim[4];
71 ret=dcmImgDim(&dcm, imgdim, verbose-2);
72 if(ret!=0 || imgdim[0]<=0 || imgdim[1]<=0 || imgdim[2]<=0 || imgdim[3]<=0) {
73 if(verbose>0) {fprintf(stderr, "Error: cannot find matrix dimensions.\n"); fflush(stderr);}
74 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
75 dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
76 }
77 unsigned short int dimx, dimy, sliceNr, frameNr;
78 dimx=imgdim[0]; dimy=imgdim[1]; sliceNr=imgdim[2]; frameNr=imgdim[3];
79 if(verbose>11)
80 printf("dimx := %u\ndimy := %u\ndimz := %u\ndimt := %u\n", dimx, dimy, sliceNr, frameNr);
81
82 /*
83 * Allocate memory for IMG data
84 */
85 ret=imgAllocate(img, sliceNr, dimy, dimx, frameNr, status);
86 if(ret!=TPCERROR_OK) {dcmfileFree(&dcm); return(ret);}
87
88
89 /* Get the status of decay correction and isotope */
90 ret=dcmImgIsotope(&dcm, &img->isot, &img->decayCorrection, verbose-2);
91 if(ret!=0 && verbose>0) {
92 fprintf(stderr, "Warning: decay correction and isotope unknown.\n"); fflush(stderr);
93 }
94 if(verbose>11) {
95 printf("decayCorrection := %s\n", decayDescr(img->decayCorrection));
96 printf("isotope := %s\n", isotopeName(img->isot));
97 fflush(stdout);
98 }
99
100 /* If decay is corrected, read time of decay correction; otherwise read start time */
101 char zeroDateTime[32]; zeroDateTime[0]=(char)0;
103 DCMTAG tag; dcmTagSet(&tag, 0x0018, 0x9701);
104 DCMITEM *iptr=dcmFindTag(dcm.item, 0, &tag, 0);
105 if(iptr!=NULL) dcmDT2intl(iptr->rd, zeroDateTime);
106 } else {
107 /* Get Acquisition DateTime */
108 DCMTAG tag; dcmTagSet(&tag, 0x0008, 0x002A);
109 DCMITEM *iptr=dcmFindTag(dcm.item, 0, &tag, 0);
110 if(iptr!=NULL) dcmDT2intl(iptr->rd, zeroDateTime);
111 }
112 if(!zeroDateTime[0]) {
113 if(verbose>0) fprintf(stderr, "Error: missing Acquisition Date and Time.\n");
114 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
115 imgFree(img); dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
116 }
117 if(verbose>14) printf("zeroDateTime := %s\n", zeroDateTime);
118
119 /* Get frame times */
120 if(modality==IMG_MODALITY_PET || modality==IMG_MODALITY_SPECT) {
121 /* Initiate frame times to NaN */
122 for(unsigned short int i=0; i<img->dimt; i++) img->x1[i]=img->x2[i]=img->x[i]=nanf("");
123
124 /* Find Per Frame Functional Groups Sequence */
125 DCMTAG tag; dcmTagSet(&tag, 0x5200, 0x9230);
126 DCMITEM *iptr=dcmFindTag(dcm.item, 0, &tag, 0);
127 if(iptr==NULL) {
128 if(verbose>0) fprintf(stderr, "Error: Per Frame Functional Groups Sequence not found.\n");
129 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
130 imgFree(img); dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
131 }
132 /* Loop through all Frame Content Sequences under it */
133 dcmTagSet(&tag, 0x0020, 0x9111);
134 DCMTAG tagstart; dcmTagSet(&tagstart, 0x0018, 0x9074);
135 DCMTAG tagdur; dcmTagSet(&tagdur, 0x0018, 0x9220);
136 DCMTAG tagfr; dcmTagSet(&tagfr, 0x0020, 0x9128);
137 DCMITEM *fptr=iptr->child_item;
138 while(fptr!=NULL) {
139 /* Find Frame Content Sequence */
140 iptr=dcmFindDownTag(fptr, 0, &tag, 0); if(iptr==NULL) break;
141 if(verbose>20) printf(" found Frame Content Sequence\n");
142 DCMITEM *jptr;
143 /* Find Temporal Position Index */
144 jptr=dcmFindDownTag(iptr->child_item, 0, &tagfr, 0);
145 if(jptr==NULL) {fptr=fptr->next_item; continue;}
146 if(verbose>30) dcmitemPrint(jptr);
147 unsigned short int frameIndex=(unsigned short int)(dcmitemGetInt(jptr)-1);
148 /* Find Frame Acquisition DateTime */
149 jptr=dcmFindDownTag(iptr->child_item, 0, &tagstart, 0);
150 char facqDateTime[32]; facqDateTime[0]=(char)0;
151 if(jptr!=NULL) dcmDT2intl(jptr->rd, facqDateTime);
152 if(!facqDateTime[0]) {
153 if(verbose>0) fprintf(stderr, "Error: missing Frame Acquisition DateTime.\n");
154 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
155 imgFree(img); dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
156 }
157 if(verbose>20) printf("facqDateTime := %s\n", facqDateTime);
158 /* Calculate the Frame start time */
159 float t1=(float)strDateTimeDifference(facqDateTime, zeroDateTime);
160 /* Set frame start time */
161 if(frameIndex<img->dimt) {
162 if(isnan(img->x1[frameIndex])) {
163 /* Save frame start time, since there is no previous value for this frame */
164 img->x1[frameIndex]=t1;
165 if(verbose>29) printf("t1[%u]=%g\n", frameIndex, t1);
166 } else {
167 /* Check whether previous frame start time is the same as current */
168 if(!floatMatch(img->x1[frameIndex], t1, 0.001)) {
169 // not the same, this probably is whole-body study with more than one bed pos
170 if(verbose>1) printf(" different t1=%g\n", t1);
171 }
172 }
173 }
174
175 /* Find Frame Acquisition Duration */
176 jptr=dcmFindDownTag(iptr->child_item, 0, &tagdur, 0);
177 if(jptr==NULL) {fptr=fptr->next_item; continue;}
178 if(verbose>20) dcmitemPrint(jptr);
179 if(frameIndex<img->dimt) {
180 img->x2[frameIndex]=img->x1[frameIndex]+(float)0.001*dcmitemGetReal(jptr);
181 img->x[frameIndex]=0.5*(img->x1[frameIndex]+img->x2[frameIndex]);
182 }
183 /* prepare for the next frame */
184 fptr=iptr->next_item;
185 }
186 }
187
188 /* Get pixel sizes and image position */
189 {
190 double pxlsize[3];
191 ret=dcmImgPxlsize(&dcm, pxlsize, verbose-2);
192 if(ret!=0) {
193 if(verbose>0) fprintf(stderr, "Error: missing Pixel size.\n");
194 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
195 imgFree(img); dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
196 }
197 img->sizex=(float)pxlsize[0];
198 img->sizey=(float)pxlsize[1];
199 img->sizez=(float)pxlsize[2];
200 if(verbose>13) printf(" pixel_size := %g x %g x %g\n", img->sizex, img->sizey, img->sizez);
201
202 double ipp[3];
203 int ret1=dcmImgPos(&dcm, ipp, verbose-2);
204 if(ret1==0) {
205 for(int i=0; i<3; i++) img->ipp[i]=ipp[i];
206 } else {
207 if(verbose>0) fprintf(stderr, "Warning: missing Image Position (Patient).\n");
208 }
209 double iop[6];
210 int ret2=dcmImgOrient(&dcm, iop, verbose-2);
211 if(ret2==0) {
212 for(int i=0; i<6; i++) img->iop[i]=iop[i];
213 } else {
214 if(verbose>0) fprintf(stderr, "Warning: missing Image Orientation (Patient).\n");
215 }
216 if(ret1==0 && ret2==0) { // calculate xform into IMG
217 double xform[16];
218 ret=dcmImgXform(iop, pxlsize, ipp, xform, verbose-2);
219 if(ret==0) {
220 img->xform[0]=1;
221 for(int i=0; i<12; i++) img->srow[i]=(float)xform[i];
222 double quatern[3], qoffset[3];
223 if(dcmXformToQuatern(xform, quatern, qoffset, verbose-2)==0) {
224 for(int i=0; i<3; i++) img->quatern[i]=(float)quatern[i];
225 for(int i=0; i<3; i++) img->quatern[3+i]=(float)qoffset[i];
226 }
227 }
228 }
229 }
230
231
232 /* Get Accession Number and write it in IMG as studyNr */
233 {
234 img->studyNr[0]=(char)0;
235 DCMITEM *iptr; DCMTAG tag; dcmTagSet(&tag, 0x0008, 0x0050);
236 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
237 if(iptr!=NULL) {
238 char *buf=dcmValueString(iptr); if(verbose>12) printf("Accession Number := '%s'\n", buf);
239 if(buf!=NULL && strlen(buf)>1) strncpyClean(img->studyNr, buf, MAX_STUDYNR_LEN+1);
240 free(buf);
241 }
242 if(!strcasecmp(img->studyNr, "empty")) img->studyNr[0]=(char)0;
243 }
244 /* If not successful, then try Patient ID */
245 if(!img->studyNr[0]) {
246 DCMITEM *iptr; DCMTAG tag; dcmTagSet(&tag, 0x0010, 0x0020);
247 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
248 if(iptr!=NULL) {
249 char *buf=dcmValueString(iptr); if(verbose>12) printf("Patient ID := '%s'\n", buf);
250 if(buf!=NULL && strlen(buf)>1) strncpyClean(img->studyNr, buf, MAX_STUDYNR_LEN+1);
251 free(buf);
252 }
253 }
254
255
256 /* Get pixel data scaling factors */
257 double rescale_intercept=0.0, rescale_slope=0.0;
258 {
259 DCMTAG tag; DCMITEM *iptr, *jptr;
260 dcmTagSet(&tag, 0x0040, 0x9096);
261 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
262 if(iptr==NULL) {
263 if(verbose>0) fprintf(stderr, "Error: missing Real World Value Mapping Sequence.\n");
264 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
265 imgFree(img); dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
266 }
267 dcmTagSet(&tag, 0x0040, 0x9224);
268 jptr=dcmFindDownTag(iptr->child_item, 0, &tag, 0);
269 if(jptr!=NULL) rescale_intercept=dcmitemGetReal(jptr);
270 dcmTagSet(&tag, 0x0040, 0x9225);
271 jptr=dcmFindDownTag(iptr->child_item, 0, &tag, 0);
272 if(jptr!=NULL) rescale_slope=dcmitemGetReal(jptr);
273 if(rescale_slope<=0.0 && verbose>0) {
274 fprintf(stderr, "Warning: rescale_slope := %g\n", rescale_slope); fflush(stderr);
275 } else if(verbose>14) {
276 printf("rescale_slope := %g\n", rescale_slope);
277 printf("rescale_intercept := %g\n", rescale_intercept); // always 0 for PET
278 }
279 /* Unit */
280 dcmTagSet(&tag, 0x0040, 0x9210);
281 jptr=dcmFindDownTag(iptr->child_item, 0, &tag, 0);
282 if(jptr!=NULL) {
283 char *buf=dcmValueString(jptr); if(verbose>14) printf(" buf := '%s'\n", buf);
284 strClean(buf); img->cunit=unitIdentify(buf);
285 free(buf);
286 }
287 if(verbose>14) printf("image_unit := %s\n", unitName(img->cunit));
288 }
289
290 /* Fill IMG pixel values */
291 {
292 DCMTAG tag; dcmTagSet(&tag, 0x7fe0, 0x0010);
293 DCMITEM *iptr=dcmFindTag(dcm.item, 0, &tag, 0);
294 if(iptr==NULL || iptr->rd==NULL) {
295 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
296 imgFree(img); dcmfileFree(&dcm); return(TPCERROR_NO_DATA);
297 }
298 unsigned long long bi=0, byteNr=iptr->vl;
299 if(verbose>13) printf(" pixel data byteNr := %llu\n", byteNr);
300
301 char *cptr=iptr->rd;
302 short int s;
303 for(unsigned int ti=0; ti<img->dimt; ti++) {
304 for(unsigned int zi=0; zi<img->dimz; zi++)
305 for(unsigned int yi=0; yi<img->dimy; yi++)
306 for(unsigned int xi=0; xi<img->dimx; xi++) {
307 if(bi>=byteNr) {printf("missing pixel data\n"); fflush(stdout); break;}
308 memcpy(&s, cptr, 2); cptr+=2; bi+=2;
309 img->m[zi][yi][xi][ti]=(float)(rescale_slope*(double)s + rescale_intercept);
310 }
311 }
312 }
313
314
315 dcmfileFree(&dcm);
316
317 /* Set IMG header fields */
318 img->modality=modality;
321 strcpy(img->scanStart, zeroDateTime);
322
323 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
324 return(TPCERROR_OK);
325}
double strDateTimeDifference(const char *dt1, const char *dt0)
Definition datetime.c:519
long int dcmitemGetInt(DCMITEM *d)
Definition dcmdata.c:295
void dcmfileInit(DCMFILE *d)
Definition dcmdata.c:22
void dcmTagSet(DCMTAG *tag, unsigned short int group, unsigned short int element)
Definition dcmdata.c:483
DCMITEM * dcmFindTag(DCMITEM *d, const short int omit, DCMTAG *tag, const int verbose)
Definition dcmdata.c:375
DCMITEM * dcmFindDownTag(DCMITEM *d, const short int omit, DCMTAG *tag, const int verbose)
Definition dcmdata.c:428
void dcmfileFree(DCMFILE *d)
Definition dcmdata.c:67
void dcmitemPrint(DCMITEM *d)
Definition dcmdata.c:467
double dcmitemGetReal(DCMITEM *d)
Definition dcmdata.c:331
char * dcmValueString(DCMITEM *d)
Definition dcmdata.c:141
int dcmImgPxlsize(DCMFILE *d, double *pxlsize, const int verbose)
Definition dcmimage.c:320
int dcmImgDim(DCMFILE *d, unsigned short int *imgdim, const int verbose)
Definition dcmimage.c:232
int dcmImgOrient(DCMFILE *d, double *iop, const int verbose)
Definition dcmimage.c:387
int dcmImgIsotope(DCMFILE *d, isotope *isot, decaycorrection *dc, const int verbose)
Definition dcmimage.c:24
int dcmImgPos(DCMFILE *d, double *imgpos, const int verbose)
Definition dcmimage.c:121
int dcmXformToQuatern(double *xform, double *quatern, double *qoffset, const int verbose)
Definition dcmimage.c:540
int dcmImgXform(double *iop, double *xyzMM, double *imgPos, double *xform, const int verbose)
Definition dcmimage.c:431
int dcmFileRead(const char *filename, DCMFILE *dcm, const short int headerOnly, TPCSTATUS *status)
Definition dcmio.c:768
char * dcmDT2intl(const char *orig, char *intl)
Definition dcmvr.c:225
char * decayDescr(decaycorrection d)
Definition decay.c:32
int imgAllocate(IMG *img, const unsigned int dimz, const unsigned int dimy, const unsigned int dimx, const unsigned int dimt, TPCSTATUS *status)
Definition image.c:126
int strncpyClean(char *s1, const char *s2, int maxlen)
Definition stringext.c:321
int strClean(char *s)
Definition stringext.c:389
DCMITEM * item
Definition tpcdcm.h:164
struct DCMITEM * child_item
Definition tpcdcm.h:143
struct DCMITEM * next_item
Definition tpcdcm.h:147
unsigned int vl
Definition tpcdcm.h:141
char * rd
Definition tpcdcm.h:152
@ TPCERROR_NO_KEY
Key not found.

Referenced by imgRead().

◆ imgReadNifti()

int imgReadNifti ( IMG * img,
const char * fname,
TPCSTATUS * status )
extern

Read NIfTI into IMG data structure.

Note
NIfTI may have missing pixel values (NaNs), remove those with imgNaNs(IMG, 1) when necessary.
Todo
Add tests.
See also
imgInit, imgRead, imgWrite, imgFree, imgNaNs, niftiCreateFNames
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to image structure. Any previous contents removed.
fnamePointer to the database name. Path alone not accepted.
statusPointer to status data; enter NULL if not needed.

Definition at line 72 of file imagenii.c.

79 {
80 int verbose=0; if(status!=NULL) verbose=status->verbose;
81 if(verbose>0) {printf("%s(..., %s, ...)\n", __func__, fname); fflush(stdout);}
82
83 if(img==NULL || strnlen(fname, 2)<1) {
84 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
85 return(TPCERROR_FAIL);
86 }
87 /* Delete any old contents in data structure */
88 imgFree(img);
89
90 /* Get NIfTI filenames, check existence, and read header */
91 if(verbose>1) printf("checking that %s exists and is NIfTI\n", fname);
92 char hdrfile[FILENAME_MAX], imgfile[FILENAME_MAX], siffile[FILENAME_MAX];
93 NIFTI_DSR dsr;
94 if(!niftiExists(fname, hdrfile, imgfile, siffile, &dsr, status)) {
95 if(status!=NULL) return(status->error);
96 else return(TPCERROR_FAIL);
97 }
98 if(verbose>1) printf("NIfTI header read from %s\n", hdrfile);
99
100 /* Get data type and check that it is currently supported */
101 if(verbose>2) printf(" verifying datatype\n");
102 int datatype=0;
103 if(dsr.n==1) datatype=dsr.h1.datatype; else datatype=dsr.h2.datatype;
104 switch(datatype) {
108 case NIFTI_DT_FLOAT:
109 case NIFTI_DT_DOUBLE:
115 break;
116 case NIFTI_DT_UNKNOWN:
117 case NIFTI_DT_BINARY:
118 case NIFTI_DT_COMPLEX:
119 case NIFTI_DT_RGB:
120 case NIFTI_DT_ALL:
124 case NIFTI_DT_RGBA:
125 default:
126 if(verbose>0) printf("Error: currently unsupported NIfTI datatype %d\n", datatype);
127 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
128 return(TPCERROR_UNSUPPORTED);
129 }
130 int bitpix=0;
131 if(dsr.n==1) bitpix=dsr.h1.bitpix; else bitpix=dsr.h2.bitpix;
132 if(verbose>2) printf(" bits per pixel := %d\n", bitpix);
133 if(bitpix==0) { // Carimas Nifti Writer does not set bitpix
134 if(datatype==NIFTI_DT_UNSIGNED_SHORT) bitpix=16;
135 }
136 if(bitpix<8 || (bitpix%8)!=0) { // We don't support bit data
137 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
138 return(TPCERROR_UNSUPPORTED);
139 }
140 if(bitpix>64) { // We don't currently support 128 bit data or larger
141 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
142 return(TPCERROR_UNSUPPORTED);
143 }
144 int bytepix=bitpix/8; if(verbose>2) printf(" bytes per pixel := %d\n", bytepix);
145
146
147 /* Allocate memory for 4D image */
148 {
149 int ret=imgGetNiftiHeader(img, &dsr, verbose-1); // Get the image dimensions
150 if(ret!=TPCERROR_OK) {
151 statusSet(status, __func__, __FILE__, __LINE__, ret);
152 return(ret);
153 }
154 if(verbose>1) printf("allocating memory for 4D image\n");
155 ret=imgAllocate(img, img->dimz, img->dimy, img->dimx, img->dimt, status);
156 if(ret) return(ret);
157 }
158
159 /* Copy header contents into IMG structure */
160 {
161 int ret=imgGetNiftiHeader(img, &dsr, verbose-1);
162 if(ret!=TPCERROR_OK) {
163 statusSet(status, __func__, __FILE__, __LINE__, ret);
164 return(ret);
165 }
166 if(verbose>2) printf("format: %s\n", imgFormatDescr(img->format));
167 }
168
169 /* Open file */
170 if(verbose>1) printf("reading pixel data in %s\n", imgfile);
171 FILE *fp=fopen(imgfile, "rb");
172 if(fp==NULL) {
173 imgFree(img);
174 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN);
175 return(TPCERROR_CANNOT_OPEN);
176 }
177
178
179 /* Set initial read position.
180 Get the image data start location from header, in case of single file format */
181 long long start_pos=0;
182 {
183 long long int s=0;
184 if(dsr.n==1) s=(int)dsr.h1.vox_offset; else s=(int)dsr.h2.vox_offset;
185 if(s<0) start_pos=-s; else start_pos=s;
186 /* Check that start location is not earlier than it can by definition; it can be later, though */
189 start_pos=s;
190 }
191 if(verbose>2) printf(" image_start_pos := %llu\n", start_pos);
192 /* Seek the data position, jumping over possible header */
193 if(start_pos>0) {
194 fseeko(fp, start_pos, SEEK_SET);
195 if(ftello(fp)!=start_pos) {
196 fclose(fp); imgFree(img);
197 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
199 }
200 }
201
202 /* Allocate memory for one frame of the binary data */
203 long long pxlNr=img->dimx*img->dimy*img->dimz;
204 if(verbose>2) printf(" pixels/frame := %llu\n", pxlNr);
205 long long rawSize=pxlNr*(bitpix/8);
206 if(verbose>1) printf(" raw bytes per frame := %lld\n", rawSize);
207 if(verbose>1) printf(" allocating memory for raw binary data\n");
208 unsigned char *buf=(unsigned char*)malloc(rawSize);
209 if(buf==NULL) {
210 fclose(fp); imgFree(img);
211 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
213 }
214
215 /* Read the data, frame-by-frame */
216 if(verbose>1) printf(" reading binary data\n");
217 int little=endianLittle(); // Are we on little endian platform?
218 int byteconv=0;
219 if(little!=dsr.byte_order) {
220 byteconv=1;
221 if(verbose>1) printf(" byte conversion needed\n");
222 }
223 /* Get scaling factors */
224 float scl_slope, scl_inter;
225 if(dsr.n==1) {scl_slope=dsr.h1.scl_slope; scl_inter=dsr.h1.scl_inter;}
226 else {scl_slope=dsr.h2.scl_slope; scl_inter=dsr.h2.scl_inter;}
227 if(scl_slope==0.0) scl_slope=1.0;
228
229 for(int ti=0; ti<img->dimt; ti++) {
230 if(verbose>3) printf(" frame %d\n", 1+ti);
231 if(fread(buf, rawSize, 1, fp) < 1) {
232 fclose(fp); imgFree(img); free(buf);
233 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_READ);
234 return(TPCERROR_CANNOT_READ);
235 }
236 /* Convert byte order if necessary */
237 if(byteconv) switch(bitpix) {
238 case 8: /* no conversion needed */ break;
239 case 16: swap16ip(buf, pxlNr); break;
240 case 32: swap32ip(buf, pxlNr); break;
241 case 64: swap64ip(buf, pxlNr); break;
242 default: /* others not supported */ break;
243 }
244 /* Copy data to float pixel values */
245 int ret=0;
246 unsigned char *bptr=buf;
247 switch(datatype) {
250 if(bitpix!=8) {ret=1; break;}
251 for(int zi=0; zi<img->dimz; zi++)
252 for(int yi=0; yi<img->dimy; yi++)
253 for(int xi=0; xi<img->dimx; xi++) {
254 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*(float)(*bptr);
255 bptr++;
256 }
257 break;
259 if(bitpix!=16) {ret=1; break;}
260 for(int zi=0; zi<img->dimz; zi++)
261 for(int yi=0; yi<img->dimy; yi++)
262 for(int xi=0; xi<img->dimx; xi++) {
263 uint16_t a;
264 memcpy(&a, bptr, 2);
265 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*(float)a;
266 bptr+=bytepix;
267 }
268 break;
270 if(bitpix!=16) {ret=1; break;}
271 for(int zi=0; zi<img->dimz; zi++)
272 for(int yi=0; yi<img->dimy; yi++)
273 for(int xi=0; xi<img->dimx; xi++) {
274 int16_t a;
275 memcpy(&a, bptr, 2);
276 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*(float)a;
277 bptr+=bytepix;
278 }
279 break;
281 if(bitpix!=32) {ret=1; break;}
282 for(int zi=0; zi<img->dimz; zi++)
283 for(int yi=0; yi<img->dimy; yi++)
284 for(int xi=0; xi<img->dimx; xi++) {
285 int32_t a;
286 memcpy(&a, bptr, 4);
287 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*(float)a;
288 bptr+=bytepix;
289 }
290 break;
292 if(bitpix!=32) {ret=1; break;}
293 for(int zi=0; zi<img->dimz; zi++)
294 for(int yi=0; yi<img->dimy; yi++)
295 for(int xi=0; xi<img->dimx; xi++) {
296 uint32_t a;
297 memcpy(&a, bptr, 4);
298 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*(float)a;
299 bptr+=bytepix;
300 }
301 break;
303 if(bitpix!=64) {ret=1; break;}
304 for(int zi=0; zi<img->dimz; zi++)
305 for(int yi=0; yi<img->dimy; yi++)
306 for(int xi=0; xi<img->dimx; xi++) {
307 int64_t a;
308 memcpy(&a, bptr, 8);
309 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*(float)a;
310 bptr+=bytepix;
311 }
312 break;
314 if(bitpix!=64) {ret=1; break;}
315 for(int zi=0; zi<img->dimz; zi++)
316 for(int yi=0; yi<img->dimy; yi++)
317 for(int xi=0; xi<img->dimx; xi++) {
318 uint64_t a;
319 memcpy(&a, bptr, 8);
320 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*(float)a;
321 bptr+=bytepix;
322 }
323 break;
324 case NIFTI_DT_FLOAT:
325 if(bitpix!=32) {ret=1; break;}
326 for(int zi=0; zi<img->dimz; zi++)
327 for(int yi=0; yi<img->dimy; yi++)
328 for(int xi=0; xi<img->dimx; xi++) {
329 float a;
330 memcpy(&a, bptr, 4);
331 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*a;
332 bptr+=bytepix;
333 }
334 break;
335 case NIFTI_DT_DOUBLE:
336 if(bitpix!=64) {ret=1; break;}
337 for(int zi=0; zi<img->dimz; zi++)
338 for(int yi=0; yi<img->dimy; yi++)
339 for(int xi=0; xi<img->dimx; xi++) {
340 double a;
341 memcpy(&a, bptr, 8);
342 img->m[zi][yi][xi][ti]=scl_inter+scl_slope*(float)a;
343 bptr+=bytepix;
344 }
345 break;
346 default:
347 ret=2;
348 }
349 if(ret) {
350 fclose(fp); imgFree(img); free(buf);
351 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
352 return(TPCERROR_UNSUPPORTED);
353 }
354 } // next frame
355 fclose(fp); free(buf);
356
357
358 /* Read SIF, if available */
359 if(siffile[0]) {
360 if(verbose>0) {printf("reading SIF %s\n", siffile); fflush(stdout);}
361 TAC sif; tacInit(&sif);
362 int ret=tacRead(&sif, siffile, status);
363 if(ret!=TPCERROR_OK) {imgFree(img); return(ret);}
364 ret=imgFromSIF(img, &sif, 1, 1, 0, verbose-1);
365 tacFree(&sif);
366 if(ret!=TPCERROR_OK) {
367 imgFree(img);
368 statusSet(status, __func__, __FILE__, __LINE__, ret);
369 return(ret);
370 }
371 }
372
373 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
374 return(TPCERROR_OK);
375}
void swap32ip(void *buf, unsigned long long size)
Definition endian.c:210
void swap64ip(void *buf, unsigned long long size)
Definition endian.c:184
int endianLittle()
Definition endian.c:53
void swap16ip(void *buf, unsigned long long size)
Definition endian.c:234
int imgGetNiftiHeader(IMG *img, NIFTI_DSR *dsr, int verbose)
Definition imagenii.c:794
int imgFromSIF(IMG *img, TAC *sif, int copy_header, int copy_frames, int copy_counts, int verbose)
Definition imagesif.c:126
short int datatype
Definition tpcnifti.h:243
short int bitpix
Definition tpcnifti.h:245
float vox_offset
Definition tpcnifti.h:251
float scl_inter
Definition tpcnifti.h:255
float scl_slope
Definition tpcnifti.h:253
int64_t vox_offset
Definition tpcnifti.h:333
int16_t datatype
Definition tpcnifti.h:317
double scl_inter
Definition tpcnifti.h:337
double scl_slope
Definition tpcnifti.h:335
int16_t bitpix
Definition tpcnifti.h:319
int byte_order
Definition tpcnifti.h:412
Definition tpctac.h:87
void tacFree(TAC *tac)
Definition tac.c:106
void tacInit(TAC *tac)
Definition tac.c:24
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
@ TPCERROR_CANNOT_OPEN
Cannot open file.
@ TPCERROR_CANNOT_READ
Cannot read file.
#define NIFTI_DT_LONG_DOUBLE
Definition tpcnifti.h:120
#define NIFTI_DT_RGB
Definition tpcnifti.h:106
#define NIFTI_DT_BINARY
Definition tpcnifti.h:92
#define NIFTI_DT_FLOAT
Definition tpcnifti.h:100
#define NIFTI_DT_UNSIGNED_SHORT
Definition tpcnifti.h:112
#define NIFTI_DT_SIGNED_SHORT
Definition tpcnifti.h:96
#define NIFTI_DT_UNSIGNED_INT
Definition tpcnifti.h:114
#define NIFTI_DT_UNSIGNED_LONG_LONG
Definition tpcnifti.h:118
#define NIFTI_DT_SIGNED_INT
Definition tpcnifti.h:98
#define NIFTI_DT_ALL
Definition tpcnifti.h:108
#define NIFTI_DT_UNSIGNED_CHAR
Definition tpcnifti.h:94
#define NIFTI1_HEADER_SIZE
Definition tpcnifti.h:33
#define NIFTI_DT_COMPLEX
Definition tpcnifti.h:102
#define NIFTI2_HEADER_SIZE
Definition tpcnifti.h:37
#define NIFTI_DT_DOUBLE_PAIR
Definition tpcnifti.h:122
#define NIFTI_DT_RGBA
Definition tpcnifti.h:126
#define NIFTI_DT_UNKNOWN
Definition tpcnifti.h:90
#define NIFTI_DT_SIGNED_CHAR
Definition tpcnifti.h:110
#define NIFTI_DT_LONG_LONG
Definition tpcnifti.h:116
#define NIFTI_DT_DOUBLE
Definition tpcnifti.h:104
#define NIFTI_DT_LONG_DOUBLE_PAIR
Definition tpcnifti.h:124

Referenced by imgRead().

◆ imgSetNiftiHeader()

int imgSetNiftiHeader ( IMG * img,
NIFTI_DSR * dsr,
int verbose )
extern

Copy header information in IMG structure into NIfTI header structure.

Header contents will depend on the output format as specified in IMG->oformat, which can be set to IMG_FORMAT_NIFTI_1D, IMG_FORMAT_NIFTI_1S, IMG_FORMAT_NIFTI_2D, or IMG_FORMAT_NIFTI_2S. NIFTI_DSR->n will tell whether NIfTI-1 or NIfTI-2 header was filled.

Todo
Add tests.
See also
imgGetNiftiHeader, imgWriteNifti, niftiWriteHeader
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to IMG structure from which header information is read.
dsrPointer to NIfTI header structure to be filled; any previous contents are removed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 576 of file imagenii.c.

583 {
584 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
585
586 if(img==NULL || imgHasData(img)==0 || dsr==NULL) return(TPCERROR_FAIL);
587
588 /* Check file format */
589 switch(img->oformat) {
591 dsr->n=1;
592 break;
594 dsr->n=1;
595 break;
597 dsr->n=2;
598 break;
600 dsr->n=2;
601 break;
602 default:
604 }
605
606 /* Find pixel value range */
607 float pmin, pmax;
608 int ret=imgMinMax(img, &pmin, &pmax);
609 if(ret!=TPCERROR_OK) return(ret);
610 if(verbose>1) {printf(" min=%g\n max=%g\n", pmin, pmax); fflush(stdout);}
611
612 /* Set NIfTI byte order to current machines byte order */
614
615 /* Initiate header structures with zeroes */
616 memset(&dsr->h1, 0, sizeof(NIFTI_1_HEADER));
617 memset(&dsr->h2, 0, sizeof(NIFTI_2_HEADER));
618 memset(&dsr->e, 0, sizeof(NIFTI_EXTENDER));
619
620
621 /* Set header */
622 if(dsr->n==1) { // NIfTI-1
623
624 dsr->h1.sizeof_hdr=NIFTI1_HEADER_SIZE; // 348
625 strcpy(dsr->h1.data_type, ""); // not used in NIfTI
626 strcpy(dsr->h1.db_name, ""); // not used in NIfTI
627 dsr->h1.extents=16384; // not used in NIfTI, but required for Analyze compatibility
628 dsr->h1.regular='r'; // not used in NIfTI, but required for Analyze compatibility
629 dsr->h1.dim_info='\0'; // MRI slice ordering
630 if(img->oformat==IMG_FORMAT_NIFTI_1S) {
632 strcpy(dsr->h1.magic, "n+1");
633 } else {
634 dsr->h1.vox_offset=0;
635 strcpy(dsr->h1.magic, "ni1");
636 }
637 strcpy(dsr->h1.aux_file, "");
638
639 /* Image dimension */
640 for(int i=0; i<8; i++) dsr->h1.dim[i]=1;
641 dsr->h1.dim[0]=4;
642 dsr->h1.dim[1]=img->dimx;
643 dsr->h1.dim[2]=img->dimy;
644 dsr->h1.dim[3]=img->dimz;
645 dsr->h1.dim[4]=img->dimt;
646
647 /* Intent */
649 dsr->h1.intent_p1=0.0;
650 dsr->h1.intent_p2=0.0;
651 dsr->h1.intent_p3=0.0;
652 strcpy(dsr->h1.intent_name, "");
653
654 /* Save data as floats, so that there is no need to scale */
656 dsr->h1.bitpix=32; // bits per pixel
657 dsr->h1.scl_slope=1.0; // data as floats, so no need to scale
658 dsr->h1.scl_inter=0.0; // data as floats, so no need to scale
659 dsr->h1.glmax=pmax; // unused in NIfTI
660 dsr->h1.glmin=pmin; // unused in NIfTI
661 dsr->h1.cal_max=pmax;
662 dsr->h1.cal_min=0.0; // scale display colours to have black at zero
663
664 /* Pixel size */
665 dsr->h1.slice_start=0;
666 for(int i=0; i<8; i++) dsr->h1.pixdim[i]=0.0;
667 // https://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/qsform.html
668 dsr->h1.pixdim[0]=1.0; // Set to either 1.0 or -1.0; default should be 1.0.
669 dsr->h1.pixdim[1]=img->sizex;
670 dsr->h1.pixdim[2]=img->sizey;
671 dsr->h1.pixdim[3]=img->sizez;
672 dsr->h1.slice_end=0;
673 dsr->h1.slice_code=0;
674 dsr->h1.xyzt_units=NIFTI_UNITS_MM; // Voxel size in mm in IMG structure
675 dsr->h1.slice_duration=0.0;
676 dsr->h1.toffset=0.0;
677
678 /* Coordinate system */
679 dsr->h1.qform_code=img->xform[0];
680 dsr->h1.sform_code=img->xform[1];
681 dsr->h1.quatern_b=img->quatern[0];
682 dsr->h1.quatern_c=img->quatern[1];
683 dsr->h1.quatern_d=img->quatern[2];
684 dsr->h1.qoffset_x=img->quatern[3];
685 dsr->h1.qoffset_y=img->quatern[4];
686 dsr->h1.qoffset_z=img->quatern[5];
687
688 /* Save pixel units into description (not standard NIfTI) */
689 if(img->cunit==UNIT_UNKNOWN) strcpy(dsr->h1.descrip, "");
690 else strlcpy(dsr->h1.descrip, unitName(img->cunit), 80);
691
692 for(int i=0; i<4; i++) dsr->h1.srow_x[i]=img->srow[i];
693 for(int i=0; i<4; i++) dsr->h1.srow_y[i]=img->srow[4+i];
694 for(int i=0; i<4; i++) dsr->h1.srow_z[i]=img->srow[8+i];
695
696 /* Extension is left as 0 0 0 0 */
697
698 } else { // NIfTI-2
699
700 /* Header size. Used for identifying the format and endianness of data */
701 dsr->h2.sizeof_hdr=NIFTI2_HEADER_SIZE; // 540
702
703 /* Magic string. Used for identifying the format and verifying validity */
704 if(img->oformat==IMG_FORMAT_NIFTI_2S) strcpy(dsr->h2.magic, "n+2");
705 else strcpy(dsr->h2.magic, "ni2");
706 dsr->h2.magic[3]='\0';
707 dsr->h2.magic[4]='\r';
708 dsr->h2.magic[5]='\n';
709 dsr->h2.magic[6]=(char)32;
710 dsr->h2.magic[7]='\n';
711
712 /* Save data as 32-bit floats, so that there is no need to scale */
714 dsr->h2.bitpix=32; // bits per pixel
715
716 /* Image dimensions */
717 for(int i=0; i<8; i++) dsr->h2.dim[i]=1;
718 dsr->h2.dim[0]=4;
719 dsr->h2.dim[1]=img->dimx;
720 dsr->h2.dim[2]=img->dimy;
721 dsr->h2.dim[3]=img->dimz;
722 dsr->h2.dim[4]=img->dimt;
723
724 /* Intent */
726 dsr->h2.intent_p1=0.0;
727 dsr->h2.intent_p2=0.0;
728 dsr->h2.intent_p3=0.0;
729 strcpy(dsr->h2.intent_name, "");
730
731 /* Grid spacings */
732 dsr->h2.pixdim[0]=1.0; // Set to either 1.0 or -1.0; default should be 1.0.
733 dsr->h2.pixdim[1]=img->sizex;
734 dsr->h2.pixdim[2]=img->sizey;
735 dsr->h2.pixdim[3]=img->sizez;
736 for(int i=4; i<8; i++) dsr->h2.pixdim[i]=0.0;
737
738 /* Offset into pixel data; zero for dual file */
739 if(img->oformat==IMG_FORMAT_NIFTI_2S) {
741 } else {
742 dsr->h2.vox_offset=0;
743 }
744
745 /* Scaling */
746 dsr->h2.scl_slope=1.0; // data as floats, so no need to scale
747 dsr->h2.scl_inter=0.0; // data as floats, so no need to scale
748 dsr->h2.cal_max=pmax;
749 dsr->h2.cal_min=0.0; // scale display colours to have black at zero
750
751 dsr->h2.slice_duration=0.0;
752 dsr->h2.toffset=0.0;
753 dsr->h2.slice_start=0;
754 dsr->h2.slice_end=img->dimz-1;
755
756 /* Save pixel units into description (not standard NIfTI) */
757 if(img->cunit==UNIT_UNKNOWN) strcpy(dsr->h2.descrip, "");
758 else strlcpy(dsr->h2.descrip, unitName(img->cunit), 80);
759
760 strcpy(dsr->h2.aux_file, "");
761
762 /* Coordinate system */
763 dsr->h2.qform_code=img->xform[0];
764 dsr->h2.sform_code=img->xform[1];
765 dsr->h2.quatern_b=img->quatern[0];
766 dsr->h2.quatern_c=img->quatern[1];
767 dsr->h2.quatern_d=img->quatern[2];
768 dsr->h2.qoffset_x=img->quatern[3];
769 dsr->h2.qoffset_y=img->quatern[4];
770 dsr->h2.qoffset_z=img->quatern[5];
771 for(int i=0; i<4; i++) dsr->h2.srow_x[i]=img->srow[i];
772 for(int i=0; i<4; i++) dsr->h2.srow_y[i]=img->srow[4+i];
773 for(int i=0; i<4; i++) dsr->h2.srow_z[i]=img->srow[8+i];
774
775 dsr->h2.slice_code=0;
777 dsr->h2.dim_info='\0'; // MRI slice ordering
778
779 /* Extension is left as 0 0 0 0 */
780
781 }
782
783 return(TPCERROR_OK);
784}
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Definition image.c:396
char db_name[18]
Definition tpcnifti.h:220
short int slice_start
Definition tpcnifti.h:247
short int slice_end
Definition tpcnifti.h:257
float slice_duration
Definition tpcnifti.h:267
float intent_p2
Definition tpcnifti.h:237
char aux_file[24]
Definition tpcnifti.h:278
float intent_p1
Definition tpcnifti.h:235
char intent_name[16]
Definition tpcnifti.h:303
float intent_p3
Definition tpcnifti.h:239
char data_type[10]
Definition tpcnifti.h:218
short int intent_code
Definition tpcnifti.h:241
char aux_file[24]
Definition tpcnifti.h:353
double slice_duration
Definition tpcnifti.h:343
double cal_min
Definition tpcnifti.h:341
double intent_p2
Definition tpcnifti.h:327
int64_t slice_start
Definition tpcnifti.h:347
double intent_p3
Definition tpcnifti.h:329
int64_t slice_end
Definition tpcnifti.h:349
double intent_p1
Definition tpcnifti.h:325
double toffset
Definition tpcnifti.h:345
double cal_max
Definition tpcnifti.h:339
char intent_name[16]
Definition tpcnifti.h:384
NIFTI_EXTENDER e
Definition tpcnifti.h:408
#define NIFTI1_HEADER_EXTENDER_SIZE
Definition tpcnifti.h:35
#define NIFTI2_HEADER_EXTENDER_SIZE
Definition tpcnifti.h:39
#define NIFTI_INTENT_NONE
Definition tpcnifti.h:129
#define NIFTI_UNITS_SEC
Definition tpcnifti.h:52

Referenced by imgWriteNifti().

◆ imgToSIF()

int imgToSIF ( IMG * img,
TAC * sif,
int copy_header,
int copy_frames,
int copy_counts,
int verbose )
extern

Set SIF contents based on data in IMG.

Todo
Add tests.
See also
imgFromSIF, imgInit, tacInit, imgWrite, tacWrite, tacWriteSIF
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to IMG struct from which content is copied to SIF.
sifPointer to SIF, which actually is stored as a TAC format. Previous contents are optionally kept.
Precondition
Must be initialized with tacInit().
Parameters
copy_headerSelect whether header contents are copied (1) or not copied (0) to SIF.
copy_framesSelect whether frame times are copied (1) or not copied (0) to SIF.
copy_countsSelect whether counts are copied (1) or not copied (0) to SIF, or created if they do not exist (2).
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 18 of file imagesif.c.

35 {
36 if(verbose>0) {
37 printf("%s(img, sif, %d, %d, %d, ...)\n", __func__, copy_header, copy_frames, copy_counts);
38 fflush(stdout);
39 }
40
41 if(img==NULL || sif==NULL) return(TPCERROR_FAIL);
42
43 /* Verify that IMG contains frame times */
44 if(!imgHasTimes(img)) {
45 if(verbose>0) printf(" image does not contain frame times.\n");
46 /* If not, then frame times cannot be copied */
47 copy_frames=0;
48 /* and counts can not be created */
49 if(copy_counts==2) copy_counts=1;
50 }
51
52 /* Check if count data needs to be created */
53 if(copy_counts==2 && imgHasCounts(img)!=0) copy_counts=1;
54
55 /* Verify that IMG contains isotope information */
56 if(img->isot==ISOTOPE_UNKNOWN) {
57 if(verbose>0) printf(" image does not contain isotope halflife.\n");
58 /* not, then count data can not be created */
59 if(copy_counts==2) copy_counts=1;
60 }
61
62 /* Allocate memory for SIF if necessary */
63 int ret=0;
64 if(sif->sampleNr<1 || sif->tacNr<1) {
65 ret=tacAllocate(sif, img->dimt, 2);
66 sif->sampleNr=img->dimt; sif->tacNr=2;
67 } else if((copy_frames || copy_counts) && sif->sampleNr!=img->dimt) {
68 if(sif->sampleNr<img->dimt)
69 ret=tacAllocateMoreSamples(sif, img->dimt-sif->sampleNr);
70 sif->sampleNr=img->dimt;
71 }
72 if((copy_frames || copy_counts) && sif->tacNr<2) {
73 ret=tacAllocateMore(sif, 2-sif->tacNr);
74 sif->tacNr=2;
75 }
76 if(ret!=0) return(TPCERROR_OUT_OF_MEMORY);
77
78 /* Copy SIF header */
79 if(copy_header) {
80 if(verbose>1) printf(" copying header fields.\n");
82 tacSetHeaderStudynr(&sif->h, img->studyNr);
83 tacSetIsotope(sif, img->isot);
84 }
85
86 /* Copy frame times */
87 if(copy_frames) {
88 if(verbose>1) printf(" copying frame times.\n");
89 for(int i=0; i<img->dimt; i++) {
90 sif->x1[i]=img->x1[i]; sif->x2[i]=img->x2[i]; sif->x[i]=img->x[i];
91 }
92 sif->tunit=UNIT_SEC;
93 }
94
95 /* Copy counts */
96 if(copy_counts==1) {
97 if(verbose>1) printf(" copying count data.\n");
98 for(int i=0; i<img->dimt; i++) {
99 sif->c[0].y[i]=img->prompts[i];
100 sif->c[1].y[i]=img->randoms[i];
101 }
102 }
103
104 /* Create counts, if required and possible */
105 if(copy_counts==2) {
106 if(verbose>1) printf(" creating count data.\n");
107
108 fprintf(stderr, "Warning: imgToSIF() does not yet guess counts.\n"); fflush(stderr);
109
110 for(int i=0; i<img->dimt; i++) {
111 sif->c[0].y[i]=0.0;
112 sif->c[1].y[i]=0.0;
113 }
114 }
115
116 return(TPCERROR_OK);
117}
double * x
Definition tpctac.h:97
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
int tacAllocateMoreSamples(TAC *tac, int addNr)
Allocate memory for more samples in TAC data.
Definition tac.c:435
int tacAllocateMore(TAC *tac, int tacNr)
Definition tac.c:178
void tacSetIsotope(TAC *tac, int isotope)
Definition tacdc.c:41
int tacSetHeaderScanstarttime(IFT *h, const char *s)
Definition tacift.c:427
int tacSetHeaderStudynr(IFT *h, const char *s)
Definition tacift.c:79
@ UNIT_SEC
seconds

Referenced by imgWriteNifti().

◆ imgWrite()

int imgWrite ( IMG * img,
const char * fname,
TPCSTATUS * status )
extern

Write image file from IMG structure.

Remarks
Stub function.
See also
imgInit, imgRead, imgFree
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to image structure.
fnamePointer to the file name, possibly path in case of DICOM.
statusPointer to status data; enter NULL if not needed.

Definition at line 214 of file imageio.c.

221 {
222 int verbose=0; if(status!=NULL) verbose=status->verbose;
223 if(verbose>0) {printf("%s(img, %s)\n", __func__, fname); fflush(stdout);}
224
225 if(img==NULL || strnlen(fname, 2)<1) {
226 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
227 return(TPCERROR_FAIL);
228 }
229 if(!imgHasData(img)) {
230 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
231 return(TPCERROR_NO_DATA);
232 }
233
234 /* Based on file name, guess file format, and use it, or check that specified format is ok */
235 imgformat format=imgFormatFromFName(fname, NULL);
236 if(format!=IMG_FORMAT_UNKNOWN) {
237 if(img->oformat==IMG_FORMAT_UNKNOWN) {
238 img->oformat=format;
239 if(verbose>1)
240 printf("based on file name, output format set to %s\n", imgFormatDescr(img->oformat));
241 } else if(format!=img->oformat) {
242 if(verbose>1)
243 printf("file name is not suitable for format %s\n", imgFormatDescr(img->oformat));
244 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
246 }
247 }
248 /* If output format is not yet set, then use input format */
250 img->oformat=img->format;
251 if(verbose>1) printf("output set to same as input format (%s)\n", imgFormatDescr(img->oformat));
252 }
253 /* If output format still unknown, set it to singe-file NIfTI */
254 if(img->oformat==IMG_FORMAT_UNKNOWN) {
256 if(verbose>1) printf("output format set to default (%s)\n", imgFormatDescr(img->oformat));
257 }
258
259 /* Fill output header */
260 if(imgFillOHeader(img, status)!=TPCERROR_OK) return(TPCERROR_INVALID_HEADER);
261
262 /* Write image */
263 if(img->oformat==IMG_FORMAT_DICOM) {
264
265 if(verbose>1) printf("writing %s\n", imgFormatDescr(img->oformat));
266
267 } else if(img->oformat==IMG_FORMAT_NIFTI_1D || img->oformat==IMG_FORMAT_NIFTI_1S) {
268
269 if(verbose>1) printf("writing %s\n", imgFormatDescr(img->oformat));
270 return(imgWriteNifti(img, fname, status));
271
272 } else if(img->oformat==IMG_FORMAT_E7) {
273
274 if(verbose>1) printf("writing %s\n", imgFormatDescr(img->oformat));
275
276 /* Create main header data block */
277 unsigned char mh[ECATBLKSIZE];
278 int ret=ecatWriteMainheader(&img->oh, mh, status);
279 if(ret!=TPCERROR_OK) return(ret);
280
281 /* Open file, write main header block, and initiate matrix list */
282
283 /* Process each frame */
284 for(unsigned int ti=0; ti<img->dimt; ti++) {
285 /* Create subheader data block */
286
287 /* Create blocks for pixel data */
288
289 /* Write header and data blocks */
290
291 }
292
293 /* Close file */
294
295 } else if(img->oformat==IMG_FORMAT_E63) {
296
297 if(verbose>1) printf("writing %s\n", imgFormatDescr(img->oformat));
298
299 /* Create main header data block */
300
301 /* Open file, write main header block, and initiate matrix list */
302
303 /* Process each plane and frame */
304 for(unsigned int ti=0; ti<img->dimt; ti++) {
305 for(unsigned int zi=0; zi<img->dimz; zi++) {
306 /* Create subheader data block */
307
308 /* Create blocks for pixel data */
309
310 /* Write header and data blocks */
311
312 }
313 }
314
315 /* Close file */
316
317 } else if(img->oformat==IMG_FORMAT_FLAT) {
318
319 if(verbose>1) printf("writing %s\n", imgFormatDescr(img->oformat));
320 FILE *fp=NULL;
321 float *fdata=NULL, *fptr;
322 if(verbose>2) printf("opening %s\n", fname);
323 if((fp=fopen(fname, "wb")) == NULL) {
324 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
325 return(TPCERROR_CANNOT_WRITE);
326 }
327 /* Allocate memory for float data for one frame */
328 unsigned long long pxlNr=img->dimz*img->dimy*img->dimx;
329 if(verbose>2) printf("allocating memory for %llu pixels\n", pxlNr);
330 fdata=(float*)malloc(pxlNr*sizeof(float));
331 if(fdata==NULL) {
332 fclose(fp);
333 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
335 }
336 /* Write one frame at a time */
337 if(verbose>2) printf("writing frame at a time\n");
338 for(int ti=0; ti<img->dimt; ti++) {
339 fptr=fdata;
340 for(int zi=0; zi<img->dimz; zi++)
341 for(int yi=0; yi<img->dimy; yi++)
342 for(int xi=0; xi<img->dimx; xi++)
343 *fptr++=img->m[zi][yi][xi][ti];
344 if(fwrite((float*)fdata, 4, pxlNr, fp) != pxlNr) {
345 fclose(fp); remove(fname); free(fdata);
346 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
347 return(TPCERROR_CANNOT_WRITE);
348 }
349 } /* next frame */
350 /* Close file, free memory */
351 fclose(fp); free(fdata);
352 if(verbose>2) printf("binary file written\n");
353 /* Write matrix information file; no error if not successful. */
354 char miffile[strlen(fname)+5]; sprintf(miffile, "%s.mif", fname);
355 if(verbose>2) printf("opening matrix information file %s\n", miffile);
356 if((fp=fopen(miffile, "w")) == NULL) {
357 if(verbose>0) fprintf(stderr, "Error: cannot open MIF for write.\n");
358 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
359 return(TPCERROR_OK);
360 }
361 if(verbose>2) printf("writing matrix information file %s\n", miffile);
362 int n=fprintf(fp, "%d %d %d %d\n", img->dimz, img->dimt, img->dimx, img->dimy);
363 fclose(fp);
364 if(n<7) {
365 if(verbose>0) fprintf(stderr, "Error: cannot write in file %s\n", miffile);
366 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
367 return(TPCERROR_OK);
368 }
369 if(verbose>2) printf("matrix information saved in %s\n", miffile);
370
371 } else {
372 if(verbose>0) printf("output format (%s) not supported\n", imgFormatDescr(img->oformat));
373 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
374 return(TPCERROR_UNSUPPORTED);
375 }
376
377 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
378 return(TPCERROR_OK);
379}
int ecatWriteMainheader(IFT *ift, unsigned char *buf, TPCSTATUS *status)
Definition ecatheader.c:25
int imgFillOHeader(IMG *img, TPCSTATUS *status)
Definition imageheader.c:61
imgformat imgFormatFromFName(const char *fname, TPCSTATUS *status)
Definition imageio.c:394
int imgWriteNifti(IMG *img, const char *fname, TPCSTATUS *status)
Definition imagenii.c:390
#define ECATBLKSIZE
Definition tpcecat.h:37
@ TPCERROR_INVALID_FILENAME
Invalid file name.
@ TPCERROR_CANNOT_WRITE
Cannot write file.

◆ imgWriteDICOM()

int imgWriteDICOM ( IMG * img,
const char * fname,
TPCSTATUS * status )
extern

Write DICOM image into IMG data structure.

Remarks
Stub function.
Todo
Add tests.
See also
imgInit, imgRead, imgWrite, imgFree, imgReadDICOM
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to image structure.
fnamePointer to the name of DICOM folder. Must be empty or not exist.
statusPointer to status data; obligatory.

Definition at line 335 of file imagedcm.c.

342 {
343 if(status==NULL) return(TPCERROR_FAIL);
344 if(status->verbose>1) {printf("%s(..., %s, ...)\n", __func__, fname); fflush(stdout);}
345 if(img==NULL || img->dimt<1 || img->dimz<1) {
346 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA); return(status->error);}
347 if(fname==NULL || strnlen(fname, 1)<1) {
348 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME); return(status->error);}
349
350 /*
351 * Make DCMFILE data structure
352 */
353 DCMFILE dcm; dcmfileInit(&dcm);
354 /* Set Transfer UID */
356 {
357 DCMTAG tag;
358 unsigned int ul;
359 char buf[256];
360
361 /* Meta Element Group */
362 dcmTagSet(&tag, 0x0002, 0x0000); ul=0;
363 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UL, 0xFFFFFFFF, (char*)&ul, 0);
364 dcmTagSet(&tag, 0x0002, 0x0001); // File Meta Information Version
365 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_OB, 2, "\0\1", 0);
366 dcmTagSet(&tag, 0x0002, 0x0002); // Media Stored SOP Class UID
367 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UI, 0xFFFFFFFF, "1.2.840.10008.5.1.4.1.1.128", 0);
368 dcmTagSet(&tag, 0x0002, 0x0003); // Media Stored SOP Instance UID
369 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UI, 0xFFFFFFFF, "1.2.826.0.1.3417726.3.0.20180616", 0);
370 dcmTagSet(&tag, 0x0002, 0x0010); // Transfer Syntax UID
371 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UI, 0xFFFFFFFF, dcmTrUIDString(dcm.truid), 0);
372 dcmTagSet(&tag, 0x0002, 0x0012); // Implementation Class UID
373 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UI, 0xFFFFFFFF, "1.3.6.1.4.1.25403.1.1.1", 0);
374 dcmTagSet(&tag, 0x0002, 0x0013); // Implementation Version Name
375 snprintf(buf, 256, "TPCCLIB_%d.%d.%d", tpcclib_VERSION_MAJOR, tpcclib_VERSION_MINOR, tpcclib_VERSION_PATCH);
376 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_SH, 0xFFFFFFFF, buf, 0);
377
378 /* Identifying Group */
379 dcmTagSet(&tag, 0x0008, 0x0000); ul=0;
380 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UL, 0xFFFFFFFF, (char*)&ul, 0);
381 dcmTagSet(&tag, 0x0008, 0x0008); // Image Type
382 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_CS, 17, "ORIGINAL/PRIMARY", 0);
383 {
384 time_t t=time(NULL);
385 struct tm *local_tm; local_tm=localtime(&t);
386 dcmTagSet(&tag, 0x0008, 0x0012); // Instance Creation Date
387 strftime(buf, 256, "%Y%m%d", local_tm);
388 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_DA, 0xFFFFFFFF, buf, 0);
389 dcmTagSet(&tag, 0x0008, 0x0013); // Instance Creation Time
390 strftime(buf, 256, "%H%M%S", local_tm);
391 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_DA, 0xFFFFFFFF, buf, 0);
392 }
393 dcmTagSet(&tag, 0x0008, 0x0016); // SOP Class UID; see dcmsop.c
394 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UI, 0xFFFFFFFF, "1.2.840.10008.5.1.4.1.1.128", 0);
395 dcmTagSet(&tag, 0x0008, 0x0018); // SOP Instance UID
396 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UI, 0xFFFFFFFF, "1.2.826.0.1.3417726.3.0.20180616", 0);
397 dcmTagSet(&tag, 0x0008, 0x0060); // Modality
398 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_CS, 3, "PT", 0);
399
400 /* Acquisition Group */
401 dcmTagSet(&tag, 0x0018, 0x0000); ul=0;
402 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UL, 0xFFFFFFFF, (char*)&ul, 0);
403 dcmTagSet(&tag, 0x0018, 0x0050); // Slice thickness (mm)
404 snprintf(buf, 256, "%g", img->sizez);
405 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_DS, 0xFFFFFFFF, buf, 0);
406 dcmTagSet(&tag, 0x0018, 0x1075); // half-life
407 if(img->isot!=ISOTOPE_UNKNOWN) {
408 snprintf(buf, 256, "%g", 60.0*isotopeHalflife(img->isot));
409 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_DS, 0xFFFFFFFF, buf, 0);
410 }
411
412 /* Relationship Group */
413 dcmTagSet(&tag, 0x0020, 0x0000); ul=0;
414 dcmAddItem(&dcm, NULL, 0, tag, DCM_VR_UL, 0xFFFFFFFF, (char*)&ul, 0);
415
416
417
418 }
419
420
421 /* Create folder, or if it already exists check that it is empty */
422 if(pathExist(fname)) {
423 if(status->verbose>2) {
424 fprintf(stdout, " checking that folder '%s' is empty\n", fname); fflush(stdout);}
425 if(pathFileNr(fname)>0) {
426 dcmfileFree(&dcm);
427 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FILE_EXISTS);
428 return(status->error);
429 }
430 } else {
431 if(status->verbose>2) {
432 fprintf(stdout, " creating subdirectory '%s'\n", fname); fflush(stdout);}
433 if(pathCreate(fname)) {
434 dcmfileFree(&dcm);
435 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
436 return(status->error);
437 }
438 }
439
440 /*
441 * Write each image plane in its own DICOM file
442 */
443 for(int zi=0; zi<img->dimz; zi++) {
444 char dname[strlen(fname)+25];
445 snprintf(dname, strlen(fname)+25, "%s/%0*d.dcm", fname, 1+(int)floor(log10(img->dimz)), 1+zi);
446 if(status->verbose>2) {printf(" writing '%s'\n", dname); fflush(stdout);}
447
448 /* Write */
449 dcmFileWrite(dname, &dcm, status);
450 if(status->error!=TPCERROR_OK) {
451 dcmfileFree(&dcm);
452 dcmFileRemove(dname, NULL);
453 pathRemove(fname);
454 return(status->error);
455 }
456 } // next plane
457 dcmfileFree(&dcm);
458
459 if(0) { // Remove files and empty folder in case of error
460 dcmFileRemove(fname, NULL);
461 pathRemove(fname);
462 }
463
464 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
465 return(TPCERROR_OK);
466}
int dcmAddItem(DCMFILE *dcm, DCMITEM *d, short int aschild, DCMTAG tag, dcmvr vr, unsigned int vl, char *rd, const int verbose)
Definition dcmdata.c:501
int dcmFileRemove(const char *filename, TPCSTATUS *status)
Remove DICOM files belonging to one image.
Definition dcmfile.c:270
int dcmFileWrite(const char *filename, DCMFILE *dcm, TPCSTATUS *status)
Definition dcmio.c:852
char * dcmTrUIDString(dcmtruid id)
Definition dcmuid.c:105
double isotopeHalflife(int isotope_code)
Definition isotope.c:62
int pathCreate(const char *pathname)
Definition pathexist.c:81
int pathRemove(const char *pathname)
Definition pathexist.c:43
dcmtruid truid
Definition tpcdcm.h:162
@ DCM_VR_UI
DICOM unique identifier (UID), max 64 bytes.
Definition tpcdcm.h:117
@ DCM_VR_CS
DICOM code (control) string, max 16 bytes.
Definition tpcdcm.h:95
@ DCM_VR_SH
DICOM short string, max 16 chars.
Definition tpcdcm.h:110
@ DCM_VR_OB
DICOM other byte string, even bytes, endian insensitive.
Definition tpcdcm.h:104
@ DCM_VR_DA
DICOM date in format YYYYMMDD, 8 bytes fixed.
Definition tpcdcm.h:96
@ DCM_VR_UL
DICOM unsigned long (32-bit) integer, 4 bytes fixed.
Definition tpcdcm.h:118
@ DCM_VR_DS
DICOM decimal string, max 16 bytes.
Definition tpcdcm.h:97
@ DCM_TRUID_LEE
Little Endian Explicit VR.
Definition tpcdcm.h:60
@ TPCERROR_FILE_EXISTS
File exists.

◆ imgWriteNifti()

int imgWriteNifti ( IMG * img,
const char * fname,
TPCSTATUS * status )
extern

Write NIfTI from IMG data structure.

IMG field oformat (or secondarily format) determines whether NIfTI is written in single file format (*.nii) or dual file format (*.hdr and *.img).

SIF file is saved to store frame times, if frame times are available.

Todo
Add tests.
See also
imgInit, imgRead, imgWrite, imgFree, niftiCreateFNames, niftiWriteHeader
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to image structure. Any previous contents removed.
fnamePointer to the database name. Path not accepted.
statusPointer to status data; enter NULL if not needed.

Definition at line 390 of file imagenii.c.

397 {
398 int verbose=0; if(status!=NULL) verbose=status->verbose;
399 if(verbose>0) {printf("%s(..., %s, ...)\n", __func__, fname); fflush(stdout);}
400
401 if(img==NULL || strnlen(fname, 2)<1) {
402 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
403 return(TPCERROR_FAIL);
404 }
405 if(!imgHasData(img)) {
406 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
407 return(TPCERROR_NO_DATA);
408 }
409
410 /* Determine the output format */
411 if(verbose>1) {printf("determine output format\n"); fflush(stdout);}
412 if(img->oformat==IMG_FORMAT_UNKNOWN) {
413 char *cptr=filenameGetExtension(fname);
414 if(cptr!=NULL && strcasecmp(cptr, ".nii")==0) img->oformat=IMG_FORMAT_NIFTI_1S;
415 else img->oformat=img->format;
416 }
420
421 /* Get database name, in case file name was given with extension */
422 if(verbose>1) {printf("get dbname\n"); fflush(stdout);}
423 char basename[FILENAME_MAX];
424 strlcpy(basename, fname, FILENAME_MAX); niftiBasename(basename);
425 /* Check that there is something left after path */
426 char basenamewopath[FILENAME_MAX];
427 strcpy(basenamewopath, basename); filenameRmPath(basenamewopath);
428 if(strlen(basenamewopath)<1) {
429 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
431 }
432 /* Create output file names (now to catch some errors) */
433 if(verbose>1) {printf("determine output file names\n"); fflush(stdout);}
434 char hdrfile[FILENAME_MAX], imgfile[FILENAME_MAX], siffile[FILENAME_MAX];
435 hdrfile[0]=imgfile[0]=siffile[0]=(char)0;
436 if(niftiCreateFNames(basename, hdrfile, imgfile, siffile, img->oformat)!=TPCERROR_OK) {
437 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
439 }
440 /* If we have path, then create it */
441 char filepath[FILENAME_MAX];
442 strcpy(filepath, basename); filenameRmFile(filepath);
443 if(pathCreate(filepath)) {
444 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
446 }
447
448
449 /* Fill the header structure */
450 NIFTI_DSR dsr;
451 int ret=imgSetNiftiHeader(img, &dsr, verbose-1);
452 if(ret!=TPCERROR_OK) {
453 statusSet(status, __func__, __FILE__, __LINE__, ret);
454 return(ret);
455 }
456
457 /* Delete previous NIfTI */
458 if(verbose>1) {printf("removing any previous files\n"); fflush(stdout);}
459 if(fileExist(hdrfile)) remove(hdrfile);
460 if(fileExist(imgfile)) remove(imgfile);
461 //if(fileExist(siffile)) remove(siffile); // NO, not this!
462
463 /* Write the header */
464 if(verbose>1) {printf("writing the header\n"); fflush(stdout);}
466 ret=niftiWriteHeader(hdrfile, &dsr, verbose-1);
467 } else if(img->oformat==IMG_FORMAT_NIFTI_1S || img->oformat==IMG_FORMAT_NIFTI_2S) {
468 ret=niftiWriteHeader(imgfile, &dsr, verbose-1);
469 }
470 if(ret!=TPCERROR_OK) {
471 statusSet(status, __func__, __FILE__, __LINE__, ret);
472 return(ret);
473 }
474 /* Write the pixel data */
475 if(verbose>1) {printf("opening file for pixel data\n"); fflush(stdout);}
476 FILE *fp;
478 fp=fopen(imgfile, "wb");
479 } else { // if(img->oformat==IMG_FORMAT_NIFTI_1S || if(img->oformat==IMG_FORMAT_NIFTI_2S
480 fp=fopen(imgfile, "r+b");
481 }
482 if(fp==NULL) {
483 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN);
484 return(TPCERROR_CANNOT_OPEN);
485 }
486 /* Move pointer to the start of pixel data */
487 long int pos;
488 if(dsr.n==1) pos=(int)dsr.h1.vox_offset; else pos=(int)dsr.h2.vox_offset;
489 if(fseek(fp, pos, SEEK_SET)!=0) {
490 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
491 fclose(fp); return(TPCERROR_CANNOT_WRITE);
492 }
493 /* Allocate memory for pixel matrix */
494 unsigned long long voxNr=img->dimt*img->dimz*img->dimy*img->dimx;
495 float *fdata;
496 fdata=(float*)calloc(voxNr, sizeof(float));
497 if(fdata==NULL) {
498 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
499 fclose(fp); return(TPCERROR_OUT_OF_MEMORY);
500 }
501 /* Write voxel values as floats */
502 float *fptr=fdata;
503 for(unsigned int fi=0; fi<img->dimt; fi++)
504 for(unsigned int zi=0; zi<img->dimz; zi++)
505 for(unsigned int yi=0; yi<img->dimy; yi++)
506 for(unsigned int xi=0; xi<img->dimx; xi++, fptr++)
507 *fptr=img->m[zi][yi][xi][fi];
508 if(verbose>1) {printf("writing pixel data\n"); fflush(stdout);}
509 fptr=fdata;
510 if(fwrite(fptr, sizeof(float), voxNr, fp) != voxNr) {
511 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
512 free(fdata); fclose(fp); return(TPCERROR_CANNOT_WRITE);
513 }
514
515 free(fdata);
516 fclose(fp);
517
518 /* Frame times into SIF */
519 if(!imgHasTimes(img)) { // no frame times to save
520 if(verbose>1) printf(" no frame times to save into SIF\n");
521 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
522 return(TPCERROR_OK);
523 }
524 {
525 if(verbose>1) {printf("making SIF\n"); fflush(stdout);}
526 TAC sif; tacInit(&sif);
527 /* Try to read existing SIF */
528 if(fileExist(siffile) && tacRead(&sif, siffile, status)==TPCERROR_OK && sif.sampleNr==img->dimt)
529 {
530 /* If SIF was found and frameNr matches with image, then update the SIF contents,
531 but keep counts, in case previous SIF comes with actual count info from scanner */
532 ret=imgToSIF(img, &sif, 1, 1, 0, verbose-3);
533 } else {
534 /* otherwise create SIF contents */
535 ret=imgToSIF(img, &sif, 1, 1, 2, verbose-3);
536 }
537 if(ret!=TPCERROR_OK) {
538 if(verbose>0) fprintf(stderr, " Error: cannot create SIF contents.\n");
539 tacFree(&sif);
540 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
541 return(TPCERROR_INVALID_X);
542 }
543 if(verbose>1) {printf("writing SIF\n"); fflush(stdout);}
544 fp=fopen(siffile, "w");
545 if(fp==NULL) {
546 tacFree(&sif);
547 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN);
548 return(TPCERROR_CANNOT_OPEN);
549 }
550 ret=tacWrite(&sif, fp, TAC_FORMAT_SIF, 0, status);
551 fclose(fp); tacFree(&sif);
552 if(ret!=TPCERROR_OK) {
553 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
554 return(TPCERROR_CANNOT_WRITE);
555 }
556 }
557
558
559 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
560 return(TPCERROR_OK);
561}
void filenameRmFile(char *s)
Definition filename.c:44
char * filenameGetExtension(const char *s)
Get the last extension of a file name.
Definition filename.c:178
void filenameRmPath(char *s)
Definition filename.c:20
int imgSetNiftiHeader(IMG *img, NIFTI_DSR *dsr, int verbose)
Definition imagenii.c:576
int niftiCreateFNames(const char *filename, char *hdrfile, char *imgfile, char *siffile, int fileformat)
Definition imagenii.c:17
int imgToSIF(IMG *img, TAC *sif, int copy_header, int copy_frames, int copy_counts, int verbose)
Definition imagesif.c:18
int niftiWriteHeader(const char *filename, NIFTI_DSR *dsr, int verbose)
Definition niftiio.c:445
void niftiBasename(char *filename)
Definition niftiname.c:14
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
Definition tacio.c:332
@ TPCERROR_INVALID_X
Invalid sample time.

Referenced by imgWrite().

◆ imgXRange()

int imgXRange ( IMG * img,
double * xmin,
double * xmax )
extern

Get the range of x values (times) in the image data.

Data is not modified. Data does not need to be sorted.

See also
imgMinMax, imgHasData
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to IMG structure.
xminPointer to variable for min x value (NULL if not needed).
xmaxPointer to variable for max x value (NULL if not needed).

Definition at line 430 of file image.c.

437 {
438 if(xmin!=NULL) *xmin=nan("");
439 if(xmax!=NULL) *xmax=nan("");
440 if(img==NULL || !imgHasData(img)) return(TPCERROR_FAIL);
441 float f1=nanf(""), f2=nanf("");
442 for(int i=0; i<img->dimt; i++) {
443 if(isfinite(img->x1[i])) {
444 if(isnan(f1) || img->x1[i]<f1) f1=img->x1[i];
445 }
446 if(isfinite(img->x2[i])) {
447 if(isnan(f2) || img->x2[i]>f2) f2=img->x2[i];
448 }
449 }
450 if(xmin!=NULL) *xmin=f1;
451 if(xmax!=NULL) *xmax=f2;
452 if(isnan(f1) || isnan(f2)) return(TPCERROR_FAIL);
453 return(TPCERROR_OK);
454}

◆ imgXUnitConvert()

int imgXUnitConvert ( IMG * img,
const int u )

Convert X values (frame times) in IMG structure to the specified unit.

See also
tacXUnitConvert, unitConversionFactor
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
imgPointer to IMG structure.
uEnum unit

Definition at line 462 of file image.c.

467 {
468 if(img==NULL || img->dimt<1) return(TPCERROR_NO_DATA);
469
470 /* If both units are unknown, then return suitable error code */
472
473 /* Determine the correction factor */
474 double cf;
475 cf=unitConversionFactor(img->tunit, u);
476 if(isnan(cf)) return(TPCERROR_INCOMPATIBLE_UNIT);
477
478 /* Multiply x values */
479 for(int i=0; i<img->dimt; i++) {
480 img->x[i]*=cf; img->x1[i]*=cf; img->x2[i]*=cf;
481 }
482 /* Set new unit in the header */
483 img->tunit=u;
484
485 return(TPCERROR_OK);
486}
@ TPCERROR_UNKNOWN_UNIT
Unknown data unit.
@ TPCERROR_INCOMPATIBLE_UNIT
Incompatible units.
double unitConversionFactor(const int u1, const int u2)
Definition units.c:487

◆ niftiCreateFNames()

int niftiCreateFNames ( const char * filename,
char * hdrfile,
char * imgfile,
char * siffile,
int fileformat )
extern

Construct the file names for NIfTI image.

See also
imgReadNifti, imgWriteNifti, niftiRemoveFNameExtension
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
filenameFilename, either header file, image file, or base name without extensions, but possibly with path name. This string is never modified.
hdrfileHeader filename will be written in this char pointer (space needs to allocated by caller); in single file format this will be set to the name of the single file; enter NULL if not needed.
imgfileImage filename will be written in this char pointer (space needs to allocated by caller); in single file format this will be set to the name of the single file; enter NULL if not needed.
siffileSIF filename will be written in this char pointer (space needs to allocated by caller); enter NULL if not needed.
fileformatNIfTI file format, either IMG_FORMAT_NIFTI_1D, IMG_FORMAT_NIFTI_1S, IMG_NIFTI_FORMAT_2D, or IMG_FORMAT_NIFTI_2S.

Definition at line 17 of file imagenii.c.

35 {
36 if(hdrfile!=NULL) strcpy(hdrfile, "");
37 if(imgfile!=NULL) strcpy(imgfile, "");
38 if(siffile!=NULL) strcpy(siffile, "");
39 if(filename==NULL) return(TPCERROR_INVALID_FILENAME);
40
41 char basename[FILENAME_MAX];
42 strlcpy(basename, filename, FILENAME_MAX); niftiBasename(basename);
43 /* Check that there is something left after path */
44 char basenamewopath[FILENAME_MAX];
45 strcpy(basenamewopath, basename); filenameRmPath(basenamewopath);
46 if(strlen(basenamewopath)<1) return(TPCERROR_INVALID_FILENAME);
47
48 /* Create database filenames */
49 if(fileformat==IMG_FORMAT_NIFTI_1D || fileformat==IMG_FORMAT_NIFTI_2D) {
50 if(hdrfile!=NULL) snprintf(hdrfile, FILENAME_MAX, "%s.hdr", basename);
51 if(imgfile!=NULL) snprintf(imgfile, FILENAME_MAX, "%s.img", basename);
52 } else if(fileformat==IMG_FORMAT_NIFTI_1S || fileformat==IMG_FORMAT_NIFTI_2S) {
53 if(hdrfile!=NULL) snprintf(hdrfile, FILENAME_MAX, "%s.nii", basename);
54 if(imgfile!=NULL) snprintf(imgfile, FILENAME_MAX, "%s.nii", basename);
55 } else {
57 }
58 if(siffile!=NULL) snprintf(siffile, FILENAME_MAX, "%s.sif", basename);
59
60 return(TPCERROR_OK);
61}

Referenced by imgWriteNifti().