Skip to content

Instantly share code, notes, and snippets.

@mdubey82
Created November 7, 2012 08:48
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save mdubey82/4030263 to your computer and use it in GitHub Desktop.
Save mdubey82/4030263 to your computer and use it in GitHub Desktop.
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
Copy link

Great! This is work!

@Anonymous-DICOMUser
Copy link

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

@sdekker90
Copy link

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
Copy link

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
Copy link

PoPGeek commented May 22, 2017

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

@anders9ustafsson
Copy link

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
Copy link

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.

@stewa9
Copy link

stewa9 commented Nov 6, 2018

Hi

GenerateUID should not use 1.08.1982.10121984.2.0.07 as the leading zeros do not conform to the Nema Standard ( http://dicom.nema.org/Dicom/2013/output/chtml/part05/chapter_9.html )
Each component of a UID is a number and shall consist of one or more digits. The first digit of each component shall not be zero unless the component is a single digit.

Also note that the start of the UID should be unique to your site. See https://www.medicalconnections.co.uk/FreeUID/ for more info.

@SushrutDeo
Copy link

SushrutDeo commented Jul 30, 2020

You can use DicomUID.Generate() instead of private static DicomUID GenerateUid() as it doesn't work. Also, you cannot use pixelData.BitsAllocated = 8; as this property is read only. Instead you can use following:

dataSet.AddOrUpdate( DicomTag.BitsAllocated, ( ushort ) 8 );
DicomPixelData pixelData = DicomPixelData.Create( dataSet, true );

Make these changes and this program is good to go. Thanks to @mdubey82

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