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

举报
华为MVP-技术无限 发表于 2018/12/21 13:36:14 2018/12/21
【摘要】 最近研究了一下DICOM和BMP文件转换的问题,也是很头大。度娘了很久,也在CSDN等论坛看到一些断断续续的文件,最主要的是代码只是片断,不是完整的实现。头大了。首先,了解一下BMP文件格式,BMP文件的显示是从左下开始显示,而DICOM显示图像是从左上开始。所以如果你直接解析BMP文件的话,记得数据区工反转一下,否则生成DICOM时看到的图像是倒着的。只需要反转BMP图像的行,列不需要反转...

最近研究了一下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字段规定了实际像素信息的存储方式,具体如下:

1ccae4ee2249a4d1a8e535c2c1a0d027e92effb3.png

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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。