This tutorial shows how to load a DICOM dataset in a C# WinForms application and write user-defined data into private tags. The tutorial also shows how to read and display the stored data after they have been written.
Overview | |
---|---|
Summary | This tutorial covers how to read and write data from DICOM tags in a WinForms C# Application. |
Completion Time | 30 minutes |
Visual Studio Project | Download tutorial project (6 KB) |
Platform | .NET 6 WinForms C# Application |
IDE | Visual Studio 2022 |
Development License | Download LEADTOOLS |
Get familiar with the basic steps of creating a project by reviewing the Add References and Set a License tutorial, before working on the Read and Write DICOM Private Tags - WinForms C# tutorial.
The specifications for Private Data Elements are listed in Part 5 Section 7.8 of the DICOM standard and are intended to be used to contain information that cannot be contained in Standard DICOM Data Elements.
The tutorial will use tags (0027, 1000-1004) to store user-defined data inputted through the WinForms UI.
For the specific rules on the insertion of Private Data tags, see the link included in the See Also section below.
In Visual Studio, create a new C# Windows WinForms project, and add the below necessary LEADTOOLS references.
The references needed depend upon the purpose of the project. References can be added by one or the other of the following two methods (but not both).
If using NuGet references, this tutorial requires the following NuGet package:
Leadtools.Dicom.Pacs.Scu
If using local DLL references, the following DLLs are needed.
The DLLs are located at <INSTALL_DIR>\LEADTOOLS23\Bin\net
:
Leadtools.dll
Leadtools.Core.dll
Leadtools.Codecs.dll
Leadtools.Dicom.dll
For a complete list of which DLL files are required for your application, refer to Files to be Included With Your Application.
The License unlocks the features needed for the project. It must be set before any toolkit function is called. For details, including tutorials for different platforms, refer to Setting a Runtime License.
There are two types of runtime licenses:
Note: Adding LEADTOOLS NuGet and local references and setting a license are covered in more detail in the Add References and Set a License tutorial.
With the project created, the references added, and the license set, coding can begin.
Add the using
statements below to the top.
using Leadtools;
using Leadtools.Codecs;
using Leadtools.Dicom;
Add the following global variables to the Form
class.
DicomDataSet dicomDS;
DicomElement root = null;
int elementGroup = 0x27;
string sUniqueID = "My Private Creator Data Element";
In Solution Explorer, double-click Form1.cs
to display it in the Designer. Click the Events icon in the Properties Window. Then, double-click the Load event to create an event handler if one does not already exist. This will bring up the code behind the form.
Add the following code inside the Form1_Load
event handler to startup the DicomEngine
object.
private void Form1_Load(object sender, EventArgs e)
{
DicomEngine.Startup();
}
In Solution Explorer, double-click Form1.cs
to display it in the Designer. Go to the Toolbox and add the following controls:
setDicomDSButton
with the text: Load DICOM DSreadButton
with the text: ReadclearButton
with the text: ClearwriteButton
with the text: WritedicomDSPathTextBox
tag1000TextBox
tag1001TextBox
tag1002TextBox
tag1003TextBox
tag1004TextBox
Six Label controls to identify the Private Element and each TextBox that will contain the tag data.
Add a new function called SetDSLoadPath()
and add the below code to it.
private String SetDSLoadPath()
{
try
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.InitialDirectory = @"C:\LEADTOOLS23\Resources\Images\DICOM";
dlg.Filter = "DICOM DataSets (*.dcm)|*.dcm";
if (dlg.ShowDialog(this) == DialogResult.OK)
{
return dlg.FileName;
}
else
return null;
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
return null;
}
}
Double-click on the Load DICOM DS button and use the following code to display the dialog used for loading the dataset file.
private void setDicomDSButton_Click(object sender, EventArgs e)
{
try
{
string dataSetPath = SetDSLoadPath();
if (dataSetPath != null)
{
dicomDSPathTextBox.Text = dataSetPath;
if(dicomDS == null)
dicomDS = new DicomDataSet();
dicomDS.Reset();
dicomDS.Load(dataSetPath, DicomDataSetLoadFlags.LoadAndClose);
}
}
catch (Exception ex)
{
dicomDS.Dispose();
MessageBox.Show("Error: " + ex.Message);
}
}
Double-click on the Read button and use the following code to check the loaded DataSet file for the Private Element stored in Group 27 (0027) and load the values stored in the tags to the respective TextBox control in the form.
private void readButton_Click(object sender, EventArgs e)
{
try
{
DicomElement privateCreatorElement = null;
DicomElement privateElement = null;
TextBox[] privateTagValuesTextBoxes =
{
tag1000TextBox,
tag1001TextBox,
tag1002TextBox,
tag1003TextBox,
tag1004TextBox
};
// Check if DS is loaded
if (dicomDS == null)
{
MessageBox.Show("Load a DICOM DataSet First");
return;
}
// Check if the Private Creator Data Element for group 0027 already exists
privateCreatorElement = dicomDS.FindFirstPrivateCreatorDataElement(root, true, sUniqueID, elementGroup);
// If the Private Creator Data Element exists, try to read from it
if (privateCreatorElement != null)
{
// Read some private elements
privateElement = dicomDS.FindFirstPrivateElement(privateCreatorElement);
for (int i = 0; i < 5; i++)
{
// Display Tag number (in hex) and value in tag.
privateTagValuesTextBoxes[i].Text = dicomDS.GetConvertValue(privateElement);
privateElement = dicomDS.FindNextPrivateElement(privateElement, privateCreatorElement);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
Double-click on the Clear button control and add the code below so that the TextBox controls are cleared from any loaded text.
private void clearButton_Click(object sender, EventArgs e)
{
tag1000TextBox.Clear();
tag1001TextBox.Clear();
tag1002TextBox.Clear();
tag1003TextBox.Clear();
tag1004TextBox.Clear();
}
Double-click on the Write button and use the following code to take the values entered in the TextBox controls and store them in the respective Private Data tag indicated. Once stored, the code will prompt the user to save the DataSet containing the Private Tags in a new DataSet file.
private void writeButton_Click(object sender, EventArgs e)
{
try
{
DicomElement privateCreatorElement = null;
DicomElement privateElement = null;
int tag = 0;
string[] privateTagsValues =
{
tag1000TextBox.Text,
tag1001TextBox.Text,
tag1002TextBox.Text,
tag1003TextBox.Text,
tag1004TextBox.Text
};
// Check if DS is loaded
if (dicomDS == null)
{
MessageBox.Show("Load a DICOM DataSet First");
return;
}
// Check if the Private Creator Data Element for group 0027 already exists
privateCreatorElement = dicomDS.FindFirstPrivateCreatorDataElement(root, true, sUniqueID, elementGroup);
// If the Private Creator Data Element does not exist, try to create it
if (privateCreatorElement == null)
{
privateCreatorElement = dicomDS.CreatePrivateCreatorDataElement(root, elementGroup, 0x10, sUniqueID);
DicomTagTable.Instance.Insert(privateCreatorElement.Tag, 0xFFFFFFFF, sUniqueID, privateCreatorElement.VR, 1, 1, 1);
for (int i = 0; i < 5; i++)
{
// Insert private tags
tag = dicomDS.GetNextUnusedPrivateTag(privateCreatorElement);
dicomDS.InsertElement(root, false, tag, DicomVRType.LO, false, 0);
}
}
// Set the values in the private tags
privateElement = dicomDS.FindFirstPrivateElement(privateCreatorElement);
for (int i = 0; i < 5; i++)
{
bool result = dicomDS.SetStringValue(privateElement, new string[] { privateTagsValues[i] });
Console.WriteLine(result.ToString());
privateElement = dicomDS.FindNextPrivateElement(privateElement, privateCreatorElement);
}
// Save
MessageBox.Show("Private Tag Values written successfully. Select a location to save the DS.");
SaveFileDialog dlg = new SaveFileDialog();
dlg.InitialDirectory = @"C:\LEADTOOLS23\Resources\Images\DICOM";
dlg.Filter = "DICOM DataSets (*.dcm)|*.dcm";
dlg.FileName = "PrivateTags.dcm";
if (dlg.ShowDialog(this) == DialogResult.OK)
{
dicomDS.Save(dlg.FileName, DicomDataSetSaveFlags.ExplicitVR);
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
Run the project by pressing F5, or by selecting Debug -> Start Debugging.
If the steps were followed correctly, the application runs and allows the user to load a DICOM DataSet, enter any valid data in each of the TextBox controls corresponding to their respective private tag, then store them into the DataSet using the Write button.
The stored Private Data tags can then be read by loading the output DataSet file and clicking the Read button which will load the values in their respective TextBox control.
This tutorial showed how to use the DicomDataSet
, DicomElement
, and DicomTagTable
classes to read and write Private Data elements in DICOM DataSets.