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

Processing DICOM image matrices. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "tpcextensions.h"
#include "tpcdcm.h"

Go to the source code of this file.

Functions

void dcmmatrixInit (DCMMATRIX *m)
 
void dcmmatrixFree (DCMMATRIX *m)
 
void dcmmlInit (DCMML *d)
 
void dcmmlFree (DCMML *d)
 
int dcmmlAllocate (DCMML *d, int mNr)
 
int dcmMListRead (IFT *ift, DCMML *ml, TPCSTATUS *status)
 
int dcmmlSortByPlane (DCMML *d, TPCSTATUS *status)
 

Detailed Description

Processing DICOM image matrices.

Definition in file dcmmatrix.c.

Function Documentation

◆ dcmmatrixFree()

void dcmmatrixFree ( DCMMATRIX * m)

Free memory allocated for DCMMATRIX data. All contents are destroyed.

Precondition
Before first use initialize the struct with dcmmatrixInit().
See also
dcmmatrixInit
Author
Vesa Oikonen
Parameters
mPointer to DCMMATRIX.

Definition at line 40 of file dcmmatrix.c.

43 {
44 if(m==NULL) return;
45 if(m->filename!=NULL) free(m->filename);
47}
void dcmmatrixInit(DCMMATRIX *m)
Definition dcmmatrix.c:22
char * filename
Definition tpcdcm.h:175

Referenced by dcmmlFree().

◆ dcmmatrixInit()

void dcmmatrixInit ( DCMMATRIX * m)

Initiate the DCMMATRIX struct before any use.

See also
dcmmatrixFree
Parameters
mPointer to DCMMATRIX.

Definition at line 22 of file dcmmatrix.c.

25 {
26 if(m==NULL) return;
27 m->filename=NULL;
28 m->acqDate[0]=m->acqTime[0]=(char)0;
29 m->frame=m->plane=0;
30 m->frameStart=m->frameDur=0.0;
31}
double frameDur
Definition tpcdcm.h:188
unsigned int plane
Definition tpcdcm.h:184
double frameStart
Definition tpcdcm.h:186
char acqTime[16]
Definition tpcdcm.h:179
char acqDate[16]
Definition tpcdcm.h:177
unsigned int frame
Definition tpcdcm.h:182

Referenced by dcmmatrixFree(), and dcmmlAllocate().

◆ dcmmlAllocate()

int dcmmlAllocate ( DCMML * d,
int mNr )

Allocate more memory for DCMML data. Previous contents are preserved.

Returns
Returns TPCERROR status.
See also
dcmmlInit, dcmmlFree
Parameters
dPointer to initiated and possibly previously allocated DCMML struct data; any old contens are preserved.
mNrNr of additional matrices to allocate; if struct contains unused space for requested number already, then nothing is done.

Definition at line 89 of file dcmmatrix.c.

96 {
97 if(d==NULL) return TPCERROR_FAIL;
98 /* Check if there is enough space already */
99 unsigned int newNr, addNr;
100 newNr=d->nr+mNr;
101 if(d->anr>=newNr) return TPCERROR_OK;
102 addNr=newNr-d->anr;
103
104 /* (Re)allocate memory. */
105 DCMMATRIX *mptr;
106 mptr=(DCMMATRIX*)realloc(d->m, sizeof(DCMMATRIX)*newNr);
107 if(mptr==NULL) return TPCERROR_OUT_OF_MEMORY;
108 d->m=mptr;
109 mptr=d->m+d->anr; for(unsigned int i=0; i<addNr; i++) dcmmatrixInit(mptr++);
110 d->anr=newNr;
111 return TPCERROR_OK;
112}
DCMMATRIX * m
Definition tpcdcm.h:198
unsigned int anr
Definition tpcdcm.h:196
unsigned int nr
Definition tpcdcm.h:194
@ TPCERROR_FAIL
General error.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_OK
No error.

Referenced by dcmMListRead().

◆ dcmmlFree()

void dcmmlFree ( DCMML * d)

Free memory allocated for DCMML data. All contents are destroyed.

Precondition
Before first use initialize the struct with dcmmlInit().
See also
dcmmlInit
Author
Vesa Oikonen
Parameters
dPointer to DCMML.

Definition at line 70 of file dcmmatrix.c.

73 {
74 if(d==NULL) return;
75 if(d->m!=NULL) {
76 for(unsigned int i=0; i<d->anr; i++) dcmmatrixFree(d->m+i);
77 free(d->m);
78 }
79 dcmmlInit(d);
80}
void dcmmlInit(DCMML *d)
Definition dcmmatrix.c:54
void dcmmatrixFree(DCMMATRIX *m)
Definition dcmmatrix.c:40

Referenced by dcmMListRead().

◆ dcmmlInit()

void dcmmlInit ( DCMML * d)

Initiate the DCMML struct before any use.

See also
dcmmlFree
Parameters
dPointer to DCMMLIST.

Definition at line 54 of file dcmmatrix.c.

57 {
58 if(d==NULL) return;
59 d->nr=d->anr=0;
60 d->m=(DCMMATRIX*)NULL;
61}

Referenced by dcmmlFree().

◆ dcmMListRead()

int dcmMListRead ( IFT * ift,
DCMML * ml,
TPCSTATUS * status )

Read DICOM image matrix list.

See also
dcmFileList, dcmmlInit
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Parameters
iftPointer to IFT structure containing file names constituting a DICOM image.
mlPointer to initiated DICOM matrix list.
statusPointer to status data; enter NULL if not needed.

Definition at line 120 of file dcmmatrix.c.

127 {
128 int verbose=0; if(status!=NULL) verbose=status->verbose;
129 if(verbose>1) printf("%s()\n", __func__);
130 if(ift==NULL || ml==NULL) {
131 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
132 return TPCERROR_FAIL;
133 }
134 if(ift->keyNr<1) {
135 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
136 return TPCERROR_NO_DATA;
137 }
138
139 /* Delete any previous data */
140 dcmmlFree(ml);
141
142 /*
143 * Read the first file in list
144 */
145 int fi=0, ret=TPCERROR_OK;
146 DCMFILE dcm; dcmfileInit(&dcm);
147 ret=dcmFileRead(ift->item[fi].value, &dcm, 1, status);
148 if(ret!=TPCERROR_OK) {dcmfileFree(&dcm); return(ret);}
149
150 /* Read some information common to the whole image */
151 DCMTAG tag;
152 DCMITEM *iptr;
153
154 /* Get and check the Image Type */
155 int dynamic=0; // 0=no, 1=yes
156 tag.group=0x0008; tag.element=0x0008;
157 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
158 if(iptr==NULL) {
159 ret=TPCERROR_NO_KEY; statusSet(status, __func__, __FILE__, __LINE__, ret);
160 dcmfileFree(&dcm); return(ret);
161 }
162 /* Check if dynamic; see DICOM 3.3 C.7.6.16.2.2.6
163 https://dicom.nema.org/MEDICAL/dicom/current/output/chtml/part03/sect_C.7.6.16.2.html
164 */
165 {
166 char *buf=dcmValueString(iptr);
167 if(verbose>2) printf("imageType := %s\n", buf);
168 if(strcasestr(buf, "DYNAMIC")!=NULL) dynamic=1; else dynamic=0;
169 free(buf);
170 }
171 if(verbose>1) {printf("dynamic := %d\n", dynamic); fflush(stdout);}
172
173 /* Check whether Per-frame Functional Groups Sequence is set */
174 int multiframe=0; // 0=no, 1=yes
175 tag.group=0x5200; tag.element=0x9230;
176 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
177 if(iptr!=NULL) {
178 if(verbose>1) fprintf(stderr, "Notice: Per-frame Functional Groups Sequence is available.\n");
179 multiframe=1;
180 }
181
182
183 if(multiframe) { /* Multi-frame file */
184
185 /* Get the number of frames and planes */
186 if(verbose>1) {printf("reading frame and slice number\n"); fflush(stdout);}
187 unsigned short int frameNr=0;
188 /* Get frame number from 'Temporal position index' */
189 tag.group=0x0020; tag.element=0x9128;
190 int a, b;
191 if(dcmTagIntRange(dcm.item, &tag, &a, &b, verbose-100)==0) frameNr=b;
192 if(verbose>1) printf("frameNr := %u\n", frameNr);
193 unsigned short int sliceNr=0;
194 /* Get plane number from 'In Stack Position Number' */
195 tag.group=0x0020; tag.element=0x9057;
196 if(dcmTagIntRange(dcm.item, &tag, &a, &b, verbose-100)==0) sliceNr=b;
197 else {
198 /* Get plane number from 'Dimension Index Values' */
199 tag.group=0x0020; tag.element=0x9157;
200 if(dcmTagIntRange(dcm.item, &tag, &a, &b, verbose-1)==0) sliceNr=b;
201 }
202 if(verbose>1) printf("sliceNr := %u\n", sliceNr);
203 if(frameNr<=0 || sliceNr<=0) {
204 if(verbose>0) fprintf(stderr, "Error: cannot find frame/slice number.\n");
205 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
206 dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
207 }
208
209 /* Get Decay Correction */
210 short unsigned int decayCorrection=0; // 0=NO, 1=YES
211 tag.group=0x0018; tag.element=0x9758;
212 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
213 if(iptr!=NULL) {
214 char *buf=dcmValueString(iptr);
215 if(verbose>2) printf("Decay Correction := '%s'\n", buf);
216 if(strcasestr(buf, "YES")!=NULL) decayCorrection=1;
217 free(buf);
218 }
219 if(verbose>1) printf("decayCorrection := %d\n", decayCorrection);
220
221 /* If decay is corrected, read time of decay correction; otherwise read start time */
222 char zeroDateTime[32]; zeroDateTime[0]=(char)0;
223 if(decayCorrection==0) {
224 /* Get Acquisition DateTime */
225 tag.group=0x0008; tag.element=0x002A;
226 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
227 if(iptr!=NULL) dcmDT2intl(iptr->rd, zeroDateTime);
228 } else {
229 tag.group=0x0018; tag.element=0x9701;
230 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
231 if(iptr!=NULL) dcmDT2intl(iptr->rd, zeroDateTime);
232 }
233 if(!zeroDateTime[0]) {
234 if(verbose>0) fprintf(stderr, "Error: missing Acquisition Date and Time.\n");
235 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
236 dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
237 }
238 if(verbose>4) printf("zeroDateTime := %s\n", zeroDateTime);
239
240 /* Initially allocate for frameNr x sliceNr matrices */
241 ret=dcmmlAllocate(ml, sliceNr*frameNr);
242 if(ret!=TPCERROR_OK) {
243 statusSet(status, __func__, __FILE__, __LINE__, ret);
244 dcmfileFree(&dcm); return ret;
245 }
246
247 /*
248 * Get the information from one matrix at a time
249 */
250 /* Find Per Frame Functional Groups Sequence */
251 tag.group=0x5200; tag.element=0x9230;
252 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
253 if(iptr==NULL) {
254 if(verbose>0) {
255 fprintf(stderr, "Error: cannot find Per Frame Functional Groups Sequence.\n");
256 fflush(stderr);
257 }
258 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_KEY);
259 dcmmlFree(ml); dcmfileFree(&dcm); return(TPCERROR_NO_KEY);
260 }
261 /* Loop through all Frame Content Sequences under it */
262 tag.group=0x0020; tag.element=0x9111;
263 DCMTAG tagstart; tagstart.group=0x0018; tagstart.element=0x9074;
264 DCMTAG tagdur; tagdur.group=0x0018; tagdur.element=0x9220;
265 DCMTAG tagfr; tagfr.group=0x0020; tagfr.element=0x9128;
266 DCMITEM *fptr=iptr->child_item;
267 while(fptr!=NULL) {
268 /* Find Frame Content Sequence */
269 iptr=dcmFindDownTag(fptr, 0, &tag, 0); if(iptr==NULL) break; // not an error!
270 if(verbose>10) printf(" found Frame Content Sequence\n");
271 /* Check that we have room */
272 if(ml->nr>=ml->anr) {
273 ret=dcmmlAllocate(ml, 100);
274 if(ret!=TPCERROR_OK) break;
275 }
276 /* Set file name */
277 ml->m[ml->nr].filename=strdup(ift->item[0].value);
278 /* Find Temporal Position Index */
279 DCMITEM *jptr;
280 jptr=dcmFindDownTag(iptr->child_item, 0, &tagfr, 0);
281 if(jptr==NULL) {
282 if(verbose>0) {printf("cannot find Temporal Position Index.\n"); fflush(stdout);}
283 ret=TPCERROR_NO_KEY; break;
284 }
285 if(verbose>20) dcmitemPrint(jptr);
286 ml->m[ml->nr].frame=(unsigned int)dcmitemGetInt(jptr);
287 //unsigned short int frameIndex=(unsigned short int)(dcmitemGetInt(jptr)-1);
288 /* Find slice index */
289 DCMTAG tagpl; tagpl.group=0x0020; tagpl.element=0x9057;
290 jptr=dcmFindDownTag(iptr->child_item, 0, &tagpl, 0);
291 if(jptr==NULL) {
292 tagpl.group=0x0020; tagpl.element=0x9157;
293 jptr=dcmFindDownTag(iptr->child_item, 0, &tagpl, 0);
294 }
295 if(jptr==NULL) {
296 if(verbose>0) {printf("cannot find Slice Index.\n"); fflush(stdout);}
297 ret=TPCERROR_NO_KEY; break;
298 }
299 if(verbose>20) dcmitemPrint(jptr);
300 ml->m[ml->nr].plane=(unsigned int)dcmitemGetInt(jptr);
301 /* Find Frame Acquisition DateTime */
302 jptr=dcmFindDownTag(iptr->child_item, 0, &tagstart, 0);
303 char facqDateTime[32]; facqDateTime[0]=(char)0;
304 if(jptr!=NULL) dcmDT2intl(jptr->rd, facqDateTime);
305 if(!facqDateTime[0]) {
306 if(verbose>0) {printf("cannot find Frame Acquisition DateTime.\n"); fflush(stdout);}
307 ret=TPCERROR_NO_KEY; break;
308 }
309 if(verbose>20) printf("facqDateTime := %s\n", facqDateTime);
310 strlcpy(ml->m[ml->nr].acqDate, facqDateTime, 11);
311 if(strlen(facqDateTime)>17) strlcpy(ml->m[ml->nr].acqTime, facqDateTime+11, 9);
312 /* Calculate the Frame start time */
313 ml->m[ml->nr].frameStart=strDateTimeDifference(facqDateTime, zeroDateTime);
314 /* Find Frame Acquisition Duration */
315 jptr=dcmFindDownTag(iptr->child_item, 0, &tagdur, 0);
316 if(jptr!=NULL) ml->m[ml->nr].frameDur=0.001*dcmitemGetReal(jptr);
317
318 /* prepare for the next matrix */
319 fptr=iptr->next_item;
320 ml->nr++;
321 }
322
323 dcmfileFree(&dcm);
324 if(ret!=TPCERROR_OK) {
325 statusSet(status, __func__, __FILE__, __LINE__, ret);
326 dcmmlFree(ml);
327 return(ret);
328 }
329
330 } else { /* Single-frame files */
331
332 /* Get the number of frames (time slices) */
333 unsigned short int frameNr=0;
334 tag.group=0x0054; tag.element=0x0101;
335 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
336 if(iptr!=NULL) {
337 frameNr=(unsigned short int)dcmitemGetInt(iptr);
338 } else {
339 if(dynamic!=0) { // error, if dynamic
340 ret=TPCERROR_NO_KEY; statusSet(status, __func__, __FILE__, __LINE__, ret);
341 dcmfileFree(&dcm); return(ret);
342 } else { // assume 1, if static or whole-body
343 frameNr=1;
344 }
345 }
346 if(verbose>1) printf("frameNr := %u\n", frameNr);
347
348 /* Get the number of slices (needed to understand image index) */
349 unsigned short int sliceNr=0;
350 tag.group=0x0054; tag.element=0x0081;
351 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
352 if(iptr==NULL) {
353 ret=TPCERROR_NO_KEY; statusSet(status, __func__, __FILE__, __LINE__, ret);
354 dcmfileFree(&dcm); return(ret);
355 }
356 sliceNr=(unsigned short int)dcmitemGetInt(iptr);
357 if(verbose>1) printf("sliceNr := %u\n", sliceNr);
358
359 /* Get Decay correction type */
360 short unsigned int decayCorrection=0; // 0=NONE, 1=START, 2=ADMIN
361 tag.group=0x0054; tag.element=0x1102;
362 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
363 if(iptr!=NULL) {
364 char *buf=dcmValueString(iptr);
365 if(verbose>2) printf("Decay Correction := %s\n", buf);
366 if(strcasecmp(buf, "NONE")==0) decayCorrection=0;
367 else if(strcasecmp(buf, "START")==0) decayCorrection=1;
368 else if(strcasecmp(buf, "ADMIN")==0) decayCorrection=2;
369 free(buf);
370 }
371
372 /* If decay is corrected to tracer administration time, the we must read it */
373 char injDateTime[32]; injDateTime[0]=(char)0;
374 if(decayCorrection==2) {
375 /* Get the Tracer Start DateTime */
376 tag.group=0x0018; tag.element=0x1078;
377 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
378 if(iptr!=NULL) {
379 if(dcmDT2intl(iptr->rd, injDateTime)==NULL) iptr=NULL;
380 }
381 /* If not successful, the try other tags */
382 if(iptr==NULL) {
383 char s1[16], s2[16];
384 /* Get the Tracer Start Time */
385 tag.group=0x0018; tag.element=0x1072;
386 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
387 if(iptr!=NULL) {
388 /* Get the Series Date */
389 tag.group=0x0008; tag.element=0x0021;
390 DCMITEM *jptr=dcmFindTag(dcm.item, 0, &tag, 0);
391 if(jptr!=NULL) {
392 if(dcmDA2intl(jptr->rd, s1)!=NULL && dcmTM2intl(iptr->rd, s2)!=NULL)
393 sprintf(injDateTime, "%s %s", s1, s2);
394 }
395 }
396 }
397 if(injDateTime[0] && verbose>3) printf("injection_time := %s\n", injDateTime);
398 }
399
400 /* Get the Series DateTime
401 https://dicom.nema.org/MEDICAL/dicom/current/output/chtml/part03/sect_C.8.9.html#figure_C.8.9.1.1.11-1a
402 */
403 char seriesDateTime[32]; seriesDateTime[0]=(char)0;
404 tag.group=0x0008; tag.element=0x0021;
405 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
406 if(iptr!=NULL) {
407 tag.group=0x0008; tag.element=0x0031;
408 DCMITEM *jptr=dcmFindTag(dcm.item, 0, &tag, 0);
409 if(jptr!=NULL) {
410 char s1[16], s2[16];
411 if(dcmDA2intl(iptr->rd, s1)!=NULL && dcmTM2intl(jptr->rd, s2)!=NULL)
412 sprintf(seriesDateTime, "%s %s", s1, s2);
413 }
414 }
415 if(seriesDateTime[0] && verbose>3) printf("seriesDateTime := %s\n", seriesDateTime);
416
417
418 /* Initially allocate for frameNr x sliceNr matrices */
419 ret=dcmmlAllocate(ml, sliceNr*frameNr);
420 if(ret!=TPCERROR_OK) {
421 statusSet(status, __func__, __FILE__, __LINE__, ret);
422 dcmfileFree(&dcm); return ret;
423 }
424
425
426 /*
427 * Get the information from one file at a time
428 */
429 //char startDateTime[32]; startDateTime[0]=(char)0;
430 //int fi=0, beds=0;
431 do {
432
433 /* Get the Image Index; DICOM PS3.3 C.8.9.4.1.9 */
434 unsigned short int imageIndex=0;
435 tag.group=0x0054; tag.element=0x1330;
436 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
437 if(iptr==NULL) {ret=TPCERROR_NO_KEY; break;}
438 imageIndex=(unsigned short int)dcmitemGetInt(iptr);
439 /* Calculate the current frame and slice (index starting from 0) */
440 unsigned short int frameIndex, sliceIndex;
441 {
442 div_t meh=div(imageIndex-1, sliceNr);
443 frameIndex=meh.quot;
444 sliceIndex=meh.rem;
445 }
446 /* Set file name, plane, and frame into matrix list */
447 if(ml->nr>=ml->anr) {
448 ret=dcmmlAllocate(ml, 100);
449 if(ret!=TPCERROR_OK) break;
450 }
451 ml->m[ml->nr].filename=strdup(ift->item[fi].value);
452 ml->m[ml->nr].plane=1+sliceIndex;
453 ml->m[ml->nr].frame=1+frameIndex;
454
455 /* Get acquisition date and time */
456 char acqDateTime[32]; acqDateTime[0]=(char)0;
457 /* Try first Acquisition Datetime */
458 tag.group=0x0008; tag.element=0x002A;
459 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
460 if(iptr!=NULL) dcmDT2intl(iptr->rd, acqDateTime);
461 /* If that did not work, try Acquisition Date and Time */
462 if(!acqDateTime[0]) {
463 tag.group=0x0008; tag.element=0x0022;
464 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
465 if(iptr!=NULL) {
466 tag.group=0x0008; tag.element=0x0032;
467 DCMITEM *jptr=dcmFindTag(dcm.item, 0, &tag, 0);
468 if(jptr!=NULL) {
469 char s1[16], s2[16];
470 if(dcmDA2intl(iptr->rd, s1)!=NULL && dcmTM2intl(jptr->rd, s2)!=NULL)
471 sprintf(acqDateTime, "%s %s", s1, s2);
472 }
473 }
474 }
475 if(acqDateTime[0]) {
476 strlcpy(ml->m[ml->nr].acqDate, acqDateTime, 11);
477 if(strlen(acqDateTime)>17) strlcpy(ml->m[ml->nr].acqTime, acqDateTime+11, 9);
478 }
479
480 /* Calculate the Frame start time, if possible */
481 if(acqDateTime[0]) {
482 double t1=nan("");
483 if(decayCorrection==2 && injDateTime[0]) {
484 /* Injection time is the reference time */
485 t1=strDateTimeDifference(acqDateTime, injDateTime);
486 ml->m[ml->nr].frameStart=t1;
487 } else if(seriesDateTime[0]) {
488 /* Use series time, for now */
489 t1=strDateTimeDifference(acqDateTime, seriesDateTime);
490 ml->m[ml->nr].frameStart=t1;
491 }
492 }
493
494 /* Get Actual Frame Duration */
495 tag.group=0x0018; tag.element=0x1242;
496 iptr=dcmFindTag(dcm.item, 0, &tag, 0);
497 if(iptr!=NULL) ml->m[ml->nr].frameDur=0.001*dcmitemGetReal(iptr);
498
499
500 /* Done with this file */
501 ml->nr++;
502 dcmfileFree(&dcm);
503
504 /* Read the next file in list */
505 fi++; if(fi>=ift->keyNr) {ret=TPCERROR_OK; break;}
506 ret=dcmFileRead(ift->item[fi].value, &dcm, 1, status);
507 if(ret!=TPCERROR_OK) break;
508
509 } while(1);
510 dcmfileFree(&dcm);
511 if(ret!=TPCERROR_OK) {
512 statusSet(status, __func__, __FILE__, __LINE__, ret);
513 dcmmlFree(ml);
514 return(ret);
515 }
516 }
517
518
519 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
520 return(TPCERROR_OK);
521}
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
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
int dcmTagIntRange(DCMITEM *d, DCMTAG *tag, int *mi, int *ma, const int verbose)
Definition dcmdata.c:631
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 dcmFileRead(const char *filename, DCMFILE *dcm, const short int headerOnly, TPCSTATUS *status)
Definition dcmio.c:768
void dcmmlFree(DCMML *d)
Definition dcmmatrix.c:70
int dcmmlAllocate(DCMML *d, int mNr)
Definition dcmmatrix.c:89
char * dcmDT2intl(const char *orig, char *intl)
Definition dcmvr.c:225
char * dcmDA2intl(const char *orig, char *intl)
Definition dcmvr.c:179
char * dcmTM2intl(const char *orig, char *intl)
Definition dcmvr.c:202
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
char * strdup(const char *s)
Definition stringext.c:185
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
char * strcasestr(const char *haystack, const char *needle)
Definition stringext.c:155
DCMITEM * item
Definition tpcdcm.h:164
struct DCMITEM * child_item
Definition tpcdcm.h:143
struct DCMITEM * next_item
Definition tpcdcm.h:147
char * rd
Definition tpcdcm.h:152
unsigned short int element
Definition tpcdcm.h:44
unsigned short int group
Definition tpcdcm.h:42
char * value
Definition tpcift.h:37
IFT_ITEM * item
Definition tpcift.h:57
int keyNr
Definition tpcift.h:47
int verbose
Verbose level, used by statusPrint() etc.
@ TPCERROR_NO_KEY
Key not found.
@ TPCERROR_NO_DATA
File contains no data.

◆ dcmmlSortByPlane()

int dcmmlSortByPlane ( DCMML * d,
TPCSTATUS * status )

Sort matrices in DCMML (DICOM matrix list) struct by plane (slice) number.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
dPointer to DCMML struct
statusPointer to status data; enter NULL if not needed

Definition at line 540 of file dcmmatrix.c.

545 {
546 int verbose=0; if(status!=NULL) verbose=status->verbose;
547 if(verbose>0) printf("%s()\n", __func__);
548 /* Check that required data exists */
549 if(d==NULL) {
550 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
551 return TPCERROR_NO_DATA;
552 }
553 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
554 if(d->nr<2) return TPCERROR_OK;
555 qsort(d->m, d->nr, sizeof(DCMMATRIX), dcmmlQSortPlane);
556 return TPCERROR_OK;
557}