ImageGear for C and C++ on Linux - Updated
DICOM Data Structures
User Guide > How to Work with... > Formats with Additional Functionality > DICOM > DICOM Metadata > DICOM Data Structures

When a DICOM image is loaded into ImageGear, it is loaded into a DIB just like any other supported image. In addition to the actual image, the following DICOM-specific data structures are also loaded: File Meta Information Header (if present) and the Data Set. This section explains how to read and/or manipulate the data in the Data Set or File Meta Information Header, or how to create your own Data Set or File Meta Information Header.

This section provides information about the following:

Get and Set Data Set and Part 10 Header Data

With the exception of the first function listed below, these functions can be used for getting or setting various parts of the Part 10 Header data. These functions are useful when you are creating a new DICOM file.

Function Description
MED_DCM_DS_info_get() Returns the number of Data Elements in the Data Set attached to the HIGEAR.
MED_DCM_DS_orig_TS_get()

Returns the Transfer Syntax used to create the image. It is returned as a MED_DCM_TS_ constant.

When a DICOM image is loaded into ImageGear, the original Transfer Syntax is stored in the HIGEAR. This value is called the Original Transfer Syntax and cannot be changed. You can to read this information using MED_DCM_DS_orig_TS_get(). Even though you can alter the Transfer Syntax Data Element in the Part 10 Header template, the Transfer Syntax of the original image file is kept in case you ever need to know what it was. It does not affect the saving of a DICOM file. To set the Transfer Syntax for an image that you are saving use either the Image Control setting or fill in the TS parameter of MED_DCM_save_DICOM().

MED_DCM_DS_part10_get() Returns the data from a Part 10 item. You specify the item you would like to read. You must supply the item as DCM_PART10_ITEM_ constant.
MED_DCM_DS_part10_set() Sets the data of an item from the Part 10 meta-info header. You specify which item and supply it with new data to be stored to that item. You must supply a DCM_PART10_ITEM_ constant.
MED_DCM_DS_preamble_get() Gets the Preamble from the Part 10 header. Your receiving buffer must be at least 128 bytes. You could also use MED_DCM_DS_part10_set() with the appropriate constant to get this value.
MED_DCM_DS_preamble_set() Sets the Preamble of the Part 10 header. You must supply it with the address of the Preamble and the length of the data you are saving to it. You could also use MED_DCM_DS_part10_get() with the appropriate constant to get this value.

Insert a New Data Element

ImageGear allows you to insert any number of Data Elements to an existing Data Set, or to a new Data Set that you have created by calling MED_DCM_DS_create(). (See the section "Creating a Data Set" below.)

DICOM Data Sets are sorted numerically by Tag number. Therefore, the Current Data Element does not affect the index position where your new Data Element is inserted. ImageGear takes your Tag number and automatically sorts the new DE into the correct position in the array. The Current Data Element does, however, determine the level at which the new DE is stored. For example, if the Current Data Element is in level 0 and has a Tag value of (0028, 0010) and your new DE has a Tag value of (0028, 0015), the new DE will be inserted into level 0 and positioned somewhere below the Current DE so that its unique Element Number fits numerically in ascending order.

If a DE with specified Tag number already exists in the Data Set, it will be overwritten. 

If there are no DEs in the Data Set, the level for the new DE will be 0 or the "top level".

You have complete flexibility in what kind of DEs you can add to the Data Set. For each new DE, you have to supply ImageGear with a Tag structure, a VR, and the data. You can add it to any Group, to any position, with any VR, and with any data that you desire.

An example of using MED_DCM_DS_DE_insert():

 
Copy Code
HIGEAR hIGear;
AT_DCM_TAG tag = 0x00111111;
AT_DCM_VR vr = MED_DCM_VR_CS;
char data[256] = "Data for test element";
DWORD dwSizeOfData = strlen(data);
MED_DCM_DS_DE_insert(hIGear, tag, vr, data, dwSizeOfData);

This function requires you to supply the following values: a Tag, a VR, a Data Field, and the size of the data for the Data Field. Below are brief descriptions of what you would need to know in order to set these arguments.

This section provides information about the following:

Set the Tag Value

All standard Tag values for a DICOM file are assigned constants in enumIGMedTag enumeration. You can also add your own user-defined Tag using MED_DCM_util_tag_info_add().

Set the VR

The DICOM specification assigns specific VRs for each defined public Tag. In other words, for a particular Tag, you must always use the specified VR. There are a few rare exceptions to this rule, and it is for this reason that you should tell MED_DCM_DS_DE_insert() what VR the data has.

If you don't know the VR for a particular Tag that you are adding, you can find out easily by calling the function MED_DCM_util_tag_info_get(), which returns you its VR as a constant.

Set the Data for a VR of CS

There are no constants in ImageGear defined for those Data Elements which have a VR of CS. Refer to Part 3 of the DICOM specification for the valid Code Strings which you can enter for data of type CS.

Here is a sample call to insert a Data Element with a Tag of DCM_TAG_PhotometricInterpretation, which has a VR of CS (Code String). You must use one of the defined values from Part 3 of the DICOM specification. The allowed values are: "MONOCHROME1", "MONOCHROME2", "PALETTE COLOR", "RGB", "HSV", "ARGB", "CMYK", "YBR_FULL", "YBR_FULL_422", and "YBR_PARTIAL_422".

 
Copy Code
MED_DCM_DS_DE_insert(hIGear, DCM_TAG_PhotometricInterpretation, MED_DCM_VR_CS,
"MONOCHROME2", 11);

Set the Data Field

What kind of data can be stored to the Data Field depends on the Tag type, the VR, the restriction flags and the Value Multiplicity (VM) defined for the Tag. It is very helpful to call MED_DCM_util_VR_info_mode()or MED_DCM_util_VR_info_string()so that you can find out what kind of restrictions are placed on the kind of data that you would like to enter. Some types of Data Fields are tricky to work with. VRs of Person Name and Code String place a number of restrictions on what can go into the Data Field, and how it is to be formatted. For these VR types, you must consult Part 5 of the DICOM specification.

The lpData parameter is a binary buffer, which can contain a character string, a BYTE or WORD array, or one or several of numbers, such as Integers or Floats. Below there is an example how to set a value of VR=FD (double):

 
Copy Code
DOUBLE dblRefPixelValueX = 1.234;
MED_DCM_DS_DE_insert(hIGear, DCM_TAG_ReferencePixelPhysicalValueX, MED_DCM_VR_FD,
&dblRefPixelValueX, sizeof(DOUBLE));

Set the Length of a Data Field

Because some VRs allow a range of values, the length of all Data Fields cannot be assumed. For this reason, you must supply ImageGear with the length of your data.

Insert a Sequence of Data Elements

Use the following steps to create and fill a sequence (SQ) of Data Elements:

  1. Insert the Data Element of VR = SQ. This positions you one level lower in the DataSet hierarchy. At this level you can only add items to the sequence, not the Data Elements.
  2. Insert the DCM_TAG_ItemItem Data Element to denote the beginning of a new item in the sequence. This positions you one level lower in the DataSet hierarchy. Now you can add Data Elements to the embedded Data Set.
  3. Insert the data elements you would like to insert to this item.
  4. Insert the DCM_TAG_ItemDeliminationItem Data Element to denote end of the item. This positions you one level higher. Repeat steps 2-4 for every item you would like to add.
  5. Insert the DCM_TAG_SequenceDeliminationItem Data Element to denote the end of the sequence. This moves you one level higher - to the same level where you added the SQ Data Element.

Examples on creating a Data Element Sequence are below. Note that it is completely valid to add same Data Elements to different Items within a Sequence.

 
Copy Code
AT_DCM_TAG  tag;
char        data_str[64];
tag = DCM_TAG_ReferencedStudySequence;
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_SQ, NULL, 0);
tag = DCM_TAG_ItemItem;
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_xx, NULL, 0);
tag = DCM_TAG_ReferencedSOPClassUID;
strcpy( data_str, "1.23.456.7.8.90.1234567890.2");
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_UI, data_str, strlen(data_str));
tag = DCM_TAG_ReferencedSOPInstanceUID;
strcpy( data_str, "1.23.456.7.8.90.1234567890.2.1");
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_UI, data_str, strlen(data_str));
tag = DCM_TAG_ItemDelimitationItem;
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_xx, NULL, 0);
tag = DCM_TAG_ItemItem;
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_xx, NULL, 0);
tag = DCM_TAG_ReferencedSOPClassUID;
strcpy( data_str, "1.23.456.7.8.90.1234567890.3");
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_UI, data_str, strlen(data_str));
tag = DCM_TAG_ReferencedSOPInstanceUID;
strcpy( data_str, "1.23.456.7.8.90.1234567890.3.1");
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_UI, data_str, strlen(data_str));
tag = DCM_TAG_ItemDelimitationItem;
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_xx, NULL, 0);
tag = DCM_TAG_SequenceDelimitationItem;
MED_DCM_DS_DE_insert( hIGear, tag, MED_DCM_VR_xx, NULL, 0);

Delete a Data Element

Data Elements can be deleted by calling MED_DCM_DS_curr_remove(). This function removes the DE designated by the Current Data Element. Therefore, you can use one of the MED_DCM_DS_move_...() functions to position the Current Data Element to the DE you want to remove.

If you've used MED_DCM_DS_move_find() or MED_DCM_DS_move_find_first() to position the Current Data Element, be sure to check the value of the Boolean argument to see whether you successfully found the Tag or Group Number that you were looking for. Otherwise, you might unintentionally delete the wrong DE.

Some calls to MED_DCM_DS_curr_remove() result in deletion of more than one Data Element:

The following types of DEs may not be deleted:

Trying to delete DEs of these types will have no affect on the Data Set. These type of DEs will be automatically deleted by ImageGear when their accompanying set of DEs are deleted.

Get and Set Data of the Current Data Element

Notice that all functions in this group include "curr" as part of their names. Below is a description of these functions..

Function Description
MED_DCM_DS_curr_data_get() Returns the data and size of data from the CDE. The data is returned in its native format. Use MED_DCM_DS_curr_info_get() to get the VR in order to know how to handle the data.
MED_DCM_DS_curr_data_get_string() Same as MED_DCM_DS_curr_data_get() except that the data is always returned as a string.
MED_DCM_DS_curr_data_set() Sets/overwrites the Value Field (data) of the CDE. Check the VR required. You cannot change the VR of an existing DE.
MED_DCM_DS_curr_index_get() Returns the index of the CDE. Lets you know where you are in the Data Set.
MED_DCM_DS_curr_info_get() Returns the following pieces of information about the CDE: Tag, VR, VL, Item Count. This is a very important method. Use it as a precautionary call before modifying info in the CDE or inserting/deleting.

Create a Data Set

If you have a HIGEAR image to which you would like to attach a Data Set, call MED_DCM_DS_create(). This file might have been loaded from a non-DICOM format or may be a DICOM file in which you've destroyed the Data Set (see the section above).

This function creates an empty Data Set and attaches it to the ImageGear's image. The function creates a Data Set structure (outlined above) and fills it with a few Data Elements whose values can be derived from the image. This function also requires you to supply a Transfer Syntax that is saved in the Part 10 Header template as the original Transfer Syntax (as if it was loaded from a DICOM file). If you then save the image and specify a different Transfer Syntax, you overwrite the TS value specified at the time of Data Set creation.

Delete a Data Set

If you have loaded a DICOM image file and do not need to keep the Data Set around you can free up the memory used to store all the Data Elements by calling MED_DCM_DS_destroy(). Once this function is called the remaining image is no different than any other ImageGear image that was created from any other non-DICOM format. The removed Data Set is discarded and cannot be recovered.

Create a Part 10 Header

When a DICOM image is loaded with the ImageGear Medical, a Part 10 Header Template is initialized automatically. If you save the image as a Part 10-compliant image (which is the default option), the values from this template are used to fill the header saved with the file.

For those wishing to modify or read the values stored in the Part 10 Header Template, the component supplies 11 constants. All except the last one correlate directly to the fields found in a Part 10 Header. The last constant can be used by ImageGear to store the length of the Private Info field, and is for informational purposes.

Below is the list of Part 10 constants. Each one is followed by its size in bytes. A check appears next to each field that is considered "Mandatory" by the specification. ("Mandatory" is one of three possible "Types" for a DICOM DE. The other Types are "Optional", and "Mandatory Depending on some Condition".)

Mandatory? MD Component Constant Size of Data Field
Yes DCM_PART10_ITEM_PREAMBLE 128 bytes
Yes DCM_PART10_ITEM_VERSION 2 bytes
Yes DCM_PART10_ITEM_MSSOPCLASSUID Max 64 bytes
Yes DCM_PART10_ITEM_MSSOPINSTUID Max 64 bytes
Yes DCM_PART10_ITEM_TRANSSYNTAXUID Max 64 bytes
Yes DCM_PART10_ITEM_IMPLCLASSUID Max 64 bytes
  DCM_PART10_ITEM_IMPLVERNAME Max 16 bytes
  DCM_PART10_ITEM_SRCAETILE Max 16 bytes
  DCM_PART10_ITEM_PRIVINFOCRUID Max 64 bytes
  DCM_PART10_ITEM_PRIVINFO any length
  DCM_PART10_ITEM_PRIVINFO_SIZE DWORD - length of Priv Info - read only

Please note the following about the above constants:

If you enter data in DCM_PART10_ITEM_PRIVINFO, it is stored with the new Part 10 Header. Also, ImageGear calculates its size and saves this information internally. This read-only size information is not made part of the template but is kept in case you need to know how much memory to allocate when getting the information from DCM_PART10_ITEM_PRIVINFO. DCM_PART10_ITEM_PRIVINFO_SIZE isn't stored to the new Part 10 header.

Here is an example of a Part 10 field being populated:

 
Copy Code
char szPreamble[] = "This DICOM File is MINE!";
DWORD size_of_data;
size_of_data = sizeof(&szPreamble[0]);
MED_DCM_DS_part10_set(hIGear, DCM_PART10_ITEM_PREAMBLE, &szPreamble[0],
&size_of_data);

Update DICOM DataSet without Updating Pixel Data

There are cases when an application needs to update DataSet of a DICOM file, while leaving PixelData unchanged. For example, if the image is compressed using a Lossy compression scheme, this will avoid degradation of image quality.

Use MED_DCM_DS_update_file() function to update DataSet in a DICOM file, without changing its pixel data.

Critical Data Elements

In this manual, we use the term "Critical Data Elements" for those DEs that are used to help load a DICOM image correctly. It's important to note that when certain IP methods are called, the toolkit alters the Data Set. For example, when an aspect of the image has been altered (for instance, by image processing) so, that the Critical DEs no longer correctly describe the image, the Data Set have to be altered. When the image is actually saved, ImageGear also analyzes the DIB and set its own values for the Critical Data Elements of the file being saved. The original values are ignored.

The Critical Data Elements are:

(0028,0010) Rows
(0028,0011) Columns
(0028,0100) Bits Allocated
(0028,0101) Bits Stored
(0028,0102) High Bit
(0028,0004) Photometric Interpretation
(0028,0103) Pixel Representation
(0028,0002) Samples per pixel
(0028,0006) Planar Configuration
(7FE0,0010) Pixel Data
PixelData DE does not contain any actual data, it is always empty. The actual pixel data is stored in ImageGear's DIB, to which the DataSet is attached. Value Representation and Value Length of the Pixel Data tag correspond to VR and VL of PixelData tag, if the DIB is saved to an uncompressed image.