因此,目前我有一个程序,它接收DICOM file并对其进行解析。在解析过程中,程序将查看DICOM数据中的数据,并将其分配给Dictionary Entry。我的目标是通过数据编辑一些关键标签,然后将XML写入新的DICOM文件。但是,我很难弄清楚如何将所做的更改保存到新的DICOM文件中,这样我就可以拥有原始的和新编辑的DICOM文件。
private XmlDictionary ReadXML(string FileName)
{
XmlSerializer xmls = new XmlSerializer(typeof(XmlDictionary));
XmlDictionary xmldic = new XmlDictionary();
XmlNodeList xn = null;
FileInfo file = new FileInfo(FileName);
if (!file.Exists)
{
return xmldic;
}
XmlDocument xdoc = new XmlDocument();
try
{
xdoc.Load(FileName);
xn = xdoc.SelectNodes("/Dictionary/Tag");
xn.GetType();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
xmldic.xmlTag = new XmlTag[xn.Count];
StreamReader sr = new StreamReader(FileName);
xmldic = (XmlDictionary)xmls.Deserialize(sr);
sr.Close();
return xmldic;
}
public void LoadPrivateTags()
{
DICOMViewer.Properties.Settings mySettings = new DICOMViewer.Properties.Settings();
DirectoryInfo dir = new DirectoryInfo(Application.StartupPath);
FileInfo[] files = dir.GetFiles("privatedata*.xml");
for (int i = 0; i < files.Length; i++)
{
try
{
string filepath = files[i].FullName;
XmlDictionary dic = ReadXML(filepath);
if (dic.xmlTag != null)
{
for (int ilist = 0; ilist < dic.xmlTag.Length; ilist++)
{
int group = Convert.ToInt32(dic.xmlTag[ilist].xmlGroup, 16);
int element = Convert.ToInt32(dic.xmlTag[ilist].xmlElement, 16);
string s = Wrapper.TagDescription((uint)((group<<16)+element));
if ((s != "Undefined")&&(mySettings.WarnOfDuplicates == true))
{
MessageBox.Show(string.Format("Element {0:X},{1:X} <{2}> seems to be in dictionary already.",group, element, s), "Duplicate Private Data");
}
Wrapper.AddDictionaryEntry(group, element,
dic.xmlTag[ilist].xmlVR, dic.xmlTag[ilist].xmlDescription,
dic.xmlTag[ilist].xmlValueMultiplicity);
}
}
}
catch
{}
}
}
public void openDcmFile(string filename)
{
UseWaitCursor = true;
ViewDCM form = new ViewDCM();
form.MdiParent = this;
form.Text = System.IO.Path.GetFileName(filename);
DateTime startTime = DateTime.Now;
DCM read = new DCM(filename);
form.treeView1.Nodes.Add(read.GetNodes());
form.treeView1.Sort();
form.imageView1.GraphicsImage.BitmapList.Clear();
form.splitContainer1.Panel1Collapsed = true;
DateTime endTime = DateTime.Now;
TimeSpan loadTime = endTime.Subtract(startTime);
Bitmap[] img = read.GetImgs();
if (img != null)
{
if (img.Length == 1)
{
form.imageView1.GraphicsImage.BitmapList.Add(img[0]);
form.trackBar1.Visible = false;
}
else
{
form.imageView1.GraphicsImage.BitmapList.AddRange(img);
form.trackBar1.Visible = true;
form.trackBar1.Maximum = img.Length - 1;
form.trackBar1.Minimum = 0;
if (img.Length < 30) form.trackBar1.LargeChange = 1;
else form.trackBar1.LargeChange = form.trackBar1.Maximum / 10;
}
form.splitContainer1.Panel1Collapsed = false;
}
else
{
form.Text += " --- No Image Data ";
}
form.imageView1.GraphicsImage.Brightness = 200;
form.imageView1.GraphicsImage.InitialBrightness = 200;
form.imageView1.GraphicsImage.Contrast = 50;
form.imageView1.GraphicsImage.InitialContrast = 50;
form.imageView1.GraphicsImage.ShowThickness = false;
form.imageView1.GraphicsImage.ColorMode = CZM.CZMGraphics.GraphicsLib.Image.ImageColorMode.Pseuocolor;
form.imageView1.GraphicsImage.Show = true;
form.treeView1.ExpandAll();
form.Show();
//Application.DoEvents();
form.imageView1.Refresh();
UseWaitCursor = false;
}
这些是我用来读取DICOM并将其转换为XML的3个关键功能。我只需要一种将已编辑的XML保存到新的DICOM文件中的方法。
编辑: 我还使用这个DICOM类将文件中的所有数据放入表单树节点
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using GraphicsLib = CZM.CZMGraphics.GraphicsLib;
using CZM.Core.DCMLib;
using System.IO;
namespace DICOMViewer
{
class DCM
{
string _fileName;
TreeNode RootNode;
Hashtable m_hash;
/// <summary>
/// Constructor
/// </summary>
/// <param name="filename"></param>
public DCM(string filename)
{
_fileName = filename;
}
/// <summary>
/// Gets tags details
/// </summary>
/// <returns></returns>
public TreeNode GetNodes()
{
RootNode = new TreeNode("DICOM Tags");
try {
m_hash = CZM.Core.DCMLib.DCMLIB.RetrieveDicom(_fileName);
DateTime t1 = DateTime.Now;
var fs = new FileStream(_fileName, FileMode.Open);
Console.WriteLine("FS data: " + fs);
var bbb = new BinaryReader(fs);
Console.WriteLine("BBB data: " + bbb);
var bb2 = bbb.ReadBytes((int)fs.Length);
Console.WriteLine("BB2 data: " + bb2);
DateTime t2 = DateTime.Now;
Console.WriteLine("T2 data: " + t2);
TimeSpan ts = t2.Subtract(t1);
Console.WriteLine("T2 Cont. data: " + ts);
int k = ts.Seconds;
Console.WriteLine("K data: " + k);
}
catch { return RootNode; }
RootNode.ForeColor = Color.Green;
foreach (DictionaryEntry de in m_hash)
{
GetValue(de);
Console.WriteLine("DICTIONARY: " + de);
Console.WriteLine("ROOTNODE IS " + RootNode.Nodes);
}
return RootNode;
}
public void GetValue(DictionaryEntry de)
{
int key = (int)de.Key;
Console.WriteLine("Get Value jey: " + key);
int group = ((key >> 16) & 0xffff);
Console.WriteLine("Get Value group " + group);
int element = (key & 0xffff);
Console.WriteLine("Get Value element: " + element);
string groupstr = group.ToString("X4");
Console.WriteLine("Get Value groupstr: " + groupstr);
string elementstr = element.ToString("X4");
Console.WriteLine("Get Value elementstr: " + elementstr);
object value = de.Value;
Console.WriteLine("Get Value of value: " + value);
Console.WriteLine("Get Value of value as string: " + value.ToString());
// Sequences handled here
if (de.Value.GetType().ToString() == "System.Collections.ArrayList")
{
if (key == 0x7FE00010)
{
return;
}
// DICOM Sequences are implemented with ArrayLists
TreeNode GroupNode = new TreeNode(groupstr);
ArrayList array = (ArrayList)de.Value;
// Each Array in the List holds a hashtable
for (int i = 0; i < array.Count; i++)
{
Hashtable table = (Hashtable)array[i];
TreeNode SeqNode = new TreeNode(groupstr + elementstr + " , " + GetDescription(group, element));
Console.WriteLine("SeqNode --- : " + SeqNode);
SeqNode.ForeColor = Color.Green;
// Fill the sequence node with the stuff in the array element's hash
AddSubNode(table, groupstr, ref SeqNode);
GroupNode.Nodes.Add(SeqNode); // put sequence in group
}
bool addGrouptoRoot = true;
// Either add the sequence to an existing node or create a new one
foreach (TreeNode snode in RootNode.Nodes)
{
if (snode.Text == GroupNode.Text) // if group node is already in root...
{
foreach (TreeNode child in GroupNode.Nodes)// copy the group's nodes to the root's group node
{
snode.Nodes.Add(child);
Console.WriteLine("Child of the SNode is: " + child);
}
addGrouptoRoot = false;
break;
}
}
// else, add the new group to the root
if (addGrouptoRoot == true)
{
RootNode.Nodes.Add(GroupNode);
Console.WriteLine("GroupNode data: " + GroupNode);
}
return;
}
// Single data elements are handled here
bool addnode = true;
foreach (TreeNode snode in RootNode.Nodes)
{
if (snode.Text == groupstr) // If the group already exists in root set..put it in the existing node
{
snode.Nodes.Add(groupstr + elementstr + " , " + GetDescription(group, element) + " : " + GetInfo(value));
Console.WriteLine("sNode in foreach: " + snode);
addnode = false;
break;
}
}
if (addnode == true)
{
TreeNode snode = new TreeNode(groupstr);
snode.Nodes.Add(groupstr + elementstr + " , " + GetDescription(group, element) + " : " + GetInfo(value));
Console.WriteLine("sNode in true: " + snode);
RootNode.Nodes.Add(snode);
Console.WriteLine("RootNode Node in true: " + snode);
}
}
string GetInfo(object obj)
{
if (obj is System.String)
{
Console.WriteLine("OBJECT DATA: " + obj.ToString());
return obj.ToString();
}
if (obj is System.Single[])
{
Single[] arr = (Single[])obj;
string str = "";
foreach (Single value in arr)
{
str += value.ToString() + ",";
}
return str;
}
return obj.ToString();
}
string GetDescription(int group,int element)
{
string str = DCMLIB.TagDescription((uint)(group << 16 | element));
Console.WriteLine("str in GetDescription: " + str);
if (str == "Undefined")
return "Needs Private Data Definition - see help.";
else
return str;
}
string TagStr(int group, int element)
{
return group.ToString("X4") + element.ToString("X4");
}
void AddSubNode(Hashtable hash,string groupname,ref TreeNode sNode)
{
foreach (DictionaryEntry de in hash)
{
int key = (int)de.Key;
Console.WriteLine("KEY: "+key);
int group = ((key >> 16) & 0xffff);
Console.WriteLine("group " + group);
int element = (key & 0xffff);
Console.WriteLine("element: " + element);
string groupstr = group.ToString("X4");
Console.WriteLine("groupstr " + groupstr);
string elementstr = element.ToString("X4");
Console.WriteLine("ElementStr " + elementstr);
object value = de.Value;
Console.WriteLine("VALUE: " + value);
if (de.Value.GetType().ToString() == "System.Collections.ArrayList")
{
if (key == 0x7FE00010)//(groupstr.ToLower() + elementstr.ToLower()) == "7fe00010")
{
return;
}
ArrayList array = (ArrayList)de.Value;
for (int i = 0; i < array.Count; i++)
{
TreeNode tNode = new TreeNode(key.ToString());
Hashtable table = (Hashtable)array[i];
AddSubNode(table, groupname, ref tNode);
sNode.Nodes.Add(tNode);
Console.WriteLine("sNode details " + sNode);
}
}
else
sNode.Nodes.Add(groupstr + elementstr + " , " + GetDescription(group, element) + " : " + GetInfo(value) );
}
}
/// <summary>
/// Gets bitmap details
/// </summary>
/// <returns></returns>
public Bitmap[] GetImgs()
{
Bitmap[] bitmaps = null;
int Width=0, Height=0, bitStored=0,Frames = 0;
try
{
Width = (int)m_hash[0x00280011]; if (Width == 0) return null;
Height = (int)m_hash[0x00280010]; if (Height == 0) return null;
bitStored = (int)m_hash[0x00280101]; if (bitStored == 0) return null;
object o = m_hash[0x00280008];
if (o != null) //frames tag check
Frames = Convert.ToInt32(o.ToString());
}
catch
{
return null;
}
// initial implementations of CDML could have frames = 0 or 1 for a single image
// multi-frame storage uses frames correctly
if ((Frames == 0) || (Frames == 1))
{
if (m_hash.Contains(0x7FE00010))
{
byte[] imgbyte = ReadByte((byte[])m_hash[0x7FE00010], bitStored);
bitmaps = new Bitmap[1];
bitmaps[0] = GraphicsLib.BitmapUtility.CopyMonochromeBytesTo8bppIndexedBitmap(Width, Height, imgbyte);
return bitmaps;
}
return null;
}
else
{
if (m_hash.Contains(0x7FE00010))
{
bitmaps = new Bitmap[Frames];
ArrayList arrayImg = (ArrayList)m_hash[0x7FE00010];
for (int i = 0; i < arrayImg.Count; i++)
{
if (bitStored == 24)
{
byte[] imgbyte = (byte[])arrayImg[i];
Bitmap bitmap = new Bitmap(Width, Height);
GraphicsLib.BitmapUtility.Copy24bppBitmapToMonochromeBytes(bitmap,ref imgbyte);
bitmaps[i] = bitmap;
}
else
{
byte[] imgbyte = ReadByte((byte[])arrayImg[i], bitStored);
bitmaps[i] = GraphicsLib.BitmapUtility.CopyMonochromeBytesTo8bppIndexedBitmap(Width, Height, imgbyte);
bitmaps[i].RotateFlip(RotateFlipType.Rotate270FlipY);
}
}
return bitmaps;
}
return null;
}
}
//Converting value to hexadecimal
/// <summary>
/// convert number to hex string of given length
/// </summary>
/// <param name="h"></param>
/// <param name="l"></param>
/// <returns></returns>
//private string hex(int h, int l)
//{
// return h.ToString("X");
//}
private byte[] ReadByte(byte[] pixel,int bits)
{
byte b1 = 0, b2 = 0, s = 0;
byte[] singlePixel = new byte[pixel.Length];
if (bits == 8)
{
return pixel;
}
if (bits <= 16)
{
int x = 0;
for (int i = 0; i < pixel.Length; i += 2)
{
b1 = pixel[i];
b2 = pixel[i + 1];
short val = (short)(b1 + (b2 * 256));
s = (byte)((val - short.MinValue) * byte.MaxValue / (short.MaxValue - short.MinValue));
singlePixel[x] = s;
x++;
}
}
return singlePixel;
}
}
}