Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Create dicom dataset from secondary capture image
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Text;
using Dicom.Imaging;
using Dicom.IO.Buffer;
namespace Dicom
{
public class BitmapToDicom
{
public static void ImportImage(string file)
{
Bitmap bitmap = new Bitmap(file);
bitmap = GetValidImage(bitmap);
int rows, columns;
byte[] pixels = GetPixels(bitmap, out rows, out columns);
MemoryByteBuffer buffer = new MemoryByteBuffer(pixels);
DicomDataset dataset = new DicomDataset();
FillDataset(dataset);
dataset.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation .Rgb .Value );
dataset.Add(DicomTag.Rows, (ushort)rows);
dataset.Add(DicomTag.Columns, (ushort)columns);
DicomPixelData pixelData = DicomPixelData.Create(dataset, true);
pixelData.BitsStored = 8;
pixelData.BitsAllocated = 8;
pixelData.SamplesPerPixel = 3;
pixelData.HighBit = 7;
pixelData.PixelRepresentation = 0;
pixelData.PlanarConfiguration = 0;
pixelData.AddFrame(buffer);
DicomFile dicomfile = new DicomFile(dataset);
dicomfile.Save("dicomfile.dcm");
}
private static void FillDataset(DicomDataset dataset)
{
//type 1 attributes.
dataset.Add(DicomTag.SOPClassUID, DicomUID.SecondaryCaptureImageStorage);
dataset.Add(DicomTag.StudyInstanceUID, GenerateUid());
dataset.Add(DicomTag.SeriesInstanceUID, GenerateUid());
dataset.Add(DicomTag.SOPInstanceUID, GenerateUid());
//type 2 attributes
dataset.Add(DicomTag.PatientID, "12345");
dataset.Add(DicomTag.PatientName, string .Empty );
dataset.Add(DicomTag.PatientBirthDate, "00000000");
dataset.Add(DicomTag.PatientSex, "M");
dataset.Add(DicomTag.StudyDate, DateTime.Now);
dataset.Add(DicomTag.StudyTime, DateTime.Now);
dataset.Add(DicomTag.AccessionNumber, string.Empty);
dataset.Add(DicomTag.ReferringPhysicianName, string.Empty);
dataset.Add(DicomTag.StudyID, "1");
dataset.Add(DicomTag.SeriesNumber, "1");
dataset.Add(DicomTag.ModalitiesInStudy, "CR");
dataset.Add(DicomTag.Modality, "CR");
dataset.Add(DicomTag.NumberOfStudyRelatedInstances, "1");
dataset.Add(DicomTag.NumberOfStudyRelatedSeries, "1");
dataset.Add(DicomTag.NumberOfSeriesRelatedInstances, "1");
dataset.Add(DicomTag.PatientOrientation, "F/A");
dataset.Add(DicomTag.ImageLaterality, "U");
}
private static DicomUID GenerateUid()
{
StringBuilder uid = new StringBuilder();
uid.Append("1.08.1982.10121984.2.0.07").Append('.').Append(DateTime.UtcNow.Ticks);
return new DicomUID(uid.ToString(), "SOP Instance UID", DicomUidType.SOPInstance);
}
private static Bitmap GetValidImage(Bitmap bitmap)
{
if (bitmap.PixelFormat != PixelFormat.Format24bppRgb)
{
Bitmap old = bitmap;
using (old)
{
bitmap = new Bitmap(old.Width, old.Height, PixelFormat.Format24bppRgb);
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap))
{
g.DrawImage(old, 0, 0, old.Width, old.Height);
}
}
}
return bitmap;
}
private static byte[] GetPixels(Bitmap image, out int rows, out int columns)
{
rows = image.Height;
columns = image.Width;
if (rows % 2 != 0 && columns % 2 != 0)
--columns;
BitmapData data = image.LockBits(new Rectangle(0, 0, columns, rows), ImageLockMode.ReadOnly, image.PixelFormat);
IntPtr bmpData = data.Scan0;
try
{
int stride = columns * 3;
int size = rows * stride;
byte[] pixelData = new byte[size];
for (int i = 0; i < rows; ++i)
Marshal.Copy(new IntPtr(bmpData.ToInt64() + i * data.Stride), pixelData, i * stride, stride);
//swap BGR to RGB
SwapRedBlue(pixelData);
return pixelData;
}
finally
{
image.UnlockBits(data);
}
}
private static void SwapRedBlue(byte[] pixels)
{
for (int i = 0; i < pixels.Length; i += 3)
{
byte temp = pixels[i];
pixels[i] = pixels[i + 2];
pixels[i + 2] = temp;
}
}
}
}
@Koki-Shimizu

This comment has been minimized.

Show comment Hide comment
@Koki-Shimizu

Koki-Shimizu Oct 30, 2016

Great! This is work!

Great! This is work!

@Anonymous-DICOMUser

This comment has been minimized.

Show comment Hide comment
@Anonymous-DICOMUser

Anonymous-DICOMUser Jan 16, 2017

This works.. Thank you..
Can you please provide source code to convert multiple images into multi-frame DICOM image?

This works.. Thank you..
Can you please provide source code to convert multiple images into multi-frame DICOM image?

@sdekker90

This comment has been minimized.

Show comment Hide comment
@sdekker90

sdekker90 Mar 9, 2017

Thanks a lot for the example. With version 3.0.1 of fo-dicom it was necessary to add

dataset.AddOrUpdate(DicomTag.BitsAllocated, CUShort(8))

before creating the pixeldata.

Thanks a lot for the example. With version 3.0.1 of fo-dicom it was necessary to add

dataset.AddOrUpdate(DicomTag.BitsAllocated, CUShort(8))

before creating the pixeldata.

@Fedino

This comment has been minimized.

Show comment Hide comment
@Fedino

Fedino Mar 15, 2017

Hello I can not find "Dicom.Imaging" and "Dicom.IO.Buffer" using. Can you help me? Thank you.
Dino

Fedino commented Mar 15, 2017

Hello I can not find "Dicom.Imaging" and "Dicom.IO.Buffer" using. Can you help me? Thank you.
Dino

@PoPGeek

This comment has been minimized.

Show comment Hide comment
@PoPGeek

PoPGeek May 22, 2017

Hello I can not find "Dicom.Imaging" and "Dicom.IO.Buffer" using. Can you help me? Thank you.

PoPGeek commented May 22, 2017

Hello I can not find "Dicom.Imaging" and "Dicom.IO.Buffer" using. Can you help me? Thank you.

@anders9ustafsson

This comment has been minimized.

Show comment Hide comment
@anders9ustafsson

anders9ustafsson Jul 19, 2017

To follow up on @sdekker90's comment above, with fo-dicom 3.1 it will additionally be necessary to remove this line:

pixelData.BitsAllocated = 8;

since the DicomPixelData.BitsAllocated setter will be removed from the API for consistency with the underlying pixel data representation. For more information see the corresponding Github issue.

To follow up on @sdekker90's comment above, with fo-dicom 3.1 it will additionally be necessary to remove this line:

pixelData.BitsAllocated = 8;

since the DicomPixelData.BitsAllocated setter will be removed from the API for consistency with the underlying pixel data representation. For more information see the corresponding Github issue.

@hero3616

This comment has been minimized.

Show comment Hide comment
@hero3616

hero3616 Jan 8, 2018

This is very useful thank you. I also need to do the same for *.avi and *.wmv files. Any help or pointer would be appreciated.

hero3616 commented Jan 8, 2018

This is very useful thank you. I also need to do the same for *.avi and *.wmv files. Any help or pointer would be appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment