TPCCLIB
Loading...
Searching...
No Matches
dcm.c
Go to the documentation of this file.
1
4/******************************************************************************/
5#include "libtpcimgio.h"
6/******************************************************************************/
7
8/******************************************************************************/
11typedef struct DCM_VR {
13 dcmvr vr;
15 char name[8];
17 unsigned char res;
19 short int es;
21 size_t s;
23 char descr[64];
24} DCM_VR;
25
31static DCM_VR dcm_vr[]={
32 {DCM_VR_AE, "AE", 0, 0, 16, "application entity"},
33 {DCM_VR_AS, "AS", 0, 0, 4, "age string"},
34 {DCM_VR_AT, "AT", 0, 0, 4, "attribute tag"},
35 {DCM_VR_CS, "CS", 0, 0, 16, "code string"},
36 {DCM_VR_DA, "DA", 0, 0, 8, "date"},
37 {DCM_VR_DS, "DS", 0, 0, 16, "decimal string"}, // actual files may contain longer strings too
38 {DCM_VR_DT, "DT", 0, 0, 26, "date and time"},
39 {DCM_VR_FL, "FL", 0, 1, 4, "floating point single precision"},
40 {DCM_VR_FD, "FD", 0, 1, 8, "floating point double precision"},
41 {DCM_VR_IS, "IS", 0, 0, 12, "integer string"},
42 {DCM_VR_LO, "LO", 0, 0, 64, "long string"},
43 {DCM_VR_LT, "LT", 0, 0, 10240, "long text"},
44 {DCM_VR_OB, "OB", 2, 0, 0, "other byte (8-bit) stream"}, // even bytes
45 {DCM_VR_OD, "OD", 2, 1, 0, "other double (64-bit) stream"},
46 {DCM_VR_OF, "OF", 2, 1, 0, "other float (32-bit) stream"},
47 {DCM_VR_OL, "OL", 2, 1, 0, "other long (32-bit) stream"},
48 {DCM_VR_OW, "OW", 2, 1, 0, "other word (16-bit) stream"},
49 {DCM_VR_PN, "PN", 0, 0, 64, "person name"},
50 {DCM_VR_SH, "SH", 0, 0, 16, "short string"},
51 {DCM_VR_SL, "SL", 0, 1, 4, "signed long (32-bit integer)"},
52 {DCM_VR_SQ, "SQ", 2, 0, 0, "sequence of elements (used for nested data)"},
53 {DCM_VR_SS, "SS", 0, 1, 2, "signed short (16-bit integer)"},
54 {DCM_VR_ST, "ST", 0, 0, 1024, "short text"},
55 {DCM_VR_TM, "TM", 0, 0, 14, "time"},
56 {DCM_VR_UC, "UC", 2, 0, 0, "unlimited characters"},
57 {DCM_VR_UI, "UI", 0, 0, 64, "UID"},
58 {DCM_VR_UL, "UL", 0, 1, 4, "unsigned long (32-bit integer)"},
59 {DCM_VR_UN, "UN", 2, 0, 0, "unknown, any valid length of another VR"},
60 {DCM_VR_UR, "UR", 2, 0, 64, "URI or URL string"},
61 {DCM_VR_US, "US", 0, 1, 2, "unsigned short (16-bit integer)"},
62 {DCM_VR_UT, "UT", 2, 0, 0, "unlimited text"},
63 // This MUST be kept as the last element
64 {DCM_VR_INVALID, "INVALID", 0, 0, 0, "invalid value representation"}
65};
67/******************************************************************************/
68
69/******************************************************************************/
72typedef struct DCM_TRUID_ITEM {
74 dcmtruid id;
76 char uid[64];
78 char descr[64];
79} DCM_TRUID_ITEM;
80
86static DCM_TRUID_ITEM dcm_truid[]={
87 {DCM_TRUID_UNKNOWN, "1.2.840.10008.1.2", "unknown"}, //< default
88 {DCM_TRUID_LEI, "1.2.840.10008.1.2", "implicit VR little endian"},
89 {DCM_TRUID_LEE, "1.2.840.10008.1.2.1", "explicit VR little endian"},
90 {DCM_TRUID_BEE, "1.2.840.10008.1.2.2", "explicit VR big endian"},
91 {DCM_TRUID_JPEG50, "1.2.840.10008.1.2.4.50", "lossy JPEG 8-bit compression"},
92 {DCM_TRUID_JPEG51, "1.2.840.10008.1.2.4.51", "lossy JPEG 12-bit compression"},
93 {DCM_TRUID_JPEG70, "1.2.840.10008.1.2.4.70", "lossless JPEG"},
94 {DCM_TRUID_JPEG80, "1.2.840.10008.1.2.4.80", "lossless JPEG-LS"},
95 {DCM_TRUID_JPEG81, "1.2.840.10008.1.2.4.81", "lossy JPEG-LS"},
96 {DCM_TRUID_JPEG90, "1.2.840.10008.1.2.4.90", "lossless JPEG 2000"},
97 {DCM_TRUID_JPEG91, "1.2.840.10008.1.2.4.91", "JPEG 2000"},
98 {DCM_TRUID_JPEG92, "1.2.840.10008.1.2.4.92", "lossless multicomponent JPEG 2000"},
99 {DCM_TRUID_JPEG93, "1.2.840.10008.1.2.4.93", "multicomponent JPEG 2000"},
100 {DCM_TRUID_MPEG100, "1.2.840.10008.1.2.4.100", "MPEG-2"},
101 {DCM_TRUID_MPEG102, "1.2.840.10008.1.2.4.102", "MPEG-4"},
102 {DCM_TRUID_MPEG103, "1.2.840.10008.1.2.4.103", "MPEG-4 BD-compatible"},
103 {DCM_TRUID_RLE, "1.2.840.10008.1.2.5", "lossless RLE"},
104 {DCM_TRUID_RFC, "1.2.840.10008.1.2.6.1", "RFC 2557"},
105 {DCM_TRUID_XML, "1.2.840.10008.1.2.6.2", "XML"},
106 {DCM_TRUID_INVALID, "", "invalid"}
107};
109/******************************************************************************/
110
111/******************************************************************************/
114typedef struct DCM_SOP_ITEM {
117 char uid[64];
119 char name[64];
120} DCM_SOP_ITEM;
121
125static DCM_SOP_ITEM dcm_sop[]={
126 {"invalid", "invalid SOP"}, // do not change this
127 {"1.2.840.10008.5.1.4.1.1.1", "Computed Radiography Image Storage"},
128 {"1.2.840.10008.5.1.4.1.1.12.1", "X-Ray Angiographic Image Storage"},
129 {"1.2.840.10008.5.1.4.1.1.128", "Positron Emission Tomography Image Storage"},
130 {"1.2.840.10008.5.1.4.1.1.130", "Enhanced PET Image Storage"},
131 {"1.2.840.10008.5.1.4.1.1.128.1", "Legacy Converted Enhanced PET Image Storage"},
132 {"1.2.840.10008.5.1.4.1.1.2", "CT Image Storage"},
133 {"1.2.840.10008.5.1.4.1.1.20", "NM Image Storage"},
134 {"1.2.840.10008.5.1.4.1.1.30", "Parametric Map Storage"},
135 {"1.2.840.10008.5.1.4.1.1.3.1", "Ultrasound Multiframe Image Storage"},
136 {"1.2.840.10008.5.1.4.1.1.4", "MR Image Storage"},
137 {"1.2.840.10008.5.1.4.1.1.4.1", "Enhanced MR Image Storage"},
138 {"1.2.840.10008.5.1.4.1.1.4.2", "MR Spectroscopy Storage"},
139 {"1.2.840.10008.5.1.4.1.1.6.1", "Ultrasound Image Storage"},
140 {"1.2.840.10008.5.1.4.1.1.66", "Raw Data Storage"},
141 {"1.2.840.10008.5.1.4.1.1.66.1", "Spatial Registration Storage"},
142 {"1.2.840.10008.5.1.4.1.1.66.2", "Spatial Fiducials Storage"},
143 {"1.2.840.10008.5.1.4.1.1.66.3", "Deformable Spatial Registration Storage"},
144 {"1.2.840.10008.5.1.4.1.1.66.4", "Segmentation Storage"},
145 {"unknown", "unknown SOP"} // do not change this
146};
148/******************************************************************************/
149
150/******************************************************************************/
160 const char *filename,
167 FILE *fp
168) {
169 FILE *lfp;
170
171 if(filename==NULL && fp==NULL) return(0);
172 if(fp!=NULL) {
173 lfp=fp; rewind(lfp);
174 } else {
175 lfp=fopen(filename, "rb");
176 }
177 if(lfp==NULL) return(0);
178
179 /* Skip the first 128 bytes */
180 if(fseek(lfp, 128, SEEK_SET)) {if(fp==NULL) fclose(lfp); return(0);}
181
182 /* Read the next 4 bytes as characters */
183 char buf[5];
184 size_t n=fread(&buf, 1, 4, lfp);
185 buf[4]=(char)0;
186 if(n!=(size_t)4) {rewind(lfp); return(0);}
187
188 /* Check the magic number */
189 if(strncmp(buf, "DICM", 4)==0) {
190 if(fp==NULL) fclose(lfp);
191 return(1);
192 } else {
193 if(fp==NULL) fclose(lfp); else rewind(lfp);
194 return(0);
195 }
196}
197/******************************************************************************/
198
199/******************************************************************************/
205unsigned char dcmVRReserved(
207 dcmvr id
208) {
209 unsigned short int i=0;
210 while(dcm_vr[i].vr!=DCM_VR_INVALID) {
211 if(id==dcm_vr[i].vr) return(dcm_vr[i].res);
212 i++;
213 }
214 return(2);
215}
216/*****************************************************************************/
217
218/*****************************************************************************/
226 const char *s
227) {
228 if(s==NULL) return(DCM_VR_INVALID);
229 char buf[3]; buf[0]=s[0]; buf[1]=s[1]; buf[2]=(char)0;
230
231 /* Identify the VR */
232 unsigned short int i=0;
233 while(dcm_vr[i].vr!=DCM_VR_INVALID) {
234 if(strncmp(dcm_vr[i].name, buf, 2)==0) return(dcm_vr[i].vr);
235 i++;
236 }
237 return(DCM_VR_INVALID);
238}
239/*****************************************************************************/
240
241/*****************************************************************************/
248 dcmvr id
249) {
250 unsigned short int i=0;
251 while(dcm_vr[i].vr!=DCM_VR_INVALID) {
252 if(id==dcm_vr[i].vr) return(dcm_vr[i].name);
253 i++;
254 }
255 return(dcm_vr[DCM_VR_INVALID].name);
256}
257/*****************************************************************************/
258
259/*****************************************************************************/
266 dcmvr id
267) {
268 unsigned short int i=0;
269 while(dcm_vr[i].vr!=DCM_VR_INVALID) {
270 if(id==dcm_vr[i].vr) return(dcm_vr[i].s);
271 i++;
272 }
273 return(dcm_vr[DCM_VR_INVALID].s);
274}
275/*****************************************************************************/
276
277/*****************************************************************************/
284 dcmvr id
285) {
286 unsigned short int i=0;
287 while(dcm_vr[i].vr!=DCM_VR_INVALID) {
288 if(id==dcm_vr[i].vr) return(dcm_vr[i].descr);
289 i++;
290 }
291 return(dcm_vr[DCM_VR_INVALID].descr);
292}
293/*****************************************************************************/
294
295/*****************************************************************************/
301 const char *orig,
304 char *intl
305) {
306 if(orig==NULL || intl==NULL) return(NULL);
307 if(strnlen(orig, 10)<8) return(NULL);
308 if(isdigit(orig[4])) { // modern format YYYYMMDD
309 sprintf(intl, "%4.4s-%2.2s-%2.2s", orig, orig+4, orig+6);
310 } else { // old format YYYY.MM.DD
311 sprintf(intl, "%4.4s-%2.2s-%2.2s", orig, orig+5, orig+8);
312 }
313 if(isdate(intl)) {intl[0]=(char)0; return(NULL);}
314 return(intl);
315}
316/*****************************************************************************/
317
318/*****************************************************************************/
324 const char *orig,
327 char *intl
328) {
329 if(orig==NULL || intl==NULL) return(NULL);
330 if(strnlen(orig, 14)<6) return(NULL);
331 if(isdigit(orig[2])) { // modern format hhmmss.fract
332 sprintf(intl, "%2.2s:%2.2s:%2.2s", orig, orig+2, orig+4);
333 } else { // old format hh.mm.ss
334 sprintf(intl, "%2.2s:%2.2s:%2.2s", orig, orig+3, orig+6);
335 }
336 if(istime(intl)) {intl[0]=(char)0; return(NULL);}
337 return(intl);
338}
339/*****************************************************************************/
340
341/*****************************************************************************/
348 const char *orig,
351 char *intl
352) {
353 if(orig==NULL || intl==NULL) return(NULL);
354 if(strnlen(orig, 26)<14) return(NULL);
355 sprintf(intl, "%4.4s-%2.2s-%2.2s %2.2s:%2.2s:%2.2s",
356 orig, orig+4, orig+6, orig+8, orig+10, orig+12);
357 if(isdatetime(intl, NULL)) {intl[0]=(char)0; return(NULL);}
358 return(intl);
359}
360/*****************************************************************************/
361
362/*****************************************************************************/
367unsigned int dcmSOPIdentify(
369 const char *s
370) {
371 if(s==NULL || strnlen(s, 3)<3) return(0);
372
373 /* Identify the SOP UID */
374 unsigned int i=0;
375 while(strcmp(dcm_sop[i].uid, "unknown")!=0) {
376 if(strcmp(dcm_sop[i].uid, s)==0) return(i);
377 i++;
378 }
379 return(i);
380}
381/*****************************************************************************/
382
383/*****************************************************************************/
390 unsigned int i
391) {
392 unsigned int j=0;
393 while(strcmp(dcm_sop[j].uid, "unknown")!=0) {
394 if(i==j) return(dcm_sop[j].name);
395 j++;
396 }
397 return(dcm_sop[j].name);
398}
399/*****************************************************************************/
400
401/*****************************************************************************/
408 unsigned int i
409) {
410 unsigned int j=0;
411 while(strcmp(dcm_sop[j].uid, "unknown")!=0) {
412 if(i==j) return(dcm_sop[j].uid);
413 j++;
414 }
415 return(dcm_sop[j].uid);
416}
417/*****************************************************************************/
418
419/*****************************************************************************/
426 const char *s
427) {
428 if(s==NULL || strnlen(s, 3)<3) return(dcm_sop[0].name);
429
430 /* Identify the SOP UID */
431 unsigned int i=0;
432 while(strcmp(dcm_sop[i].uid, "unknown")!=0) {
433 if(strcmp(dcm_sop[i].uid, s)==0) return(dcm_sop[i].name);
434 i++;
435 }
436 return(dcm_sop[i].name);
437}
438/*****************************************************************************/
439
440/*****************************************************************************/
447 const char *s
448) {
449 if(s==NULL || strnlen(s, 5)<5) return(DCM_TRUID_INVALID);
450
451 /* Identify the UID */
452 unsigned short int i=1; // 1 because 0 is unknown
453 while(dcm_truid[i].id!=DCM_TRUID_INVALID) {
454 if(strcmp(dcm_truid[i].uid, s)==0) return(dcm_truid[i].id);
455 i++;
456 }
457 return(DCM_TRUID_UNKNOWN);
458}
459/*****************************************************************************/
460
461/*****************************************************************************/
468 dcmtruid id
469) {
470 unsigned short int i=0;
471 while(dcm_truid[i].id!=DCM_TRUID_INVALID) {
472 if(id==dcm_truid[i].id) return(dcm_truid[i].descr);
473 i++;
474 }
475 return(dcm_truid[DCM_TRUID_INVALID].descr);
476}
477/*****************************************************************************/
478
479/*****************************************************************************/
486 dcmtruid id
487) {
488 unsigned short int i=0;
489 while(dcm_truid[i].id!=DCM_TRUID_INVALID) {
490 if(id==dcm_truid[i].id) return(dcm_truid[i].uid);
491 i++;
492 }
493 return(dcm_truid[DCM_TRUID_INVALID].uid);
494}
495/*****************************************************************************/
496
497/*****************************************************************************/
506 FILE *fp
507) {
508 if(fp==NULL || feof(fp)) return(DCM_TRUID_INVALID);
509 /* Save original file position */
510 fpos_t opos;
511 if(fgetpos(fp, &opos)) return(DCM_TRUID_INVALID);
512 /* Read file until we find DICOM tag 0x0002,0x0010 */
513 DCMTAG tag;
514 int tag_found=0;
515 while(!tag_found && !feof(fp)) {
516 if(dcmReadFileTag(fp, &tag)) break;
517 if(tag.group==0x0002 && tag.element==0x0010) {tag_found=1; break;}
518 /* not the tag that we want, so just go through this item */
519 dcmvr vr=dcmReadFileVR(fp, NULL);
520 unsigned int vl=0;
521 if(dcmVRReserved(vr)==0) vl=dcmReadFileVL(fp, 2);
522 else vl=dcmReadFileVL(fp, 4);
523 if(vr==DCM_VR_SQ) break;
524 if(vl==0xFFFFFFFF) break;
525 char buf[vl+1];
526 if(fread(buf, 1, vl, fp)!=vl) break;
527 } // get next tag
528 if(!tag_found) {fsetpos(fp, &opos); return(DCM_TRUID_INVALID);}
529 /* Read the UID */
530 if(dcmReadFileVR(fp, NULL)!=DCM_VR_UI) {
531 fsetpos(fp, &opos); return(DCM_TRUID_INVALID);
532 }
533 unsigned int vl=dcmReadFileVL(fp, 2);
534 if(vl==0 || vl==0xFFFFFFFF) {fsetpos(fp, &opos); return(DCM_TRUID_INVALID);}
535 char uid[vl+1];
536 if(fread(uid, 1, vl, fp)!=vl) {fsetpos(fp, &opos); return(DCM_TRUID_INVALID);}
537 /* Return file position to the original */
538 fsetpos(fp, &opos);
539 /* Identify the UID */
540 return(dcmTrUID(uid));
541}
542/*****************************************************************************/
543
544/*****************************************************************************/
555 FILE *fp,
558 DCMTAG *tag
559) {
560 if(tag!=NULL) {tag->group=tag->element=0xFFFC;} // padding
561 if(fp==NULL || feof(fp)) return(1);
562 unsigned short int buf[2];
563 size_t n=fread(&buf, 2, 2, fp);
564 if(n!=2) return(2+n);
565 if(tag!=NULL) {
566 tag->group=buf[0];
567 tag->element=buf[1];
568 if(!little_endian()) { // tag is by default little endian
569 swap(&tag->group, &tag->group, 2);
570 swap(&tag->element, &tag->element, 2);
571 }
572 }
573 return(0);
574}
575/*****************************************************************************/
576
577/*****************************************************************************/
585 FILE *fp,
587 DCMTAG *tag
588) {
589 if(fp==NULL || tag==NULL) return(1);
590 unsigned short int buf[2];
591 buf[0]=tag->group;
592 buf[1]=tag->element;
593 if(!little_endian()) swabip(buf, 4); // tag is by default little endian
594 if(fwrite(&buf, 2, 2, fp)!=2) return(2);
595 return(0);
596}
597/*****************************************************************************/
598
599/*****************************************************************************/
611 FILE *fp
612) {
613 if(fp==NULL) return(1);
614 int ret;
615 DCMTAG tag;
616 tag.group=0xFFFE; tag.element=0xE0DD;
617 ret=dcmWriteFileTag(fp, &tag); if(ret!=0) return(ret);
618 tag.group=0x0000; tag.element=0x0000;
619 ret=dcmWriteFileTag(fp, &tag); if(ret!=0) return(ret);
620 return(0);
621}
622/*****************************************************************************/
623
624/*****************************************************************************/
636 FILE *fp
637) {
638 if(fp==NULL) return(1);
639 int ret;
640 DCMTAG tag;
641 tag.group=0xFFFE; tag.element=0xE00D;
642 ret=dcmWriteFileTag(fp, &tag); if(ret!=0) return(ret);
643 tag.group=0x0000; tag.element=0x0000;
644 ret=dcmWriteFileTag(fp, &tag); if(ret!=0) return(ret);
645 return(0);
646}
647/*****************************************************************************/
648
649/*****************************************************************************/
657 FILE *fp,
660 char *vrstr
661) {
662 if(vrstr!=NULL) vrstr[0]=(char)0;
663 if(fp==NULL) return(DCM_VR_INVALID);
664
665 /* Read the first two bytes */
666 char buf[3];
667 if(fread(&buf, 1, 2, fp)!=2) return(DCM_VR_INVALID);
668 buf[2]=(char)0;
669
670 /* Identify the VR */
671 dcmvr lvr=dcmVRId(buf);
672 if(vrstr!=NULL) {
673 if(lvr!=DCM_VR_INVALID) strcpy(vrstr, dcmVRName(lvr));
674 else strcpy(vrstr, buf);
675 }
676
677 /* If this VR has extra 2 byte reserved space, then
678 we need to read but do not use the next 2 bytes. */
679 if(dcmVRReserved(lvr)!=0) {
680 if(fread(&buf, 1, 2, fp)!=2) return(DCM_VR_INVALID);
681 }
682 return(lvr);
683}
684/*****************************************************************************/
685
686/*****************************************************************************/
692unsigned int dcmReadFileVL(
694 FILE *fp,
696 unsigned int n
697) {
698 unsigned int vl=0;
699 if(fp==NULL || (n!=2 && n!=4)) return(vl);
700
701 /* Read 2 or 4 bytes */
702 if(n==2) {
703 unsigned short int si;
704 if(fread(&si, 2, 1, fp)!=1) return(vl);
705 if(!little_endian()) swap(&si, &si, 2);
706 vl=si;
707 } else if(n==4) {
708 unsigned int li;
709 if(fread(&li, 4, 1, fp)!=1) return(vl);
710 if(!little_endian()) swap(&li, &li, 4);
711 vl=li;
712 }
713 return(vl);
714}
715/*****************************************************************************/
716
717/*****************************************************************************/
726 FILE *fp,
728 dcmvr *vr,
730 unsigned int *vl,
732 unsigned int *n
733) {
734 if(vr!=NULL) *vr=DCM_VR_INVALID;
735 if(vl!=NULL) *vl=0;
736 if(n!=NULL) *n=0;
737 if(fp==NULL) return(1);
738
739 /* Read the first two bytes */
740 char buf[3];
741 if(fread(&buf, 1, 2, fp)!=2) return(2); else if(n!=NULL) *n+=2;
742 buf[2]=(char)0;
743
744 /* Identify the VR */
745 dcmvr lvr=dcmVRId(buf);
746 if(vr!=NULL) *vr=lvr;
747 if(lvr==DCM_VR_INVALID) return(3);
748
749 /* If this VR has extra 2 byte reserved space, then
750 we need to read but do not use the next 2 bytes. */
751 unsigned int bsize=2+dcmVRReserved(lvr);
752 if(bsize==4) {
753 if(fread(&buf, 1, 2, fp)!=2) return(2);
754 if(n!=NULL) *n+=2;
755 }
756
757 /* Read VL from the next 2 or 4 bytes */
758 unsigned int lvl=0;
759 if(bsize==2) {
760 unsigned short int si;
761 if(fread(&si, 2, 1, fp)!=1) return(2);
762 if(!little_endian()) swap(&si, &si, 2);
763 lvl=si;
764 } else {
765 unsigned int li;
766 if(fread(&li, 4, 1, fp)!=1) return(2);
767 if(!little_endian()) swap(&li, &li, 4);
768 lvl=li;
769 }
770 if(n!=NULL) *n+=bsize;
771 if(vl!=NULL) *vl=lvl;
772
773 return(0);
774}
775/*****************************************************************************/
776
777/*****************************************************************************/
786 FILE *fp,
788 dcmvr vr,
790 unsigned int vl,
792 unsigned int *n
793) {
794 if(n!=NULL) *n=0;
795 if(fp==NULL || vr==DCM_VR_INVALID) return(1);
796
797 /* If this VR has extra 2 byte reserved space, then
798 we need to write VR and VL with 4 bytes each, other wise with 2 bytes each. */
799 unsigned int bsize=2+dcmVRReserved(vr);
800
801 char buf[10];
802
803 /* Write VR */
804 memcpy(buf, dcmVRName(vr), 2); buf[2]=buf[3]=(char)0;
805 if(fwrite(buf, bsize, 1, fp)!=1) return(2);
806 if(n!=NULL) *n+=bsize;
807
808 /* Write VL */
809 memcpy(buf, &vl, bsize);
810 if(bsize==2) buf[2]=buf[3]=(char)0;
811 if(!little_endian()) swap(buf, buf, bsize);
812 if(fwrite(buf, bsize, 1, fp)!=1) return(2);
813 if(n!=NULL) *n+=bsize;
814
815 return(0);
816}
817/*****************************************************************************/
818
819/*****************************************************************************/
825 DCMFILE *d
826) {
827 if(d==NULL) return;
828 d->filename[0]=(char)0;
829 d->fp=(FILE*)NULL;
831 d->item=(DCMITEM*)NULL;
832}
833/*****************************************************************************/
834
835/*****************************************************************************/
842 DCMITEM *d
843) {
844 if(d==NULL) return;
845 /* find the last item in the list */
846 DCMITEM *ip=d; while(ip->next_item!=NULL) ip=ip->next_item;
847 while(ip!=NULL) {
848 /* Free items child and their children */
849 if(ip->child_item!=NULL) dcmitemFree(ip->child_item);
850 /* Free this item and move to previous item */
851 if(ip->prev_item!=NULL) {
852 ip=ip->prev_item;
853 free(ip->next_item->rd); free(ip->next_item);
854 ip->next_item=NULL;
855 } else {
856 free(ip->rd); free(ip); ip=NULL;
857 }
858 }
859}
860/*****************************************************************************/
861
862/*****************************************************************************/
870 DCMFILE *d
871) {
872 if(d==NULL) return;
873 dcmitemFree(d->item);
874 dcmfileInit(d);
875}
876/*****************************************************************************/
877
878/*****************************************************************************/
884unsigned short int dcmitemMaxDepth(
886 DCMITEM *d
887) {
888 if(d==NULL || d->child_item==NULL) return(0);
889 unsigned short int m=0, n=0;
890 DCMITEM *cd=d->child_item;
891 /* go through all children */
892 while(cd!=NULL) {
893 n=dcmitemMaxDepth(cd); if(n>m) m=n;
894 cd=cd->next_item;
895 }
896 return(m+1);
897}
903unsigned short int dcmfileMaxDepth(
905 DCMFILE *df
906) {
907 if(df==NULL || df->item==NULL) return(0);
908 unsigned short int m=0, n=0;
909 DCMITEM *sd=df->item;
910 while(sd!=NULL) { // go through all sisters
911 n=dcmitemMaxDepth(sd); if(n>m) m=n;
912 sd=sd->next_item;
913 }
914 return(m+1);
915}
916/*****************************************************************************/
917
918/*****************************************************************************/
923unsigned short int dcmitemParentNr(
925 DCMITEM *d
926) {
927 if(d==NULL) return(0);
928 unsigned short int n=0;
929 DCMITEM *pd=d->parent_item;
930 while(pd!=NULL) {n++; pd=pd->parent_item;}
931 return(n);
932}
933/*****************************************************************************/
934
935/*****************************************************************************/
944 DCMITEM *d
945) {
946 if(d==NULL) return((char*)NULL);
947
948 /* For sequence, return string 'na' */
949 if(d->vr==DCM_VR_SQ) {
950 char *s=malloc(3); strcpy(s, "na"); // do not write char *s="na";
951 return(s);
952 }
953
954 /* If there is no value, then return string 'empty', or
955 'na', if value just was not stored (pixel data) */
956 if(d->vl==0) {
957 char *s=malloc(6); strcpy(s, "empty");
958 return(s);
959 } else if(d->rd==NULL) {
960 char *s=malloc(3); strcpy(s, "na");
961 return(s);
962 }
963
964 unsigned int len;
965 if(d->vl==0xFFFFFFFF) len=(unsigned int)dcmVRVLength(d->vr); else len=d->vl;
966
967 /* String values */
968 if(d->vr==DCM_VR_CS || d->vr==DCM_VR_DS || d->vr==DCM_VR_IS ||
969 d->vr==DCM_VR_LO || d->vr==DCM_VR_LT || d->vr==DCM_VR_PN ||
970 d->vr==DCM_VR_SH || d->vr==DCM_VR_ST)
971 {
972 char *s=malloc(len+1);
973 memcpy(s, d->rd, len); s[len]=(char)0;
974 return(s);
975 }
976
977 /* More string values */
978 if(d->vr==DCM_VR_AS || d->vr==DCM_VR_PN ||
979 d->vr==DCM_VR_DA || d->vr==DCM_VR_DT || d->vr==DCM_VR_TM ||
980 d->vr==DCM_VR_UT || d->vr==DCM_VR_AE ||
981 d->vr==DCM_VR_UI || d->vr==DCM_VR_UR)
982 {
983 char *s=malloc(len+1);
984 memcpy(s, d->rd, len); s[len]=(char)0;
985 return(s);
986 }
987
989 if(d->vr==DCM_VR_AT) {
990 DCMTAG tag;
991 memcpy(&tag.group, d->rd, 2);
992 memcpy(&tag.element, d->rd+2, 2);
993 if(!little_endian()) {
994 swap(&tag.group, &tag.group, 2);
995 swap(&tag.element, &tag.element, 2);
996 }
997 char *s=malloc(14);
998 sprintf(s, "0x%04x,0x%04x", tag.group, tag.element);
999 return(s);
1000 }
1001
1003 if(d->vr==DCM_VR_FL) {
1004 float f;
1005 memcpy(&f, d->rd, 4);
1006 if(!little_endian()) swap(&f, &f, 4);
1007 char *s=malloc(16);
1008 sprintf(s, "%g", f);
1009 return(s);
1010 }
1011
1013 if(d->vr==DCM_VR_FD) {
1014 char *s=malloc(32);
1015 double f;
1016 memcpy(&f, d->rd, 8);
1017 if(!little_endian()) swap(&f, &f, 8);
1018 sprintf(s, "%g", f);
1019 return(s);
1020 }
1021
1023 if(d->vr==DCM_VR_UL) {
1024 unsigned int i;
1025 memcpy(&i, d->rd, 4);
1026 if(!little_endian()) swap(&i, &i, 4);
1027 char *s=malloc(16);
1028 sprintf(s, "%u", i);
1029 return(s);
1030 }
1031
1033 if(d->vr==DCM_VR_US) {
1034 unsigned short int i;
1035 memcpy(&i, d->rd, 2);
1036 if(!little_endian()) swap(&i, &i, 2);
1037 char *s=malloc(8);
1038 sprintf(s, "%u", i);
1039 return(s);
1040 }
1041
1043 if(d->vr==DCM_VR_SL) {
1044 int i;
1045 memcpy(&i, d->rd, 4);
1046 if(!little_endian()) swap(&i, &i, 4);
1047 char *s=malloc(16);
1048 sprintf(s, "%d", i);
1049 return(s);
1050 }
1051
1053 if(d->vr==DCM_VR_SS) {
1054 short int i;
1055 memcpy(&i, d->rd, 2);
1056 if(!little_endian()) swap(&i, &i, 2);
1057 char *s=malloc(8);
1058 sprintf(s, "%d", i);
1059 return(s);
1060 }
1061
1062/* Not (yet) printed:
1063 DCM_VR_OB, ///< DICOM other byte string, even bytes, endian insensitive.
1064 DCM_VR_OD, ///< DICOM other double (64-bit) stream, endian sensitive.
1065 DCM_VR_OF, ///< DICOM other float (32-bit) stream, endian sensitive.
1066 DCM_VR_OL, ///< DICOM other long (32-bit) stream, endian sensitive.
1067 DCM_VR_OW, ///< DICOM other word (16-bit) stream, even bytes, endian sensitive.
1068 DCM_VR_UC, ///< DICOM unlimited characters.
1069 DCM_VR_UN, ///< DICOM unknown, any valid length of another VR.
1070 DCM_VR_INVALID ///< Invalid DICOM value representation.
1071*/
1072 char *s=malloc(3); strcpy(s, "na"); // do not write char *s="na";
1073 return(s);
1074}
1075/*****************************************************************************/
1076
1077/*****************************************************************************/
1086 DCMITEM *d
1087) {
1088 if(d==NULL || d->rd==NULL) return(0);
1089 long int li=0;
1090 if(d->vr==DCM_VR_UL) { // unsigned 32-bit int
1091 unsigned int i;
1092 memcpy(&i, d->rd, 4); if(!little_endian()) swap(&i, &i, 4);
1093 li=(long int)i;
1094 } else if(d->vr==DCM_VR_US) { // unsigned 16-bit int
1095 unsigned short int i;
1096 memcpy(&i, d->rd, 2); if(!little_endian()) swap(&i, &i, 2);
1097 li=(long int)i;
1098 } else if(d->vr==DCM_VR_SL) { // signed 32-bit int
1099 int i;
1100 memcpy(&i, d->rd, 4); if(!little_endian()) swap(&i, &i, 4);
1101 li=(long int)i;
1102 } else if(d->vr==DCM_VR_SS) { // signed 16-bit int
1103 short int i;
1104 memcpy(&i, d->rd, 2); if(!little_endian()) swap(&i, &i, 2);
1105 li=(long int)i;
1106 } else if(d->vr==DCM_VR_IS) { // integer string
1107 li=atol(d->rd);
1108 }
1109 return(li);
1110}
1111/*****************************************************************************/
1112
1113/*****************************************************************************/
1122 DCMITEM *d
1123) {
1124 if(d==NULL || d->rd==NULL) return(0);
1125 double r=0.0;
1126 if(d->vr==DCM_VR_FL) { // 32-bit float
1127 float f;
1128 memcpy(&f, d->rd, 4); if(!little_endian()) swap(&f, &f, 4);
1129 r=(double)f;
1130 } else if(d->vr==DCM_VR_FD) { // 64-bit double
1131 double f;
1132 memcpy(&f, d->rd, 8); if(!little_endian()) swap(&f, &f, 8);
1133 r=f;
1134 } else if(d->vr==DCM_VR_DS) { // decimal string
1135 r=atof(d->rd);
1136 } else if(d->vr==DCM_VR_UL) { // unsigned 32-bit int
1137 unsigned int i;
1138 memcpy(&i, d->rd, 4); if(!little_endian()) swap(&i, &i, 4);
1139 r=(double)i;
1140 } else if(d->vr==DCM_VR_US) { // unsigned 16-bit int
1141 unsigned short int i;
1142 memcpy(&i, d->rd, 2); if(!little_endian()) swap(&i, &i, 2);
1143 r=(double)i;
1144 } else if(d->vr==DCM_VR_SL) { // signed 32-bit int
1145 int i;
1146 memcpy(&i, d->rd, 4); if(!little_endian()) swap(&i, &i, 4);
1147 r=(double)i;
1148 } else if(d->vr==DCM_VR_SS) { // signed 16-bit int
1149 short int i;
1150 memcpy(&i, d->rd, 2); if(!little_endian()) swap(&i, &i, 2);
1151 r=(double)i;
1152 } else if(d->vr==DCM_VR_IS) { // integer string
1153 r=(double)atol(d->rd);
1154 }
1155 return(r);
1156}
1157/*****************************************************************************/
1158
1159/*****************************************************************************/
1165 DCMITEM *d,
1167 const short int omit,
1169 DCMTAG *tag,
1171 const int verbose
1172) {
1173 if(d==NULL || tag==NULL) return(NULL);
1174 if(verbose>0) printf("%s(%04X,%04X)\n", __func__, tag->group, tag->element);
1175 DCMITEM *iptr;
1176 if(omit==0) iptr=d; else iptr=d->next_item;
1177 while(iptr!=NULL) {
1178 if(verbose>2)
1179 printf(" checking tag(%04X,%04X)...\n", iptr->tag.group, iptr->tag.element);
1180 if(iptr->tag.group==tag->group && iptr->tag.element==tag->element) {
1181 if(verbose>2) printf(" found!\n");
1182 break;
1183 }
1184 /* Check if this item has children */
1185 if(iptr->child_item!=NULL) {
1186 if(verbose>2) printf(" going to search inside children...\n");
1187 DCMITEM *rptr=dcmFindTag(iptr->child_item, 0, tag, verbose);
1188 if(rptr!=NULL) return(rptr);
1189 if(verbose>3) printf(" nothing found in any of the children\n");
1190 }
1191 iptr=iptr->next_item;
1192 }
1193 /* Stop if we found tag, or if we do not have parent */
1194 if(iptr!=NULL) return(iptr);
1195 if(d->parent_item==NULL) return(NULL);
1196
1197 /* Search from the parent */
1198 if(verbose>2) printf(" going to search inside parent...\n");
1199 return(dcmFindTag(d->parent_item, 1, tag, verbose));
1200}
1201/*****************************************************************************/
1202
1203/*****************************************************************************/
1207 DCMITEM *d
1208) {
1209 if(d==NULL) {printf("(null)\n"); fflush(stdout); return;}
1210 printf("tag(%04X,%04X)", d->tag.group, d->tag.element); fflush(stdout);
1211 printf(" VR=%s", dcmVRName(d->vr)); fflush(stdout);
1212 if(d->vl==0xFFFFFFFF) printf(" VL=%08X", d->vl); else printf(" VL=%u", d->vl);
1213 fflush(stdout);
1214 char *buf=dcmValueString(d); printf(" '%s'", buf); free(buf);
1215 printf("\n"); fflush(stdout);
1216}
1217/*****************************************************************************/
1218
1219/*****************************************************************************/
1223 DCMTAG *tag,
1225 unsigned short int group,
1227 unsigned short int element
1228) {
1229 tag->group=group;
1230 tag->element=element;
1231}
1232/*****************************************************************************/
1233
1234/*****************************************************************************/
1241 DCMFILE *dcm,
1244 DCMITEM *d,
1246 short int aschild,
1248 DCMTAG tag,
1250 dcmvr vr,
1252 unsigned int vl,
1254 char *rd,
1256 const int verbose
1257) {
1258 if(verbose>0) {
1259 printf("%s(dcm, (%04X,%04X))", __func__, tag.group, tag.element);
1260 if(d==NULL) printf(", null"); else printf(", ptr");
1261 printf(", %d, %s, 0x%08X, rd", aschild, dcmVRName(vr), vl);
1262 printf(")\n");
1263 }
1264 if(dcm==NULL) return(1);
1265 if(vr==DCM_VR_INVALID) return(2);
1266
1267 /* Check that caller has not given previous item pointer when there are none in DCMFILE */
1268 if(d!=NULL && dcm->item==NULL) return(3);
1269 /* Check that caller has not given previous item pointer that already has child */
1270 if(d!=NULL && aschild && d->child_item!=NULL) return(4);
1271
1272 /* Check whether we currently support the Transfer UID */
1273 if(dcm->truid!=DCM_TRUID_LEE) return(5);
1274
1275 /* Allocate memory for the new element; do not free it here, since it will be part of
1276 DCMFILE struct. */
1277 if(verbose>1) printf(" allocating memory for the item\n");
1278 DCMITEM *item=(DCMITEM*)malloc(sizeof(DCMITEM));
1279 if(item==NULL) return(11);
1280 item->next_item=item->child_item=(DCMITEM*)NULL;
1281 item->fp=dcm->fp; item->truid=dcm->truid;
1282 item->rd=(char*)NULL;
1283
1284 /* Set item tag, VR, and VL */
1285 if(verbose>1) printf(" setting item contents\n");
1286 item->tag.group=tag.group;
1287 item->tag.element=tag.element;
1288 item->vr=vr;
1289 item->vl=vl;
1290 /* Allocate memory for item value */
1291 size_t s;
1292 if(vl==0xFFFFFFFF) s=dcmVRVLength(vr); else s=vl;
1293 if(s>0) {
1294 if(item->vl==0xFFFFFFFF) item->vl=(unsigned int)s;
1295 if(verbose>1) printf(" allocating %u bytes for the item value\n", (unsigned int)s);
1296 item->rd=(char*)calloc(s, sizeof(char));
1297 if(item->rd==NULL) {free(item); return(21);}
1298 } else {
1299 if(verbose>1) printf("zero size for item value\n");
1300 if(rd==NULL) {
1301 if(verbose>1) printf("... which is ok since value is empty, too.\n");
1302 } else {
1303 if(verbose>0) printf("... which is not ok because we have value to store.\n");
1304 if(item->rd==NULL) {free(item); return(22);}
1305 }
1306 }
1307 /* Copy the item value */
1308 if(rd!=NULL && s>0) {
1309 if(verbose>1) printf(" copying the item value\n");
1310 /* Special treatment for strings, because those tend to be shorter than told */
1311 if(vr==DCM_VR_LO || vr==DCM_VR_LT || vr==DCM_VR_PN || vr==DCM_VR_SH || vr==DCM_VR_UI || vr==DCM_VR_UR)
1312 {
1313 unsigned int len=strnlen(rd, s);
1314 if(len<s) strlcpy(item->rd, rd, s);
1315 else memcpy(item->rd, rd, s);
1316 } else if(vr==DCM_VR_DS || vr==DCM_VR_IS)
1317 {
1318 unsigned int len=strnlen(rd, s);
1319 if(len<s) strlcpy(item->rd, rd, s);
1320 else memcpy(item->rd, rd, s);
1321 } else {
1322 memcpy(item->rd, rd, s);
1323 }
1324 }
1325
1326
1327 /* If we have the item to link to, then do the linking */
1328 if(verbose>1) printf(" link the item.\n");
1329 if(d!=NULL) {
1330 if(aschild) {
1331 d->child_item=item;
1332 item->parent_item=d;
1333 item->prev_item=(DCMITEM*)NULL;
1334 } else if(d->next_item==NULL) {
1335 d->next_item=item;
1336 item->prev_item=d;
1337 item->parent_item=d->parent_item;
1338 } else {
1339 /* find the last item in the list */
1340 DCMITEM *ip=d; while(ip->next_item!=NULL) ip=ip->next_item;
1341 ip->next_item=item;
1342 item->prev_item=ip;
1343 item->parent_item=ip->parent_item;
1344 }
1345 } else if(dcm->item==NULL) {
1346 /* This is truly the first item ever */
1347 dcm->item=item;
1348 item->prev_item=item->parent_item=(DCMITEM*)NULL;
1349 } else {
1350 /* Caller lets us find the item to link to */
1351 DCMITEM *ip=dcm->item; while(ip->next_item!=NULL) ip=ip->next_item;
1352 ip->next_item=item;
1353 item->prev_item=ip;
1354 item->parent_item=ip->parent_item;
1355 }
1356
1357 if(verbose>2) dcmitemPrint(item);
1358
1359 if(verbose>1) printf(" all done.\n");
1360 return(0);
1361}
1362/*****************************************************************************/
1363
1364/*****************************************************************************/
1372 DCMFILE *dcm,
1374 DCMITEM *prev_item,
1376 DCMITEM *parent_item,
1378 const short int sub,
1380 const short int headerOnly,
1382 int verbose
1383) {
1384 if(verbose>0) printf("%s(DCMFILE*, DCMITEM*, DCMITEM*, %d, %d)\n", __func__, sub, headerOnly);
1385 if(dcm==NULL || dcm->fp==NULL) return(1);
1386 if(sub!=0 && parent_item==NULL) return(1);
1387 if(feof(dcm->fp)) return(-1);
1388
1389 /* Check whether we currently support the Transfer UID */
1390 if(dcm->truid!=DCM_TRUID_LEE) return(2);
1391
1392 if(verbose>10) {
1393 if(dcm->item==NULL) printf(" will add first element\n");
1394 else if(sub==0) printf(" will add next element\n");
1395 else printf(" will add subelement\n");
1396 }
1397
1398 /* Is this a child to a sequence element? */
1399 int sq_child=0;
1400 if(parent_item!=NULL && parent_item->vr==DCM_VR_SQ) {sq_child=1;}
1401 if(verbose>10 && sq_child!=0) printf(" we're a child to a sequence element\n");
1402
1403 /* Allocate memory for the new element */
1404 DCMITEM *item=(DCMITEM*)malloc(sizeof(DCMITEM));
1405 if(item==NULL) return(4);
1406 item->prev_item=prev_item;
1407 item->parent_item=parent_item;
1408 item->next_item=item->child_item=(DCMITEM*)NULL;
1409 item->fp=dcm->fp; item->truid=dcm->truid;
1410 item->rd=(char*)NULL;
1411
1412 /* Save current file position (should be the start of element) */
1413 if(fgetpos(dcm->fp, &item->pos)) {
1414 free(item); return(2);
1415 }
1416
1417 /* Read the tag (2x2 bytes) */
1418 if(verbose>10) {
1419 long int tagpos=ftell(dcm->fp);
1420 printf(" reading tag at %ld\n", tagpos);
1421 }
1422 if(dcmReadFileTag(dcm->fp, &item->tag)) {
1423 if(verbose>1 && !feof(dcm->fp)) printf(" error in reading the tag.\n");
1424 free(item);
1425 if(feof(dcm->fp)) return(-1);
1426 return(2);
1427 }
1428
1429 if(verbose>2) {
1430 printf(" tag(%04x,%04x) with %u parents\n",
1431 item->tag.group, item->tag.element, dcmitemParentNr(item));
1432 }
1433
1434 /* If child, then check for item delimitation tag (although it should not be here) */
1435 if(dcmitemParentNr(item)>0 && item->tag.group==0xFFFE && item->tag.element==0xE00D) {
1436 if(verbose>10)
1437 printf(" item delimitation tag(%04x,%04x) found, reading VL\n",
1438 item->tag.group, item->tag.element);
1439 unsigned long int vl=dcmReadFileVL(dcm->fp, 4);
1440 if(verbose>1) printf(" item delimitation tag VL := %lu (0x%08lx)\n", vl, vl);
1441 if(vl!=0) {
1442 if(verbose>1) printf(" error: VL should have been 0\n");
1443 return(3);
1444 }
1445 return(0);
1446 }
1447
1448
1449 /* Read value representation and length (VR and VL, 2x2 or 2x4 bytes) */
1450 {
1451 if(verbose>10) printf(" reading VR and VL\n");
1452 int ret;
1453 unsigned int n;
1454 ret=dcmReadFileVRVL(dcm->fp, &item->vr, &item->vl, &n);
1455 if(ret!=0) {
1456 if(verbose>1) printf(" invalid VR or VL\n");
1457 free(item); return(ret);
1458 }
1459 if(verbose>1) {
1460 printf(" VR := %s (%s)\n", dcmVRName(item->vr), dcmVRDescr(item->vr));
1461 printf(" VL := %u (0x%08x) (%d bytes field)\n", item->vl, item->vl, n/2);
1462 fflush(stdout);
1463 }
1464 }
1465
1466 /* Read value field, and add the current element to the list */
1467 if(item->vr==DCM_VR_SQ) {
1468 if(ftell(dcm->fp)<0) return(2);
1469 unsigned long int sqPos=(unsigned long int)ftell(dcm->fp);
1470 if(verbose>10) {printf(" sequence... at %ld\n", sqPos); fflush(stdout);}
1471 unsigned long int sqContentLength=item->vl;
1472 if(verbose>12) printf(" sequence contents length is %lu\n", sqContentLength);
1473 /* File position is now at the start of first item in the sequence */
1474 int ret;
1475 /* If parent has no previous child, then define this as its child */
1476 if(sq_child!=0 && parent_item->child_item==NULL) {
1477 parent_item->child_item=item;
1478 } else {
1479 /* else, add SQ sequence itself as next element to the list, and later
1480 add each sequence item as child to it */
1481 if(prev_item==NULL) {
1482 if(dcm->item==NULL) { // truly the first item
1483 dcm->item=item;
1484 } else { // search for the previous one
1485 DCMITEM *ip; ip=dcm->item;
1486 while(ip->next_item!=NULL) ip=ip->next_item;
1487 ip->next_item=item; item->prev_item=ip;
1488 }
1489 } else {
1490 prev_item->next_item=item; item->prev_item=prev_item;
1491 }
1492 }
1493 /* Read the first item tag and length, but there is no VR to read this time */
1494 if(verbose>10) {
1495 long int tagpos=ftell(dcm->fp);
1496 printf(" reading first item tag at %ld\n", tagpos);
1497 }
1498 DCMTAG itemtag;
1499 ret=dcmReadFileTag(dcm->fp, &itemtag);
1500 if(ret!=0) {
1501 if(verbose>1) printf(" error %d in reading the tag.\n", ret);
1502 return(2);
1503 }
1504 if(verbose>1) printf(" item tag(%04x,%04x)\n", itemtag.group, itemtag.element);
1505 /* It is common that sequence is empty; check it first */
1506 if(itemtag.group==0xFFFE && (itemtag.element==0xE0DD || itemtag.element==0xE00D)) {
1507 /* yes; then read also the 4 byte LV, which should be zero */
1508 if(verbose>10)
1509 printf(" sequence delimitation item tag(%04x,%04x) found, reading VL\n",
1510 itemtag.group, itemtag.element);
1511 unsigned long int vl=dcmReadFileVL(dcm->fp, 4);
1512 if(verbose>1) printf(" item tag VL := %lu (0x%08lx)\n", vl, vl);
1513 if(vl!=0) {
1514 if(verbose>1) printf(" error: VL should have been 0\n");
1515 return(2);
1516 }
1517 if(verbose>3) printf(" ending sequence before it really started.\n");
1518 return(0);
1519 }
1520 /* If sequence actually contains something, the Item tag must be 0xFFFE,0xE000 */
1521 if(itemtag.group!=0xFFFE || itemtag.element!=0xE000) {
1522 if(verbose>1) printf(" invalid sequence item tag(%04x,%04x)\n", itemtag.group, itemtag.element);
1523 return(2);
1524 }
1525 /* Read past the VL of this item (always 4 bytes) */
1526 unsigned long int itemvl=dcmReadFileVL(dcm->fp, 4);
1527 if(verbose>3) {printf(" item_VL := %lu (0x%08lx)\n", itemvl, itemvl);}
1528 if(ftell(dcm->fp)<0) return(2);
1529 unsigned long int sqItemPos=(unsigned long int)ftell(dcm->fp);
1530 /* Check if that is all of this sequence (probably Siemens) */
1531 if((sqItemPos-sqPos)>=sqContentLength) {
1532 if(verbose>3) printf(" ending sequence since it was found to be empty.\n");
1533 return(0);
1534 }
1535 if(verbose>12) printf(" sequence content start position at %ld\n", sqItemPos);
1536 /* Read the first item value as its own element, adding it as child to SQ */
1537 ret=dcmFileReadNextElement(dcm, NULL, item, 1, headerOnly, verbose-1);
1538 if(ret!=0) {
1539 if(verbose>1) printf(" error in reading the first item value dataset\n");
1540 return(ret);
1541 }
1542 /* Now we continue reading more items, until we reach Sequence Delimitation Item */
1543 while(!feof(dcm->fp)) {
1544 /* Do not read pass the length of the sequence data */
1545 if(ftell(dcm->fp)<0) return(2);
1546 unsigned long int cPos=(unsigned long int)ftell(dcm->fp);
1547 if(sqContentLength>0 && (cPos-sqPos)>=sqContentLength) {
1548 if(verbose>3) printf(" we reached the end of sequence VL %lu\n", sqContentLength);
1549 /* set fake sequence delimitation tag */
1550 itemtag.group=0xFFFE; itemtag.element=0xE0DD;
1551 break;
1552 }
1553 if(verbose>10) {
1554 long int tagpos=ftell(dcm->fp);
1555 printf(" reading next sequence item tag at %ld, %ld after start\n", tagpos, tagpos-sqItemPos);
1556 }
1557 if(dcmReadFileTag(dcm->fp, &itemtag)) return(2);
1558 if(verbose>1) printf(" next item tag(%04x,%04x)\n", itemtag.group, itemtag.element);
1559 itemvl=dcmReadFileVL(dcm->fp, 4); // delimitation tag has this too
1560 if(verbose>3) {printf(" item_VL := %lu (0x%08lx)\n", itemvl, itemvl);}
1561 /* Check if we got sequence delimitation tag */
1562 if(itemtag.group==0xFFFE && itemtag.element==0xE0DD)
1563 {
1564 if(verbose>3) printf(" we got sequence delimitation tag\n");
1565 break;
1566 }
1567 /* Check if we got item delimitation tag from the previous item */
1568 if(itemtag.group==0xFFFE && itemtag.element==0xE00D)
1569 {
1570 if(verbose>3) printf(" we got item delimitation tag\n");
1571 if(itemvl!=0) {
1572 if(verbose>1) printf(" error: VL should have been 0\n");
1573 return(3);
1574 }
1575 continue;
1576 }
1577 /* Otherwise this should be sequence item tag */
1578 if(itemtag.group!=0xFFFE || itemtag.element!=0xE000) {
1579 if(verbose>3) printf(" not sequence item tag, move file position back 2x4 bytes\n");
1580 fseek(dcm->fp, -8, SEEK_CUR); //return(TPCERROR_INVALID_VALUE);
1581 }
1582 /* Read the item value as its own element, adding it to the SQ child list */
1583 DCMITEM *child=item->child_item;
1584 if(child==NULL) {
1585 if(verbose>1) printf(" error had happened in adding the child element\n");
1586 return(2);
1587 }
1588 while(child->next_item!=NULL) child=child->next_item;
1589 ret=dcmFileReadNextElement(dcm, child, item, 0, headerOnly, verbose-1);
1590 if(ret!=0) {
1591 if(verbose>1) printf(" error in reading item value dataset\n");
1592 return(ret);
1593 }
1594 }
1595 /* Check that loop really stopped at sequence delimitation item */
1596 /* 0xE00D means the end of item, 0xE0DD the end of sequence. */
1597 if(itemtag.group!=0xFFFE || itemtag.element!=0xE0DD) {
1598 if(verbose>1)
1599 printf(" invalid sequence delimitation item tag(%04x,%04x)\n", itemtag.group, itemtag.element);
1600 return(2);
1601 }
1602 /* Done. Do not free item! */
1603 if(verbose>10) {printf(" end of sequence.\n"); fflush(stdout);}
1604 } else if(item->vl!=0xFFFFFFFF) {
1605 if(verbose>10) {printf(" reading value of %u bytes...\n", item->vl); fflush(stdout);}
1606 char *buf=NULL;
1607 if(item->vl>0) {
1608 buf=(char*)calloc(item->vl+1, sizeof(char));
1609 if(buf==NULL) {free(item); return(4);}
1610 if(fread(buf, 1, item->vl, item->fp)!=item->vl) {
1611 free(item); free(buf); return(3);
1612 }
1613 /* Do not store pixel data, if that was the request */
1614 if(headerOnly!=0 &&
1615 ((item->tag.group==0x7FE0 && item->tag.element>0) || item->tag.group==0x7FE1))
1616 {
1617 if(verbose>5) {printf(" ...not storing pixel data\n"); fflush(stdout);}
1618 free(buf); buf=(char*)NULL;
1619 } else {
1620 item->rd=buf;
1621 }
1622 } else if(verbose>4) {
1623 printf(" VL=0\n");
1624 }
1625 /* Add to list */
1626 if(sub==0) {
1627 if(prev_item==NULL) {
1628 if(dcm->item==NULL) { // truly the first item
1629 dcm->item=item;
1630 } else { // search for the previous one
1631 DCMITEM *ip; ip=dcm->item;
1632 while(ip->next_item!=NULL) ip=ip->next_item;
1633 ip->next_item=item; item->prev_item=ip;
1634 }
1635 } else {
1636 prev_item->next_item=item; item->prev_item=prev_item;
1637 }
1638 } else { // add as child
1639 parent_item->child_item=item; item->parent_item=parent_item;
1640 }
1641 /* Done. Do no free item or buf! */
1642 return(0);
1643
1644 } else { // VL=0xFFFFFFFF
1645 size_t s=dcmVRVLength(item->vr);
1646 if(s==0) {
1647 if(verbose>0) printf(" Unknown VL!!\n");
1648 free(item);
1649 return(3); //return(TPCERROR_OK);
1650 }
1651 if(verbose>4) printf(" VR_based_VL=%u\n", (unsigned int)s);
1652 char *buf=(char*)calloc(s+1, sizeof(char));
1653 if(buf==NULL) {free(item); return(4);}
1654 if(fread(buf, 1, s, item->fp)!=s) {
1655 free(item); free(buf); return(3);
1656 }
1657 item->rd=buf;
1658 /* Add to list */
1659 if(sub==0) {
1660 if(prev_item==NULL) {
1661 if(dcm->item==NULL) { // truly the first item
1662 dcm->item=item;
1663 } else { // search for the previous one
1664 DCMITEM *ip; ip=dcm->item;
1665 while(ip->next_item!=NULL) ip=ip->next_item;
1666 ip->next_item=item; item->prev_item=ip;
1667 }
1668 } else {
1669 prev_item->next_item=item; item->prev_item=prev_item;
1670 }
1671 } else { // add as child
1672 parent_item->child_item=item; item->parent_item=parent_item;
1673 }
1674 /* Done. Do no free item or buf! */
1675 return(0);
1676 }
1677
1678 return(0);
1679}
1680/*****************************************************************************/
1681
1682/*****************************************************************************/
1689 const char *filename,
1691 DCMFILE *dcm,
1693 const short int headerOnly,
1695 int verbose
1696) {
1697 if(filename==NULL || strnlen(filename, 10)<1 || dcm==NULL) return(1);
1698 if(verbose>1) printf("%s('%s', %d)\n", __func__, filename, headerOnly);
1699
1700 /* Delete any previous data */
1701 dcmfileFree(dcm);
1702
1703 /* Open the file */
1704 strlcpy(dcm->filename, filename, FILENAME_MAX);
1705 dcm->fp=fopen(dcm->filename, "rb");
1706 if(dcm->fp==NULL) {
1707 return(2);
1708 }
1709
1710 /* Check the magic number and move file pointer to the end of it */
1711 if(verbose>2) printf("checking DICOM magic number\n");
1712 if(dcmVerifyMagic(NULL, dcm->fp)!=1) {
1713 fclose(dcm->fp);
1714 return(2);
1715 }
1716
1717 /* Get the Transfer Syntax UID */
1718 if(verbose>2) printf("checking Transfer Syntax UID\n");
1720 if(dcm->truid==DCM_TRUID_INVALID) { // not found
1721 fclose(dcm->fp);
1722 return(2);
1723 }
1724 if(verbose>0) { // print the UID
1725 printf("Transfer Syntax UID := %s\n", dcmTrUIDDescr(dcm->truid));
1726 fflush(stdout);
1727 }
1728
1729 /* Check whether we currently support the Transfer UID */
1730 if(dcm->truid!=DCM_TRUID_LEE) {
1731 fclose(dcm->fp);
1732 return(2);
1733 }
1734
1735 /* Read DICOM file elements */
1736 int ret=0;
1737 do {
1738 // note that the next function may need to call itself,
1739 // therefore counting loops here would not be useful.
1740 ret=dcmFileReadNextElement(dcm, NULL, NULL, 0, headerOnly, verbose-10);
1741 } while(ret==0 && !feof(dcm->fp));
1742 fclose(dcm->fp);
1743 /* TPCERROR_NO_KEY means that no (more) tag was found;
1744 other codes still mean that something bad happened. */
1745 if(ret==-1) {
1746 if(verbose>1) printf(" eof\n");
1747 ret=0;
1748 }
1749 return(ret);
1750}
1751/*****************************************************************************/
1752
1753/*****************************************************************************/
1760 const char *filename,
1762 DCMFILE *dcm,
1764 int verbose
1765) {
1766 if(filename==NULL || strnlen(filename, 10)<1 || dcm==NULL) return(1);
1767 if(verbose>1) {printf("%s('%s')\n", __func__, filename); fflush(stdout);}
1768
1769 /* Check for the data */
1770 if(dcm->item==NULL) {
1771 return(2);
1772 }
1773
1774 /* Check whether we currently support the Transfer UID */
1775 if(dcm->truid!=DCM_TRUID_LEE) { // Little endian explicit
1776 return(2);
1777 }
1778
1779
1780 /* Open the file */
1781 if(verbose>1) printf("opening the file for writing\n");
1782 FILE *fp;
1783 fp=fopen(filename, "wb");
1784 if(fp==NULL) return(3);
1785
1786 /* Write preamble (just 128 zeroes) and magic number */
1787 {
1788 if(verbose>1) printf("writing preamble\n");
1789 char buf1[128], buf2[5];
1790 for(int i=0; i<128; i++) buf1[i]=(char)0;
1791 strcpy(buf2, "DICM");
1792 if(fwrite(buf1, 128, 1, fp)<1 || fwrite(buf2, 4, 1, fp)<1) {
1793 fclose(fp);
1794 return(3);
1795 }
1796 }
1797
1798
1799 /* Write the contents */
1800 if(verbose>1) printf("writing DICOM contents\n");
1801 int ret=0;
1802 DCMITEM *iptr;
1803 DCMITEM *d1=dcm->item;
1804 while(d1!=NULL) {
1805 if(verbose>2) {dcmitemPrint(d1);}
1806 /* Write */
1807 iptr=d1;
1808 {
1809 size_t n;
1810 /* Write tag */
1811 if(dcmWriteFileTag(fp, &iptr->tag)!=0) {ret=1; break;}
1812 /* Write VR and VL */
1813 if(dcmWriteFileVRVL(fp, iptr->vr, iptr->vl, NULL)!=0) {ret=2; break;}
1814 /* Write value, unless zero length, or SQ, in which case written later */
1815 if(iptr->vl>0 && iptr->vr!=DCM_VR_SQ) {
1816 size_t len;
1817 if(iptr->vl==0xFFFFFFFF) {
1818 len=dcmVRVLength(iptr->vr);
1819 if(verbose>30) printf(" value_len1 := %u\n", (unsigned int)len);
1820 n=fwrite(iptr->rd, dcmVRVLength(iptr->vr), 1, fp);
1821 } else {
1822 len=iptr->vl;
1823 if(verbose>30) printf(" value_len3 := %u\n", (unsigned int)len);
1824 n=fwrite(iptr->rd, iptr->vl, 1, fp);
1825 }
1826 if(verbose>30) printf(" value_len := %u\n", (unsigned int)len);
1827 if(n!=1) {ret=4; break;}
1828 } else if(iptr->vr==DCM_VR_SQ && d1->child_item==NULL) {
1829 if(verbose>1) printf("SQ, but no contents to write!\n");
1830 /* Write Sequence Delimitation Item */
1831 if(dcmWriteFileSQDelimItem(fp)!=0) {ret=6; break;}
1832 }
1833 }
1834
1835 /* If this element (SQ) has children, then write those */
1836 /* Data Elements with a group of 0000, 0002 and 0006 shall not be present within Sequence Items,
1837 but that is not verified here */
1838 if(d1->child_item!=NULL) {
1839 DCMITEM *d2=d1->child_item;
1840 unsigned int d2counter=0;
1841 while(d2!=NULL) {
1842 if(verbose>2) {printf(" "); dcmitemPrint(d2);}
1843
1844 /* Write */
1845 iptr=d2;
1846
1847 /* First, write Item tag (FFFE,E000) */
1848 if(d2counter==0) {
1849 DCMTAG tag; tag.group=0xFFFE; tag.element=0xE000;
1850 if(dcmWriteFileTag(fp, &tag)!=0) {ret=11; break;}
1851 }
1852 /* Write item length; write 0xFFFFFFFF for now, correct later when known */
1853 fpos_t d2ilpos; // position for item length
1854 unsigned int d2il=0; // item length
1855 if(d2counter==0) {
1856 if(fgetpos(fp, &d2ilpos)) {ret=12; break;} // save position for writing later
1857 unsigned int ibuf;
1858 ibuf=0xFFFFFFFF;
1859 if(fwrite(&ibuf, 4, 1, fp)!=1) {ret=13; break;}
1860 }
1861 d2counter++;
1862
1863 /* Write item value data set */
1864 {
1865 /* Write tag */
1866 if(dcmWriteFileTag(fp, &iptr->tag)!=0) {ret=14; break;}
1867 d2il+=4;
1868 /* Write VR and VL */
1869 unsigned int s;
1870 if(dcmWriteFileVRVL(fp, iptr->vr, iptr->vl, &s)!=0) {ret=15; break;}
1871 d2il+=s;
1872 /* Write value, unless zero length, or SQ, in which case written later */
1873 if(iptr->vl>0 && iptr->vr!=DCM_VR_SQ) {
1874 size_t len, n;
1875 if(iptr->vl==0xFFFFFFFF) {
1876 len=dcmVRVLength(iptr->vr);
1877 if(verbose>30) printf(" value_len1 := %u\n", (unsigned int)len);
1878 n=fwrite(iptr->rd, dcmVRVLength(iptr->vr), 1, fp);
1879 d2il+=len;
1880 } else {
1881 len=iptr->vl;
1882 if(verbose>30) printf(" value_len3 := %u\n", (unsigned int)len);
1883 n=fwrite(iptr->rd, iptr->vl, 1, fp);
1884 d2il+=iptr->vl;
1885 }
1886 if(verbose>30) printf(" value_len := %u\n", (unsigned int)len);
1887 if(n!=1) {ret=17; break;}
1888 } else if(iptr->vr==DCM_VR_SQ && iptr->child_item==NULL) {
1889 if(verbose>1) printf("SQ, but no contents to write!\n");
1890 /* Write Sequence Delimitation Item */
1891 if(dcmWriteFileSQDelimItem(fp)!=0) {ret=19; break;}
1892 }
1893 }
1894
1895 /* If this element has children, then write those */
1896 if(d2->child_item!=NULL) {
1897 DCMITEM *d3=d2->child_item;
1898 unsigned int d3counter=0;
1899 while(d3!=NULL) {
1900 if(verbose>2) {printf(" "); dcmitemPrint(d3);}
1901
1902 /* Write */
1903 iptr=d3;
1904 if(iptr->vr==DCM_VR_SQ) {d3=d3->next_item; continue;} // for now do not write SQs
1905
1906 /* First, write Item tag (FFFE,E000) */
1907 if(d3counter==0) {
1908 DCMTAG tag; tag.group=0xFFFE; tag.element=0xE000;
1909 if(dcmWriteFileTag(fp, &tag)!=0) {ret=31; break;}
1910 d2il+=4;
1911 }
1912 /* Write item length; write 0xFFFFFFFF for now, correct later when known */
1913 fpos_t d3ilpos; // position for item length
1914 unsigned int d3il=0; // item length
1915 if(d3counter==0) {
1916 unsigned int ibuf;
1917 if(fgetpos(fp, &d3ilpos)) {ret=32; break;} // save position for writing later
1918 ibuf=0xFFFFFFFF;
1919 if(fwrite(&ibuf, 4, 1, fp)!=1) {ret=33; break;}
1920 d2il+=4;
1921 }
1922 d3counter++;
1923
1924 /* Write item value data set */
1925 {
1926 /* Write tag */
1927 if(dcmWriteFileTag(fp, &iptr->tag)!=0) {ret=34; break;}
1928 d3il+=4; d2il+=4;
1929 /* Write VR and VL */
1930 unsigned int s;
1931 if(dcmWriteFileVRVL(fp, iptr->vr, iptr->vl, &s)!=0) {ret=35; break;}
1932 d3il+=s; d2il+=s;
1933 /* Write value, unless zero length, or SQ, in which case written later */
1934 if(iptr->vl>0 && iptr->vr!=DCM_VR_SQ) {
1935 size_t len, n;
1936 if(iptr->vl==0xFFFFFFFF) {
1937 len=dcmVRVLength(iptr->vr);
1938 if(verbose>30) printf(" value_len1 := %u\n", (unsigned int)len);
1939 n=fwrite(iptr->rd, dcmVRVLength(iptr->vr), 1, fp);
1940 d3il+=len; d2il+=len;
1941 } else {
1942 len=iptr->vl;
1943 if(verbose>30) printf(" value_len3 := %u\n", (unsigned int)len);
1944 n=fwrite(iptr->rd, iptr->vl, 1, fp);
1945 d3il+=iptr->vl; d2il+=iptr->vl;
1946 }
1947 if(verbose>30) printf(" value_len := %u\n", (unsigned int)len);
1948 if(n!=1) {ret=37; break;}
1949 } else if(iptr->vr==DCM_VR_SQ && iptr->child_item==NULL) {
1950 if(verbose>1) printf("SQ, but no contents to write!\n");
1951 /* Write Sequence Delimitation Item */
1952 if(dcmWriteFileSQDelimItem(fp)!=0) {ret=39; break;}
1953 d2il+=8;
1954 }
1955 }
1956
1957 /* If this element has children, then write those */
1958 if(d3->child_item!=NULL) {
1959 //DCMITEM *d4=d3->child_item;
1960 if(verbose>0) fprintf(stderr, "Warning: 4th level items not written.\n");
1961 }
1962
1963 /* now that we known the length, write it to the saved position */
1964 if(0) {
1965 fpos_t opos; // current position to return to
1966 if(fgetpos(fp, &opos)) {ret=40; break;}
1967 fsetpos(fp, &d3ilpos); // go to the position for item length
1968 char buf[4];
1969 memcpy(buf, &d3il, 4);
1970 if(!little_endian()) swabip(buf, 4);
1971 if(fwrite(&buf, 4, 1, fp)!=1) {ret=41; break;}
1972 fsetpos(fp, &opos); // back to the position where we were
1973 }
1974
1975 d3=d3->next_item;
1976 }
1977 if(ret!=0) break;
1978
1979 /* Write Item Delimitation Tag */
1980 if(dcmWriteFileSQItemDelimTag(fp)!=0) {ret=21; break;}
1981 /* End of the sequence - write Sequence Delimitation Item */
1982 if(dcmWriteFileSQDelimItem(fp)!=0) {ret=21; break;}
1983
1984 }
1985
1986
1987 /* now that we known the length, write it to the saved position */
1988 if(0) {
1989 fpos_t opos; // current position to return to
1990 if(fgetpos(fp, &opos)) {ret=18; break;}
1991 fsetpos(fp, &d2ilpos); // go to the position for item length
1992 char buf[4];
1993 memcpy(buf, &d2il, 4);
1994 if(!little_endian()) swabip(buf, 4);
1995 if(fwrite(&buf, 4, 1, fp)!=1) {ret=19; break;}
1996 fsetpos(fp, &opos); // back to the position where we were
1997 }
1998
1999 d2=d2->next_item;
2000 }
2001 if(ret!=0) break;
2002
2003 /* Write Item Delimitation Tag */
2004 if(dcmWriteFileSQItemDelimTag(fp)!=0) {ret=21; break;}
2005 /* End of the sequence - write Sequence Delimitation Item */
2006 if(dcmWriteFileSQDelimItem(fp)!=0) {ret=21; break;}
2007
2008 }
2009
2010 d1=d1->next_item;
2011 } // next
2012 if(ret!=0) {
2013 if(verbose>0) fprintf(stderr, " ret := %d\n", ret);
2014 fclose(fp);
2015 return(3);
2016 }
2017
2018
2019 fclose(fp);
2020
2021 return(0);
2022}
2023/*****************************************************************************/
2024
2025/*****************************************************************************/
int isdate(char *str)
Definition datetime.c:146
int istime(char *str)
Definition datetime.c:259
int isdatetime(char *str, char *intdate)
Definition datetime.c:280
int dcmAddItem(DCMFILE *dcm, DCMITEM *d, short int aschild, DCMTAG tag, dcmvr vr, unsigned int vl, char *rd, const int verbose)
Definition dcm.c:1239
dcmtruid dcmReadTransferSyntaxUID(FILE *fp)
Definition dcm.c:502
long int dcmitemGetInt(DCMITEM *d)
Definition dcm.c:1084
unsigned short int dcmitemMaxDepth(DCMITEM *d)
Definition dcm.c:884
unsigned char dcmVRReserved(dcmvr id)
Definition dcm.c:205
unsigned int dcmSOPIdentify(const char *s)
Definition dcm.c:367
int dcmWriteFileVRVL(FILE *fp, dcmvr vr, unsigned int vl, unsigned int *n)
Definition dcm.c:784
char * dcmTrUIDDescr(dcmtruid id)
Definition dcm.c:466
int dcmFileRead(const char *filename, DCMFILE *dcm, const short int headerOnly, int verbose)
Definition dcm.c:1687
size_t dcmVRVLength(dcmvr id)
Definition dcm.c:264
void dcmfileInit(DCMFILE *d)
Definition dcm.c:823
void dcmTagSet(DCMTAG *tag, unsigned short int group, unsigned short int element)
Definition dcm.c:1221
dcmvr dcmVRId(const char *s)
Definition dcm.c:223
DCMITEM * dcmFindTag(DCMITEM *d, const short int omit, DCMTAG *tag, const int verbose)
Definition dcm.c:1163
int dcmFileWrite(const char *filename, DCMFILE *dcm, int verbose)
Definition dcm.c:1758
char * dcmDT2intl(const char *orig, char *intl)
Definition dcm.c:345
void dcmfileFree(DCMFILE *d)
Definition dcm.c:868
char * dcmDA2intl(const char *orig, char *intl)
Definition dcm.c:299
void dcmitemFree(DCMITEM *d)
Definition dcm.c:840
char * dcmTM2intl(const char *orig, char *intl)
Definition dcm.c:322
char * dcmVRName(dcmvr id)
Definition dcm.c:246
dcmvr dcmReadFileVR(FILE *fp, char *vrstr)
Definition dcm.c:655
void dcmitemPrint(DCMITEM *d)
Definition dcm.c:1205
int dcmReadFileTag(FILE *fp, DCMTAG *tag)
Definition dcm.c:553
double dcmitemGetReal(DCMITEM *d)
Definition dcm.c:1120
int dcmReadFileVRVL(FILE *fp, dcmvr *vr, unsigned int *vl, unsigned int *n)
Definition dcm.c:724
char * dcmSOPUIDName(const char *s)
Definition dcm.c:424
int dcmFileReadNextElement(DCMFILE *dcm, DCMITEM *prev_item, DCMITEM *parent_item, const short int sub, const short int headerOnly, int verbose)
Definition dcm.c:1370
int dcmWriteFileSQItemDelimTag(FILE *fp)
Definition dcm.c:634
unsigned short int dcmfileMaxDepth(DCMFILE *df)
Definition dcm.c:903
unsigned int dcmReadFileVL(FILE *fp, unsigned int n)
Definition dcm.c:692
char * dcmTrUIDString(dcmtruid id)
Definition dcm.c:484
unsigned short int dcmitemParentNr(DCMITEM *d)
Definition dcm.c:923
char * dcmValueString(DCMITEM *d)
Definition dcm.c:942
char * dcmVRDescr(dcmvr id)
Definition dcm.c:282
char * dcmSOPUID(unsigned int i)
Definition dcm.c:406
dcmtruid dcmTrUID(const char *s)
Definition dcm.c:445
int dcmWriteFileTag(FILE *fp, DCMTAG *tag)
Definition dcm.c:583
int dcmVerifyMagic(const char *filename, FILE *fp)
Definition dcm.c:157
char * dcmSOPName(unsigned int i)
Definition dcm.c:388
int dcmWriteFileSQDelimItem(FILE *fp)
Definition dcm.c:609
Header file for libtpcimgio.
dcmvr
@ DCM_VR_INVALID
Invalid DICOM value representation.
@ DCM_VR_DT
DICOM date time, max 26 bytes.
@ DCM_VR_UI
DICOM unique identifier (UID), max 64 bytes.
@ DCM_VR_FD
DICOM floating point double precision, 8 bytes fixed.
@ DCM_VR_UC
DICOM unlimited characters.
@ DCM_VR_PN
DICOM person name, max 64 chars per component group.
@ DCM_VR_CS
DICOM code (control) string, max 16 bytes.
@ DCM_VR_SS
DICOM signed short (16-bit integer), 2 bytes fixed.
@ DCM_VR_SH
DICOM short string, max 16 chars.
@ DCM_VR_OF
DICOM other float (32-bit) stream, endian sensitive.
@ DCM_VR_UT
DICOM unlimited text, character string.
@ DCM_VR_US
DICOM unsigned short (16-bit) integer, 2 bytes fixed.
@ DCM_VR_TM
DICOM time HHMMSS.FFFFFF, max 14 bytes.
@ DCM_VR_OB
DICOM other byte string, even bytes, endian insensitive.
@ DCM_VR_AS
DICOM age string, 4 bytes fixed.
@ DCM_VR_ST
DICOM short text, max 1024 chars.
@ DCM_VR_AT
DICOM attribute tag, 4 bytes fixed.
@ DCM_VR_LT
DICOM long text, max 10240 chars.
@ DCM_VR_DA
DICOM date in format YYYYMMDD, 8 bytes fixed.
@ DCM_VR_UL
DICOM unsigned long (32-bit) integer, 4 bytes fixed.
@ DCM_VR_UN
DICOM unknown, any valid length of another VR.
@ DCM_VR_DS
DICOM decimal string, max 16 bytes.
@ DCM_VR_OW
DICOM other word (16-bit) stream, even bytes, endian sensitive.
@ DCM_VR_IS
DICOM integer string, max 12 bytes.
@ DCM_VR_AE
DICOM application entity, max 16 bytes.
@ DCM_VR_UR
DICOM URI or URL, string of characters.
@ DCM_VR_LO
DICOM long string, max 64 chars.
@ DCM_VR_SQ
DICOM sequence of zero or more elements (used for nested data).
@ DCM_VR_FL
DICOM floating point single precision, 4 bytes fixed.
@ DCM_VR_SL
DICOM signed long (32-bit integer), 4 bytes fixed.
@ DCM_VR_OL
DICOM other long (32-bit) stream, endian sensitive.
@ DCM_VR_OD
DICOM other double (64-bit) stream, endian sensitive.
dcmtruid
@ DCM_TRUID_LEI
Little Endian Implicit VR (DICOM default)
@ DCM_TRUID_JPEG81
Lossy JPEG-LS.
@ DCM_TRUID_JPEG93
Multicomponent JPEG 2000.
@ DCM_TRUID_MPEG100
MPEG-2.
@ DCM_TRUID_JPEG92
Lossless multicomponent JPEG 2000.
@ DCM_TRUID_JPEG91
JPEG 2000.
@ DCM_TRUID_JPEG70
Lossless JPEG.
@ DCM_TRUID_XML
XML encoding.
@ DCM_TRUID_INVALID
Invalid Transfer Syntax UID.
@ DCM_TRUID_MPEG103
MPEG-4 BD-compatible.
@ DCM_TRUID_RFC
RFC 2557.
@ DCM_TRUID_JPEG80
Lossless JPEG-LS.
@ DCM_TRUID_UNKNOWN
Unknown Transfer Syntax UID
@ DCM_TRUID_BEE
Big Endian Explicit VR.
@ DCM_TRUID_JPEG51
Lossy JPEG 12-bit compression.
@ DCM_TRUID_RLE
Lossless RLE.
@ DCM_TRUID_LEE
Little Endian Explicit VR.
@ DCM_TRUID_JPEG90
Lossless JPEG 2000.
@ DCM_TRUID_JPEG50
Lossy JPEG 8-bit compression.
@ DCM_TRUID_MPEG102
MPEG-4.
void swabip(void *buf, long long int size)
Definition swap.c:72
size_t strnlen(const char *s, size_t n)
Definition strext.c:181
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
int little_endian()
Definition swap.c:14
void swap(void *orig, void *new, int size)
Definition swap.c:31
dcmtruid truid
DCMITEM * item
char filename[FILENAME_MAX]
FILE * fp
dcmtruid truid
struct DCMITEM * child_item
struct DCMITEM * next_item
unsigned int vl
FILE * fp
fpos_t pos
char * rd
struct DCMITEM * prev_item
struct DCMITEM * parent_item
DCMTAG tag
unsigned short int element
unsigned short int group