【实例简介】

DCM文件转图像,并高清处理图像

【实例截图】

【核心代码】

#region DicomHandler 医学图像解析

class DicomHandler

{

string fileName = "";

Dictionary tags = new Dictionary();//dicom文件中的标签

BinaryReader dicomFile;//dicom文件流

//文件元信息

public Bitmap gdiImg;//转换后的gdi图像

UInt32 fileHeadLen;//文件头长度

long fileHeadOffset;//文件数据开始位置

UInt32 pixDatalen;//像素数据长度

long pixDataOffset = 0;//像素数据开始位置

bool isLitteEndian = true;//是否小字节序(小端在前 、大端在前)

bool isExplicitVR = true;//有无VR

//像素信息

int colors;//颜色数 RGB为3 黑白为1

public int windowWith = 2048, windowCenter = 2048 / 2;//窗宽窗位

int rows, cols;

public void readAndShow(out string textBox1)

{

textBox1 = "";

if (fileName == string.Empty)

{

textBox1 = "请选择文件";

}

else

{

dicomFile = new BinaryReader(File.OpenRead(fileName));

//跳过128字节导言部分

dicomFile.BaseStream.Seek(128, SeekOrigin.Begin);

if (new string(dicomFile.ReadChars(4)) != "DICM")

{

textBox1 = "没有dicom标识头,文件格式错误";

}

else

{

tagRead();

IDictionaryEnumerator enor = tags.GetEnumerator();

while (enor.MoveNext())

{

if (enor.Key.ToString().Length > 9)

{

textBox1 = enor.Key.ToString() "\r\n";

textBox1 = enor.Value.ToString().Replace('\0', ' ');

}

else

textBox1 = enor.Key.ToString() enor.Value.ToString().Replace('\0', ' ') "\r\n";

}

dicomFile.Close();

}

}

}

public DicomHandler(string _filename)

{

fileName = _filename;

}

public void saveAs(string filename)

{

switch (filename.Substring(filename.LastIndexOf('.')))

{

case ".jpg":

gdiImg.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg);

break;

case ".bmp":

gdiImg.Save(filename, System.Drawing.Imaging.ImageFormat.Bmp);

break;

case ".png":

gdiImg.Save(filename, System.Drawing.Imaging.ImageFormat.Png);

break;

default:

break;

}

}

public bool getImg()//获取图像 在图像数据偏移量已经确定的情况下

{

if (fileName == string.Empty)

return false;

int dataLen, validLen;//数据长度 有效位

int imgNum;//帧数

rows = int.Parse(tags["0028,0010"].Substring(5));

cols = int.Parse(tags["0028,0011"].Substring(5));

colors = int.Parse(tags["0028,0002"].Substring(5));

dataLen = int.Parse(tags["0028,0100"].Substring(5));

validLen = int.Parse(tags["0028,0101"].Substring(5));

gdiImg = new Bitmap(cols, rows);

BinaryReader dicomFile = new BinaryReader(File.OpenRead(fileName));

dicomFile.BaseStream.Seek(pixDataOffset, SeekOrigin.Begin);

long reads = 0;

for (int i = 0; i < gdiImg.Height; i )

{

for (int j = 0; j < gdiImg.Width; j )

{

if (reads >= pixDatalen)

break;

byte[] pixData = dicomFile.ReadBytes(dataLen / 8 * colors);

reads = pixData.Length;

Color c = Color.Empty;

if (colors == 1)

{

int grayGDI;

double gray = BitConverter.ToUInt16(pixData, 0);

//调窗代码,就这么几句而已

//1先确定窗口范围 2映射到8位灰度

int grayStart = (windowCenter - windowWith / 2);

int grayEnd = (windowCenter windowWith / 2);

if (gray < grayStart)

grayGDI = 0;

else if (gray > grayEnd)

grayGDI = 255;

else

{

grayGDI = (int)((gray - grayStart) * 255 / windowWith);

}

if (grayGDI > 255)

grayGDI = 255;

else if (grayGDI < 0)

grayGDI = 0;

c = Color.FromArgb(grayGDI, grayGDI, grayGDI);

}

else if (colors == 3)

{

c = Color.FromArgb(pixData[0], pixData[1], pixData[2]);

}

gdiImg.SetPixel(j, i, c);

}

}

dicomFile.Close();

return true;

}

void tagRead()//不断读取所有tag 及其值 直到碰到图像数据 (7fe0 0010 )

{

bool enDir = false;

int leve = 0;

StringBuilder folderData = new StringBuilder();//该死的文件夹标签

string folderTag = "";

while (dicomFile.BaseStream.Position 6 < dicomFile.BaseStream.Length)

{

//读取tag

string tag = dicomFile.ReadUInt16().ToString("x4") ","

dicomFile.ReadUInt16().ToString("x4");

string VR = string.Empty;

UInt32 Len = 0;

//读取VR跟Len

//对OB OW SQ 要做特殊处理 先置两个字节0 然后4字节值长度

//------------------------------------------------------这些都是在读取VR一步被阻断的情况

if (tag.Substring(0, 4) == "0002")//文件头 特殊情况

{

VR = new string(dicomFile.ReadChars(2));

if (VR == "OB" || VR == "OW" || VR == "SQ" || VR == "OF" || VR == "UT" || VR == "UN")

{

dicomFile.BaseStream.Seek(2, SeekOrigin.Current);

Len = dicomFile.ReadUInt32();

}

else

Len = dicomFile.ReadUInt16();

}

else if (tag == "fffe,e000" || tag == "fffe,e00d" || tag == "fffe,e0dd")//文件夹标签

{

VR = "**";

Len = dicomFile.ReadUInt32();

}

else if (isExplicitVR == true)//有无VR的情况

{

VR = new string(dicomFile.ReadChars(2));

if (VR == "OB" || VR == "OW" || VR == "SQ" || VR == "OF" || VR == "UT" || VR == "UN")

{

dicomFile.BaseStream.Seek(2, SeekOrigin.Current);

Len = dicomFile.ReadUInt32();

}

else

Len = dicomFile.ReadUInt16();

}

else if (isExplicitVR == false)

{

VR = getVR(tag);//无显示VR时根据tag一个一个去找 真烦啊。

Len = dicomFile.ReadUInt32();

}

//判断是否应该读取VF 以何种方式读取VF

//-------------------------------------------------------这些都是在读取VF一步被阻断的情况

byte[] VF = { 0x00 };

if (tag == "7fe0,0010")//图像数据开始了

{

pixDatalen = Len;

pixDataOffset = dicomFile.BaseStream.Position;

dicomFile.BaseStream.Seek(Len, SeekOrigin.Current);

VR = "UL";

VF = BitConverter.GetBytes(Len);

}

else if ((VR == "SQ" && Len == UInt32.MaxValue) || (tag == "fffe,e000" && Len == UInt32.MaxValue))//靠 遇到文件夹开始标签了

{

if (enDir == false)

{

enDir = true;

folderData.Remove(0, folderData.Length);

folderTag = tag;

}

else

{

leve ;//VF不赋值

}

}

else if ((tag == "fffe,e00d" && Len == UInt32.MinValue) || (tag == "fffe,e0dd" && Len == UInt32.MinValue))//文件夹结束标签

{

if (enDir == true)

{

enDir = false;

}

else

{

leve--;

}

}

else

VF = dicomFile.ReadBytes((int)Len);

string VFStr;

VFStr = getVF(VR, VF);

//----------------------------------------------------------------针对特殊的tag的值的处理

//特别针对文件头信息处理

if (tag == "0002,0000")

{

fileHeadLen = Len;

fileHeadOffset = dicomFile.BaseStream.Position;

}

else if (tag == "0002,0010")//传输语法 关系到后面的数据读取

{

switch (VFStr)

{

case "1.2.840.10008.1.2.1\0"://显示little

isLitteEndian = true;

isExplicitVR = true;

break;

case "1.2.840.10008.1.2.2\0"://显示big

isLitteEndian = false;

isExplicitVR = true;

break;

case "1.2.840.10008.1.2\0"://隐式little

isLitteEndian = true;

isExplicitVR = false;

break;

default:

break;

}

}

for (int i = 1; i <= leve; i )

tag = "--" tag;

//------------------------------------数据搜集代码

if ((VR == "SQ" && Len == UInt32.MaxValue) || (tag == "fffe,e000" && Len == UInt32.MaxValue) || leve > 0)//文件夹标签代码

{

folderData.AppendLine(tag "(" VR "):" VFStr);

}

else if (((tag == "fffe,e00d" && Len == UInt32.MinValue) || (tag == "fffe,e0dd" && Len == UInt32.MinValue)) && leve == 0)//文件夹结束标签

{

folderData.AppendLine(tag "(" VR "):" VFStr);

tags.Add(folderTag "SQ", folderData.ToString());

}

else

tags.Add(tag, "(" VR "):" VFStr);

}

}

string getVR(string tag)

{

switch (tag)

{

case "0002,0000"://文件元信息长度

return "UL";

break;

case "0002,0010"://传输语法

return "UI";

break;

case "0002,0013"://文件生成程序的标题

return "SH";

break;

case "0008,0005"://文本编码

return "CS";

break;

case "0008,0008":

return "CS";

break;

case "0008,1032"://成像时间

return "SQ";

break;

case "0008,1111":

return "SQ";

break;

case "0008,0020"://检查日期

return "DA";

break;

case "0008,0060"://成像仪器

return "CS";

break;

case "0008,0070"://成像仪厂商

return "LO";

break;

case "0008,0080":

return "LO";

break;

case "0010,0010"://病人姓名

return "PN";

break;

case "0010,0020"://病人id

return "LO";

break;

case "0010,0030"://病人生日

return "DA";

break;

case "0018,0060"://电压

return "DS";

break;

case "0018,1030"://协议名

return "LO";

break;

case "0018,1151":

return "IS";

break;

case "0020,0010"://检查ID

return "SH";

break;

case "0020,0011"://序列

return "IS";

break;

case "0020,0012"://成像编号

return "IS";

break;

case "0020,0013"://影像编号

return "IS";

break;

case "0028,0002"://像素采样1为灰度3为彩色

return "US";

break;

case "0028,0004"://图像模式MONOCHROME2为灰度

return "CS";

break;

case "0028,0010"://row高

return "US";

break;

case "0028,0011"://col宽

return "US";

break;

case "0028,0100"://单个采样数据长度

return "US";

break;

case "0028,0101"://实际长度

return "US";

break;

case "0028,0102"://采样最大值

return "US";

break;

case "0028,1050"://窗位

return "DS";

break;

case "0028,1051"://窗宽

return "DS";

break;

case "0028,1052":

return "DS";

break;

case "0028,1053":

return "DS";

break;

case "0040,0008"://文件夹标签

return "SQ";

break;

case "0040,0260"://文件夹标签

return "SQ";

break;

case "0040,0275"://文件夹标签

return "SQ";

break;

case "7fe0,0010"://像素数据开始处

return "OW";

break;

default:

return "UN";

break;

}

}

string getVF(string VR, byte[] VF)

{

string VFStr = string.Empty;

switch (VR)

{

case "SS":

VFStr = BitConverter.ToInt16(VF, 0).ToString();

break;

case "US":

VFStr = BitConverter.ToUInt16(VF, 0).ToString();

break;

case "SL":

VFStr = BitConverter.ToInt32(VF, 0).ToString();

break;

case "UL":

VFStr = BitConverter.ToUInt32(VF, 0).ToString();

break;

case "AT":

VFStr = BitConverter.ToUInt16(VF, 0).ToString();

break;

case "FL":

VFStr = BitConverter.ToSingle(VF, 0).ToString();

break;

case "FD":

VFStr = BitConverter.ToDouble(VF, 0).ToString();

break;

case "OB":

VFStr = BitConverter.ToString(VF, 0);

break;

case "OW":

VFStr = BitConverter.ToString(VF, 0);

break;

case "SQ":

VFStr = BitConverter.ToString(VF, 0);

break;

case "OF":

VFStr = BitConverter.ToString(VF, 0);

break;

case "UT":

VFStr = BitConverter.ToString(VF, 0);

break;

case "UN":

VFStr = Encoding.Default.GetString(VF);

break;

default:

VFStr = Encoding.Default.GetString(VF);

break;

}

return VFStr;

}

}

#endregion

java dcm转bmp源码_DCM文件转图像,并高清处理图像相关推荐

  1. 短视频源码如何快速打造一款高清又极速的短视频APP?...

    整个短视频的市场规模一直在增长,网络数据显示2018年已经突破100亿大关,在2019年预测将超过200亿.纵观行业,在生活资讯.美食.搞笑.游戏.美妆等领域,短视频流量巨大但竞争激烈,但是在教育.财 ...

  2. html2canvas源码修改,html2canvas把div保存高清图的方法代码

    http://www.bootcdn.cn/(可以搜索html2canvans) 1.选择html2canvas版本(这个版本可以放大倍数保证图片清晰) 默认生成的canvas图片在retina设备上 ...

  3. 基于java的千千影评网站的设计与实现(论文+程序设计源码+数据库文件)

    摘要:信息技术高度发达的今天,新闻业已经在互联网行业中占越发主导地位.而我们的生活也跟新闻息息相关,尤其是在高度发达的精神文化社会,人们对于电影的喜爱也越来越热衷,但想挑到自己喜爱的片子,就需要影评网 ...

  4. 基于java项目ssm二手书交易平台设计与实现(论文+程序设计源码+数据库文件)

    1 绪论 4 1.1 项目开发背景 4 1.2 项目开发意义 5 1.3 项目主要的内容 5 2 相关技术介绍及系统环境开发条件 6 2.1相关技术介绍 6 2.2系统环境开发条件 7 3 系统的需求 ...

  5. 基于ssh的航空订票系统-飞机订票系统javaweb-机票订购课程设计java代码(源码+数据库文件+文档)

    基于ssh的航空订票系统-飞机订票系统javaweb-机票订购java代码(源码+数据库文件+文档) 注意:该项目只展示部分功能,如需了解,评论区咨询即可. 作者:IT跃迁谷 1.开发环境 开发语言: ...

  6. java的String类源码详解

    java的String类源码详解 类的定义 public final class Stringimplements java.io.Serializable, Comparable<String ...

  7. ssh+mysql实现的Java web论坛系统源码

    今天给大家来演示一下一款有spring+struts2+hibernate+mysql实现的Java web论坛系统源码,本系统功能类似与csdn论坛,用户发帖时可以设置积分,当结帖时可以选择给评论的 ...

  8. axis2 webservice入门学识(JS,Java,PHP调用实例源码)

    来源:http://www.myexception.cn/web/952419.html axis2 webservice入门知识(JS,Java,PHP调用实例源码) 背景简介 最近接触到一个银行接 ...

  9. Java中资源文件获取源码浅析

    Java中资源文件获取源码浅析 文章目录 Java中资源文件获取源码浅析 JDK11 Class.getResource(String) Class.getClassLoader().getResou ...

最新文章

  1. 基于Python的人工智能美颜系统
  2. 轻松一刻:程序员的工作状态
  3. js字符串的字典序_JavaScript通过字典进行字符串翻译转换的方法
  4. 曲线图绘制软件_Origin教程丨一文教你快速绘制20种常用图
  5. DNS通道检测 国外学术界研究情况——研究方法:基于流量,使用机器学习分类算法居多,也有使用聚类算法的;此外使用域名zif low也有...
  6. 单机负载告警,数据库与应用分离
  7. settimeout怎么用_怎么实现一个3d翻书效果
  8. CSS3那些不为人知的高级属性
  9. vue-datepicker的使用
  10. 文件操作--设置文件属性、获取文件属性
  11. 实验8.3 C++标准模板库(STL)中的双向队列类(deque)
  12. VS Code的相对路径问题 (No such file or directory: './lenna.png')
  13. SAP成都研究院飞机哥:程序猿和飞机的不解之缘
  14. sobel边缘检测java_Sobel边缘检测
  15. Linux下基于Openstack安装部署私有云
  16. MySQL【触发器】
  17. 玩转DWZ (一)---项目中怎么使用dwz
  18. Java基础入门--学习笔记
  19. 会计报表分析相关指标收集
  20. 西门子S7-200PLC自由口初始化

热门文章

  1. 【ROM制作工具】合并分割system.img和userdata.img文件修改教程
  2. python-DRF_限流Throttling_自定义频率类_内置频率类使用_过滤排序功能
  3. Flask-APScheduler使用教程 1
  4. 学术-几何:黑森错觉
  5. win10 的 PS 不能直接拖进文件的解决方法(附:与 Edge 登录的冲突)
  6. 智和信通:立足数字化、智能化、可视化,打造一站式制造业网络运维平台
  7. 《咏怀古迹五首·其三》.唐.杜甫
  8. 音频(七)——数字麦克风和模拟麦克风(DMIC/AMIC)
  9. 【报告分享】2020快手母婴生态报告-快手大数据研究院(附下载)
  10. 消息中心(系统消息)实现