这是一些代码,但我就是这样做的。这似乎是重复的常见问题。随着时间的推移,我从 Clear Canvas 论坛拼凑了这个,但它是对所提问题的完全有效的答案。
如果需要从 jpg 等标准图像文件创建 DICOM Secondary Capture 图像,并且您希望它们能够与所有 PACS、VNA 和其他 DICOM 应用程序一起正常工作,那么这里的代码适用于此。
好的,我必须再编辑一次。这是我拼凑起来的乐趣,我只需要能够做到。我创建的一些 DICOM 图像添加到了我的测试套件中,但我从中获得了更多乐趣。我拍了荷马辛普森的大脑照片并将其包裹起来。以及“当放射科医生自拍时”的照片。不要忘记我做的最后一张,最近的新闻中有一张海鳗 X 射线的高质量照片,所以我也用 DICOM 包裹了这张照片。因此,您看到的示例。
好吧,再编辑一次。自从写下这个答案后,我发现这段代码有一个非常有价值的能力。我可以以任何方式生成像素数据来测试我们的产品。我已经可以在 10,000 X 10,000 像素的 Explicit Little Endian 中生成 DICOM 图像,这肯定会导致 DICOM 产品出现问题,但我可以使用 Clear Canvas 毫无问题地生成它!
我还可以使用此代码使用简单的 5 x 5 像素小图像发送数据,这对于快速构建大型数据库或增加某些积压的测试非常有帮助。我只希望其他人发现它和我一样有用。
using ClearCanvas.Dicom.Codec;
using ClearCanvas.Common.Utilities;
using ClearCanvas.Dicom;
using ClearCanvas.Dicom.Network;
using ClearCanvas.Common;
using ClearCanvas.ImageViewer;
using ClearCanvas.ImageViewer.Imaging;
using ClearCanvas.ImageViewer.Graphics;
using ClearCanvas.ImageViewer.StudyManagement;
DicomFile df = null;
Bitmap bm = LoadImage(tbImageFile.Text);
CreateBaseDataSet();
df = ConvertImage(bm, 1);
df.Save(@"C:\test.dcm", DicomWriteOptions.Default);
然后是其余的:
private void CreateBaseDataSet()
{
_baseDataSet = new DicomAttributeCollection();
//Sop Common
_baseDataSet[DicomTags.SopClassUid].SetStringValue(SopClass.SecondaryCaptureImageStorageUid);
////Patient
//_baseDataSet[DicomTags.PatientId].SetStringValue(_parent.PatientId);
//_baseDataSet[DicomTags.PatientsName].SetStringValue(String.Format("{0}^{1}^{2}^^",
// _parent.LastName, _parent.FirstName, _parent.MiddleName));
//_baseDataSet[DicomTags.PatientsBirthDate].SetDateTime(0, _parent.Dob);
//_baseDataSet[DicomTags.PatientsSex].SetStringValue(_parent.Sex.ToString());
////Study
//_baseDataSet[DicomTags.StudyInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
//_baseDataSet[DicomTags.StudyDate].SetDateTime(0, _parent.StudyDate);
//_baseDataSet[DicomTags.StudyTime].SetDateTime(0, _parent.StudyTime);
//_baseDataSet[DicomTags.AccessionNumber].SetStringValue(_parent.AccessionNumber);
//_baseDataSet[DicomTags.StudyDescription].SetStringValue(_parent.StudyDescription);
//Patient
_baseDataSet[DicomTags.PatientId].SetStringValue("PIDEEL");
_baseDataSet[DicomTags.PatientsName].SetStringValue(String.Format("Moray^Eel^X-Ray"));
//_baseDataSet[DicomTags.PatientsAddress].SetString (0,"Hubertus");
//_baseDataSet[DicomTags.PatientsBirthDate].SetDateTime(0, DateTime.Now);
//_baseDataSet[DicomTags.PatientsBirthDate].SetString(0, "19550512");
_baseDataSet[DicomTags.PatientsSex].SetStringValue("O");
//Study
_baseDataSet[DicomTags.StudyInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
_baseDataSet[DicomTags.StudyDate].SetDateTime(0, DateTime.Now);
_baseDataSet[DicomTags.StudyTime].SetDateTime(0, DateTime.Now);
_baseDataSet[DicomTags.AccessionNumber].SetStringValue("ACCEEL");
_baseDataSet[DicomTags.StudyDescription].SetStringValue("X-Ray of a Moray Eel");
_baseDataSet[DicomTags.ReferringPhysiciansName].SetNullValue();
_baseDataSet[DicomTags.StudyId].SetNullValue();
//Series
_baseDataSet[DicomTags.SeriesInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
_baseDataSet[DicomTags.Modality].SetStringValue("OT");
_baseDataSet[DicomTags.SeriesNumber].SetStringValue("1");
//SC Equipment
_baseDataSet[DicomTags.ConversionType].SetStringValue("WSD");
//General Image
_baseDataSet[DicomTags.ImageType].SetStringValue(@"DERIVED\SECONDARY");
_baseDataSet[DicomTags.PatientOrientation].SetNullValue();
_baseDataSet[DicomTags.WindowWidth].SetStringValue("");
_baseDataSet[DicomTags.WindowCenter].SetStringValue("");
//Image Pixel
if (rbMonoChrome.Checked )
{
_baseDataSet[DicomTags.SamplesPerPixel].SetInt32(0, 1);
_baseDataSet[DicomTags.PhotometricInterpretation].SetStringValue("MONOCHROME2");
_baseDataSet[DicomTags.BitsAllocated].SetInt32(0, 8);
_baseDataSet[DicomTags.BitsStored].SetInt32(0, 8);
_baseDataSet[DicomTags.HighBit].SetInt32(0, 7);
_baseDataSet[DicomTags.PixelRepresentation].SetInt32(0, 0);
_baseDataSet[DicomTags.PlanarConfiguration].SetInt32(0, 0);
}
if (rbColor.Checked)
{
_baseDataSet[DicomTags.SamplesPerPixel].SetInt32(0, 3);
_baseDataSet[DicomTags.PhotometricInterpretation].SetStringValue("RGB");
_baseDataSet[DicomTags.BitsAllocated].SetInt32(0, 8);
_baseDataSet[DicomTags.BitsStored].SetInt32(0, 8);
_baseDataSet[DicomTags.HighBit].SetInt32(0, 7);
_baseDataSet[DicomTags.PixelRepresentation].SetInt32(0, 0);
_baseDataSet[DicomTags.PlanarConfiguration].SetInt32(0, 0);
}
}
private DicomFile ConvertImage(Bitmap image, int instanceNumber)
{
DicomUid sopInstanceUid = DicomUid.GenerateUid();
string fileName = @"C:\test.dcm";// String.Format("{0}.dcm", sopInstanceUid.UID);
//fileName = System.IO.Path.Combine(_tempFileDirectory, fileName);
DicomFile dicomFile = new DicomFile(fileName, new DicomAttributeCollection(), _baseDataSet.Copy());
//meta info
dicomFile.MediaStorageSopInstanceUid = sopInstanceUid.UID;
dicomFile.MediaStorageSopClassUid = SopClass.SecondaryCaptureImageStorageUid;
//General Image
dicomFile.DataSet[DicomTags.InstanceNumber].SetInt32(0, instanceNumber);
DateTime now = Platform.Time;
DateTime time = DateTime.MinValue.Add(new TimeSpan(now.Hour, now.Minute, now.Second));
//SC Image
dicomFile.DataSet[DicomTags.DateOfSecondaryCapture].SetDateTime(0, now);
dicomFile.DataSet[DicomTags.TimeOfSecondaryCapture].SetDateTime(0, time);
//Sop Common
dicomFile.DataSet[DicomTags.InstanceCreationDate].SetDateTime(0, now);
dicomFile.DataSet[DicomTags.InstanceCreationTime].SetDateTime(0, time);
dicomFile.DataSet[DicomTags.SopInstanceUid].SetStringValue(sopInstanceUid.UID);
//int rows, columns;
//Image Pixel
if (rbMonoChrome.Checked)
{
dicomFile.DataSet[DicomTags.PixelData].Values = GetMonochromePixelData(image, out rows, out columns);
}
if (rbColor.Checked)
{
dicomFile.DataSet[DicomTags.PixelData].Values = GetColorPixelData(image, out rows, out columns);
}
//Image Pixel
dicomFile.DataSet[DicomTags.Rows].SetInt32(0, rows);
dicomFile.DataSet[DicomTags.Columns].SetInt32(0, columns);
return dicomFile;
}
private static byte[] GetMonochromePixelData(Bitmap image, out int rows, out int columns)
{
rows = image.Height;
columns = image.Width;
//At least one of rows or columns must be even.
if (rows % 2 != 0 && columns % 2 != 0)
--columns; //trim the last column.
int size = rows * columns;
//byte[] pixelData = MemoryManager.Allocate<byte>(size);
byte[] pixelData = new byte[size];
int i = 0;
for (int row = 0; row < rows; ++row)
{
for (int column = 0; column < columns; column++)
{
pixelData[i++] = image.GetPixel(column, row).R;
}
}
return pixelData;
}
private static byte[] GetColorPixelData(Bitmap image, out int rows, out int columns)
{
rows = image.Height;
columns = image.Width;
//At least one of rows or columns must be even.
if (rows % 2 != 0 && columns % 2 != 0)
--columns; //trim the last column.
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 = MemoryManager.Allocate<byte>(size);
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 Bitmap LoadImage(string file)
{
Bitmap image = Image.FromFile(file, true) as Bitmap;
if (image == null)
throw new ArgumentException(String.Format("The specified file cannot be loaded as a bitmap {0}.", file));
if (image.PixelFormat != PixelFormat.Format24bppRgb)
{
Platform.Log(LogLevel.Info, "Attempting to convert non RBG image to RGB ({0}) before converting to Dicom.", file);
Bitmap old = image;
using (old)
{
image = new Bitmap(old.Width, old.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(image))
{
g.DrawImage(old, 0, 0, old.Width, old.Height);
}
}
}
return image;
}
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;
}
}