5#include "tpcclibConfig.h"
39 if(filename==NULL && fp==NULL)
return(0);
43 lfp=fopen(filename,
"rb");
45 if(lfp==NULL)
return(0);
48 if(fseek(lfp, 128, SEEK_SET)) {
if(fp==NULL) fclose(lfp);
return(0);}
52 size_t n=fread(&buf, 1, 4, lfp);
55 if(n!=(
size_t)4) {rewind(lfp);
return(0);}
58 if(strncmp(buf,
"DICM", 4)==0) {
59 if(fp==NULL) fclose(lfp);
62 if(fp==NULL) fclose(lfp);
else rewind(lfp);
86 while(!tag_found && !feof(fp)) {
90 if(tag.
group==0x0002 && tag.
element==0x0010) {tag_found=1;
break;}
101 if(vl==0xFFFFFFFF)
break;
104 if(fread(buf, 1, vl, fp)!=vl)
break;
143 if(fp==NULL || feof(fp))
return(1);
144 unsigned short int buf[2];
145 size_t n=fread(&buf, 2, 2, fp);
146 if(n!=2)
return(2+n);
172 unsigned short int buf[2];
244 if(vrstr!=NULL) vrstr[0]=(char)0;
256 else strcpy(vrstr, buf);
281 if(fp==NULL || (n!=2 && n!=4))
return(vl);
285 unsigned short int si;
286 if(fread(&si, 2, 1, fp)!=1)
return(vl);
291 if(fread(&li, 4, 1, fp)!=1)
return(vl);
328 if(vr!=NULL) *vr=lvr;
342 unsigned short int si;
352 if(n!=NULL) *n+=bsize;
353 if(vl!=NULL) *vl=lvl;
386 memcpy(buf,
dcmVRName(vr), 2); buf[2]=buf[3]=(char)0;
388 if(n!=NULL) *n+=bsize;
391 memcpy(buf, &vl, bsize);
392 if(bsize==2) buf[2]=buf[3]=(char)0;
396 if(n!=NULL) *n+=bsize;
419 const short int headerOnly,
423 if(verbose>0) printf(
"%s(DCMFILE*, DCMITEM*, DCMITEM*, %d, %d)\n", __func__, sub, headerOnly);
439 if(dcm->
item==NULL) printf(
" will add first element\n");
440 else if(sub==0) printf(
" will add next element\n");
441 else printf(
" will add sub-element\n");
446 if(parent_item!=NULL && parent_item->
vr==
DCM_VR_SQ) {sq_child=1;}
447 if(verbose>10 && sq_child!=0) printf(
" we're a child to a sequence element\n");
456 item->
rd=(
char*)NULL;
459 if(fgetpos(dcm->
fp, &item->
pos)) {
465 long long int tagpos=ftello(dcm->
fp);
466 printf(
" reading tag at %lld\n", tagpos);
469 if(verbose>1 && !feof(dcm->
fp)) printf(
" error in reading the tag.\n");
476 printf(
" tag(%04x,%04x) with %u parents\n",
483 printf(
" item delimitation tag(%04x,%04x) found, reading VL\n",
486 if(verbose>1) printf(
" item delimitation tag VL := %lu (0x%08lx)\n", vl, vl);
488 if(verbose>1) printf(
" error: VL should have been 0\n");
499 if(verbose>10) printf(
" reading VR and VL\n");
504 if(verbose>1) printf(
" invalid VR or VL\n");
505 free(item);
return(ret);
509 printf(
" VL := %u (0x%08x) (%d bytes field)\n", item->
vl, item->
vl, n/2);
513 if(verbose>10) printf(
" set VR based on the tag\n");
522 if(verbose>1) printf(
" VR not known for tag(%04x,%04x)\n",
525 if(verbose>10) printf(
" reading VL\n");
528 printf(
" VL := %u (0x%08x)\n", item->
vl, item->
vl);
536 unsigned long long int sqPos=(
unsigned long int)ftello(dcm->
fp);
537 if(verbose>10) {printf(
" sequence... at %llu\n", sqPos); fflush(stdout);}
538 unsigned long int sqContentLength=item->
vl;
539 if(verbose>12) printf(
" sequence contents length is %lu\n", sqContentLength);
543 if(sq_child!=0 && parent_item->
child_item==NULL) {
548 if(prev_item==NULL) {
549 if(dcm->
item==NULL) {
562 long long int tagpos=ftello(dcm->
fp);
563 printf(
" reading first item tag at %lld\n", tagpos);
568 if(verbose>1) printf(
" error %d in reading the tag.\n", ret);
571 if(verbose>1) printf(
" item tag(%04x,%04x)\n", itemtag.
group, itemtag.
element);
576 printf(
" sequence delimitation item tag(%04x,%04x) found, reading VL\n",
579 if(verbose>1) printf(
" item tag VL := %lu (0x%08lx)\n", vl, vl);
581 if(verbose>1) printf(
" error: VL should have been 0\n");
584 if(verbose>3) printf(
" ending sequence before it really started.\n");
589 if(verbose>1) printf(
" invalid sequence item tag(%04x,%04x)\n", itemtag.
group, itemtag.
element);
594 if(verbose>3) {printf(
" item_VL := %lu (0x%08lx)\n", itemvl, itemvl);}
596 unsigned long int sqItemPos=(
unsigned long int)ftell(dcm->
fp);
598 if((sqItemPos-sqPos)>=sqContentLength) {
599 if(verbose>3) printf(
" ending sequence since it was found to be empty.\n");
602 if(verbose>12) printf(
" sequence content start position at %ld\n", sqItemPos);
606 if(verbose>1) printf(
" error in reading the first item value dataset\n");
610 while(!feof(dcm->
fp)) {
613 unsigned long long int cPos=(
unsigned long long int)ftello(dcm->
fp);
614 if(sqContentLength>0 && (cPos-sqPos)>=sqContentLength) {
615 if(verbose>3) printf(
" we reached the end of sequence VL %lu\n", sqContentLength);
621 long long int tagpos=ftello(dcm->
fp);
622 printf(
" reading next sequence item tag at %lld, %lld after start\n", tagpos, tagpos-sqItemPos);
625 if(verbose>1) printf(
" next item tag(%04x,%04x)\n", itemtag.
group, itemtag.
element);
627 if(verbose>3) {printf(
" item_VL := %lu (0x%08lx)\n", itemvl, itemvl);}
631 if(verbose>3) printf(
" we got sequence delimitation tag\n");
637 if(verbose>3) printf(
" we got item delimitation tag\n");
639 if(verbose>1) printf(
" error: VL should have been 0\n");
646 if(verbose>3) printf(
" not sequence item tag, move file position back 2x4 bytes\n");
647 fseeko(dcm->
fp, -8, SEEK_CUR);
652 if(verbose>1) printf(
" error had happened in adding the child element\n");
658 if(verbose>1) printf(
" error in reading item value dataset\n");
666 printf(
" invalid sequence delimitation item tag(%04x,%04x)\n", itemtag.
group, itemtag.
element);
670 if(verbose>10) {printf(
" end of sequence.\n"); fflush(stdout);}
671 }
else if(item->
vl!=0xFFFFFFFF) {
672 if(verbose>10) {printf(
" reading value of %u bytes...\n", item->
vl); fflush(stdout);}
675 buf=(
char*)calloc(item->
vl+1,
sizeof(
char));
677 if(fread(buf, 1, item->
vl, item->
fp)!=item->
vl) {
684 if(verbose>5) {printf(
" ...not storing pixel data\n"); fflush(stdout);}
685 free(buf); buf=(
char*)NULL;
689 }
else if(verbose>4) {
694 if(prev_item==NULL) {
695 if(dcm->
item==NULL) {
721 if(verbose>0) printf(
" Unknown VL!!\n");
725 if(verbose>4) printf(
" VR_based_VL=%u\n", (
unsigned int)s);
726 char *buf=(
char*)calloc(s+1,
sizeof(
char));
728 if(fread(buf, 1, s, item->
fp)!=s) {
734 if(prev_item==NULL) {
735 if(dcm->
item==NULL) {
770 const char *filename,
774 const short int headerOnly,
778 int verbose=0;
if(status!=NULL) verbose=status->
verbose;
779 if(filename==NULL ||
strnlen(filename, 10)<1 || dcm==NULL) {
783 if(verbose>1) printf(
"%s('%s', %d)\n", __func__, filename, headerOnly);
797 if(verbose>2) printf(
"checking DICOM magic number\n");
805 if(verbose>2) printf(
"checking Transfer Syntax UID\n");
839 if(verbose>1) printf(
" eof\n");
842 statusSet(status, __func__, __FILE__, __LINE__, ret);
854 const char *filename,
860 int verbose=0;
if(status!=NULL) verbose=status->
verbose;
861 if(filename==NULL ||
strnlen(filename, 10)<1 || dcm==NULL) {
865 if(verbose>1) {printf(
"%s('%s')\n", __func__, filename); fflush(stdout);}
868 if(dcm->
item==NULL) {
881 if(verbose>1) printf(
"opening the file for writing\n");
883 fp=fopen(filename,
"wb");
891 if(verbose>1) printf(
"writing preamble\n");
892 char buf1[128], buf2[5];
893 for(
int i=0; i<128; i++) buf1[i]=(
char)0;
894 strcpy(buf2,
"DICM");
895 if(fwrite(buf1, 128, 1, fp)<1 || fwrite(buf2, 4, 1, fp)<1) {
903 if(verbose>1) printf(
"writing DICOM contents\n");
920 if(iptr->
vl==0xFFFFFFFF) {
922 if(verbose>30) printf(
" value_len1 := %u\n", (
unsigned int)len);
926 if(verbose>30) printf(
" value_len3 := %u\n", (
unsigned int)len);
927 n=fwrite(iptr->
rd, iptr->
vl, 1, fp);
929 if(verbose>30) printf(
" value_len := %u\n", (
unsigned int)len);
930 if(n!=1) {ret=4;
break;}
932 if(verbose>1) printf(
"SQ, but no contents to write!\n");
943 unsigned int d2counter=0;
959 if(fgetpos(fp, &d2ilpos)) {ret=12;
break;}
962 if(fwrite(&ibuf, 4, 1, fp)!=1) {ret=13;
break;}
978 if(iptr->
vl==0xFFFFFFFF) {
980 if(verbose>30) printf(
" value_len1 := %u\n", (
unsigned int)len);
985 if(verbose>30) printf(
" value_len3 := %u\n", (
unsigned int)len);
986 n=fwrite(iptr->
rd, iptr->
vl, 1, fp);
989 if(verbose>30) printf(
" value_len := %u\n", (
unsigned int)len);
990 if(n!=1) {ret=17;
break;}
992 if(verbose>1) printf(
"SQ, but no contents to write!\n");
1001 unsigned int d3counter=0;
1017 unsigned int d3il=0;
1020 if(fgetpos(fp, &d3ilpos)) {ret=32;
break;}
1022 if(fwrite(&ibuf, 4, 1, fp)!=1) {ret=33;
break;}
1039 if(iptr->
vl==0xFFFFFFFF) {
1041 if(verbose>30) printf(
" value_len1 := %u\n", (
unsigned int)len);
1043 d3il+=len; d2il+=len;
1046 if(verbose>30) printf(
" value_len3 := %u\n", (
unsigned int)len);
1047 n=fwrite(iptr->
rd, iptr->
vl, 1, fp);
1048 d3il+=iptr->
vl; d2il+=iptr->
vl;
1050 if(verbose>30) printf(
" value_len := %u\n", (
unsigned int)len);
1051 if(n!=1) {ret=37;
break;}
1053 if(verbose>1) printf(
"SQ, but no contents to write!\n");
1063 if(verbose>0) fprintf(stderr,
"Warning: 4th level items not written.\n");
1069 if(fgetpos(fp, &opos)) {ret=40;
break;}
1070 fsetpos(fp, &d3ilpos);
1072 memcpy(buf, &d3il, 4);
1074 if(fwrite(&buf, 4, 1, fp)!=1) {ret=41;
break;}
1093 if(fgetpos(fp, &opos)) {ret=18;
break;}
1094 fsetpos(fp, &d2ilpos);
1096 memcpy(buf, &d2il, 4);
1098 if(fwrite(&buf, 4, 1, fp)!=1) {ret=19;
break;}
1116 if(verbose>0) fprintf(stderr,
" ret := %d\n", ret);
void dcmfileFree(DCMFILE *d)
void dcmitemPrint(DCMITEM *d)
unsigned short int dcmitemParentNr(DCMITEM *d)
char * dcmValueString(DCMITEM *d)
char * dcmDictIndexVR(unsigned int i)
char * dcmDictIndexDescr(unsigned int i)
unsigned int dcmDictFindTag(DCMTAG *tag)
dcmtruid dcmReadTransferSyntaxUID(FILE *fp)
int dcmWriteFileVRVL(FILE *fp, dcmvr vr, unsigned int vl, unsigned int *n)
dcmvr dcmReadFileVR(FILE *fp, char *vrstr)
int dcmReadFileTag(FILE *fp, DCMTAG *tag)
int dcmFileRead(const char *filename, DCMFILE *dcm, const short int headerOnly, TPCSTATUS *status)
int dcmReadFileVRVL(FILE *fp, dcmvr *vr, unsigned int *vl, unsigned int *n)
int dcmFileWrite(const char *filename, DCMFILE *dcm, TPCSTATUS *status)
int dcmFileReadNextElement(DCMFILE *dcm, DCMITEM *prev_item, DCMITEM *parent_item, const short int sub, const short int headerOnly, int verbose)
int dcmWriteFileSQItemDelimTag(FILE *fp)
unsigned int dcmReadFileVL(FILE *fp, unsigned int n)
int dcmWriteFileTag(FILE *fp, DCMTAG *tag)
int dcmVerifyMagic(const char *filename, FILE *fp)
int dcmWriteFileSQDelimItem(FILE *fp)
char * dcmTrUIDDescr(dcmtruid id)
dcmtruid dcmTrUID(const char *s)
unsigned char dcmVRReserved(dcmvr id)
size_t dcmVRVLength(dcmvr id)
dcmvr dcmVRId(const char *s)
char * dcmVRName(dcmvr id)
char * dcmVRDescr(dcmvr id)
void swabip(void *buf, int size)
void swap(void *from, void *to, int size)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
size_t strnlen(const char *s, size_t n)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
char filename[FILENAME_MAX]
struct DCMITEM * child_item
struct DCMITEM * next_item
struct DCMITEM * prev_item
struct DCMITEM * parent_item
unsigned short int element
int verbose
Verbose level, used by statusPrint() etc.
Header file for libtpcdcm.
@ DCM_VR_INVALID
Invalid DICOM value representation.
@ DCM_VR_UI
DICOM unique identifier (UID), max 64 bytes.
@ DCM_VR_SQ
DICOM sequence of zero or more elements (used for nested data).
@ DCM_TRUID_LEI
Little Endian Implicit VR (DICOM default)
@ DCM_TRUID_INVALID
Invalid Transfer Syntax UID.
@ DCM_TRUID_LEE
Little Endian Explicit VR.
Header file for library libtpcextensions.
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_NO_VALUE
Value not found.
@ TPCERROR_FAIL
General error.
@ TPCERROR_INVALID_FORMAT
Invalid file format.
@ TPCERROR_CANNOT_OPEN
Cannot open file.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_NO_KEY
Key not found.
@ TPCERROR_UNSUPPORTED
Unsupported file type.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_CANNOT_READ
Cannot read file.
@ TPCERROR_CANNOT_WRITE
Cannot write file.