Core DICOM Concepts

Section 8 of 27
30% complete

Understanding these fundamental concepts is essential for working effectively with DICOM data.

Attribute Types

DICOM defines three attribute types that indicate requirements for data elements. Understanding these types is critical when creating or validating DICOM files, as violations can cause interoperability failures or rejected storage requests. Type designations determine whether attributes must be present and whether they must contain values.

Type 1 (Required and Must Have Value)

Type 1 attributes are mandatory and must contain meaningful data. Omitting these attributes or leaving them empty will cause validation failures and rejection by most DICOM systems. Common Type 1 attributes include UIDs and modality identifiers.

// Must be present, must have a valid value
// Cannot be empty - will cause validation errors

dicomImage.Attributes["0020000D"].Value = DicomUID.Generate(); // Study Instance UID
dicomImage.Attributes["00080060"].Value = "CT";                 // Modality

// Wrong: Empty Type 1 attribute
// dicomImage.Attributes["0020000D"].Value = ""; // ERROR!

Type 2 (Required But May Be Empty)

Type 2 attributes must be present in the dataset, but their values may be empty when the information is unknown or unavailable. This allows systems to acknowledge that a field exists while indicating that no data is available. Use empty strings rather than omitting these attributes entirely.

// Must be present, but value can be empty if unknown
// Use empty string when information is unavailable

dicomImage.Attributes["00100010"].Value = ""; // Patient Name - can be empty
dicomImage.Attributes["00080020"].Value = ""; // Study Date - can be empty

// The attribute MUST exist, but value is optional

Type 3 (Optional)

Type 3 attributes are completely optional and may be omitted from the dataset entirely. Only include these attributes when you have valid information to store. Adding Type 3 attributes with empty values provides no benefit and unnecessarily increases file size.

// May or may not be present
// Only add if you have the information

if (!string.IsNullOrEmpty(patientBirthDate))
{
    dicomImage.Attributes["00100030"].Value = patientBirthDate; // Patient Birth Date
}
// No error if attribute is completely absent

Type Summary

TypePresentValueExample Tags
Type 1RequiredRequiredStudy Instance UID, Modality
Type 2RequiredMay be emptyPatient Name, Study Date
Type 3OptionalOptionalPatient Birth Date, Study Description

Information Object Definitions (IODs)

IODs define the structure and content of DICOM objects. They specify what information must or may be present.

IOD Module Structure

CT Image IOD Structuresaravanansubramanian.coman IOD is assembled from modules — here, the four modules for a single CT slicePatient ModuleWHO IS BEING IMAGEDPatient Name(0010,0010)Type 2Patient ID(0010,0020)Type 2Patient Birth Date(0010,0030)Type 3Patient Sex(0010,0040)Type 3General Study ModuleWHICH EXAMStudy Instance UID(0020,000D)Type 1Study Date(0008,0020)Type 2Study Time(0008,0030)Type 2Accession Number(0008,0050)Type 2General Series ModuleGROUPS OF IMAGESModality(0008,0060)Type 1Series Instance UID(0020,000E)Type 1Series Number(0020,0011)Type 2CT Image ModuleTHE PIXELS AND CT-SPECIFIC METADATAImage Type(0008,0008)Type 1Instance Number(0020,0013)Type 1Pixel Data(7FE0,0010)Type 1KVP(0018,0060)Type 2Slice Thickness(0018,0050)Type 2Type 1 · required, must have a valueType 2 · required, may be emptyType 3 · optional

SOP Classes (Service-Object Pair Classes)

SOP Classes combine an IOD with a set of DIMSE services. They define what you can DO with an object. When establishing DICOM network connections, you must negotiate which SOP Classes both parties support. Knowing the correct SOP Class UID for each modality type is essential for storage, query, and retrieval operations.

Common SOP Classes

The following constants define frequently used SOP Class UIDs. Store these in a centralized location in your codebase to ensure consistency and ease maintenance when adding support for new modalities.

public static class SOPClasses
{
    // Storage SOP Classes
    public const string CTImageStorage = "1.2.840.10008.5.1.4.1.1.2";
    public const string MRImageStorage = "1.2.840.10008.5.1.4.1.1.4";
    public const string SecondaryCaptureStorage = "1.2.840.10008.5.1.4.1.1.7";
    public const string UltrasoundImageStorage = "1.2.840.10008.5.1.4.1.1.6.1";

    // Query/Retrieve SOP Classes
    public const string StudyRootQueryRetrieve = "1.2.840.10008.5.1.4.1.2.2.1";
    public const string PatientRootQueryRetrieve = "1.2.840.10008.5.1.4.1.2.1.1";

    // Worklist SOP Class
    public const string ModalityWorklistFind = "1.2.840.10008.5.1.4.31";

    // Verification SOP Class
    public const string Verification = "1.2.840.10008.1.1";
}

SOP Class and Services

CT Image Storage SOP Classsaravanansubramanian.comone SOP Class · four DIMSE services it can participate inCT Image Storage SOP Class1.2.840.10008.5.1.4.1.1.2C-STOREsendCT imagesC-FINDquery forCT imagesC-GETretrievedirectlyC-MOVEmove todestinationSOP Class UID goes into tag (0008,0016); a fresh SOP Instance UID goes into (0008,0018)
// Setting SOP Class in code
dicomImage.Attributes["00080016"].Value = "1.2.840.10008.5.1.4.1.1.2"; // SOP Class UID
dicomImage.Attributes["00080018"].Value = DicomUID.Generate();         // SOP Instance UID

Transfer Syntaxes

Transfer Syntaxes define how data is encoded at the binary level. They specify byte ordering, whether Value Representations are explicitly stated, and what compression algorithm (if any) is applied to pixel data. Choosing the right transfer syntax affects file size, interoperability, and processing performance.

Components of Transfer Syntax

Transfer syntax selection involves three independent choices that combine to determine the final encoding format. Understanding these components helps you choose appropriate syntaxes for different use cases.

Transfer Syntax Compositionsaravanansubramanian.comthree independent choices combine to determine the on-wire encodingTransfer Syntax = Byte Order + VR Encoding + CompressionByte Orderinghow multi-byte values are storedLittle EndianLSB first — most common;Intel / AMD defaultrecommendedBig EndianMSB firstlegacy — retired in 2006VR Encodinghow Value Representation is carriedExplicit VRVR is stated in each elementself-describingrecommendedImplicit VRVR is looked up in theDICOM dictionaryCompressionapplied to pixel data onlyUncompressedraw pixel dataLosslessJPEG Lossless · JPEG 2000 Lossless · RLELossyJPEG Baseline · JPEG 2000 LossyExplicit VR Little Endian is the widely-supported default; pick a compression only when file size matters

Common Transfer Syntaxes

Define transfer syntax UIDs as constants for use in association negotiation and file writing operations. The most widely supported syntax is Explicit VR Little Endian, which should be your default choice for maximum interoperability.

public static class TransferSyntax
{
    // Uncompressed
    public const string ImplicitVRLittleEndian = "1.2.840.10008.1.2";     // Default
    public const string ExplicitVRLittleEndian = "1.2.840.10008.1.2.1";   // Recommended
    public const string ExplicitVRBigEndian = "1.2.840.10008.1.2.2";      // Legacy

    // Lossless Compression
    public const string JPEGLossless = "1.2.840.10008.1.2.4.70";
    public const string JPEG2000Lossless = "1.2.840.10008.1.2.4.90";
    public const string RLELossless = "1.2.840.10008.1.2.5";

    // Lossy Compression
    public const string JPEGBaseline = "1.2.840.10008.1.2.4.50";
    public const string JPEG2000Lossy = "1.2.840.10008.1.2.4.91";
}

Choosing Transfer Syntax

Use CaseRecommended Transfer SyntaxReason
ArchivalJPEG 2000 LosslessGood compression, diagnostic quality
Diagnostic readingExplicit VR Little EndianUncompressed, fastest access
Web deliveryJPEG 2000 LossyHigh compression for bandwidth
InteroperabilityExplicit VR Little EndianMost compatible

UIDs (Unique Identifiers)

UIDs uniquely identify DICOM entities following ISO 8824 standard. Every study, series, and instance must have globally unique identifiers to prevent data collisions when images from multiple sources are archived together. UIDs are also used to identify SOP Classes, Transfer Syntaxes, and other DICOM-defined entities.

UID Structure

UIDs follow a hierarchical numeric format where organizations register root prefixes to ensure global uniqueness. Understanding the structure helps you generate valid UIDs and recognize well-known DICOM-defined identifiers.

UID Format: <root>.<organization>.<application>.<instance>
============================================================

Example: 1.2.840.113619.2.55.1.1762295408.1084.1234567890.1

Breakdown:
  1.2.840      = ISO registered (USA)
  113619       = GE Medical Systems
  2.55.1       = Application identifier
  1762295408   = Process/timestamp
  1084         = Counter
  1234567890   = Instance specific
  .1           = Sub-instance

Generating UIDs

Generate UIDs using the SDK’s built-in methods to ensure proper formatting and uniqueness. For production systems, consider registering your organization’s own UID root prefix to maintain namespace isolation and traceability.

// Using DICOMObjects UID generation
string studyUID = DicomUID.Generate();
string seriesUID = DicomUID.Generate();
string instanceUID = DicomUID.Generate();

// Custom UID with organization root
const string MyOrgRoot = "1.2.840.99999"; // Must be registered
string customUID = $"{MyOrgRoot}.{DateTime.Now.Ticks}";

// UID validation
public bool IsValidUID(string uid)
{
    if (string.IsNullOrEmpty(uid)) return false;
    if (uid.Length > 64) return false; // Max 64 characters
    return System.Text.RegularExpressions.Regex.IsMatch(uid, @"^[\d.]+$");
}

Important UID Uses

Different UIDs serve specific purposes within the DICOM hierarchy. Study UIDs are shared across all images from a single examination, while Series UIDs group related images within a study. Understanding these relationships ensures proper data organization in PACS systems.

// Study Instance UID - identifies entire study
// Shared across all series in the study
dicomImage.Attributes["0020000D"].Value = studyUID;

// Series Instance UID - identifies a series
// Unique within the study
dicomImage.Attributes["0020000E"].Value = seriesUID;

// SOP Instance UID - identifies single DICOM object
// Globally unique
dicomImage.Attributes["00080018"].Value = instanceUID;

// Frame of Reference UID - links images spatially
// Shared by images in same coordinate system
dicomImage.Attributes["00200052"].Value = frameOfReferenceUID;

Value Representations (VR)

VR defines the data type of an attribute’s value, similar to data types in programming languages. Each DICOM attribute has a defined VR that specifies how its value should be encoded and interpreted. Understanding VRs is essential for correctly parsing and creating DICOM data, especially when working with Implicit VR transfer syntaxes that require VR lookup from dictionaries.

Common VRs

The following VRs are frequently encountered when working with DICOM data. Each has specific formatting rules and length limits that must be followed for valid DICOM encoding.

// AE - Application Entity (16 bytes max)
// Example: "PACS_SERVER", "CT_SCANNER"

// AS - Age String (4 bytes, format: nnnD/W/M/Y)
// Example: "025Y" for 25 years

// CS - Code String (16 bytes max, uppercase)
// Example: "CT", "MR", "ORIGINAL"

// DA - Date (8 bytes, format: YYYYMMDD)
// Example: "20240115"

// DS - Decimal String (16 bytes max)
// Example: "1.5", "0.25"

// DT - DateTime (26 bytes max)
// Example: "20240115093045.123456"

// IS - Integer String (12 bytes max)
// Example: "512", "256"

// LO - Long String (64 chars max)

// PN - Person Name (64 chars per component)
// Format: LastName^FirstName^MiddleName^Prefix^Suffix
// Example: "Doe^John^A^Dr^Jr"

// SH - Short String (16 chars max)

// SQ - Sequence of Items

// TM - Time (16 bytes, format: HHMMSS.FFFFFF)
// Example: "093045" or "093045.123"

// UI - Unique Identifier (64 bytes max)

// UL - Unsigned Long (4 bytes)

// US - Unsigned Short (2 bytes)

Working with VRs in Code

When processing DICOM data programmatically, you often need to check the VR of attributes to determine proper parsing or formatting. The SDK provides methods to inspect VR information and perform type-appropriate conversions. Multi-valued attributes use backslash delimiters.

// Check VR of an attribute
DicomAttribute attr = dicomImage.Attributes["00100010"];
DicomVR vr = attr.VR;
Console.WriteLine($"VR: {vr}"); // Output: VR: PN

// Convert values based on VR
if (attr.VR == DicomVR.VRDate)
{
    string dateString = attr.Value.ToString();
    DateTime date = DateTime.ParseExact(dateString, "yyyyMMdd", null);
}

// Handle multi-valued attributes (backslash separator)
dicomImage.Attributes["00200037"].Value = "1\\0\\0\\0\\1\\0"; // Image Orientation
string[] orientations = dicomImage.Attributes["00200037"].Value.ToString().Split('\\');

VR Summary Table

VRNameExampleMax Length
AEApplication Entity”PACS_SERVER”16
DADate”20240115”8
DSDecimal String”1.5”16
ISInteger String”512”12
LOLong StringDescription text64
PNPerson Name”Doe^John”64 per component
SHShort String”ACC123”16
TMTime”143000”16
UIUnique Identifier”1.2.840…“64
USUnsigned Short5122 bytes
SQSequenceNested itemsN/A

Understanding these core concepts provides the foundation for all DICOM development work.

Quiz: Core DICOM Concepts

Question 1 of 4

What is a Type 1 attribute in DICOM?