Contents
DICOM Network Transport Protocol

University of California, Davis

Rev. 11.22.1995.0001 - Beta

Forward

Part 2: PDU_Service (DICOM Chapters 8,10)

Part 3: DICOM Objects

Part 4: Endian Architectures

Part 5: DIMSE-C Service Classes

Part 6: SOP Classes

Part 7: Low-Level Examples

Part 8: High-Level Examples


Forward

Class Hierarchy

How does one use this DICOM library?

File Names/Extensions

This version of the UCDMC DICOM Network Transport library is the first Beta release.  Many thanks to the folks out there who tested and used the Alpha releases.  In this beta release the following core areas should be fairly well debuged:

Chapter 4 SOP Classes for Storage, Query & Retrieve, and Verification

Chapter 6 Lowlevel DICOM Object support

Chapter 7 DIMSE-C (only) Messaging

Chapter 8 TCP/IP Network Transport

Chapter 10 File (only) Disk I/O

Support was recently added for the following:

Chapter 3 High level IOD Support

Chapter 5 Explicit Transfer Syntax support (along with simple” JPEG support no JPEG encoding/decoding but the JPEG transfer syntaxs will be aliased to the explicit transfer syntax).

The following platforms are supported:

Platform	Compiler
WindowsNT x86 / Windows95	Microsoft Visual C++ v2.2
WindowsNT x86 / Windows95	Watcom C++ v10
WindowsNT x86 / Windows95	Borland C++ v4.0
WindowsNT Alpha AXP	Microsoft Visual C++ v2.0
Solaris v2.3	gcc v2.6.0
SunOS v4.1	gcc v2.5.8
Irix 4 MIPS	gcc v2.5.8
DEC Ultrix MIPS	gcc v2.5.8
Macintosh Power PC	CodeWarrior v5.0

A special thanks to Deborah Hoang who worked on transcribing Part 3 of DICOM into a meta langauge which could then be compiled into C++.  With out her diligence, the IOD support would be almost useless with the quantity of typos I naturally would induce.

Mark Oskin

UC Davis Medical Center

mhoskin@ucdavis.edu

This implementation of the DICOM TCP/IP protocol transport is built up from "network objects".  A network object is a self-contained protocol unit.  This release of the UCDMC DICOM implementation completely covers base level Chapter 8 TCP/IP transport.

 A "network object" is a protocol unit that understands these fundimental functions:

Read from a buffered transport

Write to a buffered transport

Set parameters

Get parameters

It's important to realize that not included in this unit is "interrogate parameters".  Interrogation of parameters is considered a "driving" function.  Protocol units do not drive the DICOM messaging.  They are meant as collectors and senders of complex structures.  To illustrate, a DICOM TCP/IP transport must support these classes:

AAssociateRQ	Association Request

AAssociateAC	Association Accept

AAssociateRJ	Association Reject

AAbortRQ	Association Abort Request

AReleaseRQ	Association Release Request

AReleastRSP	Association Release Response

PDataTF	P-DATA Transport Function

The transport base class is called "PDU_Service".  The PDU_Service provides the "intelligence" of when to read and when to write a protocol unit.  For instance, here is the psuedo-code for a PDU_Serivce :: Connect () function:

Connect:

Link := Open TCP/IP Link

AAssociateRQ :: Write ( Link )

reply = Link :: Read

IF reply := AAssociateAC THEN return TRUE

IF reply := AAssociateRJ THEN

Close TCP/IP Link

return FALSE

END-IF


Class Hierarchy

:	implies inheritance relationship

*	implies inclusive relationship

PDU_Service

: Buffer

* Array < BufferSpace >

* Array < BufferSpace >

: AssociateRQ

* ApplicationContext

* UID

* Array < PresentationContext >

* AbstractSyntax

* UID

* Array < TransferSyntax >

* UID

* UserInformation

* MaximumSubLength

* UID

* ImplementationClass

* UID

* ImplementationVersion

* UID

* SCPSCURoleSelect

* UID

: AssociateAC

* ApplicationContext

* UID

* Array < PresentationContextAccept >

* AbstractSyntax

* UID

* TransferSyntax

* UID

* UserInformation

* MaximumSubLength

* UID

* ImplementationClass

* UID

* ImplementationVersion

* UID

* SCPSCURoleSelect

* UID

: AssociateRJ

: PDataTF

* LinkedBuffer

: Buffer

* Array < BufferSpace >

* Array < BufferSpace >

: AReleaseRQ

: AReleaseRP

: AAbortRQ

* Socket


How does one use this DICOM library?

The best introduction would be to refer to the example files included: test.cpp and sscscp.cpp.  Here is an example of a C-Echo Server.  This example writes directly to the PDU_Service class and does not use the high-level Verification class.  See the teste.C/.cpp or Part 8 for this example using the built-in SOP/DIMSE-C classes.

CEchoServer()

{

PDU_Service	PDU;

DICOMCommandObject	DCO;

DICOMCommandObject	DCOR;

VR	*vr;

UINT16	tuint16;

if(PDU.Listen(PORT))

{

PDU.Read(&DCO);

while(vr = DCO.Pop())

{

switch(vr>Element)

{

case	0x0000:	delete vr; break;

case	0x0002:	DCOR.Push(vr);	break;

case	0x0100:

tuint16 = 0x8030;	// 0x8030

memcpy(vr>Data, &tuint16, 2);

DCOR.Push(vr);	break;

case	0x0800:	DCOR.Push(vr);	break;

case	0x0110:

vr>Element = 0x0120;

DCOR.Push(vr);	break;

}

}

vr = new VR(0x0000, 0x0900, 0x0002, TRUE);

tuint16 = 0;

memcpy(vr>Data, &tuint16, 2);

DCOR.Push(vr);

PDU.Write(&DCOR);

}

// The sender should initiate the close at this point, but send

// one anyway (wont hurt).

PDU.Close();

return ( TRUE );

}

Now, to walk you through line-by-line:

CEchoServer()

{

PDU_Service	PDU;

PDU_Service is the base class for the DICOM TCP/IP transport.  The base class behavior is fully functional.  The default behavior is to accept any incoming ACR-NEMA address, and any SOP/Abstract class.  The default (and only supported) Transfer syntax is LittleEndian 1.2.840.10008.1.2

DICOMCommandObject	DCO;

DICOMCommandObject is a "low-level" DICOM Object.  Access is via Push() and Pop().  If you examine the internals of both DICOMCommandObject and DICOMDataObject they are Priority Queues of Prioriry Queues.  The top level queue is of the group code.  Each element in that queue is a pointer to another queue of elements for that group.  In this manner one can Push() VR's into an Object without regard to Group/Element order.

DICOMCommandObject	DCOR;

VR	*vr;

VR is the base class for all VR's.  A VR is a structure with a Group / Element / Length / Value.  This corresponds to the most basic fundamental object of a DICOM Object.  Every DICOM message is built up from sequences of VR's..

UINT16	tuint16;

if(PDU.Listen(PORT))

Establish a server on a given port.  This port exists in the TCP domain on the local default IP transport of the given machine, (I.e., during socket initiation the default IP address is bound to the socket).  A TRUE return from this call indicates not only that a connection was attempted at the TCP/IP level, but that the DICOM AAssociateRQ structure was sent, parsed, and replied to successfully.  After this call, normal high level DIMSE-C services can take place over the link.

{

PDU.Read(&DCO);

Read an entire DICOM Command object from the link.  This corresponds to a complete message from the remote end.  This call is blocking.

while(vr = DCO.Pop())

Pop() is the main interface to retrieving elements from a DICOM low-level object.  There is also GetVR() and GetUINT16(); however, using those routines is discouraged because they represent a linear search through an array, (i.e., slow).

{

switch(vr>Element)

{

case	0x0000:	delete vr; break;

For now, DICOM low-level objects return group length codes.  This behavior is not required by DICOM v3 protocols, and in the future might be discontinued.  It is safe to delete this VR since it is automatically generated inside the DICOMObject class, (i.e., one never Push()'s a VR of Group/0x0000 into a DICOM Object).

case	0x0002:	DCOR.Push(vr);	break;

SOP Class:  In a real C-Echo server this should be checked for the correct Abstract class (note, SOP Class, and Abstract class are one and the same).

case	0x0100:

tuint16 = 0x8030;	// 0x8030

memcpy(vr>Data, &tuint16, 2);

DCOR.Push(vr);	break;

Command.  A C-Echo-RQ DIMSE-C command is 0x0030.  The C-Echo-RSP is 0x8030.  It is safe to assume that the public item vr->Data is allocated, and is of size 2.  Therefore we just alter the command code to be 0x8030 and push it back on the reply object.

case	0x0800:	DCOR.Push(vr);	break;

case	0x0110:

vr>Element = 0x0120;

DCOR.Push(vr);	break;

}

}

vr = new VR(0x0000, 0x0900, 0x0002, TRUE);

tuint16 = 0;

memcpy(vr>Data, &tuint16, 2);

DCOR.Push(vr);

Create a new VR and add it to the reply object.  Most of the time you create VR's dynamically on the heap with the "new" operator.  This creation can take on one of two forms:

VR(Group, Element, Length, Allocation ?)

VR(Group, Element, Length, Data, Free ?)

The first form creates an element, and allocates the amount of space for length on the heap.  This allocation is flagged "delete/TRUE".  The second method sets the Data pointer to the pointer specified, and sets the delete flag to the parameter given.  If (in both cases) the delete flag is true then when the element is deleted (or out of scope), then the data value is also deleted.

PDU.Write(&DCOR);

Write the DICOM object to the link.  This call is blocking.

}

PDU.Close();

Close the DICOM link.  This call handles all the details about sending either an AReleaseRQ message, and/or sending an AAsbortRQ message.  A return from this call  closes the link; the socket itself is closed.

 	return ( TRUE );

}


File Names/Extensions

Files are named with the following extensions:

.hpp	- Standard C++ include file

.h	- Standard C like header file

.C / .cpp	- C++ Source file

.thh	- C++ Header file (template)

.tcc	- C++ Source file (template)

Source Files:

dicom.hpp	- Standard Include file (all files)

array.thh	- Array Template Header

array.tcc	- Array Template Source

pqueue.thh	- PQueue Template Header

pqueue.tcc	- PQueue Template Source

buffer.thh	- Buffer Class Defination

buffer.tcc	- Buffer Class Source

aarq.hpp	- Class Definitions:

AAssociateRQ

PresentationClass

MaximumLength

ImplementationClass

ImplementationVersion

AbstractClass

TransferSyntax

ApplicationContext

aaac.hpp	- Class Definitions:

AAssociateAC

PresentationClassAccept

aarj.hpp	- Class Definitions:

AAssociateRJ

AReleaseRQ

AReleaseRP

AAbortRQ

 	aarj.hpp	- Source for above

pdata.hpp	- Class Definitions:

PDataTF

LinkedBuffer

deivr.h	- Definitions for:

VR

PQueueVRGroup

DICOMObject

DICOMCommandObject

DICOMDataObject

socket.hpp	- Socket I/O Class definition

unixsock.h	- Combined header information for sockets

dimsec.hpp	- DISME-C Service Objects

verify.hpp	- Verification SOP Class

storage.hpp	- SOP (Storage) Classes

qrsop.hpp	- Q/R (Query & Retrieve) SOP Classes

rtc.hpp	- Run Time Classing

filepdu.hpp	- Chapter 10 I/O support

flpdu.hpp	- Secure PDU_Service Support

endian.hpp	- Endian Nuetral Support

[---------------------------------------------------------------------------]

test.C	- Command line DICOM test program

teste.C	- Command Line DICOM test program

sscscp.C	- Windows NT Service Object SSC-SCP

idicom.cpp	- Windows NT Service Object installation program.


Part 2: PDU_Service (DICOM Chapters 8,10)

Buffer Class

LinkedBuffer Class

Array<DATATYPE> Template Class

PQueue<DATATYPE> Template Class

PQueuePtr<DATATYPE> Template Class

Socket Class

AAssociateRQ Class

AAssociateAC Class

AAssociateRJ Class

AReleaseRQ Class

AReleaseRP Class

AAbortRQ Class

ApplicationContextClass

AbstractSyntaxClass

TransferSyntaxClass

ImplementationClassClass

ImplementationVersionClass

SCPSCURoleSelectClass

MaximumSubLengthClass

PresentationContextClass

PresentationContextAcceptClass

UIDClass

PDataTFClass

PDU_ServiceClass

CheckedPDU_Service Class


Buffer Class

Purpose:

Provides flexible buffered I/O ontop of any derived base transmission class.  Provides for endian translation, and dynamic allocation.

Theory:

Buffers are allocated from a dynamically growing array of type buffer space.  Each buffer space can handle a fixed block size (user selectable), and buffers are allocated on-demand, and freed upon termination of use.  Maximum buffer space is limited by available memory.  It is recommended you set a reasonable value for the default buffer allocation (like 4k).  The usual trade offs: too little and performance suffers; too much, and memory is wasted.  It is extremely important that you compile everything with the NATIVE_ENDIAN constant set to either LITTLE_ENDIAN or BIG_ENDIAN.  If you port the libraries, but get really odd results talking to another system (but no problems having the demo program talk to itself), then you have the endian wrong.

Interface:

BOOL	SetBreakSize( UINT )

Sets the default allocation memory size.  This tells  the buffer what block size of memory should be allocated.  Setting this value to low can cause an increase in overhead, both in time and memory for large buffer operations.  Setting it to high can waste memory for small buffer operations.

BOOL	SetIncomingEndian( UINT )

Sets the type of Endian of the incoming data.  If the type of endian differs from the native endian architecture, then a series of byte swapping operations are performed on >> operations.

BOOL	SetOutgoingEndian ( UINT )

Sets the type of endian data to output.  As the data is placed in the outgoing buffer, it is translated.  Note this translation only takes place on << operations (same for >> operations).

>> <<

Overloaded operations, which understand BYTE, UINT16, and UINT32, char, INT16, INT32 data types.  These operations correctly transform Endian architectures.

BOOL	Flush ()
BOOL	Flush ( UINT )

Flush () without any arguments flushes the entire outgoing buffer to the transport medium.  With one argument, only X bytes of data are flushed.  (This feature is rarely used, except in the Linked Buffer class.)

BOOL	Kill(UINT)

Kill X bytes from the incoming buffer.  This is generally used when communication is corrupted in some way.

BOOL	Read(BYTE *, UINT)

Read X bytes from the input buffer (blocking).  Bytes are read binary, without any endian translation.

BOOL	Write(BYTE *, UINT)

Write X bytes to the output buffer.  The buffer is not flushed, and the data is quarried for a later push.

virtual	INT	ReadBinary(BYTE *, UINT) = 0
virtual	BOOL	SendBinary(BYTE *, UINT) = 0

These routines comprise the "hooks" into the derived transport class.  Any transport class (or any class that wants to pretend to look like a transport class), must support these routines (ANSI C++ wont compile, and will give an Abstract Class defination error).  ReadBinary does not have to read the number of bytes specified on the argument, but it must return -1 on critical errors (errors which should terminate the session).  It must also not write past the amount specified on the argument list.  SendBinary must block to send the data.  And must send the amount of data specified on the argument list.


LinkedBuffer Class

Purpose:

Provides a convient memory storage, for a pre-buffered” data set.  For instance, if there is a raw data file to be transmitted, it is convient to store this file in memory, and then have a protocol class insert the control codes for it's protocol "in line" with the data set, as the data is moving out of the buffer.  Put another way, if a protocol "packets" data with signalling, then it makes logical sense to have the data inside the packets be removed from the signalling bytes.  The LinkedBuffer was designed for this purpose.  In the DICOM protocol, the raw VR's are translated into a sequence of bytes and put in a LinkedBuffer.  A P-DATA-TF protocol class pulls bytes from this buffer and chops them into separate PDU service requests, and then outputs them to the main transport buffer.  A reverse process is done on incoming P-DATA-TF requests.

Theory:

See "Buffer" class.  LinkedBuffer is a derived class from Buffer.

Interface:

BOOL	Fill(Buffer &, UINT)

Fill the buffer passed as an argument with X bytes of the LinkedBuffer.

BOOL	Flush(Buffer &, UINT)

Flush X bytes of the LinkedBuffer into the buffer passed as an argument.


Array<DATATYPE> Template Class

Purpose:

Provides a flexible, dynamically growing array of any data type.  Strong type-checking (a feature of C++) is used, rather than having an unsafe, common base class array type.  Associated control features, such as control over self destruct on end of scope, are added for added flexibility.

Theory:

(Currently) built atop a linked list structure.  This will probably change in future evolutions of the software, since so much of the protocol implementation uses this Array type.  (i.e., A little work on speeding it up will go a long way toward improving the overall performance of the software).

Interface:

DATATYPE & Add(DATATYPE &)

Adds the argument of type DATATYPE to the end of the array.

DATATYPE & Get( UINT )

Gets a reference to the value stored in position X of the array.

DATATYPE & RemoveAt( UINT )

Removes the array element at position X in the array, and returns that element.

DATATYPE & operator []

Gets a reference to the value stored in position X of the array.

UINT	GetSize()

Gets the size of the array.


PQueue<DATATYPE> Template Class

Purpose:

Provides a sorted heap of elements of type DATATYPE.

Theory:

Class is a derived class of Array<DATATYPE>.

Interface:

DATATYPE & Push( DATAYPE & )

Adds an object of type DATATYPE on the heap.

DATATYPE & Pop( DATATYPE &)

Removes the lowest value DATATYPE from the heap.


PQueuePtr<DATATYPE> Template Class

Purpose:

Provides a sorted heap, where the objects stored are pointers to objects, and the sorting order is the order of the objects themselves.  (i.e., In order to determine the order of the heap, the pointers are first de-referenced, and then compared).

Theory:

Sort of a hack.  In true object orientated fashion, this class would not be needed, but it's a trade-off between speed and elegance; and in this case speed won out.

Interface:

DATATYPE & Push ( DATATYPE & )

Adds an object of type DATATYPE on the heap.

DATATYPE & Pop ( DATATYPE & )

Removes the lowest value DATATYPE from the heap.

Special Note:

In order to use this class, you must supply a data type which is a pointer.  For instance, these all mean different things:

PQueue<int>	Heap of integers (sorted by value)
PQueue<int *>	Heap of pointers (sorted by address)
PQueuePtr<int>	Error.  (*integer) will de-reference to an invalid pointer (if youre lucky).
PQueuePtr<int *>	Heap of pointers (sorted by value)


Socket Class

Purpose:

Provides a machine independent interface to the TCP/IP network.

Theory:

In most cases, there is a finite way to design the interface to a TCP/IP network.  UNIX uses "Berkeley Sockets", Windows uses "WinSock", which is almost Berkeley Sockets.  A DOS-based system like PC/TCP uses something almost berkeley socket compatible (a slight difference in the concept of listen/accept).  The purpose of this class is to provide as thin a wrapper around the machine sub-system as possible, while maintaining cross-platform portability.

Interface:

BOOL	Open(char *dest, char *port)

Open a connection to the destination, to the specific port.  Both the destination and port can be given as symbolic names.  (i.e., these calls are functionally equivalent:

Open ( "152.79.140.1", "23" )

Open ( "imrad.ucdmc.ucdavis.edu", "telnet" )

and, so long as DNS is working, will return the same value.

BOOL	Close()

Closes a socket connection

INT	ReadBinary(BYTE *, UINT)

Reads up to X bytes into the buffer given as an argument.  Returns either -1 on a critical error, or the amount of data actually read (can return 0 data read, and this should not be an error).

BOOL	SendBinary(BYTE *, UINT)

Sends (blocking) X bytes of the buffer given as an argument over the connected socket.

BOOL	Listen(char *port)

Sets the socket up for listening on the named port.

BOOL	Accept()

Blocks until a connection is opened to the named port.


AAssociateRQ Class

Purpose:

To provide all the functionality of an AAssociateRQ object.  Including read / write from a buffered link.  Setting / Getting of service parameters.

Theory:

As in all protocol objects, this one is designed for an explicit read() and a readdynamic() operation.  (i.e., an external state-machine can "drive" these objects).  Contained inside the AAssociateRQ class are ApplicationContext, PresentationContext's, and UserInformation classes.  Each of these objects is similar in design, in that read / readdynamic / write calls all function the same (as does Size() calls).  The AAssoicateRQ class (as with all protocol classes) is not designed to interrogate its parameters after a read() from a network link.  Its goal is to get the data, and package it into an organized manner.  A high level state-machine should look at this data, then send the correct object back to the calling party.

Interface:

ApplicationContext	AppContext

Public data member of the ApplicationContext class.  See the ApplicationContext class documentation for how to access this object.

Array<PresentationContext>	PresContexts

Public data member of type Array<PresentationContext>.  See the Array template, and PresentationContext class documentation on how to access this object.

UserInformation	UserInfo

Public data member of the type UserInformation.  See the UserInformation class documentation for how to access this object.

AAssociateRQ ()

Constructor.  Called automatically during object instantiation.

AAssociateRQ ( BYTE *, BYTE * )

Constructor.  Same as AAssociateRQ(), SetCallingApTitle(BYTE *), SetCalledApTitle (BYTE *).

~AAssociateRQ ()

Destructor.  Responsible for freeing up the PresentationContext array.

void	SetCalledApTitle ( BYTE * )

Sets the CalledAp member of the AAssociateRQ class.  The CalledAp title corresponds to the "remote" ACR-Nema address.

void	SetCallingApTitle ( BYTE * )

Sets the CallingAp member of the AAssociateRQ class.  The CallingAp title corresponds to the "local" ACR-Nema address.

void	SetApplicationContext ( ApplicationContext & )

Sets the ApplicationContext member of the AAssociateRQ class.  This is usually set to the standard "DICOM" UID.

void	AddPresentationContext ( PresentationContext & )

Adds a PresentationContext to the array of presentation classes.  Note that the presentation class is not checked for uniqueness among the other presentation classes in the array.  This function should not be accessed directly from a higher level than the PDU_Service class.  (PDU_Service provides a high level access function which builds a presentation context from SOP (Abstract) UID automatically.)

void	SetUserInformation ( UserInformation & )

Sets the UserInformation member of the AAssociateRQ class.  This should not be accessed from any level higher than the PDU_Service class.  All supported UserInformation objects are parameters for the protocol stack level itself, and not for the application level.

BOOL	Write ( Buffer & )

Writes the AAssociateRQ class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire AAssociateRQ class from a buffer.  Including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire AAssociateRQ class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  Very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.  The size may not correspond with the number of incoming bytes on an AAssociateRQ packet.  Some objects contained in the UserInformation packet are considered "baggage", and are discarded.


AAssociateAC Class

Purpose:

To provide all the functionality of an AAssociateAC object.  Including read / write from a buffered link.  Setting / Getting of service parameters.

Theory:

As in all protocol objects, this one is designed for an explicit read() and a readdynamic() operation; (i.e., an external state-machine can "drive" these objects).  Contained inside the AAssociateAC class is an application context, an array of PresentationContextAccept's, and UserInformation classes.  Each of these objects is similar in design, in that read / readdynamic / write calls all functions the same (as does Size() calls).  The AAssoicateAC class (as with all protocol classes) is not designed to interrogate its parameters after a read() from a network link.  Its goal is to get the data and package it into an organized manner.  A high level state-machine should look at this data and send the correct object back to the calling party.

Interface:

BYTE	CalledApTitle[16]

Publicly accessible data item which contains the Called Application Title (remote app title).  This member is really stored in a 17 byte array (so don't worry about the appended null character).  This member is really the new name for the remote ACR-Nema address.

BYTE	CallingApTitle[16]

Publicly accessible data item which contains the Calling Application Title (local app title).  This member is really stored in a 17 byte array (to offset the null terminated strings in C++).  This member is really the new name for the local ACR-Nema address.

ApplicationContext	AppContext

Publicly accessible data item which contains the application context.  An application context is usually set to the default DICOM application context (a UID).  However, different implementations (particularly those which where written to ACR-Nema v2 specifications) did not use the default DICOM uid.

Array<PresentationContextAccept>	PresContextAccepts

Publicly accessible data item which contains a list of PresentationContextAccept classes.  A Presentation Context Accept is described in the PresentationContextAccept class documentation.  In summary, each PresentationContext proposed in the AAssociateRQ packet is read and an appropiate PresentationContextAccept is generated for it.  The accept structure contains such information as what TransferSyntax class to use, and appropriate error codes if applicable.

UserInformation	UserInfo

This object is identical in nature to the one used in the AAssociateRQ packet.

AAssociateAC ()

Constructor.  Called automatically during object instantiation.

AAssociateAC ( BYTE *, BYTE * )

Constructor.  Same as AAssociateAC(), SetCallingApTitle(BYTE *), SetCalledApTitle (BYTE *).

~AAssociateAC ()

Destructor.  Responsiable for freeing up the PresentationContextAccept array.

void	SetCalledApTitle ( BYTE * )

Sets the CalledAp member of the AAssociateAC class.  The CalledAp title corresponds to the "remote" ACR-Nema address.

void	SetCallingApTitle ( BYTE * )

Sets the CallingAp member of the AAssociateAC class.  The CallingAp title corresponds to the "local" ACR-Nema address.

void	SetApplicationContext ( ApplicationContext & )

Sets the ApplicationContext member of the AAssociateAC class.  This is usually set to the standard "DICOM" UID.

void	AddPresentationContextAccept ( PresentationContextAccept & )

Adds a PresentationContextAccept to the array of presentation classes accepts.  Note that the presentation context accept class is not checked for uniqueness among the other Presentation Context Accept Classes in the array.  This function should not be accessed directly from a higher level than the PDU_Service class.  (PDU_Service provides a high level access function which builds a presentation context accept from a presentation context automatically.)

void	SetUserInformation ( UserInformation & )

Sets the UserInformation member of the AAssociateAC class.  This should not be accessed from any level higher than the PDU_Service class.  All supported UserInformation objects are parameters for the protocol stack level itself, and not for the application level.

BOOL	Write ( Buffer & )

Writes the AAssociateAC class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire AAssociateAC class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire AAssociateAC class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.  The size may not correspond with the number of incoming bytes on an AAssociateAC packet.  Some objects contained in the UserInformation packet are considered "baggage" and are not sized.


AAssociateRJ Class

Purpose:

Like all protocol classes this class encapsulates all aspects of an AAssociateRJ PDU request packet.  The packet is for rejecting an incoming association.

Theory:

As in all protocol objects, this one is designed for an explicit read() and a readdynamic() operation, (i.e., an external state-machine can drive these objects).  Each of these objects is similar in design, in that read / readdynamic / write calls all function the same (as does Size() calls).  The AAssociateRJ class (as with all protocol classes) is not designed to interrogate its parameters after a read() from a network link.  Its goal is to get the data and package it into an organized manner.  A high level state-machine should look at this data and send the correct object back to the calling party.

Interface:

BYTE	Result

Result code.

1	Rejected Permanent
2	Rejected Transient
*See Reason

BYTE	Source

Source code (PDU level, or IOD Object level)

1	DICOM UL Service User
2	DICOM UL Service Provider (ACSE Related)
3	DICOM UL Service Proivder (Presentation Related)
*See Reason

BYTE	Reason

Reason for Rejection.  This field is usually the one you should check to find anything useful.

1	No reason
2	Application Context name not supported
3	Calling Application title is not known
7	Called Application title is not known

Most common reasons are 3 (flat out rejection of Abstract classes proposed), and 7 (rejection of ACR-Nema address).

AAssociateRJ ()

Constructor.  Sets up some initial default values.

AAssociateRJ (BYTE, BYTE, BYTE)

Constructor.  Sets up the Result/Source/Reason according to the parameters given.

~AAssociateRJ ()

Destructor.  (Empty.  Currently does nothing).

BOOL	Write ( Buffer & )

Writes the AAssociateRJ class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire AAssociateRJ class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire AAssociateRJ class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  Very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


AReleaseRQ Class

Purpose:

Like all protocol classes this class encapsulates all aspects of an AReleaseRQ PDU request packet.  The packet is for dropping an established association.

Theory:

As in all protocol objects, this one is designed for an explicit read() and a readdynamic() operation, (i.e., an external state-machine can "drive" these objects).  Each of these objects is similar in design, in that read / readdynamic / write calls all function the same (as does Size() calls).  The AReleaseRQ class (as with all protocol classes) is not designed to interrogate its parameters after a read() from a network link.  Its goal is to get the data and package it into an organized manner.  A high level state-machine should look at this data and send the correct object back to the calling party.

Interface:

AReleaseRQ ()

Constructor.  Sets up some initial default values.

~AReleaseRQ ()

Destructor.  (Empty.  Currently does nothing).

BOOL	Write ( Buffer & )

Writes the AReleaseRQ class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire AReleaseRQ class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire AReleaseRQ class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


AReleaseRP Class

Purpose:

Like all protocol classes this class encapsulates all aspects of an AReleaseRP PDU request packet.  The packet is for answering the request to drop an established association.

Theory:

As in all protocol objects, this one is designed for an explicit read() and a readdynamic() operation, (i.e., an external state-machine can "drive" these objects).  Each of these objects is similar in design, in that read / readdynamic / write calls all function the same (as does Size() calls).  The AReleaseRP class (as with all protocol classes) is not designed to interrogate its parameters after a read() from a network link.  Its goal is to get the data and package it into an organized manner.  A high level state-machine should look at this data and send the correct object back to the calling party.

Interface:

AReleaseRP ()

Constructor.  Sets up some initial default values.

~AReleaseRP ()

Destructor.  (Empty.  Currently does nothing).

BOOL	Write ( Buffer & )

Writes the AReleaseRP class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen and PDU_Service() :: Close() service methods.

BOOL	Read ( Buffer & )

Reads the entire AReleaseRP class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen  and PDU_Service() :: Close() service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire AReleaseRP class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


AAbortRQ Class

Purpose:

Like all protocol classes this class encapsulates all aspects of an AAbortRQ PDU request packet.  The packet is for dropping an established association because of some unexpected event (for instance, if the underlying protocol messed up, or the remote end send a corrupted object).

Theory:

As in all protocol objects, this one is designed for an explicit read() and a readdynamic() operation, (i.e., an external state-machine can "drive" these objects).  Each of these objects is similar in design, in that read / readdynamic / write calls all function the same (as does Size() calls).  The AAbortRQ class (as with all protocol classes) is not designed to interrogate its parameters after a read() from a network link.  Its goal is to get the data, and package it into an organized manner.  A high level state-machine should look at this data, and send the correct object back to the calling party.

Interface:

BYTE	Source

Source of the error

BYTE	Reason

Reason for terminating association.

AAbortRQ ()

Constructor.  Sets up some initial default values.

~AAbortRQ ()

Destructor.  (Empty.  Currently does nothing).

BOOL	Write ( Buffer & )

Writes the AAbortRQ class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen, and PDU_Service :: Close() service methods.

BOOL	Read ( Buffer & )

Reads the entire AAbortRQ class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire AAbortRQ class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


ApplicationContext Class

Purpose:

Provides all high level functionality of an application context, including Set/Get of the application context UID, along with Read/Write/Size methods for network transport.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.  The application context uid itself is stored in an UID object.

Interface:

UID	ApplicationContextName

The actual data storage area for the application context.

ApplicationContext()

Constructor.  Currently only clears the ApplicationContextName variable.

ApplicationContext (UID &)

Constructor.  Like ApplicationContext() but sets the ApplicationContextName variable.

ApplicationContext ( BYTE * )

Constructor.  Like ApplicationContext(UID &)

~ApplicationContext ()

Desstructor.  Currently empty.

void	Set(UID &)

Sets the ApplicationContextName

void	Set(BYTE *)

Sets the ApplicationContextName

BOOL	Write ( Buffer & )

Writes the ApplicationContext class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire ApplicationContext class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire ApplicationContext class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


AbstractSyntax Class

Purpose:

Provides all high level functionality of an abstract syntax, including Set/Get of the abstract syntax UID, along with Read/Write/Size methods for network transport.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.  The abstract syntax uid itself is stored in an UID object.

Interface:

UID	AbstractSyntaxName

The actual data storage area for the abstract syntax.

AbstractSyntax()

Constructor.  Currently only clears the AbstractSyntaxName variable.

AbstractSyntax (UID &)

Constructor.  Like AbstractSyntax() but sets the AbstractSyntaxName variable.

AbstractSyntax ( BYTE * )

Constructor.  Like AbstractSyntax(UID &)

~AbstractSyntax ()

Desstructor.  Currently empty.

void	Set(UID &)

Sets the AbstractSyntaxName

void	Set(BYTE *)

Sets the AbstractSyntaxName

BOOL	Write ( Buffer & )

Writes the AbstractSyntax class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire AbstractSyntax class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire AbstractSyntax class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  Very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


TransferSyntax Class

Purpose:

Provides all high level functionality of a transfer syntax, including Set/Get of the transfer syntax UID, along with Read/Write/Size methods for network transport.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.  The transfer syntax uid itself is stored in an UID object.

Interface:

UID	TransferSyntaxName

The actual data storage area for the transfer syntax.

UINT	EndianType

The endian type.  (LITTLE_ENDIAN / BIG_ENDIAN).  This field is not actually transmitted over the network (it is implied implictly in the transfer syntax UID), however, it is used by the Read/Write methods in the PDU_Service class to prepare a buffer for transfer syntax translation.

* Use of this field is obselate.

TransferSyntax()

Constructor.  Currently only clears the TransferSyntaxName variable.

TransferSyntax (UID &)

Constructor.  Like TransferSyntax() but sets the TransferSyntaxName variable.

TransferSyntax ( BYTE * )

Constructor.  Like TransferSyntax(UID &)

~TransferSyntax ()

Desstructor.  Currently empty.

void	Set(UID &)

Sets the TransferSyntaxName

void	Set(BYTE *)

Sets the TransferSyntaxName

BOOL	Write ( Buffer & )

Writes the TransferSyntax class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire TransferSyntax class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire TransferSyntax class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


ImplementationClass Class

Purpose:

Provides all high level functionality of an implementation class, including Set/Get of the ImplementationClass UID, along with Read/Write/Size methods for network transport.  An Implementation Class is a PDU level parameter.  As a user of the DICOM protocol you should not be using this class.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.  The implementation class uid itself is stored in an UID object.

Interface:

UID	ImplementationClassName

The actual data storage area for the implementation class.

ImplementationClass()

Constructor.  Currently only clears the ImplementationClassName variable.

ImplementationClass (UID &)

Constructor.  Like ImplementationClass() but sets the ImplementationClassName variable.

ImplementationClass ( BYTE * )

Constructor.  Like ImplementationClass(UID &)

~ImplementationClass ()

Destructor.  Currently empty.

void	Set(UID &)

Sets the ImplementationClassName

void	Set(BYTE *)

Sets the ImplementationClassName

BOOL	Write ( Buffer & )

Writes the ImplementationClass class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire ImplementationClass class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire ImplementationClass class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  Very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


ImplementationVersion Class

Purpose:

Provides all high level functionality of an implementation version, including Set/Get of the ImplementationVersion UID, along with Read/Write/Size methods for network transport.  An implementation class is a PDU level parameter.  As a user of the DICOM protocol you should not be using this class.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.  The implementation version uid itself is stored in an UID object.

Interface:

UID	Version

The actual data storage area for the implementation version.

ImplementationVersion()

Constructor.  Currently only clears the Version variable.

ImplementationVersion (UID &)

Constructor.  Like ImplementationVersion() but sets the Version variable.

ImplementationVersion ( BYTE * )

Constructor.  Like ImplementationVersion(UID &)

~ImplementationVersion ()

Destructor.  Currently empty.

void	Set(UID &)

Sets the Version

void	Set(BYTE *)

Sets the Version

BOOL	Write ( Buffer & )

Writes the ImplementationVersion class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire ImplementationVersion class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire ImplementationVersion class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  Very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


SCPSCURoleSelect Class

Purpose:

Provides high level functionality of an SCPSCU Role Select.  This object is read from a network but is never written back.  It is considered baggage and is not implemented yet.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.

Interface:

UID	uid

Public data member corresponding to the Abstract SOP class that this role select object is about.

BYTE	SCURole

The role of the SCU

BYTE	SCPRole

The role of the SCP

SCPSCURoleSelect()

Constructor.  Currently only sets up some internal members.

~SCPSCURoleSelect()

Destructor.  Currently empty.

BOOL	Write ( Buffer & )

Writes the SCPSCURoleSelect class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire SCPSCURoleSelect class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire SCPSCURoleSelect class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


MaximumSubLength Class

Purpose:

Provides all high level functionality of a maximum sub length class, including Set/Get of the MaximumSubLength value, along with Read/Write/Size methods for network transport.  A maximum sublength class is a PDU level parameter.  As a user of the DICOM protocol you should not be using this class.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.

Interface:

MaximumSubLength()

Constructor.  Currently sets the maximum sublength to 16384

MaximumSubLength (UINT32)

Constructor.  Like MaximumSubLength() but sets the value.

~MaximumSubLength ()

Destructor.  Currently empty.

void	Set(UINT32)

Sets the Maximum Sub Length.  This must be less than 16384 as defined in the DICOM v3 draft documents.

UINT32	Get()

Get the maximum sub length.

BOOL	Write ( Buffer & )

Writes the MaximumSubLength class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire MaximumSubLength class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire MaximumSubLength class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


UserInformation Class

Purpose:

Provides all the functionality of a user information section of an AAssociateRQ / AC message.  This class is a PDU level parameter (in this implementation) and should not be used by a user of the PDU_Service class.  Exchanged within this class are such details as MaximumSubLength, ImplementationClass / Version, and Role Select.  This class currently implements only a subset of the full DICOM v3 standard.  This subset includes all required user information parameters.  All required user information parameters are PDU level.  In the future there may be support for some upper lay parameters.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.

Interface:

UINT32	Baggage

This parameter stores a "size" containing the number of bytes which were discarded on an incoming AAssociateRQ / AC message.  This parameter allows the user information class to support the incoming of private user information parameters.  It should be noted that private (or unsupported) user information classes are not sent back in an AAssociateAC class; however, this is within DICOM v3 conformance.

MaximumSubLength	MaxSubLength

MaxiumSubLength protocol unit.  See the section on MaximumSubLength.  This protocol unit is always sent during an AAssociateRQ / AC.

ImplementationClass	ImpClass

ImplementationClass protocol unit.  See the section on ImplementationClass.  This protocol unit is always sent during an AAssociateRQ / AC.

ImplementationVerision	ImpVersion

ImplementationVersion protocol unit.  See the section on ImplementationVersion.  This protocol unit is always sent during an AAssociateRQ / AC.

UserInformation ()

Constructor.  Intializes each of the protocol units.

~UserInformation ()

Destructor.  Currently empty.

void	SetMax(MaximumSubLength &)

Copies the parameter into the MaxSubLength value.

UINT32	GetMax ()

Returns the maximum sublength value

BOOL	Write ( Buffer & )

Writes the UserInformation class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire UserInformation class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire UserInformation class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


PresentationContext Class

Purpose:

A "Presentation Context" is a way of saying, "I'm can transfer this type of high level object, using any of these low-level transfer syntaxs."  (A typical message is: "I'm going to send CT images using implicit Little Endian transfer syntax").  A PresentationContext contains the high level object UID (AbstractSyntax), and a number of propesed TransferSyntax UIDs.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.

Interface:

AbstractSyntax	AbsSyntax

See the class documentation on AbstraxSyntax classes.

Array < TransferSyntax >	TrnSyntax

The array of proposed Transfer Syntaxs.  See the class documentation on TransferSyntax's, as well as the PDU_Service documentation.  This implementaion of the PDU_Service class handles the transfer syntaxs automatically.  A user of the PDU_Service class need not worry about this field.

PresentationContext()

Constructor.  Called automatically.  Sets up internal parameters only.

PresentationContext ( AbstractSyntax &, TransferSyntax & )

Constructor.  Like PresentationContext(), except the AbsSyntax field is set, and one TransferSyntax is added to the array of proposed transfer syntaxs.

~PresentationContext()

Destructor.  Responsible for clearing the TransferSyntax array.

void	SetAbstraxtSyntax ( AbstractSyntax & )

Sets the abstract syntax (SOP class) for this PresentationContext.

void	AddTransferSyntax ( TransferSyntax & )

Adds the transfer syntax to the proposed transfer syntax array.

BOOL	Write ( Buffer & )

Writes the PresentationContext class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire PresentationContext class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire PresentationContext class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects. It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


PresentationContextAccept Class

Purpose:

A PresentationContextAccept is a protocol unit that is generated for an AAssociateAC message for each PresentationContext sent in the AAssociateRQ message.  The fields generated in this class are set by the PDU_Service class which makes virtual function calls to determine acceptence.  See the PDU_Service class documentation for where and why this is done.

Theory:

Straight forward implementation.  See any of the protocol classes for a description on network read/write.

Interface:

TransferSyntax	TrnSyntax

Of the proposed TransferSyntax's in the PresentationContext sent inside the AAssociateRQ message, this field contains the UID of one of those syntaxs.  See the PDU_Service class documentation for how this parameter is chosen.

PresentationContextAccept()

Constructor.  Called automatically.  Sets up internal parameters only.

PresentationContextAccept ( TransferSyntax & )

Constructor.  Like PresentationContextAccept(), except the TransferSyntax is set.

~PresentationContextAccept()

Destructor.  Responsible for clearing the TransferSyntax array.

void	SetTransferSyntax ( TransferSyntax & )

Sets the Transfer Syntax (SOP class) for this PresentationContextAccept.

void	SetResult (BYTE)

Sets the result parameter (accepted, rejected, etc).

BYTE	GetResult ()

Gets the result paramter.

BOOL	Write ( Buffer & )

Writes the PresentationContextAccept class packet to a buffer.  The object should first be Size()'ed.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	Read ( Buffer & )

Reads the entire PresentationContextAccept class from a buffer, including the first identifying byte.  This function should not be accessed directly.  See the PDU_Service :: Connect() and PDU_Service() :: Listen service methods.

BOOL	ReadDynamic ( Buffer & )

Reads the entire PresentationContextAccept class from a buffer, except for the first identifying byte.  This function should never be accessed directly, except in a protocol state-machine within the PDU_Service class.

UINT32	Size()

Sizes the object, manipulating the internal data members length for all contained objects.  It is very important that this member is called before a Write ().  No harm is done from multiple calls to this function.  The size returned is the absolute size, which does not correspond directly with the "length to end" field of the DICOM protocol field.


UID Class

Purpose:

A UID is a specialized type of string.  It's restricted to a maximum of 64 characters.  Future implementations of this protocol stack will concentrate on deriving specialized type of UID classes from the base UID class.  For instance, it makes more sense to have a TransferSyntax be a specialized type of UID (an inheritance relationship), than the way it's currently set out with an inclusive relationship.

Theory:

Fixed string size of 65 bytes is allocated, along with a length field.

Interface:

UID ()

Clears the UID.

void	Set(BYTE *)

void	Set(UID &)

void	Set(char *)

=

Sets the UID to the parameter.  BYTE *, and char * must be null terminated strings.

BYTE	*GetBuffer ( UINT )

Gets a pointer to the internal buffer.  You must pass a minimum length parameter.

void	SetLength ( UINT )

Sets the length field.  This is used for incoming UID's on a network link.  Such UID's are not null terminated, thus it helps to convert them.

UINT	GetSize ()

Gets the length of a UID

==

Operator == to test equality.


PDataTF Class

Purpose:

Provides the PDU protocol services to transfer byte streams using DICOM PDU level packets.  The byte stream to be transmitted / received is stored in a linked buffer and is stored as a public parameter inside the class.  This class is different than the other protocol classes.  There is no Size() method.  See the PDU_Service class *code* to see how this class is driven.

Theory:

Basic philosophy is that DICOM objects are first converted into byte streams.  These byte streams are then arbitrarily chopped up (in size equal to the MaximumSubLength field) and then pushed back over another byte stream.  One way to think of this class is that an arbitrarily long data stream must be "framed" inside smaller packets.  This framing is added for outgoing objects, and removed for incoming ones.  This class does that with the help of an outside driver function.

Interface:

LinkedBuffer	VRBuffer

Linked Buffer to send / receive data from.

BOOL	Write ( Buffer & )

Writes all the data in the VRBuffer LinkedBuffer to the buffer passed as a parameter.  Framing information is added.

BOOL	ReadDynamic ( Buffer & )

A Single PDU level frame PDataTF packet is read and added to the VRBuffer.  This read may not correspond to a full object.


PDU_Service Class

Purpose:

Provide all the high level functionality to construct DICOM servers and clients.  The interface provided is at the Connect/Listen and Read/Write of DICOM object level.  Most low level protocol details are hidden.

Theory:

As a user of a PDU level class, you need not be aware of transfer syntax, link-layer mediums, or association negotiation.  What you want is a high level way of saying I want to pass these objects over some DICOM compatible link.  That's what the PDU_Service class provides.  To open an outgoing connection you simply say what IOD classes you will be sending, and then provide an IP/Port address.  To create a server, just provide the TCP port address.  Once the link is established, you can Read / Write entire DICOM objects at once.  You should not worry about how the object is sent / received, just make sure that it was done so.

Interface

BOOL	SaveDICOMDataObject (

char	*filename,

UINT	Format,

DICOMDataObject *)

Saves a DICOMDataObject to disk in one of the following formats:

Format	Description
ACRNEMA_VR_DUMP	A file format commonly referred to as ACR-NEMA v2”.  Although there is no standard format for this, there is an accepted standard.  This format is a straight raw Implicit Little Endian VR dump.  It is compatible with CTN v1.5
DICOM_CHAPTER_10_IMPLICIT	This is the pre-change DICOM Chapter 10 file format.  It is a Chapter 10 file encoded strickly with Implicit Little Endian
DICOM_CHAPTER_10_EXPLICIT	This is the newest (and standardized) DICOM Chapter 10 compatible file.  The file meta header is encoded as explicit Little Endian, and the remainder of the object is encoded implicit little endian.
DICOMDataObject	*LoadDICOMDataObject(char *filename)

Loads a DICOMDataObject from disk.  The format of the object is automatically detected.  All three of the above formats is accpeted (and detected for automatically)

BOOL	ClearAbstractSyntaxs()

Clears all known Abstract Syntaxs

BOOL	AddAbstractSyntax(UID &)

Adds an Abstract syntax to the list of abstract syntaxs to be proposed during an association negotiation (outgoing)

BOOL	SetApplicationContext(UID &)

Sets the Application Context for outgoing connections.

BOOL	SetLocalAddress(BYTE *)

Sets the local ACR-NEMA address for outgoing connections.

BOOL	SetRemoteAddress(BYTE *)

Sets the remote ACR-NEMA address for outgoing connections.

BOOL	Connect(BYTE *, BYTE *)

Opens a TCP/IP connection to IP / PORT.  If this procedure returns, the PDU level negotiation is done, the connection was accepted.  The remote end is ready to receive a DICOM Object.

BOOL	Close()

Disconnect a session.  This disconnection may be an AAbortRQ or an AReleaseRQ depending on what the state of communication.

BOOL	Listen(BYTE *)

Hang a listen on a local TCP port.  Incoming connections are fully associated before this procedure returns.  A user should check the return value.  TRUE = accepted, ready to perform DICOM Object communication.  FALSE = rejected.

BOOL	Multiplex(int)

Multiplex is used like Listen() except you pass in a connected socket.  Usually this function is used in multithread servers.  You first init a listen() on a socket, then when you perform an accept() you get a new socket handle.  At this point you would fork (or create a thread), and then pass the new socket handle to the Multiplex function.  The multiplex function will then attempt to negotiate a DICOM association.

BOOL	Read(DICOMObject	*)

Read an entire DICOM Object from the network (blocking)

BOOL	Write(DICOMCommandObject	*)

BOOL	Write(DICOMDataObject	*)

Write an entire DICOM object to the network.

Association Parameter Checking:

virtual	BOOL	CanYouHandleTransferSyntax(TransferSyntax &)

Determine whether the TransferSyntax extension can handle the given UID.

virtual	BOOL	ShouldIAcceptRemoteApTitle(BYTE	*)

Determine whether to accept / reject the remote ACR-NEMA address

virtual	BOOL	ShouldIAcceptLocalApTitle(BYTE *)

Determine whether to accept / reject the local ACR-NEMA address

virtual	BOOL	ShouldIAcceptApplicationContext(ApplicationContext 	&)

Determine whether to accept / reject the proposed Application Context

virtual	BOOL	ShouldIAcceptPresentationContext 	(PresentationContext &, PresentationContextAccept &)

Determine whether to accept the Presentation Context, and construct the Presentation Context accept.  A derived class should not (in most cases) overload this function.  The default implementation breaks down the parameters and passes them for checking to the derived class anyway.

virtual	BOOL	ShouldIAcceptAbstractSyntax(AbstractSyntax &)

Determine whether to accept / reject the proposed abstract syntax.

virtual	BOOL	AddTransferSyntaxs(PresentationContext &)

Add all known transfer syntaxs to a given presentation context.

virtual	BOOL	GetImplementationClass(ImplementationClass &)

Set the outgoing implementation class

virtual	BOOL	GetImplementationVersion(ImplementationVersion &)

Set the outgoing implementation version.

Transfer Syntax Extension:

virtual	BOOL	ParseRawVRIntoDCM ( 	BYTE,	 LinkedBuffer &, DICOMObject *)

Parse Raw VR data streams into DICOM objects.  The BYTE corresponds to the PresentationContextID.  Use GetTransferSyntaxUID to obtain the UID for the given BYTE.  Then use the UID to determine the format of the incoming data.  The default implementation will understand DICOM Implicit Little Endian format.

virtual	BYTE	ParseDCMIntoRawVR(DICOMObject *, LinkedBuffer &)

Parse DICOM Object into raw VR data stream.  Return the PresentationContextID corresponding to the format of the data.  A return of 0 means error, and the association is dropped.  Put the raw data stream into the LinkedBuffer.  The default implementation parses into DICOM Implicit Little Endian format.

BYTE	GetPresentationContextID(UID &)

Obtain PresentationContextID from Transfer Syntax UID

BOOL	GetTransferSyntaxUID(BYTE, UID &)

Obtain Transfer Syntax UID from PresentationContextID

The following functions are used internally by ParseRawVRIntoDCM and ParseDCMIntoRaw.  They should not (normally) be accessed directly.  Internally, the Parse functions will simple”illy encode/decode JPEG compressed transfer syntaxes.  If you want to add better support for JPEG, you will need to override the Parse entry points, and provide it.

Currently Explicit VR transfer syntax encoding/decoding is supported.  By default, it is disabled.  To use it, you will need override the AddTransferSyntaxs() function.  Also, if you are using an Explicit VR transfer syntax, you must load an RTC class, and RTC a DICOMObject before sending it.

virtual	BOOL	Implicit_ParseRawVRIntoDCM (	LinkedBuffer &, DICOMObject *);

virtual	BOOL	Implicit_ParseDCMIntoRawVR (	DICOMObject *, LinkedBuffer &);

virtual	BOOL	ImplicitLittleEndian_ParseRawVRIntoDCM (	LinkedBuffer &, DICOMObject *);

virtual	BOOL	ImplicitLittleEndian_ParseDCMIntoRawVR(	DICOMObject *, LinkedBuffer &);

virtual	BOOL	Explicit_ParseRawVRIntoDCM(	LinkedBuffer &, DICOMObject *);

virtual	BOOL	Explicit_ParseDCMIntoRawVR(	DICOMObject *, LinkedBuffer &);

virtual	BOOL	ExplicitLittleEndian_ParseRawVRIntoDCM(	LinkedBuffer &, DICOMObject *);

virtual	BOOL	ExplicitLittleEndian_ParseDCMIntoRawVR(	DICOMObject *, LinkedBuffer &);

virtual	BOOL	ExplicitBigEndian_ParseRawVRIntoDCM(	LinkedBuffer &, DICOMObject *);

virtual	BOOL	ExplicitBigEndian_ParseDCMIntoRawVR(	DICOMObject *, LinkedBuffer &);

virtual	BOOL	Dynamic_ParseRawVRIntoDCM(	LinkedBuffer &, DICOMObject *, UINT StartMode);

virtual	BOOL	Dynamic_ParseDCMIntoRawVR(	DICOMObject *, LinkedBuffer &, UINT StartMode);


CheckedPDU_Service Class

Purpose:

To provide a greater degree of security, and association checks.  This class allows you to specifiy at run-time what application titles, application entities, service classes, and transfer syntaxes to accept on incoming associations.

Theory:

Rather than hard code a series of MyPDU_Service classes (as was previously recommended), this is a general purpose checked PDU_Service.  The parameters for this class are read from a file.  Here is an example file:

#

# DICOM Application / sop / transfer UID list.

#

# This list is used by the CheckedPDU_Service ( "filename" ) service

# class.  All incoming associations will be verified against this

# file.

None	none	RemoteAE

None	none	LocalAE

DICOM	1.2.840.10008.3.1.1.1	application

Verification	1.2.840.10008.1.1	sop

#CRStorage	1.2.840.10008.5.1.4.1.1.1	sop

#CTStorage	1.2.840.10008.5.1.4.1.1.2	sop

#USMutliframeStorage	1.2.840.10008.5.1.4.1.1.3	sop

#MRStorage	1.2.840.10008.5.1.4.1.1.4	sop

#NMStorage	1.2.840.10008.5.1.4.1.1.5	sop

#USStorage	1.2.840.10008.5.1.4.1.1.6	sop

#SCStorage	1.2.840.10008.5.1.4.1.1.7	sop

#StandaloneOverlayStorage	1.2.840.10008.5.1.4.1.1.8	sop

#StandaloneCurveStorage	1.2.840.10008.5.1.4.1.1.9	sop

#StandaloneModalityLUTStorage	1.2.840.10008.5.1.4.1.1.10	sop

#StandaloneVOILUTStorage	1.2.840.10008.5.1.4.1.1.11	sop

#GEMRStorage	1.2.840.113619.4.2	sop

#GECTStorage	1.2.840.113619.4.3	sop

#PatientRootQuery	1.2.840.10008.5.1.4.1.2.1.1	sop

#PatientRootRetrieve	1.2.840.10008.5.1.4.1.2.1.2	sop

#StudyRootQuery	1.2.840.10008.5.1.4.1.2.2.1	sop

#StudyRootRetrieve	1.2.840.10008.5.1.4.1.2.2.2	sop

#PatientStudyOnlyQuery	1.2.840.10008.5.1.4.1.2.3.1	sop

#PatientStudyOnlyRetrieve	1.2.840.10008.5.1.4.1.2.3.2	sop

LittleEndianImplicit	1.2.840.10008.1.2	transfer

#LittleEndianExplicit	1.2.840.10008.1.2.1	transfer

#BigEndianExplicit	1.2.840.10008.1.2.2	transfer

#JPEGBaseLine1	1.2.840.10008.1.2.4.50	transfer LittleEndianImplicit

#JPEGExtended2and4 1.2.840.10008.1.2.4.51	transfer	LittleEndianImplicit

#JPEGExtended3and5 1.2.840.10008.1.2.4.52	transfer	LittleEndianImplicit

#JPEGSpectralNH6and8 1.2.840.10008.1.2.4.53	transfer LittleEndianImplicit

This class is derived from PDU_Service.  All methods/data mebers from PDU_Service that where public, are public here.  In addition there are the following functions:

CheckedPDU_Service ( char *filename)

Constructor.  You can pass in a NULL filename, in which case the CheckedPDU_Service class will behave exactly like PDU_Service.

InitializeFrom(char	*filename)

Read in a new database of sop, transfer, application titles.

ReleaseMemory()

This function clears the current database of sop, transfer, application entities.


Part 3: DICOM Objects

Introduction

VR Class

DICOMObject Class

DICOMCommandObject Class

VR_AE Class

VR_AS Class

VR_AT Class

VR_CS Class

VR_DA Class

VR_DS Class

VR_DT Class

VR_FL Class

VR_FD Class

VR_IS Class

VR_LO Class

VR_LT Class

VR_OB Class

VR_OW Class

VR_PN Class

VR_SH Class

VR_SL Class

VR_SQ Class

VR_SS Class

VR_ST Class

VR_TM Class

VR_UI Class

VR_UL Class

VR_US Class

VR_XS Class

VR_OX Class

RTC Class

Normalized Complex Object Classes

Composite Complex Object Classes


Introduction

VR Value Representation

A VR is the most basic form of an object of a DICOM object.  A VR consists of a unique Group / Element code, a length field, a type code, and the actual data.  Chapter 6 of the DICOM standard defines a "Data Dictionary".  This dictionary assigns attributes of patient demographics, image information, etc., a common Group / Element code.  (For instance, the patient name is given Group = 0x0010 and Element = 0x0010).  This implementation uses a base class "VR" for a common VR class.

IOD Information Object Definition

DICOM defines a set of data structures termed the IOD”, for Information Object Defination.  These data structures come in two forms: normalized, and composite.  There is high level support for all DICOM Part 3 IOD modules.  This support comes in two forms:

CO”	for Complex Object (corresponding to Normalized Objects)

CCO” for Composite Complex Object (corresponding to Composite Objects)

The following is an Example of a Composite Object defination:

class	CTImageIODModule	:

public	CCO_AbstractClass

{

public:

CO_PatientModule	PatientModule;

CO_StudyModule	StudyModule;

};

The following is an example of a Normalized (Complex) object:

class	CO_PatientModule	:

public	CO_AbstractClass

{

public:

VR_PN	PatientsName;

VR_DA	PatientBirthdate;

.

.

.

};

This sort of access / class structure we define as "Complex Object support".  To understand the contrast (low-level object), one needs to understand how DICOM actually communicates data structures.  DICOM defines a VR data dictionary (chapter 6 of the DICOM standard).  This VR syntax assigns a unique Group / Element tag number for every VR field.  Therefore, one can think of a complex IOD being built up from several smaller unique VRs.  Hence, these two (given proper initial conditions of the data) are equivalent:

CTImageIODModule	CTImage;

DICOMDataObject	DDO;

char	s[128];

1)

CTImage.PatientModule.PatientsName.VMGet(0, s);

2)

memset( (void*) s, 0, 128);

memcpy((void*) s,

(void*) DDO.GetVR(0x0010, 0x0010)->Data,

(DDO.GetVR(0x0010, 0x0010)->Length);

The first method is not only more readable, but has the added advantage of supporting value-multiplicity (multiple entries per VR).  This VM support can be achieved with the first method, but requires several more lines of code.

Obviously, the first one is more readable, but is it more usable?  (Do we even need two views of the data?)  Well, here is where Chapter 8 of the DICOM standard comes to play.  When you physically transfer an IOD over a network link a DICOM transport must order the VR objects in acending group, and acending element order.  This means every DICOM transmission starts with the lowest tag, and ends with the highest tag of an IOD.  Hence, the "Complex View" does not work well for actual transmission.  Thus, the PDU_Service class only understands how to Read / Write low-level DICOM objects.

What is a low-level object?  There are two kinds of low-level DICOM objects:

DICOMCommandObject

DICOMDataObject

Really these are the same thing.  They are both derived from a base class "DICOMObject".  Henceforth we will use DICOMObject to mean both DICOMCommandObject, and DICOMDataObject.

A DICOMObject is a data structure that exists in two states.  The first state is "Unpackaged" and the second is "Packaged".  Basically, an object must be "packaged" before it can be transmitted over a network link.  It must be "unpackaged" while you add VRs to it.  How do you know what state it is in?  A DICOMObect initially is unpackaged.  So long as you are Push()'ing VR's (or other DICOMObjects) onto it, it remains unpackaged.  As soon as you try and Pop() an object from the DICOMObject, it becomes packaged, and will remain so until you Pop() the last object, at which time it will again become unpackaged.

Why two states?  Internally the object exists in two different data structures.  The first is as an array of pointers to priority queues.  The second is as an array of priority queues of priority queues.

Sequence Objects

Sequences are an unfortunate complexity to the DICOM standard.  This version of the DICOM transport protocol supports sequences as "Embedded DICOM Objects".  You create a sequence object by creating a second DICOMObject, and then Push()'ing it onto the first object.  For example:

DICOMDataObject	*DDO, *EDDO;

DDO = new DICOMDataObject;

DDO->Push(new VR(0x0010, 0x0010, 0, FALSE) );

DDO->Push(new VR(0x0010, 0x0020, 0, FALSE) );

EDDO = new DICOMDataObject;

EDDO->Push(new VR(0x0008, 0x0002, 0, FALSE) );

DDO->Push( EDDO );

DDO->Push(new VR(0x0010, 0x0030, 0, FALSE) );

What's gone on is you've "embedded" a DICOMObject inside another DICOMObject.  This is how sequence elements are handled.  Now, how to retrieve them:

void

PrintElements(DICOMObject	*DO)

{

UINT	Index;

Array < DICOMObject *> 	*ArrayPtr;

VR	*vr;

while ( vr = DO->Pop() )

{

PrintVR ( vr );

if (vr->SQObjectArray)

{

Index = 0;

ArrayPtr = (Array<DICOMObject *> *)

vr->SQObjectArray;

while ( Index < ArrayPtr->GetSize())

{

PrintElements (ArrayPtr->Get(Index));

++Index;

}

}

delete vr;

}

}

Currently, sequence objects are stored in an array inside the last VR pushed onto the DICOMObject.  I'd appreciate some feedback from users on whether you like this approach, and if not, how you might want to see it implemented.  I find it reasonable, but in many ways an ad-hoc hack.

A note on TCP/IP transporting:  Currently this protocol encodes sequence objects using (0xfffe, 0xe000) with an explicit length code.  Incoming sequences that are explicit or implicit lengths are supported.  Any level of depth of sequence objects is supported, both in the DICOMObject class, and in the PDU_Service transport class.

Caveats

Currently the DICOMObject class stores internally length codes which are hard coded to Implicit Little Endian transfer syntax.  In the future this will become a programmable feature (via a SetVROverhead() call), but this call returns FALSE in this alpha release.


VR Class

Purpose:

Provides a non-pure abstract class which stores the base level data of any DICOM object.

Theory:

Currently maintains the group, element, length and data portions of a value representation.  Support is not yet implemented for TypeCodes.  De-allocation of the data portion is programmable.  Stored inside each VR is a pointer to a sequence DICOMObject array.  This is to support sequence (embedded) objects.

Interface:

UINT16	Group

Group code for the VR.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR.  (always even numbered).

void	*Data

Pointer the data for the VR.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type (US, AE, etc).  Currently this value is not used.

VR ( UINT16, UINT16, UINT32, BOOL )

Create a VR with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR ( UINT16, UINT16, UINT32, void * )

Create a VR, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR ()

Create an empty VR.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR's Group / Element with another.

<

Operator.  Compares one VR's Group / Element with another.

==

Operator.  Compares one VR's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR from the VR passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.


DICOMObject Class

Purpose:

Provides the base class support for DICOMCommandObject and DICOMDataObject.

Theory:

A complex object that exists in two data structures.  The first is as an array of pointers to priority queues.  The second is of a priority queue.

Interface:

UINT32	Length

Length of the entire DICOM object.

BOOL	Push ( VR * )

Add a VR to the object.

BOOL	Push ( DICOMObject * )

Add a sequence (embedded) DICOMObject at the place of the last Push'ed VR.

VR	*Pop ()

Remove a VR from the object.

LE_UINT16	GetUINT16 ( UINT16, UINT16 )

Obtain the value of a US VR from inside the object.  The object must be unpackaged,, (i.e., not yet Pop()'ed).  The value returned is a Little-Endian data type.

VR	*GetVR ( UINT16, UINT16 )

Obtain a pointer to a VR inside the object.  The object must not be packaged.

BOOL	Reset()

Resets (clears) a DICOMObject.  Useful for servers, etc.


DICOMCommandObject Class

Purpose:

Provides a storage mechanism for DICOM Command messages (those with Group codes of 0x0000).

Theory:

See DICOMObject Class


DICOMDataObject Class

Purpose:

Provides a storage mechanism for DICOM data messages (those with group codes not equal to 0x0000).

Theory:

See DICOMObject Class


VR_AE Class

Purpose:

Provides a high level VR which supports the AE VR data type.  The AE VR holds strings (of 16 bytes or less) which contain an Application Entity name.  Examples are MYAE”.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_AE.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_AE.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_AE.  (always even numbered).

void	*Data

Pointer the data for the VR_AE.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_AE should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type AE”.

VR_AE ( UINT16, UINT16, UINT32, BOOL )

Create a VR_AE with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_AE ( UINT16, UINT16, UINT32, void * )

Create a VR_AE, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_AE ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_AE and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_AE ()

Create an empty VR_AE.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_AE()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_AE's Group / Element with another.

<

Operator.  Compares one VR_AE's Group / Element with another.

==

Operator.  Compares one VR_AE's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_AE back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_AE from the VR_AE passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the AE class.

BOOL	Get(char *)

Gets the data of the AE class.

BOOL	Set(UINT, char *)

Sets the data in VM position (0 based).

BOOL	Get(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (AE)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_AS Class

Purpose:

Provides a high level VR which supports the AS VR data type.  The AS class is a VR which holds fixed length strings (4 letters each) which hold an encoding of an age.  For instnace, 001M (1 Month), or 045Y (45 years).

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_AS.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_AS.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_AS.  (always even numbered).

void	*Data

Pointer the data for the VR_AS.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_AS should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type AS”.

VR_AS ( UINT16, UINT16, UINT32, BOOL )

Create a VR_AE with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_AS ( UINT16, UINT16, UINT32, void * )

Create a VR_AE, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_AS ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_AS and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_AS ()

Create an empty VR_AS.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_AS()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_AS's Group / Element with another.

<

Operator.  Compares one VR_AS's Group / Element with another.

==

Operator.  Compares one VR_AS's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_AS back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_AS from the VR_AS passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the AS class.

BOOL	Get(char *)

Gets the data of the AS class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (AS)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_AT Class

Purpose:

Provides a high level VR which supports the AT VR data type.  The AT datatype holds two 16 bit unsigned integers that hold a group, and element tag (respectivelly).

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_AT.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_AT.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_AT.  (always even numbered).

void	*Data

Pointer the data for the VR_AT.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_AT should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type AT”.

VR_AT ( UINT16, UINT16, UINT32, BOOL )

Create a VR_AE with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_AT ( UINT16, UINT16, UINT32, void * )

Create a VR_AE, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_AT ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_AT and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_AT ()

Create an empty VR_AT.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_AT()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_AT's Group / Element with another.

<

Operator.  Compares one VR_AT's Group / Element with another.

==

Operator.  Compares one VR_AT's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_AT back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_AT from the VR_AT passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the AT class.

BOOL	Get(void *)

Gets the data of the AT class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (AT)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_CS Class

Purpose:

Provides a high level VR which supports the CS VR data type.  The CS VR holds strings (of 16 bytes or less).

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_CS.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_CS.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_CS.  (always even numbered).

void	*Data

Pointer the data for the VR_CS.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_CS should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type CS”.

VR_CS ( UINT16, UINT16, UINT32, BOOL )

Create a VR_CS with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_CS ( UINT16, UINT16, UINT32, void * )

Create a VR_CS, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_CS ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_CS and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_CS ()

Create an empty VR_CS.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_CS()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_CS's Group / Element with another.

<

Operator.  Compares one VR_CS's Group / Element with another.

==

Operator.  Compares one VR_CS's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_CS back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_CS from the VR_CS passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the CS class.

BOOL	Get(char *)

Gets the data of the CS class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (CS)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_DA Class

Purpose:

Provides a high level VR which supports the DA VR data type.  The DA VR holds  encoded dates.  Examples are 19950913” for September 13th, 1995.  The VR_DA class is backward compatible with older style ACR-NEMA date encodings (princply, things such as 1995.09.13).   The VR_DA class will accept incoming data of the older form, but will always return the newer form.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_DA.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_DA.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_DA.  (always even numbered).

void	*Data

Pointer the data for the VR_DA.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_DA should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type DA”.

VR_DA ( UINT16, UINT16, UINT32, BOOL )

Create a VR_DA with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_DA ( UINT16, UINT16, UINT32, void * )

Create a VR_DA, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_DA ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_DA and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_DA ()

Create an empty VR_DA.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_DA()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_DA's Group / Element with another.

<

Operator.  Compares one VR_DA's Group / Element with another.

==

Operator.  Compares one VR_DA's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_DA back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_DA from the VR_DA passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the DA class.

BOOL	Get(char *)

Gets the data of the DA class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (DA)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_DS Class

Purpose:

Provides a high level VR which supports the DS VR data type.  The DS VR holds decimal strings (of 16 bytes or less).

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_DS.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_DS.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_DS.  (always even numbered).

void	*Data

Pointer the data for the VR_DS.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_DS should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type DS”.

VR_DS ( UINT16, UINT16, UINT32, BOOL )

Create a VR_DS with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_DS ( UINT16, UINT16, UINT32, void * )

Create a VR_DS, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_DS ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_DS and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_DS ()

Create an empty VR_DS.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_DS()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_DS's Group / Element with another.

<

Operator.  Compares one VR_DS's Group / Element with another.

==

Operator.  Compares one VR_DS's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_DS back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_DS from the VR_DS passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the DS class.

BOOL	Get(char *)

Gets the data of the DS class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (DS)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_DT Class

Purpose:

Provides a high level VR which supports the DT VR data type.  The DT VR holds decimal strings (of 16 bytes or less).

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_DT.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_DT.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_DT.  (always even numbered).

void	*Data

Pointer the data for the VR_DT.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_DT should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type DT”.

VR_DT ( UINT16, UINT16, UINT32, BOOL )

Create a VR_DT with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_DT ( UINT16, UINT16, UINT32, void * )

Create a VR_DT, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_DT ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_DT and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_DT ()

Create an empty VR_DT.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_DT()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_DT's Group / Element with another.

<

Operator.  Compares one VR_DT's Group / Element with another.

==

Operator.  Compares one VR_DT's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_DT back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_DT from the VR_DT passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the DT class.

BOOL	Get(char *)

Gets the data of the DT class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (DT)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_FL Class

Purpose:

Provides a high level VR which supports the FL VR data type.  The FL VR holds floating point fixed single precision numbers (4 bytes each).  The format is IEEE 754:1985.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_FL.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_FL.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_FL.  (always even numbered).

void	*Data

Pointer the data for the VR_FL.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_FL should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type FL”.

VR_FL ( UINT16, UINT16, UINT32, BOOL )

Create a VR_FL with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_FL ( UINT16, UINT16, UINT32, void * )

Create a VR_FL, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_FL ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_FL and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_FL ()

Create an empty VR_FL.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_FL()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_FL's Group / Element with another.

<

Operator.  Compares one VR_FL's Group / Element with another.

==

Operator.  Compares one VR_FL's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_FL back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_FL from the VR_FL passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the FL class.

BOOL	Get(void *)

Gets the data of the FL class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (FL)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_FD Class

Purpose:

Provides a high level VR which supports the FD VR data type.  The FD VR holds floating point fixed double precision numbers (8 bytes each).  The format is IEEE 754:1985.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_FD.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_FD.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_FD.  (always even numbered).

void	*Data

Pointer the data for the VR_FD.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_FD should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type FD”.

VR_FD ( UINT16, UINT16, UINT32, BOOL )

Create a VR_FD with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_FD ( UINT16, UINT16, UINT32, void * )

Create a VR_FD, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_FD ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_FD and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_FD ()

Create an empty VR_FD.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_FD()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_FD's Group / Element with another.

<

Operator.  Compares one VR_FD's Group / Element with another.

==

Operator.  Compares one VR_FD's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_FD back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_FD from the VR_FD passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the FD class.

BOOL	Get(void *)

Gets the data of the FD class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (FD)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_IS Class

Purpose:

Provides a high level VR which supports the IS VR data type.  The IS VR holds integer strings (of 12 bytes or less).

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_IS.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_IS.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_IS.  (always even numbered).

void	*Data

Pointer the data for the VR_IS.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_IS should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type IS”.

VR_IS ( UINT16, UINT16, UINT32, BOOL )

Create a VR_IS with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_IS ( UINT16, UINT16, UINT32, void * )

Create a VR_IS, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_IS ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_IS and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_IS ()

Create an empty VR_IS.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_IS()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_IS's Group / Element with another.

<

Operator.  Compares one VR_IS's Group / Element with another.

==

Operator.  Compares one VR_IS's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_IS back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_IS from the VR_IS passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the IS class.

BOOL	Get(char *)

Gets the data of the IS class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (IS)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_LO Class

Purpose:

Provides a high level VR which supports the LO VR data type.  The LO VR holds text (up to 64 bytes).  The charactor \ may not be present in the string.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_LO.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_LO.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_LO.  (always even numbered).

void	*Data

Pointer the data for the VR_LO.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_LO should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type LO”.

VR_LO ( UINT16, UINT16, UINT32, BOOL )

Create a VR_LO with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_LO ( UINT16, UINT16, UINT32, void * )

Create a VR_LO, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_LO ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_LO and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_LO ()

Create an empty VR_LO.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_LO()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_LO's Group / Element with another.

<

Operator.  Compares one VR_LO's Group / Element with another.

==

Operator.  Compares one VR_LO's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_LO back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_LO from the VR_LO passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the LO class.

BOOL	Get(char *)

Gets the data of the LO class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (LO)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_LT Class

Purpose:

Provides a high level VR which supports the LT VR data type.  The LT VR holds text (up to 10240 bytes).  The charactor \ may be used, but the VMSet() call may not.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_LT.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_LT.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_LT.  (always even numbered).

void	*Data

Pointer the data for the VR_LT.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_LT should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type LT”.

VR_LT ( UINT16, UINT16, UINT32, BOOL )

Create a VR_LT with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_LT ( UINT16, UINT16, UINT32, void * )

Create a VR_LT, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_LT ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_LT and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_LT ()

Create an empty VR_LT.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_LT()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_LT's Group / Element with another.

<

Operator.  Compares one VR_LT's Group / Element with another.

==

Operator.  Compares one VR_LT's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_LT back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_LT from the VR_LT passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the LT class.

BOOL	Get(char *)

Gets the data of the LT class.

UINT16	GetTypeCode ()

Gets the run time type of this VR (LT)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_OB Class

Purpose:

Provides a high level VR which supports the OB VR data type.  The OB VR holds bytes.  No \ is present since this is a binary VR type.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_OB.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_OB.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_OB.  (always even numbered).

void	*Data

Pointer the data for the VR_OB.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_OB should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type OB”.

VR_OB ( UINT16, UINT16, UINT32, BOOL )

Create a VR_OB with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_OB ( UINT16, UINT16, UINT32, void * )

Create a VR_OB, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_OB ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_OB and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_OB ()

Create an empty VR_OB.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_OB()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_OB's Group / Element with another.

<

Operator.  Compares one VR_OB's Group / Element with another.

==

Operator.  Compares one VR_OB's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_OB back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_OB from the VR_OB passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the OB class.

BOOL	Get(void *)

Gets the data of the OB class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (OB)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_OW Class

Purpose:

Provides a high level VR which supports the OW VR data type.  The OW VR holds words (unsigned 16 bit integers).  No \ is present since this is a binary VR type.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_OW.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_OW.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_OW.  (always even numbered).

void	*Data

Pointer the data for the VR_OW.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_OW should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type OW”.

VR_OW ( UINT16, UINT16, UINT32, BOOL )

Create a VR_OW with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_OW ( UINT16, UINT16, UINT32, void * )

Create a VR_OW, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_OW ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_OW and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_OW ()

Create an empty VR_OW.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_OW()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_OW's Group / Element with another.

<

Operator.  Compares one VR_OW's Group / Element with another.

==

Operator.  Compares one VR_OW's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_OW back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_OW from the VR_OW passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the OW class.

BOOL	Get(void *)

Gets the data of the OW class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (OW)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_PN Class

Purpose:

Provides a high level VR which supports the PN VR data type.  The PN VR holds patient names (up to 64 byts each).  This class has an algoritham behind it which will transform human-readable names into ANSI MSDS.  The algoritham has a number of different states which are to specific to mention here.  If there is an encoding of a name which this class does not handle, please email me a few examples.  I will try and integrate it.  Note the names going into and out of this VR should be normal human-readable names.  The VR_PN data type will always store the names as ANSI.

The algoritham can be overridded by parsing the name into ANSI form yourself.  Simply pass an ANSI name (with ^s in it), and the algoritham is disabled.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_PN.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_PN.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_PN.  (always even numbered).

void	*Data

Pointer the data for the VR_PN.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_PN should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type PN”.

VR_PN ( UINT16, UINT16, UINT32, BOOL )

Create a VR_PN with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_PN ( UINT16, UINT16, UINT32, void * )

Create a VR_PN, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_PN ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_PN and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_PN ()

Create an empty VR_PN.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_PN()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_PN's Group / Element with another.

<

Operator.  Compares one VR_PN's Group / Element with another.

==

Operator.  Compares one VR_PN's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_PN back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_PN from the VR_PN passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the PN class.

BOOL	Get(char *)

Gets the data of the PN class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (PN)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_SH Class

Purpose:

Provides a high level VR which supports the SH VR data type.  The SH VR holds short strings up to 16 bytes.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_SH.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_SH.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_SH.  (always even numbered).

void	*Data

Pointer the data for the VR_SH.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_SH should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type SH”.

VR_SH ( UINT16, UINT16, UINT32, BOOL )

Create a VR_SH with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_SH ( UINT16, UINT16, UINT32, void * )

Create a VR_SH, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_SH ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_SH and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_SH ()

Create an empty VR_SH.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_SH()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_SH's Group / Element with another.

<

Operator.  Compares one VR_SH's Group / Element with another.

==

Operator.  Compares one VR_SH's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_SH back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_SH from the VR_SH passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the SH class.

BOOL	Get(char *)

Gets the data of the SH class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (SH)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_SL Class

Purpose:

Provides a high level VR which supports the SL VR data type.  The SL VR holds 32 bit signed long integers.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_SL.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_SL.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_SL.  (always even numbered).

void	*Data

Pointer the data for the VR_SL.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_SL should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type SL”.

VR_SL ( UINT16, UINT16, UINT32, BOOL )

Create a VR_SL with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_SL ( UINT16, UINT16, UINT32, void * )

Create a VR_SL, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_SL ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_SL and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_SL ()

Create an empty VR_SL.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_SL()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_SL's Group / Element with another.

<

Operator.  Compares one VR_SL's Group / Element with another.

==

Operator.  Compares one VR_SL's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_SL back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_SL from the VR_SL passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the SL class.

BOOL	Get(void *)

Gets the data of the SL class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (SL)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_SQ Class

Purpose:

Provides a high level VR which supports the SQ VR data type.  The SQ VR is a place holder for an object which contains an array of DICOM objects (sequences).  This

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_SQ.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_SQ.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_SQ.  (always even numbered).

void	*Data

Pointer the data for the VR_SQ.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_SQ should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type SQ”.

VR_SQ ( UINT16, UINT16, UINT32, BOOL )

Create a VR_SQ with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_SQ ( UINT16, UINT16, UINT32, void * )

Create a VR_SQ, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_SQ ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_SQ and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_SQ ()

Create an empty VR_SQ.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_SQ()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_SQ's Group / Element with another.

<

Operator.  Compares one VR_SQ's Group / Element with another.

==

Operator.  Compares one VR_SQ's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_SQ back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_SQ from the VR_SQ passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.


VR_SS Class

Purpose:

Provides a high level VR which supports the SS VR data type.  The SS VR holds signed 16 bit integers.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_SS.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_SS.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_SS.  (always even numbered).

void	*Data

Pointer the data for the VR_SS.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_SS should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type SS”.

VR_SS ( UINT16, UINT16, UINT32, BOOL )

Create a VR_SS with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_SS ( UINT16, UINT16, UINT32, void * )

Create a VR_SS, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_SS ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_SS and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_SS ()

Create an empty VR_SS.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_SS()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_SS's Group / Element with another.

<

Operator.  Compares one VR_SS's Group / Element with another.

==

Operator.  Compares one VR_SS's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_SS back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_SS from the VR_SS passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the SS class.

BOOL	Get(void *)

Gets the data of the SS class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (SS)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_ST Class

Purpose:

Provides a high level VR which supports the ST VR data type.  The ST VR holds text (up to 1024 bytes).  The charactor \ may be used, but the VMSet() call may not.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_ST.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_ST.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_ST.  (always even numbered).

void	*Data

Pointer the data for the VR_ST.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_ST should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type ST”.

VR_ST ( UINT16, UINT16, UINT32, BOOL )

Create a VR_ST with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_ST ( UINT16, UINT16, UINT32, void * )

Create a VR_ST, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_ST ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_ST and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_ST ()

Create an empty VR_ST.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_ST()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_ST's Group / Element with another.

<

Operator.  Compares one VR_ST's Group / Element with another.

==

Operator.  Compares one VR_ST's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_ST back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_ST from the VR_ST passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the ST class.

BOOL	Get(char *)

Gets the data of the ST class.

UINT16	GetTypeCode ()

Gets the run time type of this VR (ST)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_TM Class

Purpose:

Provides a high level VR which supports the TM VR data type.  The TM VR holds time strings of the form hhmmss.frac.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_TM.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_TM.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_TM.  (always even numbered).

void	*Data

Pointer the data for the VR_TM.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_TM should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type TM”.

VR_TM ( UINT16, UINT16, UINT32, BOOL )

Create a VR_TM with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_TM ( UINT16, UINT16, UINT32, void * )

Create a VR_TM, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_TM ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_TM and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_TM ()

Create an empty VR_TM.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_TM()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_TM's Group / Element with another.

<

Operator.  Compares one VR_TM's Group / Element with another.

==

Operator.  Compares one VR_TM's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_TM back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_TM from the VR_TM passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the TM class.

BOOL	Get(char *)

Gets the data of the TM class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (TM)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_UI Class

Purpose:

Provides a high level VR which supports the UI VR data type.  The UI VR holds unique identifiers.

Theory:

This class is derived from the base typeless VR class.

Interface:

UINT16	Group

Group code for the VR_UI.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_UI.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_UI.  (always even numbered).

void	*Data

Pointer the data for the VR_UI.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_UI should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type UI”.

VR_UI ( UINT16, UINT16, UINT32, BOOL )

Create a VR_UI with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_UI ( UINT16, UINT16, UINT32, void * )

Create a VR_UI, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_UI ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_UI and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_UI ()

Create an empty VR_UI.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_UI()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_UI's Group / Element with another.

<

Operator.  Compares one VR_UI's Group / Element with another.

==

Operator.  Compares one VR_UI's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_UI back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_UI from the VR_UI passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(char *)

Sets the data of the UI class.

BOOL	Get(char *)

Gets the data of the UI class.

BOOL	VMSet(UINT, char *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, char *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (UI)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_UL Class

Purpose:

Provides a high level VR which supports the UL VR data type.  The UL VR holds unsigned long 32 bit integers.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_UL.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_UL.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_UL.  (always even numbered).

void	*Data

Pointer the data for the VR_UL.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_UL should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type UL”.

VR_UL ( UINT16, UINT16, UINT32, BOOL )

Create a VR_UL with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_UL ( UINT16, UINT16, UINT32, void * )

Create a VR_UL, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_UL ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_UL and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_UL ()

Create an empty VR_UL.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_UL()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_UL's Group / Element with another.

<

Operator.  Compares one VR_UL's Group / Element with another.

==

Operator.  Compares one VR_UL's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_UL back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_UL from the VR_UL passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the UL class.

BOOL	Get(void *)

Gets the data of the UL class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (UL)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_US Class

Purpose:

Provides a high level VR which supports the US VR data type.  The US VR holds unsigned short 16 integers.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_US.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_US.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_US.  (always even numbered).

void	*Data

Pointer the data for the VR_US.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_US should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type US”.

VR_US ( UINT16, UINT16, UINT32, BOOL )

Create a VR_US with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NUSL).

VR_US ( UINT16, UINT16, UINT32, void * )

Create a VR_US, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_US ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_US and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_US ()

Create an empty VR_US.  Data = NUSL, Group = 0, Element = 0, Length = 0.

~VR_US()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_US's Group / Element with another.

<

Operator.  Compares one VR_US's Group / Element with another.

==

Operator.  Compares one VR_US's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_US back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_US from the VR_US passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the US class.

BOOL	Get(void *)

Gets the data of the US class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (US)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_XS Class

Purpose:

Provides a high level VR which supports the XS VR data type.  The XS VR holds signed/unsigned short 16 integers.  This VR is run-time configurable to be a US or SS data type.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_XS.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_XS.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_XS.  (always even numbered).

void	*Data

Pointer the data for the VR_XS.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_XS should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type US” or SS”.

VR_XS ( UINT16, UINT16, UINT32, BOOL )

Create a VR_XS with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_XS ( UINT16, UINT16, UINT32, void * )

Create a VR_XS, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_XS ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_XS and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_XS ()

Create an empty VR_XS.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_XS()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_XS's Group / Element with another.

<

Operator.  Compares one VR_XS's Group / Element with another.

==

Operator.  Compares one VR_XS's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_XS back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_XS from the VR_XS passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the XS class.

BOOL	Get(void *)

Gets the data of the XS class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (US or SS)

BOOL	SetTypeCode (UINT16)

Gets the run time type of this VR (US or SS)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


VR_OX Class

Purpose:

Provides a high level VR which supports the OX VR data type.  The OX VR holds signed/unsigned short 16 integers.  This VR is run-time configurable to be a US or SS data type.

Theory:

This class is derived from the base typeless VR class.  This class will perform endian-swapping to / from the native architecture of the machine.  The arguments passed into / out-of it should be of native form.

Interface:

UINT16	Group

Group code for the VR_OX.  See Chapter 6: DICOM v3 draft.

UINT16	Element

Element code for the VR_OX.  See Chapter 6: DICOM v3 draft.

UINT32	Length

Length code for the VR_OX.  (always even numbered).

void	*Data

Pointer the data for the VR_OX.

BOOL	ReleaseMemory

Flag that indicates whether the destructor of the VR_OX should delete the member pointed to by data.

void	*SQObjectArray

Pointer to a (potential) array of sequenced DICOMObjects.  This value should be checked for any embedded DICOMObject.  Checking involves casting it to a type of Array < DICOMObject * > *.

UINT16	TypeCode

Value holding a 16 bit code for the VR type US” or SS”.

VR_OX ( UINT16, UINT16, UINT32, BOOL )

Create a VR_OX with code Group / Element, and Length.  The last parameter is a boolean operator.  TRUE indicates memory will be allocated (data will be valid), or FALSE, (data will be NULL).

VR_OX ( UINT16, UINT16, UINT32, void * )

Create a VR_OX, and mark the ReleaseMemory flag as TRUE, and set the data member to the value passed in as a parameter.

VR_OX ( UINT16, UINT16, UINT32, void *, BOOL )

Create a VR_OX and mark the ReleaseMemory flag to the BOOL parameter.  Set the data member to the void * parameter.

VR_OX ()

Create an empty VR_OX.  Data = NULL, Group = 0, Element = 0, Length = 0.

~VR_OX()

Destroy the VR and release memory associated with sequence objects, and delete the data section according to the ReleaseMemory flag.

>

Operator.  Compares one VR_OX's Group / Element with another.

<

Operator.  Compares one VR_OX's Group / Element with another.

==

Operator.  Compares one VR_OX's Group / Element with another.

BOOL	Reset()

Clears (resets) a VR_OX back to its initalized state.  Does not change the Group / Element data members.

BOOL	SetIf(VR	*vr)

Sets the VR_OX from the VR_OX passed in as a parameter, if the group/element codes are the same.  A return of TRUE from this call means the passed in VR has been delete”ed.  You should only pass in VRs allocated with new” to this function.

BOOL	Morph(DICOMObject	*)

If the Valid” data member is TRUE, then the current VR is put into the DICOMObject passed in as a parameter.  Note this function, and the previous are a prelude to Complex-Object support.  In every day use you should not need to use them.

BOOL	Set(void *)

Sets the data of the OX class.

BOOL	Get(void *)

Gets the data of the OX class.

BOOL	VMSet(UINT, void *)

Sets the data in VM position (0 based).

BOOL	VMGet(UINT, void *)

Gets the data in VM position (0 based).

UINT16	GetTypeCode ()

Gets the run time type of this VR (US or SS)

BOOL	SetTypeCode (UINT16)

Gets the run time type of this VR (US or SS)

UINT32	GetSetSize ()

Returns the fixed size (if any) of this data element.  For variable length VR types, this procedure returns 0.


RTC Class

Purpose:

Run-Time-Classing of VR elements.  This allows one to lookup a Group, Element pair, and obtain the description, and type-code for a VR.

Theory:

Interface:

An RTC database is loaded from a text file.  This file has the following format:

{ 0x0000, 0x0000, 'UL', "Group 0000 Length" },

{ 0x0000, 0x0001, 'UL', "Group 0000 Length to End (RET)" },

{ 0x0000, 0x0002, 'UI', "Affected SOP Class UID" },

{ 0x0000, 0x0003, 'UI', "Requested SOP Class UID" },

{ 0x0000, 0x0010, 'SH', "Recognition Code (RET)" },

.

.

.

Blank, or incomplete lines are ignored.  This file has the same format as the file that can be found on: ftp://zippy.nih.gov/pub/nihimage/documents/dicom-dict.txt

RTC (BOOL = TRUE, char * = NULL)

Constructor.  The first aurgument is a flag for Carry Descriptions”.  This allows you to specify whether the RTC should store (and allocate memorry for) descriptions of VR codes.  In certain instances where you want to conserve memory, set this flag to FALSE.  The second argument is the filename to load.  Both arguments need not be supplied.

~RTC ()

Destructor.

BOOL	AttachRTC (char	*filename)

Load an RTC database.

BOOL	DetachRTC ()

Clear the RTC database.

BOOL	RunTimeClass(DICOMObject	*)

Type-code all known VRs in the DICOMObject.  Note, all VR points will be changed in the DICOMObject.  Hence, old VR points will be invalid.

BOOL	RunTimeClass(VR	*)

Type-code a VR.

UINT16	RunTimeClass(UINT16, UINT16, char *)

Look up a group/element pair, and obtain the type-code, and (if the char * is non-NULL), the description of the group/element.  A value of 0 will be returned if the VR is not known.


Normalized Complex Object Classes

Normalized objects are representations of single IOD descriptions from Part 3 of the DICOM standard.  The class descriptions that follow are abbreviations.  To read them transform each line:

CO_PatientRelationshipModule

SQ	ReferencedVisitSequence	0x0008	0x1125

Into:

class	CO_PatientRelationshipModule	:

public	CO_Abstract

{

public:

VR_SQ	ReferencedVisitSequence;

.

.

.

public:

BOOL	Set ( DICOMDataObject * );

DICOMDataObject	*Get ();

BOOL	Reset ();

};

The procedure Set () will take only the elements defined in the module description below, and remove them from the DICOMDataObject.

The procedure Get () will return a DICOMDataObject from only the defined (used) elements from the description below.

The procedure Reset () will reset the Normalized object back to the initial state.


CO_PatientRelationshipModule

// C.2.1

SQ	ReferencedVisitSequence	0x0008	0x1125

SQ	ReferencedStudySequence	0x0008	0x1110

SQ	ReferencedPatientAliasSOPInstanceUIDs	0x0038	0x0004

end


CO_ReferencedVisitSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_ReferencedPatientAliasSOPInstanceUIDs

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_PatientIdentificationModule

// C.2.2

PN	PatientsName	0x0010	0x0010

LO	PatientID	0x0010	0x0020

LO	IssuerOfPatientID	0x0010	0x0021

LO	OtherPatientIDs	0x0010	0x1000

PN	OtherPatientNames	0x0010	0x1001

PN	PatientsMaidenName	0x0010	0x1005

PN	PatientsMothersMaidenName	0x0010	0x1060

LO	MedicalRecordLocator	0x0010	0x1090

end


CO_PatientDemographicModule

// C.2.3

LO	PatientsAddress	0x0010	0x1040

LO	RegionOfResidence	0x0010	0x2152

LO	CountryOfResidence	0x0010	0x2150

SH	PatientsTelephoneNumbers	0x0010	0x2154

DA	PatientsBirthDate	0x0010	0x0030

TM	PatientsBirthTime	0x0010	0x0032

SH	EthnicGroup	0x0010	0x2160

CS	PatientsSex	0x0010	0x0040

DS	PatientsSize	0x0010	0x1020

DS	PatientsWeight	0x0010	0x1030

LO	MilitaryRank	0x0010	0x1080

LO	BranchOfService	0x0010	0x1081

SQ	PatientsInsurencePlanCodeSequence	0x0010	0x0050

LO	PatientsRelgiousPreference	0x0010	0x21f0

LT	PatientComments	0x0010	0x4000

end


CO_PatientsInsurencePlanCodeSequence

SH	CodeValue	0x0008	0x0100

SH	CodingSchemeDesignator	0x0008	0x0102

LO	CodeMeaning	0x0008	0x0104

end


CO_PatientMedicalModule

// C.2.4

LO	PatientState	0x0038	0x0500

US	PregnancyStatus	0x0010	0x21c0

LO	MedicalAlerts	0x0010	0x2000

LO	ContrastAllergies	0x0010	0x2110

LO	SpecialNeeds	0x0038	0x0050

DA	LastMenstrualDate	0x0010	0x21d0

CS	SmokingStatus	0x0010	0x21a0

LT	AdditionalPatientHistory	0x0010	0x21b0

end


CO_VisitRelationshipModule

// C.3.1

SQ	ReferencedStudySequence	0x0008	0x1110

SQ	ReferencedPatientSequence	0x0008	0x1120

end


CO_VisitIdentificationModule

// C.3.2

LO	InsitutionName	0x0008	0x0080

ST	InsitutionAddress	0x0008	0x0081

SQ	InsitutionCodeSequence	0x0008	0x0082

LO	AdmissionID	0x0038	0x0010

LO	IssuerOfAdmissionID	0x0038	0x0011

end


CO_InsitutionCodeSequence

SH	CodeValue	0x0008	0x0100

SH	CodingSchemeDesignator	0x0008	0x0102

LO	CodeMeaning	0x0008	0x0104

end


CO_VisitStatusModule

// C.3.3

CS	VisitStatusID	0x0038	0x0008

LO	CurrentPatientLocation	0x0038	0x0300

LO	PatientsInsitionResidence	0x0038	0x0400

LT	VisitComments	0x0038	0x4000

end


CO_VisitAdmissionModule

// C.3.4

DA	AdmittingDate	0x0038	0x0020

TM	AdmittingTime	0x0038	0x0021

LO	RouteOfAdmissions	0x0038	0x0016

LO	AdmittingDiagnosisDescription	0x0008	0x1080

SQ	AdmittingDiagnosisCodeSequence	0x0008	0x1084

PN	ReferringPhysiciansName	0x0008	0x0090

ST	ReferringPhysiciansAddress	0x0008	0x0092

SH	ReferringPhysiciansPhoneNumbers	0x0008	0x0094

end


CO_AdmittingDiagnosisCodeSequence

SH	CodeValue	0x0008	0x0100

SH	CodingSchemeDesignator	0x0008	0x0102

LO	CodeMeaning	0x0008	0x0104

end


CO_VisitDischargeModule

// C.3.5

DA	DischargeDate	0x0038	0x0030

TM	DischargeTime	0x0038	0x0032

LO	DischargeDiagnosisDescription	0x0038	0x0040

SQ	DischargeDiagnosisCodeSequence	0x0038	0x0044

end


CO_DischargeDiagnosisCodeSequence

SH	CodeValue	0x0008	0x0100

SH	CodingSchemeDesignator	0x0008	0x0102

LO	CodeMeaning	0x0008	0x0104

end


CO_VisitSchedulingModule

// C.3.6

DA	ScheduledAdmissionDate	0x0038	0x001A

TM	ScheduledAdmissionTime	0x0038	0x001B

DA	ScheduledDischargeDate	0x0038	0x001C

TM	ScheduledDischargeTime	0x0038	0x001D

LO	ScheduledPatientInsitutionResidence	0x0038	0x001E

end


CO_StudyRelationshipModule

// C.4.1

SQ	ReferencedVisitSequence	0x0008	0x1125

SQ	ReferencedPatientSequence	0x0008	0x1155

SQ	ReferencedResultsSequence	0x0008	0x1100

SQ	ReferencedStudyComponentSequence	0x0008	0x1100

UI	StudyInstanceUID	0x0020	0x000D

SH	AccessionNumber	0x0008	0x0050

end


CO_ReferencedResultsSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_ReferencedStudyComponentSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_StudyIdentificationMoudle

// C.4.2

SH	StudyID	0x0020	0x0010

LO	StudyIDIssuer	0x0032	0x0012

IS	OtherStudyNumbers	0x0020	0x1070

end


CO_StudyModule

// C.4.3

CS	StudyStatusID	0x0032	0x000A

CS	StudyPriorityID	0x0032	0x000C

LT	StudyComments	0x0032	0x4000

end


CO_StudySchedulingModule

// C.4.4

DA	ScheduledStudyStartDate	0x0032	0x1000

TM	ScheduledStudyStartTime	0x0032	0x1001

DA	ScheduledStudyStopDate	0x0032	0x1010

TM	ScheduledStudyStopTime	0x0032	0x1011

LO	ScheduledStudyLocation	0x0032	0x1020

AE	ScheduledStudyLocationAETitle	0x0032	0x1021

LO	ReasonForStudy	0x0032	0x1030

PN	RequestingPhysician	0x0032	0x1032

LO	RequestingService	0x0032	0x1033

LO	RequestedProcedureDescription	0x0032	0x1060

SQ	RequestedProcedureCodeSequence	0x0032	0x1064

LO	RequestedContrastAgent	0x0032	0x1070

end


CO_RequestedProcedureCodeSequence

SH	CodeValue	0x0008	0x0100

SH	CodingSchemeDesignator	0x0008	0x0102

LO	CodeMeaning	0x0008	0x0104

end


CO_StudyAcquisitionModule

// C.4.5

DA	StudyArrivalDate	0x0032	0x1080

TM	StudyArrivalTime	0x0032	0x1081

DA	StudyDate	0x0008	0x0020

TM	StudyTime	0x0008	0x0030

DA	StudyCompletionDate	0x0032	0x1050

TM	StudyCompletionTime	0x0032	0x1051

DA	StudyVerifiedDate	0x0032	0x0032

TM	StudyVerifiedTime	0x0032	0x0033

IS	SeriesInStudy	0x0020	0x1000

IS	AcquisitionsInStudy	0x0020	0x1004

end


CO_StudyReadModule

// C.4.6

PN	NameOfPhysiciansReadingStudy	0x0008	0x1060

DA	StudyReadDate	0x0032	0x0034

TM	StudyReadTime	0x0032	0x0035

end


CO_StudyComponentModule

// C.4.7

SH	StudyID	0x0020	0x0010

UI	StudyInstanceUID	0x0020	0x000D

SQ	ReferencedSeriesSequence	0x0008	0x1115

end


CO_ReferencedSeriesSequence

DA	SeriesDate	0x0008	0x0021

TM	SeriesTime	0x0008	0x0031

UI	SeriesInstanceUID	0x0020	0x000E

AE	RetrieveAETitle	0x0008	0x0054

SH	StorageMediaFileSetID	0x0088	0x0130

UI	StorageMediaFileSetUID	0x0088	0x0140

SQ	ReferencedImageSequence	0x0008	0x1120

end


CO_StudyComponentRelationshipModule

// C.4.8

SQ	ReferencedStudySequence	0x0008	0x1110

end


CO_StudyComponentStatusModule

// C.4.9

CS	Modality	0x0008	0x0060

LO	StudyDescription	0x0008	0x1030

SQ	ProcedureCodeSequence	0x0008	0x1032

PN	AttendingPhysiciansName	0x0008	0x1050

CS	StudyComponentStatusID	0x0032	0x1055

end


CO_ProcedureCodeSequence

SH	CodeValue	0x0008	0x0100

SH	CodingSchemeDesignator	0x0008	0x0102

LO	CodeMeaning	0x0008	0x0104

end


CO_ResultsRelationshipModule

// C.5.1

SQ	ReferencedInterpretationSequence	0x4008	0x0050

end


CO_ReferencedInterpretationSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_ResultsIdentificationModule

// C.5.2

SH	ResultsID	0x4008	0x0040

LO	ResultsIDIssuer	0x4008	0x0042

end


CO_ResultsImpressionsModule

// C.5.3

ST	Impressions	0x4008	0x0300

end


CO_InterpretationRelationshipModule

// C.6.1

SQ	ReferencedResultsSequence	0x0008	0x1100

end


CO_InterpretationIdentificationModule

// C.6.2

SH	InterpretationID	0x4008	0x0200

LO	InterpretationIDIssuer	0x4008	0x0202

end


CO_InterpretationStateModule

// C.6.3

CS	InterpretationTypeID	0x4008	0x0210

CS	InterpretationStatusID	0x4008	0x0212

end


CO_InterpretationRecordingModule

// C.6.4

DA	InterpretationRecordedDate	0x4008	0x0100

TM	InterpretationRecordedTime	0x4008	0x0101

PN	InterpretationRecorder	0x4008	0x0102

LO	ReferenceToRecordedSound	0x4008	0x0103

end


CO_InterpretationTranscriptionModule

// C.6.5

DA	InterpretationTranscriptionDate	0x4008	0x0108

TM	InterpretationTranscriptionTime	0x4008	0x0109

PN	InterpretationTranscriptionTranscriber	0x4008	0x010A

ST	InterpretationTranscriptionText	0x4008	0x010B

PN	InterpretationAuthor	0x4008	0x010C

end


CO_InterpretationApprovalModule

// C.6.6

SQ	InterpretationApproverSequence	0x4008	0x0111

LT	InterpretationDiagnosisDescription	0x4008	0x0115

SQ	InterpretationDiagnosisCodesSequence	0x4008	0x0117

SQ	ResultsDistributionListSequence	0x4008	0x0118

end


CO_InterpretationApproverSequence

DA	InterpretationApprovalDate	0x4008	0x0112

TM	InterpretationApprovalTime	0x4008	0x0113

PN	PhysiciansApprovingInterpretation	0x4008	0x0114

end


CO_InterpretationDiagnosisCodesSequence

SH	CodeValue	0x0008	0x0100

SH	CodingSchemeDesignator	0x0008	0x0102

LO	CodeMeaning	0x0008	0x0104

end


CO_ResultsDistributionListSequence

PN	DistributionName	0x4008	0x0119

LO	DistributionAddress	0x4008	0x011A

end


CO_PatientModule

// C.7.1

PN	PatientsName	0x0010	0x0010

LO	PatientID	0x0010	0x0020

DA	PatientsBirthDate	0x0010	0x0030

CS	PatientsSex	0x0010	0x0040

SQ	ReferencedPatientSequence	0x0008	0x1120

TM	PatientsBirthTime	0x0010	0x0032

LO	OtherPatientID	0x0010	0x1000

PN	OtherPatientNames	0x0010	0x1001

SH	EthnicGroup	0x0010	0x2160

LT	PatientComments	0x0010	0x4000

end


CO_ReferencedPatientSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_GeneralStudyModule

// C.7.2.1

UI	StudyInstanceUID	0x0020	0x000D

DA	StudyDate	0x0008	0x0020

TM	StudyTime	0x0008	0x0030

PN	ReferringPhysiciansName	0x0008	0x0090

SH	StudyID	0x0020	0x0010

SH	AccessionNumber	0x0008	0x0050

LO	StudyDescription	0x0008	0x1030

PN	NameOfPhysiciansReadingStudy	0x0008	0x1060

SQ	ReferencedStudySequence	0x0008	0x1110

end


CO_ReferencedStudySequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_PatientStudyModule

// C.7.2.2

LO	AdmittingDiagnosesDescription	0x0008	0x1080

AS	PatientsAge	0x0010	0x1010

DS	PatientsSize	0x0010	0x1020

DS	PatientsWeight	0x0010	0x1030

SH	Occupation	0x0010	0x2180

LT	AdditionalPatientsHistory	0x0010	0x21B0

end


CO_GeneralSeriesModule

// C.7.3.1

CS	Modality	0x0008	0x0060

UI	SeriesInstanceUID	0x0020	0x000E

IS	SeriesNumber	0x0020	0x0011

CS	Laterality	0x0020	0x0060

DA	SeriesDate	0x0008	0x0021

TM	SeriesTime	0x0008	0x0031

PN	PerformingPhysiciansName	0x0008	0x1050

LO	ProtocolName	0x0018	0x1030

LO	SeriesDescription	0x0008	0x103E

PN	OperatorsName	0x0008	0x1070

SQ	ReferenedStudyComponentSequence	0x0008	0x1111

CS	BodyPartExamined	0x0018	0x0015

CS	PatientPosition	0x0018	0x5100

XS	SmallestPixelValueInSeries	0x0028	0x0108

XS	LargestPixelValueInSeries	0x0028	0x0109

end


CO_FrameOfReferenceModule

// C.7.4.1

UI	FrameOfReferenceUID	0x0020	0x0052

LO	PositionReferenceIndicator	0x0020	0x1040

end


CO_GeneralEquipmentModule

// C.7.5.1

LO	Manufacturer	0x0008	0x0070

LO	InstitutionName	0x0008	0x0080

ST	InstitutionAddress	0x0008	0x0081

ST	StationName	0x0008	0x1010

LO	InstitutionalDepartmentName	0x0008	0x1040

LO	ManufacturersModelName	0x0008	0x1090

LO	DeviceSerialNumber	0x0018	0x1000

LO	SoftwareVersions	0x0018	0x1020

DS	SpatialResolution	0x0018	0x1050

DA	DateOfLastCalibration	0x0018	0x1200

TM	TimeOfLastCalibration	0x0018	0x1201

XS	PixelPaddingValue	0x0028	0x0120

end


CO_GeneralImageModule

// C.7.6.1

IS	ImageNumber	0x0020	0x0013

CS	PatientOrientation	0x0020	0x0020

DA	ImageDate	0x0008	0x0023

TM	ImageTime	0x0008	0x0033

CS	ImageType	0x0008	0x0008

IS	AcquisitionNumber	0x0020	0x0012

DA	AcquisitionDate	0x0008	0x0022

TM	AcquisitionTime	0x0008	0x0032

SQ	ReferencedImageSequence	0x0008	0x1140

ST	DerivationDescription	0x0008	0x2111

SQ	SourceImageSequence	0x0008	0x2112

IS	ImagesInAcquisition	0x0020	0x1002

LT	ImageComments	0x0020	0x4000

end


CO_SourceImageSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_ImagePlaneModule

// C.7.6.2

DS	PixelSpacing	0x0028	0x0030

DS	ImageOrientationPatient	0x0020	0x0037

DS	ImagePositionPatient	0x0020	0x0032

DS	SliceThickness	0x0018	0x0050

DS	SliceLocation	0x0020	0x1041

end


CO_ImagePixelModule

// C.7.6.3

US	SamplesPerPixel	0x0028	0x0002

CS	PhotometricInterpretation	0x0028	0x0004

US	Rows	0x0028	0x0010

US	Columns	0x0028	0x0011

US	BitsAllocated	0x0028	0x0100

US	BitsStored	0x0028	0x0101

US	HighBit	0x0028	0x0102

US	PixelRepresentation	0x0028	0x0103

OX	PixelData	0x7FE0	0x0010

US	PlanarConfiguration	0x0028	0x0006

IS	PixelAspectRatio	0x0028	0x0034

XS	SmallestImagePixelValue	0x0028	0x0106

XS	LargestImagePixelValue	0x0028	0x0107

XS	RedPaletteColorLookupTableDescriptor	0x0028	0x1101

XS	GreenPaletteColorLookupTableDescriptor	0x0028	0x1102

XS	BluePaletteColorLookupTableDescriptor	0x0028	0x1103

XS	RedPaletteColorLookupTableData	0x0028	0x1201

XS	GreenPaletteColorLookupTableData	0x0028	0x1202

XS	BluePaletteColorLookupTableData	0x0028	0x1203

end


CO_ContrastBolusModule

// C.7.6.4

LO	ContrastBolusAgent	0x0018	0x0010

LO	ContrastBolusRoute	0x0018	0x1040

DS	ContrastBolusVolume	0x0018	0x1041

TM	ContrastBolusStartTime	0x0018	0x1042

TM	ContrastBolusStopTime	0x0018	0x1043

DS	ContrastBolusTotalDose	0x0018	0x1044

end


CO_CineModule

// C.7.6.5

DS	FrameTime	0x0018	0x1063

DS	FrameTimeVector	0x0018	0x1065

IS	StartTrim	0x0008	0x2142

IS	StopTrim	0x0008	0x2143

IS	RecommendedDisplayFrameRate	0x0008	0x2144

IS	CineRate	0x0018	0x0040

DS	FrameDelay	0x0018	0x1066

DS	EffectiveDuration	0x0018	0x0072

IS	ActualFrameDuration	0x0018	0x1242

end


CO_MultiframeModule

// C.7.6.6

IS	NumberOfFrames	0x0028	0x0008

AT	FrameIncrementPointer	0x0028	0x0009

end


CO_PatientSummaryModule

// C.7.7

PN	PatientsName	0x0010	0x0010

LO	PatientID	0x0010	0x0020

end


CO_StudyContentModule

// C.7.8

SH	StudyID	0x0020	0x0010

UI	StudyInstanceUID	0x0020	0x000D

SQ	ReferencedSeriesSequence	0x0008	0x1115

end


CO_ReferencedImageSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferenceSOPInstanceUID	0x0008	0x1155

AE	RetrieveApplicationEntityTitle	0x0008	0x0054

SH	StorageMediaFileSetID	0x0088	0x0130

UI	StorageMediaFileSetUID	0x0088	0x0140

end


CO_CRSeriesModule

// C.8.1.1

CS	BodyPartExamined	0x0018	0x0015

CS	VeiwPosition	0x0018	0x5101

SH	FilterType	0x0018	0x1160

SH	CollimatorGridName	0x0018	0x1180

DS	FocalSpot	0x0018	0x1190

SH	PlateType	0x0018	0x1260

LO	PhosphorType	0x0018	0x1261

end


CO_CRImageModule

// C.8.1.2

DS	KVP	0x0018	0x0060

LO	PlateID	0x0018	0x1004

DS	DistanceSourceToDetector	0x0018	0x1110

DS	DistanceSourceToPatient	0x0018	0x1111

IS	ExposureTime	0x0018	0x1150

IS	XRayTubeCurrent	0x0018	0x1151

IS	Exposure	0x0018	0x1152

IS	GeneratorPower	0x0018	0x1170

LO	AcquisitionDeviceProcessingDescription	0x0018	0x1400

LO	AcquisitionDeviceProcessingCode	0x0018	0x1401

CS	CassetteOrientation	0x0018	0x1402

CS	CassetteSize	0x0018	0x1403

US	ExposuresOnPlate	0x0018	0x1404

IS	RelativeXRayExposure	0x0018	0x1405

DS	Sensitivity	0x0018	0x6000

end


CO_CTImageModule

// C.8.2.1

CS	ImageType	0x0008	0x0008

US	SamplesPerPixel	0x0028	0x0002

CS	PhotometricInterpretation	0x0028	0x0004

US	BitsAllocated	0x0028	0x0100

US	BitsStored	0x0028	0x0101

US	HighBit	0x0028	0x0102

DS	RescaleIntercept	0x0028	0x1052

DS	RescaleSlope	0x0028	0x1053

DS	KVP	0x0018	0x0060

IS	AcquisitionNumber	0x0020	0x0012

CS	ScanOptions	0x0018	0x0022

DS	DataCollectionDiameter	0x0018	0x0090

DS	ReconstructionDiameter	0x0018	0x1100

DS	DistanceSourceToDector	0x0018	0x1110

DS	DistanceSourceToPatient	0x0018	0x1111

DS	GantryDetectorTilt	0x0018	0x1111

DS	TableHeight	0x0018	0x1130

CS	RotationDirection	0x0018	0x1140

IS	ExposureTime	0x0018	0x1150

IS	XRayTubeCurrent	0x0018	0x1151

IS	Exposure	0x0018	0x1152

SH	FilterType	0x0018	0x1160

IS	GeneratorPower	0x0018	0x1170

DS	FocalSpot	0x0018	0x1190

SH	ConvolutionKernel	0x0018	0x1210

end


CO_MRImageModule

// C.8.3.1

CS	ImageType	0x0008	0x0008

US	SamplesPerPixel	0x0028	0x0002

CS	PhotometricInterpretation	0x0028	0x0004

US	BitsAllocated	0x0028	0x0100

SQ	ScanningSequence	0x0018	0x0020

CS	DequenceVariant	0x0018	0x0021

CS	ScanOptions	0x0018	0x0022

CS	MRAcquisitionType	0x0018	0x0023

DS	RepetitionTime	0x0018	0x0080

DS	EchoTime	0x0018	0x0081

IS	EchoTrainLength	0x0018	0x0091

DS	InversionTime	0x0018	0x0082

DS	TriggerTime	0x0018	0x1060

SH	SequenceName	0x0018	0x0024

CS	AngioFlag	0x0018	0x0025

DS	NumberOfAverages	0x0018	0x0083

DS	ImagingFrequency	0x0018	0x0084

SH	ImagedNucleus	0x0018	0x0085

IS	EchoNumber	0x0018	0x0086

DS	MagneticFieldStrength	0x0018	0x0087

DS	SpacingBetweenSlices	0x0018	0x0088

IS	NumberOfPhaseEncodingSteps	0x0018	0x0089

DS	PercentSampling	0x0018	0x0093

DS	PercentPhaseFieldOfView	0x0018	0x0094

DS	PixelBandwidth	0x0018	0x0095

IS	NominalInterval	0x0018	0x1062

CS	BeatRejectionFlag	0x0018	0x1080

IS	LowRRValue	0x0018	0x1081

IS	IntervalsAcquired	0x0018	0x1083

IS	InvervalsRejected	0x0018	0x1084

LO	PVCRejection	0x0018	0x1085

IS	SkipBeats	0x0018	0x1086

IS	HeartRate	0x0018	0x1088

IS	CardiacNumberOfImages	0x0018	0x1090

IS	TriggerWindow	0x0018	0x1094

DS	ReconstructionDiameter	0x0018	0x1100

SH	ReceivingCoil	0x0018	0x1250

SH	TransmittingCoil	0x0018	0x1251

US	AcquisitionMatrix	0x0018	0x1310

CS	PhaseEncodingDirection	0x0018	0x1312

DS	FlipAngle	0x0018	0x1312

DS	SAR	0x0018	0x1316

CS	VariableFlipAngleFlag	0x0018	0x1315

DS	dBdt	0x0018	0x1318

IS	TemporalPositionIdentifier	0x0020	0x0100

IS	NumberOfTemporalPositions	0x0020	0x0105

DS	TemporalResolution	0x0020	0x0110

end


CO_NMSeriesModule

// C.8.4.1

LO	Radionuclide	0x0018	0x0030

CS	NuclearMedicineSeriesType	0x0008	0x0042

IS	ScanVelocity	0x0018	0x1300

CS	WholeBodyTechnique	0x0018	0x1301

IS	ScanLength	0x0018	0x1302

LO	Radiopharmaceutical	0x0018	0x0031

DS	EnergyWindowCenterline	0x0018	0x0032

DS	EnergyWindowTotalWidth	0x0018	0x0033

LO	InterventionDrugName	0x0018	0x0034

TM	InterventionDrugStartTime	0x0018	0x0035

DS	EffectiveSeriesDuration	0x0018	0x0072

IS	SyringeCounts	0x0018	0x1045

LO	TriggerSourceOrType	0x0018	0x1061

LO	RadionuclideRoute	0x0018	0x1070

DS	RadionuclideVolume	0x0018	0x1071

TM	RadionuclideStartTime	0x0018	0x1072

TM	RadionuclideStopTime	0x0018	0x1073

DS	RadionuclideTotalDose	0x0018	0x1074

DS	GantryDetectorTilt	0x0018	0x1120

IS	IsotopeNumber	0x0020	0x0014

end


CO_NMEquipmentModule

// C.8.4.2

DS	CenterOfRotationOffset	0x0018	0x1145

CS	FieldOfViewShape	0x0018	0x1147

IS	FieldOfViewDimensions	0x0018	0x1149

SH	CollimatorGridName	0x0018	0x1180

CS	CollimatorType	0x0018	0x1181

IS	FocalDistance	0x0018	0x1182

DS	XFocusCenter	0x0018	0x1183

DS	YFocusCenter	0x0018	0x1184

end


CO_NMImageModule

// C.8.4.3

AT	FrameIncrementPointer	0x0028	0x0009

DS	ZoomFactor	0x0028	0x0031

IS	CountsAccumulated	0x0018	0x0070

SQ	ReferencedOverlaySequence	0x0008	0x1130

SQ	ReferencedCurveSequence	0x0008	0x1145

CS	AcquisitionTerminationCondition	0x0018	0x0071

DS	ReconstructionDiameter	0x0018	0x1100

DS	DistanceSourceToDetector	0x0018	0x1110

DS	TableHeight	0x0018	0x1130

DS	TableTraverse	0x0018	0x1131

DS	AngularPosition	0x0018	0x1141

DS	RadialPosition	0x0018	0x1142

SH	ConvolutionKernel	0x0018	0x1210

IS	ActualFrameDuration	0x0018	0x1242

IS	CountRate	0x0018	0x1243

LO	PreprocessingFunction	0x0018	0x5020

LO	PostprocessingFunction	0x0018	0x5021

IS	PhaseNumber	0x0020	0x0015

IS	IntervalNumber	0x0020	0x0016

IS	TimeSlotNumber	0x0020	0x0017

IS	AngleNumber	0x0020	0x0018

DS	ZoomCenter	0x0028	0x0032

CS	CorrectedImage	0x0028	0x0051

end


CO_NMSPECTAcquisitionImageModule

// C.8.4.4

AT	FrameIncrementPointer	0x0028	0x0009

DS	AngularStep	0x0018	0x1144

DS	ZoomFactor	0x0028	0x0031

DS	ScanArc	0x0018	0x1143

DS	ReconstructionDiameter	0x0018	0x1100

DS	DistanceSourceToDetector	0x0018	0x1110

DS	TableHeight	0x0018	0x1130

DS	TableTraverse	0x0018	0x1131

CS	RotationDirection	0x0018	0x1140

DS	AngularPosition	0x0018	0x1141

DS	RadialPosition	0x0018	0x1142

DS	RotationOffset	0x0018	0x1146

IS	AngleNumber	0x0020	0x0018

DS	ZoomCenter	0x0028	0x0032

end


CO_NMMultigatedAcquisitionImageModule

// C.8.4.5

AT	FrameIncrementPointer	0x0028	0x0009

LO	TriggerSourceORType	0x0018	0x1061

DS	FrameTime	0x0018	0x1063

DS	TriggerTime	0x0018	0x1060

IS	NominalInterval	0x0018	0x1062

LO	FramingType	0x0018	0x1064

CS	BeatRejectionFlag	0x0018	0x1080

IS	LowRRValue	0x0018	0x1081

IS	HighRRValue	0x0018	0x1082

IS	IntervalsAcquired	0x0018	0x1083

IS	IntervalsRejected	0x0018	0x1084

LO	PVCRejection	0x0018	0x1085

IS	SkipBeats	0x0018	0x1086

IS	HeartRate	0x0018	0x1088

IS	CardiacNumberOfImages	0x0018	0x1090

end


CO_USFrameOfReferenceModule

// C.8.5.1

UL	RegionLocationMinX0	0x0018	0x6018

UL	RegionLocationMinY0	0x0018	0x601A

UL	RegionLocationMaxX1	0x0018	0x601C

UL	RegionLocationMaxY1	0x0018	0x601E

US	PhysicalUnitsXDirection	0x0018	0x6024

US	PhysicalUnitsYDirection	0x0018	0x6026

FD	PhysicalDeltaX	0x0018	0x602C

FD	PhysicalDeltaY	0x0018	0x602E

SL	ReferencePixelX0	0x0018	0x6020

SL	ReferencePixelY0	0x0018	0x6022

FD	RefPixelPhysicalValueX	0x0018	0x6028

FD	RefPixelPhysicalValueY	0x0018	0x602A

end


CO_USRegionCalibrationModule

// C.8.5.2

SQ	SequenceOfUltrasoundRegions	0x0018	0x6011

end


CO_SequenceOfUltrasoundRegions

UL	RegionLocationMinX0	0x0018	0x6018

UL	RegionLocationMinY0	0x0018	0x601A

UL	RegionLocationMaxX1	0x0018	0x601C

UL	RegionLocationMaxY1	0x0018	0x601E

US	PhysicalUnitsXDirection	0x0018	0x6024

US	PhysicalUnitsYDirection	0x0018	0x6026

FD	PhysicalDeltaX	0x0018	0x602C

FD	PhysicalDeltaY	0x0018	0x602E

SL	ReferencePixelX0	0x0018	0x6020

SL	ReferencePixelY0	0x0018	0x6022

FD	RefPixelPhysicalValueX	0x0018	0x6028

FD	RefPixelPhysicalValueY	0x0018	0x602A

US	RegionSpatialFormat	0x0018	0x6012

US	RegionDataType	0x0018	0x6014

UL	RegionFlags	0x0018	0x6016

US	PixelComponentOrganization	0x0018	0x6044

UL	PixelComponentMask	0x0018	0x6046

UL	PixelComponentRangeStart	0x0018	0x6048

UL	PixelComponentRangeStop	0x0018	0x604A

US	PixelComponentPhysicalUnits	0x0018	0x604C

US	PixelComponentDataType	0x0018	0x604E

UL	NumberOfTableBreakPoints	0x0018	0x6050

UL	TableOfXBreakPoints	0x0018	0x6052

FD	TableOfYBreakPoints	0x0018	0x6054

UL	TransducerFrequency	0x0018	0x6030

UL	PulseRepetitionFrequency	0x0018	0x6032

FD	DopplerCorrectionAngle	0x0018	0x6034

FD	SteeringAngle	0x0018	0x6036

UL	DopplerSampleVolumeXPosition	0x0018	0x6038

UL	DopplerSampleVolumeYPosition	0x0018	0x603A

UL	TMLinePositionX0	0x0018	0x603C

UL	TMLinePositionY0	0x0018	0x603E

UL	TMLinePositionX1	0x0018	0x6040

UL	TMLinePositionY1	0x0018	0x6042

end


CO_USImageModule

// C.8.5.3

CS	PhotometricInterpretation	0x0028	0x0004

US	PixelRepresentation	0x0028	0x0103

AT	FrameIncrementPointer	0x0028	0x0009

CS	ImageType	0x0008	0x0008

IS	NumberOfStages	0x0008	0x2124

IS	NumberOfViewsInStage	0x0008	0x212A

SQ	ReferencedOverlaySequence	0x0008	0x1130

SQ	ReferencedCurveSequence	0x0008	0x1145

SH	StageName	0x0008	0x2120

IS	StageNumber	0x0008	0x2122

IS	ViewNumber	0x0008	0x2128

IS	NumberOfEventTimers	0x0008	0x2129

DS	EventElapsedTimes	0x0008	0x2130

LO	EventTimerNames	0x0008	0x2132

CS	TransducerPosition	0x0008	0x2200

CS	TransducerOrientation	0x0008	0x2204

CS	AnatomicStructure	0x0008	0x2208

DS	TriggerTime	0x0018	0x1060

IS	MonimalInterval	0x0018	0x1062

CS	BeatRejectionFlag	0x0018	0x1080

IS	LowRRValue	0x0018	0x1081

IS	HighRRValue	0x0018	0x1082

IS	HeartRate	0x0018	0x1088

SH	OutputPower	0x0018	0x5000

LO	TransducerDate	0x0018	0x5010

CS	TransducerType	0x0018	0x6031

DS	FocusDepth	0x0018	0x5012

LO	PreprocessingFunction	0x0018	0x5020

DS	MechanicalIndex	0x0018	0x5022

DS	BoneThermalIndex	0x0018	0x5024

DS	CranialThermalIndex	0x0018	0x5026

DS	SoftTissueThermalIndex	0x0018	0x5027

DS	SoftTissueFocusThermalIndex	0x0018	0x5028

DS	SoftTissueSurfaceThermalIndex	0x0018	0x5029

IS	DepthOfScanField	0x0018	0x5050

DS	ImageTransformationMatrix	0x0018	0x5210

DS	ImageTranslationVector	0x0018	0x5212

end


CO_ReferencedCurveSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_SCEquipmentModule

// C.8.6.1

CS	ConversionType	0x0008	0x0064

CS	Modality	0x0008	0x0060

LO	SecondaryCaptureDeviseID	0x0018	0x1010

LO	SecondaryCaptureDeviceManufacturer	0x0018	0x1016

LO	SecondaryCaptureDeviceManufacturersModelName	0x0018	0x1018

LO	SecondaryCaptureDeviceSoftwareVersion	0x0018	0x1019

SH	VideoImageFormatAcquired	0x0018	0x1022

LO	DigitalImageFormatAcquired	0x0018	0x1023

end


CO_SCImageModule

// C.8.6.2

DA	DateOfSecondaryCapture	0x0018	0x1012

TM	TimeOfSecondaryCapture	0x0018	0x1014

US	OverlayNumber	0x0020	0x0022

DA	OverlayDate	0x0008	0x0024

TM	OverlayTime	0x0008	0x0034

SQ	ReferencedImageSequence	0x0008	0x1140

end


CO_OverlayIdentificationModule

// C.9.1

US	OverlayNumber	0x0020	0x0022

DA	OverlayDate	0x0008	0x0024

TM	OverlayTime	0x0008	0x0034

SQ	ReferenceImageSequence	0x0008	0x1140

end


CO_OverlayPlaneModule

// C.9.2

US	Rows	0x6001	0x0010

US	Columns	0x6001	0x0011

CS	OverlayType	0x6001	0x0040

SS	Origin	0x6001	0x0050

US	BitsAllocated	0x6001	0x0100

US	BitPosition	0x6001	0x0102

OW	OverlayData	0x6001	0x3000

IS	ROIArea	0x6001	0x1301

DS	ROIMean	0x6001	0x1302

DS	ROIStandardDeviation	0x6001	0x1303

US	OverlayDescriptorGray	0x6001	0x1100

US	OverlayDescriptorRed	0x6001	0x1101

US	OverlayDescriptorGreen	0x6001	0x1102

US	OverlayDescriptorBlue	0x6001	0x1103

US	OverlaysGray	0x6001	0x1200

US	OverlaysRed	0x6001	0x1201

US	OverlaysGreen	0x6001	0x1202

US	OverlaysBlue	0x6001	0x1203

end


CO_MultiframeOverlayModule

// C.9.3

IS	NumberOfFramesInOverlay	0x6001	0x0015

end


CO_CurveIdentificationModule

// C.10.1

US	CurveNumber	0x0020	0x0024

DA	CurveDate	0x0008	0x0025

TM	CurveTime	0x0008	0x0035

SQ	ReferencedImageSequence	0x0008	0x1140

SQ	ReferencedOverlaySequence	0x0008	0x1130

SQ	ReferencedCurveSequence	0x0008	0x1145

end


CO_ReferencedOverlaySequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_CurveModule

// C.10.2

US	CurveDimensions	0x5001	0x0005

US	NumberOfPoints	0x5001	0x0010

CS	TypeOfData	0x5001	0x0020

US	DataValueRepresentation	0x5001	0x0103

OX	CurveData	0x5001	0x3000

LO	CurveDescription	0x5001	0x0022

SH	AxisUnits	0x5001	0x0030

SH	AxisLabels	0x5001	0x0040

US	MinimumCoordinateValue	0x5001	0x0104

US	MaximumCoordinateValue	0x5001	0x0105

SH	CurveRange	0x5001	0x0106

US	CurveDataDescriptor	0x5001	0x0110

US	CoordinateStartValue	0x5001	0x0112

US	CoordinateStepValue	0x5001	0x0114

end


CO_AudioModule

// C.10.3

US	AudioType	0x5001	0x2000

US	AudioSampleFormat	0x5001	0x2002

US	NumberOfChannels	0x5001	0x2004

UL	NumberOfSamples	0x5001	0x2006

UL	SampleRate	0x5001	0x2008

UL	TotalTime	0x5001	0x200A

OX	AudioSampleData	0x5001	0x200C

SQ	ReferencedImageSequence	0x0008	0x1140

LT	AudioComments	0x5001	0x200E

end


CO_ModalityLUTModule

// C.11.1

SQ	ModalityLUTSequence	0x0028	0x3000

DS	RescaleIntercept	0x0028	0x1052

DS	RescaleSlope	0x0028	0x1053

LO	RescaleType	0x0028	0x1054

end


CO_ModalityLUTSequence

XS	LUTDescriptor	0x0028	0x3002

LO	LUTExplanation	0x0028	0x3003

LO	ModalityLUTType	0x0028	0x3004

XS	LUTData	0x0028	0x3006

end


CO_VOILUTModule

// C.11.2

SQ	VOILUTSequence	0x0028	0x3010

DS	WindowCenter	0x0028	0x1050

DS	WindowWidth	0x0028	0x1051

LO	WindowCenterAndWidthExplanation	0x0028	0x1055

end


CO_VOILUTSequence

XS	LUTDescriptor	0x0028	0x3002

LO	LUTExplanation	0x0028	0x3003

XS	LUTData	0x0028	0x3006

end


CO_LUTIdentificationModule

// C.11.3

IS	LUTNumber	0x0020	0x0026

SQ	ReferencedImageSequence	0x0008	0x1140

end

// C.12.1


CO_SOPCommonModule

UI	SOPClassUID	0x0008	0x0016

UI	SOPInstanceUID	0x0008	0x0018

CS	SpecificCharacterSet	0x0008	0x0005

DA	InstanceCreationDate	0x0008	0x0012

TM	InstanceCreationTime	0x0008	0x0013

UI	InstanceCreatorUID	0x0008	0x0014

end


CO_BasicFilmSessionPresentationModule

// C.13.1

IS	NumberOfCopies	0x2000	0x0010

CS	PrintPriority	0x2000	0x0020

CS	MediumType	0x2000	0x0030

CS	FilmDestination	0x2000	0x0040

LO	FilmSessionLabel	0x2000	0x0050

IS	MemoryAllocation	0x2000	0x0060

end


CO_BasicFilmSessionRelationshipModule

// C.13.2

SQ	ReferencedFilmBoxSequence	0x2000	0x0500

end


CO_ReferencedFilmBoxSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_BasicFilmBoxPresentationModule

// C.13.3

ST	ImageDisplayFormat	0x2010	0x0010

CS	AnnotationDisplayFormatID	0x2010	0x0030

CS	FilmOrientation	0x2010	0x0040

CS	FilmSizeID	0x2010	0x0050

CS	MagnificationType	0x2010	0x0060

CS	SmoothingType	0x2010	0x0080

CS	BorderDensity	0x2010	0x0100

CS	EmptyImageDensity	0x2010	0x0110

US	MinDensity	0x2010	0x0120

US	MaxDensity	0x2010	0x0130

CS	Trim	0x2010	0x0140

ST	ConfigurationInformation	0x2010	0x0150

end


CO_BasicFilmBoxRelationshipModule

// C.13.4

SQ	ReferencedFilmSessionSequence	0x2010	0x0500

SQ	ReferencedImageBoxSequence	0x2010	0x0510

SQ	ReferencedBasicAnnotationBoxSequence	0x2010	0x0520

end


CO_ReferencedFilmSessionSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_ReferencedImageBoxSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_ReferencedBasicAnnotationBoxSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_ImageBoxPixelPresentationModule

// C.13.5

US	ImagePosition	0x2020	0x0010

CS	Polarity	0x2020	0x0020

CS	MagnificationType	0x2010	0x0060

CS	SmoothingType	0x2010	0x0080

DS	RequestedImageSize	0x2020	0x0030

SQ	PreformattedGrayscaleImageSequence	0x2020	0x0110

SQ	PreformattedColorImageSequence	0x2020	0x0111

end


CO_PreformattedGrayscaleImageSequence

US	SamplesPerPixel	0x0028	0x0002

CS	PhotometricInterpretation	0x0028	0x0004

US	Rows	0x0028	0x0010

US	Columns	0x0028	0x0011

IS	PixelAspectRatio	0x0028	0x0034

US	BitsAllocated	0x0028	0x0100

US	BitsStored	0x0028	0x0101

US	HighBit	0x0028	0x0102

US	PixelRepresentation	0x0028	0x0103

OX	PixelData	0x7FE0	0x0010

end


CO_PreformattedColorImageSequence

US	SamplesPerPixel	0x0028	0x0002

CS	PhotometricInterpretation	0x0028	0x0004

US	PlanarConfiguration	0x0028	0x0006

US	Rows	0x0028	0x0010

US	Columns	0x0028	0x0011

IS	PixelAspectRatio	0x0028	0x0034

US	BitsAllocated	0x0028	0x0100

US	BitsStored	0x0028	0x0101

US	HighBit	0x0028	0x0102

US	PixelRepresentation	0x0028	0x0103

OX	PixelData	0x7FE0	0x0010

end


CO_ImageBoxRelationshipModule

// C.13.6

SQ	ReferencedImageSequence	0x0008	0x1140

SQ	ReferencedImageOverlayBoxSequence	0x2020	0x0130

SQ	ReferencedVOILUTSequence	0x2020	0x0140

end


CO_ReferencedImageOverlayBoxSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

UI	ReferencedFrameNumber	0x0008	0x1160

end


CO_ReferencedVOILUTSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

end


CO_BasicAnnotationPresentationModule

// C.13.7

US	AnnotationPosition	0x2030	0x0010

LO	TextString	0x2030	0x0020

end


CO_PrintJobModule

// C.13.8

CS	ExecutionStatus	0x2100	0x0020

CS	ExecutionStatusInfo	0x2100	0x0030

DA	CreationDate	0x2100	0x0040

TM	CreationTime	0x2100	0x0050

CS	PrintPriority	0x2000	0x0020

LO	PrinterName	0x2110	0x0030

AE	Originator	0x2100	0x0070

end


CO_PrinterModule

// C.13.9

CS	PrinterStatus	0x2110	0x0010

CS	PrinterStatusInfo	0x2110	0x0020

LO	PrinterName	0x2110	0x0030

LO	Manufacturer	0x0008	0x0070

LO	ManufacturerModelName	0x0008	0x1090

LO	DeviceSerialNumber	0x0018	0x1000

LO	SoftwareVersions	0x0018	0x1020

DA	DateOfLastCalibration	0x0018	0x1200

TM	TimeOfLastCalibration	0x0018	0x1201

end


CO_ImageOverlayBoxPresentationModule

// C.13.10

SQ	ReferencedOverlayPlaneSequence	0x2040	0x0010

CS	OverlayMagnificationType	0x2040	0x0060

CS	OverlaySmoothingType	0x2040	0x0070

CS	OverlayForegroundDensity	0x2040	0x0080

CS	OverlayMode	0x2040	0x0090

CS	ThresholdDensity	0x2040	0x0100

end


CO_ReferencedOverlayPlaneSequence

UI	ReferencedSOPClassUID	0x0008	0x1150

UI	ReferencedSOPInstanceUID	0x0008	0x1155

UI	ReferencedOverlayPlaneGroups	0x2040	0x0011

end


Composite Complex Object Classes

Normalized objects are representations of single IOD descriptions from Part 3 of the DICOM standard.  The class descriptions that follow are abbreviations.  To read them transform each line:

CRImageIODModule

PatientModule	PatientModule

Into:

class	CRImageIODModule	:

public	CCO_Abstract

{

private:

DICOMDataObject	StrayVRs;

public:

CO_PatientModule	PatientModule;

.

.

.

public:

BOOL	Set ( DICOMDataObject * );

DICOMDataObject	*Get ();

BOOL	Reset ();

};

The procedure Set () will take only the elements defined in the module description below, and remove them from the DICOMDataObject.  All other VRs in the DICOMDataObject will be dumped into StrayVRs.

The procedure Get () will return a DICOMDataObject from only the defined (used) elements from the description below.  Any elements in StrayVRs will also be placed in the resulting object.

The procedure Reset () will reset the Normalized object back to the initial state.


CRImageIODModule

// A.2.3 CR Image

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

CRSeriesModule	CRSeriesModule

GeneralEquipmentModule	GeneralEquipmentModule

GeneralImageModule	GeneralImageModule

ImagePixelModule	ImagePixelModule

ContrastBolusModule	ContrastBolusModule

CRImageModule	CRImageModule

OverlayPlaneModule	OverlayPlaneModule

CurveModule	CurveModule

ModalityLUTModule	ModalityLUTModule

VOILUTModule	VOILUTModule

SOPCommonModule	SOPCommonModule

end


CTImageIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

FrameOfReferenceModule	FrameOfReferenceModule

GeneralEquipmentModule	GeneralEquipmentModule

GeneralImageModule	GeneralImageModule

ImagePlaneModule	ImagePlaneModule

ImagePixelModule	ImagePixelModule

ContrastBolusModule	ContrastBolusModule

CTImageModule	CTImageModule

OverlayPlaneModule	OverlayPlaneModule

VOILUTModule	VOILUTModule

SOPCommonModule	SOPCommonModule

end


MRImageIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

FrameOfReferenceModule	FrameOfReferenceModule

GeneralEquipmentModule	GeneralEquipmentModule

GeneralImageModule	GeneralImageModule

ImagePlaneModule	ImagePlaneModule

ImagePixelModule	ImagePixelModule

ContrastBolusModule	ContrastBolusModule

MRImageModule	MRImageModule

OverlayPlaneModule	OverlayPlaneModule

VOILUTModule	VOILUTModule

SOPCommonModule	SOPCommonModule

end


NMImageIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

NMSeriesModule	NMSeriesModule

FrameOfReferenceModule	FrameOfReferenceModule

GeneralEquipmentModule	GeneralEquipmentModule

NMEquipmentModule	NMEquipmentModule

GeneralImageModule	GeneralImageModule

ImagePlaneModule	ImagePlaneModule

ImagePixelModule	ImagePixelModule

CineModule	CineModule

MultiframeModule	MultiframeModule

NMImageModule	NMImageModule

NMSPECTAcquisitionImageModule	NMSPECTAcquisitionImageModule

NMMultigatedAcquisitionImageModule NMMultigatedAcquisitionImageModule

OverlayPlaneModule	OverlayPlaneModule

MultiframeOverlayModule	MultiframeOverlayModule

CurveModule	CurveModule

VOILUTModule	VOILUTModule

SOPCommonModule	SOPCommonModule

OverlayIdentificationModule	OverlayIdentificationModule

CurveIdentificationModule	CurveIdentificationModule

end


USImageIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

FrameOfReferenceModule	FrameOfReferenceModule

USFrameOfReferenceModule	USFrameOfReferenceModule

GeneralEquipmentModule	GeneralEquipmentModule

ImagePixelModule	ImagePixelModule

ContrastBolusModule	ContrastBolusModule

USRegionCalibrationModule	USRegionCalibrationModule

USImageModule	USImageModule

OverlayPlaneModule	OverlayPlaneModule

VOILUTModule	VOILUTModule

SOPCommonModule	SOPCommonModule

CurveIdentificationModule	CurveIdentificationModule

CurveModule	CurveModule

AudioModule	AudioModule

end


USNMultiframeImageIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

FrameOfReferenceModule	FrameOfReferenceModule

USFrameOfReferenceModule	USFrameOfReferenceModule

GeneralEquipmentModule	GeneralEquipmentModule

ImagePixelModule	ImagePixelModule

ContrastBolusModule	ContrastBolusModule

CineModule	CineModule

MultiframeModule	MultiframeModule

USRegionCalibrationModule	USRegionCalibrationModule

USImageModule	USImageModule

OverlayPlaneModule	OverlayPlaneModule

VOILUTModule	VOILUTModule

SOPCommonModule	SOPCommonModule

CurveIdentificationModule	CurveIdentificationModule

CurveModule	CurveModule

AudioModule	AudioModule

end


SCImageIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

GeneralEquipmentModule	GeneralEquipmentModule

SCEquipmentModule	SCEquipmentModule

GeneralImageModule	GeneralImageModule

ImagePlaneModule	ImagePlaneModule

ImagePixelModule	ImagePixelModule

SCImageModule	SCImageModule

OverlayPlaneModule	OverlayPlaneModule

ModalityLUTModule	ModalityLUTModule

VOILUTModule	VOILUTModule

SOPCommonModule	SOPCommonModule

end


StandaloneOverlayIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

GeneralEquipmentModule	GeneralEquipmentModule

OverlayIdentificationModule	OverlayIdentificationModule

OverlayPlaneModule	OverlayPlaneModule

SOPCommonModule	SOPCommonModule

end


StandaloneCurveIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

GeneralEquipmentModule	GeneralEquipmentModule

CurveIdentificationModule	CurveIdentificationModule

CurveModule	CurveModule

SOPCommonModule	SOPCommonModule

end


StandaloneModalityLUTIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

GeneralEquipmentModule	GeneralEquipmentModule

ModalityLUTModule	ModalityLUTModule

LUTIdentificationModule	LUTIdentificationModule

SOPCommonModule	SOPCommonModule

end


StandaloneVOILUTIODModule

PatientModule	PatientModule

GeneralStudyModule	GeneralStudyModule

PatientStudyModule	PatientStudyModule

GeneralSeriesModule	GeneralSeriesModule

GeneralEquipmentModule	GeneralEquipmentModule

VOILUTModule	ModalityLUTModule

LUTIdentificationModule	LUTIdentificationModule

SOPCommonModule	SOPCommonModule

end


Part 4: Endian Architectures

The NEN Data Type

Introduction

NEN (Native Endian Neutral) Data Types


Introduction

Architecturally the DICOM standard is divided.  The lower level TCP/IP transport relies upon "Network Byte Order" Big-Endian numerics.  The default DICOM transfer syntax is Little-Endian.  When compiling with the DICOM library you must define a NATIVE_ENDIAN constant such that it has one of these values:

NATIVE_ENDIAN = LITTLE_ENDIAN = 1

NATIVE_ENDIAN = BIG_ENDIAN = 2

Setting this value correctly is very important.  If you compile with the wrong setting your software will behave very oddly.  (The most common behavior is if you have your software talk to itself on the same machine, it works fine; but, when you talk to another DICOM unit, everything goes wrong.)

There is a test program: getend.c.  To compile this file on UNIX using GCC do:

gcc -c getend.c

gcc -o getend getend.o

The program will print out the native endian architecture type of the machine, along with what constant setting to use.

From the NATIVE_ENDIAN setting the lower-level TCP/IP transport is properly configured, but, the DICOMObject (see Part 3 of this document) is inherently tied to the DICOM Little Endian transfer syntax.  How does one reconcile this on Big-Endian machines, and how do you write software which will recompile on both?


NEN (Native Endian Neutral) Data Types

When you include "dicom.hpp" you get eight endian specific datatypes.  They are termed "Native Endian Neutral", because if you declare an instance of a little endian type, it is stored in memory as little endian (and likewise for big endian).  The defined data types are:

LE_UINT16	Little Endian 16 bit unsigned integer

LE_UINT32	Little Endian 32 bit unsigned integer

LE_INT16	Little Endian 16 bit signed integer

LE_INT32	Little Endian 32 bit signed integer

BE_UINT16	Big Endian 16 bit unsigned integer

BE_UINT32	Big Endian 32 bit unsigned integer

BE_INT16	Big Endian 16 bit signed integer

BE_INT32	Big Endian 32 bit signed integer

All level 7 (DICOM Application) layer (and DIMSE-C service) routines should use xE_sINTb datatypes (x=Endian, s=un/signed, b=bit width).  These datatypes fully support the complete range of C/C++ operators: +, -, *, /, &, etc.

Caveats

Do not use NEN data types for math intensive operations.  In most cases if the endian type is non-native, the numeric is converted to native, the math operation performed and then converted back.  This is an obvious performance problem.

Do not assume that if you take the address of an NEN and further de-reference it, that that address will validly point to an NEN.  It does in fact point to an internal data-member of the NEN class.  Whether or not this will work is a compiler-dependent issue.  The reason is the & operator is overloaded and points to an internal data member.  This data member is the only object in the NEN class; however, certain compilers always generate a virtual-function table (and possibly other excess data) for classes.  Due to the over-loaded nature of the operator one cannot guarantee that a de-reference will always work.  To overcome this situation it is recommended that you work with native sINTb datatypes and only convert to xE_sINTb data types when creating VRs.  For most compilers you can code "non-portable" code and never worry about this issue; but it's always good practice to avoid non-portable code.

The result of sizeof() operations is not guaranteed.  Again, this is due to possible hidden data generated by the particular compiler you are using, as well as structure-padding.  It is recommended that, rather than hard-code sizes, you take the size of a native type instead.  For instance, the example program test.C has codes like:

LE_UINT16	CommandCode;

VR	*vr;

CommandCode = 0x8030;	// C-Echo Response

vr = new ( 0x0000, 0x0100, sizeof(UINT16), &CommandCode, FALSE);

Notes:

NEN data type support is via a "template" class.  This class is not a real C++ template.  The reason behind this is I wanted variable declarations to be simple.  For instance, this is one possible way of declaring endian numeric types:

FixedEndianType < UINT16 >	leValue16 ( LITTLE_ENDIAN ),

beValue16 ( BIG_ENDIAN );

Rather than add this complexity, NEN data types are instantiated like:

LE_UINT16	leValue16;

BE_UINT16	beValue16;


Part 5: DIMSE-C Service Classes

Introduction

CEchoRQ Class

CEchoRSP Class

CStoreRQ Class

CStoreRSP Class

CFindRQ Class

CFindRSP Class

CMoveRQ Class

CMoveRSP Class

Creating your own methods, a CEcho example


Introduction

Currently there are two princple ways to program using this DICOM TCP/IP implementation.  You can choose to code directly to the PDU interface (test.C/.cpp is an example of this), or you can use the pre-built higher level service objects.  These service objects comprise two more layers of abstraction away from the raw PDU interface.  This chapter deals with the first layer away: service methods.

There are eight service methods currently included in the package:

CEchoRQ	C-Echo Request

CEchoRSP	C-Echo Response

CStoreRQ	C-Store Request

CStoreRSP	C-Store Response

CFindRQ	C-Find Request

CFindRSP	C-Find Response

CMoveRQ	C-Move Request

CMoveRSP	C-Move Response

These service methods encapsulate all the "knowledge" of their associatied method type.  It should be noted that while each service provides two functions (Read / Write) these functions take different parameters for each object.

The behavior of each object is unique.  You should check this reference carefully for any side effects.  In general, you can rely on these commonalities:

* If the DICOMCommandObject is passed into a RSP/Write message, that object is usually distorted.  This is tru of CEchoRSP, CStoreRSP.  It is not true of CFindRSP and CMoveRSP.

* No object passed in as a parameter is ever deleted from the free store.  Objects passed in may be used and exist in a dissimilar state, but they are not de-allocated.  You are responsible for removing any dynamically allocated objects.

* Read() calls are boolean type operators.  They do not actually interrogate or generate any sort of response.  The code for a Read() basically checks the Command VR and returns a TRUE / FALSE on wheather is matches it's Command code.

* Write() calls generate the DICOMCommandObject.  They do not check the DICOMDataObject (if any) for correctness.  You are responsible for ensuring that the DICOMDataObject contains the correct data set.

* Every DIMSE-C Service object is an abstract base class.  You must derive an SOP class from the DIMSE-C Service class(es) before you can use them.  This is because each Write() call, calls a virtual function GetUID() to obtain the UID of the SOP class.


CEchoRQ Class

Purpose:

Encapsulate the inner workings of a CEchoRQ method (See Chapter 7 of the DICOM v3 draft).

Theory:

Relies upon DICOMObject classes (ie, not CCO's).

Interface:

BOOL	Read ( DICOMCommandObject	*)

Read() calls are considered "Checks".  They are considered a boolean check returning TRUE if the message is the associated type, or FALSE if it is not.

BOOL	Write ( PDU_Service	*)

Write() constructs the associated DICOM message and sends it to the connected remote DICOM entity associated with the PDU_Service parameter.  The write call will make a virtual function call to GetUID().


CEchoRSP Class

Purpose:

Encapsulate the inner workings of a CEchoRSP method (See Chapter 7 of the DICOM v3 draft).  Response objects require that the DICOMCommandObject sent on the Request object be passed in as a parameter.  The response generated will depend on some of the values inside the DICOMCommandObject.

Theory:

Relies upon DICOMObject classes, (i.e., not CCO's).

Interface:

BOOL	Read ( DICOMCommandObject	*)

Read() calls are considered "Checks".  They are considered a boolean check returning TRUE if the message is the associated type, or FALSE if it is not.

BOOL	Write ( PDU_Service	*, DICOMCommandObject	*)

Write() constructs the associated DICOM message and sends it to the connected remote DICOM entity associated with the PDU_Service parameter.  The write call will make a virtual function call to GetUID().


CStoreRQ Class

Purpose:

Encapsulate the inner workings of a CStoreRQ method (See Chapter 7 of the DICOM v3 draft).

Theory:

Relies upon DICOMObject classes, (i.e., not CCO's).

Interface:

BOOL	Read ( DICOMCommandObject	*,  DICOMDataObject *)

BOOL	Read ( DICOMCommandObject	*)

Read() calls are considered "Checks".  They are considered a boolean check returning TRUE if the message is the associated type, or FALSE if it is not.  If you pass in a pointer to an allocated DICOMDataObject, and if this is a CStoreRQ message, the data section (i.e., the image) will be stored in the DICOMDataObject pointed to by the parameter.

BOOL	Write ( PDU_Service	*, DICOMDataObject	*)

BOOL	Write ( PDU_Service	*)

Write() constructs the associated DICOM message and sends it to the connected remote DICOM entity associated with the PDU_Service parameter.  The write call will make a virtual function call to GetUID().  If you pass in a DICOMDataObject, that object will be sent over the link.  The object will not be returned in a consistent state, (i.e., it will no longer be an image).  You must still delete the DICOMDataObject from the heap.  If you do not pass an object, then you are required to send a DICOMDataObject over the link before further communication can continue.  If you do not, the remote entity should flag an error and/or timeout and close the connection (eventually).


CStoreRSP Class

Purpose:

Encapsulate the inner workings of a CStoreRSP method (See Chapter 7 of the DICOM v3 draft).  Response objects require that the DICOMCommandObject sent on the Request object be passed in as a parameter.  The response generated will depend on some of the values inside the DICOMCommandObject.

Theory:

Relies upon DICOMObject classes (ie, not CCO's).

Interface:

BOOL	Read ( DICOMCommandObject	*)

Read() calls are considered "Checks".  They are considered a boolean check returning TRUE if the message is the associated type, or FALSE if it is not.

BOOL	Write ( PDU_Service	*, DICOMCommandObject	*, UINT16)

BOOL	Write ( PDU_Service	*, DICOMCommandObject	*)

Write() constructs the associated DICOM message and sends it to the connected remote DICOM entity associated with the PDU_Service parameter.  The write call will make a virtual function call to GetUID().  If you pass in a UINT16, that value will be placed in the response code: 0x0000, 0x0900 of the CStoreRSP.  The default value is 0x0000 (Success).


CFindRQ Class

Purpose:

Encapsulate the inner workings of a CFindRQ method (See Chapter 7 of the DICOM v3 draft).

Theory:

Relies upon DICOMObject classes (ie, not CCO's).

Interface:

BOOL	Read (	DICOMCommandObject	*, PDU_Service	*,DICOMDataObject *)

BOOL	Read ( DICOMCommandObject	*)

Read() calls are considered "Checks".  They are considered a boolean check returning TRUE if the message is the associated type, or FALSE if it is not.  If you pass in a pointer to an allocated DICOMDataObject, and if this is a CFindRQ message.  The data section (i.e.,  the image) will be stored in the DICOMDataObject pointed to by the parameter.

BOOL	Write ( PDU_Service	*, DICOMDataObject	*)

BOOL	Write ( PDU_Service	*)

Write() constructs the associated DICOM message and sends it to the connected remote DICOM entity associated with the PDU_Service parameter.  The write call will make a virtual function call to GetUID().  If you pass in a DICOMDataObject, that object will be sent over the link.  The object will not be returned in a consistent state, (i.e., it will no longer be an image).  You must still delete the DICOMDataObject from the heap.  If you do not pass an object, then you are required to send a DICOMDataObject over the link before further communication can continue.  If you do not, the remote entity should flag an error and/or timeout and close the connection (eventually).


CFindRSP Class

Purpose:

Encapsulate the inner workings of a CFindRSP method (See Chapter 7 of the DICOM v3 draft).  Response objects require that the DICOMCommandObject sent on the Request object be passed in as a parameter.  The response generated will depend on some of the values inside the DICOMCommandObject.

Theory:

Relies upon DICOMObject classes, (i.e., not CCO's).

Interface:

BOOL	Read (	DICOMCommandObject	*, PDU_Service  *, DICOMDataObject	*)

BOOL	Read ( DICOMCommandObject	*)

Read() calls are considered "Checks".  They are considered a boolean check returning TRUE if the message is the associated type, or FALSE if it is not.

BOOL	Write (	PDU_Service *, DICOMCommandObject *, UINT16,	DICOMDataObject	*)

BOOL	Write (	PDU_Service *, DICOMCommandObject *, DICOMDataObject	* )

Write() constructs the associated DICOM message and sends it to the connected remote DICOM entity associated with the PDU_Service parameter.  The write call will make a virtual function call to GetUID().  The UINT16 parameter is the value placed in element 0x0000, 0x0900 (Response / Error code).  If you omit this parameter it is generated automatically.  The algorithm for generating it is: if a DICOMDataObject is passed in, then the response code will be 0xff00 (Sub-operations continueing), if the DICOMDataObject is NULL, then the response code will be 0x0000 (successful).


CMoveRQ Class

Purpose:

Encapsulate the inner workings of a CMoveRQ method (See Chapter 7 of the DICOM v3 draft).

Theory:

Relies upon DICOMObject classes, (i.e., not CCO's).

Interface:

BOOL	Read (	DICOMCommandObject *, PDU_Service *, DICOMDataObject *)

BOOL	Read ( DICOMCommandObject	*)

Read() calls are considered "Checks".  They are considered a boolean check returning TRUE if the message is the associated type, or FALSE if it is not.  If you pass in a pointer to an allocated DICOMDataObject, and if this is a CMoveRQ message, the data section (i.e., the image) will be stored in the DICOMDataObject pointed to by the parameter.

BOOL	Write ( PDU_Service	*, DICOMDataObject	*, BYTE *)

Write() constructs the associated DICOM message and sends it to the connected remote DICOM entity associated with the PDU_Service parameter.  The write call will make a virtual function call to GetUID().  If you pass in a DICOMDataObject, that object will be sent over the link.  The object will not be returned in a consistent state, (i.e., it will no longer be an image).  You must still delete the DICOMDataObject from the heap.  If you do not pass an object, then you are required to send a DICOMDataObject over the link before further communication can continue.  If you do not, the remote entity should flag an error and/or timeout and close the connection (eventually).  You must supply an ACR-NEMA address on the Write() call.  This address will place in element 0x0000, 0x0600 of the CMoveRQ message.  The remote entity will send the images to this ACR-Nema address.


CMoveRSP Class

Purpose:

Encapsulate the inner workings of a CMoveRSP method (See Chapter 7 of the DICOM v3 draft).  Response objects require that the DICOMCommandObject sent on the Request object be passed in as a parameter.  The response generated will depend on some of the values inside the DICOMCommandObject.

Theory:

Relies upon DICOMObject classes, (i.e., not CCO's).

Interface:

BOOL	Read (	DICOMCommandObject	*, PDU_Service  *, DICOMDataObject	*)

BOOL	Read ( DICOMCommandObject	*)

Read() calls are considered "Checks".  They are considered a boolean check returning TRUE if the message is the associated type, or FALSE if it is not.

BOOL	Write (	PDU_Service *, DICOMCommandObject *, UINT16 ErrorCode,	UINT16 NumberRemaining,  UINT16 NumberComplete,	UINT16 NumberFailed, UINT16 NumberWarning, 	DICOMDataObject	*)

Write() constructs the associated DICOM message and sends it to the connected remote DICOM entity associated with the PDU_Service parameter.  The write call will make a virtual function call to GetUID().  You must supply all UINT16 values.


Creating your own methods, a CEcho example

cecho.hpp

class	CEchoRQ

{

public:

BOOL	Read ( DICOMCommandObject * );

BOOL	Write ( PDU_Service * );

virtual	BOOL	GetUID ( UID & ) = 0;

};

class	CEchoRSP

{

public:

BOOL	Read ( DICOMCommandObject * );

BOOL	Write ( PDU_Service *, DICOMCommandObject *, UINT16 );

BOOL	Write ( PDU_Service *, DICOMCommandObject * );

virtual	BOOL	GetUID ( UID & ) = 0;

};

cecho.C/.cpp

#	include	"dicom.hpp"

/************************* C-Echo *******************************/

BOOL	CEchoRQ :: Read ( DICOMCommandObject *DCO )

{

if (!DCO)

return ( FALSE );

if (DCO->GetUINT16(0x0000, 0x0100)!=0x0030)

return ( FALSE );	// not a C-Echo-RQ

return ( TRUE );

}

BOOL	CEchoRQ :: Write ( PDU_Service *PDU )

{

DICOMCommandObject	DCO;

VR	*vr;

UINT16	Temp;

LE_UINT16	leCommand, leDSType, leMessageID;

UID	uid;

if (!PDU)

return ( FALSE );

if (!GetUID(uid))

return ( FALSE );

vr = new VR (0x0000, 0x0002, uid.GetSize(),

(void*)uid.GetBuffer(1), FALSE );

DCO.Push ( vr );

leCommand = 0x0030;

vr = new VR (0x0000, 0x0100, sizeof(UINT16), (void*)&leCommand,

FALSE);

DCO.Push ( vr );

leDSType = 0x0101;

vr = new VR (0x0000, 0x0800, sizeof(UINT16), (void*)&leDSType,

FALSE);

DCO.Push ( vr );

Temp = uniq16odd();

leMessageID = Temp;

vr = new VR (0x0000, 0x0110, sizeof(UINT16), (void*)&leMessageID,

FALSE);

DCO.Push ( vr );

if (!PDU->Write(&DCO))

return ( FALSE );

return ( TRUE );

}

BOOL	CEchoRSP :: Read ( DICOMCommandObject *DCO )

{

if ( ! DCO )

return ( FALSE );

if (DCO->GetUINT16(0x0000, 0x0100)!=0x8030)

return ( FALSE );

return ( TRUE );

}

BOOL	CEchoRSP :: Write ( PDU_Service *PDU, DICOMCommandObject *DCO,

UINT16	ErrorCode )

{

DICOMCommandObject	DCOR;

LE_UINT16	leCommand, leError;

VR	*vr;

if ( ! PDU )

return ( FALSE );

if ( ! DCO )

return ( FALSE );

while ( vr = DCO->Pop() )

{

switch (vr->Element)

{

case	0x0002:

case	0x0800:

DCOR.Push ( vr );

break;

case	0x0110:

vr->Element = 0x0120;

DCOR.Push ( vr );

break;

default:

delete vr;

}

}

leCommand = 0x8030;

vr = new VR (0x0000, 0x0100, sizeof(UINT16), &leCommand, FALSE );

DCOR.Push ( vr );

leError = ErrorCode;

vr = new VR (0x0000, 0x0900, sizeof(UINT16), &leError, FALSE );

DCOR.Push ( vr );

if (!PDU->Write(&DCOR))

return ( FALSE );

return ( TRUE );

}

BOOL	CEchoRSP :: Write (PDU_Service *PDU, DICOMCommandObject *DCO)

{

return ( Write ( PDU, DCO, 0x0000 ) );	// Write Success

}


Part 6: SOP Classes

Introduction

Verification1.2.840.10008.1.1

StandardStorageAbstract Base Class

StandardQuery Abstract Base Class

StandardRetrieve Abstract Base Class

Creating your own SOP Classes, a Verification example


Introduction

SOP classes function as the highest level interface between your application and the DICOM TCP/IP transport.  SOP classes use methods from Part 5 (DIMSE-C, etc), and encapsulate an even higher degree of functionality.  To illustrate the difference between methods and SOP classes, consider C-Store.  The DIMSE-C service C-Store object provides a high level CStoreRQ :: Write ( PDU_Service *, DICOMDataObject *) function.  The SOP Class CRStorage provides a similar CRStorage :: Write ( PDU_Service *, DICOMDataObject *).  The SOP class Write() will first send the object using the CStoreRQ object, but then further wait for a CStoreRSP message.  In effect, the program logic of that SOP class exists in the Write() call.

As a programmer you should think of SOP classes as the logic behind sending and receiving DICOM objects.  DIMSE-C services are the methods used to actually send them.

Included are four fundamental types of SOP classes:

Verification	1.2.840.10008.1.1

StandardStorage	Abstract Base Class

CRStorage	1.2.840.10008.5.1.4.1.1.1

CTStorage	1.2.840.10008.5.1.4.1.1.2

USMultiframeStorage	1.2.840.10008.5.1.4.1.1.3

MRStorage	1.2.840.10008.5.1.4.1.1.4

NMStorage	1.2.840.10008.5.1.4.1.1.5

USStorage	1.2.840.10008.5.1.4.1.1.6

SCStorage	1.2.840.10008.5.1.4.1.1.7

StandaloneOverlayStorage	1.2.840.10008.5.1.4.1.1.8

StandaloneCurveStorage	1.2.840.10008.5.1.4.1.1.9

StandaloneModalityLUT	1.2.840.10008.5.1.4.1.1.10

StandaloneVOILUT	1.2.840.10008.5.1.4.1.1.11

GEMRStorage	1.2.840.113619.4.2

GECTStorage	1.2.840.113619.4.3

StandardQuery	Abstract Base Class

PatientRootQuery	1.2.840.10008.5.1.4.1.2.1.1

StudyRootQuery	1.2.840.10008.5.1.4.1.2.2.1

PatientStudyOnlyQuery	1.2.840.10008.5.1.4.1.2.3.1

StandardRetrieve	Abstract Base Class

PatientRootRetrieve	1.2.840.10008.5.1.4.1.2.1.2

StudyRootRetrieve	1.2.840.10008.5.1.4.1.2.2.2

PatientStudyOnlyRetrieve	1.2.840.10008.5.1.4.1.2.3.2

Samples at the end of this section document show how the Verification SOP class is implemented.  You should refer to this in modalling the creation of your own SOP classes.


Verification1.2.840.10008.1.1

Purpose:

Encapsulates the entire Verification class including SCU and SCP roles.

Theory:

A derived class from CEcho-RQ and CEcho-RSP.

Interface:

BOOL	Read ( PDU_Service *, DICOMCommandObject * )

If the DICOMCommandObject is a CEchoRQ message, then a succesful C-Echo-RSP message is generated and sent over the PDU_Service Link.  A TRUE will be returned only if the DICOMCommandObject was a CEchoRQ, and the response was successfully sent.  In both cases the DICOMCommandObject will be altered, but not deleted from the free store.

BOOL	Write ( PDU_Service * )

Send a C-Echo-RQ over a connected PDU_Service object, and wait for a C-Echo-RSP.  If no C-Echo-RSP was sent, or the link was not valid, a FALSE will be returned, otherwise a TRUE.


StandardStorage Abstract Base Class

CRStorage 1.2.840.10008.5.1.4.1.1.1

CTStorage 1.2.840.10008.5.1.4.1.1.2

USMultiframeStorage 1.2.840.10008.5.1.4.1.1.3

MRStorage 1.2.840.10008.5.1.4.1.1.4

NMStorage 1.2.840.10008.5.1.4.1.1.5

USStorage 1.2.840.10008.5.1.4.1.1.6

SCStorage 1.2.840.10008.5.1.4.1.1.7

StandaloneOverlayStorage 1.2.840.10008.5.1.4.1.1.8

StandaloneCurveStorage 1.2.840.10008.5.1.4.1.1.9

StandaloneModalityLUT 1.2.840.10008.5.1.4.1.1.10

StandaloneVOILUT 1.2.840.10008.5.1.4.1.1.11

GEMRStorage 1.2.840.113619.4.2

GECTStorage 1.2.840.113619.4.3

Purpose:

Encapsulates the entire SSC (Storage Service Class) class including SCU and SCP roles.

Theory:

A derived class from CStoreRQ and CStoreRSP.

Interface:

BOOL	Read (

PDU_Service *,

DICOMCommandObject *,

DICOMDataObject * )

If the DICOMCommandObject is a CStoreRQ message, then a succesful CStoreRSP message is generated and sent over the PDU_Service Link, and a DICOMDataObject is read from the link.  A TRUE will be returned only if the DICOMCommandObject was a CStoreRQ, the DICOMDataObject was read, and the response was successfully sent.  In both cases the DICOMCommandObject will be altered, but not deleted from the free store.

BOOL	Write ( PDU_Service *, DICOMDataObject * )

Send a CStoreRQ over a connected PDU_Service object, and send the DICOMDataObject.  Wait for a CStoreRSP.  If no CStoreRSP was sent, or the link was not valid, a FALSE will be returned, otherwise a TRUE.  A TRUE indicates the remote entity sent the CStoreRSP, and the status code was 0x0000 (success).

virtual	UINT16	CheckObject(DICOMDataObject	*)

This function will be called before a call is made to CStoreRSP.  The 0x0900 field of the C-Store-Response message will contain the value returned from this function.  You should overload this function for the following reasons:

To save an object to disk/database before the C-Store-RSP is generated.

To check the validity of the particular IOD.


StandardQuery Abstract Base Class

PatientRootQuery 1.2.840.10008.5.1.4.1.2.1.1

StudyRootQuery 1.2.840.10008.5.1.4.1.2.2.1

PatientStudyOnlyQuery 1.2.840.10008.5.1.4.1.2.3.1

Purpose:

Encapsulates the entire Query Class including SCU and SCP roles.

Theory:

A derived class from CFindRQ and CFindRSP.

Interface:

BOOL	Read ( PDU_Service *, DICOMCommandObject * )

This function call checks the DICOMCommandObject.  If it is a CFindRQ, then the Read() call will call the pure virtual function SearchOn() with a DICOMDataObject.  Further a CFindRSP will be generated for each object returned from the SearchOn().

BOOL	Write ( PDU_Service *, DICOMDataObject * )

Write sends a CFindRQ message over the connected PDU_Service object.  For each CFindRSP is called to CallBack() will be issued.  Before any CFindRSP is sent a call to CallBack(Valid, NULL) will be issued.  For each CFindRSP a call to CallBack ( Valid, Valid ) will be issued.  After the final CFindRSP a call to CallBack(NULL, Valid) will be issued.

virtual	BOOL	SearchOn (

DICOMDataObject *,

Array < DICOMDataObject * > *)

A pure virtual function which you must implement.  This call is issued on incoming CFindRQ messages from remote application entities.  You should perform any database queries here and add to the array pointed to by the parameter.  (Note: Do not allocate an array, use the one pre-allocated within the StandardQuery class.)  The StandardQuery class will handle de-allocate of the DICOMDataObjects.

virtual	BOOL	CallBack (DICOMCommandObject *,DICOMDataObjct *)

A callback routine.  Your derived class must overload this function.  You are not required to do anything.  Normally you would update some display here.


StandardRetrieve Abstract Base Class

PatientRootRetrieve 1.2.840.10008.5.1.4.1.2.1.2

StudyRootRetrieve 1.2.840.10008.5.1.4.1.2.2.2

PatientStudyOnlyRetrieve 1.2.840.10008.5.1.4.1.2.3.2

Purpose:

Encapsulates the entire Retrieve Class including SCU and SCP roles.

Theory:

A derived class from CMoveRQ and CMoveRSP.

Interface:

BOOL	Read ( PDU_Service *, DICOMCommandObject * )

This function call checks the DICOMCommandObject.  If it is a CMoveRQ, then the Read() call will call the pure virtual function SearchOn() with a DICOMDataObject.  Further a CMoveRSP will be generated for each object returned from the SearchOn().

BOOL	Write ( PDU_Service *, DICOMDataObject * )

Write sends a CMoveRQ message over the connected PDU_Service object.  For each CMoveRSP is call to CallBack() will be issued.  Before any CMoveRSP is sent a call to CallBack(Valid, NULL) will be issued.  For each CMoveRSP a call to CallBack ( Valid, Valid ) will be issued.  After the final CFindRSP a call to CallBack(NULL, Valid) will be issued.

virtual	BOOL	SearchOn (

DICOMDataObject *,

Array < DICOMDataObject * > *)

A pure virtual function which you must implement.  This call is issued on incoming CMoveRQ messages from remote application entities.  You should perform any database queries here and add to the array pointed to by the parameter.  (Note: Do not allocate an array, use the one pre-allocated within the StandardRetrieve class.)  The StandardRetrieve class will handle de-allocate of the DICOMDataObjects.

virtual	BOOL	CallBack ( DICOMCommandObject *, DICOMDataObjct *)

A callback routine.  Your derived class must overload this function.  You are not required to do anything.  Normally you would update some display here.

virtual	BOOL	RetrieveOn (

DICOMDataObject	*,

DICOMDataObject	**,

StandardStorage **)

This call will be passed in a DICOMDataObject (returned from a SearchOn()).  You should locate the image in your database, bring it into memory, load it into the result-parameter DICOMDataObject **, and further set a value-result parameter to the correct SSC SOP Service Class for that image type, (i.e., if the image was a CT scan, then you should make the pointer pointed to by the StandardStorage pointer, point to a CTStorage class).

virtual	BOOL	QualifyOn (

BYTE	*RemoteACRNema,

BYTE	*MyACRNema,

BYTE	*RemoteIPAddress,

BYTE	*RemotePortAddress )

During a Read() call, after a SearchOn() but before a RetrieveOn, this pure virtual function will be called.  You must implement this function.  Typically you would look up the RemoteACRNema address, and then copy the IP address (dotted-quad or DNS name) and port address to the strings pointed to by the parameters.  You should also set your ACR-Nema address.  This address will be used in the outgoing CStoreRQ requests generated from the incoming CMoveRQ request.


Creating your own SOP Classes, a Verification example

verify.hpp

// Verification SOP Service Class

class	Verification	:

public	CEchoRQ,

public	CEchoRSP

{

public:

BOOL	GetUID ( UID & );

public:

BOOL	Read ( PDU_Service *, DICOMCommandObject * );

BOOL	Write ( PDU_Service * );

};

verify.C/.cpp

#	include	"dicom.hpp"

BOOL	Verification :: GetUID ( UID &uid )

{

uid.Set("1.2.840.10008.1.1");

return ( TRUE );

}

BOOL	Verification :: Read ( PDU_Service *PDU, DICOMCommandObject *DCO)

{

VR	*vr;

UID	MyUID, uid;

GetUID(MyUID);	// always try and use GetUID to obtain my own uid

if ( ! PDU )

return ( FALSE );

if ( ! DCO )

return ( FALSE );

vr = DCO>GetVR ( 0x0000, 0x0002 );

if ( ! vr )

return ( FALSE );

if ( !SetUID(uid, vr) )

return ( FALSE );

if ( MyUID != uid )

return ( FALSE );

if ( CEchoRQ :: Read ( DCO ) )

{

return ( CEchoRSP :: Write ( PDU, DCO ) );

}

if ( CEchoRSP :: Read ( DCO ) )

{

// No worries..

return ( TRUE );

}

return ( FALSE );	// woa.. corrupted message

}

BOOL	Verification :: Write ( PDU_Service *PDU )

{

DICOMCommandObject	DCO;

if ( ! PDU )

return ( FALSE );

if ( ! CEchoRQ :: Write ( PDU ) )

return ( FALSE );

if(!PDU>Read ( & DCO ))

return (FALSE);

if ( ! CEchoRSP :: Read ( &DCO ) )

return ( FALSE );

return ( TRUE );

}


Part 7: Low-Level Examples

C-Echo Server Process

C-Echo Client Process

C-Find Client

Multi-threaded C-Echo / C-Store server


C-Echo Server Process

BOOL

CEchoServer()

{

PDU_Service	PDU;

DICOMCommandObject	DCO;

DICOMCommandObject	DCOR;

VR	*vr;

LE_UINT16	tuint16;

// PORT is a BYTE string which contains the TCP port number to listen on.

// Most DICOM servers are done on a defacto-standard port 104.  Note that

// that port requires priveledge (ie root) access on UNIX (not on NT).

//

// This call returns TRUE / FALSE.  A FALSE indicates no connection.  No

// connection can result from either a TCP level error (ie bind), or a

// DICOM PDU level error.

//

// Note: This example represents a "toy" server.  A real server should

// multi-thread and take advantage of "driver" sockets and the PDU_Service

// call: Multiplex ( int ).  The third example shows just how to do this.

if(PDU.Listen(PORT))

{

// Since the client started the connection, usually it is up to it

// to send the first command object.

PDU.Read(&DCO);

// Interrogate this object.  This server is rather dumb.  A real

// server would want to more thoroughly investigate the object.

// This loop simply tears open the object, and reconstructs

// a response object from it.

while(vr = DCO.Pop())

{

fprintf(stderr, "Object: (%4.4x, %4.4x), %d Length\n",

vr>Group, vr>Element, vr>Length);

switch(vr>Element)

{

case	0x0000:	delete vr; break;

case	0x0002:	DCOR.Push(vr);	break;

case	0x0100:

tuint16 = 0x8030;	// 0x8030

memcpy(vr>Data, &tuint16, 2);

DCOR.Push(vr);	break;

case	0x0800:	DCOR.Push(vr);	break;

case	0x0110:

vr>Element = 0x0120;

DCOR.Push(vr);	break;

default:

delete vr;

}

}

vr = new VR(0x0000, 0x0900, 0x0002, TRUE);

tuint16 = 0;

memcpy(vr>Data, &tuint16, 2);

DCOR.Push(vr);

// Write the response object back over the link

PDU.Write(&DCOR);

// Close the link.  A real server should loop here and wait for

// another DICOMCommandObject (and should close the link on the

// failed Read() call.  See the CMEchoStoreServer example

PDU.Close();

return ( TRUE );

}

return ( FALSE );

}


C-Echo Client Process

BOOL

CEchoClient(BYTE	*ip, BYTE	*port)

{

PDU_Service	PDU;

DICOMCommandObject	DCO;

DICOMCommandObject	DCOR;

UID	uid;

VR	*vr;

LE_UINT16	tuint16, command, datasettype, messageid;

BYTE	SOP[64];

// CleatAbstractSyntaxs() is not required in this case, because

// PDU_Service is a new instance.

PDU.ClearAbstractSyntaxs();

// Set Local / Remote ACR-Nema addresses.  This call is required

// on outgoing connections.

PDU.SetLocalAddress(LOCAL_ACR);

PDU.SetRemoteAddress(REMOTE_ACR);

// Set the application context.  Usually a good idea to use the DICOM

// Application Context as defined in Chapter 5 of the DICOM standard.

uid.Set("1.2.840.10008.3.1.1.1");

PDU.SetApplicationContext(uid);

// Say that we want to connect to the Verification Service Class.

uid.Set("1.2.840.10008.1.1");

PDU.AddAbstractSyntax(uid);

// At this point we are ready to create the TCP/IP link.  PDU.Connect()

// does just that.

if(!PDU.Connect(ip, port))

{

// Some error.  Print out AAssociateRJ data.  Most common print-outs

// are 1,1,3 (indicating usually that the connection was failed

// at the TCP/IP level, or 1,1,7 which means you tried to connect

// to the wrong ACR-Nema address.

fprintf(stderr, "AAssociateRJ: %d, %d, %d\n",

PDU.AAssociateRJ :: Result,

PDU.AAssociateRJ :: Source,

PDU.AAssociateRJ :: Reason);

return ( FALSE );

}

// Connection is setup, now we construct a DICOMCommandObject such that

// it is a C-Echo-RQ packet.

strcpy((char*) SOP, "1.2.840.10008.1.1");

vr = new VR (0x0000, 0x0002, strlen((char*)SOP), (void*) SOP, FALSE);

DCO.Push(vr);

command = 0x0030;

vr = new VR (0x0000, 0x0100, 0x0002, &command, FALSE);

DCO.Push(vr);

datasettype = 0x0101;

vr = new VR (0x0000, 0x0800, 0x0002, &datasettype, FALSE);

DCO.Push(vr);

messageid = 1;

vr = new VR (0x0000, 0x0110, 0x0002, &messageid, FALSE);

DCO.Push(vr);

// Write the object over the link.

fprintf(stderr, "Writting CEchoRQ %d\n", PDU.Write(&DCO));

fprintf(stderr, "Waiting for CEchoRSP\n");

// Read an entire response object from the link.

if(!PDU.Read(&DCOR))

return ( FALSE );	// associate lost

// Dump the response objects' contents.

while(vr = DCOR.Pop())

{

fprintf(stderr, "Object: (%4.4x, %4.4x), %d Length\n",

vr>Group, vr>Element, vr>Length);

delete vr;

}

// Close the link

PDU.Close();

return ( TRUE );

}


C-Find Client

Note: This is a StudyRoot client.  It also only interogates the first level (STUDY) of the SOP class.  Its purpose is to get a list of patients from a modality / PACS and print them out.

BOOL

CFindClient(BYTE	*ip, BYTE	*port)

{

BOOL	quit;

PDU_Service	PDU;

DICOMCommandObject	DCO;

DICOMCommandObject	DCOR;

DICOMDataObject	DDO;

DICOMDataObject	DDOR;

UID	uid;

VR	*vr;

LE_UINT16	tuint16, command, datasettype, messageid, priority;

BYTE	SOP[64];

BYTE	QLevel[16];

BYTE	AppTitle[64];

BYTE	Star[32];

PDU.ClearAbstractSyntaxs();

PDU.SetLocalAddress(LOCAL_ACR);

PDU.SetRemoteAddress(REMOTE_ACR);

uid.Set("1.2.840.10008.3.1.1.1");	// DICOM App

PDU.SetApplicationContext(uid);

uid.Set("1.2.840.10008.5.1.4.1.2.2.1");

PDU.AddAbstractSyntax(uid);

if(!PDU.Connect(ip, port))

{

// Some error.  Print out AAssociateRJ data

fprintf(stderr, "AAssociateRJ: %d, %d, %d\n",

PDU.AAssociateRJ :: Result,

PDU.AAssociateRJ :: Source,

PDU.AAssociateRJ :: Reason);

return ( FALSE );

}

strcpy((char*) SOP, "1.2.840.10008.5.1.4.1.2.2.1");

vr = new VR (0x0000, 0x0002, strlen((char*)SOP), (void*) SOP, FALSE);

DCO.Push(vr);

command = 0x0020;

vr = new VR (0x0000, 0x0100, 0x0002, &command, FALSE);

DCO.Push(vr);

priority = 0;	// MEDIUM

vr = new VR (0x0000, 0x0700, 0x0002, &priority, FALSE);

DCO.Push(vr);

datasettype = 0x0102;

vr = new VR (0x0000, 0x0800, 0x0002, &datasettype, FALSE);

DCO.Push(vr);

messageid = 3;

vr = new VR (0x0000, 0x0110, 0x0002, &messageid, FALSE);

DCO.Push(vr);

strcpy((char*) QLevel, "STUDY ");

vr = new VR(0x0008, 0x0052, strlen((char*)QLevel), (void*) QLevel,

FALSE);

DDO.Push(vr);

strcpy((char*) AppTitle, "                ");

vr = new VR(0x0008, 0x0054, 16, (void*)AppTitle, FALSE);

DDO.Push(vr);

strcpy((char*) &Star[0], "*");

vr = new VR(0x0008, 0x0018, 0, FALSE);	DDO.Push(vr);

vr = new VR(0x0020, 0x0013, 0, FALSE);	DDO.Push(vr);

vr = new VR(0x0020, 0x000d, 0, FALSE);	DDO.Push(vr);

vr = new VR(0x0010, 0x0010, 0, FALSE);	DDO.Push(vr);

PDU.Write(&DCO);

PDU.Write(&DDO);

quit = 0;

while(!quit)

{

//	fprintf(stderr, "Waiting for CFindRSP");

if(!PDU.Read(&DCOR))

return ( FALSE );	// associate lost

// is this a CFindRSP ?

if(DCOR.GetUINT16(0x0000, 0x0100)!=0x8020)

{

//	fprintf(stderr, "not a CFindRSP: %4.4x\n",

//	DCOR.GetUINT16(0x0000, 0x0100));

PDU.Close();

return(FALSE);

}

// is there a data set?

if(DCOR.GetUINT16(0x0000, 0x0800)==0x0101)

{

//	fprintf(stderr, "no data set included\n");

PDU.Close();

return( TRUE );

}

if(DCOR.GetUINT16(0x0000, 0x0900)==0x0000)	// success

{

PDU.Close();

return ( TRUE );

}

//	fprintf(stderr, "Waiting for data section\n");

if(!PDU.Read(&DDOR))

{

PDU.Close();

return(FALSE);

}

// 	figure out what we got in the data section

//	fprintf(stderr, "Data Object:\n");

while(vr = DDOR.Pop())

{

if(vr>Group == 0x0000)

{

fprintf(stderr, "Data Object:\n");

DumpVR(vr);

while(vr = DDOR.Pop())

DumpVR(vr);

fprintf(stderr, "Command Object:\n");

while(vr = DCOR.Pop())

DumpVR(vr);

PDU.Close();

return ( TRUE );

}

if(vr>Group == 0x0010)

if(vr>Element == 0x0010)

DumpVR(vr);

//	fprintf(stderr, "\tObject: (%4.4x, %4.4x), %d Length\n",

//	vr>Group, vr>Element, vr>Length);

}

while(vr = DCOR.Pop())

;

}

PDU.Close();

return ( TRUE );

}


Multi-threaded C-Echo / C-Store server

BOOL

CMEchoStoreServerProc(int	socketfd)

{

PDU_Service	PDU;

DICOMCommandObject	DCO;

DICOMCommandObject	*DCORPtr;

DICOMDataObject	*DDOPtr;

DICOMCommandObject	DCOR;

VR	*vr;

LE_UINT16	tuint16;

LE_UINT16	Command, MId, MRId, DSet, E200, E300, E700,E900;

// NOTE: PDU.Multiplex(filedes).  This call is saying, here's a just

// connected socket, now go through the regular PDU association, and

// return to me a connected DICOM link.

if(PDU.Multiplex(socketfd))

{

while(TRUE)

{

if(!PDU.Read(&DCO))

return ( FALSE );

switch ( DCO.GetUINT16 ( 0x0000, 0x0100 ) )

{

case	0x0030:	// C-Echo

while(vr = DCO.Pop())

{

switch(vr>Element)

{

case	0x0000:	delete vr; break;

case	0x0002:	DCOR.Push(vr);

break;

case	0x0100:

tuint16 = 0x8030;	// 0x8030

memcpy(vr>Data, &tuint16, 2);

DCOR.Push(vr);

break;

case	0x0800:	DCOR.Push(vr);

break;

case	0x0110:

vr>Element = 0x0120;

DCOR.Push(vr);	break;

default:

delete vr;

}

}

vr = new VR(0x0000, 0x0900, 0x0002, TRUE);

tuint16 = 0;

memcpy(vr>Data, &tuint16, 2);

DCOR.Push(vr);

PDU.Write(&DCOR);

break;

case	0x0001:	// CStore

DDOPtr = new DICOMDataObject;

if(!DDOPtr)

return(FALSE);

if(!PDU.Read(DDOPtr))

return ( FALSE );

// DDOPtr now contains the Image.  Since this

// is an example, just delete it.

delete DDOPtr;

DCORPtr = new DICOMCommandObject;

if(!DCORPtr)

return ( FALSE );

Command = 0x8001;

MId = DCO.GetUINT16(0x0000, 0x0110);

MRId = MId;

DSet = 0x0101;

E200 = DCO.GetUINT16(0x0000, 0x0200);

E300 = DCO.GetUINT16(0x0000, 0x0300);

E700 = 0;

E900 = 0;

vr = new VR(0x0000, 0x0100, 2, &Command,

 FALSE);	DCORPtr>Push(vr);

vr = new VR(0x0000, 0x0110, 2, &MId,

 FALSE);	DCORPtr>Push(vr);

vr = new VR(0x0000, 0x0120, 2, &MRId,

 FALSE);	DCORPtr>Push(vr);

vr = new VR(0x0000, 0x0200, 2, &E200,

 FALSE);	DCORPtr>Push(vr);

vr = new VR(0x0000, 0x0300, 2, &E300,

 FALSE);	DCORPtr>Push(vr);

vr = new VR(0x0000, 0x0700, 2, &E700,

 FALSE);	DCORPtr>Push(vr);

vr = new VR(0x0000, 0x0800, 2, &DSet,

 FALSE);	DCORPtr>Push(vr);

vr = new VR(0x0000, 0x0900, 2, &E900,

 FALSE);	DCORPtr>Push(vr);

while(vr = DCO.Pop())

;

PDU.Write(DCORPtr);

break;

}

}

}

PDU.Close();

return ( TRUE );

}

// Driver routine for Multiplexed Socket I/O (reuseaddress type).  Note,

// in a real server the child should be forked off.

BOOL

CMEchoStoreServer()

{

Socket	MSocket;

if(!MSocket.Listen((char*)PORT))

return ( FALSE );

while(MSocket.Accept())

{

// A Server must be tied down to a particular OS here.  In NT you

// can use CreateThread to create the server within the processes

// own addresses space.  On Solaris you can also create a thread.

// On POSIX you need to fork(), and correctly handle file

// descriptors.

CMEchoStoreServerProc(MSocket.Socketfd);

MSocket.Socketfd = 0;

MSocket.Connected = FALSE;

}

return ( FALSE );	// should never return except on error

}


Part 8: High-Level Examples

DriverApp Class

VerificationApp Class

CTStorageApp Class

MyStudyRootRetrieve

CFindExampleApp

CMoveExampleApp

Composite Object Example


DriverApp Class

#	include	"dicom.hpp"

// Base class for "driven" servers.  In a real server this class

// should implement the fork() for CreateThread()

class	DriverApp

{

protected:

virtual	BOOL	ServerChild ( int ) = 0;

public:

BOOL	Server ( BYTE * );

};

// This Server is a system-independent (non-multitasking) driver.

BOOL	DriverApp	::	Server ( BYTE	*port )

{

Socket	MSocket;

if (!MSocket.Listen ((char*) port ))

return ( FALSE );	// failed on the bind

while (MSocket.Accept() )

{

// Should fork() or CreateThread here.

ServerChild ( MSocket.Socketfd );

MSocket.Socketfd = 0;

MSocket.Connected = FALSE;

}

return ( FALSE );

}

Purpose:

All high-level examples should share a common server driver” class.  This class manages the TCP/IP socket, and forks off (in a system dependent way) the associated Server-Child proc.  This systems dependentness, and the re-usable logic, makes using a DriverApp type class useful.


VerificationApp Class

#	include	dicom.hpp”

class	VerificationApp	:

public	DriverApp

{

Verification	SOPVerification;

private:

BOOL	ServerChild ( int );

public:

BOOL	Client ( BYTE *, BYTE *, BYTE	*, BYTE	* );

};

BOOL	VerificationApp	::	ServerChild (int	socketfd )

{

PDU_Service	PDU;

DICOMCommandObject	DCO;

if(!PDU.Multiplex ( socketfd ))

return ( FALSE );

while(PDU.Read(&DCO))

{

if(!SOPVerification.Read(&PDU, &DCO))

{

PDU.Close();	// something bad

return ( FALSE );

}

DCO.Reset();

}

return ( TRUE );

}

BOOL	VerificationApp	::	Client (

BYTE	*LocalACRNema,

BYTE	*RemoteACRNema,

BYTE 	*ip,

BYTE	*port )

{

UID	uid, Appuid("1.2.840.10008.3.1.1.1");

PDU_Service	PDU;

PDU.SetApplicationContext(Appuid);

SOPVerification.GetUID(uid);

PDU.AddAbstractSyntax(uid);

PDU.SetLocalAddress(LocalACRNema);

PDU.SetRemoteAddress(RemoteACRNema);

if(!PDU.Connect(ip, port))

return ( FALSE );

return(SOPVerification.Write ( & PDU ));

}


CTStorageApp Class

class	CTStorageApp	:

public	DriverApp

{

CTStorage	SOPCTStorage;

MRStorage	SOPMRStorage;

UnknownStorage	SOPUnknownStorage;// last thing to accept

Verification	SOPVerification;

MyStudyRootQueryRetrieve	SOPMyStudyRootQueryRetrieve;

private:

BOOL	ServerChild ( int );

public:

BOOL	Client ( 	BYTE *,

BYTE *,

BYTE *,

BYTE *,

DICOMDataObject *);

};

BOOL	CTStorageApp	::	ServerChild (int	socketfd )

{

PDU_Service	PDU;

DICOMCommandObject	DCO;

DICOMDataObject	*DDO;

VR	*vr;

UINT16	val;

char	name [ 65 ];

if(!PDU.Multiplex ( socketfd ))

return ( FALSE );

while(TRUE)

{

DCO.Reset();

if (!PDU.Read(&DCO))

break;

val = DCO.GetUINT16(0x0000, 0x0100);

fprintf(stdout, "Server, command = %4.4x\n", val);

if (SOPVerification.Read(&PDU, &DCO))

{

fprintf(stdout, "Successful C-Echo\n");

continue;

}

if(SOPMyStudyRootQueryRetrieve.StudyRootQuery :: Read(&PDU, &DCO))

{

fprintf(stdout, "Successful C-Find\n");

continue;

}

if(SOPMyStudyRootQueryRetrieve.StudyRootRetrieve :: Read(&PDU,

&DCO))

{

fprintf(stdout, "Successful C-Move\n");

continue;

}

DDO = new DICOMDataObject;

if(SOPCTStorage.Read(&PDU, &DCO, DDO))

{

// DDO contains object (image) read from C-Store

vr = DDO->GetVR(0x0010, 0x0010);

if ( vr )

{

memset((void*)name, 0, 64);

memcpy((void*)name, vr->Data, vr->Length);

fprintf (stderr, "Successful C-Store for %s\n", name);

}

else

fprintf (stderr, "Successful C-Store\n");

delete DDO;

continue;

}

if(SOPMRStorage.Read(&PDU, &DCO, DDO))

{

fprintf(stderr, "Successful C-Store (MR)\n");

// DDO now contains the image

delete DDO;

continue;

}

if(SOPUnknownStorage.Read(&PDU, &DCO, DDO))

{

fprintf(stderr, "Successful C-Store (unknown class)\n");

// DDO now contains the image

delete DDO;

continue;

}

delete DDO;

PDU.Close();

return ( FALSE );

}

return ( TRUE );

}

BOOL	CTStorageApp	::	Client (

BYTE	*LocalACRNema,

BYTE	*RemoteACRNema,

BYTE 	*ip,

BYTE	*port,

DICOMDataObject	*DDO )

{

UID	uid, Appuid("1.2.840.10008.3.1.1.1");

PDU_Service	PDU;

PDU.SetApplicationContext(Appuid);

SOPCTStorage.GetUID(uid);

PDU.AddAbstractSyntax(uid);

PDU.SetLocalAddress(LocalACRNema);

PDU.SetRemoteAddress(RemoteACRNema);

if(!PDU.Connect(ip, port))

return ( FALSE );

return(SOPCTStorage.Write ( & PDU, DDO ));

}


MyStudyRootRetrieve

// NOTE: In a correct ARM compiler (like Microsoft, or to some extent

// gcc v2.6.0 you can derive MyStudyRootQueryRetrieve directly.

// however gcc v2.5.8 (beta) and v2.5.4 do not compile this way.

// The example here compiles on both gcc v2.6.0 and early v2.5.4/8.

class	MyStudyRootRetrieve	:

public	StudyRootRetrieve

{

public:

CRStorage	SOPCRStorage;

CTStorage	SOPCTStorage;

MRStorage	SOPMRStorage;

public:

BOOL	SearchOn	(DICOMDataObject	*DDO,

Array < DICOMDataObject *> *ADDO);

BOOL	CallBack	(DICOMCommandObject	*DCO,

DICOMDataObject	*DDO);

BOOL	QualifyOn	(BYTE *, BYTE *, BYTE *, BYTE *);

BOOL	RetrieveOn	(	DICOMDataObject *,

DICOMDataObject **,

StandardStorage	** );

};

class	MyStudyRootQueryRetrieve	:

public	StudyRootQuery,

public	MyStudyRootRetrieve

{

BOOL	SearchOn	(DICOMDataObject	*DDO,

Array < DICOMDataObject *> *ADDO)

{ return ( MyStudyRootRetrieve :: SearchOn ( DDO, ADDO ) ); };

BOOL	CallBack	(DICOMCommandObject	*DCO,

DICOMDataObject	*DDO)

{ return ( MyStudyRootRetrieve :: CallBack ( DCO, DDO ) ); };

};

// Call back is not required to do anything, but return TRUE, and

// not destroy/alter the DICOMObjects passed in.  The most simple

// CallBack() routine is a return ( TRUE ); statement.

BOOL	MyStudyRootRetrieve	::	CallBack (

DICOMCommandObject	*DCO,

DICOMDataObject	*DDO )

{

VR	*vr;

char	Name[100];

if (! DCO )

return ( TRUE );	// Initial call back (start)

if (! DDO )

return ( TRUE );	// final call back (end)

memset((void*) Name, 0, 100);

vr = DDO->GetVR(0x0010, 0x0010);

if(!vr)

return ( FALSE );

memcpy((void*) Name, vr->Data, (int)vr->Length);

fprintf(stdout, "Patient : %s\n", Name);

return ( TRUE );

}

// SearchOn presents the hook into your database.  Here you should

// perform your SQL quary, or link to any other database routines.

BOOL	MyStudyRootRetrieve	::	SearchOn (

DICOMDataObject	*DDO,

Array < DICOMDataObject	*>	*ADDO)

{

// generate 5 dummy patients

UINT	Index;

DICOMDataObject	*DDO1;

VR	*vr;

char	Name [ 64 ];

char	SOPClass[64] = "1.2.840.10008.5.1.4.1.1.2";

Index = 0;

while ( Index < 5 )

{

sprintf(Name, "PatientName#%d", Index+1);

++Index;

vr = new VR(0x0010, 0x0010, strlen(Name)+1, TRUE);

strcpy((char*)vr->Data, Name);

DDO1 = new DICOMDataObject;

DDO1->Push ( vr );

vr = new VR (0x0008, 0x0016, strlen ( SOPClass ),

(void *) SOPClass, FALSE);

DDO1->Push ( vr );

ADDO->Add ( DDO1 );

}

return ( TRUE );

}

// Retrieve on is like SearchOn in that it is the hook into

// the database.  However, this time you should actually retrieve

// the entire image, and not just the attributes asked for.

BOOL	MyStudyRootRetrieve	::	RetrieveOn (

DICOMDataObject	*DDO,

DICOMDataObject	**pRDDO,

StandardStorage	**SOPClass)

{

VR	*vr, *vr1;

// A Real RetrieveOn should check the class of the image, and

// set the SOPClass to that.

(*SOPClass) = &SOPCTStorage;

(*pRDDO ) = new DICOMDataObject;

// A Real RetrieveOn should actually get the image..

vr1 = DDO->GetVR(0x0010, 0x0010);

if(!vr1)

vr = new VR ( 0x0010, 0x0010, 0, FALSE );

else

{

vr = new VR ( 0x0010, 0x0010, vr1->Length, TRUE);

memcpy(vr->Data, vr1->Data, vr1->Length);

}

(*pRDDO)->Push ( vr );

return ( TRUE );

}

// QualifyOn is a way of looking up known ACR-NEMA addresses.

// In most cases you should check whatever table you have

// set up for storing other DICOM entities, and return the

// parameters.  The first parameter is passed in, the final

// three on actually value-result,(i.e., you fill them in).

BOOL	MyStudyRootRetrieve	::	QualifyOn (

BYTE	*ACRNema,

BYTE	*MyACRNema,

BYTE	*RemoteIP,

BYTE	*RemotePort)

{

fprintf(stderr, "Search for ACR-Nema: %s\n", (char*)ACRNema);

strcpy ((char*) MyACRNema, "none");

strcpy ((char*) RemoteIP, "rocky.ucdavis.edu");

strcpy ((char*) RemotePort, "10004");

return ( TRUE );

}


CFindExampleApp

class	CFindExampleApp

{

MyStudyRootQueryRetrieve	SOPMyStudyRootQueryRetrieve;

public:

BOOL	Client ( BYTE	*, BYTE	*, BYTE	*, BYTE	* );

};

BOOL	CFindExampleApp	::	Client (

BYTE	*LocalACRNema,

BYTE	*RemoteACRNema,

BYTE 	*ip,

BYTE	*port)

{

UID	uid, Appuid("1.2.840.10008.3.1.1.1");

PDU_Service	PDU;

DICOMDataObject	QDDO;

VR	*vr;

char	*QLevel = "STUDY ";

PDU.SetApplicationContext(Appuid);

SOPMyStudyRootQueryRetrieve.StudyRootQuery :: GetUID(uid);

PDU.AddAbstractSyntax(uid);

PDU.SetLocalAddress(LocalACRNema);

PDU.SetRemoteAddress(RemoteACRNema);

if(!PDU.Connect(ip, port))

return ( FALSE );

vr = new VR(0x0008, 0x0052, 6, (void*)QLevel, FALSE);

QDDO.Push ( vr );

vr = new VR(0x0008, 0x0018, 0, FALSE);	QDDO.Push ( vr );

vr = new VR(0x0020, 0x0013, 0, FALSE);	QDDO.Push ( vr );

vr = new VR(0x0020, 0x000d, 0, FALSE);	QDDO.Push ( vr );

vr = new VR(0x0010, 0x0010, 0, FALSE);	QDDO.Push ( vr );

return(

  SOPMyStudyRootQueryRetrieve.StudyRootQuery :: Write ( & PDU, &QDDO ));

}


CMoveExampleApp

class	CMoveExampleApp

{

MyStudyRootQueryRetrieve	SOPMyStudyRootQueryRetrieve;

public:

BOOL	Client ( BYTE	*, BYTE	*, BYTE	*, BYTE	* );

};

BOOL	CMoveExampleApp	::	Client (

BYTE	*LocalACRNema,

BYTE	*RemoteACRNema,

BYTE 	*ip,

BYTE	*port)

{

UID	uid, Appuid("1.2.840.10008.3.1.1.1");

PDU_Service	PDU;

DICOMDataObject	QDDO;

VR	*vr;

char	*QLevel = "STUDY ";

PDU.SetApplicationContext(Appuid);

SOPMyStudyRootQueryRetrieve.StudyRootRetrieve :: GetUID(uid);

PDU.AddAbstractSyntax(uid);

PDU.SetLocalAddress(LocalACRNema);

PDU.SetRemoteAddress(RemoteACRNema);

if(!PDU.Connect(ip, port))

return ( FALSE );

vr = new VR(0x0008, 0x0052, 6, (void*)QLevel, FALSE);

QDDO.Push ( vr );

vr = new VR(0x0008, 0x0018, 0, FALSE);	QDDO.Push ( vr );

vr = new VR(0x0020, 0x0013, 0, FALSE);	QDDO.Push ( vr );

vr = new VR(0x0020, 0x000d, 0, FALSE);	QDDO.Push ( vr );

vr = new VR(0x0010, 0x0010, 0, FALSE);	QDDO.Push ( vr );

return(

  SOPMyStudyRootQueryRetrieve.StudyRootRetrieve :: Write ( & PDU,

&QDDO, (BYTE*) "none" ));

}


Composite Object Example

#	include	"dicom.hpp"

#	include	"iod.hpp"

// Overloadable Dump routine

BOOL

Dump (

CO_PatientModule	&PatientModule)

{

char	s[128];

PatientModule.PatientsName.VMGet(0, s);

printf ("Patient's Name := %s\n", s);s[0]='\0';

PatientModule.PatientID.VMGet(0, s);

printf ("Patient ID := %s\n", s);s[0]='\0';

PatientModule.PatientsBirthDate.VMGet(0, s);

printf ("Patients Birth Date := %s\n", s);s[0]='\0';

PatientModule.PatientsSex.VMGet(0, s);

printf ("Patients Sex := %s\n", s);s[0]='\0';

return ( TRUE );

}

int

main (

int	argc,

char	*argv[])

{

int	valid_argc;

PDU_Service	PDU;

valid_argc = 1;

while ( valid_argc < argc )

{

DICOMDataObject *DDO = PDU.LoadDICOMDataObject (argv[valid_argc]);

if ( ! DDO )

{

fprintf (stderr, "Could not open IOD File %s\n",

argv[valid_argc]);

}

else

{

CTImageIODModule	CTImage;

CTImage.Set(DDO);	delete DDO;

Dump(CTImage.PatientModule);

}

++valid_argc;

}

return ( 0 );

}