一般医学用的DICOM文件一般都是在标签 7FE00010和60003000
使用方法
ImageDcm _Property_Dcm = new ImageDcm(); string _Address = “e:\1.dcm”; _Property_Dcm.File_Load(System.IO.File.ReadAllBytes( _Bytes));
Image _Property_DrawImage = m_Property_Dcm.ElementValue_Image("7FE00010"); Image _Property_60003000 = m_Property_Dcm.ElementValue_Image("60003000");
下面是代码。
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.IO;
namespace Zgke.MyImage.ImageFile
{
///
/// DCM 文件转换类
/// [email protected]
/// qq:116149
///
public class ImageDcm
{
private Dictionary m_ParamentValue = new Dictionary();
public ImageDcm()
{
}
public void File_Load(byte[] p_FileBytes)
{
if (p_FileBytes.Length < 132) throw new Exception("文件错误!");
if (Encoding.ASCII.GetString(p_FileBytes, 128, 4) != "DICM") throw new Exception("文件DICOM错误!");
int _ReaderIndex = 132;
while (_ReaderIndex < p_FileBytes.Length)
{
string _ElementID = p_FileBytes[_ReaderIndex + 1].ToString("X02") + p_FileBytes[_ReaderIndex].ToString("X02") + p_FileBytes[_ReaderIndex + 3].ToString("X02") + p_FileBytes[_ReaderIndex + 2].ToString("X02");
_ReaderIndex += 4;
string _ElementVR = Encoding.ASCII.GetString(p_FileBytes, _ReaderIndex, 2);
_ReaderIndex += 2;
//if (_ElementID == "20500020")
//{
// int a = 0;
//}
object _Value = File_ElementVR(_ElementID, _ElementVR, p_FileBytes, ref _ReaderIndex);
m_ParamentValue.Add(_ElementID, _Value);
}
}
private object File_ElementVR(string p_ElementID, string p_ElementVR, byte[] p_FileBytes, ref int p_ReaderIndex)
{
object _Value = null;
int _Size = 0;
switch (p_ElementVR)
{
case "OB":
case "OW":
_Size = BitConverter.ToInt32(p_FileBytes, p_ReaderIndex + 2);
p_ReaderIndex += 6;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
case "SL":
_Size = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
case "UL":
case "AT":
_Size = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
case "US":
_Size = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
case "SS":
_Size = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
case "FL":
_Size = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
case "FD":
_Size = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
case "UI":
case "SH":
case "CS":
case "DA":
case "TM":
case "LO":
case "ST":
case "PN":
case "AS":
case "AE":
case "DS":
case "IS":
case "LT":
case "DT":
_Size = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
if (_Size != 0)
{
_Value = Encoding.ASCII.GetString(p_FileBytes, p_ReaderIndex, _Size);
p_ReaderIndex += _Size;
}
else
{
_Value = null;
}
break;
case "SQ":
#region SQ
if (BitConverter.ToString(p_FileBytes, p_ReaderIndex, 6) != "00-00-FF-FF-FF-FF") throw new Exception(p_ElementID + " Error 【" + p_ReaderIndex.ToString() + "】");
p_ReaderIndex += 6;
List _ReturnList = new List< object>();
while (true)
{
Dictionary _Return = new Dictionary();
if (BitConverter.ToString(p_FileBytes, p_ReaderIndex, 2) != "FE-FF") throw new Exception(p_ElementID + " Error 【" + p_ReaderIndex.ToString() + "】");
string _ElementIDSub = BitConverter.ToString(p_FileBytes, p_ReaderIndex, 4);
p_ReaderIndex += 4;
switch (BitConverter.ToString(p_FileBytes, p_ReaderIndex, 4))
{
case "FF-FF-FF-FF":
p_ReaderIndex += 4;
while (true)
{
if (BitConverter.ToString(p_FileBytes, p_ReaderIndex, 8) == "FE-FF-0D-E0-00-00-00-00")
{
p_ReaderIndex += 8;
break;
}
string _ElementID = p_FileBytes[p_ReaderIndex + 1].ToString("X02") + p_FileBytes[p_ReaderIndex].ToString("X02") + p_FileBytes[p_ReaderIndex + 3].ToString("X02") + p_FileBytes[p_ReaderIndex + 2].ToString("X02");
p_ReaderIndex += 4;
string _ElementVR = Encoding.ASCII.GetString(p_FileBytes, p_ReaderIndex, 2);
p_ReaderIndex += 2;
object _ValueSub = File_ElementVR(_ElementID, _ElementVR, p_FileBytes, ref p_ReaderIndex);
_Return.Add(_ElementID, _ValueSub);
}
break;
case "00-00-00-00":
p_ReaderIndex += 4;
break;
}
_ReturnList.Add(_Return);
if (BitConverter.ToString(p_FileBytes, p_ReaderIndex, 8) == "FE-FF-DD-E0-00-00-00-00")
{
p_ReaderIndex += 8;
break;
}
if (_ElementIDSub == "FE-FF-DD-E0") break;
}
_Value = _ReturnList;
#endregion
break;
default:
_Value = File_ElementID(p_ElementID, p_FileBytes, ref p_ReaderIndex);
break;
}
return _Value;
}
private object File_ElementID(string p_ElementID, byte[] p_FileBytes, ref int p_ReaderIndex)
{
object _Value = null;
int _Size = 0;
if (p_ElementID.Substring(4, 4) == "0000")
{
_Size = BitConverter.ToInt32(p_FileBytes, p_ReaderIndex - 2);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
}
else
{
switch (p_ElementID)
{
case "7FE00010":
_Size = BitConverter.ToInt32(p_FileBytes, p_ReaderIndex - 2);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
case "00280010":
case "00280011":
case "00280100":
case "00280002":
_Size = BitConverter.ToInt32(p_FileBytes, p_ReaderIndex - 2);
p_ReaderIndex += 2;
_Value = File_DataReader(p_FileBytes, ref p_ReaderIndex, _Size);
break;
default:
_Size = BitConverter.ToInt32(p_FileBytes, p_ReaderIndex - 2);
p_ReaderIndex += 2;
if (_Size != 0)
{
_Value = Encoding.ASCII.GetString(p_FileBytes, p_ReaderIndex, _Size);
p_ReaderIndex += _Size;
}
else
{
_Value = null;
}
break;
}
}
return _Value;
}
private object File_DataReader(byte[] p_FileBytes, ref int p_ReaderIndex, int p_ReaderSize)
{
if (p_ReaderSize == 0) return null;
int _Count = 0;
switch (typeof(T).Name)
{
case "Byte[]":
byte[] _Bytes =new byte[p_ReaderSize];
Array.Copy(p_FileBytes, p_ReaderIndex, _Bytes, 0, _Bytes.Length);
p_ReaderIndex += p_ReaderSize;
return _Bytes;
case "Double":
if (p_ReaderSize % 8 != 0) throw new Exception("DataReader Size Error at【" + p_ReaderIndex.ToString() + "】");
_Count = p_ReaderSize / 8;
if (_Count == 1)
{
double _Double = BitConverter.ToDouble(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 8;
return _Double;
}
else
{
double[] _Double = new double[_Count];
for (int i = 0; i != _Count; i++)
{
_Double[i] = BitConverter.ToDouble(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 8;
}
return _Double;
}
case "Single":
if (p_ReaderSize % 4 != 0) throw new Exception("DataReader Size Error at【" + p_ReaderIndex.ToString() + "】");
_Count = p_ReaderSize / 4;
if (_Count == 1)
{
float _Float = BitConverter.ToSingle(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 4;
return _Float;
}
else
{
float[] _Float = new float[_Count];
for (int i = 0; i != _Count; i++)
{
_Float[i] = BitConverter.ToSingle(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 4;
}
return _Float;
}
case "Int32":
if (p_ReaderSize % 4 != 0) throw new Exception("DataReader Size Error at【" + p_ReaderIndex.ToString() + "】");
_Count = p_ReaderSize / 4;
if (_Count == 1)
{
int _Int = BitConverter.ToInt32(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 4;
return _Int;
}
else
{
int[] _Int = new int[_Count];
for (int i = 0; i != _Count; i++)
{
_Int[i] = BitConverter.ToInt32(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 4;
}
return _Int;
}
case "UInt32":
if (p_ReaderSize % 4 != 0) throw new Exception("DataReader Size Error at【" + p_ReaderIndex.ToString() + "】");
_Count = p_ReaderSize / 4;
if (_Count == 1)
{
uint _Unit32 = BitConverter.ToUInt32(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 4;
return _Unit32;
}
else
{
uint[] _Uint32 = new uint[_Count];
for (int i = 0; i != _Count; i++)
{
_Uint32[i] = BitConverter.ToUInt32(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 4;
}
return _Uint32;
}
case "Int16":
if (p_ReaderSize % 2 != 0) throw new Exception("DataReader Size Error at【" + p_ReaderIndex.ToString() + "】");
_Count = p_ReaderSize / 2;
if (_Count == 1)
{
short _Short = BitConverter.ToInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
return _Short;
}
else
{
short[] _Short = new short[_Count];
for (int i = 0; i != _Count; i++)
{
_Short[i] = BitConverter.ToInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
}
return _Short;
}
case "UInt16":
if (p_ReaderSize % 2 != 0) throw new Exception("DataReader Size Error at【" + p_ReaderIndex.ToString() + "】");
_Count = p_ReaderSize / 2;
if (_Count == 1)
{
ushort _Unit16 = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
return _Unit16;
}
else
{
ushort[] _Unit16 = new ushort[_Count];
for (int i = 0; i != _Count; i++)
{
_Unit16[i] = BitConverter.ToUInt16(p_FileBytes, p_ReaderIndex);
p_ReaderIndex += 2;
}
return _Unit16;
}
default:
throw new Exception(typeof(T).Name + " DataReader Type at【" + p_ReaderIndex.ToString() + "】");
}
}
public double ElementValue_Double(string p_ElementID)
{
if (!m_ParamentValue.ContainsKey(p_ElementID) || m_ParamentValue[p_ElementID] == null) return 0;
double _ReturnValue = 0;
if (double.TryParse(m_ParamentValue[p_ElementID].ToString(), out _ReturnValue)) return _ReturnValue;
return 0;
}
public short ElementValue_Int16(string p_ElementID)
{
if (!m_ParamentValue.ContainsKey(p_ElementID) || m_ParamentValue[p_ElementID] == null ) return 0;
short _ReturnValue = 0;
if (short.TryParse(m_ParamentValue[p_ElementID].ToString(), out _ReturnValue)) return _ReturnValue;
return 0;
}
public int ElementValue_Int32(string p_ElementID)
{
if (!m_ParamentValue.ContainsKey(p_ElementID) || m_ParamentValue[p_ElementID]==null ) return 0;
int _ReturnValue = 0;
if (int.TryParse(m_ParamentValue[p_ElementID].ToString(), out _ReturnValue)) return _ReturnValue;
return 0;
}
public string ElementValue_String(string p_ElementID)
{
if (!m_ParamentValue.ContainsKey(p_ElementID) || m_ParamentValue[p_ElementID]==null) return "";
return m_ParamentValue[p_ElementID].ToString();
}
public void ElementValue_Save(string p_ElementID, object p_Value)
{
if (!m_ParamentValue.ContainsKey(p_ElementID)) m_ParamentValue.Add(p_ElementID, null);
m_ParamentValue[p_ElementID] = p_Value;
}
public Bitmap ElementValue_Image(string p_ElementID)
{
if (!m_ParamentValue.ContainsKey(p_ElementID) || m_ParamentValue[p_ElementID] == null || m_ParamentValue[p_ElementID].GetType()!=typeof(byte[]) ) return null;
string _ElementGroup = p_ElementID.Substring(0, 4);
if (p_ElementID == "7FE00010") _ElementGroup = "0028";
string _Type = ElementValue_String(_ElementGroup + "0004").Trim();
int _Width = ElementValue_Int32(_ElementGroup + "0011");
int _Height = ElementValue_Int32(_ElementGroup + "0010");
int _Pix = ElementValue_Int32(_ElementGroup + "0100");
int _Samples = ElementValue_Int32(_ElementGroup + "0002");
if (_Samples != 0) _Pix *= _Samples;
if (_Width == 0 || _Height == 0 || _Pix == 0) return null;
byte[] _ImageBytes = (byte[])m_ParamentValue[p_ElementID];
Bitmap _NewBitmap = null;
BitmapData _NewBitmapData = null;
ColorPalette _Palette = null;
byte[] _ImageBytesWrite = null;
switch (_Pix)
{
case 24:
#region 原始24位 彩色
_NewBitmap = new Bitmap(_Width, _Height, PixelFormat.Format24bppRgb);
_NewBitmapData = _NewBitmap.LockBits(new Rectangle(0, 0, _NewBitmap.Width, _NewBitmap.Height), ImageLockMode.ReadWrite, _NewBitmap.PixelFormat);
Marshal.Copy(_ImageBytes, 0, _NewBitmapData.Scan0, _ImageBytes.Length);
_NewBitmap.UnlockBits(_NewBitmapData);
#endregion
break;
case 16:
#region 原始16位 灰度
_NewBitmap = new Bitmap(_Width, _Height, PixelFormat.Format8bppIndexed);
_NewBitmapData = _NewBitmap.LockBits(new Rectangle(0, 0, _NewBitmap.Width, _NewBitmap.Height), ImageLockMode.ReadWrite, _NewBitmap.PixelFormat);
_Palette = _NewBitmap.Palette;
switch (_Type)
{
case "MONOCHROME2":
for (int i = 0; i != _Palette.Entries.Length; i++)
{
_Palette.Entries[i] = Color.FromArgb(255, i, i, i);
}
break;
case "MONOCHROME1":
for (int i = 0; i != _Palette.Entries.Length; i++)
{
int _PaletteValue = 255 - i;
_Palette.Entries[i] = Color.FromArgb(255, _PaletteValue, _PaletteValue, _PaletteValue);
}
break;
default: throw new Exception("DrawImage Not (MONOCHROME2 OR MONOCHROME1)");
}
_NewBitmap.Palette = _Palette;
_ImageBytesWrite = new byte[_NewBitmapData.Stride * _NewBitmap.Height];
double _WindowCenter = 0;
if (!double.TryParse(ElementValue_String(_ElementGroup + "1050").Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries)[0], out _WindowCenter)) return null;
double _WindowWidth = 0;
if (!double.TryParse(ElementValue_String(_ElementGroup + "1051").Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries)[0], out _WindowWidth)) return null;
short _RescaleIntercept = ElementValue_Int16(_ElementGroup + "1052");
double _WindowMin = _WindowCenter - _WindowWidth / 2;
double _WindowMax = _WindowCenter + _WindowWidth / 2;
for (int y = 0; y != _NewBitmap.Height; y++)
{
int _IndexWrite = _NewBitmapData.Stride * y;
int _IndexReader = _Width * 2 * y;
for (int x = 0; x != _NewBitmap.Width; x++)
{
int _ReaderValue = BitConverter.ToInt16(_ImageBytes, _IndexReader) + _RescaleIntercept;
if (_ReaderValue < _WindowMin)
{
_ImageBytesWrite[_IndexWrite] = 0;
}
else if (_ReaderValue > _WindowMax)
{
_ImageBytesWrite[_IndexWrite] = 255;
}
else
{
double _ImageValue = (_ReaderValue - _WindowMin) / _WindowWidth * 255;
_ImageBytesWrite[_IndexWrite] = (byte)_ImageValue;
}
_IndexWrite++;
_IndexReader += 2;
}
}
Marshal.Copy(_ImageBytesWrite, 0, _NewBitmapData.Scan0, _ImageBytesWrite.Length);
_NewBitmap.UnlockBits(_NewBitmapData);
#endregion
break;
case 1:
#region 原始1位
_NewBitmap = new Bitmap(_Width, _Height, PixelFormat.Format1bppIndexed);
_NewBitmapData = _NewBitmap.LockBits(new Rectangle(0, 0, _NewBitmap.Width, _NewBitmap.Height), ImageLockMode.ReadWrite, _NewBitmap.PixelFormat);
_Palette = _NewBitmap.Palette;
_Palette.Entries[0] = Color.FromArgb(0, 0, 0, 0);
_Palette.Entries[1] = Color.FromArgb(255, 255, 255, 255);
_NewBitmap.Palette = _Palette;
_ImageBytesWrite = new byte[_NewBitmapData.Stride * _NewBitmap.Height];
int _Sleep = _Width / 8;
for (int y = 0; y != _NewBitmap.Height; y++)
{
int _IndexRow = _NewBitmapData.Stride * y;
for (int x = 0; x != _Sleep; x++)
{
_ImageBytesWrite[_IndexRow] = Zgke.MyConvert.OperateBytes.ReverseByte(_ImageBytes[_IndexRow]);
_IndexRow++;
}
}
Marshal.Copy(_ImageBytesWrite, 0, _NewBitmapData.Scan0, _ImageBytesWrite.Length);
_NewBitmap.UnlockBits(_NewBitmapData);
#endregion
break;
default: throw new Exception("DrawImage Not 【" + _Pix.ToString() + "】");
}
return _NewBitmap;
}
}
}