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) {
37 }
38
39
41
42
46
47
48
49
51 {
53 if(iptr==NULL) {
54 if(verbose>0) {fprintf(stderr, "Error: cannot find modality.\n"); fflush(stderr);}
57 }
59 if(verbose>12) printf("Modality := '%s'\n", buf);
64 else if(verbose>0) fprintf(stderr, "Warning: modality '%s' not supported.\n", buf);
65 free(buf);
66 }
67
68
69 if(verbose>10) {printf("reading matrix dimensions\n"); fflush(stdout);}
70 unsigned short int imgdim[4];
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);}
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
84
85 ret=
imgAllocate(img, sliceNr, dimy, dimx, frameNr, status);
87
88
89
91 if(ret!=0 && verbose>0) {
92 fprintf(stderr, "Warning: decay correction and isotope unknown.\n"); fflush(stderr);
93 }
94 if(verbose>11) {
97 fflush(stdout);
98 }
99
100
101 char zeroDateTime[32]; zeroDateTime[0]=(char)0;
106 } else {
107
111 }
112 if(!zeroDateTime[0]) {
113 if(verbose>0) fprintf(stderr, "Error: missing Acquisition Date and Time.\n");
116 }
117 if(verbose>14) printf("zeroDateTime := %s\n", zeroDateTime);
118
119
121
122 for(
unsigned short int i=0; i<img->
dimt; i++) img->
x1[i]=img->
x2[i]=img->
x[i]=nanf(
"");
123
124
127 if(iptr==NULL) {
128 if(verbose>0) fprintf(stderr, "Error: Per Frame Functional Groups Sequence not found.\n");
131 }
132
138 while(fptr!=NULL) {
139
141 if(verbose>20) printf(" found Frame Content Sequence\n");
143
145 if(jptr==NULL) {fptr=fptr->
next_item;
continue;}
147 unsigned short int frameIndex=(
unsigned short int)(
dcmitemGetInt(jptr)-1);
148
150 char facqDateTime[32]; facqDateTime[0]=(char)0;
152 if(!facqDateTime[0]) {
153 if(verbose>0) fprintf(stderr, "Error: missing Frame Acquisition DateTime.\n");
156 }
157 if(verbose>20) printf("facqDateTime := %s\n", facqDateTime);
158
160
161 if(frameIndex<img->dimt) {
162 if(isnan(img->
x1[frameIndex])) {
163
164 img->
x1[frameIndex]=t1;
165 if(verbose>29) printf("t1[%u]=%g\n", frameIndex, t1);
166 } else {
167
169
170 if(verbose>1) printf(" different t1=%g\n", t1);
171 }
172 }
173 }
174
175
177 if(jptr==NULL) {fptr=fptr->
next_item;
continue;}
179 if(frameIndex<img->dimt) {
181 img->
x[frameIndex]=0.5*(img->
x1[frameIndex]+img->
x2[frameIndex]);
182 }
183
185 }
186 }
187
188
189 {
190 double pxlsize[3];
192 if(ret!=0) {
193 if(verbose>0) fprintf(stderr, "Error: missing Pixel size.\n");
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];
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) {
217 double xform[16];
218 ret=
dcmImgXform(iop, pxlsize, ipp, xform, verbose-2);
219 if(ret==0) {
221 for(
int i=0; i<12; i++) img->
srow[i]=(
float)xform[i];
222 double quatern[3], qoffset[3];
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
233 {
237 if(iptr!=NULL) {
238 char *buf=
dcmValueString(iptr);
if(verbose>12) printf(
"Accession Number := '%s'\n", buf);
240 free(buf);
241 }
243 }
244
248 if(iptr!=NULL) {
249 char *buf=
dcmValueString(iptr);
if(verbose>12) printf(
"Patient ID := '%s'\n", buf);
251 free(buf);
252 }
253 }
254
255
256
257 double rescale_intercept=0.0, rescale_slope=0.0;
258 {
262 if(iptr==NULL) {
263 if(verbose>0) fprintf(stderr, "Error: missing Real World Value Mapping Sequence.\n");
266 }
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);
278 }
279
282 if(jptr!=NULL) {
283 char *buf=
dcmValueString(jptr);
if(verbose>14) printf(
" buf := '%s'\n", buf);
285 free(buf);
286 }
287 if(verbose>14) printf(
"image_unit := %s\n",
unitName(img->
cunit));
288 }
289
290
291 {
294 if(iptr==NULL || iptr->
rd==NULL) {
297 }
298 unsigned long long bi=0, byteNr=iptr->
vl;
299 if(verbose>13) printf(" pixel data byteNr := %llu\n", byteNr);
300
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
316
317
322
325}
double strDateTimeDifference(const char *dt1, const char *dt0)
long int dcmitemGetInt(DCMITEM *d)
void dcmfileInit(DCMFILE *d)
void dcmTagSet(DCMTAG *tag, unsigned short int group, unsigned short int element)
DCMITEM * dcmFindTag(DCMITEM *d, const short int omit, DCMTAG *tag, const int verbose)
DCMITEM * dcmFindDownTag(DCMITEM *d, const short int omit, DCMTAG *tag, const int verbose)
void dcmfileFree(DCMFILE *d)
void dcmitemPrint(DCMITEM *d)
double dcmitemGetReal(DCMITEM *d)
char * dcmValueString(DCMITEM *d)
int dcmImgPxlsize(DCMFILE *d, double *pxlsize, const int verbose)
int dcmImgDim(DCMFILE *d, unsigned short int *imgdim, const int verbose)
int dcmImgOrient(DCMFILE *d, double *iop, const int verbose)
int dcmImgIsotope(DCMFILE *d, isotope *isot, decaycorrection *dc, const int verbose)
int dcmImgPos(DCMFILE *d, double *imgpos, const int verbose)
int dcmXformToQuatern(double *xform, double *quatern, double *qoffset, const int verbose)
int dcmImgXform(double *iop, double *xyzMM, double *imgPos, double *xform, const int verbose)
int dcmFileRead(const char *filename, DCMFILE *dcm, const short int headerOnly, TPCSTATUS *status)
char * dcmDT2intl(const char *orig, char *intl)
char * decayDescr(decaycorrection d)
int floatMatch(const float v1, const float v2, const float lim)
int imgAllocate(IMG *img, const unsigned int dimz, const unsigned int dimy, const unsigned int dimx, const unsigned int dimt, TPCSTATUS *status)
char * isotopeName(int isotope_code)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
size_t strnlen(const char *s, size_t n)
int strncpyClean(char *s1, const char *s2, int maxlen)
struct DCMITEM * child_item
struct DCMITEM * next_item
decaycorrection decayCorrection
char studyNr[MAX_STUDYNR_LEN+1]
int verbose
Verbose level, used by statusPrint() etc.
@ TPCERROR_FAIL
General error.
@ TPCERROR_NO_KEY
Key not found.
@ TPCERROR_NO_DATA
File contains no data.
int unitIdentify(const char *s)
char * unitName(int unit_code)
#define MAX_STUDYNR_LEN
Define max study number length.
@ IMG_MODALITY_SPECT
SPECT.
@ IMG_MODALITY_UNKNOWN
Unknown modality.
@ IMG_CONTENT_IMAGE
Image data.
@ DECAY_CORRECTED
Data is corrected for physical decay.