Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
dcmpschk.cxx
Package: dcmtk-3.5.3.zip [view]
Upload User: jinxing
Upload Date: 2016-11-26
Package Size: 5101k
Code Size: 37k
Category:
Picture Viewer
Development Platform:
Visual C++
- /*
- *
- * Copyright (C) 2000-2004, OFFIS
- *
- * This software and supporting documentation were developed by
- *
- * Kuratorium OFFIS e.V.
- * Healthcare Information and Communication Systems
- * Escherweg 2
- * D-26121 Oldenburg, Germany
- *
- * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
- * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
- * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
- * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
- * PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
- *
- * Module: dcmpstat
- *
- * Author: Andrew Hewett/Marco Eichelberg
- *
- * Purpose:
- * VR and IOD checker for Presentation States
- *
- *
- * Last Update: $Author: joergr $
- * Update Date: $Date: 2004/02/04 15:44:38 $
- * CVS/RCS Revision: $Revision: 1.16 $
- * Status: $State: Exp $
- *
- * CVS/RCS Log at end of file
- *
- */
- #include "osconfig.h" /* make sure OS specific configuration is included first */
- #define INCLUDE_CSTDLIB
- #include "ofstdinc.h"
- #ifdef HAVE_WINDOWS_H
- #include <windows.h> /* this includes either winsock.h or winsock2.h */
- #endif
- #ifdef HAVE_GUSI_H
- /* needed for Macintosh */
- #include <GUSI.h>
- #include <SIOUX.h>
- #endif
- #include "ofstream.h"
- #include "dctk.h" /* for class DcmDataset */
- #include "ofstring.h" /* for class OFString */
- #include "vrscan.h"
- #include "ofconapp.h" /* for OFConsoleApplication */
- #include "dcmpstat.h" /* for DcmPresentationState */
- #ifdef WITH_ZLIB
- #include <zlib.h> /* for zlibVersion() */
- #endif
- #define OFFIS_CONSOLE_APPLICATION "dcmpschk"
- static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
- OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
- /* command line options */
- static OFBool opt_verbose = OFFalse; /* default: not verbose */
- static const char * opt_logfilename = NULL;
- static const char * opt_filename = NULL;
- static int opt_debugMode = 0;
- static ostream * logstream = &COUT;
- // ********************************************
- enum ErrorMode
- {
- EM_ok,
- EM_informational,
- EM_warning,
- EM_error
- };
- #define MSG_invalidVR "Error: Unsupported Value Representation."
- #define MSG_lengthtoolarge "Error: Value Length too large."
- #define MSG_lengthtoosmall "Error: Value Length too small."
- #define MSG_unexpectedVR "Error: Unexpected Value Representation."
- #define MSG_vmtoolarge "Error: Value Multiplicity too large."
- #define MSG_vmtoosmall "Error: Value Multiplicity too small."
- #define MSGe_mhxferError "Error: Meta-header encoded using invalid transfer syntax."
- #define MSGe_missingAtt "Error: Attribute is missing."
- #define MSGe_wrongAtt "Error: Attribute is incorrect."
- #define MSGe_wrongDType "Error: Attribute value does not conform to data type definition."
- #define MSGi_wrongDType "Informational: Attribute value does not conform to data type definition."
- #define MSGw_wrongDType "Warning: Attribute value uses retired form."
- void printVRError(
- ostream& out,
- ErrorMode mode,
- const char *elementDescription,
- const DcmDictEntry* dictRef,
- const char *format)
- {
- if (mode == EM_error) out << MSGe_wrongDType << endl;
- else if (mode == EM_warning) out << MSGw_wrongDType << endl;
- else if (mode == EM_informational) out << MSGi_wrongDType << endl;
- out << " Affected attribute: ";
- if (dictRef)
- {
- out << dictRef->getTagName();
- out << " " << dictRef->getKey();
- out << ", Type " << dictRef->getVR().getVRName() << endl;
- } else out << "(unnamed)" << endl;
- out << " Attribute value : ";
- if (elementDescription) out << "[" << elementDescription << "]" << endl;
- else out << "(empty)" << endl;
- if (mode == EM_error)
- {
- out << " Expected format for each value: ";
- if (format)
- {
- out << format << endl;
- } else out << "(undefined)" << endl;
- }
- out << endl;
- }
- void printResult(ostream& out, DcmStack& stack, OFBool showFullData)
- {
- unsigned long n = stack.card();
- if (n == 0) {
- return;
- }
- /* print the path leading up to the top stack elem */
- for (unsigned long i=n-1; i>=1; i--)
- {
- DcmObject *dobj = stack.elem(i);
- /* do not print if a DCM_Item as this is not
- * very helpful to distinguish instances.
- */
- if (dobj != NULL && dobj->getTag().getXTag() != DCM_Item)
- {
- char buf[128];
- sprintf(buf, "(%04x,%04x).",
- (unsigned)dobj->getGTag(),
- (unsigned)dobj->getETag());
- out << buf;
- }
- }
- /* print the tag and its value */
- DcmObject *dobj = stack.top();
- dobj->print(out, (showFullData ? 0 : DCMTypes::PF_shortenLongTagValues));
- }
- OFBool isaStringVR(DcmVR& vr)
- {
- OFBool isaString = OFFalse;
- switch(vr.getEVR())
- {
- case EVR_AE:
- case EVR_AS:
- case EVR_CS:
- case EVR_DA:
- case EVR_DS:
- case EVR_DT:
- case EVR_IS:
- case EVR_LO:
- case EVR_LT:
- case EVR_PN:
- case EVR_SH:
- case EVR_ST:
- case EVR_TM:
- case EVR_UI:
- isaString = OFTrue;
- break;
- default:
- isaString = OFFalse;
- break;
- }
- return isaString;
- }
- const char* streamvm(const DcmDictEntry *e)
- {
- static char buf[256];
- if (e->isFixedSingleVM()) {
- sprintf(buf, "%d", e->getVMMax());
- } else if (e->isVariableRangeVM()) {
- sprintf(buf, "%d-n", e->getVMMin());
- } else if (e->isFixedRangeVM()){
- sprintf(buf, "%d-%d", e->getVMMin(), e->getVMMax());
- } else {
- sprintf(buf, "?(%d-%d)?", e->getVMMin(), e->getVMMax());
- }
- return buf;
- }
- const char* streamLengthOfValue(DcmVR& vr)
- {
- static char buf[256];
- Uint32 min = vr.getMinValueLength();
- Uint32 max = vr.getMaxValueLength();
- Uint32 undefLen = DCM_UndefinedLength;
- if (min==max) {
- sprintf(buf, "%d bytes fixed length", (int)min);
- } else if (min==0) {
- if (max==undefLen) {
- sprintf(buf, "unrestricted length");
- } else {
- sprintf(buf, "%d bytes maximum", (int)max);
- }
- } else {
- sprintf(buf, "range %d-%d bytes length", (int)min, (int)max);
- }
- return buf;
- }
- int
- splitFields(char* line, char* fields[], Uint32 maxFields, char splitChar)
- {
- char* p;
- Uint32 foundFields = 0;
- int len;
- do {
- p = strchr(line, splitChar);
- if (p == NULL) {
- len = strlen(line);
- } else {
- len = p - line;
- }
- fields[foundFields] = new char[len+1];
- strncpy(fields[foundFields], line, len);
- fields[foundFields][len] = '';
- foundFields++;
- line = p + 1;
- } while ((foundFields < maxFields) && (p != NULL));
- return foundFields;
- }
- OFBool isaKnownPointer(DcmTag& t)
- {
- /*
- ** The DICOMDIR code automatically converts any pointers
- ** to have VR=up even if when the data has an explicit VR encoding.
- ** If this attribute is a known pointer then it is ok for it to
- ** have the internal VR=up.
- */
- OFBool result = OFFalse;
- const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock();
- const DcmDictEntry *dictRef = globalDataDict.findEntry(t, NULL);
- if (dictRef && (t.getEVR() == EVR_up) && (t.getEVR() == dictRef->getEVR())) result = OFTrue;
- dcmDataDict.unlock();
- return result;
- }
- int scanValue(istream& scannerInput)
- {
- vrscan valueScanner;
- valueScanner.yyin = &scannerInput;
- int firstResult = valueScanner.yylex();
- if (valueScanner.yylex())
- return 16;
- return firstResult;
- }
- int checkelem(ostream & out, DcmElement *elem, DcmXfer& oxfer,
- DcmStack& stack, OFBool showFullData,
- int& dderrors, OFBool /* verbose */)
- {
- DcmVR vr(elem->getVR());
- Uint32 len = elem->getLength();
- DcmTag tag(elem->getTag());
- Uint32 vm = elem->getVM();
- const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock();
- const DcmDictEntry *dictRef = globalDataDict.findEntry(tag, NULL);
- int i = 0;
- /*
- ** if the data was encoded in explicit VR then check that the given VR matches
- ** the value in the data dictionary.
- */
- if (oxfer.isExplicitVR()) {
- if (!vr.isStandard() && !isaKnownPointer(tag)) {
- out << MSG_invalidVR << endl
- << " Affected VR : [" << vr.getVRName() << "]";
- if (dictRef) out << ", should be ["
- << dictRef->getVR().getVRName() << "] according to data dictionary.";
- out << endl << " Affected attribute: ";
- printResult(out, stack, showFullData);
- out << endl;
- dderrors++;
- } else if (dictRef && !vr.isEquivalent(dictRef->getVR())) {
- out << MSG_unexpectedVR << endl
- << " Affected VR : [" << vr.getVRName() << "], should be ["
- << dictRef->getVR().getVRName() << "] according to data dictionary." << endl
- << " Affected attribute: ";
- printResult(out, stack, showFullData);
- out << endl;
- dderrors++;
- }
- }
- if (len) /* type 2 attributes can be empty. */
- {
- /*
- ** Check value multiplicity
- */
- if ((dictRef)&&(vm < (Uint32)dictRef->getVMMin()))
- {
- out << MSG_vmtoosmall << endl
- << " Affected VM : " << vm << ", should be "
- << streamvm(dictRef) << " according to data dictionary."
- << endl << " Affected attribute: ";
- printResult(out, stack, showFullData);
- out << endl;
- dderrors++;
- }
- if ((dictRef)&&(vm > (Uint32)dictRef->getVMMax()))
- {
- out << MSG_vmtoolarge << endl
- << " Affected VM : " << vm << ", should be "
- << streamvm(dictRef) << " according to data dictionary."
- << endl << " Affected attribute: ";
- printResult(out, stack, showFullData);
- out << endl;
- dderrors++;
- }
- /*
- ** Check length of attribute
- */
- /* Need to split the value into its components if VM>1 */
- if (isaStringVR(vr)) {
- /* only strings have variable length components */
- char* value = NULL;
- ((DcmByteString*)elem)->getString(value);
- char **fields = new char*[vm+1];
- if (fields == NULL) {
- printResult(out, stack, showFullData);
- out << "Internal error: out of memory (value multiplicity too large)" << endl;
- } else {
- int nfields = splitFields(value, fields, vm, '\');
- if ((Uint32)nfields != vm) {
- printResult(out, stack, showFullData);
- out << "Internal error: splitFields inconsistency ("
- << nfields << "!=" << vm << ")" << endl;
- exit(1);
- }
- for (i=0; (Uint32)i<vm; i++) {
- char* s = fields[i];
- int slen = strlen(s);
- if ((Uint32)slen > vr.getMaxValueLength()) {
- out << MSG_lengthtoolarge << endl
- << " Affected length : " << slen << " bytes, should be "
- << streamLengthOfValue(vr) << " for " << vr.getVRName() << "." << endl;
- if (vm > 1) out << " Affected value [" << i << "]: "" << s << """ << endl;
- out << " Affected attribute: ";
- printResult(out, stack, showFullData);
- dderrors++;
- out << endl;
- }
- if ((Uint32)slen < vr.getMinValueLength()) {
- out << MSG_lengthtoosmall << endl
- << " Affected length : " << slen << " bytes, should be "
- << streamLengthOfValue(vr) << " for " << vr.getVRName() << "." << endl;
- if (vm > 1) out << " Affected value [" << i << "]: "" << s << """ << endl;
- out << " Affected attribute: ";
- printResult(out, stack, showFullData);
- dderrors++;
- out << endl;
- }
- delete[] fields[i];
- fields[i] = NULL;
- }
- delete[] fields;
- }
- } else {
- Uint32 componentSize = len; /* vm is 0 if value field is too short, e.g. < 8 bytes for FD */
- if (vm>0) componentSize = len/vm;
- if (componentSize > vr.getMaxValueLength()) {
- out << MSG_lengthtoolarge << endl
- << " Affected length : " << componentSize << " bytes, should be "
- << streamLengthOfValue(vr) << " for " << vr.getVRName() << "." << endl
- << " Affected attribute: ";
- printResult(out, stack, showFullData);
- dderrors++;
- out << endl;
- }
- if (componentSize < vr.getMinValueLength()) {
- out << MSG_lengthtoosmall << endl
- << " Affected length : " << componentSize << " bytes, should be "
- << streamLengthOfValue(vr) << " for " << vr.getVRName() << "." << endl
- << " Affected attribute: ";
- printResult(out, stack, showFullData);
- dderrors++;
- out << endl;
- }
- }
- /*
- ** check, wether the value of the element is suitable to the data type.
- */
- /*** differenciate all value representations */
- if (isaStringVR(vr))
- {
- char* value = NULL;
- if (EC_Normal == ((DcmByteString*)elem)->getString(value) && value) switch (vr.getEVR())
- {
- case EVR_AE:
- {
- OFString vrAndValue("ae");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 13)
- {
- printVRError(out, EM_error, value, dictRef, "all but control characters");
- dderrors++;
- }
- }
- break;
- case EVR_AS:
- {
- OFString vrAndValue("as");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 1)
- {
- printVRError(out, EM_error, value, dictRef, "[0-9]{3}[DWMY]");
- dderrors++;
- }
- }
- break;
- case EVR_CS:
- {
- OFString vrAndValue("cs");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 10)
- {
- printVRError(out, EM_error, value, dictRef, "[0-9A-Z _]+");
- dderrors++;
- }
- }
- break;
- case EVR_DA:
- {
- OFString vrAndValue("da");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 2 )
- {
- if (realVR == 3)
- {
- printVRError(out, EM_warning, value, dictRef, NULL);
- dderrors++;
- } else {
- printVRError(out, EM_error, value, dictRef, "[0-9]{8} with valid values for year, month and day");
- dderrors++;
- }
- }
- }
- break;
- case EVR_DS:
- {
- OFString vrAndValue("ds");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 6)
- {
- printVRError(out, EM_error, value, dictRef, "([\-\+]?[0-9]*[\.]?[0-9]+)|([\-\+]?[0-9][\.]?[0-9]+[Ee][\+\-][0-9]+)");
- dderrors++;
- }
- }
- break;
- case EVR_DT:
- {
- OFString vrAndValue("dt");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 7)
- {
- printVRError(out, EM_error, value, dictRef, "[0-9]{8}[0-9]{2}([0-9]{2}([0-9]{2}(\.[0-9]{1,6})?)?)?([\+\-][0-9]{4})?");
- dderrors++;
- }
- }
- break;
- case EVR_IS:
- {
- OFString vrAndValue("is");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 8)
- {
- printVRError(out, EM_error, value, dictRef, "[\+\-]?[0-9]+ in the range -2^31 .. 2^31-1");
- dderrors++;
- }
- }
- break;
- case EVR_SH:
- case EVR_LO:
- {
- OFString vrAndValue("lo");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 12)
- {
- printVRError(out, EM_error, value, dictRef, "all but '\' and control characters");
- dderrors++;
- }
- }
- break;
- case EVR_ST:
- case EVR_LT:
- {
- OFString vrAndValue("lt");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 14)
- {
- printVRError(out, EM_error, value, dictRef, "all");
- dderrors++;
- }
- }
- break;
- case EVR_PN:
- {
- OFString vrAndValue("pn");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 11)
- {
- if (realVR == 15) /* OLD_PN */
- {
- printVRError(out, EM_warning, value, dictRef, NULL);
- dderrors++;
- } else {
- printVRError(out, EM_error, value, dictRef, "{all}*([\^]{all}*([\^]{all}*([\^]{all}*(\^{all}*)?)?)?)?");
- dderrors++;
- }
- }
- }
- break;
- case EVR_TM:
- {
- OFString vrAndValue("tm");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 4)
- {
- if (realVR == 5)
- {
- printVRError(out, EM_warning, value, dictRef, NULL);
- dderrors++;
- } else {
- printVRError(out, EM_error, value, dictRef, "[0-9]{2}([0-9]{2}([0-9]{2}(\.[0-9]{1,6})?)?)? with valid values for hour, minute and second");
- dderrors++;
- }
- }
- }
- break;
- case EVR_UI:
- {
- OFString vrAndValue("ui");
- vrAndValue += value;
- OFIStringStream input((char*)(vrAndValue.c_str()));
- int realVR = scanValue(input);
- if (realVR != 9)
- {
- printVRError(out, EM_error, value, dictRef, "([0-9]+\.)*[0-9]+ without any leading zeroes");
- dderrors++;
- }
- }
- break;
- default:
- break;
- }
- } //end of if (isaStringVR(vr))
- }
- dcmDataDict.unlock();
- return 0;
- }
- int checkitem(ostream & out, DcmItem *item, DcmXfer& oxfer,
- DcmStack& stack, OFBool showFullData, int& dderrors, OFBool verbose)
- {
- if (item == NULL) {
- return 0;
- }
- /*
- ** Step through each attribute and check it.
- */
- unsigned long count = item->card();
- for (unsigned long i=0; i<count; i++) {
- DcmElement *elem = item->getElement(i);
- stack.push(elem);
- checkelem(out, elem, oxfer, stack, showFullData, dderrors, verbose);
- stack.pop();
- if (elem->ident() == EVR_SQ) {
- DcmSequenceOfItems *seq = (DcmSequenceOfItems*)elem;
- unsigned long nitems = seq->card();
- for (unsigned long j=0; j<nitems; j++) {
- /* check each item. an item is just another dataset */
- stack.push(seq);
- checkitem(out, seq->getItem(j), oxfer, stack, showFullData, dderrors, verbose);
- stack.pop();
- }
- }
- }
- return 0;
- }
- int dcmchk(
- ostream & out,
- const char* ifname,
- OFBool isDataset,
- E_TransferSyntax xfer,
- OFBool showFullData,
- OFBool loadAllDataInMemory,
- int& dderrors,
- OFBool verbose)
- {
- DcmFileFormat *ds = new DcmFileFormat();
- OFCondition cond = ds->loadFile(ifname, xfer, EGL_noChange, DCM_MaxReadLength, isDataset);
- if (! cond.good())
- {
- out << "Error: " << cond.text() << " reading file: " << ifname << endl;
- }
- if (loadAllDataInMemory) {
- ds->loadAllDataIntoMemory();
- if (ds->error() != EC_Normal)
- {
- out << "Error: " << ds->error().text()
- << " reading file: " << ifname << endl;
- return 1;
- }
- }
- DcmStack stack;
- DcmXfer oxfer(META_HEADER_DEFAULT_TRANSFERSYNTAX);
- DcmMetaInfo *mi = ds->getMetaInfo();
- if (mi->card() > 0)
- {
- // we only check the meta-header if there is something to check
- checkitem(out, mi, oxfer, stack, showFullData, dderrors, verbose);
- }
- oxfer = ds->getDataset()->getOriginalXfer();
- checkitem(out, ds->getDataset(), oxfer, stack, showFullData, dderrors, verbose);
- delete ds;
- return 0;
- }
- //*********************************************************
- static void
- printAttribute(ostream& out, DcmItem* dset,
- const DcmTagKey& key)
- {
- DcmElement *elem = NULL;
- DcmStack stack;
- OFCondition ec = EC_Normal;
- ec = dset->search(key, stack, ESM_fromHere, OFFalse);
- elem = (DcmElement*) stack.top();
- elem->print(out, DCMTypes::PF_shortenLongTagValues);
- }
- static OFBool
- chkType1AttributeExistance(ostream& out, DcmItem* dset,
- const DcmTagKey& key)
- {
- OFBool found = OFTrue;
- if (!dset->tagExistsWithValue(key)) {
- DcmTag t(key);
- out << MSGe_missingAtt << endl
- << " Affected attribute: " << t.getXTag()
- << " " << t.getTagName() << endl;
- out << endl;
- found = OFFalse;
- }
- return found;
- }
- int dcmchkMetaHeader(ostream& out, DcmMetaInfo* meta, DcmDataset* dset)
- {
- if (meta == NULL || meta->card() == 0) {
- /* no meta-header so no errors */
- return 0;
- }
- int nErrs = 0;
- /*
- ** The meta-header should use the LittleEndianExplicit transfer syntax
- */
- if (meta->getOriginalXfer() != EXS_LittleEndianExplicit) {
- DcmXfer used(meta->getOriginalXfer());
- DcmXfer expected(EXS_LittleEndianExplicit);
- out << MSGe_mhxferError << endl
- << " Expected: " << expected.getXferName() << endl
- << " Used: " << used.getXferName() << endl << endl;
- nErrs++;
- }
- /*
- ** Check the meta-header contents
- */
- // examine the FileMetaInformationVersion
- DcmTagKey fmiv(DCM_FileMetaInformationVersion);
- if (chkType1AttributeExistance(out, meta, fmiv)) {
- Uint8 b0 = 0xff;
- Uint8 b1 = 0xff;
- // get bytes
- meta->findAndGetUint8(fmiv, b0, 0);
- meta->findAndGetUint8(fmiv, b1, 1);
- // we expect 0x00/0x01 for the version
- if ((b0 != 0x00) || (b1 != 0x01)) {
- out << MSGe_wrongAtt << endl
- << " Invalid FileMetaInformationVersion (expected: 00\01)"
- << endl << " Affected attribute: " << endl << " ";
- printAttribute(out, meta, fmiv);
- out << endl;
- nErrs++;
- }
- } else {
- nErrs++;
- }
- // examine the MediaStorageSOPClassUID
- DcmTagKey msscuid(DCM_MediaStorageSOPClassUID);
- if (chkType1AttributeExistance(out, meta, msscuid)) {
- OFString metaHeaderClassUID;
- meta->findAndGetOFStringArray(msscuid, metaHeaderClassUID);
- // should be the same as SOPClassUID in the dataset
- if (dset && dset->tagExistsWithValue(DCM_SOPClassUID)) {
- OFString datasetClassUID;
- dset->findAndGetOFStringArray(DCM_SOPClassUID, datasetClassUID);
- if (metaHeaderClassUID != datasetClassUID) {
- out << MSGe_wrongAtt << endl
- << " Inconsistant SOP class information"
- << endl << " Affected attributes: " << endl << " ";
- printAttribute(out, meta, msscuid);
- out << " ";
- printAttribute(out, dset, DCM_SOPClassUID);
- out << endl;
- nErrs++;
- }
- }
- if (!dcmFindNameOfUID(metaHeaderClassUID.c_str())) {
- out << MSGe_wrongAtt << endl
- << " Unknown SOP Class"
- << endl << " Affected attribute: " << endl << " ";
- printAttribute(out, meta, msscuid);
- out << endl;
- nErrs++;
- }
- } else {
- nErrs++;
- }
- // Examine MediaStorageSOPInstanceUID
- DcmTagKey mssiuid(DCM_MediaStorageSOPInstanceUID);
- if (chkType1AttributeExistance(out, meta, mssiuid)) {
- OFString metaHeaderInstanceUID;
- meta->findAndGetOFStringArray(mssiuid, metaHeaderInstanceUID);
- // should be the same as SOPInstanceUID in the dataset
- if (dset && dset->tagExistsWithValue(DCM_SOPInstanceUID)) {
- OFString datasetInstanceUID;
- dset->findAndGetOFStringArray(DCM_SOPInstanceUID, datasetInstanceUID);
- if (metaHeaderInstanceUID != datasetInstanceUID) {
- out << MSGe_wrongAtt << endl
- << " Inconsistant SOP instance information"
- << endl << " Affected attributes: " << endl << " ";
- printAttribute(out, meta, mssiuid);
- out << " ";
- printAttribute(out, dset, DCM_SOPInstanceUID);
- out << endl;
- nErrs++;
- }
- }
- } else {
- nErrs++;
- }
- // examine the TransferSyntaxUID
- DcmTagKey tsuid(DCM_TransferSyntaxUID);
- if (chkType1AttributeExistance(out, meta, tsuid)) {
- OFString transferSyntaxUID;
- meta->findAndGetOFStringArray(tsuid, transferSyntaxUID);
- // is this transfer syntax known ?
- DcmXfer expected(transferSyntaxUID.c_str());
- if (expected.getXfer() == EXS_Unknown) {
- out << MSGe_wrongAtt << endl
- << " Unknown Transfer Syntax"
- << endl << " Affected attribute: " << endl << " ";
- printAttribute(out, meta, tsuid);
- out << endl;
- nErrs++;
- }
- // should be the same as transfer syntax used to read the dataset
- if (dset && (dset->getOriginalXfer() != EXS_LittleEndianExplicit)) {
- DcmXfer used(dset->getOriginalXfer());
- OFString usedTransferSyntaxUID(used.getXferID());
- if (transferSyntaxUID != usedTransferSyntaxUID) {
- out << MSGe_wrongAtt << endl
- << " Dataset not encoded using specified transfer syntax"
- << endl << " Affected attribute: " << endl << " ";
- printAttribute(out, meta, tsuid);
- out << " Dataset encoded using: " << used.getXferName()
- << endl << endl;
- nErrs++;
- }
- }
- } else {
- nErrs++;
- }
- // Check the group length information
- DcmTagKey gltag(DCM_MetaElementGroupLength);
- if (chkType1AttributeExistance(out, meta, gltag)) {
- Uint32 len = 0;
- meta->findAndGetUint32(gltag, len, 0);
- // Compute how large the Meta-Header should be
- Uint32 expectedLength = meta->getLength(EXS_LittleEndianExplicit,
- EET_ExplicitLength);
- expectedLength -= 12; // less length of group length element itself
- if (len != expectedLength) {
- out << MSGe_wrongAtt << endl
- << " Invalid meta-header group length (expected: "
- << expectedLength << ")"
- << endl << " Affected attribute: " << endl << " ";
- printAttribute(out, meta, gltag);
- out << endl;
- nErrs++;
- }
- } else {
- nErrs++;
- }
- return nErrs;
- }
- int checkfile(const char *filename, OFBool verbose, ostream& out, OFConsole *outconsole, OFBool opt_debug)
- {
- DcmFileFormat *dfile = new DcmFileFormat();
- if (dfile == NULL)
- {
- out << "Error: out of memory." << endl;
- return -1;
- }
- OFCondition cond = dfile->loadFile(filename);
- if (! cond.good())
- {
- out << "Error: " << cond.text() << " reading file: " << filename << endl;
- delete dfile;
- return -1;
- }
- int numberOfErrors = 0;
- OFBool test_passed = OFTrue;
- DcmDataset *DataSet = dfile->getDataset();
- DcmMetaInfo *MetaInfo = dfile->getMetaInfo();
- if (verbose)
- {
- out << "=========================================================" << endl;
- }
- out << "Testing: " << filename << endl;
- if (verbose)
- {
- out << "=========================================================" << endl << endl;
- } else out << endl;
- if (MetaInfo)
- {
- if (verbose)
- {
- out << "---------------------------------------------------------" << endl
- << "Pass 1 - Inconsistencies between Meta-header and Data Set" << endl
- << "---------------------------------------------------------" << endl << endl;
- }
- numberOfErrors += dcmchkMetaHeader(out, MetaInfo, DataSet);
- }
- if (verbose)
- {
- out << "-------------------------------------------------------------" << endl
- << "Pass 2 - Inconsistencies between Data Dictionary and Data Set" << endl
- << "-------------------------------------------------------------" << endl << endl;
- }
- dcmchk(out, opt_filename, OFFalse, EXS_Unknown,
- OFFalse /* showFullData */, OFTrue /* loadAllDataInMemory */,
- numberOfErrors, verbose);
- if (verbose)
- {
- out << "-------------------------------------------------------------" << endl
- << "Pass 3 - Semantic Check of Presentation State Object " << endl
- << "-------------------------------------------------------------" << endl << endl;
- }
- DcmUniqueIdentifier sopclassuid(DCM_SOPClassUID);
- DcmStack stack;
- if (EC_Normal == DataSet->search(DCM_SOPClassUID, stack, ESM_fromHere, OFFalse))
- {
- sopclassuid = *((DcmUniqueIdentifier *)(stack.top()));
- }
- OFString aString;
- sopclassuid.getOFString(aString,0);
- if (aString == UID_GrayscaleSoftcopyPresentationStateStorage)
- {
- DcmPresentationState pState;
- pState.setLog(outconsole, OFTrue, opt_debug);
- if (pState.read(*DataSet).bad())
- {
- test_passed = OFFalse;
- out << endl;
- }
- } else {
- if (verbose) out << "Not a Grayscale Softcopy Presentation State, skipping pass 3." << endl <<endl;
- }
- if (numberOfErrors > 0) test_passed = OFFalse;
- if (test_passed) out << "Test passed." << endl << endl;
- else out << "Test failed - one or more errors." << endl << endl;
- if (dfile) delete dfile;
- return numberOfErrors;
- }
- void closeLog()
- {
- ofConsole.setCout();
- ofConsole.split();
- if (logstream != &COUT)
- {
- delete logstream;
- logstream = &COUT;
- }
- }
- #define SHORTCOL 2
- #define LONGCOL 14
- int main(int argc, char *argv[])
- {
- #ifdef HAVE_GUSI_H
- GUSISetup(GUSIwithSIOUXSockets);
- GUSISetup(GUSIwithInternetSockets);
- #endif
- #ifdef HAVE_WINSOCK_H
- WSAData winSockData;
- /* we need at least version 1.1 */
- WORD winSockVersionNeeded = MAKEWORD( 1, 1 );
- WSAStartup(winSockVersionNeeded, &winSockData);
- #endif
- SetDebugLevel((0));
- OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "Checking tool for presentation states", rcsid);
- OFCommandLine cmd;
- cmd.setOptionColumns(LONGCOL, SHORTCOL);
- cmd.setParamColumn(LONGCOL + SHORTCOL + 2);
- cmd.addParam("filename_in", "presentation state file(s) to be checked", OFCmdParam::PM_MultiMandatory);
- cmd.addGroup("general options:");
- cmd.addOption("--help", "-h", "print this help text and exit");
- cmd.addOption("--version", "print version information and exit", OFTrue /* exclusive */);
- cmd.addOption("--verbose", "-v", "verbose mode, print actions");
- cmd.addOption("--debug", "-d", "debug mode, print debug information");
- cmd.addOption("--logfile", "-l", 1, "[f]ilename: string",
- "write output to logfile f");
- /* evaluate command line */
- prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
- if (app.parseCommandLine(cmd, argc, argv, OFCommandLine::ExpandWildcards))
- {
- /* check exclusive options first */
- if (cmd.getParamCount() == 0)
- {
- if (cmd.findOption("--version"))
- {
- app.printHeader(OFTrue /*print host identifier*/); // uses ofConsole.lockCerr()
- CERR << endl << "External libraries used:";
- #ifdef WITH_ZLIB
- CERR << endl << "- ZLIB, Version " << zlibVersion() << endl;
- #else
- CERR << " none" << endl;
- #endif
- return 0;
- }
- }
- /* options */
- if (cmd.findOption("--verbose")) opt_verbose = OFTrue;
- if (cmd.findOption("--debug")) opt_debugMode = 3;
- if (cmd.findOption("--logfile"))
- {
- app.checkValue(cmd.getValue(opt_logfilename));
- }
- }
- SetDebugLevel((opt_debugMode));
- if (opt_logfilename)
- {
- ofstream *newstream = new ofstream(opt_logfilename);
- if (newstream && (newstream->good()))
- {
- logstream=newstream;
- ofConsole.setCout(logstream);
- ofConsole.join();
- }
- else
- {
- delete newstream;
- }
- }
- int paramCount = cmd.getParamCount();
- for (int param=1; param <= paramCount; param++)
- {
- cmd.getParam(param, opt_filename);
- checkfile(opt_filename, opt_verbose, *logstream, &ofConsole, ((opt_debugMode>0) ? OFTrue : OFFalse));
- }
- closeLog();
- #ifdef DEBUG
- dcmDataDict.clear(); /* useful for debugging with dmalloc */
- #endif
- return 0;
- }
- /*
- * CVS/RCS Log:
- * $Log: dcmpschk.cc,v $
- * Revision 1.16 2004/02/04 15:44:38 joergr
- * Removed acknowledgements with e-mail addresses from CVS log.
- *
- * Revision 1.15 2003/09/05 09:00:49 meichel
- * Updated presentation state checker to use class DcmPresentationState
- * instead of DVPresentationState. Imported updated VR checking code
- * from module dcmcheck.
- *
- * Revision 1.14 2003/09/01 12:58:58 wilkens
- * Added #include to file to be able to compile again under Win32.
- *
- * Revision 1.13 2003/03/12 17:34:20 meichel
- * Updated DcmObject::print() flags
- *
- * Revision 1.12 2002/11/27 15:47:52 meichel
- * Adapted module dcmpstat to use of new header file ofstdinc.h
- *
- * Revision 1.11 2002/11/26 08:44:27 meichel
- * Replaced all includes for "zlib.h" with <zlib.h>
- * to avoid inclusion of zlib.h in the makefile dependencies.
- *
- * Revision 1.10 2002/09/23 18:26:07 joergr
- * Added new command line option "--version" which prints the name and version
- * number of external libraries used (incl. preparation for future support of
- * 'config.guess' host identifiers).
- *
- * Revision 1.9 2002/08/20 12:21:53 meichel
- * Adapted code to new loadFile and saveFile methods, thus removing direct
- * use of the DICOM stream classes.
- *
- * Revision 1.8 2002/06/14 10:44:18 meichel
- * Adapted log file handling to ofConsole singleton
- *
- * Revision 1.7 2002/05/02 14:10:04 joergr
- * Added support for standard and non-standard string streams (which one is
- * supported is detected automatically via the configure mechanism).
- *
- * Revision 1.6 2002/04/16 14:01:27 joergr
- * Added configurable support for C++ ANSI standard includes (e.g. streams).
- *
- * Revision 1.5 2001/11/09 16:04:51 joergr
- * Changed type of variable to avoid compiler warnings (comparison of signed
- * and unsigned data).
- *
- * Revision 1.4 2001/10/02 11:51:59 joergr
- * Introduced new general purpose functions to get/put DICOM element values
- * from/to an item/dataset - removed some old and rarely used functions.
- *
- * Revision 1.3 2001/09/26 15:36:02 meichel
- * Adapted dcmpstat to class OFCondition
- *
- * Revision 1.2 2001/06/01 15:50:08 meichel
- * Updated copyright header
- *
- * Revision 1.1 2000/06/21 15:40:32 meichel
- * Added initial version of Presentation State Checker.
- *
- *
- */