C# Jpg、Bmp图像转Dicom
什么是Dicom?
DICOM(Digital Imaging and Communications in Medicine)即医学数字成像和通信,是医学图像和相关信息的国际标准(ISO 12052)。它定义了质量能满足临床需要的可用于数据交换的医学图像格式。
使用Dicom有什么优势?
DICOM标准的推出与实现,大大简化了医学影像信息交换的实现,推动了远程放射学系统、图像管理与通信系统(PACS)的研究与发展,并且由于DICOM的开放性与互联性,使得与其它医学应用系统(HIS、RIS等)的集成成为可能。此处,Dicom标注还定义了数据集,数据集又由多个数据元素(Data Element)组成,每个数据元素描述一条信息,因此可以在Dicom文件中存储一些数据,例如患者信息、申请单信息、检查类型等。
源代码展示
包管理,安装fo-dicom和fo-dicom.Desktop
代码中用到的数据类
using System; namespace ConvertJpgToDicom { public class DicomUploadInfo { public string PatientId { get; set; } public string PatientName { get; set; } public string PatientGender { get; set; } public string PatientDob { get; set; } public string PatientAge { get; set; } public DateTime StudyTime { get; set; } public string AccessionNumber { get; set; } } public class DicomUploadImageInfo { public int? ImageInfoId { get; set; } public string ImageFileName { get; set; } public string DicomFileName { get; set; } public string ImageUID { get; set; } public string SeriesUID { get; set; } public bool IsImageUIDChanged { get; set; } public string Modality { get; set; } public string PixelSpacing { get; set; } public string TargetFileName { get; set; } public string ToBeUploadedFileName { get; set; } } }
Jpg2Dicom具体代码
1 public class ConverttHelper 2 { 3 public static void ImageFileToDicomFile(DicomUploadImageInfo dicomUploadImageInfo, DicomUploadInfo dicomInfo, DicomUID studyUID, DicomUID seriesUID, DicomUID imageUID) 4 { 5 using (var bitmap = new Bitmap(dicomUploadImageInfo.ImageFileName)) 6 { 7 int rows, columns; 8 byte[] pixels; 9 if (bitmap.PixelFormat != PixelFormat.Format24bppRgb) 10 { 11 using (var newBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format24bppRgb)) 12 { 13 using (var g = Graphics.FromImage(newBitmap)) 14 { 15 g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height); 16 } 17 pixels = GetPixels(newBitmap, out rows, out columns); 18 } 19 } 20 else 21 { 22 pixels = GetPixels(bitmap, out rows, out columns); 23 } 24 var buffer = new MemoryByteBuffer(pixels); 25 var dataset = new DicomDataset(); 26 FillDataset(dataset, dicomInfo, dicomUploadImageInfo, studyUID, seriesUID, imageUID); 27 dataset.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Rgb.Value); 28 dataset.Add(DicomTag.Rows, (ushort)rows); 29 dataset.Add(DicomTag.Columns, (ushort)columns); 30 dataset.Add(DicomTag.BitsAllocated, (ushort)8); 31 var pixelData = DicomPixelData.Create(dataset, true); 32 pixelData.BitsStored = 8; 33 pixelData.SamplesPerPixel = 3; 34 pixelData.HighBit = 7; 35 pixelData.PixelRepresentation = 0; 36 pixelData.PlanarConfiguration = 0; 37 pixelData.AddFrame(buffer); 38 var dicomFile = new DicomFile(dataset); 39 if (_imageCompression) 40 { 41 try 42 { 43 // 压缩方式存储 44 DicomTranscoder transcoder = new DicomTranscoder(dicomFile.Dataset.InternalTransferSyntax, DicomTransferSyntax.JPEGLSLossless); 45 transcoder.Transcode(dicomFile).Save(dicomUploadImageInfo.TargetFileName); 46 } 47 catch 48 { 49 // 压缩失败,则改为不压缩的方式存储 50 dicomFile.Save(dicomUploadImageInfo.TargetFileName); 51 } 52 } 53 else 54 { 55 dicomFile.Save(dicomUploadImageInfo.TargetFileName); 56 } 57 } 58 } 59 60 private static void FillDataset(DicomDataset dataset, DicomUploadInfo dicomInfo, DicomUploadImageInfo dicomUploadImageInfo, DicomUID studyUID, DicomUID seriesUID, DicomUID imageUID) 61 { 62 // Type 1 attributes 63 dataset.Add(DicomTag.SOPClassUID, dicomUploadImageInfo.Modality == "ES" ? DicomUID.VideoEndoscopicImageStorage : DicomUID.UltrasoundImageStorage); 64 dataset.Add(DicomTag.StudyInstanceUID, studyUID); 65 dataset.Add(DicomTag.SeriesInstanceUID, seriesUID); 66 dataset.Add(DicomTag.SOPInstanceUID, imageUID); 67 68 // Type 2 attributes 69 dataset.Add(DicomTag.PatientID, dicomInfo.PatientId); 70 dataset.Add(DicomTag.PatientName, dicomInfo.PatientName); 71 dataset.Add(DicomTag.PatientSex, dicomInfo.PatientGender); 72 dataset.Add(DicomTag.PatientBirthDate, dicomInfo.PatientDob); 73 dataset.Add(DicomTag.StudyDate, dicomInfo.StudyTime.Date); 74 dataset.Add(DicomTag.StudyTime, dicomInfo.StudyTime); 75 dataset.Add(DicomTag.AccessionNumber, dicomInfo.AccessionNumber); 76 dataset.Add(DicomTag.StudyID, "1"); 77 dataset.Add(DicomTag.SeriesNumber, "1"); 78 dataset.Add(DicomTag.Modality, dicomUploadImageInfo.Modality); 79 if (!string.IsNullOrWhiteSpace(dicomUploadImageInfo.PixelSpacing)) 80 { 81 dataset.Add(DicomTag.PixelSpacing, dicomUploadImageInfo.PixelSpacing); 82 } 83 } 84 85 [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)] 86 private static byte[] GetPixels(Bitmap image, out int rows, out int columns) 87 { 88 rows = image.Height; 89 columns = image.Width; 90 91 if (rows % 2 != 0 && columns % 2 != 0) 92 --columns; 93 94 var data = image.LockBits(new Rectangle(0, 0, columns, rows), ImageLockMode.ReadOnly, image.PixelFormat); 95 var bmpData = data.Scan0; 96 try 97 { 98 var stride = columns * 3; 99 var size = rows * stride; 100 var pixelData = new byte[size]; 101 for (var i = 0; i < rows; ++i) 102 Marshal.Copy(new IntPtr(bmpData.ToInt64() + i * data.Stride), pixelData, i * stride, stride); 103 104 // Swap BGR to RGB 105 SwapRedBlue(pixelData); 106 return pixelData; 107 } 108 finally 109 { 110 image.UnlockBits(data); 111 } 112 } 113 114 private static void SwapRedBlue(byte[] pixels) 115 { 116 for (var i = 0; i < pixels.Length; i += 3) 117 { 118 var temp = pixels[i]; 119 pixels[i] = pixels[i + 2]; 120 pixels[i + 2] = temp; 121 } 122 } 123 124 private static readonly bool _imageCompression = false; 125 126 }
调用处代码,Winfrom窗体中包含 selectImageFileButton按钮,一个OpenFileDialog控件,一个PictureBox控件。
1 private void selectImageFileButton_Click(object sender, EventArgs e) 2 { 3 openFileDialog1.Filter = "图片|*.jpg;*.jpeg;*.bmp;*.png"; 4 openFileDialog1.ShowDialog(); 5 openFileDialog1.Multiselect = false; 6 string imgaeFileName = openFileDialog1.FileName; 7 if (!string.IsNullOrEmpty(imgaeFileName)) 8 { 9 uploadingImagePictureBox.Image = Image.FromFile(imgaeFileName); 10 Random random = new Random(Guid.NewGuid().GetHashCode()); 11 DicomUploadInfo dicomUploadInfo = new DicomUploadInfo 12 { 13 PatientId = Guid.NewGuid().ToString(), 14 PatientName = "zhangsan", 15 PatientGender = "M", 16 PatientDob = DateTime.Now.AddDays(random.Next(-1000, 1000)).ToString("yyyyMMdd"), 17 StudyTime = DateTime.Now.AddDays(random.Next(-1000, 1000)), 18 AccessionNumber = "US" + DateTime.Now.ToString("yyyyMMddHHmmss") 19 }; 20 string strStudyUid = string.Empty; 21 DicomUID imageUid = GenerateUid(); 22 DicomUID seriesUid = GenerateUid(); 23 DicomUploadImageInfo dicomUploadImageInfo = new DicomUploadImageInfo 24 { 25 ImageInfoId = Guid.NewGuid(), 26 ImageFileName = imgaeFileName, 27 Modality = "US", 28 TargetFileName = $"{imgaeFileName}.dcm" 29 }; 30 ConverttHelper.ImageFileToDicomFile(dicomUploadImageInfo, dicomUploadInfo, GetStudyUid(ref strStudyUid), seriesUid, imageUid); 31 } 32 } 33 34 private DicomUID GetStudyUid(ref string studyUid) 35 { 36 DicomUID uid; 37 if (string.IsNullOrEmpty(studyUid)) 38 { 39 uid = GenerateUid(); 40 studyUid = uid.UID; 41 } 42 else 43 { 44 uid = DicomUID.Parse(studyUid); 45 } 46 return uid; 47 } 48 49 private static readonly object _lockGenerateUidObject = new object(); 50 private DicomUID GenerateUid() 51 { 52 lock (_lockGenerateUidObject) 53 { 54 Random random = new Random(Guid.NewGuid().GetHashCode()); 55 StringBuilder uidBuilder = new StringBuilder(); 56 string uidSeed = GetIPAddress() + "."; 57 uidBuilder.Append("1.2.826.0.1.3680043.9.5115").Append('.').Append(uidSeed).Append(DateTime.UtcNow.Ticks).Append(random.Next(0, 1000).ToString("D3")); // D3 十进制数,不足3位时前面补0 58 return new DicomUID(uidBuilder.ToString(), "SOP Instance UID", DicomUidType.SOPInstance); 59 } 60 } 61 62 public string GetIPAddress() 63 { 64 IPAddress ipAddress = Dns.GetHostAddresses(Dns.GetHostName()).FirstOrDefault(p => p.AddressFamily == AddressFamily.InterNetwork); 65 return ipAddress != null ? ipAddress.ToString() : string.Empty; 66 }
如果想要查看Dicom文件中的图像,可参考下方的代码:
1 private void selectDicomFileButton_Click(object sender, EventArgs e) 2 { 3 //将图像处理模式设置为全局WPF模式 4 Dicom.Imaging.ImageManager.SetImplementation(Dicom.Imaging.WinFormsImageManager.Instance); 5 6 openFileDialog1.Filter = "Dicom文件|*.dcm"; 7 openFileDialog1.ShowDialog(); 8 openFileDialog1.Multiselect = false; 9 string dicomFileName = openFileDialog1.FileName; 10 11 //实例化文件处理对象并打开文件 12 DicomFile dicomFile = DicomFile.Open(dicomFileName); 13 //获取dicom图像对象 14 DicomImage dicomImage = new DicomImage(dicomFile.Dataset); 15 //不使用LUT 16 dicomImage.UseVOILUT = false; 17 18 //转换成一般图像格式,bmp,png等, 19 //在WPF中我们转换成WriteableBitmap 20 var bitmap = dicomImage.RenderImage().AsClonedBitmap(); 21 pictureBox1.Image = bitmap; 22 }
本文来自博客园,作者:业荒于嬉,转载请注明原文链接:https://www.cnblogs.com/FreeLoopPowter/p/17511038.html
如内容对您有所帮助,还请不吝推荐一下!