ImageGear .NET - Updated
Loading and Saving DICOM Images
User Guide > How to Work with... > DICOM > Loading and Saving DICOM Images

Load DICOM images in the same way as you load images of other formats. Use DICOM format options to set specific features for image loading.

Save DICOM images in the same way as you save images of other formats. However, there are a few items that need to be discussed about saving DICOM images. 

DICOM File Loading Times

Often, a DICOM file contains a set of pages which is a sequence of frames recorded from the scanning device. For example, recording the working of the heart or the dynamics of the spread of a contrasting drug inside the body. Hence, the need for sequential playback of pages to create a realistic live image illustrating the process occurring in the body. ImageGear allows you to playback the pages in a few different ways. Each of these methods has its own advantages and disadvantages.

This first example illustrates how to load a whole DICOM file into memory and play pages using ImGearPageView. This method is the simplest, although the time to load the file is highest and playing frame rate is slow.

C#
Copy Code
        /// <summary>
        /// Plays DICOM file using ImGearDocument and ImGearPageView.
        /// </summary>
        /// <param name="igPageView">ImGearPageView object for pages playing.</param>
        /// <param name="dicomFilePathName">Full path and name of playing DICOM file.</param>
        public static void PlayDicomDocumentWithImageGear(ImGearPageView igPageView, string dicomFilePathName)
        {
            // Load entire document to the memory.
            ImGearDocument igDocument;
            using (Stream stream = new FileStream(dicomFilePathName, FileMode.Open, FileAccess.Read))
                igDocument = ImGearFileFormats.LoadDocument(stream);
            // Play the pages of document one by one with maximal possible frame rate.
            for (int i = 0; i < igDocument.Pages.Count; i++)
            {
                igPageView.Page = igDocument.Pages[i];
                igPageView.Refresh();
            }
        }
VB.NET
Copy Code
        ''' <summary>
        ''' Plays DICOM file using ImGearDocument and ImGearPageView.
        ''' </summary>
        ''' <param name="igPageView">ImGearPageView object for pages playing.</param>
        ''' <param name="dicomFilePathName">Full path and name of playing DICOM file.</param>
        Public Shared Sub PlayDicomDocumentWithImageGear(igPageView As ImGearPageView, dicomFilePathName As String)
            ' Load entire document to the memory.
            Dim igDocument As ImGearDocument
            Using stream As Stream = New FileStream(dicomFilePathName, FileMode.Open, FileAccess.Read)
                igDocument = ImGearFileFormats.LoadDocument(stream)
            End Using
            ' Play the pages of document one by one with maximal possible frame rate.
            For i As Integer = 0 To igDocument.Pages.Count - 1
                igPageView.Page = igDocument.Pages(i)
                igPageView.Refresh()
            Next
        End Sub

This second example performs the loading the same way as the first example, however, the rendering of pages is performed with Windows GUI using System.Drawing.Bitmap class object (https://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(SYSTEM.DRAWING.BITMAP);k(TargetFrameworkMoniker-".NETFRAMEWORK,VERSION=V2.0");k(DevLang-CSHARP)&rd=true). As in the first example, the time to load is slow, however, the playing of pages is very fast. This method is suitable for reviewing information in a file because after the initial loading any page may be displayed quickly.

C#
Copy Code
        /// <summary>
        /// Plays DICOM file using ImGearDocument and System.Drawing.Bitmap.
        /// </summary>
        /// <param name="pictureBox">Control for playing a file.</param>
        /// <param name="dicomFilePathName">Full path and name of playing DICOM file.</param>
        public static void PlayDicomDocumentWithWindowsGui(System.Windows.Forms.PictureBox pictureBox, string dicomFilePathName)
        {
            // Load entire document to the memory.
            ImGearDocument igDocument;
            using (Stream stream = new FileStream(dicomFilePathName, FileMode.Open, FileAccess.Read))
                igDocument = ImGearFileFormats.LoadDocument(stream);
            // Play the pages of document one by one with maximal possible frame rate.
            foreach (ImGearPage igPage in igDocument.Pages)
            {
                // Free replacing image.
                if (pictureBox.BackgroundImage != null)
                    pictureBox.BackgroundImage.Dispose();
                // Draw new image.
                pictureBox.BackgroundImage = ImGearDibToBitmap(igPage.DIB);
                pictureBox.Refresh();
            }
        }
VB.NET
Copy Code
        ''' <summary>
        ''' Plays DICOM file using ImGearDocument and System.Drawing.Bitmap.
        ''' </summary>
        ''' <param name="pictureBox">Control for playing a file.</param>
        ''' <param name="dicomFilePathName">Full path and name of playing DICOM file.</param>
        Public Shared Sub PlayDicomDocumentWithWindowsGui(pictureBox As System.Windows.Forms.PictureBox, dicomFilePathName As String)
            ' Load entire document to the memory.
            Dim igDocument As ImGearDocument
            Using stream As Stream = New FileStream(dicomFilePathName, FileMode.Open, FileAccess.Read)
                igDocument = ImGearFileFormats.LoadDocument(stream)
            End Using
            ' Play the pages of document one by one with maximal possible frame rate.
            For Each igPage As ImGearPage In igDocument.Pages
                ' Free replacing image.
                If pictureBox.BackgroundImage IsNot Nothing Then
                    pictureBox.BackgroundImage.Dispose()
                End If
                ' Draw new image.
                pictureBox.BackgroundImage = ImGearDibToBitmap(igPage.DIB)
                pictureBox.Refresh()
            Next
        End Sub

If the DICOM file is very large, loading all the pages to memory may be a time consuming operation. For cases when the count of pages is very large or the summary size of pages is very large, another method should be used. ImageGear provides the method of loading single page by index from a DICOM file. It does not load all pages into the memory, instead limits to loading only one required page. The following example illustrates how it may be performed with ImageGear and drawing of pages is performed by ImGearPageView. The pre-loading time with this method is absent, however, frame rate will be slow in comparison to the previous methods.

C#
Copy Code
        /// <summary>
        /// Plays DICOM file using ImGearPage and ImGearPageView.
        /// </summary>
        /// <param name="igPageView">ImGearPageView object for pages playing.</param>
        /// <param name="dicomFilePathName">Full path and name of playing DICOM file.</param>
        public static void PlayDicomFileWithImageGear(ImGearPageView igPageView, string dicomFilePathName)
        {
            // Open DICOM file for reading.
            using (Stream stream = new FileStream(dicomFilePathName, FileMode.Open, FileAccess.Read))
            {
                // Detect format of file one time for all pages.
                IImGearFormat format = ImGearFileFormats.Detect(stream);
                // Get page count of document in file.
                int pageCount = ImGearFileFormats.GetPageCount(stream, format.ID);
                // Place format in load options.
                ImGearLoadOptions options = new ImGearLoadOptions();
                options.Format = format.ID;
                // Play the pages in file one by one with maximal possible frame rate.
                for (int i = 0; i < pageCount; i++)
                {
                    // Use Load page with options where format is already defined.
                    // It allows to do not make format detection for each page.
                    igPageView.Page = ImGearFileFormats.LoadPage(stream, i, options);
                    // Apply the changes to PageView.
                    igPageView.Refresh();
                }
            }
        }
VB.NET
Copy Code
        ''' <summary>
        ''' Plays DICOM file using ImGearPage and ImGearPageView.
        ''' </summary>
        ''' <param name="igPageView">ImGearPageView object for pages playing.</param>
        ''' <param name="dicomFilePathName">Full path and name of playing DICOM file.</param>
        Public Shared Sub PlayDicomFileWithImageGear(igPageView As ImGearPageView, dicomFilePathName As String)
            ' Open DICOM file for reading.
            Using stream As Stream = New FileStream(dicomFilePathName, FileMode.Open, FileAccess.Read)
                ' Detect format of file one time for all pages.
                Dim format As IImGearFormat = ImGearFileFormats.Detect(stream)
                ' Get page count of document in file.
                Dim pageCount As Integer = ImGearFileFormats.GetPageCount(stream, format.ID)
                ' Place format in load options.
                Dim options As New ImGearLoadOptions()
                options.Format = format.ID
                ' Play the pages in file one by one with maximal possible frame rate.
                For i As Integer = 0 To pageCount - 1
                    ' Use Load page with options where format is already defined.
                    ' It allows to do not make format detection for each page.
                    igPageView.Page = ImGearFileFormats.LoadPage(stream, i, options)
                    ' Apply the changes to PageView.
                    igPageView.Refresh()
                Next
            End Using
        End Sub

An alternative way of playing the pages is by drawing the pages with System.Drawing.Bitmap (https://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(SYSTEM.DRAWING.BITMAP);k(TargetFrameworkMoniker-".NETFRAMEWORK,VERSION=V2.0");k(DevLang-CSHARP)&rd=true). It will increase the frame rate of playing. But, it will still be slower than in first two methods.

C#
Copy Code
        /// <summary>
        /// Plays DICOM file using ImGearPage and System.Drawing.Bitmap.
        /// </summary>
        /// <param name="pictureBox">Control for playing a file.</param>
        /// <param name="dicomFilePathName">Full path and name of playing DICOM file.</param>
        public static void PlayDicomFileWithWindowsGui(System.Windows.Forms.PictureBox pictureBox, string dicomFilePathName)
        {
            // Open DICOM file for reading.
            using (Stream stream = new FileStream(dicomFilePathName, FileMode.Open, FileAccess.Read))
            {
                // Detect format of file one time for all pages.
                IImGearFormat format = ImGearFileFormats.Detect(stream);
                // Get page count of document in file.
                int pageCount = ImGearFileFormats.GetPageCount(stream, format.ID);
                // Place format in load options.
                ImGearLoadOptions options = new ImGearLoadOptions();
                options.Format = format.ID;
                // Load first page for creation intermediate data.
                ImGearDIB igDib = ImGearFileFormats.LoadPage(stream, 0, options).DIB;
                // Create intermediate data for playing.
                Rectangle rectangle = new Rectangle(0, 0, igDib.Width, igDib.Height);
                byte[] bytes = new byte[igDib.GetRaster(0).Content.Length];
                int rasterLength = ((igDib.Width * 24 + 31) & ~31) / 8;
                // Load and play pages one by one.
                for (int i = 0; i < pageCount; i++)
                {
                    // Load page from file with options where format is already defined.
                    // It allows to do not make format detection for each page.
                    if (i > 0) // First page is already loaded.
                        igDib = ImGearFileFormats.LoadPage(stream, i, options).DIB;
                    // Free replacing image.
                    if (pictureBox.BackgroundImage != null)
                        pictureBox.BackgroundImage.Dispose();
                    // Draw new image.
                    pictureBox.BackgroundImage = ImGearDibToBitmap(igDib);
                    pictureBox.Refresh();
                }
            }
        }
VB.NET
Copy Code
        ''' <summary>
        ''' Plays DICOM file using ImGearPage and System.Drawing.Bitmap.
        ''' </summary>
        ''' <param name="pictureBox">Control for playing a file.</param>
        ''' <param name="dicomFilePathName">Full path and name of playing DICOM file.</param>
        Public Shared Sub PlayDicomFileWithWindowsGui(pictureBox As System.Windows.Forms.PictureBox, dicomFilePathName As String)
            ' Open DICOM file for reading.
            Using stream As Stream = New FileStream(dicomFilePathName, FileMode.Open, FileAccess.Read)
                ' Detect format of file one time for all pages.
                Dim format As IImGearFormat = ImGearFileFormats.Detect(stream)
                ' Get page count of document in file.
                Dim pageCount As Integer = ImGearFileFormats.GetPageCount(stream, format.ID)
                ' Place format in load options.
                Dim options As New ImGearLoadOptions()
                options.Format = format.ID
                ' Load first page for creation intermediate data.
                Dim igDib As ImGearDIB = ImGearFileFormats.LoadPage(stream, 0, options).DIB
                ' Create intermediate data for playing.
                Dim rectangle As New Rectangle(0, 0, igDib.Width, igDib.Height)
                Dim bytes As Byte() = New Byte(igDib.GetRaster(0).Content.Length - 1) {}
                Dim rasterLength As Integer = ((igDib.Width * 24 + 31) And Not 31) / 8
                ' Load and play pages one by one.
                For i As Integer = 0 To pageCount - 1
                    ' Load page from file with options where format is already defined.
                    ' It allows to do not make format detection for each page.
                    If i > 0 Then
                        ' First page is already loaded.
                        igDib = ImGearFileFormats.LoadPage(stream, i, options).DIB
                    End If
                    ' Free replacing image.
                    If pictureBox.BackgroundImage IsNot Nothing Then
                        pictureBox.BackgroundImage.Dispose()
                    End If
                    ' Draw new image.
                    pictureBox.BackgroundImage = ImGearDibToBitmap(igDib)
                    pictureBox.Refresh()
                Next
            End Using
        End Sub

In our samples we used the method that converts ImGearDIB object to System.Drawing.Bitmap (https://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(SYSTEM.DRAWING.BITMAP);k(TargetFrameworkMoniker-".NETFRAMEWORK,VERSION=V2.0");k(DevLang-CSHARP)&rd=true) for majority count of colorspaces used in DICOM format. We give an example of such methods below.

C#
Copy Code
        /// <summary>
        /// Converts ImageGearDIB object to System.Drawing.Bitmap.
        /// </summary>
        /// <param name="igDib">ImGearDIB object for conversion.</param>
        /// <returns>System.Drawing.Bitmap object as result of conversion.</returns>
        /// <exception cref="System.Exception">
        /// Exception is thrown in case of incorrect or unsupported format of DIB.
        /// </exception>
        public static Bitmap ImGearDibToBitmap(ImGearDIB igDib)
        {
            // Create new bitmap with the same size as DIB.
            Bitmap bitmap = new Bitmap(igDib.Width, igDib.Height, PixelFormat.Format24bppRgb);
            // Get bitmap data.
            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, igDib.Width, igDib.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
            // Create intermediate buffer.
            byte[] bytes = new byte[data.Stride * data.Height];
            try
            {
                if (igDib.ColorSpace.Value == ImGearColorSpaceIDs.RGB)
                {
                    if (igDib.ChannelDepths.Length == 3)
                    {
                        // Check channels depth.
                        for (int channelIndex = 0; channelIndex < 3; channelIndex++)
                            if (igDib.ChannelDepths[channelIndex] != 8)
                                throw new Exception("Unsupported channel depth.");
                        // Calculate raster line length in bytes aligned to 32 bits.
                        int rasterLength = ((igDib.Width * 24 + 31) & ~31) / 8;
                        // Expand raster data of page.
                        byte[] raster = (byte[])igDib.GetRaster(0).Content;
                        // Copy raster data to intermediate buffer.
                        for (int rasterStart = 0; rasterStart < raster.Length; rasterStart += rasterLength)
                        {
                            for (int pixelIndex = 0; pixelIndex < rasterLength; pixelIndex += 3)
                            {
                                // Swap R and B channels.
                                bytes[rasterStart + pixelIndex + 0] = raster[rasterStart + pixelIndex + 2];
                                bytes[rasterStart + pixelIndex + 1] = raster[rasterStart + pixelIndex + 1];
                                bytes[rasterStart + pixelIndex + 2] = raster[rasterStart + pixelIndex + 0];
                            }
                        }
                    }
                    else
                        throw new Exception("Incorrect number of channels for RGB colorspace.");
                }
                else if (igDib.ColorSpace.Value == ImGearColorSpaceIDs.I)
                {
                    if (igDib.ChannelDepths.Length == 1)
                    {
                        if (igDib.ChannelDepths[0] == 8)
                        {
                            // Calculate raster line length in bytes aligned to 32 bits.
                            int rasterLength = ((igDib.Width + 3) & ~3);
                            // Expand raster data of page.
                            byte[] raster = (byte[])igDib.GetRaster(0).Content;
                            // Copy raster data to intermediate buffer.
                            for (int rasterStartInDib = 0, rasterStartInBmp = 0; rasterStartInDib < raster.Length; rasterStartInDib += rasterLength, rasterStartInBmp += data.Stride)
                            {
                                for (int pixelIndexInDib = 0, pixelIndexInBmp = 0; pixelIndexInDib < igDib.Width; pixelIndexInDib++, pixelIndexInBmp += 3)
                                {
                                    // Convert palette color to RGB.
                                    ImGearRGBQuad color = igDib.Palette[raster[rasterStartInDib + pixelIndexInDib]];
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 0] = color.Red;
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 1] = color.Green;
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 2] = color.Blue;
                                }
                            }
                        }
                        else
                            throw new Exception("Unsupported channel depth for Indexed colorspace.");
                    }
                    else
                        throw new Exception("Incorrect number of channels for Indexed colorspace.");
                }
                else if (igDib.ColorSpace.Value == ImGearColorSpaceIDs.Gy)
                {
                    if (igDib.ChannelDepths.Length == 1)
                    {
                        if (igDib.ChannelDepths[0] == 1)
                        {
                            throw new Exception("Unsupported channel depth for Grayscale colorspace.");
                        }
                        else if (igDib.ChannelDepths[0] <= 8)
                        {
                            // Calculate raster line length in bytes aligned to 32 bits.
                            int rasterLength = ((igDib.Width + 3) & ~3);
                            // Expand raster data of page.
                            byte[] raster = (byte[])igDib.GetRaster(0).Content;
                            // Calculate maximal value for channel depth.
                            int maxValue = (1 << igDib.ChannelDepths[0]) - 1;
                            // Copy raster data to intermediate buffer.
                            for (int rasterStartInDib = 0, rasterStartInBmp = 0; rasterStartInDib < raster.Length; rasterStartInDib += rasterLength, rasterStartInBmp += data.Stride)
                            {
                                for (int pixelIndexInDib = 0, pixelIndexInBmp = 0; pixelIndexInDib < igDib.Width; pixelIndexInDib++, pixelIndexInBmp += 3)
                                {
                                    byte value = (byte)(raster[rasterStartInDib + pixelIndexInDib] * 255 / maxValue);
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 0] = value;
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 1] = value;
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 2] = value;
                                }
                            }
                        }
                        else if (igDib.ChannelDepths[0] <= 16)
                        {
                            // Calculate raster line length in bytes aligned to 32 bits.
                            int rasterLength = ((igDib.Width + 1) & ~1);
                            // Expand raster data of page.
                            short[] raster = (short[])igDib.GetRaster(0).Content;
                            // Calculate maximal value for channel depth.
                            int maxValue = (1 << igDib.ChannelDepths[0]) - 1;
                            // Copy raster data to intermediate buffer.
                            for (int rasterStartInDib = 0, rasterStartInBmp = 0; rasterStartInDib < raster.Length; rasterStartInDib += rasterLength, rasterStartInBmp += data.Stride)
                            {
                                for (int pixelIndexInDib = 0, pixelIndexInBmp = 0; pixelIndexInDib < igDib.Width; pixelIndexInDib++, pixelIndexInBmp += 3)
                                {
                                    byte value = (byte)(raster[rasterStartInDib + pixelIndexInDib] * 255 / maxValue);
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 0] = value;
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 1] = value;
                                    bytes[rasterStartInBmp + pixelIndexInBmp + 2] = value;
                                }
                            }
                        }
                    }
                    else
                        throw new Exception("Incorrect number of channels for Grayscale colorspace.");
                }
                else
                    throw new Exception("Unsupported colorspace.");
                // Copy content of intermediate buffer to new bitmap.
                Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);
                // Bitmap data should be unlocked in any case.
                bitmap.UnlockBits(data);
            }
            catch
            {
                // Bitmap data should be unlocked in any case.
                bitmap.UnlockBits(data);
                // In case of error bitmap should be free.
                bitmap.Dispose();
                throw;
            }
            return bitmap;
        }
VB.NET
Copy Code
        ''' <summary>
        ''' Converts ImageGearDIB object to System.Drawing.Bitmap.
        ''' </summary>
        ''' <param name="igDib">ImGearDIB object for conversion.</param>
        ''' <returns>System.Drawing.Bitmap object as result of conversion.</returns>
        ''' <exception cref="System.Exception">
        ''' Exception is thrown in case of incorrect or unsupported format of DIB.
        ''' </exception>
        Public Shared Function ImGearDibToBitmap(igDib As ImGearDIB) As Bitmap
            ' Create new bitmap with the same size as DIB.
            Dim bitmap As New Bitmap(igDib.Width, igDib.Height, PixelFormat.Format24bppRgb)
            ' Get bitmap data.
            Dim data As BitmapData = bitmap.LockBits(New Rectangle(0, 0, igDib.Width, igDib.Height), ImageLockMode.[WriteOnly], PixelFormat.Format24bppRgb)
            ' Create intermediate buffer.
            Dim bytes As Byte() = New Byte(data.Stride * data.Height - 1) {}
            Try
                If igDib.ColorSpace.Value = ImGearColorSpaceIDs.RGB Then
                    If igDib.ChannelDepths.Length = 3 Then
                        ' Check channels depth.
                        For channelIndex As Integer = 0 To 2
                            If igDib.ChannelDepths(channelIndex) <> 8 Then
                                Throw New Exception("Unsupported channel depth.")
                            End If
                        Next
                        ' Calculate raster line length in bytes aligned to 32 bits.
                        Dim rasterLength As Integer = ((igDib.Width * 24 + 31) And Not 31) / 8
                        ' Expand raster data of page.
                        Dim raster As Byte() = DirectCast(igDib.GetRaster(0).Content, Byte())
                        ' Copy raster data to intermediate buffer.
                        Dim rasterStart As Integer = 0
                        While rasterStart < raster.Length
                            For pixelIndex As Integer = 0 To rasterLength - 1 Step 3
                                ' Swap R and B channels.
                                bytes(rasterStart + pixelIndex + 0) = raster(rasterStart + pixelIndex + 2)
                                bytes(rasterStart + pixelIndex + 1) = raster(rasterStart + pixelIndex + 1)
                                bytes(rasterStart + pixelIndex + 2) = raster(rasterStart + pixelIndex + 0)
                            Next
                            rasterStart += rasterLength
                        End While
                    Else
                        Throw New Exception("Incorrect number of channels for RGB colorspace.")
                    End If
                ElseIf igDib.ColorSpace.Value = ImGearColorSpaceIDs.I Then
                    If igDib.ChannelDepths.Length = 1 Then
                        If igDib.ChannelDepths(0) = 8 Then
                            ' Calculate raster line length in bytes aligned to 32 bits.
                            Dim rasterLength As Integer = ((igDib.Width + 3) And Not 3)
                            ' Expand raster data of page.
                            Dim raster As Byte() = DirectCast(igDib.GetRaster(0).Content, Byte())
                            ' Copy raster data to intermediate buffer.
                            Dim rasterStartInDib As Integer = 0, rasterStartInBmp As Integer = 0
                            While rasterStartInDib < raster.Length
                                Dim pixelIndexInDib As Integer = 0, pixelIndexInBmp As Integer = 0
                                While pixelIndexInDib < igDib.Width
                                    ' Convert palette color to RGB.
                                    Dim color As ImGearRGBQuad = igDib.Palette(raster(rasterStartInDib + pixelIndexInDib))
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 0) = color.Red
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 1) = color.Green
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 2) = color.Blue
                                    pixelIndexInDib += 1
                                    pixelIndexInBmp += 3
                                End While
                                rasterStartInDib += rasterLength
                                rasterStartInBmp += data.Stride
                            End While
                        Else
                            Throw New Exception("Unsupported channel depth for Indexed colorspace.")
                        End If
                    Else
                        Throw New Exception("Incorrect number of channels for Indexed colorspace.")
                    End If
                ElseIf igDib.ColorSpace.Value = ImGearColorSpaceIDs.Gy Then
                    If igDib.ChannelDepths.Length = 1 Then
                        If igDib.ChannelDepths(0) = 1 Then
                            Throw New Exception("Unsupported channel depth for Grayscale colorspace.")
                        ElseIf igDib.ChannelDepths(0) <= 8 Then
                            ' Calculate raster line length in bytes aligned to 32 bits.
                            Dim rasterLength As Integer = ((igDib.Width + 3) And Not 3)
                            ' Expand raster data of page.
                            Dim raster As Byte() = DirectCast(igDib.GetRaster(0).Content, Byte())
                            ' Calculate maximal value for channel depth.
                            Dim maxValue As Integer = (1 << igDib.ChannelDepths(0)) - 1
                            ' Copy raster data to intermediate buffer.
                            Dim rasterStartInDib As Integer = 0, rasterStartInBmp As Integer = 0
                            While rasterStartInDib < raster.Length
                                Dim pixelIndexInDib As Integer = 0, pixelIndexInBmp As Integer = 0
                                While pixelIndexInDib < igDib.Width
                                    Dim value As Byte = CByte(raster(rasterStartInDib + pixelIndexInDib) * 255 / maxValue)
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 0) = value
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 1) = value
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 2) = value
                                    pixelIndexInDib += 1
                                    pixelIndexInBmp += 3
                                End While
                                rasterStartInDib += rasterLength
                                rasterStartInBmp += data.Stride
                            End While
                        ElseIf igDib.ChannelDepths(0) <= 16 Then
                            ' Calculate raster line length in bytes aligned to 32 bits.
                            Dim rasterLength As Integer = ((igDib.Width + 1) And Not 1)
                            ' Expand raster data of page.
                            Dim raster As Short() = DirectCast(igDib.GetRaster(0).Content, Short())
                            ' Calculate maximal value for channel depth.
                            Dim maxValue As Integer = (1 << igDib.ChannelDepths(0)) - 1
                            ' Copy raster data to intermediate buffer.
                            Dim rasterStartInDib As Integer = 0, rasterStartInBmp As Integer = 0
                            While rasterStartInDib < raster.Length
                                Dim pixelIndexInDib As Integer = 0, pixelIndexInBmp As Integer = 0
                                While pixelIndexInDib < igDib.Width
                                    Dim value As Byte = CByte(raster(rasterStartInDib + pixelIndexInDib) * 255 / maxValue)
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 0) = value
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 1) = value
                                    bytes(rasterStartInBmp + pixelIndexInBmp + 2) = value
                                    pixelIndexInDib += 1
                                    pixelIndexInBmp += 3
                                End While
                                rasterStartInDib += rasterLength
                                rasterStartInBmp += data.Stride
                            End While
                        End If
                    Else
                        Throw New Exception("Incorrect number of channels for Grayscale colorspace.")
                    End If
                Else
                    Throw New Exception("Unsupported colorspace.")
                End If
                ' Copy content of intermediate buffer to new bitmap.
                Marshal.Copy(bytes, 0, data.Scan0, bytes.Length)
                ' Bitmap data should be unlocked in any case.
                bitmap.UnlockBits(data)
            Catch
                ' Bitmap data should be unlocked in any case.
                bitmap.UnlockBits(data)
                ' In case of error bitmap should be free.
                bitmap.Dispose()
                Throw
            End Try
            Return bitmap
        End Function

This section provides information about the following:

ImageGear .NET allows saving of non-DICOM images to DICOM format. A default Secondary Capture DataSet is created for such images.