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

IO functions for DICOM files. 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 dcmVerifyMagic (const char *filename, FILE *fp)
 
dcmtruid dcmReadTransferSyntaxUID (FILE *fp)
 
int dcmReadFileTag (FILE *fp, DCMTAG *tag)
 
int dcmWriteFileTag (FILE *fp, DCMTAG *tag)
 
int dcmWriteFileSQDelimItem (FILE *fp)
 
int dcmWriteFileSQItemDelimTag (FILE *fp)
 
dcmvr dcmReadFileVR (FILE *fp, char *vrstr)
 
unsigned int dcmReadFileVL (FILE *fp, unsigned int n)
 
int dcmReadFileVRVL (FILE *fp, dcmvr *vr, unsigned int *vl, unsigned int *n)
 
int dcmWriteFileVRVL (FILE *fp, dcmvr vr, unsigned int vl, unsigned int *n)
 
int dcmFileReadNextElement (DCMFILE *dcm, DCMITEM *prev_item, DCMITEM *parent_item, const short int sub, const short int headerOnly, int verbose)
 
int dcmFileRead (const char *filename, DCMFILE *dcm, const short int headerOnly, TPCSTATUS *status)
 
int dcmFileWrite (const char *filename, DCMFILE *dcm, TPCSTATUS *status)
 

Detailed Description

IO functions for DICOM files.

Definition in file dcmio.c.

Function Documentation

◆ dcmFileRead()

int dcmFileRead ( const char * filename,
DCMFILE * dcm,
const short int headerOnly,
TPCSTATUS * status )

Read a single DICOM file.

See also
dcmVerifyMagic, dcmfileInit, dcmfileFree, dcmReadTransferSyntaxUID, dcmFileWrite, dcmFileList
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Parameters
filenamePointer to filename.
dcmPointer to initiated data structure.
headerOnlyRead only header (1), or read both header and pixel data (0).
statusPointer to status data; enter NULL if not needed.

Definition at line 768 of file dcmio.c.

777 {
778 int verbose=0; if(status!=NULL) verbose=status->verbose;
779 if(filename==NULL || strnlen(filename, 10)<1 || dcm==NULL) {
780 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
781 return TPCERROR_FAIL;
782 }
783 if(verbose>1) printf("%s('%s', %d)\n", __func__, filename, headerOnly);
784
785 /* Delete any previous data */
786 dcmfileFree(dcm);
787
788 /* Open the file */
789 strlcpy(dcm->filename, filename, FILENAME_MAX);
790 dcm->fp=fopen(dcm->filename, "rb");
791 if(dcm->fp==NULL) {
792 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN);
794 }
795
796 /* Check the magic number and move file pointer to the end of it */
797 if(verbose>2) printf("checking DICOM magic number\n");
798 if(dcmVerifyMagic(NULL, dcm->fp)!=1) {
799 fclose(dcm->fp);
800 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
802 }
803
804 /* Get the Transfer Syntax UID */
805 if(verbose>2) printf("checking Transfer Syntax UID\n");
807 if(dcm->truid==DCM_TRUID_INVALID) { // not found
808 fclose(dcm->fp);
809 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
811 }
812 if(verbose>0) { // print the UID
813 printf("Transfer Syntax UID := %s\n", dcmTrUIDDescr(dcm->truid));
814 fflush(stdout);
815 }
816
817 /* Check whether we currently support the Transfer UID */
818 switch(dcm->truid) {
819 case DCM_TRUID_LEE:
820 case DCM_TRUID_LEI: // actually not supported yet
821 break;
822 default:
823 fclose(dcm->fp);
824 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
826 }
827
828 /* Read DICOM file elements */
829 int ret=TPCERROR_OK;
830 do {
831 // note that the next function may need to call itself,
832 // therefore counting loops here would not be useful.
833 ret=dcmFileReadNextElement(dcm, NULL, NULL, 0, headerOnly, verbose-10);
834 } while(ret==TPCERROR_OK && !feof(dcm->fp));
835 fclose(dcm->fp);
836 /* TPCERROR_NO_KEY means that no (more) tag was found;
837 other codes still mean that something bad happened. */
838 if(ret==TPCERROR_NO_KEY) {
839 if(verbose>1) printf(" eof\n");
840 ret=TPCERROR_OK;
841 }
842 statusSet(status, __func__, __FILE__, __LINE__, ret);
843 return(ret);
844}
void dcmfileFree(DCMFILE *d)
Definition dcmdata.c:67
dcmtruid dcmReadTransferSyntaxUID(FILE *fp)
Definition dcmio.c:73
int dcmFileReadNextElement(DCMFILE *dcm, DCMITEM *prev_item, DCMITEM *parent_item, const short int sub, const short int headerOnly, int verbose)
Definition dcmio.c:409
int dcmVerifyMagic(const char *filename, FILE *fp)
Definition dcmio.c:25
char * dcmTrUIDDescr(dcmtruid id)
Definition dcmuid.c:87
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
dcmtruid truid
Definition tpcdcm.h:162
char filename[FILENAME_MAX]
Definition tpcdcm.h:158
FILE * fp
Definition tpcdcm.h:160
int verbose
Verbose level, used by statusPrint() etc.
@ DCM_TRUID_LEI
Little Endian Implicit VR (DICOM default)
Definition tpcdcm.h:59
@ DCM_TRUID_INVALID
Invalid Transfer Syntax UID.
Definition tpcdcm.h:78
@ DCM_TRUID_LEE
Little Endian Explicit VR.
Definition tpcdcm.h:60
@ TPCERROR_FAIL
General error.
@ TPCERROR_INVALID_FORMAT
Invalid file format.
@ TPCERROR_CANNOT_OPEN
Cannot open file.
@ TPCERROR_NO_KEY
Key not found.
@ TPCERROR_UNSUPPORTED
Unsupported file type.
@ TPCERROR_OK
No error.

Referenced by dcmFileList(), dcmMListRead(), and imgReadDICOM().

◆ dcmFileReadNextElement()

int dcmFileReadNextElement ( DCMFILE * dcm,
DCMITEM * prev_item,
DCMITEM * parent_item,
const short int sub,
const short int headerOnly,
int verbose )

Read an element from DICOM file, and add it to the given linked list. This function will be called recursively in case of sequential items.

Returns
Code tpcerror, TPCERROR_OK (0) when successful, TPCERROR_NO_KEY when no more elements could be read.
See also
dcmFileRead
Parameters
dcmPointer to DCMFILE struct; must be initiated before first call.
prev_itemPointer to previous element; NULL if none exists (yet).
parent_itemPointer to parent element; NULL if none exists (yet).
subAdd as next element (0) or as child element.
headerOnlyRead only header (1), or read both header and pixel data (0).
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 409 of file dcmio.c.

422 {
423 if(verbose>0) printf("%s(DCMFILE*, DCMITEM*, DCMITEM*, %d, %d)\n", __func__, sub, headerOnly);
424 if(dcm==NULL || dcm->fp==NULL) return(TPCERROR_FAIL);
425 if(sub!=0 && parent_item==NULL) return(TPCERROR_FAIL);
426 if(feof(dcm->fp)) return(TPCERROR_NO_KEY);
427
428 /* Check whether we currently support the Transfer UID */
429 switch(dcm->truid) {
430 case DCM_TRUID_LEE:
431 break;
432 case DCM_TRUID_LEI: // actually not supported yet
433 break;
434 default:
435 return(TPCERROR_UNSUPPORTED);
436 }
437
438 if(verbose>10) {
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");
442 }
443
444 /* Is this a child to a sequence element? */
445 int sq_child=0;
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");
448
449 /* Allocate memory for the new element */
450 DCMITEM *item=(DCMITEM*)malloc(sizeof(DCMITEM));
451 if(item==NULL) return(TPCERROR_OUT_OF_MEMORY);
452 item->prev_item=prev_item;
453 item->parent_item=parent_item;
454 item->next_item=item->child_item=(DCMITEM*)NULL;
455 item->fp=dcm->fp; item->truid=dcm->truid;
456 item->rd=(char*)NULL;
457
458 /* Save current file position (should be the start of element) */
459 if(fgetpos(dcm->fp, &item->pos)) {
460 free(item); return(TPCERROR_CANNOT_READ);
461 }
462
463 /* Read the tag (2x2 bytes) */
464 if(verbose>10) {
465 long long int tagpos=ftello(dcm->fp);
466 printf(" reading tag at %lld\n", tagpos);
467 }
468 if(dcmReadFileTag(dcm->fp, &item->tag)) {
469 if(verbose>1 && !feof(dcm->fp)) printf(" error in reading the tag.\n");
470 free(item);
471 if(feof(dcm->fp)) return(TPCERROR_NO_KEY);
472 return(TPCERROR_CANNOT_READ);
473 }
474
475 if(verbose>2) {
476 printf(" tag(%04x,%04x) with %u parents\n",
477 item->tag.group, item->tag.element, dcmitemParentNr(item));
478 }
479
480 /* If child, then check for item delimitation tag (although it should not be here) */
481 if(dcmitemParentNr(item)>0 && item->tag.group==0xFFFE && item->tag.element==0xE00D) {
482 if(verbose>10)
483 printf(" item delimitation tag(%04x,%04x) found, reading VL\n",
484 item->tag.group, item->tag.element);
485 unsigned long int vl=dcmReadFileVL(dcm->fp, 4);
486 if(verbose>1) printf(" item delimitation tag VL := %lu (0x%08lx)\n", vl, vl);
487 if(vl!=0) {
488 if(verbose>1) printf(" error: VL should have been 0\n");
490 }
491 return(TPCERROR_OK);
492 }
493
494
495 /* Read value representation and length (VR and VL, 2x2 or 2x4 bytes) */
496 if(item->tag.group==0x0002 || dcm->truid==DCM_TRUID_LEE) {
497 // Group 0x0002 is always DCM_TRUID_LEE, the other groups are specified by
498 // the Transfer Syntax UID
499 if(verbose>10) printf(" reading VR and VL\n");
500 int ret;
501 unsigned int n;
502 ret=dcmReadFileVRVL(dcm->fp, &item->vr, &item->vl, &n);
503 if(ret!=TPCERROR_OK) {
504 if(verbose>1) printf(" invalid VR or VL\n");
505 free(item); return(ret);
506 }
507 if(verbose>1) {
508 printf(" VR := %s (%s)\n", dcmVRName(item->vr), dcmVRDescr(item->vr));
509 printf(" VL := %u (0x%08x) (%d bytes field)\n", item->vl, item->vl, n/2);
510 fflush(stdout);
511 }
512 } else if(dcm->truid==DCM_TRUID_LEI) {
513 if(verbose>10) printf(" set VR based on the tag\n");
514 unsigned int i=dcmDictFindTag(&item->tag);
515 item->vr=dcmVRId(dcmDictIndexVR(i));
516 if(item->vr!=DCM_VR_INVALID) {
517 if(verbose>1) {
518 printf(" VR := %s (%s)\n", dcmVRName(item->vr), dcmVRDescr(item->vr));
519 fflush(stdout);
520 }
521 } else {
522 if(verbose>1) printf(" VR not known for tag(%04x,%04x)\n",
523 item->tag.group, item->tag.element);
524 }
525 if(verbose>10) printf(" reading VL\n");
526 item->vl=dcmReadFileVL(dcm->fp, 4);
527 if(verbose>1) {
528 printf(" VL := %u (0x%08x)\n", item->vl, item->vl);
529 fflush(stdout);
530 }
531 }
532
533 /* Read value field, and add the current element to the list */
534 if(item->vr==DCM_VR_SQ) {
535 if(ftello(dcm->fp)<0) return(TPCERROR_INVALID_FORMAT);
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);
540 /* File position is now at the start of first item in the sequence */
541 int ret;
542 /* If parent has no previous child, then define this as its child */
543 if(sq_child!=0 && parent_item->child_item==NULL) {
544 parent_item->child_item=item;
545 } else {
546 /* else, add SQ sequence itself as next element to the list, and later
547 add each sequence item as child to it */
548 if(prev_item==NULL) {
549 if(dcm->item==NULL) { // truly the first item
550 dcm->item=item;
551 } else { // search for the previous one
552 DCMITEM *ip; ip=dcm->item;
553 while(ip->next_item!=NULL) ip=ip->next_item;
554 ip->next_item=item; item->prev_item=ip;
555 }
556 } else {
557 prev_item->next_item=item; item->prev_item=prev_item;
558 }
559 }
560 /* Read the first item tag and length, but there is no VR to read this time */
561 if(verbose>10) {
562 long long int tagpos=ftello(dcm->fp);
563 printf(" reading first item tag at %lld\n", tagpos);
564 }
565 DCMTAG itemtag;
566 ret=dcmReadFileTag(dcm->fp, &itemtag);
567 if(ret!=0) {
568 if(verbose>1) printf(" error %d in reading the tag.\n", ret);
569 return(TPCERROR_CANNOT_READ);
570 }
571 if(verbose>1) printf(" item tag(%04x,%04x)\n", itemtag.group, itemtag.element);
572 /* It is common that sequence is empty; check it first */
573 if(itemtag.group==0xFFFE && (itemtag.element==0xE0DD || itemtag.element==0xE00D)) {
574 /* yes; then read also the 4 byte LV, which should be zero */
575 if(verbose>10)
576 printf(" sequence delimitation item tag(%04x,%04x) found, reading VL\n",
577 itemtag.group, itemtag.element);
578 unsigned long int vl=dcmReadFileVL(dcm->fp, 4);
579 if(verbose>1) printf(" item tag VL := %lu (0x%08lx)\n", vl, vl);
580 if(vl!=0) {
581 if(verbose>1) printf(" error: VL should have been 0\n");
583 }
584 if(verbose>3) printf(" ending sequence before it really started.\n");
585 return(TPCERROR_OK);
586 }
587 /* If sequence actually contains something, the Item tag must be 0xFFFE,0xE000 */
588 if(itemtag.group!=0xFFFE || itemtag.element!=0xE000) {
589 if(verbose>1) printf(" invalid sequence item tag(%04x,%04x)\n", itemtag.group, itemtag.element);
590 return(TPCERROR_INVALID_FORMAT); //return(TPCERROR_OK);
591 }
592 /* Read past the VL of this item (always 4 bytes) */
593 unsigned long int itemvl=dcmReadFileVL(dcm->fp, 4);
594 if(verbose>3) {printf(" item_VL := %lu (0x%08lx)\n", itemvl, itemvl);}
595 if(ftello(dcm->fp)<0) return(TPCERROR_INVALID_FORMAT);
596 unsigned long int sqItemPos=(unsigned long int)ftell(dcm->fp);
597 /* Check if that is all of this sequence (probably Siemens) */
598 if((sqItemPos-sqPos)>=sqContentLength) {
599 if(verbose>3) printf(" ending sequence since it was found to be empty.\n");
600 return(TPCERROR_OK);
601 }
602 if(verbose>12) printf(" sequence content start position at %ld\n", sqItemPos);
603 /* Read the first item value as its own element, adding it as child to SQ */
604 ret=dcmFileReadNextElement(dcm, NULL, item, 1, headerOnly, verbose-1);
605 if(ret!=TPCERROR_OK) {
606 if(verbose>1) printf(" error in reading the first item value dataset\n");
607 return(ret);
608 }
609 /* Now we continue reading more items, until we reach Sequence Delimitation Item */
610 while(!feof(dcm->fp)) {
611 /* Do not read pass the length of the sequence data */
612 if(ftello(dcm->fp)<0) return(TPCERROR_INVALID_FORMAT);
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);
616 /* set fake sequence delimitation tag */
617 itemtag.group=0xFFFE; itemtag.element=0xE0DD;
618 break;
619 }
620 if(verbose>10) {
621 long long int tagpos=ftello(dcm->fp);
622 printf(" reading next sequence item tag at %lld, %lld after start\n", tagpos, tagpos-sqItemPos);
623 }
624 if(dcmReadFileTag(dcm->fp, &itemtag)) return(TPCERROR_CANNOT_READ);
625 if(verbose>1) printf(" next item tag(%04x,%04x)\n", itemtag.group, itemtag.element);
626 itemvl=dcmReadFileVL(dcm->fp, 4); // delimitation tag has this too
627 if(verbose>3) {printf(" item_VL := %lu (0x%08lx)\n", itemvl, itemvl);}
628 /* Check if we got sequence delimitation tag */
629 if(itemtag.group==0xFFFE && itemtag.element==0xE0DD)
630 {
631 if(verbose>3) printf(" we got sequence delimitation tag\n");
632 break;
633 }
634 /* Check if we got item delimitation tag from the previous item */
635 if(itemtag.group==0xFFFE && itemtag.element==0xE00D)
636 {
637 if(verbose>3) printf(" we got item delimitation tag\n");
638 if(itemvl!=0) {
639 if(verbose>1) printf(" error: VL should have been 0\n");
641 }
642 continue;
643 }
644 /* Otherwise this should be sequence item tag */
645 if(itemtag.group!=0xFFFE || itemtag.element!=0xE000) {
646 if(verbose>3) printf(" not sequence item tag, move file position back 2x4 bytes\n");
647 fseeko(dcm->fp, -8, SEEK_CUR); //return(TPCERROR_INVALID_VALUE);
648 }
649 /* Read the item value as its own element, adding it to the SQ child list */
650 DCMITEM *child=item->child_item;
651 if(child==NULL) {
652 if(verbose>1) printf(" error had happened in adding the child element\n");
653 return(TPCERROR_UNSUPPORTED);
654 }
655 while(child->next_item!=NULL) child=child->next_item;
656 ret=dcmFileReadNextElement(dcm, child, item, 0, headerOnly, verbose-1);
657 if(ret!=TPCERROR_OK) {
658 if(verbose>1) printf(" error in reading item value dataset\n");
659 return(ret);
660 }
661 }
662 /* Check that loop really stopped at sequence delimitation item */
663 /* 0xE00D means the end of item, 0xE0DD the end of sequence. */
664 if(itemtag.group!=0xFFFE || itemtag.element!=0xE0DD) {
665 if(verbose>1)
666 printf(" invalid sequence delimitation item tag(%04x,%04x)\n", itemtag.group, itemtag.element);
667 return(TPCERROR_UNSUPPORTED);
668 }
669 /* Done. Do not free item! */
670 if(verbose>10) {printf(" end of sequence.\n"); fflush(stdout);} //return(TPCERROR_OK);
671 } else if(item->vl!=0xFFFFFFFF) {
672 if(verbose>10) {printf(" reading value of %u bytes...\n", item->vl); fflush(stdout);}
673 char *buf=NULL;
674 if(item->vl>0) {
675 buf=(char*)calloc(item->vl+1, sizeof(char));
676 if(buf==NULL) {free(item); return(TPCERROR_OUT_OF_MEMORY);}
677 if(fread(buf, 1, item->vl, item->fp)!=item->vl) {
678 free(item); free(buf); return(TPCERROR_NO_VALUE);
679 }
680 /* Do not store pixel data, if that was the request */
681 if(headerOnly!=0 &&
682 ((item->tag.group==0x7FE0 && item->tag.element>0) || item->tag.group==0x7FE1))
683 {
684 if(verbose>5) {printf(" ...not storing pixel data\n"); fflush(stdout);}
685 free(buf); buf=(char*)NULL;
686 } else {
687 item->rd=buf;
688 }
689 } else if(verbose>4) {
690 printf(" VL=0\n");
691 }
692 /* Add to list */
693 if(sub==0) {
694 if(prev_item==NULL) {
695 if(dcm->item==NULL) { // truly the first item
696 dcm->item=item;
697 } else { // search for the previous one
698 DCMITEM *ip; ip=dcm->item;
699 while(ip->next_item!=NULL) ip=ip->next_item;
700 ip->next_item=item; item->prev_item=ip;
701 }
702 } else {
703 prev_item->next_item=item; item->prev_item=prev_item;
704 }
705 } else { // add as child
706 parent_item->child_item=item; item->parent_item=parent_item;
707 }
708 /* Print tag and its value */
709 if(verbose>1) {
710 char *tagval=dcmValueString(item);
711 printf(" (%04x,%04x) %s := %s\n", item->tag.group, item->tag.element,
712 dcmDictIndexDescr(dcmDictFindTag(&item->tag)), tagval);
713 free(tagval);
714 }
715 /* Done. Do no free item or buf! */
716 return(TPCERROR_OK);
717
718 } else { // VL=0xFFFFFFFF
719 size_t s=dcmVRVLength(item->vr);
720 if(s==0) {
721 if(verbose>0) printf(" Unknown VL!!\n");
722 free(item);
723 return(TPCERROR_INVALID_VALUE); //return(TPCERROR_OK);
724 }
725 if(verbose>4) printf(" VR_based_VL=%u\n", (unsigned int)s);
726 char *buf=(char*)calloc(s+1, sizeof(char));
727 if(buf==NULL) {free(item); return(TPCERROR_OUT_OF_MEMORY);}
728 if(fread(buf, 1, s, item->fp)!=s) {
729 free(item); free(buf); return(TPCERROR_NO_VALUE);
730 }
731 item->rd=buf;
732 /* Add to list */
733 if(sub==0) {
734 if(prev_item==NULL) {
735 if(dcm->item==NULL) { // truly the first item
736 dcm->item=item;
737 } else { // search for the previous one
738 DCMITEM *ip; ip=dcm->item;
739 while(ip->next_item!=NULL) ip=ip->next_item;
740 ip->next_item=item; item->prev_item=ip;
741 }
742 } else {
743 prev_item->next_item=item; item->prev_item=prev_item;
744 }
745 } else { // add as child
746 parent_item->child_item=item; item->parent_item=parent_item;
747 }
748 /* Print tag and its value */
749 if(verbose>1) {
750 char *tagval=dcmValueString(item);
751 printf(" (%04x,%04x) %s := %s\n", item->tag.group, item->tag.element,
752 dcmDictIndexDescr(dcmDictFindTag(&item->tag)), tagval);
753 free(tagval);
754 }
755 /* Done. Do no free item or buf! */
756 return(TPCERROR_OK);
757 }
758
759 return(TPCERROR_OK);
760}
unsigned short int dcmitemParentNr(DCMITEM *d)
Definition dcmdata.c:122
char * dcmValueString(DCMITEM *d)
Definition dcmdata.c:141
char * dcmDictIndexVR(unsigned int i)
char * dcmDictIndexDescr(unsigned int i)
unsigned int dcmDictFindTag(DCMTAG *tag)
int dcmReadFileTag(FILE *fp, DCMTAG *tag)
Definition dcmio.c:135
int dcmReadFileVRVL(FILE *fp, dcmvr *vr, unsigned int *vl, unsigned int *n)
Definition dcmio.c:306
unsigned int dcmReadFileVL(FILE *fp, unsigned int n)
Definition dcmio.c:274
size_t dcmVRVLength(dcmvr id)
Definition dcmvr.c:144
dcmvr dcmVRId(const char *s)
Definition dcmvr.c:103
char * dcmVRName(dcmvr id)
Definition dcmvr.c:126
char * dcmVRDescr(dcmvr id)
Definition dcmvr.c:162
DCMITEM * item
Definition tpcdcm.h:164
dcmtruid truid
Definition tpcdcm.h:135
dcmvr vr
Definition tpcdcm.h:139
struct DCMITEM * child_item
Definition tpcdcm.h:143
struct DCMITEM * next_item
Definition tpcdcm.h:147
unsigned int vl
Definition tpcdcm.h:141
FILE * fp
Definition tpcdcm.h:131
fpos_t pos
Definition tpcdcm.h:133
char * rd
Definition tpcdcm.h:152
struct DCMITEM * prev_item
Definition tpcdcm.h:149
struct DCMITEM * parent_item
Definition tpcdcm.h:145
DCMTAG tag
Definition tpcdcm.h:137
unsigned short int element
Definition tpcdcm.h:44
unsigned short int group
Definition tpcdcm.h:42
@ DCM_VR_INVALID
Invalid DICOM value representation.
Definition tpcdcm.h:123
@ DCM_VR_SQ
DICOM sequence of zero or more elements (used for nested data).
Definition tpcdcm.h:112
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_NO_VALUE
Value not found.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_CANNOT_READ
Cannot read file.

Referenced by dcmFileRead(), and dcmFileReadNextElement().

◆ dcmFileWrite()

int dcmFileWrite ( const char * filename,
DCMFILE * dcm,
TPCSTATUS * status )

Write a single DICOM file.

See also
dcmFileRead, dcmfileInit, dcmfileFree, dcmFileRemove
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Parameters
filenamePointer to file name.
dcmPointer to DICOM data to be written.
statusPointer to status data; enter NULL if not needed.

Definition at line 852 of file dcmio.c.

859 {
860 int verbose=0; if(status!=NULL) verbose=status->verbose;
861 if(filename==NULL || strnlen(filename, 10)<1 || dcm==NULL) {
862 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
863 return TPCERROR_FAIL;
864 }
865 if(verbose>1) {printf("%s('%s')\n", __func__, filename); fflush(stdout);}
866
867 /* Check for the data */
868 if(dcm->item==NULL) {
869 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
870 return TPCERROR_NO_DATA;
871 }
872
873 /* Check whether we currently support the Transfer UID */
874 if(dcm->truid!=DCM_TRUID_LEE) { // Little endian explicit
875 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
877 }
878
879
880 /* Open the file */
881 if(verbose>1) printf("opening the file for writing\n");
882 FILE *fp;
883 fp=fopen(filename, "wb");
884 if(fp==NULL) {
885 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
887 }
888
889 /* Write preamble (just 128 zeroes) and magic number */
890 {
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) {
896 fclose(fp); statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
898 }
899 }
900
901
902 /* Write the contents */
903 if(verbose>1) printf("writing DICOM contents\n");
904 int ret=0;
905 DCMITEM *iptr;
906 DCMITEM *d1=dcm->item;
907 while(d1!=NULL) {
908 if(verbose>2) {dcmitemPrint(d1);}
909 /* Write */
910 iptr=d1;
911 {
912 size_t n;
913 /* Write tag */
914 if(dcmWriteFileTag(fp, &iptr->tag)!=TPCERROR_OK) {ret=1; break;}
915 /* Write VR and VL */
916 if(dcmWriteFileVRVL(fp, iptr->vr, iptr->vl, NULL)!=TPCERROR_OK) {ret=2; break;}
917 /* Write value, unless zero length, or SQ, in which case written later */
918 if(iptr->vl>0 && iptr->vr!=DCM_VR_SQ) {
919 size_t len;
920 if(iptr->vl==0xFFFFFFFF) {
921 len=dcmVRVLength(iptr->vr);
922 if(verbose>30) printf(" value_len1 := %u\n", (unsigned int)len);
923 n=fwrite(iptr->rd, dcmVRVLength(iptr->vr), 1, fp);
924 } else {
925 len=iptr->vl;
926 if(verbose>30) printf(" value_len3 := %u\n", (unsigned int)len);
927 n=fwrite(iptr->rd, iptr->vl, 1, fp);
928 }
929 if(verbose>30) printf(" value_len := %u\n", (unsigned int)len);
930 if(n!=1) {ret=4; break;}
931 } else if(iptr->vr==DCM_VR_SQ && d1->child_item==NULL) {
932 if(verbose>1) printf("SQ, but no contents to write!\n");
933 /* Write Sequence Delimitation Item */
934 if(dcmWriteFileSQDelimItem(fp)!=TPCERROR_OK) {ret=6; break;}
935 }
936 }
937
938 /* If this element (SQ) has children, then write those */
939 /* Data Elements with a group of 0000, 0002 and 0006 shall not be present within Sequence Items,
940 but that is not verified here */
941 if(d1->child_item!=NULL) {
942 DCMITEM *d2=d1->child_item;
943 unsigned int d2counter=0;
944 while(d2!=NULL) {
945 if(verbose>2) {printf(" "); dcmitemPrint(d2);}
946
947 /* Write */
948 iptr=d2;
949
950 /* First, write Item tag (FFFE,E000) */
951 if(d2counter==0) {
952 DCMTAG tag; tag.group=0xFFFE; tag.element=0xE000;
953 if(dcmWriteFileTag(fp, &tag)!=TPCERROR_OK) {ret=11; break;}
954 }
955 /* Write item length; write 0xFFFFFFFF for now, correct later when known */
956 fpos_t d2ilpos; // position for item length
957 unsigned int d2il=0; // item length
958 if(d2counter==0) {
959 if(fgetpos(fp, &d2ilpos)) {ret=12; break;} // save position for writing later
960 unsigned int ibuf;
961 ibuf=0xFFFFFFFF;
962 if(fwrite(&ibuf, 4, 1, fp)!=1) {ret=13; break;}
963 }
964 d2counter++;
965
966 /* Write item value data set */
967 {
968 /* Write tag */
969 if(dcmWriteFileTag(fp, &iptr->tag)!=TPCERROR_OK) {ret=14; break;}
970 d2il+=4;
971 /* Write VR and VL */
972 unsigned int s;
973 if(dcmWriteFileVRVL(fp, iptr->vr, iptr->vl, &s)!=TPCERROR_OK) {ret=15; break;}
974 d2il+=s;
975 /* Write value, unless zero length, or SQ, in which case written later */
976 if(iptr->vl>0 && iptr->vr!=DCM_VR_SQ) {
977 size_t len, n;
978 if(iptr->vl==0xFFFFFFFF) {
979 len=dcmVRVLength(iptr->vr);
980 if(verbose>30) printf(" value_len1 := %u\n", (unsigned int)len);
981 n=fwrite(iptr->rd, dcmVRVLength(iptr->vr), 1, fp);
982 d2il+=len;
983 } else {
984 len=iptr->vl;
985 if(verbose>30) printf(" value_len3 := %u\n", (unsigned int)len);
986 n=fwrite(iptr->rd, iptr->vl, 1, fp);
987 d2il+=iptr->vl;
988 }
989 if(verbose>30) printf(" value_len := %u\n", (unsigned int)len);
990 if(n!=1) {ret=17; break;}
991 } else if(iptr->vr==DCM_VR_SQ && iptr->child_item==NULL) {
992 if(verbose>1) printf("SQ, but no contents to write!\n");
993 /* Write Sequence Delimitation Item */
994 if(dcmWriteFileSQDelimItem(fp)!=TPCERROR_OK) {ret=19; break;}
995 }
996 }
997
998 /* If this element has children, then write those */
999 if(d2->child_item!=NULL) {
1000 DCMITEM *d3=d2->child_item;
1001 unsigned int d3counter=0;
1002 while(d3!=NULL) {
1003 if(verbose>2) {printf(" "); dcmitemPrint(d3);}
1004
1005 /* Write */
1006 iptr=d3;
1007 if(iptr->vr==DCM_VR_SQ) {d3=d3->next_item; continue;} // for now do not write SQs
1008
1009 /* First, write Item tag (FFFE,E000) */
1010 if(d3counter==0) {
1011 DCMTAG tag; tag.group=0xFFFE; tag.element=0xE000;
1012 if(dcmWriteFileTag(fp, &tag)!=TPCERROR_OK) {ret=31; break;}
1013 d2il+=4;
1014 }
1015 /* Write item length; write 0xFFFFFFFF for now, correct later when known */
1016 fpos_t d3ilpos; // position for item length
1017 unsigned int d3il=0; // item length
1018 if(d3counter==0) {
1019 unsigned int ibuf;
1020 if(fgetpos(fp, &d3ilpos)) {ret=32; break;} // save position for writing later
1021 ibuf=0xFFFFFFFF;
1022 if(fwrite(&ibuf, 4, 1, fp)!=1) {ret=33; break;}
1023 d2il+=4;
1024 }
1025 d3counter++;
1026
1027 /* Write item value data set */
1028 {
1029 /* Write tag */
1030 if(dcmWriteFileTag(fp, &iptr->tag)!=TPCERROR_OK) {ret=34; break;}
1031 d3il+=4; d2il+=4;
1032 /* Write VR and VL */
1033 unsigned int s;
1034 if(dcmWriteFileVRVL(fp, iptr->vr, iptr->vl, &s)!=TPCERROR_OK) {ret=35; break;}
1035 d3il+=s; d2il+=s;
1036 /* Write value, unless zero length, or SQ, in which case written later */
1037 if(iptr->vl>0 && iptr->vr!=DCM_VR_SQ) {
1038 size_t len, n;
1039 if(iptr->vl==0xFFFFFFFF) {
1040 len=dcmVRVLength(iptr->vr);
1041 if(verbose>30) printf(" value_len1 := %u\n", (unsigned int)len);
1042 n=fwrite(iptr->rd, dcmVRVLength(iptr->vr), 1, fp);
1043 d3il+=len; d2il+=len;
1044 } else {
1045 len=iptr->vl;
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;
1049 }
1050 if(verbose>30) printf(" value_len := %u\n", (unsigned int)len);
1051 if(n!=1) {ret=37; break;}
1052 } else if(iptr->vr==DCM_VR_SQ && iptr->child_item==NULL) {
1053 if(verbose>1) printf("SQ, but no contents to write!\n");
1054 /* Write Sequence Delimitation Item */
1055 if(dcmWriteFileSQDelimItem(fp)!=TPCERROR_OK) {ret=39; break;}
1056 d2il+=8;
1057 }
1058 }
1059
1060 /* If this element has children, then write those */
1061 if(d3->child_item!=NULL) {
1062 //DCMITEM *d4=d3->child_item;
1063 if(verbose>0) fprintf(stderr, "Warning: 4th level items not written.\n");
1064 }
1065
1066 /* now that we known the length, write it to the saved position */
1067 if(0) {
1068 fpos_t opos; // current position to return to
1069 if(fgetpos(fp, &opos)) {ret=40; break;}
1070 fsetpos(fp, &d3ilpos); // go to the position for item length
1071 char buf[4];
1072 memcpy(buf, &d3il, 4);
1073 if(!endianLittle()) swabip(buf, 4);
1074 if(fwrite(&buf, 4, 1, fp)!=1) {ret=41; break;}
1075 fsetpos(fp, &opos); // back to the position where we were
1076 }
1077
1078 d3=d3->next_item;
1079 }
1080 if(ret!=0) break;
1081
1082 /* Write Item Delimitation Tag */
1083 if(dcmWriteFileSQItemDelimTag(fp)!=0) {ret=21; break;}
1084 /* End of the sequence - write Sequence Delimitation Item */
1085 if(dcmWriteFileSQDelimItem(fp)!=TPCERROR_OK) {ret=21; break;}
1086
1087 }
1088
1089
1090 /* now that we known the length, write it to the saved position */
1091 if(0) {
1092 fpos_t opos; // current position to return to
1093 if(fgetpos(fp, &opos)) {ret=18; break;}
1094 fsetpos(fp, &d2ilpos); // go to the position for item length
1095 char buf[4];
1096 memcpy(buf, &d2il, 4);
1097 if(!endianLittle()) swabip(buf, 4);
1098 if(fwrite(&buf, 4, 1, fp)!=1) {ret=19; break;}
1099 fsetpos(fp, &opos); // back to the position where we were
1100 }
1101
1102 d2=d2->next_item;
1103 }
1104 if(ret!=0) break;
1105
1106 /* Write Item Delimitation Tag */
1107 if(dcmWriteFileSQItemDelimTag(fp)!=0) {ret=21; break;}
1108 /* End of the sequence - write Sequence Delimitation Item */
1109 if(dcmWriteFileSQDelimItem(fp)!=TPCERROR_OK) {ret=21; break;}
1110
1111 }
1112
1113 d1=d1->next_item;
1114 } // next
1115 if(ret!=0) {
1116 if(verbose>0) fprintf(stderr, " ret := %d\n", ret);
1117 fclose(fp);
1118 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
1119 return TPCERROR_CANNOT_WRITE;
1120 }
1121
1122
1123 fclose(fp);
1124
1125 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
1126 return(TPCERROR_OK);
1127}
void dcmitemPrint(DCMITEM *d)
Definition dcmdata.c:467
int dcmWriteFileVRVL(FILE *fp, dcmvr vr, unsigned int vl, unsigned int *n)
Definition dcmio.c:366
int dcmWriteFileSQItemDelimTag(FILE *fp)
Definition dcmio.c:216
int dcmWriteFileTag(FILE *fp, DCMTAG *tag)
Definition dcmio.c:165
int dcmWriteFileSQDelimItem(FILE *fp)
Definition dcmio.c:191
void swabip(void *buf, int size)
Definition endian.c:115
int endianLittle()
Definition endian.c:53
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_CANNOT_WRITE
Cannot write file.

Referenced by imgWriteDICOM().

◆ dcmReadFileTag()

int dcmReadFileTag ( FILE * fp,
DCMTAG * tag )

Read DICOM tag from current file position.

Note
Tag validity is not verified here; error may be caused by end-of-file. Alternatively, read may seem to be successful, but tag contents are file padding symbols (0xFFFC).
See also
dcmReadFile, dcmReadFileElement
Returns
Returns 0 when successful, otherwise >0.
Author
Vesa Oikonen
Parameters
fpFile pointer, positioned at the start of the element (and tag).
tagPointer to DICOM tag struct; enter NULL if you just need to move file position over the tag.

Definition at line 135 of file dcmio.c.

141 {
142 if(tag!=NULL) {tag->group=tag->element=0xFFFC;} // padding
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);
147 if(tag!=NULL) {
148 tag->group=buf[0];
149 tag->element=buf[1];
150 if(!endianLittle()) { // tag is by default little endian
151 swap(&tag->group, &tag->group, 2);
152 swap(&tag->element, &tag->element, 2);
153 }
154 }
155 return(0);
156}
void swap(void *from, void *to, int size)
Definition endian.c:69

Referenced by dcmFileReadNextElement(), and dcmReadTransferSyntaxUID().

◆ dcmReadFileVL()

unsigned int dcmReadFileVL ( FILE * fp,
unsigned int n )

Read DICOM value length (2 or 4 bytes, depending on VR) from current file position.

See also
dcmReadFileTag, dcmReadFileVR, dcmReadFileElement
Returns
Returns the value length.
Author
Vesa Oikonen
Parameters
fpFile pointer, positioned at the VL start.
nNumber of bytes (2 or 4) in the VL representation.

Definition at line 274 of file dcmio.c.

279 {
280 unsigned int vl=0;
281 if(fp==NULL || (n!=2 && n!=4)) return(vl);
282
283 /* Read 2 or 4 bytes */
284 if(n==2) {
285 unsigned short int si;
286 if(fread(&si, 2, 1, fp)!=1) return(vl);
287 if(!endianLittle()) swap(&si, &si, 2);
288 vl=si;
289 } else if(n==4) {
290 unsigned int li;
291 if(fread(&li, 4, 1, fp)!=1) return(vl);
292 if(!endianLittle()) swap(&li, &li, 4);
293 vl=li;
294 }
295 return(vl);
296}

Referenced by dcmFileReadNextElement(), and dcmReadTransferSyntaxUID().

◆ dcmReadFileVR()

dcmvr dcmReadFileVR ( FILE * fp,
char * vrstr )

Read DICOM value representation (2 or 4 bytes) from current file position.

See also
dcmReadFileTag, dcmReadFileElement
Returns
Returns the enumerated VR number, DCM_VR_INVALID in case of an error.
Author
Vesa Oikonen
Parameters
fpFile pointer, positioned at the VR start.
vrstrPointer for VR string, allocated for at least 3 characters to have space for the trailing null; enter NULL if not needed.

Definition at line 237 of file dcmio.c.

243 {
244 if(vrstr!=NULL) vrstr[0]=(char)0;
245 if(fp==NULL) return(DCM_VR_INVALID);
246
247 /* Read the first two bytes */
248 char buf[3];
249 if(fread(&buf, 1, 2, fp)!=2) return(DCM_VR_INVALID);
250 buf[2]=(char)0;
251
252 /* Identify the VR */
253 dcmvr lvr=dcmVRId(buf);
254 if(vrstr!=NULL) {
255 if(lvr!=DCM_VR_INVALID) strcpy(vrstr, dcmVRName(lvr));
256 else strcpy(vrstr, buf);
257 }
258
259 /* If this VR has extra 2 byte reserved space, then
260 we need to read but do not use the next 2 bytes. */
261 if(dcmVRReserved(lvr)!=0) {
262 if(fread(&buf, 1, 2, fp)!=2) return(DCM_VR_INVALID);
263 }
264 return(lvr);
265}
unsigned char dcmVRReserved(dcmvr id)
Definition dcmvr.c:85
dcmvr
Definition tpcdcm.h:91

Referenced by dcmReadTransferSyntaxUID().

◆ dcmReadFileVRVL()

int dcmReadFileVRVL ( FILE * fp,
dcmvr * vr,
unsigned int * vl,
unsigned int * n )

Read DICOM Value Representation (VR, 2 or 4 bytes) and Value Length (VL, 2 or 4 bytes) from current file position.

See also
dcmReadFileVR, dcmReadFileVL, dcmReadFileTag, dcmReadFileElement, dcmWriteFileVRVL
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Author
Vesa Oikonen
Parameters
fpFile pointer, positioned at the VR start.
vrPointer for enumerated VR value; enter NULL if not needed (file pointer moved anyway).
vlPointer for VL; enter NULL if not needed (file pointer moved anyway).
nPointer for number of bytes read from file; enter NULL if not needed.

Definition at line 306 of file dcmio.c.

315 {
316 if(vr!=NULL) *vr=DCM_VR_INVALID;
317 if(vl!=NULL) *vl=0;
318 if(n!=NULL) *n=0;
319 if(fp==NULL) return(TPCERROR_FAIL);
320
321 /* Read the first two bytes */
322 char buf[3];
323 if(fread(&buf, 1, 2, fp)!=2) return(TPCERROR_CANNOT_READ); else if(n!=NULL) *n+=2;
324 buf[2]=(char)0;
325
326 /* Identify the VR */
327 dcmvr lvr=dcmVRId(buf);
328 if(vr!=NULL) *vr=lvr;
329 if(lvr==DCM_VR_INVALID) return(TPCERROR_UNSUPPORTED);
330
331 /* If this VR has extra 2 byte reserved space, then
332 we need to read but do not use the next 2 bytes. */
333 unsigned int bsize=2+dcmVRReserved(lvr);
334 if(bsize==4) {
335 if(fread(&buf, 1, 2, fp)!=2) return(TPCERROR_CANNOT_READ);
336 if(n!=NULL) *n+=2;
337 }
338
339 /* Read VL from the next 2 or 4 bytes */
340 unsigned int lvl=0;
341 if(bsize==2) {
342 unsigned short int si;
343 if(fread(&si, 2, 1, fp)!=1) return(TPCERROR_CANNOT_READ);
344 if(!endianLittle()) swap(&si, &si, 2);
345 lvl=si;
346 } else {
347 unsigned int li;
348 if(fread(&li, 4, 1, fp)!=1) return(TPCERROR_CANNOT_READ);
349 if(!endianLittle()) swap(&li, &li, 4);
350 lvl=li;
351 }
352 if(n!=NULL) *n+=bsize;
353 if(vl!=NULL) *vl=lvl;
354
355 return(TPCERROR_OK);
356}

Referenced by dcmFileReadNextElement().

◆ dcmReadTransferSyntaxUID()

dcmtruid dcmReadTransferSyntaxUID ( FILE * fp)

Read and identify the DICOM Transfer Syntax UID.

Returns
Returns the enumerated UID, or DCM_TRUID_INVALID.
See also
dcmVerifyMagic
Parameters
fpPointer to DICOM file opened in binary format, and positioned right after the Magic number. Position will be returned to this position.

Definition at line 73 of file dcmio.c.

78 {
79 if(fp==NULL || feof(fp)) return(DCM_TRUID_INVALID);
80 /* Save original file position */
81 fpos_t opos;
82 if(fgetpos(fp, &opos)) return(DCM_TRUID_INVALID);
83 /* Read file until we find DICOM tag 0x0002,0x0010 */
84 DCMTAG tag;
85 int tag_found=0;
86 while(!tag_found && !feof(fp)) {
87 //printf("reading tag\n");
88 if(dcmReadFileTag(fp, &tag)) break;
89 //printf(" -> (%04x,%04x)\n", tag.group, tag.element);
90 if(tag.group==0x0002 && tag.element==0x0010) {tag_found=1; break;}
91 /* not the tag that we want, so just go through this item */
92 //printf("reading vr etc\n");
93 dcmvr vr=dcmReadFileVR(fp, NULL);
94 //printf("-> %s\n", dcmVRName(vr));
95 unsigned int vl=0;
96 if(dcmVRReserved(vr)==0) vl=dcmReadFileVL(fp, 2);
97 else vl=dcmReadFileVL(fp, 4);
98 //printf("reserved=%d\n", dcmVRReserved(vr));
99 if(vr==DCM_VR_SQ) break;
100 //printf("huuh\n");
101 if(vl==0xFFFFFFFF) break;
102 char buf[vl+1];
103 //printf("read buf length %d\n", vl);
104 if(fread(buf, 1, vl, fp)!=vl) break;
105 } // get next tag
106 //printf("end of loop\n");
107 if(!tag_found) {fsetpos(fp, &opos); return(DCM_TRUID_INVALID);}
108 /* Read the UID */
109 //printf("reading vr\n");
110 if(dcmReadFileVR(fp, NULL)!=DCM_VR_UI) {
111 fsetpos(fp, &opos); return(DCM_TRUID_INVALID);
112 }
113 //printf("reading vl\n");
114 unsigned int vl=dcmReadFileVL(fp, 2);
115 if(vl==0 || vl==0xFFFFFFFF) {fsetpos(fp, &opos); return(DCM_TRUID_INVALID);}
116 char uid[vl+1];
117 //printf("reading uid\n");
118 if(fread(uid, 1, vl, fp)!=vl) {fsetpos(fp, &opos); return(DCM_TRUID_INVALID);}
119 /* Return file position to the original */
120 fsetpos(fp, &opos);
121 /* Identify the UID */
122 return(dcmTrUID(uid));
123}
dcmvr dcmReadFileVR(FILE *fp, char *vrstr)
Definition dcmio.c:237
dcmtruid dcmTrUID(const char *s)
Definition dcmuid.c:66
@ DCM_VR_UI
DICOM unique identifier (UID), max 64 bytes.
Definition tpcdcm.h:117

Referenced by dcmFileRead().

◆ dcmVerifyMagic()

int dcmVerifyMagic ( const char * filename,
FILE * fp )

Verify that given file (either file name or file pointer) appears to be DICOM file, based on the magic number.

See also
dcmReadFile, dcmReadTransferSyntaxUID
Returns
Returns 1 if DICOM magic number can be found, or 0 if not.
Author
Vesa Oikonen
Parameters
filenameName of file to open and to verify for the magic number; enter NULL to use the file pointer (next argument) instead.
fpFile pointer of file to check, opened with fp=fopen(filename, "rb"); enter NULL to open file (previous argument) locally. Previously opened file pointer is first rewound to start; if DICOM magic number is found, then file pointer is left to the end of magic number, and if not, it is rewound to the file start.

Definition at line 25 of file dcmio.c.

36 {
37 FILE *lfp;
38
39 if(filename==NULL && fp==NULL) return(0);
40 if(fp!=NULL) {
41 lfp=fp; rewind(lfp);
42 } else {
43 lfp=fopen(filename, "rb");
44 }
45 if(lfp==NULL) return(0);
46
47 /* Skip the first 128 bytes */
48 if(fseek(lfp, 128, SEEK_SET)) {if(fp==NULL) fclose(lfp); return(0);}
49
50 /* Read the next 4 bytes as characters */
51 char buf[5];
52 size_t n=fread(&buf, 1, 4, lfp);
53 buf[4]=(char)0;
54 //if(fp==NULL) fclose(lfp); else rewind(lfp);
55 if(n!=(size_t)4) {rewind(lfp); return(0);}
56
57 /* Check the magic number */
58 if(strncmp(buf, "DICM", 4)==0) {
59 if(fp==NULL) fclose(lfp);
60 return(1);
61 } else {
62 if(fp==NULL) fclose(lfp); else rewind(lfp);
63 return(0);
64 }
65}

Referenced by dcmFileList(), dcmFileRead(), and imgRead().

◆ dcmWriteFileSQDelimItem()

int dcmWriteFileSQDelimItem ( FILE * fp)

Write DICOM Sequence delimitation item into current file position.

This item consists of four byte sequence delimitation tag (0xFFFE, 0xE0DD) and four byte item length (0x00000000), i.e. together 8 bytes.

See also
dcmWriteFileTag, dcmReadFileTag, dcmWriteFileSQItemDelimTag
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Author
Vesa Oikonen
Parameters
fpFile pointer, at the write position.

Definition at line 191 of file dcmio.c.

194 {
195 if(fp==NULL) return(TPCERROR_FAIL);
196 int ret;
197 DCMTAG tag;
198 tag.group=0xFFFE; tag.element=0xE0DD;
199 ret=dcmWriteFileTag(fp, &tag); if(ret!=TPCERROR_OK) return(ret);
200 tag.group=0x0000; tag.element=0x0000;
201 ret=dcmWriteFileTag(fp, &tag); if(ret!=TPCERROR_OK) return(ret);
202 return(TPCERROR_OK);
203}

Referenced by dcmFileWrite().

◆ dcmWriteFileSQItemDelimTag()

int dcmWriteFileSQItemDelimTag ( FILE * fp)

Write DICOM Sequence Item Delimitation Tag with VL into current file position.

This tag consists of four bytes, sequence item delimitation tag (0xFFFE, 0xE00D), followed by four byte item length (0x00000000), i.e. together 8 bytes.

See also
dcmWriteFileTag, dcmReadFileTag, dcmWriteFileSQDelimItem
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Author
Vesa Oikonen
Parameters
fpFile pointer, at the write position.

Definition at line 216 of file dcmio.c.

219 {
220 if(fp==NULL) return(TPCERROR_FAIL);
221 int ret;
222 DCMTAG tag;
223 tag.group=0xFFFE; tag.element=0xE00D;
224 ret=dcmWriteFileTag(fp, &tag); if(ret!=TPCERROR_OK) return(ret);
225 tag.group=0x0000; tag.element=0x0000;
226 ret=dcmWriteFileTag(fp, &tag); if(ret!=TPCERROR_OK) return(ret);
227 return(TPCERROR_OK);
228}

Referenced by dcmFileWrite().

◆ dcmWriteFileTag()

int dcmWriteFileTag ( FILE * fp,
DCMTAG * tag )

Write DICOM tag into current file position.

See also
dcmWriteFile, dcmReadFileTag
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Author
Vesa Oikonen
Parameters
fpFile pointer, at the write position.
tagPointer to DICOM tag struct to write.

Definition at line 165 of file dcmio.c.

170 {
171 if(fp==NULL || tag==NULL) return(TPCERROR_FAIL);
172 unsigned short int buf[2];
173 buf[0]=tag->group;
174 buf[1]=tag->element;
175 if(!endianLittle()) swabip(buf, 4); // tag is by default little endian
176 if(fwrite(&buf, 2, 2, fp)!=2) return TPCERROR_CANNOT_WRITE;
177 return(TPCERROR_OK);
178}

Referenced by dcmFileWrite(), dcmWriteFileSQDelimItem(), and dcmWriteFileSQItemDelimTag().

◆ dcmWriteFileVRVL()

int dcmWriteFileVRVL ( FILE * fp,
dcmvr vr,
unsigned int vl,
unsigned int * n )

Write DICOM Value Representation (VR, 2 or 4 bytes) and Value Length (VL, 2 or 4 bytes) into current file position.

See also
dcmWriteFileTag, dcmReadFileElement, dcmWriteFileVRVL
Returns
Code tpcerror, TPCERROR_OK (0) when successful.
Author
Vesa Oikonen
Parameters
fpFile pointer, opened fro writing in binary mode.
vrEnumerated VR value.
vlVL
nPointer for number of bytes written into file; enter NULL if not needed.

Definition at line 366 of file dcmio.c.

375 {
376 if(n!=NULL) *n=0;
377 if(fp==NULL || vr==DCM_VR_INVALID) return(TPCERROR_FAIL);
378
379 /* If this VR has extra 2 byte reserved space, then
380 we need to write VR and VL with 4 bytes each, other wise with 2 bytes each. */
381 unsigned int bsize=2+dcmVRReserved(vr);
382
383 char buf[10];
384
385 /* Write VR */
386 memcpy(buf, dcmVRName(vr), 2); buf[2]=buf[3]=(char)0;
387 if(fwrite(buf, bsize, 1, fp)!=1) return(TPCERROR_CANNOT_WRITE);
388 if(n!=NULL) *n+=bsize;
389
390 /* Write VL */
391 memcpy(buf, &vl, bsize);
392 if(bsize==2) buf[2]=buf[3]=(char)0;
393// if(!endianLittle()) swabip(buf, bsize);
394 if(!endianLittle()) swap(buf, buf, bsize);
395 if(fwrite(buf, bsize, 1, fp)!=1) return(TPCERROR_CANNOT_WRITE);
396 if(n!=NULL) *n+=bsize;
397
398 return(TPCERROR_OK);
399}

Referenced by dcmFileWrite().