DICOM Basics using Java - Encapsulated Documents
Introduction
This is part of my series of articles on the DICOM standard. In this tutorial, we'll explore DICOM Encapsulated Documents, which allow you to store non-DICOM documents like PDF reports, CDA documents, and 3D models within DICOM objects for storage in PACS alongside images.
This capability is commonly used for radiology reports, pathology reports, consent forms, and other clinical documents that need to be associated with imaging studies.
Prerequisites
Before you begin, ensure you have the following:
- Java JDK installed (Java 8 or later)
- PixelMed Java DICOM Toolkit
- A PDF file to encapsulate (optional)
- You can find all the code demonstrated in this tutorial on GitHub here
“The soul becomes dyed with the color of its thoughts.” ~ Marcus Aurelius
The Theory Behind Encapsulated Documents
Encapsulated Documents address a fundamental challenge in healthcare IT: document unification. Clinical care generates diverse document types - reports, images, waveforms, PDFs - but patients need a unified longitudinal record.
The Document Heterogeneity Problem
Before DICOM encapsulation, clinical documents lived in separate silos:
- PACS: Stored images but not text reports
- RIS: Stored report text but couldn't associate with images
- Document Management: Stored PDFs without clinical context
- EMR: Attempted to link everything but with proprietary mechanisms
Encapsulated Documents allow any document type to be stored in PACS with the same patient/study associations as images. A radiology report PDF becomes a DICOM object linked to the imaging study it describes.
The DICOM Wrapper Concept
Encapsulation wraps the original document with DICOM metadata:
- Patient Module: Links document to correct patient
- Study Module: Associates with imaging study
- Series Module: Modality="DOC" identifies as document
- Encapsulated Document Module: Contains MIME type and the document bytes
The original document is preserved bit-for-bit in the Encapsulated Document attribute - a PDF encapsulated in DICOM can be extracted and will be identical to the original.
XDS-I and Cross-Enterprise Sharing
Encapsulated Documents play a key role in IHE's Cross-Enterprise Document Sharing for Imaging (XDS-I) profile. When sharing imaging data between organizations:
- Reports can be shared alongside images
- Both documents and images are retrievable via the same mechanisms
- Metadata in the DICOM wrapper enables document registry indexing
The 3D Printing Revolution
STL and OBJ encapsulation (added to DICOM recently) enables storing 3D-printable models derived from medical imaging. A surgeon can:
- View CT images in PACS
- Generate 3D model of patient anatomy
- Store model as encapsulated STL in same study
- Print physical model for surgical planning
The model is permanently associated with its source imaging and available anywhere the study is accessible.
Encapsulated Document SOP Classes
| SOP Class | UID | MIME Type | Use Case |
|---|---|---|---|
| Encapsulated PDF | 1.2.840.10008.5.1.4.1.1.104.1 | application/pdf | Reports, forms |
| Encapsulated CDA | 1.2.840.10008.5.1.4.1.1.104.2 | text/xml | HL7 CDA documents |
| Encapsulated STL | 1.2.840.10008.5.1.4.1.1.104.3 | model/stl | 3D printing models |
| Encapsulated OBJ | 1.2.840.10008.5.1.4.1.1.104.4 | model/obj | 3D surface models |
| Encapsulated MTL | 1.2.840.10008.5.1.4.1.1.104.5 | model/mtl | 3D model materials |
Creating an Encapsulated PDF
package com.saravanansubramanian.dicom.pixelmedtutorial;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.pixelmed.dicom.*;
public class CreateEncapsulatedPdfDemo {
public static void main(String[] args) {
try {
System.out.println("=== DICOM Encapsulated PDF Creation Demo ===\n");
String pdfFilePath = "C:\\path\\to\\report.pdf";
String outputFile = "C:\\temp\\encapsulated_pdf.dcm";
// Read the PDF file
byte[] pdfData = readFileBytes(pdfFilePath);
System.out.println("PDF file size: " + pdfData.length + " bytes");
// Create the encapsulated PDF DICOM object
AttributeList list = createEncapsulatedPdf(
pdfData,
"Doe^John",
"PAT123",
"19700101",
"M",
"ACC456",
"Chest CT Report",
"1.2.3.4.5.6.7.8.9" // Study Instance UID to link to
);
// Add file meta information
FileMetaInformation.addFileMetaInformation(
list,
TransferSyntax.ExplicitVRLittleEndian,
"OurAET"
);
// Write the file
list.write(outputFile);
System.out.println("\nEncapsulated PDF created: " + outputFile);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
private static byte[] readFileBytes(String filePath) throws Exception {
File file = new File(filePath);
byte[] data = new byte[(int) file.length()];
try (FileInputStream fis = new FileInputStream(file)) {
fis.read(data);
}
return data;
}
}
Building the Encapsulated PDF Attributes
private static AttributeList createEncapsulatedPdf(
byte[] pdfData, String patientName, String patientId,
String patientBirthDate, String patientSex,
String accessionNumber, String documentTitle,
String studyInstanceUID) throws Exception {
AttributeList list = new AttributeList();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
Date now = new Date();
String currentDate = dateFormat.format(now);
String currentTime = timeFormat.format(now);
// === SOP Common Module ===
Attribute sopClass = new UniqueIdentifierAttribute(TagFromName.SOPClassUID);
sopClass.addValue(SOPClass.EncapsulatedPDFStorage);
list.put(sopClass);
Attribute sopInstance = new UniqueIdentifierAttribute(TagFromName.SOPInstanceUID);
sopInstance.addValue(UniqueIdentifierAttribute.createUID());
list.put(sopInstance);
// === Patient Module ===
Attribute patNameAttr = new PersonNameAttribute(TagFromName.PatientName);
patNameAttr.addValue(patientName);
list.put(patNameAttr);
Attribute patIdAttr = new LongStringAttribute(TagFromName.PatientID);
patIdAttr.addValue(patientId);
list.put(patIdAttr);
// === Encapsulated Document Series Module ===
Attribute modalityAttr = new CodeStringAttribute(TagFromName.Modality);
modalityAttr.addValue("DOC"); // Document modality
list.put(modalityAttr);
// === Encapsulated Document Module ===
Attribute burnedIn = new CodeStringAttribute(TagFromName.BurnedInAnnotation);
burnedIn.addValue("YES"); // PDF likely contains patient info
list.put(burnedIn);
Attribute docTitleAttr = new LongStringAttribute(TagFromName.DocumentTitle);
docTitleAttr.addValue(documentTitle);
list.put(docTitleAttr);
Attribute mimeType = new LongStringAttribute(TagFromName.MIMETypeOfEncapsulatedDocument);
mimeType.addValue("application/pdf");
list.put(mimeType);
// === The actual PDF data ===
OtherByteAttribute encapDoc = new OtherByteAttribute(TagFromName.EncapsulatedDocument);
encapDoc.setValues(pdfData);
list.put(encapDoc);
return list;
}
Key Attributes for Encapsulated Documents
| Tag | Name | Description |
|---|---|---|
| (0008,0016) | SOP Class UID | 1.2.840.10008.5.1.4.1.1.104.1 for PDF |
| (0008,0060) | Modality | DOC |
| (0008,0064) | Conversion Type | WSD (Workstation) |
| (0028,0301) | Burned In Annotation | YES if contains PHI |
| (0042,0010) | Document Title | User-friendly title |
| (0042,0012) | MIME Type | application/pdf |
| (0042,0011) | Encapsulated Document | The document bytes |
Privacy Considerations
Encapsulated documents require special attention for privacy:
- Burned In Annotation: Set to YES if the document contains PHI
- De-identification: Standard DICOM anonymization tools cannot modify PDF content
- Document Title: Should not contain PHI
- Redaction: Consider using redacted PDFs for teaching/research
Common Use Cases
| Use Case | Document Type | Notes |
|---|---|---|
| Radiology Reports | Final signed reports | |
| Pathology Reports | PDF/CDA | Diagnostic findings |
| Consent Forms | Patient consent documentation | |
| Prior Exam Reports | Historical reports | |
| Referral Letters | Referring physician letters | |
| Lab Results | CDA | HL7 CDA structured documents |
| 3D Print Models | STL | Surgical planning models |
Conclusion
DICOM Encapsulated Documents provide a standardized way to store non-image documents alongside medical images in PACS. This enables a unified archive for all patient-related clinical documents, improving workflow efficiency and data accessibility.
When implementing encapsulated documents, pay careful attention to privacy considerations, as the document content is not directly accessible to standard DICOM anonymization tools. In the next tutorial in this series, I will cover DICOM Presentation States for storing display settings separately from images. See you then!