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

DICOM file and directory functions. 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

int dcmSameImage (const DCMFILE *d1, const DCMFILE *d2, const int verbose)
 
int dcmFileList (const char *filename, IFT *ift, TPCSTATUS *status)
 List DICOM files belonging to one image.
 
int dcmFileRemove (const char *filename, TPCSTATUS *status)
 Remove DICOM files belonging to one image.
 

Detailed Description

DICOM file and directory functions.

Definition in file dcmfile.c.

Function Documentation

◆ dcmFileList()

int dcmFileList ( const char * filename,
IFT * ift,
TPCSTATUS * status )

List DICOM files belonging to one image.

User can give DICOM image as a folder containing image file(s), or as a name of one of the files of the image. This function lists the files (with paths) belonging to the same image.

See also
dcmFileRemove, dcmSameImage
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Parameters
filenamePointer to the name of DICOM directory or file.
iftPointer to initiated IFT structure, into which file names will be stored; any previous contents will be deleted.
statusPointer to status data; enter NULL if not needed.

Definition at line 123 of file dcmfile.c.

131 {
132 int verbose=0; if(status!=NULL) verbose=status->verbose;
133 if(filename==NULL || strnlen(filename, 10)<1 || ift==NULL) {
134 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
135 return TPCERROR_FAIL;
136 }
137 if(verbose>1) printf("%s('%s', ...)\n", __func__, filename);
138
139 /* Make the list */
140 unsigned short int fileNr=0;
141 if(pathExist(filename)) {
142 /* We got a directory */
143 if(verbose>2) printf("%s is a directory\n", filename);
144 /* List all files in it */
145 iftFree(ift);
146 fileNr=pathFileList(filename, ift);
147 if(fileNr==0) {
148 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_FILE);
149 return(TPCERROR_NO_FILE);
150 }
151 /* Remove files that are not DICOM */
152 int i=ift->keyNr-1;
153 do {
154 if(!dcmVerifyMagic(ift->item[i].value, NULL)) iftDelete(ift, i);
155 i--;
156 } while(i>=0);
157 fileNr=ift->keyNr; if(verbose>3) printf("fileNr := %d\n", fileNr);
158 if(fileNr==0) {
159 iftFree(ift);
160 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
161 return(TPCERROR_UNSUPPORTED);
162 }
163 /* Check that all remaining files belong to the same image */
164 DCMFILE dcm1; dcmfileInit(&dcm1);
165 i=0; int ret;
166 ret=dcmFileRead(ift->item[i].value, &dcm1, 1, status);
167 if(ret!=TPCERROR_OK) {iftFree(ift); return(ret);}
168 DCMFILE dcm2; dcmfileInit(&dcm2);
169 for(i=1; i<ift->keyNr; i++) {
170 ret=dcmFileRead(ift->item[i].value, &dcm2, 1, NULL /*status*/);
171 if(ret!=TPCERROR_OK) {
172 iftFree(ift); dcmfileFree(&dcm1);
173 statusSet(status, __func__, __FILE__, __LINE__, ret);
174 return(ret);
175 }
176 if(!dcmSameImage(&dcm1, &dcm2, verbose-10)) {
177 dcmfileFree(&dcm2); iftFree(ift);
178 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_DATA);
180 }
181 dcmfileFree(&dcm2);
182 }
183 dcmfileFree(&dcm1);
184 } else if(fileExist(filename)) {
185 /* We got a file */
186 if(verbose>2) printf("%s is a file\n", filename);
187 /* Verify that it is DICOM */
188 if(!dcmVerifyMagic(filename, NULL)) {
189 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
190 return(TPCERROR_UNSUPPORTED);
191 }
192 if(verbose>2) {printf("... and DICOM\n"); fflush(stdout);}
193 /* Read the specified file */
194 DCMFILE dcm1; dcmfileInit(&dcm1);
195 int ret;
196 ret=dcmFileRead(filename, &dcm1, 1, status);
197 if(ret!=TPCERROR_OK) {iftFree(ift); return(ret);}
198 /* Check whether Per-frame Functional Groups Sequence is set */
199 DCMTAG tag; dcmTagSet(&tag, 0x5200, 0x9230);
200 if(dcmFindTag(dcm1.item, 0, &tag, 0)!=NULL) {
201 dcmfileFree(&dcm1);
202 if(verbose>1)
203 printf("Per-frame Functional Groups Sequence is available: assuming single-file.\n");
204 iftFree(ift); fileNr=1;
205 iftPut(ift, "", filename, 0, NULL);
206 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
207 return(TPCERROR_OK);
208 }
209
210 /* Since there is no RELIABLE way to tell how many files make up the whole
211 image, we have to list files in the same path */
212 char *pathname=strdup(filename); filenameRmFile(pathname);
213 if(verbose>3) printf("%s is its path\n", pathname);
214 iftFree(ift);
215 fileNr=pathFileList(pathname, ift); free(pathname);
216 if(verbose>3) printf("fileNr := %d\n", fileNr);
217 if(fileNr==0) {
218 iftFree(ift);
219 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
221 }
222 /* Remove files that are not DICOM */
223 int i=ift->keyNr-1;
224 do {
225 if(!dcmVerifyMagic(ift->item[i].value, NULL)) iftDelete(ift, i);
226 i--;
227 } while(i>=0);
228 fileNr=ift->keyNr; if(verbose>3) printf("fileNr := %d\n", fileNr);
229 if(fileNr==0) {
230 iftFree(ift);
231 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
232 return(TPCERROR_UNSUPPORTED);
233 }
234 /* Remove files that do not belong to the same series as the specified file */
235 DCMFILE dcm2; dcmfileInit(&dcm2);
236 i=ift->keyNr-1;
237 do {
238 ret=dcmFileRead(ift->item[i].value, &dcm2, 1, NULL /*status*/);
239 if(ret!=TPCERROR_OK || !dcmSameImage(&dcm1, &dcm2, verbose-10)) {
240 if(verbose>5) {printf(" not same, removing from list\n"); fflush(stdout);}
241 iftDelete(ift, i);
242 }
243 dcmfileFree(&dcm2);
244 i--;
245 } while(i>=0);
246 dcmfileFree(&dcm1);
247 fileNr=ift->keyNr; if(verbose>3) printf("fileNr := %d\n", fileNr);
248 if(fileNr==0) {
249 iftFree(ift);
250 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
251 return(TPCERROR_UNSUPPORTED);
252 }
253 } else {
254 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_FILE);
255 return(TPCERROR_NO_FILE);
256 }
257
258 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
259 return(TPCERROR_OK);
260}
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
void dcmfileFree(DCMFILE *d)
Definition dcmdata.c:67
int dcmSameImage(const DCMFILE *d1, const DCMFILE *d2, const int verbose)
Definition dcmfile.c:24
int dcmFileRead(const char *filename, DCMFILE *dcm, const short int headerOnly, TPCSTATUS *status)
Definition dcmio.c:768
int dcmVerifyMagic(const char *filename, FILE *fp)
Definition dcmio.c:25
void filenameRmFile(char *s)
Definition filename.c:44
unsigned short int pathFileList(const char *pathname, IFT *ift)
Definition filexist.c:83
int fileExist(const char *filename)
Definition filexist.c:17
void iftFree(IFT *ift)
Definition ift.c:37
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
Definition ift.c:63
int iftDelete(IFT *ift, int index)
Definition ift.c:206
int pathExist(const char *pathname)
Definition pathexist.c:17
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 strnlen(const char *s, size_t n)
Definition stringext.c:566
DCMITEM * item
Definition tpcdcm.h:164
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_FILE
File does not exist.
@ TPCERROR_FAIL
General error.
@ TPCERROR_UNSUPPORTED
Unsupported file type.
@ TPCERROR_OK
No error.
@ TPCERROR_INVALID_FILENAME
Invalid file name.
@ TPCERROR_INCOMPATIBLE_DATA
Incompatible data.

Referenced by dcmFileRemove(), and imgRead().

◆ dcmFileRemove()

int dcmFileRemove ( const char * filename,
TPCSTATUS * status )

Remove DICOM files belonging to one image.

User can give DICOM image as a folder containing image file(s), or as a name of one of the files of the image.

See also
dcmFileList, dcmSameImage, pathRemoveFiles, dcmFileWrite
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Parameters
filenamePointer to the name of DICOM directory or file.
statusPointer to status data; enter NULL if not needed.

Definition at line 270 of file dcmfile.c.

275 {
276 int verbose=0; if(status!=NULL) verbose=status->verbose;
277 if(filename==NULL || strnlen(filename, 10)<1) {
278 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
279 return TPCERROR_FAIL;
280 }
281 if(verbose>1) printf("%s('%s', ...)\n", __func__, filename);
282
283 /* List files belonging to the image */
284 IFT ift; iftInit(&ift);
285 int ret=dcmFileList(filename, &ift, status);
286 if(ret!=TPCERROR_OK) {iftFree(&ift); return(ret);}
287
288 /* Remove the files */
289 for(int i=0; i<ift.keyNr; i++) {
290 if(remove(ift.item[i].value)) {
291 iftFree(&ift);
292 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_DELETE);
294 }
295 }
296 iftFree(&ift);
297
298 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
299 return(TPCERROR_OK);
300}
int dcmFileList(const char *filename, IFT *ift, TPCSTATUS *status)
List DICOM files belonging to one image.
Definition dcmfile.c:123
void iftInit(IFT *ift)
Definition ift.c:21
Definition tpcift.h:43
@ TPCERROR_CANNOT_DELETE
Cannot delete.

Referenced by imgWriteDICOM().

◆ dcmSameImage()

int dcmSameImage ( const DCMFILE * d1,
const DCMFILE * d2,
const int verbose )

Check that two DICOM files belong to the same image.

Defaults to yes, if the needed tags are missing.

See also
dcmFileList, dcmVerifyMagic
Returns
Returns 1 if they are part of the same image, 0 if not.
Parameters
d1Pointer to the first DICOM file data (pixel data not necessary).
d2Pointer to the second DICOM file data (pixel data not necessary).
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 24 of file dcmfile.c.

31 {
32 if(verbose>0) printf("%s()\n", __func__);
33 if(d1==NULL || d2==NULL) return(0);
34
35 DCMTAG tag;
36 DCMITEM *iptr;
37
38 /* Check the similarity of Series Instance UID */
39 char siuid1[64], siuid2[64];
40 siuid1[0]=siuid2[0]=(char)0;
41 dcmTagSet(&tag, 0x0020, 0x000E);
42 iptr=dcmFindTag(d1->item, 0, &tag, 0);
43 if(iptr!=NULL) strlcpy(siuid1, iptr->rd, 64);
44 iptr=dcmFindTag(d2->item, 0, &tag, 0);
45 if(iptr!=NULL) strlcpy(siuid2, iptr->rd, 64);
46 if(verbose>1) {
47 printf("Series Instance UID [1] := %s\n", siuid1);
48 printf("Series Instance UID [2] := %s\n", siuid2);
49 }
50 if(strcmp(siuid1, siuid2)) return(0);
51
52 /* Check the similarity of Study ID */
53 char sid1[16], sid2[16];
54 sid1[0]=sid2[0]=(char)0;
55 dcmTagSet(&tag, 0x0020, 0x0010);
56 iptr=dcmFindTag(d1->item, 0, &tag, 0);
57 if(iptr!=NULL) strlcpy(sid1, iptr->rd, 16);
58 iptr=dcmFindTag(d2->item, 0, &tag, 0);
59 if(iptr!=NULL) strlcpy(sid2, iptr->rd, 16);
60 if(verbose>1) {
61 printf("Study ID [1] := %s\n", sid1);
62 printf("Study ID [2] := %s\n", sid2);
63 }
64 if(strcmp(sid1, sid2)) return(0);
65
66 /* Check the series number */
67 char snr1[12], snr2[12];
68 snr1[0]=snr2[0]=(char)0;
69 dcmTagSet(&tag, 0x0020, 0x0011);
70 iptr=dcmFindTag(d1->item, 0, &tag, 0);
71 if(iptr!=NULL) strlcpy(snr1, iptr->rd, 12);
72 iptr=dcmFindTag(d2->item, 0, &tag, 0);
73 if(iptr!=NULL) strlcpy(snr2, iptr->rd, 12);
74 if(verbose>1) {
75 printf("Series Number [1] := %s\n", snr1);
76 printf("Series Number [2] := %s\n", snr2);
77 }
78 if(strcmp(snr1, snr2)) return(0);
79
80 /* The rest of checks should not be necessary... */
81 if(verbose>2) {printf(" ... still looks the same...\n"); fflush(stdout);}
82
83 /* Check the number of frames (time slices) */
84 unsigned short int frameNr1=0, frameNr2=0;
85 dcmTagSet(&tag, 0x0054, 0x0101);
86 iptr=dcmFindTag(d1->item, 0, &tag, 0);
87 if(iptr!=NULL) frameNr1=(unsigned short int)dcmitemGetInt(iptr);
88 iptr=dcmFindTag(d2->item, 0, &tag, 0);
89 if(iptr!=NULL) frameNr2=(unsigned short int)dcmitemGetInt(iptr);
90 if(verbose>1) {
91 printf("frameNr [1] := %u\n", frameNr1);
92 printf("frameNr [2] := %u\n", frameNr2);
93 }
94 if(frameNr1!=frameNr2) return(0);
95 if(verbose>2) {printf(" ... still looks the same...\n"); fflush(stdout);}
96
97 /* Check the number of slices */
98 unsigned short int sliceNr1=0, sliceNr2=0;
99 dcmTagSet(&tag, 0x0054, 0x0081);
100 iptr=dcmFindTag(d1->item, 0, &tag, 0);
101 if(iptr!=NULL) sliceNr1=(unsigned short int)dcmitemGetInt(iptr);
102 iptr=dcmFindTag(d2->item, 0, &tag, 0);
103 if(iptr!=NULL) sliceNr2=(unsigned short int)dcmitemGetInt(iptr);
104 if(verbose>1) {
105 printf("sliceNr [1] := %u\n", sliceNr1);
106 printf("sliceNr [2] := %u\n", sliceNr2);
107 }
108 if(sliceNr1!=sliceNr2) return(0);
109
110 if(verbose>2) {printf(" ... the same.\n"); fflush(stdout);}
111 return(1);
112}
long int dcmitemGetInt(DCMITEM *d)
Definition dcmdata.c:295
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
char * rd
Definition tpcdcm.h:152

Referenced by dcmFileList().