DICOM Basics using .NET and C# - Character Set Handling
Introduction
This is part of my series of articles on the DICOM standard. In this tutorial, we'll explore how DICOM handles international character sets for patient names, institution names, and other text data. Proper character set handling is essential for healthcare systems operating in multilingual environments.
DICOM defines specific mechanisms for encoding text in various character sets, from basic ASCII to full Unicode support via UTF-8. Understanding these mechanisms ensures that patient demographic data is correctly displayed and preserved across different systems and locales.
Prerequisites
Before you begin, ensure you have the following:
- A .NET development environment (Visual Studio or Visual Studio Code)
- The Fellow Oak DICOM library (fo-dicom) installed via NuGet
- Basic understanding of DICOM concepts from previous tutorials
- You can find all the code demonstrated in this tutorial on GitHub here
“Language is the road map of a culture. It tells you where its people come from and where they are going.” ~ Rita Mae Brown
The Theory Behind Character Set Handling
Character encoding is fundamentally about mapping human writing systems to numbers that computers can store and transmit. The challenge is that there are thousands of characters across hundreds of scripts worldwide. Early computing assumed ASCII (128 characters sufficient for English) would be enough. DICOM, as a global standard for healthcare, must handle patient names in any language.
The evolution from code pages to Unicode reflects computing history. ISO 8859 series created separate 256-character sets for different language groups (Latin-1 for Western European, ISO 8859-5 for Cyrillic, etc.). This worked for monolingual systems but failed when a German hospital needed to store a Chinese patient's name. Unicode solved this by creating one universal character set with over 140,000 characters covering virtually all writing systems.
UTF-8's design is elegant: it encodes ASCII characters in one byte (identical to ASCII), uses 2-4 bytes for other characters, and is self-synchronizing (you can find character boundaries by examining any byte). This backward compatibility with ASCII and efficiency for Western text made it the dominant encoding on the web and the recommended choice for DICOM (ISO_IR 192).
The code extension mechanism (ISO 2022) predates Unicode and allows switching between character sets within a single string using escape sequences. This was necessary for Japanese, which uses multiple scripts: kanji (ideographs), hiragana, katakana, and romaji. While complex, it enabled internationalization before Unicode was widely supported. Legacy systems may still use this approach.
The Person Name representation with three component groups (Alphabetic, Ideographic, Phonetic) addresses a specific need in Asian contexts. A Japanese name might be written in kanji (ideographic), have a pronunciation guide in hiragana (phonetic), and a romanization for Western systems (alphabetic). DICOM's structure preserves all three representations, enabling display appropriate to context.
Understanding DICOM Character Sets
DICOM uses the Specific Character Set attribute (0008,0005) to indicate how text data is encoded within a dataset. The key concepts include:
- Default Character Set: ASCII (ISO 646) when Specific Character Set is absent
- Single-Byte Sets: ISO 8859 series for European languages
- Multi-Byte Sets: UTF-8 for Unicode, GB18030 for Chinese
- Code Extension: ISO 2022 for Asian languages with multiple scripts
Character Set Reference
Here are the commonly used character sets in DICOM:
| Character Set | Code | Use Case |
|---|---|---|
| ASCII | (empty) | Default, basic Latin characters |
| ISO 8859-1 (Latin-1) | ISO_IR 100 | Western European (French, German, Spanish) |
| ISO 8859-2 (Latin-2) | ISO_IR 101 | Central European (Polish, Czech) |
| ISO 8859-5 | ISO_IR 144 | Cyrillic (Russian) |
| ISO 8859-6 | ISO_IR 127 | Arabic |
| ISO 8859-7 | ISO_IR 126 | Greek |
| ISO 8859-8 | ISO_IR 138 | Hebrew |
| UTF-8 | ISO_IR 192 | Unicode (RECOMMENDED) |
| GB18030 | GB18030 | Chinese |
Step 1 of 4: Default ASCII Character Set
When no Specific Character Set is specified, DICOM defaults to ASCII. This limits text to basic Latin characters:
using System;
using System.Diagnostics;
using FellowOakDicom;
namespace DicomCharacterSetHandling
{
public class Program
{
public static void Main(string[] args)
{
try
{
LogToDebugConsole("=== DICOM Character Set Handling Demo ===");
LogToDebugConsole("");
// Demo 1: Default ASCII character set
DemonstrateDefaultCharacterSet();
// Demo 2: Latin-1 for Western European
DemonstrateLatin1CharacterSet();
// Demo 3: UTF-8 Unicode
DemonstrateUtf8CharacterSet();
// Demo 4: Japanese character set
DemonstrateJapaneseCharacterSet();
}
catch (Exception e)
{
LogToDebugConsole($"Error: {e.Message}");
}
}
/// <summary>
/// Default ASCII character set - no Specific Character Set specified
/// </summary>
private static void DemonstrateDefaultCharacterSet()
{
LogToDebugConsole("--- Demo 1: Default (ASCII) ---");
var dataset = new DicomDataset();
// No Specific Character Set - defaults to ASCII
// Only basic Latin characters allowed: A-Z, a-z, 0-9, basic punctuation
dataset.Add(DicomTag.PatientName, "Doe^John");
dataset.Add(DicomTag.InstitutionName, "General Hospital");
LogToDebugConsole("Patient Name: Doe^John");
LogToDebugConsole("Institution: General Hospital");
LogToDebugConsole("Specific Character Set: (not specified - ASCII default)");
LogToDebugConsole("Supported characters: A-Z, a-z, 0-9, basic punctuation");
}
private static void LogToDebugConsole(string message)
{
Debug.WriteLine(message);
}
}
}
Step 2 of 4: ISO 8859-1 (Latin-1) for Western European Languages
For Western European languages with accented characters, use ISO 8859-1 (ISO_IR 100):
/// <summary>
/// ISO 8859-1 (Latin-1) for Western European languages
/// </summary>
private static void DemonstrateLatin1CharacterSet()
{
LogToDebugConsole("");
LogToDebugConsole("--- Demo 2: ISO 8859-1 (Latin-1) ---");
var dataset = new DicomDataset();
// Set ISO 8859-1 (Latin-1) character set
dataset.Add(DicomTag.SpecificCharacterSet, "ISO_IR 100");
// Now we can use accented characters
// French: François, German: Müller, Spanish: José
dataset.Add(DicomTag.PatientName, "Müller^François");
dataset.Add(DicomTag.InstitutionName, "Hôpital Général de Zürich");
LogToDebugConsole("Patient Name: Müller^François");
LogToDebugConsole("Institution: Hôpital Général de Zürich");
LogToDebugConsole("Specific Character Set: ISO_IR 100 (ISO 8859-1, Latin-1)");
LogToDebugConsole("Supports: Western European languages (French, German, Spanish, etc.)");
}
Step 3 of 4: UTF-8 Unicode (Recommended)
UTF-8 (ISO_IR 192) is the recommended character set for new implementations. It supports all Unicode characters, including Asian scripts:
/// <summary>
/// UTF-8 Unicode - recommended for new implementations
/// </summary>
private static void DemonstrateUtf8CharacterSet()
{
LogToDebugConsole("");
LogToDebugConsole("--- Demo 3: UTF-8 (Unicode) ---");
var dataset = new DicomDataset();
// Set UTF-8 character set - supports all Unicode characters
dataset.Add(DicomTag.SpecificCharacterSet, "ISO_IR 192");
// UTF-8 supports all scripts
// Chinese: 王小明, Japanese: 山田太郎, Korean: 김철수
// Arabic: محمد أحمد, Russian: Иван Петров, Greek: Νίκος Παπαδόπουλος
LogToDebugConsole("Examples of names in different scripts:");
LogToDebugConsole("");
LogToDebugConsole(" Chinese: 王小明 (Wang Xiaoming)");
LogToDebugConsole(" Japanese: 山田太郎 (Yamada Taro)");
LogToDebugConsole(" Korean: 김철수 (Kim Cheolsu)");
LogToDebugConsole(" Arabic: محمد أحمد (Muhammad Ahmad)");
LogToDebugConsole(" Russian: Иван Петров (Ivan Petrov)");
LogToDebugConsole(" Greek: Νίκος Παπαδόπουλος (Nikos Papadopoulos)");
LogToDebugConsole("");
LogToDebugConsole("Specific Character Set: ISO_IR 192 (UTF-8)");
LogToDebugConsole("Supports: All Unicode characters - RECOMMENDED for new implementations");
}
Step 4 of 4: Japanese and Code Extension Character Sets
Asian languages like Japanese require special handling with multiple character set components for different scripts (alphabetic, ideographic, phonetic):
/// <summary>
/// Japanese character set with code extensions
/// </summary>
private static void DemonstrateJapaneseCharacterSet()
{
LogToDebugConsole("");
LogToDebugConsole("--- Demo 4: Japanese ---");
var dataset = new DicomDataset();
// Japanese requires multiple character sets with code extensions
// The backslash indicates code extension for additional components
dataset.Add(DicomTag.SpecificCharacterSet, @"\ISO 2022 IR 87");
LogToDebugConsole("Japanese names use three components:");
LogToDebugConsole(" Alphabetic: Yamada^Taro (Romaji)");
LogToDebugConsole(" Ideographic: 山田^太郎 (Kanji characters)");
LogToDebugConsole(" Phonetic: やまだ^たろう (Hiragana characters)");
LogToDebugConsole("");
LogToDebugConsole("Person Name format with components:");
LogToDebugConsole(" Alphabetic=Ideographic=Phonetic");
LogToDebugConsole(" Yamada^Taro=山田^太郎=やまだ^たろう");
LogToDebugConsole("");
LogToDebugConsole(@"Specific Character Set: \ISO 2022 IR 87");
LogToDebugConsole("Note: Backslash indicates code extension for additional components");
}
Person Name Components in DICOM
DICOM Person Names can have up to three component groups, especially useful for Asian names:
| Component | Description | Example |
|---|---|---|
| Alphabetic | Single-byte characters | Yamada^Taro |
| Ideographic | Ideographic characters | 山田^太郎 |
| Phonetic | Phonetic representation | やまだ^たろう |
Within each component group, the name is further divided:
Family^Given^Middle^Prefix^Suffix
The complete format for multilingual names:
Alphabetic=Ideographic=Phonetic
Best Practices for Character Set Handling
- Use UTF-8 (ISO_IR 192): Recommended for all new implementations
- Always Specify Character Set: Don't rely on defaults
- Test with International Data: Verify correct display of accented and non-Latin characters
- Handle Encoding Errors: Gracefully handle malformed character data
- Consider Legacy Systems: Some older systems may not support UTF-8
Code Extension Character Sets Reference
For systems using ISO 2022 code extensions:
| Character Set | Code | Language/Script |
|---|---|---|
| JIS X 0201 | ISO 2022 IR 13 | Japanese Katakana |
| JIS X 0208 | ISO 2022 IR 87 | Japanese Kanji |
| JIS X 0212 | ISO 2022 IR 159 | Japanese Supplementary |
| KS X 1001 | ISO 2022 IR 149 | Korean |
| GB 2312 | ISO 2022 IR 58 | Chinese Simplified |
Conclusion
Proper character set handling is essential for healthcare systems that serve diverse patient populations. DICOM provides comprehensive support for international character sets, from basic ASCII to full Unicode via UTF-8.
For new implementations, UTF-8 (ISO_IR 192) is strongly recommended as it supports all Unicode characters and simplifies internationalization. However, when integrating with legacy systems, understanding the various ISO 8859 and ISO 2022 character sets remains important for proper data exchange and display.
Please check out the next tutorial in this series where we cover DICOM private tags.