【C#】使用fo-dicom完成BMP,JPG,PNG图片转换为DICOM文件

简介:

最近研究了一下DICOM和BMP文件转换的问题,也是很头大。度娘了很久,也在CSDN等论坛看到一些断断续续的文件,最主要的是代码只是片断,不是完整的实现。头大了。
首先,了解一下BMP文件格式,BMP文件的显示是从左下开始显示,而DICOM显示图像是从左上开始。所以如果你直接解析BMP文件的话,记得数据区工反转一下,否则生成DICOM时看到的图像是倒着的。只需要反转BMP图像的行,列不需要反转。
不过好在Microsoft的C#给我们提供了一个较好的类库叫Bitmap类,使用它可以不用管这个反转了。
首先要从BMP图中获取图像数据区,代码如下:

        public static byte[] GetPixels(Bitmap bitmap)
        {
            byte[] bytes = new byte[bitmap.Width * bitmap.Height*3];
            int wide = bitmap.Width;
            int i = 0;
            int height = bitmap.Height;
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < wide; x++)
                {
                    var srcColor = bitmap.GetPixel(x, y);
                    //bytes[i] = (byte)(srcColor.R * .299 + srcColor.G * .587 + srcColor.B * .114);
                    bytes[i] = srcColor.R;
                    i++;
                    bytes[i] = srcColor.G;
                    i++;
                    bytes[i] = srcColor.B;
                    i++;
                }
            }
            return bytes;
        }

申请的数据为什么是图像的宽高乘积的3倍,这是因为R,G,B各占一个Byte。如果采用上面代码中注释的行,生成的DICOM文件图像就是灰度图像(黑白图了)。
然后是真正的转存DICOM文件了。代码如下:

        public static void ImportImage(string file)
        {
            Bitmap bitmap = new Bitmap(file);
            //bitmap = GetValidImage(bitmap);


            byte[] pixels = GetPixels(bitmap);
            MemoryByteBuffer buffer = new MemoryByteBuffer(pixels);
            DicomDataset dataset = new DicomDataset();
            //FillDataset(dataset);
            dataset.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Rgb.Value);
            dataset.Add(DicomTag.Rows, (ushort)bitmap.Height);
            dataset.Add(DicomTag.Columns, (ushort)bitmap.Width);
            dataset.Add(DicomTag.BitsAllocated, (ushort)8);
            dataset.Add(DicomTag.SOPClassUID, "1.2.840.10008.5.1.4.1.1.2");
            dataset.Add(DicomTag.SOPInstanceUID, "1.2.840.10008.5.1.4.1.1.2.20181120090837121314");
            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(@"e:\dicomfile.dcm");
            SaveDicomFile2(pixels, bitmap.Height, bitmap.Width);
        }

其中传入参数就是BMP/JPG/PNG图像的路径。这样你只需要一个入口程序(比如控制台的Main函数)就可以将一个图片转为DICOM还是彩色的。
这里只设置了DICOM必须的几个字段,这几个字段的意义可以参考官方标准说明。部分说明如下:
DICOM文件格式:
1)Samples Per Pixel:

    标签为(0028,0002),具体的介绍在DICOM3.0标准第3部分的附录C7.6.3.1。含义表示【the number of separate planes in this image】,就像PhotoShop中的通道,每个通道表示一种颜色(除了RGB三个通道以外,也会存在第四个通透性通道)。对于灰度图像(monochrome或gray)和颜色表图像(palette,就是BMP格式中介绍的有调色板的BMP文件),该标签值为1,RGB图像或其他色彩模式图像,该标签值为3。本实例中使用的BMP图像是RGB格式的,因此SamplePerPixel=3,起初的文件格式错误就是由于该字段设置为1所致。

2)Photometric Interpretation:

    标签为(0028,0004),具体介绍在DICOM3.0标准第3部分的附录C7.6.3.1.2。该字段常见的值有MONOCHROME1、MONOCHROME2、PALETTE COLOR、RGB,其中MONOCHROME1和MONOCHROME2表示单通道灰度图像,只是两者对黑色和白色的映射相反而已;PALETTE COLOR就是BMP中提到的调色板图像,此时需要SamplesPerPixel字段为1,;RGB是常见的R(红)、G(绿)、B(蓝)三通道彩色图像,此时SamplesPerPixel字段值为3,这就是我们实例中使用的图像。除此以外DICOM3.0标准中还给出了YBR_FULL、HSV、ARGB、CMYK等方式,此处就不详细介绍了。

3)Planar Configuration:

    标签为(0028,0006),具体介绍在DICOM3.0标准第3部分附录C7.6.3.1.3。当Samples Per Pixel字段的值大于1时,Planar Configuration字段规定了实际像素信息的存储方式,具体如下:

20150727112322434
BitsAllocated 每一种颜色值所分配的存储位数,一般彩色是8,灰度可以设置到16,不能大于16。
BitsStored 像素值的实际存储位数
HighBit 像素值存储的最高位(一般是BitsStored-1)。
关于BMP文件格式说明可参照:https://blog.csdn.net/zjq_1314520/article/details/53830349

目录
相关文章
|
2月前
|
数据采集 JavaScript C#
C#图像爬虫实战:从Walmart网站下载图片
C#图像爬虫实战:从Walmart网站下载图片
|
1月前
|
存储 C#
【C#】大批量判断文件是否存在的两种方法效率对比
【C#】大批量判断文件是否存在的两种方法效率对比
32 1
|
1月前
|
XML 存储 缓存
C#使用XML文件的详解及示例
C#使用XML文件的详解及示例
76 0
|
3月前
|
监控 安全 C#
使用C#如何监控选定文件夹中文件的变动情况?
使用C#如何监控选定文件夹中文件的变动情况?
115 19
|
3月前
|
编译器 C# Windows
C#基础:手动编译一个.cs源代码文件并生成.exe可执行文件
通过上述步骤,应该能够高效准确地编译C#源代码并生成相应的可执行文件。此外,这一过程强调了对命令行编译器的理解,这在调试和自动化编译流程中是非常重要的。
234 2
|
3月前
|
文字识别 C# Python
使用C#将几个Excel文件合并去重分类
使用C#将几个Excel文件合并去重分类
30 3
|
3月前
|
C# 图形学 数据安全/隐私保护
Unity数据加密☀️ 二、使用Rider将C#代码生成DLL文件
Unity数据加密☀️ 二、使用Rider将C#代码生成DLL文件
|
3月前
|
C#
C# 写日志文件
C# 写日志文件
42 0
|
5月前
|
C#
【C#】C#读写Excel文件
【C#】C#读写Excel文件
124 1
|
5月前
|
JavaScript 前端开发 C#
初识Unity——创建代码、场景以及五个常用面板(创建C#代码、打开代码文件、场景的创建、Project、Hierarchy、Inspector、Scene、Game )
初识Unity——创建代码、场景以及五个常用面板(创建C#代码、打开代码文件、场景的创建、Project、Hierarchy、Inspector、Scene、Game )
272 0