Creating Frame-Specific DICOM Presentation State using DicomObjects
Sometimes we are asked about how to create frame-specific DICOM presentation state files for multiframe images. This is not difficult in DicomObjects and can by done in a slightly awkward way. Instead of adding the entire “Referenced Series Sequence” to the top level of the presentation state file,
all you need to do is adding the “Referenced Frame Number” item into “Referenced Image Sequence” under “Graphic Annotation Sequence”, as shown in the following picture:
(0008,1115): Referenced Series Sequence :Sequence of 1 items:
>----S1------------
>(0080,1140): Referenced Image Sequence :Sequence of 1 items:
>>----S1------------
>>(0008,1150): Referenced SOP Class UID :1.2.840.10008.5.1.4.1.1.12.1
>>(0008,1155): Referenced SOP Instance UID :1.2.826.0.1.3680043.6.91625.93058.20061018124307.7.4
>>(0008,1160): Referenced Frame Number :13
>>----E1------------
>>----------------------------
>(0020,000E): Series Instance UID :1.3.12.2.1107.5.4.3.11540117440512.19970422.140030.46
(0010,0010): Patient's Name: Rubo DEMO
(0070,0001): Graphic Annotation Sequence :Sequence of 1 items:
>----S1------------
>(0080,1140): Referenced Image Sequence :Sequence of 1 items:
>>----S1------------
>>(0008,1150): Referenced SOP Class UID :1.2.840.10008.5.1.4.1.1.12.1
>>(0008,1155): Referenced SOP Instance UID :1.2.826.0.1.3680043.6.91625.93058.20061018124307.7.4
>>(0008,1160): Referenced Frame Number :13
>>----E1------------
>>----------------------------
Content inside the top box is the top level sequence which you don’t need to add. All you need to do is find the “Graphic Annotation Sequence” (0070, 0001), then the “Referenced Image Sequence” (0008, 1140) and add the “Referenced Frame Number” (0008, 1160) into it.
Below is some simple code to show you how to do it:
DicomObjects.NET
DicomDataSet ps;
DicomImage image = Viewer.CurrentImage;
image.CurrentToPresentationState(Viewer, true);
ps = image.PresentationState;
DicomDataSetCollection graphicAnnoSQ = ps[Keyword.GraphicAnnotationSequence].Value as DicomDataSetCollection;
DicomDataSetCollection refImageSQ = graphicAnnoSQ.First()[Keyword.ReferencedImageSequence].Value as DicomDataSetCollection;
refImageSQ.First().Add(Keyword.ReferencedFrameNumber, 13); // frame 13 for example
ps.Write(psFilePath, true, TransferSyntaxes.ExplicitVRLittleEndian);
DicomObjects.COM
Dim ps As DicomDataSet
DicomViewer1.CurrentImage.CurrentToPresentationState True
Set ps = DicomViewer1.CurrentImage.PresentationState
Dim graphicAnnoSQ As DicomDataSets
Dim graphicAnnoSQItem As DicomDataSet
Set graphicAnnoSQ = ps.Attributes(&H70, 1).Value
Set graphicAnnoSQItem = graphicAnnoSQ(1)
Dim refImageSQ As DicomDataSets
Dim refImageSQItem As DicomDataSet
Set refImageSQ = graphicAnnoSQItem.Attributes(&H8, &H1140).Value
Set refImageSQItem = refImageSQ(1)
refImageSQItem.Attributes.Add &H8, &H1160, 13
ps.WriteFile psFilePath, True, "1.2.840.10008.1.2.1"
This should work equally well in the .NET version of DicomObjects. For future development in the .NET version, we may add in a new method DicomDataSet.PresentationStateByFrame, we can also combine multiple presentation state into one so that people don’t have to load them all and change the DicomImage.PresentationState property every time the user changes the Frame.