Unity 读取DICOM文件,并支持移动端

本文参考网上大神的源码,在此基础上修改,适配Unity,并支持移动端,本文代码支持安卓端,ios端请各位自行适配,原理不变,只是在数据读取的方法上可以有点区别。

大神原贴:医学影像调窗技术 - assassinx - 博客园

Dicom格式文件解析器 - assassinx - 博客园

下面直接上源码。

  public RawImage testimg;
    public TextMeshProUGUI detext;

    string fileName = "";
    Dictionary<string, string> tags = new Dictionary<string, string>();//dicom文件中的标签
    BinaryReader dicomFile = null;//dicom文件流
   
    //文件元信息
    //public Bitmap gdiImg;//转换后的gdi图像
    private Texture2D dicomimg = null;
    UInt32 fileHeadLen;//文件头长度
    long fileHeadOffset;//文件数据开始位置
    UInt32 pixDatalen;//像素数据长度
    long pixDataOffset = 0;//像素数据开始位置
    bool isLitteEndian = true;//是否小字节序(小端在前 、大端在前)
    bool isExplicitVR = true;//有无VR
    MemoryStream mstream;
    //像素信息
    int colors;//颜色数 RGB为3 黑白为1
    //public int windowWith = 2048, windowCenter = 2048 / 2;//窗宽窗位
    private int windowWith = 0, windowCenter = 0;//窗宽窗位
    int rows, cols;

 void Start()
    {
#if UNITY_EDITOR
        fileName = Application.dataPath + "/StreamingAssets/DicomImage" + "/test.dcm";
#elif UNITY_IPHONE
            fileName = Application.dataPath +"/Raw/DicomImage"+"/test.dcm";
#elif UNITY_ANDROID
            //fileName = Application.persistentDataPath + "/DicomImage"+"/test.dcm";
            fileName = "jar:file://" + Application.dataPath + "!/assets/DicomImage"+"/test.dcm";
#endif
        detext.text += fileName + "\n";
        mstream = new MemoryStream();
        UnityWebRequest request = UnityWebRequest.Get(fileName);
        request.SendWebRequest();//读取数据
        while (true)
        {
            if (request.downloadHandler.isDone)//是否读取完数据
            {
                mstream.Write(request.downloadHandler.data, 0, request.downloadHandler.data.Length);
                break;
            }
        }
        readAndShow();
    }

public void readAndShow()
    {
        if (fileName == string.Empty)
            return;
        dicomFile = new BinaryReader(mstream);
        if(dicomFile == null)
            detext.text += "dicomFile == null" + "\n";
        //跳过128字节导言部分
        dicomFile.BaseStream.Seek(128, SeekOrigin.Begin);

        if (new string(dicomFile.ReadChars(4)) != "DICM")
        {
            //MessageBox.Show("没有dicom标识头,文件格式错误");
            Debug.Log("没有dicom标识头,文件格式错误");
            detext.text += "没有dicom标识头,文件格式错误" + "\n";
            return;
        }
        else
        {
            detext.text += "DICM" + "\n";
        }

 
        tagRead();
        getImg();
        IDictionaryEnumerator enor = tags.GetEnumerator();
       
        dicomFile.Close();
    }

  void tagRead()//不断读取所有tag 及其值 直到碰到图像数据 (7fe0 0010 )
    {
        detext.text += "tagRead" + "\n";
        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));
                VR = Encoding.Default.GetString(dicomFile.ReadBytes(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 == &#

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值