Introduction to DICOM - Chapter 4 - DICOM Objects


Chapter 4 – DICOM Objects
In chapter 3 we’ve learned about DICOM elements. Every element is one piece of typed data with a pre defined, well specified meaning. There are thousands of DICOM elements (See chapter 6 of the standard) from the very basic attributes of patient name and birth date to the most esoteric uses of 3D surface vortices. In this chapter we’re going to collect elements into image object that is called Secondary Capture Image. 

The guys at DICOM did a lot of very good work and created well defined classes for a very detailed Data Model. This is why I always advise to dig in the DICOM standard before designing your imaging device software because there’s a very good chance that the DICOM technical committees already did the work for you and you can save a lot of expansive design time this way. 

In a way DICOM objects definitions are similar to object oriented programming. I prefer though the analog to interfaces specifications. The motivation to adhere to a standard is to enable interoperability. By detailing information object definitions (IOD’s) DICOM enables us to exchange virtual objects between applications without knowing in advance anything about the application we are going to interface with. 

In this chapter I'm going to complete chapter’s 3 examples by adding elements to the object until it’s a valid Secondary Capture Image according to the DICOM standard. Secondary Capture Image is the simplest DICOM image object. Secondary Captures is not related to any specific device. It has the very basic set of elements that a DICOM application needs in order to display and archive a DICOM image properly.

The DICOM Data Model

The specification of DICOM objects are documented in chapter 3 of the DICOM standard that defines the DICOM data model. In its most simplified form the DICOM Data Model looks like this. 

A simplified view of the DICOM Data Model


The data model defines Information Entities (IE’s); Patient, Study, Series and Image. There are more IE’s like Visit, Equipment, Clinical Trial, Procedure and many others and they are all defined in chapter 3 which is the longest chapter of the standard. The DICOM Data Model that is made of IE's is normalized. It is a perfect relational database definition. The classes of the DICOM Objects however are composites made of modules from different entities. The integration is achieved by applications that exchange composite objects between one another. Each application is responsible for it's own internal normalized database that is private to itself and should not interest any other application and is out of the standard's scope. The way you build your DICOM application internals is completely your business. The only thing that matters is your interfaces. Your application should talk proper DICOM. By the way, the DICOM network protocol that we’ll get to in later chapters also makes a distinction between Normalized and Composite operations and there’s N protocol and C protocol with different commands for each one.

The classes of the DICOM static data model are called SOP Classes and are defined by IOD’s – Information Object Definition. IOD’s are specified in Appendix A of chapter 3 of the standard. An IOD is a collection of Modules and a Module is a collection of elements from one information entity that together represent something. The modules are also defined in chapter 3 of the DICOM standard in appendix C. Two object oriented concepts, composition and reuse, that are used by DICOM is the Modules that are parts shared between different IOD’s.

All DICOM Objects must include the SOP Common Module and modules from the four main IE’s: Patient, Study, Series and Image (Image and Instance are the same in DICOM. Once there were only images but then objects that are not images has been defined and the name thus changed from Image to Instance in order to represent an instance of a SOP class). All DICOM Images, that is DICOM Instances that Are Images, must include the Image Module. Because Every DICOM Object must be part of a Series, all DICOM Objects must include the General Series Module and because all series must be part of a Study, every DICOM Object must include the General Study Module and because every study is made on some patient, all DICOM objects must have a Patient Module. You probably wonder what SOP means? That's an acronym for "Service Object Pair" and please take my word for it, that for now this is all we need to say about that. Maybe when we talk about DICOM Services or understanding DICOM Conformance Statements I'll try to explain where this name comes from, but I'm not sure that it makes much difference. In a word, SOP is a pair of a DICOM Sevice and and DICOM Object like Secondary Capture Object and Storage Service.

Secondary Capture Image IOD

With that understanding at hand, let’s look at the SC Image IOD Modules from section A.8.1.3 of the standard. It looks like this:

IE
Module
Reference
Usage
Patient
Patient
C.7.1.1
M

Clinical Trial Subject
C.7.1.3
U
Study
General Study
C.7.2.1
M

Patient Study
C.7.2.2
U

Clinical Trial Study
C.7.2.3
U
Series
General Series
C.7.3.1
M

Clinical Trial Series
C.7.3.2
U
Equipment
General Equipment
C.7.5.1
U

SC Equipment
C.8.6.1
M
Image
General Image
C.7.6.1
M

Image Pixel
C.7.6.3
M

Device
C.7.6.12
U

Specimen
C.7.6.22
U

SC Image
C.8.6.2
M

Overlay Plane
C.9.2
U

Modality LUT
C.11.1
U

VOI LUT
C.11.2
U

SOP Common
C.12.1
M

Taking out all the lines marked with a U that mark these modules as User optional and leaving only the M lines that stand for Mandatory modules and we are left with eight modules that one of them is actually empty as you will soon find out.

IE
Module
Reference
Usage
Patient
Patient
C.7.1.1
M
Study
General Study
C.7.2.1
M
Series
General Series
C.7.3.1
M
Equipment
SC Equipment
C.8.6.1
M
Image
General Image
C.7.6.1
M

Image Pixel
C.7.6.3
M

SC Image
C.8.6.2
M

SOP Common
C.12.1
M

Note also that in this table there are only two modules that are specific to SC and all the other modules are general and common modules that are shared by many IOD’s. It's very common in DICOM that the mandatory elements are very few and there are a lot of optional elements. This is not unique to the DICOM standard and is common to many standards and sometime leads to uncertainties and ambiguities or gaps as we sometime call them. These gaps led IHE to publish technical frameworks that further specify the use of the standard and narrow the options. The IHE initiative is a great success and participating in IHE connect-a-thon is an outstanding opportunity to test systems in a very realistic integration environment. 

During the design of your application, when you need to add some data to an object and don’t find a proper place for it, remember these optional modules that we’ve omitted here and look for a place to put your data in them before defining private elements, modules and objects. DICOM let you define new elements that are called private elements and we’ll look at that later on but as already said more than once, there’s a very good chance that these guys have already did the work for you and defined a solution to your problem and went through the process of validating it and it is probably documented very well in the standard. After all, the DICOM standard is more than 3,000 pages long.

Element Types

To finish our digging in the DICOM standard, we now need to replace every line in the modules table with the module's definition from appendix C of chapter 3 of the DICOM standard. If you look at the standard you will see that every module is rather large and includes many elements but luckily, like the optional modules, many of the elements are optional too. In the modules tables elements are marked with a ‘Type’ column that can be 1 for Mandatory with actual value (not zero length), 2 for Mandatory that can be null (zero length) or 3 for optional. 1 and 2 can also have a ‘C’ for conditional so 1C is mandatory if some condition, that is detailed in the module table, is met and the same for 2C. 

So we are now going to copy the modules but only the 1 and 2 elements dumping all the 3’s and also 1C and 2C’s that their condition is obviously not met for our example. Remember that we are talking interoperability so striving to the simplest object that as many systems as possible can understand is our goal. 

Next to every element I’m going to add the C# code to add it into the object and at the end we’re going to have all the code at hand.

Unique Identifiers (UID’s)

One last thing, before we dive into the code, I’d like to say a word about Unique Identifiers. DICOM makes extensive use of Unique Identifiers. Almost every entity in the DICOM Data Model has a unique identifier. In DICOM every SOP Class have its UID. All pre-define UID’s including the SOP Class UID’s are documented in chapter 6 of the DICOM standard. A DICOM Object is an Instance of such class and is called SOP Instance and it also has a UID called SOP Instance UID. DICOM defines a mechanism in order to make sure UID’s are globally Unique. Every DICOM application should acquire a ‘root’ UID that is used as a prefix to the UID’s it creates. Every entity in the DICOM Data Model also has a UID with the exception of the patient. Patients are identified using the combination of their name and ID. Studies, Series, all have UID’s. DICOM Archives (PACS) should use the UID’s to index their databases so when other applications make searches (Queries) they can refer to objects using the UID’s and the archive can respond to the searches quickly. 

As I said earlier, every DICOM Image Object has patient, study, series, and image modules. In our example we’ll generate new UID’s for Series Instance UID and SOP Instance UID (that is the Image UID). In "proper" DICOM integration the Study Instance UID is provided by the department IT system (RIS/PACS) through a DICOM service called Modality Worklist but devices can default to creating the Study Instance UID if it’s not provided from an external system. The Series Instance UID and SOP Instance UID are always generated by the Imaging device. The definition of a DICOM series is a set of DICOM Instances that were generated together by the same equipment at the same operation. You can read the exact definition in section A.1.2.3 of chapter 3 of the standard.


Creating a Secondary Capture DICOM Image
// create the object
DCXOBJ o = new DCXOBJ();
Table C.7-1
 PATIENT MODULE ATTRIBUTES

Attribute Name
Tag
Type
Attribute Description
// Create element
DCXELM e = new DCXELM();

Patient's Name
(0010,0010)
2
Patient's full name.
// Patient name
// But we set it to "DOE^JOHN"
e.Init((int)DICOM_TAGS_ENUM.PatientsName);
o.insertElement(e);
Patient ID
(0010,0020)
2
Primary hospital identification number or code for the patient.
// Patient ID - type 2 can be empty
e.Init((int)DICOM_TAGS_ENUM.patientID);
o.insertElement(e);
Patient's Birth Date
(0010,0030)
2
Birth date of the patient.
e.Init((int)DICOM_TAGS_ENUM.PatientBirthDate);
o.insertElement(e);
Patient's Sex
(0010,0040)
2
Sex of the named patient.
Enumerated Values:
            M = male
            F = female
            O = other
e.Init((int)DICOM_TAGS_ENUM.PatientsSex);
o.insertElement(e);

Table C.7-3
GENERAL STUDY MODULE ATTRIBUTES

Attribute Name
Tag
Type
Attribute Description

Study Instance UID
(0020,000D)
1
Unique identifier for the Study.
// Let's assume we got a Study Instance
// UID from the department IT system
// and that it's 1.2.3.4.5.6.7
e.Init((int)DICOM_TAGS_ENUM.studyInstanceUID);
e.Value = "1.2.3.4.5.6.7";
o.insertElement(e);
Study Date
(0008,0020)
2
Date the Study started.
// Let's say the study was created now         e.Init((int)DICOM_TAGS_ENUM.StudyDate);
e.Value = DateTime.Now;
o.insertElement(e);
Study Time
(0008,0030)
2
Time the Study started.
e.Init((int)DICOM_TAGS_ENUM.StudyTime);
e.Value = DateTime.Now;
o.insertElement(e);
Referring Physician's Name
(0008,0090)
2
Name of the patient's referring physician
e.Init((int)DICOM_TAGS_ENUM.ReferringPhysicianName);
o.insertElement(e);

Study ID
(0020,0010)
2
User or equipment generated Study identifier.
e.Init((int)DICOM_TAGS_ENUM.StudyID);
o.insertElement(e);
Accession Number
(0008,0050)
2
A RIS generated number that identifies the order for the Study.
e.Init((int)DICOM_TAGS_ENUM.AccessionNumber);
o.insertElement(e);
Table C.7-5a
GENERAL SERIES MODULE ATTRIBUTES

Attribute Name
Tag
Type
Attribute Description

Modality
(0008,0060)
1
Type of equipment that originally acquired the data used to create the images in this Series. See C.7.3.1.1.1 for Defined Terms.
// Modality is type 1 in 
// Generalseries module but
// it is also type 3 in SC
// Equipment module that
// overtakes in this case so we
// can leave it out of the object
Series Instance UID
(0020,000E)
1
Unique identifier of the Series.
// Let's generate a
// Series Instance UID
DCXUID uid = new DCXUID();
e.Init((int)DICOM_TAGS_ENUM.seriesInstanceUID);
e.Value = uid.CreateUID(UID_TYPE.UID_TYPE_SERIES);
o.insertElement(e);
Series Number
(0020,0011)
2
A number that identifies this Series.
e.Init((int)DICOM_TAGS_ENUM.SeriesNumber);
o.insertElement(e);
Laterality
(0020,0060)
2C
Laterality of (paired) body part examined. Required if the body part examined is a paired structure and Image Laterality (0020,0062) or Frame Laterality (0020,9072) are not sent. Enumerated Values:
            R = right
            L = left
Note:        Some IODs support Image Laterality (0020,0062) at the Image level or Frame Laterality(0020,9072) at the Frame level in the Frame Anatomy functional group macro, which can provide a more comprehensive mechanism for specifying the laterality of the body part(s) being examined.
e.Init((int)DICOM_TAGS_ENUM.Laterality);
o.insertElement(e);
Table C.8-24
SC EQUIPMENT MODULE ATTRIBUTES

Attribute Name
Tag
Type
Attribute Description

Conversion Type
(0008,0064)
1
Describes the kind of image conversion. Defined Terms :
            DV       = Digitized Video
            DI         = Digital Interface
            DF        = Digitized Film
            WSD    = Workstation
            SD       = Scanned Document
            SI         = Scanned Image
            DRW    = Drawing
            SYN     = Synthetic Image
e.Init((int)DICOM_TAGS_ENUM.ConversionType);
e.Value = "DRW";
o.insertElement(e);
Modality
(0008,0060)
3
Source equipment for the image. This type definition shall override the definition in the General Series Module.
See C.7.3.1.1.1 for Defined Terms.
// See comment above about Modality
Note that here I left in a type 3 element named Modality. Read the description and see why. What it says here is that a SC image doesn’t have to have a Modality tag.

Table C.7-9
GENERAL IMAGE MODULE ATTRIBUTES

Attribute Name
Tag
Type
Attribute Description

Instance Number
(0020,0013)
2
A number that identifies this image.
Note:        This Attribute was named Image Number in earlier versions of this Standard.
e.Init((int)DICOM_TAGS_ENUM.InstanceNumber);
o.insertElement(e);
Patient Orientation
(0020,0020)
2C
Patient direction of the rows and columns of the image. Required if image does not require Image Orientation (Patient) (0020,0037) and Image Position (Patient) (0020,0032). May be present otherwise. See C.7.6.1.1.1 for further explanation.
Note:        IOD’s may have attributes other than Patient Orientation, Image Orientation, or Image Position (Patient) to describe orientation in which case this attribute will be zero length.
// Let's assume the condition
// for all the 2C's bellow
// is not met
Content Date
(0008,0023)
2C
The date the image pixel data creation started. Required if image is part of a series in which the images are temporally related.
Note:        This Attribute was formerly known as Image Date.

Content Time
(0008,0033)
2C
The time the image pixel data creation started. Required if image is part of a series in which the images are temporally related.

Table C.7-11b
IMAGE PIXEL MACRO ATTRIBUTES
// The Image Pixel module is
// completely set by RZDCX when
// we insert the bitmap or jpeg
// We'll discuss this module later on
o.SetBMPFrames("my_image.bmp");
Attribute Name
Tag
Type
Attribute Description

Samples per Pixel
(0028,0002)
1
Number of samples (planes) in this image. See C.7.6.3.1.1 for further explanation.

Photometric Interpretation
(0028,0004)
1
Specifies the intended interpretation of the pixel data. See C.7.6.3.1.2 for further explanation.

Rows
(0028,0010)
1
Number of rows in the image.

Columns
(0028,0011)
1
Number of columns in the image

Bits Allocated
(0028,0100)
1
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. See PS 3.5 for further explanation.

Bits Stored
(0028,0101)
1
Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. See PS 3.5 for further explanation.

High Bit
(0028,0102)
1
Most significant bit for pixel sample data. Each sample shall have the same high bit. See PS 3.5  for further explanation.

Pixel Representation
(0028,0103)
1
Data representation of the pixel samples. Each sample shall have the same pixel representation. Enumerated Values:
            0000H = unsigned integer.
            0001H = 2's complement

Pixel Data
(7FE0,0010)
1C
A data stream of the pixel samples that comprise the Image. See C.7.6.3.1.4 for further explanation.
Required if Pixel Data Provider URL (0028,7FE0) is not present.

Planar Configuration
(0028,0006)
1C
Indicates whether the pixel data are sent color-by-plane or color-by-pixel. Required if Samples per Pixel (0028,0002) has a value greater than 1. See C.7.6.3.1.3 for further explanation.

Note: in the Image Pixel Module I left out all the 1C elements related to Palette because we’re going to create here a RGB image.

Table C.8-25
SC IMAGE MODULE ATTRIBUTES

Note: all the elements in this module are type 3.

Table C.12-1
SOP COMMON MODULE ATTRIBUTES

Attribute Name
Tag
Type
Attribute Description

SOP Class UID
(0008,0016)
1
Uniquely identifies the SOP Class. See C.12.1.1.1 for further explanation. See also PS 3.4.
// The SOP Class UID of
// SC Image is
e.Init((int)DICOM_TAGS_ENUM.sopClassUid);
e.Value = "1.2.840.10008.5.1.4.1.1.7";
o.insertElement(e);
SOP Instance UID
(0008,0018)
1
Uniquely identifies the SOP Instance. See C.12.1.1.1 for further explanation. See also PS 3.4.
// We've instanciated a DCXUID
// above. Let's use it again
// to create a SOP Instance UID
e.Init((int)DICOM_TAGS_ENUM.sopInstanceUID);
e.Value = uid.CreateUID(UID_TYPE.UID_TYPE_INSTANCE);
o.insertElement(e);
Specific Character Set
(0008,0005)
1C
Character Set that expands or replaces the Basic  Graphic Set.
Required if an expanded or replacement character set is used.
See C.12.1.1.2 for Defined Terms.
// Let's default to latin 1
// and leave it out



Now it’s time to add a dump command at the end of this code and see what we’ve got. Here’s the complete function:


        public DCXOBJ CreateSCImage()
        {
            // create the object
            DCXOBJ o = new DCXOBJ();
            // Create element
            DCXELM e = new DCXELM();
            // Patient name
            // But we set it to "DOE^JOHN"
            e.Init((int)DICOM_TAGS_ENUM.PatientsName);
            o.insertElement(e);
            // Patient ID - type 2 can be empty
            e.Init((int)DICOM_TAGS_ENUM.patientID);
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.PatientBirthDate);
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.PatientsSex);
            o.insertElement(e);

            // Let's assume we got a Study Instance
            // UID from the department IT system
            // and that it's 1.2.3.4.5.6.7
            e.Init((int)DICOM_TAGS_ENUM.studyInstanceUID);
            e.Value = "1.2.3.4.5.6.7";
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.PatientsSex);
            o.insertElement(e);

            // Let's say the study was created now
            e.Init((int)DICOM_TAGS_ENUM.StudyDate);
            e.Value = DateTime.Now;
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.StudyTime);
            e.Value = DateTime.Now;
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.ReferringPhysicianName);
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.StudyID);
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.AccessionNumber);
            o.insertElement(e);

            // Modality is type 1 in 
            // Generalseries module but
            // it is also type 3 in SC
            // Equipment module that
            // overtakes in this case so we
            // can leave it out of the object

            // Let's generate a
            // Series Instance UID
            DCXUID uid = new DCXUID();
            e.Init((int)DICOM_TAGS_ENUM.seriesInstanceUID);
            e.Value = uid.CreateUID(UID_TYPE.UID_TYPE_SERIES);
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.SeriesNumber);
            o.insertElement(e);

            e.Init((int)DICOM_TAGS_ENUM.Laterality);
            o.insertElement(e);


            e.Init((int)DICOM_TAGS_ENUM.ConversionType);
            e.Value = "DRW";
            o.insertElement(e);

            // See comment above about Modality

            e.Init((int)DICOM_TAGS_ENUM.InstanceNumber);
            o.insertElement(e);

            // Let's assume the condition
            // for all the 2C's bellow
            // is not met

            // The Image Pixel module is
            // completely set when
            // we insert set the bitmap or jpeg
            // See chapter 3 of this tutorial.
            // We'll discuss this module later on
            o.SetBMPFrames("my_image.bmp");

            // The SOP Class UID of
            // SC Image is
            e.Init((int)DICOM_TAGS_ENUM.sopClassUid);
            e.Value = "1.2.840.10008.5.1.4.1.1.7";
            o.insertElement(e);

            // We've instanciated a DCXUID
            // above. Let's use it again
            // to create a SOP Instance UID
            e.Init((int)DICOM_TAGS_ENUM.sopInstanceUID);
            e.Value = uid.CreateUID(UID_TYPE.UID_TYPE_INSTANCE);
            o.insertElement(e);

            // Let's default to latin 1
            // and leave the character set out

            // Let's dump the object to text file
            o.Dump("my_image.txt");


            // And don't forget to save it too
            o.saveFile("my_image.dcm");

            return o;
        }

And here’s the dump:

# Dicom-Data-Set
# Used TransferSyntax: UnknownTransferSyntax
(0008,0016) UI =SecondaryCaptureImageStorage            #  26, 1 SOPClassUID
(0008,0018) UI [2.16.124.113543.6021.1.3.3727584845.2784.1322776593.2] #  54, 1 SOPInstanceUID
(0008,0020) DA [20111201]                               #   8, 1 StudyDate
(0008,0030) TM [235633.000]                             #  10, 1 StudyTime
(0008,0050) SH (no value available)                     #   0, 0 AccessionNumber
(0008,0064) CS [DRW]                                    #   4, 1 ConversionType
(0008,0090) PN (no value available)                     #   0, 0 ReferringPhysicianName
(0010,0010) PN (no value available)                     #   0, 0 PatientName
(0010,0020) LO (no value available)                     #   0, 0 PatientID
(0010,0030) DA (no value available)                     #   0, 0 PatientBirthDate
(0010,0040) CS (no value available)                     #   0, 0 PatientSex
(0020,000d) UI [1.2.3.4.5.6.7]                          #  14, 1 StudyInstanceUID
(0020,000e) UI [2.16.124.113543.6021.1.2.3727584845.2784.1322776593.1] #  54, 1 SeriesInstanceUID
(0020,0010) SH (no value available)                     #   0, 0 StudyID
(0020,0011) IS (no value available)                     #   0, 0 SeriesNumber
(0020,0013) IS (no value available)                     #   0, 0 InstanceNumber
(0020,0060) CS (no value available)                     #   0, 0 Laterality
(0028,0002) US 3                                        #   2, 1 SamplesPerPixel
(0028,0004) CS [RGB]                                    #   4, 1 PhotometricInterpretation
(0028,0006) US 0                                        #   2, 1 PlanarConfiguration
(0028,0010) US 50                                       #   2, 1 Rows
(0028,0011) US 50                                       #   2, 1 Columns
(0028,0100) US 8                                        #   2, 1 BitsAllocated
(0028,0101) US 8                                        #   2, 1 BitsStored
(0028,0102) US 7                                        #   2, 1 HighBit
(0028,0103) US 0                                        #   2, 1 PixelRepresentation
(7fe0,0010) OB ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff\ff... # 7500, 1 PixelData

Couple of notes about this dump (highlighted).

First you can see the UID of this instance. Whenever you run this code again, a new UID will be generated. The same goes for Series Instance UID.

See the (7fe0,0010) element? This is the pixel data. The pixels from the bitmap image we’ve converted. It is 7500 bytes long because the image I converted is 50x50 and there's 3 bytes per pixel (Red, Green and Blue).

Look at Study Date (0008,0020) and Study Time (0008,0030). The DA (Date) VR (Value Representation) is defined as formatted date string YYYYMMDD and the TM (Time) VR is a time formatted string with format HHMMSS.TTT. You can see that I ran this example four minutes before midnight on December 1st 2011.

Here’s a short quiz: 

Look at the length Photometric Interpretation (0028,0004). The value is “RGB” but the value length is 4 bytes. Why?

This was quite long and complicated chapter covring the DICOM Data Model, Information Entities, Modules, Information Objects Definitions (IOD's), SOP Classes and SOP Instances, Unqiue Identifiers and element types. Most important, we've walked through the process of reading chapter 3 of the standard and translating it to a software that creates the DICOM Object according to the standard specifications. I hope it wasn't too complicated. As always, comments and questions are most welcome.

27 comments:

  1. Thanks dude for a nice article.
    4th byte is used for representing luminence value. Is that right?

    ReplyDelete
  2. Thanks Anonymous.
    There are images with 4 channels: Red, Green Blue and Alpha where the Alpha Channel is the transparency. In this case the value of element (0028,0004) Photometric Interpretation would be "RGBA".
    My question was about the length of (0028,0004) Photometric Interpretation itself. In the example it is "RGB", a 3 characters code string but the length in the DICOM element is 4 and not 3. Hint: this was discussed in chapter 3 when describing the DICOM elements.

    ReplyDelete
    Replies
    1. Is it because the length of VR type values is always even? Its padded by null 0x0 or space 0x20 if its not.

      Delete
  3. Can you please post a link to Dicom Standard document you are referring to
    (example: A.1.2.3 of chapter 3 of the standard)

    ReplyDelete
  4. The latest DICOM standard on the DICOM home page is here:
    ftp://medical.nema.org/medical/dicom/2011/

    Chapter 3 is:
    ftp://medical.nema.org/medical/dicom/2011/11_03pu.pdf

    The file names start with the year (11) and then the chapter number so chapter 3 is 11_03.
    You can download the PDF and Word versions.

    ReplyDelete
  5. The length of all DICOM elements must be even so although RGB is 3 bytes it is padded to 4 to satisfy the rule that you hinted at.

    ReplyDelete
  6. This is one of the best approaches to demonstrating to people how to populate an SOP instance with data using your toolkit. As I said before, your toolkit was well thought out and makes the development straight forward for those of us who are learning DICOM for the first time. Well done.

    ReplyDelete
  7. Thanks Greg. I don't know what to say.

    ReplyDelete
  8. Yes, the length of the elemnt must always be even so RGB has a pading space at the end making it 4 bytes long.

    ReplyDelete
  9. Which parameter should be set to determine display range of image ?

    ReplyDelete
  10. I believe you refer to WC/WW - the elements that control the display contrast and brightness.
    WC - Window Center is the middle of the display range
    WW - Window Width is the width
    The values that will be displayed are in the range WC-WW/2 to WC+WW/2.
    There are other elements that affects the display. I plan to write a post about image display soon.

    ReplyDelete
  11. I need some help (more specific) about saving pixel data of unsigned short image.
    Can I turn to you directly via email or in any other possible way?

    ReplyDelete
  12. Sure. Send email to info@roniza.com

    ReplyDelete
  13. Fantastic explanation!!

    Keep it up. You are doing a great service to DICOM professionals!

    ReplyDelete
  14. I am tryig to learn DICOM in 3 days,for a job intervie,wwhat is the best way to go about that.
    Thanks

    ReplyDelete
    Replies
    1. Good luck! Well, you've defiantly started in the right place :)
      I would suggest the following:
      1. Read this tutorial
      2. Make a list of DICOM toolkits, choose the most relevant for the job (C#/Java Windows/Mac/Linux) and read more about it. If you can play with it to make a Storage SCU and maybe a A Q/R SCU you're doing good
      3. Make sure you know all the buzzwords. Memorize these lists:
      - A list of large players in the industry (GE, Siemens, Fuji, CareStream, McKeson, ...
      - A list of DICOM viewers (ClearCanvas, k-PACS, DicomWorks, ...
      - A list of DICOM Toolkits (RZDCX - figure out the rest ;)
      - DICOM terminology (tag, transfer syntax, ae title, dicom conformance statement, association)
      - Some other technologies (IHE, HL7, WADO
      At that point I think you'll be ready

      Delete
  15. I'm sort of in the same situation where I have to learn this fast. The guy that does Dicom related issues for the company got frustrated and resigned yesterday. The weeks before quitting he continually complained about DiCom and the servers being slow, about 6 seconds to load a single image in the viewer he designed. Client complaining, now they throw me in the fire, yikes. Hopefully I can learn something here to bring the times down.

    ReplyDelete
  16. Please tell me the logic to apply the VOI LUT in the DICOM Image buffer.
    I have extracted the LUT DATA from the VOI LUT Sequence present in the DICOM Header but on applying the LUT, my image is not getting reconstructed. Please help me in this. I have to show the Dicom image buffer after getting VOI LUT applied on the WPF Control Image Viewer and for that i need to convert the proccesed buffer into Bitmap Image.

    ReplyDelete
  17. I am new to medical imaging, I am interested in applying some visualization techniques on tractography on DT-MRI images. What exactly do I need to dig into in terms of DICOM? do I have to study all the details provided here?

    ReplyDelete
    Replies
    1. Hi Sherif,
      What's provided here is very high level background on different aspects of the DICOM standard and it's use. Maybe you can start by learning what data is available to you in the DICOM Objects you get from the MRI and see what is relevant for your work.
      I'm not aware of tractography objects and modules defined by the standard but I suggest that you run your own check on that by browsing through chapter 3 of the standard and looking for relevant modules of the MR Image SOP Class.
      Roni

      Delete
  18. Hi, I have a question about DICOM files. How entities like patient, study, series and instance reference to each other in the file? I assume that one DICOM file can have only one Patient so this one is solved. But I know studies can have several series and these can have several instances. So when constructing DICOM file I should place several studies/series/instances one after another(and then reference it by ID) or enclose them into sequences like this:

    Patient
    ->Study1
    -->Series1
    --->Instance1
    -->Series2
    ->Study2
    -->Series1

    ReplyDelete
    Replies
    1. Hi Andrew,
      That's a very good question and I'm very happy you asked it.
      In most cases, DICOM File holds one DICOM Instance. The only exception to this is new multi-frame objects that use continuations which are not very common yet.
      Every IOD (Information Object Definition) includes modules of the series, study and patient entities as in the example here.
      So all the files that belongs to the same series will all have the same values in their series module and study module and patient module. The same elements with the same values will repeat in every object and in every file.
      You can group files of the same series by checking their series instance uid and group files of the same study by checking their study instance uid.
      With patient I recommend comparing not only the patient id but all four elements: Patient Name, Patient ID, Sex and Birth Date and alerting the user if not all match.
      Regards,
      Roni

      Delete
    2. Thank you Roni, that was very helpful! Now I understand why DICOMDIR is so important :)

      Delete
  19. hey i'm new in dicom and i want to make web application in asp.net about dicom viewer and i have alot of problem can any one help me

    thanks

    ReplyDelete
  20. Is it possible to have multiple 7fe0,0010 elements in a DICOM file?

    ReplyDelete
    Replies
    1. Hi. Sorry for the late response.
      Only inside sequence. For example thumbnails within a DICOMDIR file.
      Every tag in a DICOM object is unique.
      To put lists of same tags you put them in a sequence (like a DICOM 'list').
      The pixel data cn hold many images, for example in DICOM Ultrasound you can have a multi-frame class so that you can put many images in one DICOM object (DICOM file).

      Delete
  21. hi all,

    and given a study with, say, formed by 120 slices, how to identify which image the physician has marked to be printed (printer or films)?

    many thanks!

    francesco

    ReplyDelete