diff --git a/.gitignore b/.gitignore index ab765df..46c92f0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,8 @@ packages/ AutoUpdate/ ConsoleApp/ -DicomTool/ IDCardRead/ PublishUpgrade/ -Scale/ PEIS/PEIS.zip # ---> VisualStudio ## Ignore Visual Studio temporary files, build results, and diff --git a/DicomTool/App.config b/DicomTool/App.config new file mode 100644 index 0000000..6d44113 --- /dev/null +++ b/DicomTool/App.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DicomTool/DicomTool.csproj b/DicomTool/DicomTool.csproj new file mode 100644 index 0000000..23c5e8f --- /dev/null +++ b/DicomTool/DicomTool.csproj @@ -0,0 +1,114 @@ + + + + + Debug + AnyCPU + {7AFE3A9A-02C9-4D8C-A03B-1BFFECB153A3} + Exe + DicomTool + DicomTool + v4.5.2 + 512 + true + true + + + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + x64 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + + ..\packages\fo-dicom.Desktop.3.0.0\lib\net452\Dicom.Core.dll + + + ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + + + False + Microsoft .NET Framework 4.5.2 %28x86 和 x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + \ No newline at end of file diff --git a/DicomTool/FtpHelper.cs b/DicomTool/FtpHelper.cs new file mode 100644 index 0000000..7c89e6b --- /dev/null +++ b/DicomTool/FtpHelper.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System; +using System.IO; +using System.Net; +using DicomTool.Model; + +namespace DicomTool +{ + public static class FtpHelper + { + + public static void DownloadFtpFile(List ftpUriList, string username, string password, string localFilePath) + { + // 确保本地文件路径是目录 + if (!Directory.Exists(localFilePath)) + { + Directory.CreateDirectory(localFilePath); + } + + foreach (var reportEcg in ftpUriList) + { + // 创建 FtpWebRequest 对象 + var request = (FtpWebRequest)WebRequest.Create(reportEcg.ReportUrl); + request.Method = WebRequestMethods.Ftp.DownloadFile; + request.Credentials = new NetworkCredential(username, password); + + try + { + // 获取响应并读取数据 + var response = (FtpWebResponse)request.GetResponse(); + var responseStream = response.GetResponseStream(); + + // 获取文件名 + // string fileName = Path.GetFileName(new Uri(reportEcg.ReportUrl).LocalPath); + var fileName = reportEcg.ID + ".jpg"; + Console.WriteLine("【下载】"+ reportEcg.ID + ".jpg"); + var localFileFullPath = Path.Combine(localFilePath, fileName); + + // 将 FTP 文件内容写入本地文件 + using (FileStream fileStream = new FileStream(localFileFullPath, FileMode.Create, FileAccess.Write)) + { + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) != 0) + { + fileStream.Write(buffer, 0, bytesRead); + } + } + + responseStream.Close(); + response.Close(); + } + catch (WebException ex) + { + // 处理异常,例如打印错误信息 + Console.WriteLine("Download failed for " + reportEcg + ": " + ex.Message); + } + } + } + } +} diff --git a/DicomTool/Helper.cs b/DicomTool/Helper.cs new file mode 100644 index 0000000..e1c26f0 --- /dev/null +++ b/DicomTool/Helper.cs @@ -0,0 +1,561 @@ +// using System; +// using System.Collections.Generic; +// using System.Data.SqlClient; +// using System.Diagnostics; +// using System.IO; +// using System.Net; +// using System.Timers; +// using Dicom; +// using Dicom.Imaging; +// using DicomTool.Entity; +// using DicomTool.Utils; +// +// namespace DicomTool +// { +// internal class Program +// { +// private static void Main(string[] args) +// { +// // InsertPacsImgToPeis(); +// // Console.ReadKey(); +// // return; +// // +// // var basePath = "C://PACS/DICOM/"; +// // var pacsReprot = DataModel.GetPacsReport(); +// // var fileNameList = new List() +// // { +// // "10011-164-1.DCM" +// // }; +// // GetLocalFile(basePath, fileNameList); +// // return; +// +// Console.WriteLine($"【启动】{DateTime.Now:yyyy-MM-dd HH:mm}"); +// /* +// * TEST +// // GetPacsReport(); +// // InsertPacsImgToPeis(); +// // Console.ReadKey(); +// // return; +// */ +// +// GetPacsReport(); +// // 创建一个 Timer 实例 +// var timer = new Timer(); +// // 设置间隔时间为10分钟(以毫秒为单位) +// var intervalInMinutes = 30; +// timer.Interval = intervalInMinutes * 60 * 1000; +// // 设置为 true,使得 Timer 每隔设定的间隔时间自动触发一次 Elapsed 事件 +// timer.AutoReset = true; +// // 绑定 Elapsed 事件处理程序 +// timer.Elapsed += Timer_Elapsed; +// // 启动 Timer +// timer.Start(); +// // 阻止控制台程序退出 +// Console.ReadKey(); +// // 停止 Timer +// timer.Stop(); +// +// +// Console.WriteLine($"SUCCESS"); +// Console.ReadKey(); +// } +// +// #region Pacs TEST +// +// /// +// /// 定时执行任务 +// /// +// /// +// /// +// private static void Timer_Elapsed(object sender, ElapsedEventArgs e) +// { +// GetPacsReport(); +// } +// +// private static void GetPacsReport() +// { +// Console.WriteLine($"【查询】{DateTime.Now:yyyy-MM-dd HH:mm}"); +// var basePath = "C://PACS/DICOM/"; +// var pacsReprot = DataModel.GetPacsReport(); +// var fileNameList = new List(); +// // 获取PACS数据 +// foreach (var info in pacsReprot) +// { +// InsertInfo(info); +// // 得到DCM共享文件地址 +// int i = 1; +// var dcmPaths = info.ImageFile.Split(';'); +// foreach (var dcmPath in dcmPaths) +// { +// if (string.IsNullOrEmpty(dcmPath)) +// { +// continue; +// } +// //获取远程共享文件 +// var client = new WebClient(); +// var userName = "XBDLISUser"; +// var password = "BlueFlag.Lis!@#"; +// // 配置授权账户密码 +// var credentials = new NetworkCredential(userName, password); +// client.Credentials = credentials; +// //下载远程文件 +// var buffer = client.DownloadData(dcmPath); +// +// // 保存本地 +// Bytes2File(buffer, basePath, $"{info.PatientCode}-{info.ExamFeeitem_Code}-{i}.DCM"); +// i++; +// fileNameList.Add($"{info.PatientCode}-{info.ExamFeeitem_Code}-{i}.DCM"); +// Console.WriteLine($"下载:{info.PatientCode}-{info.ExamFeeitem_Code}-{i}.DCM"); +// //continue; +// // // 读取DCM by byte[] +// // using (var streamDcm = new MemoryStream()) +// // { +// // streamDcm.Write(buffer, 0, buffer.Length); +// // //fo-dicom类库 读取DCM +// // var file = DicomFile.Open(streamDcm); +// // if (file?.Dataset == null) +// // { +// // continue;//BUG +// // } +// // var image = new DicomImage(file.Dataset); +// // //image.NumberOfFrames 如果有多帧图片需要将每帧都转成jpeg +// // //DCM转Bitmap +// // var bitmap = image.RenderImage().AsBitmap(); +// // using (var streamImg = new MemoryStream()) +// // { +// // //Bitmap To byte[] +// // bitmap.Save(streamImg, System.Drawing.Imaging.ImageFormat.Jpeg); +// // var imgBytes = streamImg.ToArray(); +// // InsertData(imgBytes, Convert.ToInt64(info.PatientCode), info.ExamFeeitem_Code); +// // // //byte[] To Base64String +// // // var img = Convert.ToBase64String(imgBytes); +// // // // 保存数据到PEIS DB +// // // var saveItem = info; +// // // saveItem.ImageFile = img; +// // // var i = DAOHelp.Save(saveItem); +// // } +// // //bitmap.Save("imageName", System.Drawing.Imaging.ImageFormat.Jpeg); +// // } +// } +// } +// +// if (pacsReprot.Count > 0) +// // 保存到本地后上传到服务器 +// GetLocalFile(basePath, fileNameList); +// +// } +// +// /// +// /// 1、将本地文件PACS影像图片发送到服务器 +// /// +// public static void GetLocalFile(string folderPath, List fileNameList) +// { +// //var folderPath = "C:\\PACS\\DicomFile"; // 替换为实际的文件夹路径 +// // 获取文件夹下所有文件的路径 +// var files = Directory.GetFiles(folderPath); +// var i = 1; +// // 遍历文件路径并输出 +// foreach (var filePath in files) +// { +// +// var fileName = Path.GetFileName(filePath); +// if (!fileNameList.Contains(fileName)) +// { +// continue; +// } +// var eid = Convert.ToInt64(fileName.Split('-')[0]); +// var reportNo = fileName.Split('-')[1]; +// var image = new DicomImage(filePath); +// //image.NumberOfFrames 如果有多帧图片需要将每帧都转成jpeg +// //DCM转Bitmap +// var bitmap = image.RenderImage().AsBitmap(); +// using (var streamImg = new MemoryStream()) +// { +// //Bitmap To byte[] +// bitmap.Save(streamImg, System.Drawing.Imaging.ImageFormat.Jpeg); +// var imgBytes = streamImg.ToArray(); +// InsertData(imgBytes, eid, reportNo); +// // //byte[] To Base64String +// // var img = Convert.ToBase64String(imgBytes); +// // // 保存数据到PEIS DB +// // var j = DAOHelp.ExecuteSql($@"UPDATE Report_Pacs SET ImageFile='{img}' WHERE ID={i}"); +// } +// i++; +// } +// } +// +// /// +// /// 2、将图片插入PEIS服务器 +// /// +// /// +// public static void InsertData(byte[] img, Int64 eid, string ReportNo) +// { +// +// Console.WriteLine($"【上传】{eid}-{ReportNo}-{DateTime.Now:yyyy-MM-dd HH:mm}"); +// // 建立数据库连接 +// //string connectionString = "Data Source=192.168.12.188;Initial Catalog=peisdb;User ID=sa;Password=000626; "; +// //盈江妇幼 +// var connectionString = "Data Source=172.172.100.12;Initial Catalog=peisdb;User ID=sa;Password=xbdLis!@#77911; "; +// using (var connection = new SqlConnection(connectionString)) +// { +// connection.Open(); +// // 创建插入记录的 SQL 查询 +// var insertQuery = "INSERT INTO Report_Pacs (Image,EID,ReportNo,InTime) VALUES (@ImageData,@EID,@ReportNo,@InTime)"; +// // 创建命令对象 +// using (var command = new SqlCommand(insertQuery, connection)) +// { +// // 设置参数值 +// command.Parameters.AddWithValue("@ImageData", img); +// command.Parameters.AddWithValue("@EID", eid); +// command.Parameters.AddWithValue("@ReportNo", ReportNo); +// command.Parameters.AddWithValue("@InTime", DateTime.Now); +// // 执行插入操作 +// command.ExecuteNonQuery(); +// } +// connection.Close(); +// } +// } +// public static void InsertReportImg(byte[] img, Int64 eid, string ReportNo) +// { +// +// Console.WriteLine($"【上传】{eid}-{ReportNo}-{DateTime.Now:yyyy-MM-dd HH:mm}"); +// // 建立数据库连接 +// //string connectionString = "Data Source=192.168.12.188;Initial Catalog=peisdb;User ID=sa;Password=000626; "; +// //盈江妇幼 +// var connectionString = "Data Source=172.172.100.12;Initial Catalog=peisdb;User ID=sa;Password=xbdLis!@#77911; "; +// using (var connection = new SqlConnection(connectionString)) +// { +// connection.Open(); +// // 创建插入记录的 SQL 查询 +// var insertQuery = "UPDATE Report SET ReportImage = @ImageData WHERE EID=@EID AND ReportNo=@ReportNo"; +// // 创建命令对象 +// using (var command = new SqlCommand(insertQuery, connection)) +// { +// // 设置参数值 +// command.Parameters.AddWithValue("@ImageData", img); +// command.Parameters.AddWithValue("@EID", eid); +// command.Parameters.AddWithValue("@ReportNo", ReportNo); +// // 执行插入操作 +// command.ExecuteNonQuery(); +// } +// connection.Close(); +// } +// } +// +// public static void InsertInfo(ReportPacs info) +// { +// var sql = $@"INSERT INTO [Report] +// ( [EID], [ReportNo], [Class], [Title], [Examer], [Reporter], [ReportTime], [Description], [Summary] ,[Positive], [InTime] ) +// VALUES ({info.PatientCode},'{info.ExamFeeitem_Code}', '{info.TransfTertarget}','{info.ImageTitle}' , '{info.InputDoctor}', '{info.ExamDoctor}','{info.ExamDatetime}', '{info.ExamDesc}', +// '{info.ExamSummary}' ,'{info.ExamPositive}','{DateTime.Now}');"; +// DAOHelp.ExecuteSql(sql); +// } +// +// public void GetPacsData() +// { +// // var data = DAOHelp.GetDataBySQL("select * from PacsTest").FirstOrDefault(); +// // +// // var rtfData1 = data.Description; // 从文件或网络中读取字节数据 +// // +// // if (rtfData1 != null && rtfData1.Length > 0) +// // { +// // using (var stream = new MemoryStream(rtfData1)) +// // using (var reader = new StreamReader(stream)) +// // { +// // string rtfText = reader.ReadToEnd(); +// // Console.WriteLine(rtfText); +// // } +// // } +// // var rtfData2 = data.Diagnose; +// // +// // if (rtfData2 != null && rtfData2.Length > 0) +// // { +// // using (var stream = new MemoryStream(rtfData2)) +// // using (var reader = new StreamReader(stream)) +// // { +// // string rtfText = reader.ReadToEnd(); +// // Console.WriteLine(rtfText); +// // } +// // } +// } +// +// public void GetPacs() +// { +// // var handler = new DicomHandler(filePath); +// // handler.readAndShow(); +// // if (handler.getImg()) +// //pictureBox1.Image = Image.FromFile(@"C:/Pacs/0.DCM"); +// +// // string downloadPath = @"C:\PACS\2.DCM"; +// // var handler = new DicomHandler(downloadPath); +// // handler.readAndShow(); +// // if (handler.getImg()) +// // pictureBox1.Image = handler.gdiImg; +// +// //DicomRead.Convert(@"C:\PACS\2.DCM", @"C:\PACS\2.jpg"); +// string strFileName = @"C:\PACS\2.DCM"; +// string strOutFileName = @"C:\PACS\2.jpg"; +// // var img = new DicomImage(strFileName); +// // Bitmap bitmap = new Bitmap(img.RenderImage()); +// // pictureBox1.Image = bitmap; +// //bitmap.Save(strOutFileName, ImageFormat.Jpeg); +// +// // string userName = "XBDLISUser"; +// // string password = "BlueFlag.Lis!@#"; +// // NetworkCredential credentials = new NetworkCredential(userName, password); +// // var path= @" +// // \\172.172.100.11\DICOMFILES$\Data_2023.05.24\B超\B超.1.3.12.2.1107.5.1.4.50455.20230524090327573.DCM; +// // \\172.172.100.11\DICOMFILES$\Data_2023.05.24\B超\B超.1.3.12.2.1107.5.1.4.50455.20230524090347743.DCM; +// // \\172.172.100.11\DICOMFILES$\Data_2023.05.24\B超\B超.1.3.12.2.1107.5.1.4.50455.20230524090449223.DCM; +// // \\172.172.100.11\DICOMFILES$\Data_2023.05.24\B超\B超.1.3.12.2.1107.5.1.4.50455.20230524090543067.DCM; +// // \\172.172.100.11\DICOMFILES$\Data_2023.05.24\B超\B超.1.3.12.2.1107.5.1.4.50455.20230524090739127.DCM; +// // \\172.172.100.11\DICOMFILES$\Data_2023.05.24\B超\B超.1.3.12.2.1107.5.1.4.50455.20230524090327573.DCM;"; +// // var list = path.Split(';').ToList(); +// // foreach (var item in list) +// // { +// // WebClient client = new WebClient(); +// // client.Credentials = credentials; +// // +// // // 下载文件 +// // client.DownloadFile(item.Trim(), @"C:\PACS\"+list.IndexOf(item)+".DCM"); +// // +// // } +// +// //string sourceFile = @"\\172.172.100.11\DICOMFILES$\Data_2023.05.24\B超\B超.1.3.12.2.1107.5.1.4.50455.20230524090327573.DCM"; +// // if (!File.Exists(sourceFile)) +// // { +// // MessageBox.Show("File not found " ); +// // return; +// // } +// +// // string downloadPath = @"C:\pacs.DCM"; +// // WebClient client = new WebClient(); +// // client.Credentials = credentials; +// // +// // // 下载文件 +// // client.DownloadFile(sourceFile, downloadPath); +// // +// // HttpWebRequest request = (HttpWebRequest)WebRequest.Create(sourceFile); +// // request.Credentials = credentials; +// // +// // // 获取响应流并读取文件内容 +// // using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) +// // { +// // using (Stream stream = response.GetResponseStream()) +// // { +// // StreamReader reader = new StreamReader(stream); +// // string content = reader.ReadToEnd(); +// // } +// // } +// // // WebClient client = new WebClient(); +// // +// // WebClient client = new WebClient(); +// // client.Credentials = new NetworkCredential(userName, password); +// // client.DownloadFile(sourceFile, downloadPath); +// //client.DownloadFile(sourceFile, downloadPath); +// +// // if (!File.Exists(filePath)) +// // { +// // MessageBox.Show("File not found: " + filePath); +// // return; +// // } +// // var handler = new DicomHandler(filePath); +// // handler.readAndShow(); +// // if (handler.getImg()) +// // pictureBox1.Image = handler.gdiImg; +// // FileStream stream = File.OpenRead(filePath); +// // byte[] data = new byte[stream.Length]; +// // stream.Read(data, 0, data.Length); +// // stream.Close(); +// } +// +// /// +// /// 将byte数组转换为文件并保存到指定地址 +// /// +// /// byte数组 +// /// 保存地址 +// public static void Bytes2File(byte[] buff, string savepath, string fileName) +// { +// try +// { +// +// //如果不存在就创建Enclosure文件夹  +// if (Directory.Exists(savepath) == false) +// { +// Directory.CreateDirectory(savepath); +// } +// +// if (System.IO.File.Exists(savepath + fileName)) +// { +// System.IO.File.Delete(savepath + fileName); +// } +// //创建Process命令 +// var cmd = new Process(); +// FileStream fs = new FileStream(savepath + fileName, FileMode.CreateNew); +// BinaryWriter bw = new BinaryWriter(fs); +// bw.Write(buff, 0, buff.Length); +// bw.Close(); +// fs.Close(); +// // //创建要运行的文件或者程序 +// // var startfile = new ProcessStartInfo +// // { +// // FileName = savepath + fileName,//文件完全路径 +// // WindowStyle = ProcessWindowStyle.Normal,//Windows窗口样式 +// // UseShellExecute = true//为true,则用默认的打开方式打开 +// // }; +// // cmd.StartInfo = startfile; +// // cmd.Start(); //打开文件 +// } +// catch (Exception e) +// { +// Console.WriteLine(fileName + "--" + e.Message); +// } +// +// } +// +// +// /* +// * +// // //icom 转 Jpeg +// // //fo-dicom类库 +// // var dcmFile = @"C:/Pacs/DX.DCM"; +// // string fullName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Files", dcmFile); +// +// //生成设置要改为X64位 +// //System.Reflection.Assembly.LoadFrom(Path.Combine(Application.StartupPath, "Dicom.Native.dll")); +// +// //file //= file.ChangeTransferSyntax(DicomTransferSyntax.ExplicitVRLittleEndian, new DicomJpegLsParams()); +// // string path = AppDomain.CurrentDomain.BaseDirectory; +// // Dicom.Imaging.Codec.TranscoderManager.LoadCodecs(path, "Dicom.Native*.dll"); +// // var image = new DicomImage(file.Dataset); +// // //image.NumberOfFrames 如果有多帧图片需要将每帧都转成jpeg +// // Bitmap bitmap = image.RenderImage().AsBitmap(); +// // string imageName = $"{DateTime.Now.ToString("yyyy-MM-ddHHmmss")}DX.jpeg"; +// //bitmap.Save(imageName); +// // 不行 +// // ImageConverter converter = new ImageConverter(); +// // var imgBytes= (byte[])converter.ConvertTo(bitmap, typeof(byte[])); +// +// // using (var stream = new MemoryStream()) +// // { +// // bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png); +// // var imgBytes =stream.ToArray(); +// // var img=Convert.ToBase64String(imgBytes); +// // var i=DAOHelp.Save(new Pacs( img)); +// // } +// //bitmap.Save(imageName, System.Drawing.Imaging.ImageFormat.Jpeg); +// // bitmap.Save(imageName, System.Drawing.Imaging.ImageFormat.Jpeg); +// */ +// #endregion Pacs TEST +// +// +// +// +// +// +// /// +// /// 手动导入PACS数据到PEIS +// /// +// public static void InsertPacsImgToPeis() +// { +// var path = "C://PACS//DICOM//Manual//"; +// var list = new List() +// { +// new ManualModel() +// { +// Eid = 10002, +// ReportNo = "22", +// imgFile = @"\\172.172.100.11\DICOMFILES$\Data_2023.08.08\DX\DX.1.2.840.887072.1.9.1.1.20230808093901.4.220240230221.DCM;" +// }, +// }; +// //下载 +// foreach (var item in list) +// { +// DownReportImg(path, item.imgFile, item.Eid, item.ReportNo); +// } +// +// //上传 +// UploadReportImg(path); +// } +// +// /// +// /// 下载PACS检查文件到本地 +// /// +// /// DCM文件 +// /// 体检号 +// /// 收费项目ID +// public static List DownReportImg(string basePath, string imgFile, long eid, string reportNo) +// { +// var fileNameList = new List(); +// // 得到DCM共享文件地址 +// int i = 1; +// var dcmPaths = imgFile.Split(';'); +// foreach (var dcmPath in dcmPaths) +// { +// if (string.IsNullOrEmpty(dcmPath)) +// { +// continue; +// } +// //获取远程共享文件 +// var client = new WebClient(); +// var userName = "XBDLISUser"; +// var password = "BlueFlag.Lis!@#"; +// // 配置授权账户密码 +// var credentials = new NetworkCredential(userName, password); +// client.Credentials = credentials; +// //下载远程文件 +// var buffer = client.DownloadData(dcmPath); +// +// // 保存本地 +// Bytes2File(buffer, basePath, $"{eid}-{reportNo}-{i}.DCM"); +// fileNameList.Add($"{eid}-{reportNo}-{i}.DCM"); +// Console.WriteLine($"下载:{eid}-{reportNo}-{i}.DCM"); +// i++; +// } +// return fileNameList; +// } +// +// +// /// +// /// 1、将本地文件PACS影像图片发送到服务器 +// /// +// public static void UploadReportImg(string folderPath, List fileNameList = null) +// { +// //var folderPath = "C:\\PACS\\DicomFile"; // 替换为实际的文件夹路径 +// // 获取文件夹下所有文件的路径 +// var files = Directory.GetFiles(folderPath); +// var i = 1; +// // 遍历文件路径并输出 +// foreach (var filePath in files) +// { +// +// var fileName = Path.GetFileName(filePath); +// // if (!fileNameList.Contains(fileName)) +// // { +// // continue; +// // } +// var eid = Convert.ToInt64(fileName.Split('-')[0]); +// var reportNo = fileName.Split('-')[1]; +// var image = new DicomImage(filePath); +// //image.NumberOfFrames 如果有多帧图片需要将每帧都转成jpeg +// //DCM转Bitmap +// var bitmap = image.RenderImage().AsBitmap(); +// using (var streamImg = new MemoryStream()) +// { +// //Bitmap To byte[] +// bitmap.Save(streamImg, System.Drawing.Imaging.ImageFormat.Jpeg); +// var imgBytes = streamImg.ToArray(); +// InsertData(imgBytes, eid, reportNo); +// // //byte[] To Base64String +// // var img = Convert.ToBase64String(imgBytes); +// // // 保存数据到PEIS DB +// // var j = DAOHelp.ExecuteSql($@"UPDATE Report_Pacs SET ImageFile='{img}' WHERE ID={i}"); +// } +// +// Console.WriteLine($"上传:{eid}-{reportNo}"); +// i++; +// } +// } +// +// } +// } \ No newline at end of file diff --git a/DicomTool/Model/ReportEcg.cs b/DicomTool/Model/ReportEcg.cs new file mode 100644 index 0000000..67e0dba --- /dev/null +++ b/DicomTool/Model/ReportEcg.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PEIS.Utils; + +namespace DicomTool.Model +{ + public class ReportEcg : ObjectData + { + public override String TableName { get => "Report_GSEXD"; } + + [KeyFlag(true)] + public Int64 ID { get; set; } + + public String ReportUrl { get; set; } + // [RefFlag(true)] + // public String n { get; set; } + } +} diff --git a/DicomTool/Model/ReportPacs.cs b/DicomTool/Model/ReportPacs.cs new file mode 100644 index 0000000..6a56f61 --- /dev/null +++ b/DicomTool/Model/ReportPacs.cs @@ -0,0 +1,21 @@ +using System; +using PEIS.Utils; + +namespace DicomTool +{ + public class ReportPacs : ObjectData + { + public override String TableName { get => "Report_Pacs"; } + + [KeyFlag(true)] + public Int64 ID { get; set; } + + public String PatientCode { get; set; } + public String ImageFile { get; set; } + public String ExamFeeitem_Code { get; set; } + public String AccessionNumber { get; set; } + + [RefFlag(true)] + public String SopInstanceUID { get; set; } + } +} \ No newline at end of file diff --git a/DicomTool/Program.cs b/DicomTool/Program.cs new file mode 100644 index 0000000..51d16fe --- /dev/null +++ b/DicomTool/Program.cs @@ -0,0 +1,378 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Net; +using System.Timers; +using Dicom.Imaging; +using DicomTool.Model; +using DicomTool.Utils; + +namespace DicomTool +{ + internal class Program + { + // 设置循环间隔时间为10分钟 + private const int intervalInMinutes = 60; + // PACS 共享文件访问 + private const string UserName = "XBDLISUser"; + private const string Password = "BlueFlag.Lis!@#"; + // DCM文件下载存放路径 + private static readonly string DcmPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DicomFiles/"); + private static readonly string EcgPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EcgFiles/"); + + // 188 + //private const string connectionString = "Data Source=192.168.12.188;Initial Catalog=peisdb;User ID=sa;Password=000626;"; + // 盈江妇幼 + // private const string ConnectionString = @"Data Source=172.172.100.12;Initial Catalog=peisdb;User ID=sa;Password=xbdLis!@#77911;"; + // 芒市妇幼 + // private const string ConnectionString = @"Data Source=192.168.11.5;Initial Catalog=peisdb;User ID=XBDLISUser;Password=BlueFlag.Lis!@#;"; + // 德宏中医 + private const string ConnectionString = @"Data Source=200.200.200.71;Initial Catalog=peisdb;User ID=sa;Password=wVJeC28@eY*&F#5NGL^eYC3m;"; + + /// + /// PACS报告中已选的图片 + /// + private const string InsertExamPacsImage = + @"INSERT INTO Exam_PacsImage (Image,EID,ReportNo,InTime) VALUES (@ImageData,@EID,@ReportNo,@InTime); + INSERT INTO Report_Pacs(Image, EID, ReportNo, InTime) VALUES(@ImageData, @EID, @ReportNo, @InTime);"; + + private static void Main(string[] args) + { + Console.WriteLine($"【启动】{DateTime.Now:yyyy-MM-dd HH:mm}"); + // 创建一个 Timer 实例 + var timer = new Timer(); + try + { + //DownEcgFtpImage(); + Execute(); + + Console.ReadKey(); + timer.Interval = intervalInMinutes * 60 * 1000; + // 设置为 true,使得 Timer 每隔设定的间隔时间自动触发一次 Elapsed 事件 + timer.AutoReset = true; + // 绑定 Elapsed 事件处理程序 + timer.Elapsed += Timer_Elapsed; + // 启动 Timer + timer.Start(); + // 阻止控制台程序退出 + Console.ReadKey(); + // 停止 Timer + timer.Stop(); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + timer.Stop(); + } + + Console.WriteLine($"【停止】{DateTime.Now:yyyy-MM-dd HH:mm}"); + Console.ReadKey(); + } + + /// + /// 定时执行任务 + /// + /// + /// + private static void Timer_Elapsed(object sender, ElapsedEventArgs e) + { + Console.WriteLine($@"执行-{DateTime.Now:yyyy-MM-dd HH:mm}"); + DownEcgFtpImage(); + Execute(); + SyncPacsReport(); + //DelDownFiles(); + } + + /// + /// 下载选择的 + /// + private static void Execute() + { + Console.WriteLine($"【开始同步PACS报告图片】{DateTime.Now:yyyy-MM-dd HH:mm}------------"); + //--将PACS检查报告同步到体检系统中 + if (!Directory.Exists(DcmPath)) + { + Directory.CreateDirectory(DcmPath); + } + var reportList = PacsSqlHelper.GetPacsReportList(); + var fileNameList = new List(); + int i = 1; + foreach (var report in reportList) + { + try + { + // 已选图片UID + var selectedList = PacsSqlHelper.GetReportUidList(report.AccessionNumber); + if (selectedList.Count <= 0) continue; + // DCM图片路径 + var imageFiles = PacsSqlHelper.GetPacsImageFile(report.PatientCode,report.ExamFeeitem_Code); + if (string.IsNullOrEmpty(imageFiles)) continue; + // 得到DCM共享文件地址 + var dcmPaths = imageFiles.Split(';'); + // 路径为空 + if (!(dcmPaths?.Length > 0)) continue; + + //获取远程共享文件 + using (var client = new WebClient()) + { + // 配置授权账户密码 + var credentials = new NetworkCredential(UserName, Password); + client.Credentials = credentials; + selectedList.ForEach(selected => + { + var file = selected + ".DCM"; + var dcmPacsDict = dcmPaths[0].Substring(dcmPaths[0].Length , file.Length); + string downPath = dcmPaths[0].Replace(dcmPacsDict, file); + if (Path.HasExtension(downPath)) + { + //下载远程文件 + var buffer = client.DownloadData(downPath); + // 保存本地 + var name = $"{report.PatientCode?.Trim()}-{report.ExamFeeitem_Code?.Trim()}-" + i; + Bytes2File(buffer, DcmPath, $"{name}.DCM"); + fileNameList.Add($"{name}.DCM"); + Console.WriteLine($"下载:{name}.DCM"); + i++; + }; + }); + // 循环路径 + for (var index = 0; index < dcmPaths.Count(); index++) + { + try + { + // 当前路径 + var dcmPath = dcmPaths[index]; + if (string.IsNullOrEmpty(dcmPath)) continue; + if (!Path.HasExtension(dcmPath) ) continue; + selectedList.ForEach(selected => + { + if (dcmPath.Contains(selected)) + { + //下载远程文件 + var buffer = client.DownloadData(dcmPath); + // 保存本地 + var name = $"{report.PatientCode?.Trim()}-{report.ExamFeeitem_Code?.Trim()}-" + i; + Bytes2File(buffer, DcmPath, $"{name}.DCM"); + fileNameList.Add($"{name}.DCM"); + Console.WriteLine($"下载:{name}.DCM"); + i++; + } + }); + } + catch (Exception e) + { + Console.WriteLine($"01." + e.Message); + } + } + } + } + catch (Exception e) + { + Console.WriteLine($"02." + e.Message); + } + } + + Console.WriteLine($@"【下载】{fileNameList.Count}"); + if (fileNameList.Count > 0) + // 保存到本地后上传到服务器 + UploadDcmImg(DcmPath, fileNameList, InsertExamPacsImage); + + Console.WriteLine($@"【等待】{intervalInMinutes}min"); + Console.WriteLine($"------------------------------------------"); + } + + /// + /// 1、将本地文件PACS影像图片发送到服务器 + /// + public static void UploadDcmImg(string folderPath, List fileNameList, string insertSql) + { + var time = DateTime.Now; + // 获取文件夹下所有文件的路径 + var files = Directory.GetFiles(folderPath); + var i = 0; + // 建立数据库连接 + using (var connection = new SqlConnection(ConnectionString)) + { + // 遍历文件路径并输出 + foreach (var filePath in files) + { + try + { + var fileName = System.IO.Path.GetFileName(filePath); + if (!fileNameList.Contains(fileName)) continue; + var eid = Convert.ToInt64(fileName.Split('-')[0]); + var reportNo = fileName.Split('-')[1]; + var image = new DicomImage(filePath); + //image.NumberOfFrames 如果有多帧图片需要将每帧都转成jpeg + //DCM转Bitmap + var bitmap = image.RenderImage().AsBitmap(); + using (var streamImg = new MemoryStream()) + { + //Bitmap To byte[] + bitmap.Save(streamImg, System.Drawing.Imaging.ImageFormat.Jpeg); + var imgBytes = streamImg.ToArray(); + // File.WriteAllBytes(Path.Combine(DcmPath, i+".jpeg"), imgBytes); + //上传 + { + connection.Open(); + // 创建插入记录的 SQL 查询 + // 创建命令对象 + using (var command = new SqlCommand(insertSql, connection)) + { + // 设置参数值 + command.Parameters.AddWithValue("@ImageData", imgBytes); + command.Parameters.AddWithValue("@EID", eid); + command.Parameters.AddWithValue("@ReportNo", reportNo); + command.Parameters.AddWithValue("@InTime", time); + + Console.WriteLine($@"【上传】{fileName}"); + // 执行插入操作 + command.ExecuteNonQuery(); + i++; + } + + connection.Close(); + } + } + // 删除上传成功的文件 + File.Delete(filePath); + } + catch (Exception e) + { + Console.WriteLine(System.IO.Path.GetFileName(filePath)); + Console.WriteLine(e.Message); + } + } + } + + Console.WriteLine($@"【上传成功】{i}"); + } + + /// + /// 将byte数组转换为文件并保存到指定地址 + /// + /// byte数组 + /// 保存地址 + /// + public static void Bytes2File(byte[] buff, string path, string fileName) + { + try + { + //如果不存在就创建Enclosure文件夹  + if (Directory.Exists(path) == false) + Directory.CreateDirectory(path); + + if (File.Exists(path + fileName)) + File.Delete(path + fileName); + + var fs = new FileStream(path + fileName, FileMode.CreateNew); + var bw = new BinaryWriter(fs); + bw.Write(buff, 0, buff.Length); + bw.Close(); + fs.Close(); + } + catch (Exception e) + { + Console.WriteLine("【下载失败】" + fileName + "--" + e.Message); + } + } + + public static void DownEcgFtpImage() + { + Console.WriteLine("-----------------------------------"); + Console.WriteLine($"【ECG-START】{DateTime.Now:yyyy-MM-dd HH:mm}"); + var files = DAOHelp.GetDataBySQL + ($@"SELECT id,ReportUrl FROM Report_GSEXD WHERE ReportUrl is not null and ReportData is null"); + Console.WriteLine("[ECG-ReportCount]" + files.Count); + if (files.Count == 0) + return; + var name = "TJ_HXECG"; + var password = "123456"; + if (!Directory.Exists(EcgPath)) + { + Directory.CreateDirectory(EcgPath); + } + + FtpHelper.DownloadFtpFile(files, name, password, EcgPath); + UploadEcgImg(EcgPath, files.Select(s => s.ID.ToString()).ToList()); + Console.WriteLine("ECG 下载完毕"); + Console.WriteLine($"【ECG-END】{DateTime.Now:yyyy-MM-dd HH:mm}"); + Console.WriteLine("-----------------------------------"); + } + + /// + /// 1、将ecg图片发送到服务器 + /// + public static void UploadEcgImg(string folderPath, List idList) + { + var i = 0; + // 建立数据库连接 + using (var connection = new SqlConnection(ConnectionString)) + { + // 遍历文件路径并输出 + foreach (var id in idList) + { + var jpgFilePath = Path.Combine(folderPath, id + ".jpg"); + try + { + if (!File.Exists(jpgFilePath)) + { + Console.WriteLine(id + "NotFound" + jpgFilePath); + continue; + } + + // 加载JPG图片 + using (var image = Image.FromFile(jpgFilePath)) + { + // 创建内存流 + using (MemoryStream memoryStream = new MemoryStream()) + { + // 将图像保存到内存流中,指定图像格式为JPEG + image.Save(memoryStream, ImageFormat.Jpeg); + // 将内存流中的数据复制到字节数组 + var imgBytes = memoryStream.ToArray(); + //上传 + { + connection.Open(); + // 创建插入记录的 SQL 查询 + string updateEcgRpt = + @"update Report_GSEXD set ReportData=@ReportData where id=@ID"; + // 创建命令对象 + using (var command = new SqlCommand(updateEcgRpt, connection)) + { + // 设置参数值 + command.Parameters.AddWithValue("@ReportData", imgBytes); + command.Parameters.AddWithValue("@ID", id); + Console.WriteLine($@"【上传】{id}.jpg"); + // 执行插入操作 + command.ExecuteNonQuery(); + i++; + } + + connection.Close(); + } + } + } + + File.Delete(jpgFilePath); + } + catch (Exception e) + { + Console.WriteLine(id + "-" + e.Message); + } + } + } + + Console.WriteLine($@"【上传成功】{i}"); + } + + public static void SyncPacsReport() + { + DAOHelp.ExecuteSql("EXEC sp_PacsRptInsert;"); + } + } +} \ No newline at end of file diff --git a/DicomTool/Properties/AssemblyInfo.cs b/DicomTool/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3b85095 --- /dev/null +++ b/DicomTool/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("DicomTool")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DicomTool")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("7afe3a9a-02c9-4d8c-a03b-1bffecb153a3")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/DicomTool/Utils/DAOHelp.cs b/DicomTool/Utils/DAOHelp.cs new file mode 100644 index 0000000..db6a60e --- /dev/null +++ b/DicomTool/Utils/DAOHelp.cs @@ -0,0 +1,258 @@ +#region CopyRight + +/**************************************************************** + * Project:健康体检信息管理系统(PEIS) + * Author:张剑峰 + * CLR Version:4.0.30319.42000 + * CreateTime:2023-05-01 14:43:04 + * Version:v2.0 + * + * Description: + * + * History: + * +***************************************************************** + * Copyright @ 云南新八达科技有限公司 2023 All rights reserved +*****************************************************************/ + +#endregion CopyRight + +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Reflection; +using PEIS.Utils; + +namespace DicomTool.Utils +{ + /* + * 操作数据库的方法 + * 约定: + * 1)对象属性必须有public string TableName + * 2)属性名与字段名一样。 + * 3)主键属性需标记自定义特性KeyFlagAttribute,表示此属性是数据表中的主键 + * 4)数据表中每个表必须设有主键 + */ + + public class DAOHelp + { + #region 属性 + + /// + /// 数据库连接字符串 + /// + private static readonly string connectionString = MySecurity.SDecryptString(ConfigurationManager.ConnectionStrings["ConnString"].ToString()); + + #endregion 属性 + + #region 数据库增、删、改、查 + + public static DataTable GetDataBySql(string sql) + { + DateTime startTime = DateTime.Now; + DataTable dt = new DataTable(); + using (SqlConnection conn = new SqlConnection(connectionString)) + { + try + { + conn.Open(); + SqlCommand cmd = new SqlCommand(sql, conn); + cmd.CommandTimeout = Convert.ToInt32(Global.GetAppConfig("TimeOut")); + SqlDataAdapter adapter = new SqlDataAdapter(cmd); + + foreach (DataColumn column in dt.Columns) + { + if (column.DataType == typeof(string)) + { + column.DefaultValue = string.Empty; + } + } + + adapter.Fill(dt); + } + catch (Exception e) + { + Debug.WriteLine("GetDataBySQL异常:" + sql + "," + e.Message); + Console.WriteLine("数据库连接失败,请检查网络,或联系管理员!" + e.Message); + } + } + + // 数据库连接池 + //DBConnectionSingletion pool = DBConnectionSingletion.Instance; + //DBConnectionSingletion.ConnectionString = connectionString; + //SqlConnection conn = pool.BorrowDBConnection(); + //SqlCommand cmd = new SqlCommand(sql, conn); + //SqlDataAdapter adapter = new SqlDataAdapter(cmd); + //adapter.Fill(dt); + //pool.ReturnDBConnection(conn); + + //Global.CostTime("conn.Open", StartTime); + + return dt; + } + + /// + /// 执行非查询SQL + /// + /// + /// + public static int ExecuteSql(String sql, Boolean startTrans = false) + { + //sql = sql.ToUpper(); + Debug.WriteLine("执行SQL=>" + sql); + int n = 0;//影响的行数 + DateTime StartTime = DateTime.Now; + DataTable dt = new DataTable(); + using (SqlConnection conn = new SqlConnection(connectionString)) + { + if (startTrans) + { + SqlTransaction trans = null; + try + { + conn.Open(); + } + catch (Exception e) + { + Console.WriteLine("数据库连接失败,请检查网络,或联系管理员!" + e.Message); + } + try + { + trans = conn.BeginTransaction(); + SqlCommand cmd = new SqlCommand(sql, conn); + cmd.CommandTimeout = Convert.ToInt32(Global.GetAppConfig("TimeOut")); + n = cmd.ExecuteNonQuery(); + trans.Commit(); + } + catch + { + trans.Rollback(); + Debug.WriteLine(sql); + Console.WriteLine("SQL执行错误!"); + } + } + else + { + try + { + conn.Open(); + } + catch (Exception e) + { + Console.WriteLine("数据库连接失败,请检查网络,或联系管理员!" + e.Message); + } + try + { + SqlCommand cmd = new SqlCommand(sql, conn); + n = cmd.ExecuteNonQuery(); + } + catch + { + Debug.WriteLine(sql); + Console.WriteLine("SQL执行错误!"); + } + } + } + return n; + } + + public static List GetDataBySQL(String sql) where T : class, new() + { + Debug.WriteLine("执行SQL=>" + sql); + Type type = typeof(T); + List list = new List(); + DataTable dt = GetDataBySql(sql.ToUpper()); + + foreach (DataRow row in dt.Rows) + { + PropertyInfo[] pArray = type.GetProperties(); + T entity = new T(); + foreach (PropertyInfo p in pArray) + { + if (dt.Columns.IndexOf(p.Name) == -1) + { + continue; + } + if (p.Name == "TableName") + { + continue; + } + else + { + if (row[p.Name] is String) + { + p.SetValue(entity, row[p.Name], null); + continue; + } + if (row[p.Name] is Int32) + { + p.SetValue(entity, Convert.ToInt32(row[p.Name]), null); + continue; + } + if (row[p.Name] is Int64) + { + p.SetValue(entity, Convert.ToInt64(row[p.Name]), null); + continue; + } + if (row[p.Name] is DateTime) + { + p.SetValue(entity, Convert.ToDateTime(row[p.Name]), null); + continue; + } + if (row[p.Name] is byte[]) + { + //Image image = Global.BytesToImage((byte[])row[p.Name]); + p.SetValue(entity, row[p.Name], null); + continue; + } + if (row[p.Name] is DBNull) + { + if (p.PropertyType.Name == "Int64" || p.PropertyType.Name == "Int32") + { + p.SetValue(entity, 0, null); + continue; + } + else if (p.PropertyType.Name == "Decimal") + { + p.SetValue(entity, Convert.ToDecimal(0), null); + continue; + } + else if (p.PropertyType.Name == "Boolean") + { + p.SetValue(entity, false, null); + continue; + } + else if (p.PropertyType.Name == "Image" || p.PropertyType.Name == "Byte[]") + { + p.SetValue(entity, null, null); + continue; + } + else + { + p.SetValue(entity, null, null); + } + continue; + } + //object[] attrs = p.GetCustomAttributes(false); + //if (attrs.Count() > 0) + //{ + // if (attrs[0].GetType().Name.Equals("RefFlagAttribute")) + // { + // if (attrs.Count() == 1) + // continue; + // } + //} + p.SetValue(entity, row[p.Name], null); + } + } + list.Add(entity); + } + return list; + } + + #endregion 数据库增、删、改、查 + } +} \ No newline at end of file diff --git a/DicomTool/Utils/DicomDecoder.cs b/DicomTool/Utils/DicomDecoder.cs new file mode 100644 index 0000000..46d18a6 --- /dev/null +++ b/DicomTool/Utils/DicomDecoder.cs @@ -0,0 +1,939 @@ +// using System; +// using System.Collections.Generic; +// using System.Globalization; +// using System.IO; +// using System.Linq; +// +// namespace DICOMCoverter +// { +// public enum TypeOfDicomFile +// { +// NotDicom, +// Dicom3File, +// DicomOldTypeFile, +// DicomUnknownTransferSyntax +// }; +// +// public class DicomDecoder +// { +// #region 定义变量与初始化 +// +// private const uint PIXEL_REPRESENTATION = 0x00280103; +// private const uint TRANSFER_SYNTAX_UID = 0x00020010; +// private const uint MODALITY = 0x00080060; +// private const uint SLICE_THICKNESS = 0x00180050; +// private const uint SLICE_SPACING = 0x00180088; +// private const uint SAMPLES_PER_PIXEL = 0x00280002; +// private const uint PHOTOMETRIC_INTERPRETATION = 0x00280004; +// private const uint PLANAR_CONFIGURATION = 0x00280006; +// private const uint NUMBER_OF_FRAMES = 0x00280008; +// private const uint ROWS = 0x00280010; +// private const uint COLUMNS = 0x00280011; +// private const uint PIXEL_SPACING = 0x00280030; +// private const uint BITS_ALLOCATED = 0x00280100; +// private const uint WINDOW_CENTER = 0x00281050; +// private const uint WINDOW_WIDTH = 0x00281051; +// private const uint RESCALE_INTERCEPT = 0x00281052; +// private const uint RESCALE_SLOPE = 0x00281053; +// private const uint RED_PALETTE = 0x00281201; +// private const uint GREEN_PALETTE = 0x00281202; +// private const uint BLUE_PALETTE = 0x00281203; +// private const uint ICON_IMAGE_SEQUENCE = 0x00880200; +// private const uint PIXEL_DATA = 0x7FE00010; +// +// private const string ITEM = "FFFEE000"; +// private const string ITEM_DELIMITATION = "FFFEE00D"; +// private const string SEQUENCE_DELIMITATION = "FFFEE0DD"; +// +// private const int +// AE = 0x4145, +// AS = 0x4153, +// AT = 0x4154, +// CS = 0x4353, +// DA = 0x4441, +// DS = 0x4453, +// DT = 0x4454, +// FD = 0x4644, +// FL = 0x464C, +// IS = 0x4953, +// LO = 0x4C4F, +// LT = 0x4C54, +// PN = 0x504E, +// SH = 0x5348, +// SL = 0x534C, +// SS = 0x5353, +// ST = 0x5354, +// TM = 0x544D, +// UI = 0x5549, +// UL = 0x554C, +// US = 0x5553, +// UT = 0x5554, +// OB = 0x4F42, +// OW = 0x4F57, +// SQ = 0x5351, +// UN = 0x554E, +// QQ = 0x3F3F, +// RT = 0x5254; +// +// private const int ID_OFFSET = 128; //location of "DICM" +// private const int IMPLICIT_VR = 0x2D2D; // '--' +// private const String DICM = "DICM"; +// +// public int bitsAllocated; +// public int width; +// public int height; +// public int offset; +// public int nImages; +// public int samplesPerPixel; +// public double pixelDepth = 1.0; +// public double pixelWidth = 1.0; +// public double pixelHeight = 1.0; +// public string unit; +// public double windowCentre, windowWidth; +// public bool signedImage; +// public TypeOfDicomFile typeofDicomFile; +// public List dicomInfo; +// public bool dicmFound; // "DICM" found at offset 128 +// +// private DicomDictionary dic; +// private BinaryReader file; +// private String dicomFileName; +// +// /// +// /// Photometric Interpretation有以下几种类型: +// ///Monochrome2 一般的灰度图像都采用这种,Pixel值越大,图像就越白。 +// ///Monochrome1 只有部分CR, DR图像使用,Pixel值越大,图像就越黑。 +// /// +// private String photoInterpretation; +// +// private bool littleEndian = true; +// private bool oddLocations; // one or more tags at odd locations +// private bool bigEndianTransferSyntax = false; +// private bool inSequence; +// private bool widthTagFound; +// private bool heightTagFound; +// private bool pixelDataTagFound; +// private int location = 0; +// private int elementLength; +// private int vr; // Value Representation +// private int min8 = Byte.MinValue; +// private int max8 = Byte.MaxValue; +// private int min16 = short.MinValue; +// private int max16 = ushort.MaxValue; +// private int pixelRepresentation; +// private double rescaleIntercept; +// private double rescaleSlope; +// private byte[] reds; +// private byte[] greens; +// private byte[] blues; +// private byte[] vrLetters = new byte[2]; +// private List pixels8; +// private List pixels24; // 8 bits bit depth, 3 samples per pixel +// private List pixels16; +// private List pixels16Int; +// +// public DicomDecoder() +// { +// dic = new DicomDictionary(); +// signedImage = false; +// dicomInfo = new List(); +// InitializeDicom(); +// } +// +// private void InitializeDicom() +// { +// bitsAllocated = 0; +// width = 1; +// height = 1; +// offset = 1; +// nImages = 1; +// samplesPerPixel = 1; +// photoInterpretation = ""; +// unit = "mm"; +// windowCentre = 0; +// windowWidth = 0; +// signedImage = false; +// widthTagFound = false; +// heightTagFound = false; +// pixelDataTagFound = false; +// rescaleIntercept = 0.0; // Default value +// rescaleSlope = 1.0; // Default value +// typeofDicomFile = TypeOfDicomFile.NotDicom; +// } +// +// #endregion 定义变量与初始化 +// +// //public string DicomFileName +// //{ +// // set +// // { +// // dicomFileName = value; +// // InitializeDicom(); +// +// // // Thanks to CodeProject member Alphons van der Heijden for +// // // suggesting to add this - FileAccess.Read (July 2010) +// // file = new BinaryReader(File.Open(dicomFileName, FileMode.Open, FileAccess.Read)); +// // location = 0; // Reset the location +// // dicomInfo.Clear(); +// // try +// // { +// // bool readResult = ReadFileInfo(); +// // if (readResult && widthTagFound && heightTagFound && pixelDataTagFound) +// // { +// // ReadPixels(); +// // if (dicmFound == true) +// // typeofDicomFile = TypeOfDicomFile.Dicom3File; +// // else +// // typeofDicomFile = TypeOfDicomFile.DicomOldTypeFile; +// // } +// // } +// // catch +// // { +// // // Nothing here +// // } +// // finally +// // { +// // file.Close(); +// // } +// // } +// //} +// +// /// +// ///读取dicom文件及操作 +// ///取图片第几帧 +// /// +// public void ReadDicomFile(string path, int famenum = 1) +// { +// file = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read)); +// location = 0; // Reset the location +// dicomInfo.Clear(); +// try +// { +// //读Tag信息 +// bool readResult = ReadFileInfo(); +// //图片宽高及图像数据都已读到 +// if (readResult && widthTagFound && heightTagFound && pixelDataTagFound) +// { +// ////存在多帧图像 +// //if (nImages > 1) +// //{ +// // for (int i = 1; i < nImages; i++) +// // { +// // ReadPixels(i); +// // } +// //} +// //else { +// // //读取图片数据 +// // ReadPixels(); +// //} +// +// ReadPixels(); +// +// if (dicmFound == true) +// typeofDicomFile = TypeOfDicomFile.Dicom3File; +// else +// typeofDicomFile = TypeOfDicomFile.DicomOldTypeFile; +// } +// } +// catch (Exception ex) +// { +// // Nothing here +// } +// finally +// { +// file.Close(); +// } +// } +// +// private void BuildImage() +// { +// } +// +// public void GetPixels8(ref List pixels) +// { +// pixels = pixels8; +// } +// +// public void GetPixels16(ref List pixels) +// { +// pixels = pixels16; +// } +// +// public void GetPixels24(ref List pixels) +// { +// pixels = pixels24; +// } +// +// private String GetString(int length) +// { +// byte[] buf = new byte[length]; +// file.BaseStream.Position = location; +// int count = file.Read(buf, 0, length); +// location += length; +// string s = System.Text.ASCIIEncoding.ASCII.GetString(buf); +// return s; +// } +// +// private byte GetByte() // Changed return type to byte +// { +// file.BaseStream.Position = location; +// byte b = file.ReadByte(); +// ++location; +// return b; +// } +// +// private ushort GetShort() // Changed return type to ushort +// { +// byte b0 = GetByte(); +// byte b1 = GetByte(); +// ushort s; +// if (littleEndian) +// s = Convert.ToUInt16((b1 << 8) + b0); +// else +// s = Convert.ToUInt16((b0 << 8) + b1); +// return s; +// } +// +// private int GetInt() +// { +// byte b0 = GetByte(); +// byte b1 = GetByte(); +// byte b2 = GetByte(); +// byte b3 = GetByte(); +// int i; +// if (littleEndian) +// i = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0; +// else +// i = (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; +// return i; +// } +// +// private double GetDouble() +// { +// byte b0 = GetByte(); +// byte b1 = GetByte(); +// byte b2 = GetByte(); +// byte b3 = GetByte(); +// byte b4 = GetByte(); +// byte b5 = GetByte(); +// byte b6 = GetByte(); +// byte b7 = GetByte(); +// +// long res = 0; +// if (littleEndian) +// { +// res += b0; +// res += (((long)b1) << 8); +// res += (((long)b2) << 16); +// res += (((long)b3) << 24); +// res += (((long)b4) << 32); +// res += (((long)b5) << 40); +// res += (((long)b6) << 48); +// res += (((long)b7) << 56); +// } +// else +// { +// res += b7; +// res += (((long)b6) << 8); +// res += (((long)b5) << 16); +// res += (((long)b4) << 24); +// res += (((long)b3) << 32); +// res += (((long)b2) << 40); +// res += (((long)b1) << 48); +// res += (((long)b0) << 56); +// } +// +// double d = Convert.ToDouble(res, new CultureInfo("en-US")); +// return d; +// } +// +// private float GetFloat() +// { +// byte b0 = GetByte(); +// byte b1 = GetByte(); +// byte b2 = GetByte(); +// byte b3 = GetByte(); +// +// int res = 0; +// +// if (littleEndian) +// { +// res += b0; +// res += (((int)b1) << 8); +// res += (((int)b2) << 16); +// res += (((int)b3) << 24); +// } +// else +// { +// res += b3; +// res += (((int)b2) << 8); +// res += (((int)b1) << 16); +// res += (((int)b0) << 24); +// } +// +// float f1; +// f1 = Convert.ToSingle(res, new CultureInfo("en-US")); +// return f1; +// } +// +// private byte[] GetLut(int length) +// { +// if ((length & 1) != 0) // odd +// { +// String dummy = GetString(length); +// return null; +// } +// +// length /= 2; +// byte[] lut = new byte[length]; +// for (int i = 0; i < length; ++i) +// lut[i] = Convert.ToByte(GetShort() >> 8); +// return lut; +// } +// +// private int GetLength() +// { +// byte b0 = GetByte(); +// byte b1 = GetByte(); +// byte b2 = GetByte(); +// byte b3 = GetByte(); +// +// // Cannot know whether the VR is implicit or explicit without the +// // complete Dicom Data Dictionary. +// vr = (b0 << 8) + b1; +// +// switch (vr) +// { +// case OB: +// case OW: +// case SQ: +// case UN: +// case UT: +// // Explicit VR with 32-bit length if other two bytes are zero +// if ((b2 == 0) || (b3 == 0)) return GetInt(); +// // Implicit VR with 32-bit length +// vr = IMPLICIT_VR; +// if (littleEndian) +// return ((b3 << 24) + (b2 << 16) + (b1 << 8) + b0); +// else +// return ((b0 << 24) + (b1 << 16) + (b2 << 8) + b3); +// // break; // Not necessary +// case AE: +// case AS: +// case AT: +// case CS: +// case DA: +// case DS: +// case DT: +// case FD: +// case FL: +// case IS: +// case LO: +// case LT: +// case PN: +// case SH: +// case SL: +// case SS: +// case ST: +// case TM: +// case UI: +// case UL: +// case US: +// case QQ: +// case RT: +// // Explicit vr with 16-bit length +// if (littleEndian) +// return ((b3 << 8) + b2); +// else +// return ((b2 << 8) + b3); +// +// default: +// // Implicit VR with 32-bit length... +// vr = IMPLICIT_VR; +// if (littleEndian) +// return ((b3 << 24) + (b2 << 16) + (b1 << 8) + b0); +// else +// return ((b0 << 24) + (b1 << 16) + (b2 << 8) + b3); +// } +// } +// +// private int GetNextTag() +// { +// int groupWord = GetShort(); +// if (groupWord == 0x0800 && bigEndianTransferSyntax) +// { +// littleEndian = false; +// groupWord = 0x0008; +// } +// int elementWord = GetShort(); +// int tag = groupWord << 16 | elementWord; +// +// elementLength = GetLength(); +// +// // Hack to read some GE files +// if (elementLength == 13 && !oddLocations) +// elementLength = 10; +// +// // "Undefined" element length. +// // This is a sort of bracket that encloses a sequence of elements. +// if (elementLength == -1) +// { +// elementLength = 0; +// inSequence = true; +// } +// return tag; +// } +// +// private String GetHeaderInfo(int tag, String value) +// { +// string str = tag.ToString("X8"); +// if (str == ITEM_DELIMITATION || str == SEQUENCE_DELIMITATION) +// { +// inSequence = false; +// return null; +// } +// +// string id = null; +// +// if (dic.dict.ContainsKey(str)) +// { +// id = dic.dict[str]; +// if (id != null) +// { +// if (vr == IMPLICIT_VR) +// vr = (id[0] << 8) + id[1]; +// id = id.Substring(2); +// } +// } +// +// if (str == ITEM) +// return (id != null ? id : ":null"); +// if (value != null) +// return id + ": " + value; +// +// switch (vr) +// { +// case FD: +// for (int i = 0; i < elementLength; ++i) +// GetByte(); +// break; +// +// case FL: +// for (int i = 0; i < elementLength; i++) +// GetByte(); +// break; +// +// case AE: +// case AS: +// case AT: +// case CS: +// case DA: +// case DS: +// case DT: +// case IS: +// case LO: +// case LT: +// case PN: +// case SH: +// case ST: +// case TM: +// case UI: +// value = GetString(elementLength); +// break; +// +// case US: +// if (elementLength == 2) +// value = Convert.ToString(GetShort()); +// else +// { +// value = ""; +// int n = elementLength / 2; +// for (int i = 0; i < n; i++) +// value += Convert.ToString(GetShort()) + " "; +// } +// break; +// +// case IMPLICIT_VR: +// value = GetString(elementLength); +// if (elementLength > 44) +// value = null; +// break; +// +// case SQ: +// value = ""; +// bool privateTag = ((tag >> 16) & 1) != 0; +// if (tag != ICON_IMAGE_SEQUENCE && !privateTag) +// break; +// goto default; +// default: +// location += elementLength; +// value = ""; +// break; +// } +// +// if (value != null && id == null && value != "") +// return "---: " + value; +// else if (id == null) +// return null; +// else +// return id + ": " + value; +// } +// +// private void AddInfo(int tag, string value) +// { +// string info = GetHeaderInfo(tag, value); +// +// string str = tag.ToString("X"); +// string strPadded = str.PadLeft(8, '0'); +// string strInfo; +// if (inSequence && info != null && vr != SQ) +// info = ">" + info; +// if (info != null && str != ITEM) +// { +// if (info.Contains("---")) +// strInfo = info.Replace("---", "Private Tag"); +// else +// strInfo = info; +// +// dicomInfo.Add(strPadded + "//" + strInfo); +// } +// } +// +// private void AddInfo(int tag, int value) +// { +// AddInfo(tag, Convert.ToString(value)); +// } +// +// private void GetSpatialScale(String scale) +// { +// double xscale = 0, yscale = 0; +// int i = scale.IndexOf('\\'); +// if (i == 1) // Aug 2012, Fixed an issue found while opening some images +// { +// yscale = Convert.ToDouble(scale.Substring(0, i), new CultureInfo("en-US")); +// xscale = Convert.ToDouble(scale.Substring(i + 1), new CultureInfo("en-US")); +// } +// if (xscale != 0.0 && yscale != 0.0) +// { +// pixelWidth = xscale; +// pixelHeight = yscale; +// unit = "mm"; +// } +// } +// +// /// +// /// 读取Tag信息 +// /// +// /// +// public bool ReadFileInfo() +// { +// long skipCount = Convert.ToInt32(ID_OFFSET); +// bitsAllocated = 16; +// +// file.BaseStream.Seek(skipCount, SeekOrigin.Begin); +// location += ID_OFFSET; +// +// if (GetString(4) != DICM) +// { +// // This is for reading older DICOM files (Before 3.0) +// // Seek from the beginning of the file +// file.BaseStream.Seek(0, SeekOrigin.Begin); +// location = 0; +// +// // Older DICOM files do not have the preamble and prefix +// dicmFound = false; +// +// // Continue reading further. +// // See whether the width, height and pixel data tags +// // are present. If these tags are present, then it we conclude that this is a +// // DICOM file, because all DICOM files should have at least these three tags. +// // Otherwise, it is not a DICOM file. +// } +// else +// { +// // We have a DICOM 3.0 file +// dicmFound = true; +// } +// +// bool decodingTags = true; +// samplesPerPixel = 1; +// int planarConfiguration = 0; +// photoInterpretation = ""; +// string modality; +// +// while (decodingTags) +// { +// int tag = GetNextTag(); +// if ((location & 1) != 0) +// oddLocations = true; +// +// if (inSequence) +// { +// AddInfo(tag, null); +// continue; +// } +// +// string s; +// switch (tag) +// { +// case (int)(TRANSFER_SYNTAX_UID): +// s = GetString(elementLength); +// AddInfo(tag, s); +// //if (s.IndexOf("1.2.4") > -1 || s.IndexOf("1.2.5") > -1) +// //{ +// // file.Close(); +// // typeofDicomFile = TypeOfDicomFile.DicomUnknownTransferSyntax; +// // // Return gracefully indicating that this type of +// // // Transfer Syntax cannot be handled +// // return false; +// //} +// if (s.IndexOf("1.2.840.10008.1.2.2") >= 0) +// bigEndianTransferSyntax = true; +// break; +// +// case (int)MODALITY: +// modality = GetString(elementLength); +// AddInfo(tag, modality); +// break; +// +// case (int)(NUMBER_OF_FRAMES): +// s = GetString(elementLength); +// AddInfo(tag, s); +// double frames = Convert.ToDouble(s, new CultureInfo("en-US")); +// if (frames > 1.0) +// nImages = (int)frames; +// break; +// +// case (int)(SAMPLES_PER_PIXEL): +// samplesPerPixel = GetShort(); +// AddInfo(tag, samplesPerPixel); +// break; +// +// case (int)(PHOTOMETRIC_INTERPRETATION): +// photoInterpretation = GetString(elementLength); +// photoInterpretation = photoInterpretation.Trim(); +// AddInfo(tag, photoInterpretation); +// break; +// +// case (int)(PLANAR_CONFIGURATION): +// planarConfiguration = GetShort(); +// AddInfo(tag, planarConfiguration); +// break; +// +// case (int)(ROWS): +// height = GetShort(); +// AddInfo(tag, height); +// heightTagFound = true; +// break; +// +// case (int)(COLUMNS): +// width = GetShort(); +// AddInfo(tag, width); +// widthTagFound = true; +// break; +// +// case (int)(PIXEL_SPACING): +// String scale = GetString(elementLength); +// GetSpatialScale(scale); +// AddInfo(tag, scale); +// break; +// +// case (int)(SLICE_THICKNESS): +// case (int)(SLICE_SPACING): +// String spacing = GetString(elementLength); +// pixelDepth = Convert.ToDouble(spacing, new CultureInfo("en-US")); +// AddInfo(tag, spacing); +// break; +// +// case (int)(BITS_ALLOCATED): +// bitsAllocated = GetShort(); +// AddInfo(tag, bitsAllocated); +// break; +// +// case (int)(PIXEL_REPRESENTATION): +// pixelRepresentation = GetShort(); +// AddInfo(tag, pixelRepresentation); +// break; +// +// case (int)(WINDOW_CENTER): +// String center = GetString(elementLength); +// int index = center.IndexOf('\\'); +// if (index != -1) center = center.Substring(index + 1); +// windowCentre = Convert.ToDouble(center, new CultureInfo("en-US")); +// AddInfo(tag, center); +// break; +// +// case (int)(WINDOW_WIDTH): +// String widthS = GetString(elementLength); +// index = widthS.IndexOf('\\'); +// if (index != -1) widthS = widthS.Substring(index + 1); +// windowWidth = Convert.ToDouble(widthS, new CultureInfo("en-US")); +// AddInfo(tag, widthS); +// break; +// +// case (int)(RESCALE_INTERCEPT): +// String intercept = GetString(elementLength); +// rescaleIntercept = Convert.ToDouble(intercept, new CultureInfo("en-US")); +// AddInfo(tag, intercept); +// break; +// +// case (int)(RESCALE_SLOPE): +// String slop = GetString(elementLength); +// rescaleSlope = Convert.ToDouble(slop, new CultureInfo("en-US")); +// AddInfo(tag, slop); +// break; +// +// case (int)(RED_PALETTE): +// reds = GetLut(elementLength); +// AddInfo(tag, elementLength / 2); +// break; +// +// case (int)(GREEN_PALETTE): +// greens = GetLut(elementLength); +// AddInfo(tag, elementLength / 2); +// break; +// +// case (int)(BLUE_PALETTE): +// blues = GetLut(elementLength); +// AddInfo(tag, elementLength / 2); +// break; +// +// case (int)(PIXEL_DATA): +// // Start of image data... +// if (elementLength != 0) +// { +// offset = location; +// AddInfo(tag, location); +// decodingTags = false; +// } +// else +// AddInfo(tag, null); +// pixelDataTagFound = true; +// break; +// //case Convert.ToInt64(ITEM, 16): +// +// // break; +// default: +// AddInfo(tag, null); +// break; +// } +// } +// return true; +// } +// +// /// +// /// 读取图片信息(从1 开始) +// /// 取图片第几帧 +// /// +// private void ReadPixels(int famenum = 1) +// { +// //if (famenum > 1) +// //{ +// // //默认offset就是第一帧的位置 +// // offset = width * height * (famenum - 1); +// //} +// +// if (samplesPerPixel == 1 && bitsAllocated == 8) +// { +// if (pixels8 != null) +// pixels8.Clear(); +// pixels8 = new List(); +// int numPixels = width * height; +// byte[] buf = new byte[numPixels]; +// +// file.BaseStream.Position = offset; +// file.Read(buf, 0, numPixels); +// +// for (int i = 0; i < numPixels; ++i) +// { +// int pixVal = (int)(buf[i] * rescaleSlope + rescaleIntercept); +// +// if (photoInterpretation == "MONOCHROME1") +// pixVal = max8 - pixVal; +// +// pixels8.Add((byte)(pixelRepresentation == 1 ? pixVal : (pixVal - min8))); +// } +// } +// +// if (samplesPerPixel == 1 && bitsAllocated == 16) +// { +// if (pixels16 != null) +// pixels16.Clear(); +// if (pixels16Int != null) +// pixels16Int.Clear(); +// +// pixels16 = new List(); +// pixels16Int = new List(); +// int numPixels = width * height; +// byte[] bufByte = new byte[numPixels * 2]; +// byte[] signedData = new byte[2]; +// file.BaseStream.Position = offset; +// file.Read(bufByte, 0, numPixels * 2); +// ushort unsignedS; +// int i, i1, pixVal; +// byte b0, b1; +// +// for (i = 0; i < numPixels; ++i) +// { +// i1 = i * 2; +// b0 = bufByte[i1]; +// b1 = bufByte[i1 + 1]; +// unsignedS = Convert.ToUInt16((b1 << 8) + b0); +// if (pixelRepresentation == 0) // Unsigned +// { +// pixVal = (int)(unsignedS * rescaleSlope + rescaleIntercept); +// if (photoInterpretation == "MONOCHROME1") +// pixVal = max16 - pixVal; +// } +// else // Pixel representation is 1, indicating a 2s complement image +// { +// signedData[0] = b0; +// signedData[1] = b1; +// short sVal = System.BitConverter.ToInt16(signedData, 0); +// +// // Need to consider rescale slope and intercepts to compute the final pixel value +// pixVal = (int)(sVal * rescaleSlope + rescaleIntercept); +// if (photoInterpretation == "MONOCHROME1") +// pixVal = max16 - pixVal; +// } +// pixels16Int.Add(pixVal); +// } +// +// int minPixVal = pixels16Int.Min(); +// signedImage = false; +// if (minPixVal < 0) signedImage = true; +// +// // Use the above pixel data to populate the list pixels16 +// foreach (int pixel in pixels16Int) +// { +// // We internally convert all 16-bit images to the range 0 - 65535 +// if (signedImage) +// pixels16.Add((ushort)(pixel - min16)); +// else +// pixels16.Add((ushort)(pixel)); +// } +// +// pixels16Int.Clear(); +// } +// +// // 30 July 2010 - to account for Ultrasound images +// if (samplesPerPixel == 3 && bitsAllocated == 8) +// { +// signedImage = false; +// if (pixels24 != null) +// pixels24.Clear(); +// pixels24 = new List(); +// int numPixels = width * height; +// int numBytes = numPixels * samplesPerPixel; +// byte[] buf = new byte[numBytes]; +// file.BaseStream.Position = offset; +// file.Read(buf, 0, numBytes); +// +// for (int i = 0; i < numBytes; ++i) +// { +// pixels24.Add(buf[i]); +// } +// } +// } +// } +// } \ No newline at end of file diff --git a/DicomTool/Utils/DicomDictionary.cs b/DicomTool/Utils/DicomDictionary.cs new file mode 100644 index 0000000..206b652 --- /dev/null +++ b/DicomTool/Utils/DicomDictionary.cs @@ -0,0 +1,804 @@ +// using System.Collections.Generic; +// +// namespace DICOMCoverter +// { +// internal class DicomDictionary +// { +// public Dictionary dict = new Dictionary() +// { +// {"00020002", "UIMedia Storage SOP Class UID"}, +// {"00020003", "UIMedia Storage SOP Instance UID"}, +// {"00020010", "UITransfer Syntax UID"}, +// {"00020012", "UIImplementation Class UID"}, +// {"00020013", "SHImplementation Version Name"}, +// {"00020016", "AESource Application Entity Title"}, +// +// {"00080005", "CSSpecific Character Set"}, +// {"00080008", "CSImage Type"}, +// {"00080010", "CSRecognition Code"}, +// {"00080012", "DAInstance Creation Date"}, +// {"00080013", "TMInstance Creation Time"}, +// {"00080014", "UIInstance Creator UID"}, +// {"00080016", "UISOP Class UID"}, +// {"00080018", "UISOP Instance UID"}, +// {"00080020", "DAStudy Date"}, +// {"00080021", "DASeries Date"}, +// {"00080022", "DAAcquisition Date"}, +// {"00080023", "DAContent Date"}, +// {"00080024", "DAOverlay Date"}, +// {"00080025", "DACurve Date"}, +// {"00080030", "TMStudy Time"}, +// {"00080031", "TMSeries Time"}, +// {"00080032", "TMAcquisition Time"}, +// {"00080033", "TMContent Time"}, +// {"00080034", "TMOverlay Time"}, +// {"00080035", "TMCurve Time"}, +// {"00080040", "USData Set Type"}, +// {"00080041", "LOData Set Subtype"}, +// {"00080042", "CSNuclear Medicine Series Type"}, +// {"00080050", "SHAccession Number"}, +// {"00080052", "CSQuery/Retrieve Level"}, +// {"00080054", "AERetrieve AE Title"}, +// {"00080058", "AEFailed SOP Instance UID List"}, +// {"00080060", "CSModality"}, +// {"00080064", "CSConversion Type"}, +// {"00080068", "CSPresentation Intent Type"}, +// {"00080070", "LOManufacturer"}, +// {"00080080", "LOInstitution Name"}, +// {"00080081", "STInstitution Address"}, +// {"00080082", "SQInstitution Code Sequence"}, +// {"00080090", "PNReferring Physician's Name"}, +// {"00080092", "STReferring Physician's Address"}, +// {"00080094", "SHReferring Physician's Telephone Numbers"}, +// {"00080096", "SQReferring Physician Identification Sequence"}, +// {"00080100", "SHCode Value"}, +// {"00080102", "SHCoding Scheme Designator"}, +// {"00080103", "SHCoding Scheme Version"}, +// {"00080104", "LOCode Meaning"}, +// {"00080201", "SHTimezone Offset From UTC"}, +// {"00081010", "SHStation Name"}, +// {"00081030", "LOStudy Description"}, +// {"00081032", "SQProcedure Code Sequence"}, +// {"0008103E", "LOSeries Description"}, +// {"00081040", "LOInstitutional Department Name"}, +// {"00081048", "PNPhysician(s) of Record"}, +// {"00081050", "PNPerforming Physician's Name"}, +// {"00081060", "PNName of Physician(s) Reading Study"}, +// {"00081070", "PNOperator's Name"}, +// {"00081080", "LOAdmitting Diagnoses Description"}, +// {"00081084", "SQAdmitting Diagnoses Code Sequence"}, +// {"00081090", "LOManufacturer's Model Name"}, +// {"00081100", "SQReferenced Results Sequence"}, +// {"00081110", "SQReferenced Study Sequence"}, +// {"00081111", "SQReferenced Performed Procedure Step Sequence"}, +// {"00081115", "SQReferenced Series Sequence"}, +// {"00081120", "SQReferenced Patient Sequence"}, +// {"00081125", "SQReferenced Visit Sequence"}, +// {"00081130", "SQReferenced Overlay Sequence"}, +// {"00081140", "SQReferenced Image Sequence"}, +// {"00081145", "SQReferenced Curve Sequence"}, +// {"00081150", "UIReferenced SOP Class UID"}, +// {"00081155", "UIReferenced SOP Instance UID"}, +// {"00082111", "STDerivation Description"}, +// {"00082112", "SQSource Image Sequence"}, +// {"00082120", "SHStage Name"}, +// {"00082122", "ISStage Number"}, +// {"00082124", "ISNumber of Stages"}, +// {"00082129", "ISNumber of Event Timers"}, +// {"00082128", "ISView Number"}, +// {"0008212A", "ISNumber of Views in Stage"}, +// {"00082130", "DSEvent Elapsed Time(s)"}, +// {"00082132", "LOEvent Timer Name(s)"}, +// {"00082142", "ISStart Trim"}, +// {"00082143", "ISStop Trim"}, +// {"00082144", "ISRecommended Display Frame Rate"}, +// {"00082200", "CSTransducer Position"}, +// {"00082204", "CSTransducer Orientation"}, +// {"00082208", "CSAnatomic Structure"}, +// +// {"00100010", "PNPatient's Name"}, +// {"00100020", "LOPatient ID"}, +// {"00100021", "LOIssuer of Patient ID"}, +// {"00100022", "CSType of Patient ID"}, +// {"00100030", "DAPatient's Birth Date"}, +// {"00100032", "TMPatient's Birth Time"}, +// {"00100040", "CSPatient's Sex"}, +// {"00100050", "SQPatient's Insurance Plan Code Sequence"}, +// {"00100101", "SQPatient's Primary Language Code Sequence"}, +// {"00100102", "SQPatient's Primary Language Modifier Code Sequence"}, +// {"00101000", "LOOther Patient IDs"}, +// {"00101001", "PNOther Patient Names"}, +// {"00101005", "PNPatient's Birth Name"}, +// {"00101010", "ASPatient's Age"}, +// {"00101020", "DSPatient's Size"}, +// {"00101030", "DSPatient's Weight"}, +// {"00101040", "LOPatient's Address"}, +// {"00101050", "LOInsurance Plan Identification"}, +// {"00102000", "LOMedical Alerts"}, +// {"00102110", "LOAllergies"}, +// {"00102150", "LOCountry of Residence"}, +// {"00102152", "LORegion of Residence"}, +// {"00102154", "SHPatient's Telephone Numbers"}, +// {"00102160", "SHEthnic Group"}, +// {"00102180", "SHOccupation"}, +// {"001021A0", "CSSmoking Status"}, +// {"001021B0", "LTAdditional Patient History"}, +// {"00102201", "LOPatient Species Description"}, +// {"00102203", "CSPatient Sex Neutered"}, +// {"00102292", "LOPatient Breed Description"}, +// {"00102297", "PNResponsible Person"}, +// {"00102298", "CSResponsible Person Role"}, +// {"00102299", "CSResponsible Organization"}, +// {"00104000", "LTPatient Comments"}, +// +// {"00180010", "LOContrast/Bolus Agent"}, +// {"00180015", "CSBody Part Examined"}, +// {"00180020", "CSScanning Sequence"}, +// {"00180021", "CSSequence Variant"}, +// {"00180022", "CSScan Options"}, +// {"00180023", "CSMR Acquisition Type"}, +// {"00180024", "SHSequence Name"}, +// {"00180025", "CSAngio Flag"}, +// {"00180030", "LORadionuclide"}, +// {"00180031", "LORadiopharmaceutical"}, +// {"00180032", "DSEnergy Window Centerline"}, +// {"00180033", "DSEnergy Window Total Width"}, +// {"00180034", "LOIntervention Drug Name"}, +// {"00180035", "TMIntervention Drug Start Time"}, +// {"00180040", "ISCine Rate"}, +// {"00180050", "DSSlice Thickness"}, +// {"00180060", "DSKVP"}, +// {"00180070", "ISCounts Accumulated"}, +// {"00180071", "CSAcquisition Termination Condition"}, +// {"00180072", "DSEffective Duration"}, +// {"00180073", "CSAcquisition Start Condition"}, +// {"00180074", "ISAcquisition Start Condition Data"}, +// {"00180075", "ISAcquisition Termination Condition Data"}, +// {"00180080", "DSRepetition Time"}, +// {"00180081", "DSEcho Time"}, +// {"00180082", "DSInversion Time"}, +// {"00180083", "DSNumber of Averages"}, +// {"00180084", "DSImaging Frequency"}, +// {"00180085", "SHImaged Nucleus"}, +// {"00180086", "ISEcho Numbers(s)"}, +// {"00180087", "DSMagnetic Field Strength"}, +// {"00180088", "DSSpacing Between Slices"}, +// {"00180089", "ISNumber of Phase Encoding Steps"}, +// {"00180090", "DSData Collection Diameter"}, +// {"00180091", "ISEcho Train Length"}, +// {"00180093", "DSPercent Sampling"}, +// {"00180094", "DSPercent Phase Field of View"}, +// {"00180095", "DSPixel Bandwidth"}, +// {"00181000", "LODevice Serial Number"}, +// {"00181004", "LOPlate ID"}, +// {"00181010", "LOSecondary Capture Device ID"}, +// {"00181012", "DADate of Secondary Capture"}, +// {"00181014", "TMTime of Secondary Capture"}, +// {"00181016", "LOSecondary Capture Device Manufacturer"}, +// {"00181018", "LOSecondary Capture Device Manufacturer's Model Name"}, +// {"00181019", "LOSecondary Capture Device Software Versions"}, +// {"00181020", "LOSoftware Versions(s)"}, +// {"00181022", "SHVideo Image Format Acquired"}, +// {"00181023", "LODigital Image Format Acquired"}, +// {"00181030", "LOProtocol Name"}, +// {"00181040", "LOContrast/Bolus Route"}, +// {"00181041", "DSContrast/Bolus Volume"}, +// {"00181042", "TMContrast/Bolus Start Time"}, +// {"00181043", "TMContrast/Bolus Stop Time"}, +// {"00181044", "DSContrast/Bolus Total Dose"}, +// {"00181045", "ISSyringe Counts"}, +// {"00181050", "DSSpatial Resolution"}, +// {"00181060", "DSTrigger Time"}, +// {"00181061", "LOTrigger Source or Type"}, +// {"00181062", "ISNominal Interval"}, +// {"00181063", "DSFrame Time"}, +// {"00181064", "LOCardiac Framing Type"}, +// {"00181065", "DSFrame Time Vector"}, +// {"00181066", "DSFrame Delay"}, +// {"00181070", "LORadiopharmaceutical Route"}, +// {"00181071", "DSRadiopharmaceutical Volume"}, +// {"00181072", "TMRadiopharmaceutical Start Time"}, +// {"00181073", "TMRadiopharmaceutical Stop Time"}, +// {"00181074", "DSRadionuclide Total Dose"}, +// {"00181075", "DSRadionuclide Half Life"}, +// {"00181076", "DSRadionuclide Positron Fraction"}, +// {"00181080", "CSBeat Rejection Flag"}, +// {"00181081", "ISLow R-R Value"}, +// {"00181082", "ISHigh R-R Value"}, +// {"00181083", "ISIntervals Acquired"}, +// {"00181084", "ISIntervals Rejected"}, +// {"00181085", "LOPVC Rejection"}, +// {"00181086", "ISSkip Beats"}, +// {"00181088", "ISHeart Rate"}, +// {"00181090", "ISCardiac Number of Images"}, +// {"00181094", "ISTrigger Window"}, +// {"00181100", "DSReconstruction Diameter"}, +// {"00181110", "DSDistance Source to Detector"}, +// {"00181111", "DSDistance Source to Patient"}, +// {"00181120", "DSGantry/Detector Tilt"}, +// {"00181130", "DSTable Height"}, +// {"00181131", "DSTable Traverse"}, +// {"00181140", "CSRotation Direction"}, +// {"00181141", "DSAngular Position"}, +// {"00181142", "DSRadial Position"}, +// {"00181143", "DSScan Arc"}, +// {"00181144", "DSAngular Step"}, +// {"00181145", "DSCenter of Rotation Offset"}, +// {"00181146", "DSRotation Offset"}, +// {"00181147", "CSField of View Shape"}, +// {"00181149", "ISField of View Dimensions(s)"}, +// {"00181150", "ISExposure Time"}, +// {"00181151", "ISX-ray Tube Current"}, +// {"00181152", "ISExposure"}, +// {"00181153", "ISExposure in uAs"}, +// {"00181154", "DSAverage Pulse Width"}, +// {"00181155", "CSRadiation Setting"}, +// {"00181156", "CSRectification Type"}, +// {"0018115A", "CSRadiation Mode"}, +// {"0018115E", "DSImage and Fluoroscopy Area Dose Product"}, +// {"00181160", "SHFilter Type"}, +// {"00181161", "LOType of Filters"}, +// {"00181162", "DSIntensifier Size"}, +// {"00181164", "DSImager Pixel Spacing"}, +// {"00181166", "CSGrid"}, +// {"00181170", "ISGenerator Power"}, +// {"00181180", "SHCollimator/grid Name"}, +// {"00181181", "CSCollimator Type"}, +// {"00181182", "ISFocal Distance"}, +// {"00181183", "DSX Focus Center"}, +// {"00181184", "DSY Focus Center"}, +// {"00181190", "DSFocal Spot(s)"}, +// {"00181191", "CSAnode Target Material"}, +// {"001811A0", "DSBody Part Thickness"}, +// {"001811A2", "DSCompression Force"}, +// {"00181200", "DADate of Last Calibration"}, +// {"00181201", "TMTime of Last Calibration"}, +// {"00181210", "SHConvolution Kernel"}, +// {"00181242", "ISActual Frame Duration"}, +// {"00181243", "ISCount Rate"}, +// {"00181250", "SHReceive Coil Name"}, +// {"00181251", "SHTransmit Coil Name"}, +// {"00181260", "SHPlate Type"}, +// {"00181261", "LOPhosphor Type"}, +// {"00181300", "ISScan Velocity"}, +// {"00181301", "CSWhole Body Technique"}, +// {"00181302", "ISScan Length"}, +// {"00181310", "USAcquisition Matrix"}, +// {"00181312", "CSIn-plane Phase Encoding Direction"}, +// {"00181314", "DSFlip Angle"}, +// {"00181315", "CSVariable Flip Angle Flag"}, +// {"00181316", "DSSAR"}, +// {"00181318", "DSdB/dt"}, +// {"00181400", "LOAcquisition Device Processing Description"}, +// {"00181401", "LOAcquisition Device Processing Code"}, +// {"00181402", "CSCassette Orientation"}, +// {"00181403", "CSCassette Size"}, +// {"00181404", "USExposures on Plate"}, +// {"00181405", "ISRelative X-Ray Exposure"}, +// {"00181450", "CSColumn Angulation"}, +// {"00181500", "CSPositioner Motion"}, +// {"00181508", "CSPositioner Type"}, +// {"00181510", "DSPositioner Primary Angle"}, +// {"00181511", "DSPositioner Secondary Angle"}, +// {"00181520", "DSPositioner Primary Angle Increment"}, +// {"00181521", "DSPositioner Secondary Angle Increment"}, +// {"00181530", "DSDetector Primary Angle"}, +// {"00181531", "DSDetector Secondary Angle"}, +// {"00181600", "CSShutter Shape"}, +// {"00181602", "ISShutter Left Vertical Edge"}, +// {"00181604", "ISShutter Right Vertical Edge"}, +// {"00181606", "ISShutter Upper Horizontal Edge"}, +// {"00181608", "ISShutter Lower Horizontal Edge"}, +// {"00181610", "ISCenter of Circular Shutter"}, +// {"00181612", "ISRadius of Circular Shutter"}, +// {"00181620", "ISVertices of the Polygonal Shutter"}, +// {"00181700", "ISCollimator Shape"}, +// {"00181702", "ISCollimator Left Vertical Edge"}, +// {"00181704", "ISCollimator Right Vertical Edge"}, +// {"00181706", "ISCollimator Upper Horizontal Edge"}, +// {"00181708", "ISCollimator Lower Horizontal Edge"}, +// {"00181710", "ISCenter of Circular Collimator"}, +// {"00181712", "ISRadius of Circular Collimator"}, +// {"00181720", "ISVertices of the Polygonal Collimator"}, +// {"00185000", "SHOutput Power"}, +// {"00185010", "LOTransducer Data"}, +// {"00185012", "DSFocus Depth"}, +// {"00185020", "LOProcessing Function"}, +// {"00185021", "LOPostprocessing Function"}, +// {"00185022", "DSMechanical Index"}, +// {"00185024", "DSBone Thermal Index"}, +// {"00185026", "DSCranial Thermal Index"}, +// {"00185027", "DSSoft Tissue Thermal Index"}, +// {"00185028", "DSSoft Tissue-focus Thermal Index"}, +// {"00185029", "DSSoft Tissue-surface Thermal Index"}, +// {"00185050", "ISDepth of Scan Field"}, +// {"00185100", "CSPatient Position"}, +// {"00185101", "CSView Position"}, +// {"00185104", "SQProjection Eponymous Name Code Sequence"}, +// {"00185210", "DSImage Transformation Matrix"}, +// {"00185212", "DSImage Translation Vector"}, +// {"00186000", "DSSensitivity"}, +// {"00186011", "SQSequence of Ultrasound Regions"}, +// {"00186012", "USRegion Spatial Format"}, +// {"00186014", "USRegion Data Type"}, +// {"00186016", "ULRegion Flags"}, +// {"00186018", "ULRegion Location Min X0"}, +// {"0018601A", "ULRegion Location Min Y0"}, +// {"0018601C", "ULRegion Location Max X1"}, +// {"0018601E", "ULRegion Location Max Y1"}, +// {"00186020", "SLReference Pixel X0"}, +// {"00186022", "SLReference Pixel Y0"}, +// {"00186024", "USPhysical Units X Direction"}, +// {"00186026", "USPhysical Units Y Direction"}, +// {"00181628", "FDReference Pixel Physical Value X"}, +// {"0018602A", "FDReference Pixel Physical Value Y"}, +// {"0018602C", "FDPhysical Delta X"}, +// {"0018602E", "FDPhysical Delta Y"}, +// {"00186030", "ULTransducer Frequency"}, +// {"00186031", "CSTransducer Type"}, +// {"00186032", "ULPulse Repetition Frequency"}, +// {"00186034", "FDDoppler Correction Angle"}, +// {"00186036", "FDSteering Angle"}, +// {"00186038", "ULDoppler Sample Volume X Position (Retired)"}, +// {"00186039", "SLDoppler Sample Volume X Position"}, +// {"0018603A", "ULDoppler Sample Volume Y Position (Retired)"}, +// {"0018603B", "SLDoppler Sample Volume Y Position"}, +// {"0018603C", "ULTM-Line Position X0 (Retired)"}, +// {"0018603D", "SLTM-Line Position X0"}, +// {"0018603E", "ULTM-Line Position Y0 (Retired)"}, +// {"0018603F", "SLTM-Line Position Y0"}, +// {"00186040", "ULTM-Line Position X1 (Retired)"}, +// {"00186041", "SLTM-Line Position X1"}, +// {"00186042", "ULTM-Line Position Y1 (Retired)"}, +// {"00186043", "SLTM-Line Position Y1"}, +// {"00186044", "USPixel Component Organization"}, +// {"00186046", "ULPixel Component Mask"}, +// {"00186048", "ULPixel Component Range Start"}, +// {"0018604A", "ULPixel Component Range Stop"}, +// {"0018604C", "USPixel Component Physical Units"}, +// {"0018604E", "USPixel Component Data Type"}, +// {"00186050", "ULNumber of Table Break Points"}, +// {"00186052", "ULTable of X Break Points"}, +// {"00186054", "FDTable of Y Break Points"}, +// {"00186056", "ULNumber of Table Entries"}, +// {"00186058", "ULTable of Pixel Values"}, +// {"0018605A", "ULTable of Parameter Values"}, +// {"00187000", "CSDetector Conditions Nominal Flag"}, +// {"00187001", "DSDetector Temperature"}, +// {"00187004", "CSDetector Type"}, +// {"00187005", "CSDetector Configuration"}, +// {"00187006", "LTDetector Description"}, +// {"00187008", "LTDetector Mode"}, +// {"0018700A", "SHDetector ID"}, +// {"0018700C", "DADate of Last Detector Calibration"}, +// {"0018700E", "TMTime of Last Detector Calibration"}, +// {"00187010", "ISExposures on Detector Since Last Calibration"}, +// {"00187011", "ISExposures on Detector Since Manufactured"}, +// {"00187012", "DSDetector Time Since Last Exposure"}, +// {"00187014", "DSDetector Active Time"}, +// {"00187016", "DSDetector Activation Offset From Exposure"}, +// {"0018701A", "DSDetector Binning"}, +// {"00187020", "DSDetector Element Physical Size"}, +// {"00187022", "DSDetector Element Spacing"}, +// {"00187024", "CSDetector Active Shape"}, +// {"00187026", "DSDetector Active Dimension(s)"}, +// {"00187028", "DSDetector Active Origin"}, +// {"00187030", "DSField of View Origin"}, +// {"00187032", "DSField of View Rotation"}, +// {"00187034", "CSField of View Horizontal Flip"}, +// {"00187040", "LTGrid Absorbing Material"}, +// {"00187041", "LTGrid Spacing Material"}, +// {"00187042", "DSGrid Thickness"}, +// {"00187044", "DSGrid Pitch"}, +// {"00187046", "ISGrid Aspect Ratio"}, +// {"00187048", "DSGrid Period"}, +// {"0018704C", "DSGrid Focal Distance"}, +// {"00187050", "LTFilter Material"}, +// {"00187052", "DSFilter Thickness Minimum"}, +// {"00187054", "DSFilter Thickness Maximum"}, +// {"00187060", "CSExposure Control Mode"}, +// {"00187062", "LTExposure Control Mode Description"}, +// {"00187064", "CSExposure Status"}, +// {"00187065", "DSPhototimer Setting"}, +// +// {"0020000D", "UIStudy Instance UID"}, +// {"0020000E", "UISeries Instance UID"}, +// {"00200010", "SHStudy ID"}, +// {"00200011", "ISSeries Number"}, +// {"00200012", "ISAcquisition Number"}, +// {"00200013", "ISInstance Number"}, +// {"00200014", "ISIsotope Number"}, +// {"00200015", "ISPhase Number"}, +// {"00200016", "ISInterval Number"}, +// {"00200017", "ISTime Slot Number"}, +// {"00200018", "ISAngle Number"}, +// {"00200020", "CSPatient Orientation"}, +// {"00200022", "USOverlay Number"}, +// {"00200024", "USCurve Number"}, +// {"00200030", "DSImage Position"}, +// {"00200032", "DSImage Position (Patient)"}, +// {"00200037", "DSImage Orientation (Patient)"}, +// {"00200050", "DSLocation"}, +// {"00200052", "UIFrame of Reference UID"}, +// {"00200060", "CSLaterality"}, +// {"00200070", "LOImage Geometry Type"}, +// {"00200080", "UIMasking Image"}, +// {"00200100", "ISTemporal Position Identifier"}, +// {"00200105", "ISNumber of Temporal Positions"}, +// {"00200110", "DSTemporal Resolution"}, +// {"00201000", "ISSeries in Study"}, +// {"00201002", "ISImages in Acquisition"}, +// {"00201004", "ISAcquisitions in Study"}, +// {"00201040", "LOPosition Reference Indicator"}, +// {"00201041", "DSSlice Location"}, +// {"00201070", "ISOther Study Numbers"}, +// {"00201200", "ISNumber of Patient Related Studies"}, +// {"00201202", "ISNumber of Patient Related Series"}, +// {"00201204", "ISNumber of Patient Related Instances"}, +// {"00201206", "ISNumber of Study Related Series"}, +// {"00201208", "ISNumber of Study Related Instances"}, +// {"00204000", "LTImage Comments"}, +// +// {"00280002", "USSamples per Pixel"}, +// {"00280004", "CSPhotometric Interpretation"}, +// {"00280006", "USPlanar Configuration"}, +// {"00280008", "ISNumber of Frames"}, +// {"00280009", "ATFrame Increment Pointer"}, +// {"00280010", "USRows"}, +// {"00280011", "USColumns"}, +// {"00280030", "DSPixel Spacing"}, +// {"00280031", "DSZoom Factor"}, +// {"00280032", "DSZoom Center"}, +// {"00280034", "ISPixel Aspect Ratio"}, +// {"00280051", "CSCorrected Image"}, +// {"00280100", "USBits Allocated"}, +// {"00280101", "USBits Stored"}, +// {"00280102", "USHigh Bit"}, +// {"00280103", "USPixel Representation"}, +// {"00280106", "USSmallest Image Pixel Value"}, +// {"00280107", "USLargest Image Pixel Value"}, +// {"00280108", "USSmallest Pixel Value in Series"}, +// {"00280109", "USLargest Pixel Value in Series"}, +// {"00280120", "USPixel Padding Value"}, +// {"00280300", "CSQuality Control Image"}, +// {"00280301", "CSBurned In Annotation"}, +// {"00281040", "CSPixel Intensity Relationship"}, +// {"00281041", "SSPixel Intensity Relationship Sign"}, +// {"00281050", "DSWindow Center"}, +// {"00281051", "DSWindow Width"}, +// {"00281052", "DSRescale Intercept"}, +// {"00281053", "DSRescale Slope"}, +// {"00281054", "LORescale Type"}, +// {"00281055", "LOWindow Center & Width Explanation"}, +// {"00281101", "USRed Palette Color Lookup Table Descriptor"}, +// {"00281102", "USGreen Palette Color Lookup Table Descriptor"}, +// {"00281103", "USBlue Palette Color Lookup Table Descriptor"}, +// {"00281104", "USAlpha Palette Color Lookup Table Descriptor"}, +// {"00281201", "OWRed Palette Color Lookup Table Data"}, +// {"00281202", "OWGreen Palette Color Lookup Table Data"}, +// {"00281203", "OWBlue Palette Color Lookup Table Data"}, +// {"00281204", "OWAlpha Palette Color Lookup Table Data"}, +// {"00282110", "CSLossy Image Compression"}, +// {"00283000", "SQModality LUT Sequence"}, +// {"00283002", "USLUT Descriptor"}, +// {"00283003", "LOLUT Explanation"}, +// {"00283004", "LOModality LUT Type"}, +// {"00283006", "USLUT Data"}, +// {"00283010", "SQVOI LUT Sequence"}, +// +// {"0032000A", "CSStudy Status ID"}, +// {"0032000C", "CSStudy Priority ID"}, +// {"00320012", "LOStudy ID Issuer"}, +// {"00320032", "DAStudy Verified Date"}, +// {"00320033", "TMStudy Verified Time"}, +// {"00320034", "DAStudy Read Date"}, +// {"00320035", "TMStudy Read Time"}, +// {"00321000", "DAScheduled Study Start Date"}, +// {"00321001", "TMScheduled Study Start Time"}, +// {"00321010", "DAScheduled Study Stop Date"}, +// {"00321011", "TMScheduled Study Stop Time"}, +// {"00321020", "LOScheduled Study Location"}, +// {"00321021", "AEScheduled Study Location AE Title"}, +// {"00321030", "LOReason for Study"}, +// {"00321032", "PNRequesting Physician"}, +// {"00321033", "LORequesting Service"}, +// {"00321040", "DAStudy Arrival Date"}, +// {"00321041", "TMStudy Arrival Time"}, +// {"00321050", "DAStudy Completion Date"}, +// {"00321051", "TMStudy Completion Time"}, +// {"00321055", "CSStudy Component Status ID"}, +// {"00321060", "LORequested Procedure Description"}, +// {"00321064", "SQRequested Procedure Code Sequence"}, +// {"00321070", "LORequested Contrast Agent"}, +// {"00324000", "LTStudy Comments"}, +// +// {"00400001", "AEScheduled Station AE Title"}, +// {"00400002", "DAScheduled Procedure Step Start Date"}, +// {"00400003", "TMScheduled Procedure Step Start Time"}, +// {"00400004", "DAScheduled Procedure Step End Date"}, +// {"00400005", "TMScheduled Procedure Step End Time"}, +// {"00400006", "PNScheduled Performing Physician's Name"}, +// {"00400007", "LOScheduled Procedure Step Description"}, +// {"00400008", "SQScheduled Protocol Code Sequence"}, +// {"00400009", "SHScheduled Procedure Step ID"}, +// {"00400010", "SHScheduled Station Name"}, +// {"00400011", "SHScheduled Procedure Step Location"}, +// {"00400012", "LOPre-Medication"}, +// {"00400020", "CSScheduled Procedure Step Status"}, +// {"00400100", "SQScheduled Procedure Step Sequence"}, +// {"00400220", "SQReferenced Non-Image Composite SOP Instance Sequence"}, +// {"00400241", "AEPerformed Station AE Title"}, +// {"00400242", "SHPerformed Station Name"}, +// {"00400243", "SHPerformed Location"}, +// {"00400244", "DAPerformed Procedure Step Start Date"}, +// {"00400245", "TMPerformed Procedure Step Start Time"}, +// {"00400250", "DAPerformed Procedure Step End Date"}, +// {"00400251", "TMPerformed Procedure Step End Time"}, +// {"00400252", "CSPerformed Procedure Step Status"}, +// {"00400253", "SHPerformed Procedure Step ID"}, +// {"00400254", "LOPerformed Procedure Step Description"}, +// {"00400255", "LOPerformed Procedure Type Description"}, +// {"00400260", "SQPerformed Protocol Code Sequence"}, +// {"00400270", "SQScheduled Step Attributes Sequence"}, +// {"00400275", "SQRequest Attributes Sequence"}, +// {"00400280", "STComments on the Performed Procedure Step"}, +// {"00400293", "SQQuantity Sequence"}, +// {"00400294", "DSQuantity"}, +// {"00400295", "SQMeasuring Units Sequence"}, +// {"00400296", "SQBilling Item Sequence"}, +// {"00400300", "USTotal Time of Fluoroscopy"}, +// {"00400301", "USTotal Number of Exposures"}, +// {"00400302", "USEntrance Dose"}, +// {"00400303", "USExposed Area"}, +// {"00400306", "DSDistance Source to Entrance"}, +// {"00400307", "DSDistance Source to Support"}, +// {"00400310", "STComments on Radiation Dose"}, +// {"00400312", "DSX-Ray Output"}, +// {"00400314", "DSHalf Value Layer"}, +// {"00400316", "DSOrgan Dose"}, +// {"00400318", "CSOrgan Exposed"}, +// {"00400320", "SQBilling Procedure Step Sequence"}, +// {"00400321", "SQFilm Consumption Sequence"}, +// {"00400324", "SQBilling Supplies and Devices Sequence"}, +// {"00400330", "SQReferenced Procedure Step Sequence"}, +// {"00400340", "SQPerformed Series Sequence"}, +// {"00400400", "LTComments on the Scheduled Procedure Step"}, +// {"0040050A", "LOSpecimen Accession Number"}, +// {"00400550", "SQSpecimen Sequence"}, +// {"00400551", "LOSpecimen Identifier"}, +// {"00400555", "SQAcquisition Context Sequence"}, +// {"00400556", "STAcquisition Context Description"}, +// {"0040059A", "SQSpecimen Type Code Sequence"}, +// {"004006FA", "LOSlide Identifier"}, +// {"0040071A", "SQImage Center Point Coordinates Sequence"}, +// {"0040072A", "DSX Offset in Slide Coordinate System"}, +// {"0040073A", "DSY Offset in Slide Coordinate System"}, +// {"0040074A", "DSZ Offset in Slide Coordinate System"}, +// {"004008D8", "SQPixel Spacing Sequence"}, +// {"004008DA", "SQCoordinate System Axis Code Sequence"}, +// {"004008EA", "SQMeasurement Units Code Sequence"}, +// {"00401001", "SHRequested Procedure ID"}, +// {"00401002", "LOReason for the Requested Procedure"}, +// {"00401003", "SHRequested Procedure Priority"}, +// {"00401004", "LOPatient Transport Arrangements"}, +// {"00401005", "LORequested Procedure Location"}, +// {"00401006", "SHPlacer Order Number / Procedure"}, +// {"00401007", "SHFiller Order Number / Procedure"}, +// {"00401008", "LOConfidentiality Code"}, +// {"00401009", "SHReporting Priority"}, +// {"00401010", "PNNames of Intended Recipients of Results"}, +// {"00401400", "LTRequested Procedure Comments"}, +// {"00402001", "LOReason for the Imaging Service Request"}, +// {"00402004", "DAIssue Date of Imaging Service Request"}, +// {"00402005", "TMIssue Time of Imaging Service Request"}, +// {"00402006", "SHPlacer Order Number / Imaging Service Request (Retired)"}, +// {"00402007", "SHFiller Order Number / Imaging Service Request (Retired)"}, +// {"00402008", "PNOrder Entered By"}, +// {"00402009", "SHOrder Enterer's Location"}, +// {"00402010", "SHOrder Callback Phone Number"}, +// {"00402016", "LOPlacer Order Number / Imaging Service Request"}, +// {"00402017", "LOFiller Order Number / Imaging Service Request"}, +// {"00402400", "LTImaging Service Request Comments"}, +// {"00403001", "LOConfidentiality Constraint on Patient Data Description"}, +// {"00408302", "DSEntrance Dose in mGy"}, +// {"0040A010", "CSRelationship Type"}, +// {"0040A027", "LOVerifying Organization"}, +// {"0040A030", "DTVerification Date Time"}, +// {"0040A032", "DTObservation Date Time"}, +// {"0040A040", "CSValue Type"}, +// {"0040A043", "SQConcept Name Code Sequence"}, +// {"0040A050", "CSContinuity Of Content"}, +// {"0040A073", "SQVerifying Observer Sequence"}, +// {"0040A075", "PNVerifying Observer Name"}, +// {"0040A088", "SQVerifying Observer Identification Code Sequence"}, +// {"0040A0B0", "USReferenced Waveform Channels"}, +// {"0040A120", "DTDateTime"}, +// {"0040A121", "DADate"}, +// {"0040A122", "TMTime"}, +// {"0040A123", "PNPerson Name"}, +// {"0040A124", "UIUID"}, +// {"0040A130", "CSTemporal Range Type"}, +// {"0040A132", "ULReferenced Sample Positions"}, +// {"0040A136", "USReferenced Frame Numbers"}, +// {"0040A138", "DSReferenced Time Offsets"}, +// {"0040A13A", "DTReferenced DateTime"}, +// {"0040A160", "UTText Value"}, +// {"0040A168", "SQConcept Code Sequence"}, +// {"0040A180", "USAnnotation Group Number"}, +// {"0040A195", "SQModifier Code Sequence"}, +// {"0040A300", "SQMeasured Value Sequence"}, +// {"0040A30A", "DSNumeric Value"}, +// {"0040A360", "SQPredecessor Documents Sequence"}, +// {"0040A370", "SQReferenced Request Sequence"}, +// {"0040A372", "SQPerformed Procedure Code Sequence"}, +// {"0040A375", "SQCurrent Requested Procedure Evidence Sequence"}, +// {"0040A385", "SQPertinent Other Evidence Sequence"}, +// {"0040A491", "CSCompletion Flag"}, +// {"0040A492", "LOCompletion Flag Description"}, +// {"0040A493", "CSVerification Flag"}, +// {"0040A504", "SQContent Template Sequence"}, +// {"0040A525", "SQIdentical Documents Sequence"}, +// {"0040A730", "SQContent Sequence"}, +// {"0040B020", "SQWaveform Annotation Sequence"}, +// {"0040DB00", "CSTemplate Identifier"}, +// {"0040DB06", "DTTemplate Version"}, +// {"0040DB07", "DTTemplate Local Version"}, +// {"0040DB0B", "CSTemplate Extension Flag"}, +// {"0040DB0C", "UITemplate Extension Organization UID"}, +// {"0040DB0D", "UITemplate Extension Creator UID"}, +// {"0040DB73", "ULReferenced Content Item Identifier"}, +// +// {"00540011", "USNumber of Energy Windows"}, +// {"00540012", "SQEnergy Window Information Sequence"}, +// {"00540013", "SQEnergy Window Range Sequence"}, +// {"00540014", "DSEnergy Window Lower Limit"}, +// {"00540015", "DSEnergy Window Upper Limit"}, +// {"00540016", "SQRadiopharmaceutical Information Sequence"}, +// {"00540017", "ISResidual Syringe Counts"}, +// {"00540018", "SHEnergy Window Name"}, +// {"00540020", "USDetector Vector"}, +// {"00540021", "USNumber of Detectors"}, +// {"00540022", "SQDetector Information Sequence"}, +// {"00540030", "USPhase Vector"}, +// {"00540031", "USNumber of Phases"}, +// {"00540032", "SQPhase Information Sequence"}, +// {"00540033", "USNumber of Frames in Phase"}, +// {"00540036", "ISPhase Delay"}, +// {"00540038", "ISPause Between Frames"}, +// {"00540039", "CSPhase Description"}, +// {"00540050", "USRotation Vector"}, +// {"00540051", "USNumber of Rotations"}, +// {"00540052", "SQRotation Information Sequence"}, +// {"00540053", "USNumber of Frames in Rotation"}, +// {"00540060", "USR-R Interval Vector"}, +// {"00540061", "USNumber of R-R Intervals"}, +// {"00540062", "SQGated Information Sequence"}, +// {"00540063", "SQData Information Sequence"}, +// {"00540070", "USTime Slot Vector"}, +// {"00540071", "USNumber of Time Slots"}, +// {"00540072", "SQTime Slot Information Sequence"}, +// {"00540073", "DSTime Slot Time"}, +// {"00540080", "USSlice Vector"}, +// {"00540081", "USNumber of Slices"}, +// {"00540090", "USAngular View Vector"}, +// {"00540100", "USTime Slice Vector"}, +// {"00540101", "USNumber of Time Slices"}, +// {"00540200", "DSStart Angle"}, +// {"00540202", "CSType of Detector Motion"}, +// {"00540210", "ISTrigger Vector"}, +// {"00540211", "USNumber of Triggers in Phase"}, +// {"00540220", "SQView Code Sequence"}, +// {"00540222", "SQView Modifier Code Sequence"}, +// {"00540300", "SQRadionuclide Code Sequence"}, +// {"00540302", "SQAdministration Route Code Sequence"}, +// {"00540304", "SQRadiopharmaceutical Code Sequence"}, +// {"00540306", "SQCalibration Data Sequence"}, +// {"00540308", "USEnergy Window Number"}, +// {"00540400", "SHImage ID"}, +// {"00540410", "SQPatient Orientation Code Sequence"}, +// {"00540412", "SQPatient Orientation Modifier Code Sequence"}, +// {"00540414", "SQPatient Gantry Relationship Code Sequence"}, +// {"00540500", "CSSlice Progression Direction"}, +// {"00541000", "CSSeries Type"}, +// {"00541001", "CSUnits"}, +// {"00541002", "CSCounts Source"}, +// {"00541004", "CSReprojection Method"}, +// {"00541100", "CSRandoms Correction Method"}, +// {"00541101", "LOAttenuation Correction Method"}, +// {"00541102", "CSDecay Correction"}, +// {"00541103", "LOReconstruction Method"}, +// {"00541104", "LODetector Lines of Response Used"}, +// {"00541105", "LOScatter Correction Method"}, +// {"00541200", "DSAxial Acceptance"}, +// {"00541201", "ISAxial Mash"}, +// {"00541202", "ISTransverse Mash"}, +// {"00541203", "DSDetector Element Size"}, +// {"00541210", "DSCoincidence Window Width"}, +// {"00541220", "CSSecondary Counts Type"}, +// {"00541300", "DSFrame Reference Time"}, +// {"00541310", "ISPrimary (Prompts) Counts Accumulated"}, +// {"00541311", "ISSecondary Counts Accumulated"}, +// {"00541320", "DSSlice Sensitivity Factor"}, +// {"00541321", "DSDecay Factor"}, +// {"00541322", "DSDose Calibration Factor"}, +// {"00541323", "DSScatter Fraction Factor"}, +// {"00541324", "DSDead Time Factor"}, +// {"00541330", "USImage Index"}, +// {"00541400", "CSCounts Included"}, +// {"00541401", "CSDead Time Correction Flag"}, +// +// {"20300010", "USAnnotation Position"}, +// {"20300020", "LOText String"}, +// +// {"20500010", "SQPresentation LUT Sequence"}, +// {"20500020", "CSPresentation LUT Shape"}, +// {"20500500", "SQReferenced Presentation LUT Sequence"}, +// +// {"30020002", "SHRT Image Label"}, +// {"30020003", "LORT Image Name"}, +// {"30020004", "STRT Image Description"}, +// {"3002000A", "CSReported Values Origin"}, +// {"3002000C", "CSRT Image Plane"}, +// {"3002000D", "DSX-Ray Image Receptor Translation"}, +// {"3002000E", "DSX-Ray Image Receptor Angle"}, +// {"30020010", "DSRT Image Orientation"}, +// {"30020011", "DSImage Plane Pixel Spacing"}, +// {"30020012", "DSRT Image Position"}, +// {"30020020", "SHRadiation Machine Name"}, +// {"30020022", "DSRadiation Machine SAD"}, +// {"30020024", "DSRadiation Machine SSD"}, +// {"30020026", "DSRT Image SID"}, +// {"30020028", "DSSource to Reference Object Distance"}, +// {"30020029", "ISFraction Number"}, +// {"30020030", "SQExposure Sequence"}, +// {"30020032", "DSMeterset Exposure"}, +// {"30020034", "DSDiaphragm Position"}, +// {"30020040", "SQFluence Map Sequence"}, +// {"30020041", "CSFluence Data Source"}, +// {"30020042", "DSFluence Data Scale"}, +// +// {"30040001", "CSDVH Type"}, +// {"30040002", "CSDose Units"}, +// {"30040004", "CSDose Type"}, +// {"30040006", "LODose Comment"}, +// {"30040008", "DSNormalization Point"}, +// {"3004000A", "CSDose Summation Type"}, +// {"3004000C", "DSGrid Frame Offset Vector"}, +// {"3004000E", "DSDose Grid Scaling"}, +// {"30040010", "SQRT Dose ROI Sequence"}, +// {"30040012", "DSDose Value"}, +// {"30040014", "CSTissue Heterogeneity Correction"}, +// {"30040040", "DSDVH Normalization Point"}, +// {"30040042", "DSDVH Normalization Dose Value"}, +// {"30040050", "SQDVH Sequence"}, +// {"30040052", "DSDVH Dose Scaling"}, +// {"30040054", "CSDVH Volume Units"}, +// {"30040056", "ISDVH Number of Bins"}, +// {"30040058", "DSDVH Data"}, +// {"30040060", "SQDVH Referenced ROI Sequence"}, +// {"30040062", "CSDVH ROI Contribution Type"}, +// {"30040070", "DSDVH Minimum Dose"}, +// {"30040072", "DSDVH Maximum Dose"}, +// {"30040074", "DSDVH Mean Dose"}, +// +// {"300A00B3", "CSPrimary Dosimeter Unit"}, +// {"300A00F0", "ISNumber of Blocks"}, +// {"300A011E", "DSGantry Angle"}, +// {"300A0120", "DSBeam Limiting Device Angle"}, +// {"300A0122", "DSPatient Support Angle"}, +// {"300A0128", "DSTable Top Vertical Position"}, +// {"300A0129", "DSTable Top Longitudinal Position"}, +// {"300A012A", "DSTable Top Lateral Position"}, +// +// {"300C0006", "ISReferenced Beam Number"}, +// {"300C0008", "DSStart Cumulative Meterset Weight"}, +// {"300C0022", "ISReferenced Fraction Group Number"}, +// +// {"7FE00010", "OXPixel Data"}, // Represents OB or OW type of VR +// +// {"FFFEE000", "DLItem"}, +// {"FFFEE00D", "DLItem Delimitation Item"}, +// {"FFFEE0DD", "DLSequence Delimitation Item"} +// }; +// } +// } \ No newline at end of file diff --git a/DicomTool/Utils/Global.cs b/DicomTool/Utils/Global.cs new file mode 100644 index 0000000..b1871db --- /dev/null +++ b/DicomTool/Utils/Global.cs @@ -0,0 +1,24 @@ +using System.Configuration; + +namespace DicomTool.Utils +{ + internal class Global + { + /// + /// 返回*.exe.cdddonfig文件中appSettings配置节的value项 + /// + /// + /// + public static string GetAppConfig(string key) + { + foreach (string str in ConfigurationManager.AppSettings) + { + if (str == key) + { + return ConfigurationManager.AppSettings[key]; + } + } + return null; + } + } +} \ No newline at end of file diff --git a/DicomTool/Utils/ImageControl.cs b/DicomTool/Utils/ImageControl.cs new file mode 100644 index 0000000..064b02f --- /dev/null +++ b/DicomTool/Utils/ImageControl.cs @@ -0,0 +1,365 @@ +// using System; +// using System.Collections.Generic; +// using System.Drawing; +// using System.Drawing.Drawing2D; +// using System.Drawing.Imaging; +// using System.Linq; +// +// namespace DICOMCoverter +// { +// public enum ImageBitsPerPixel { Eight, Sixteen, TwentyFour }; +// +// internal class ImageControl +// { +// private List pix8; +// private List pix16; +// private List pix24; +// private Bitmap bmp; +// +// // For Window Level +// private int winMin; +// +// private int winMax; +// private int winCentre; +// private int winWidth; +// +// private byte[] lut8; +// private byte[] lut16; +// +// //====================== +// private List pixels8; +// +// private List pixels16; +// private List pixels24; // 30 July 2010 +// +// /// +// /// 每一个像素的取样数,一般来说,CT,MR,DR等灰度图像都是1,而彩超等彩**图像都是3,分别表示R, G, B三个颜色通道。 +// /// +// // int samplesPerPixel; // Updated 30 July 2010 +// private double windowsCentre; +// +// private double windowsWidth; +// private int maxPixelValue; // Updated July 2012 +// private int minPixelValue; +// //===================== +// +// public ImageControl() +// { +// pix8 = new List(); +// pix16 = new List(); +// pix24 = new List(); +// winMin = 0; +// winMax = 65535; +// lut8 = new byte[256]; +// lut16 = new byte[65536]; +// //========================== +// pixels8 = new List(); +// pixels16 = new List(); +// pixels24 = new List(); +// maxPixelValue = 0; +// minPixelValue = 65535; +// //=========================== +// } +// +// /// +// /// 生成8位深度图 +// /// +// /// +// public void CreateImage8depth(DicomDecoder dd) +// { +// if (dd.samplesPerPixel == 1 && dd.bitsAllocated == 8) +// { +// windowsCentre = dd.windowCentre; +// windowsWidth = dd.windowWidth; +// pixels8.Clear(); +// pixels16.Clear(); +// pixels24.Clear(); +// dd.GetPixels8(ref pixels8); +// +// minPixelValue = pixels8.Min(); +// maxPixelValue = pixels8.Max(); +// +// if (dd.signedImage) +// { +// windowsCentre -= char.MinValue; +// } +// +// if (Math.Abs(windowsWidth) < 0.001) +// { +// windowsWidth = maxPixelValue - minPixelValue; +// } +// +// if ((windowsCentre == 0) || +// (minPixelValue > windowsCentre) || (maxPixelValue < windowsCentre)) +// { +// windowsCentre = (maxPixelValue + minPixelValue) / 2; +// } +// +// winWidth = Convert.ToInt32(windowsWidth); +// winCentre = Convert.ToInt32(windowsCentre); +// +// pix8 = pixels8; +// if (bmp != null) +// bmp.Dispose(); +// ResetValues(); +// ComputeLookUpTable8(); +// bmp = new Bitmap(dd.width, dd.height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); +// +// CreateImage8(dd.width, dd.height); +// } +// +// if (dd.samplesPerPixel == 3 && dd.bitsAllocated == 8) +// { +// windowsCentre = dd.windowCentre; +// windowsWidth = dd.windowWidth; +// winWidth = Convert.ToInt32(windowsWidth); +// winCentre = Convert.ToInt32(windowsCentre); +// pixels8.Clear(); +// pixels16.Clear(); +// pixels24.Clear(); +// dd.GetPixels8(ref pixels8); +// pix24 = pixels8; +// +// if (bmp != null) +// bmp.Dispose(); +// ResetValues(); +// ComputeLookUpTable8(); +// bmp = new Bitmap(dd.width, dd.height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); +// CreateImage24(dd.width, dd.height); +// } +// } +// +// /// +// /// 生成16位深度的图 +// /// +// /// +// public void CreateImage16Depth(DicomDecoder dd) +// { +// windowsWidth = dd.windowWidth; +// windowsCentre = dd.windowCentre; +// pixels16.Clear(); +// pixels8.Clear(); +// pixels24.Clear(); +// dd.GetPixels16(ref pixels16); +// +// minPixelValue = pixels16.Min(); +// maxPixelValue = pixels16.Max(); +// +// if (dd.signedImage) +// { +// windowsCentre -= short.MinValue; +// } +// +// if (Math.Abs(windowsWidth) < 0.001) +// { +// windowsWidth = maxPixelValue - minPixelValue; +// } +// +// if ((windowsCentre == 0) || +// (minPixelValue > windowsCentre) || (maxPixelValue < windowsCentre)) +// { +// windowsCentre = (maxPixelValue + minPixelValue) / 2; +// } +// +// winWidth = Convert.ToInt32(windowsWidth); +// winCentre = Convert.ToInt32(windowsCentre); +// +// pix16 = pixels16; +// if (bmp != null) +// bmp.Dispose(); +// ResetValues(); +// ComputeLookUpTable16(); +// bmp = new Bitmap(dd.width, dd.height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); +// CreateImage16(dd.width, dd.height); +// } +// +// // Create a bitmap on the fly, using 8-bit grayscale pixel data +// private void CreateImage8(int imgWidth, int imgHeight) +// { +// BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, imgWidth, imgHeight), +// System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat); +// +// unsafe +// { +// int pixelSize = 3; +// int i, j, j1; +// byte b; +// +// for (i = 0; i < bmd.Height; ++i) +// { +// byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride); +// +// for (j = 0; j < bmd.Width; ++j) +// { +// b = lut8[pix8[i * bmd.Width + j]]; +// j1 = j * pixelSize; +// row[j1] = b; // Red +// row[j1 + 1] = b; // Green +// row[j1 + 2] = b; // Blue +// } +// } +// } +// +// bmp.UnlockBits(bmd); +// +// bmp = KiResizeImage(bmp, 400, 400); +// SaveImage(bmp, DateTime.Now.ToString("yyyy-MM-dd") + DateTime.Now.Millisecond); +// } +// +// // Create a bitmap on the fly, using 24-bit RGB pixel data +// private void CreateImage24(int imgWidth, int imgHeight) +// { +// { +// int numBytes = imgWidth * imgHeight * 3; +// int j; +// int i, i1; +// +// BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, +// bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat); +// +// int width3 = bmd.Width * 3; +// +// unsafe +// { +// for (i = 0; i < bmd.Height; ++i) +// { +// byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride); +// i1 = i * bmd.Width * 3; +// +// for (j = 0; j < width3; j += 3) +// { +// // Windows uses little-endian, so the RGB data is +// // actually stored as BGR +// row[j + 2] = lut8[pix24[i1 + j]]; // Blue +// row[j + 1] = lut8[pix24[i1 + j + 1]]; // Green +// row[j] = lut8[pix24[i1 + j + 2]]; // Red +// } +// } +// } +// bmp.UnlockBits(bmd); +// } +// } +// +// // Create a bitmap on the fly, using 16-bit grayscale pixel data +// private void CreateImage16(int imgWidth, int imgHeight) +// { +// BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, imgWidth, imgHeight), +// System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); +// +// unsafe +// { +// int pixelSize = 3; +// int i, j, j1 = 0; +// byte b; +// +// for (i = 0; i < bmd.Height; ++i) +// { +// //取到每行的总长度 +// byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride); +// +// //i1 = i * bmd.Width; +// +// for (j = 0; j < bmd.Width; ++j) +// { +// //取色值 +// b = lut16[pix16[i * bmd.Width + j]];//i*width+j当前行的第j个像素点 +// j1 = j * pixelSize; +// row[j1] = b; // Red +// row[j1 + 1] = b; // Green +// row[j1 + 2] = b; // Blue +// } +// } +// } +// bmp.UnlockBits(bmd); +// //指定压缩后的图片大小 +// bmp = KiResizeImage(bmp, imgWidth, imgHeight); +// SaveImage(bmp, DateTime.Now.ToString("yyyy-MM-dd") + DateTime.Now.Millisecond); +// //bmp.Save(DateTime.Now.ToString("yyyy-MM-dd") + DateTime.Now.Millisecond + ".jpg"); +// } +// +// /// +// /// 压缩图片大小 +// /// +// /// +// /// +// /// +// /// +// /// +// public Bitmap KiResizeImage(Bitmap bmp, int newW, int newH) +// { +// try +// { +// Bitmap b = new Bitmap(newW, newH); +// Graphics g = Graphics.FromImage(b); +// // 插值算法的质量 +// g.InterpolationMode = InterpolationMode.Low; +// g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel); +// g.Dispose(); +// return b; +// } +// catch (Exception ex) +// { +// return null; +// } +// } +// +// // Method to save an image as PNG. The image is saved as per the current window/level values. +// public void SaveImage(Bitmap bmp, String fileName) +// { +// if (bmp != null && !string.IsNullOrWhiteSpace(fileName)) +// bmp.Save(fileName + ".jpg"); +// } +// +// // We use the linear interpolation method here +// // Nonlinear methods like sigmoid are also common, but we don't do them here. +// private void ComputeLookUpTable8() +// { +// if (winMax == 0) +// winMax = 255; +// +// int range = winMax - winMin; +// if (range < 1) range = 1; +// double factor = 255.0 / range; +// +// for (int i = 0; i < 256; ++i) +// { +// if (i <= winMin) +// lut8[i] = 0; +// else if (i >= winMax) +// lut8[i] = 255; +// else +// { +// lut8[i] = (byte)((i - winMin) * factor); +// } +// } +// } +// +// // Linear interpolation here too +// private void ComputeLookUpTable16() +// { +// int range = winMax - winMin; +// if (range < 1) range = 1; +// double factor = 255.0 / range; +// int i; +// +// for (i = 0; i < 65536; ++i) +// { +// if (i <= winMin) +// lut16[i] = 0; +// else if (i >= winMax) +// lut16[i] = 255; +// else +// { +// lut16[i] = (byte)((i - winMin) * factor); +// } +// } +// } +// +// // Restore original window/level values +// public void ResetValues() +// { +// winMax = Convert.ToInt32(winCentre + 0.5 * winWidth); +// winMin = winMax - winWidth; +// } +// } +// } \ No newline at end of file diff --git a/DicomTool/Utils/MySecurity.cs b/DicomTool/Utils/MySecurity.cs new file mode 100644 index 0000000..b16658d --- /dev/null +++ b/DicomTool/Utils/MySecurity.cs @@ -0,0 +1,269 @@ +#region CopyRight + +/**************************************************************** + * Project:健康体检信息管理系统(PEIS) + * Author:张剑峰 + * CLR Version:4.0.30319.42000 + * CreateTime:2023-05-01 14:43:48 + * Version:v2.0 + * + * Description: + * + * History: + * +***************************************************************** + * Copyright @ 云南新八达科技有限公司 2023 All rights reserved +*****************************************************************/ + +#endregion CopyRight + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace PEIS.Utils +{ + /// + /// MySecurity(安全类) 的摘要说明。 + /// + public class MySecurity + { + /// + /// 初始化安全类 + /// + public MySecurity() + { + ///默认密码 + key = "peis77911@*71"; + } + + private string key; //默认密钥 + + private byte[] sKey; + private byte[] sIV; + + #region 加密字符串 + + /// + /// 加密字符串 + /// + /// 输入字符串 + /// 密码,可以为“” + /// 输出加密后字符串 + static public string SEncryptString(string inputStr, string keyStr) + { + MySecurity ws = new MySecurity(); + return ws.EncryptString(inputStr, keyStr); + } + + /// + /// 加密字符串 + /// + /// 输入字符串 + /// 密码,可以为“” + /// 输出加密后字符串 + public string EncryptString(string inputStr, string keyStr) + { + DESCryptoServiceProvider des = new DESCryptoServiceProvider(); + if (keyStr == "") + keyStr = key; + byte[] inputByteArray = Encoding.Default.GetBytes(inputStr); + byte[] keyByteArray = Encoding.Default.GetBytes(keyStr); + SHA1 ha = new SHA1Managed(); + byte[] hb = ha.ComputeHash(keyByteArray); + sKey = new byte[8]; + sIV = new byte[8]; + for (int i = 0; i < 8; i++) + sKey[i] = hb[i]; + for (int i = 8; i < 16; i++) + sIV[i - 8] = hb[i]; + des.Key = sKey; + des.IV = sIV; + MemoryStream ms = new MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + StringBuilder ret = new StringBuilder(); + foreach (byte b in ms.ToArray()) + { + ret.AppendFormat("{0:X2}", b); + } + cs.Close(); + ms.Close(); + return ret.ToString(); + } + + #endregion 加密字符串 + + #region 加密字符串 密钥为系统默认 0123456789 + + /// + /// 加密字符串 密钥为系统默认 + /// + /// 输入字符串 + /// 输出加密后字符串 + static public string SEncryptString(string inputStr) + { + MySecurity ws = new MySecurity(); + return ws.EncryptString(inputStr, ""); + } + + #endregion 加密字符串 密钥为系统默认 0123456789 + + #region 加密文件 + + /// + /// 加密文件 + /// + /// 输入文件路径 + /// 加密后输出文件路径 + /// 密码,可以为“” + /// + public bool EncryptFile(string filePath, string savePath, string keyStr) + { + DESCryptoServiceProvider des = new DESCryptoServiceProvider(); + if (keyStr == "") + keyStr = key; + FileStream fs = File.OpenRead(filePath); + byte[] inputByteArray = new byte[fs.Length]; + fs.Read(inputByteArray, 0, (int)fs.Length); + fs.Close(); + byte[] keyByteArray = Encoding.Default.GetBytes(keyStr); + SHA1 ha = new SHA1Managed(); + byte[] hb = ha.ComputeHash(keyByteArray); + sKey = new byte[8]; + sIV = new byte[8]; + for (int i = 0; i < 8; i++) + sKey[i] = hb[i]; + for (int i = 8; i < 16; i++) + sIV[i - 8] = hb[i]; + des.Key = sKey; + des.IV = sIV; + MemoryStream ms = new MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + fs = File.OpenWrite(savePath); + foreach (byte b in ms.ToArray()) + { + fs.WriteByte(b); + } + fs.Close(); + cs.Close(); + ms.Close(); + return true; + } + + #endregion 加密文件 + + #region 解密字符串 + + /// + /// 解密字符串 + /// + /// 要解密的字符串 + /// 密钥 + /// 解密后的结果 + static public string SDecryptString(string inputStr, string keyStr) + { + MySecurity ws = new MySecurity(); + return ws.DecryptString(inputStr, keyStr); + } + + /// + /// 解密字符串 密钥为系统默认 + /// + /// 要解密的字符串 + /// 解密后的结果 + static public string SDecryptString(string inputStr) + { + MySecurity ws = new MySecurity(); + return ws.DecryptString(inputStr, ""); + } + + /// + /// 解密字符串 + /// + /// 要解密的字符串 + /// 密钥 + /// 解密后的结果 + public string DecryptString(string inputStr, string keyStr) + { + DESCryptoServiceProvider des = new DESCryptoServiceProvider(); + if (keyStr == "") + keyStr = key; + byte[] inputByteArray = new byte[inputStr.Length / 2]; + for (int x = 0; x < inputStr.Length / 2; x++) + { + int i = (Convert.ToInt32(inputStr.Substring(x * 2, 2), 16)); + inputByteArray[x] = (byte)i; + } + byte[] keyByteArray = Encoding.Default.GetBytes(keyStr); + SHA1 ha = new SHA1Managed(); + byte[] hb = ha.ComputeHash(keyByteArray); + sKey = new byte[8]; + sIV = new byte[8]; + for (int i = 0; i < 8; i++) + sKey[i] = hb[i]; + for (int i = 8; i < 16; i++) + sIV[i - 8] = hb[i]; + des.Key = sKey; + des.IV = sIV; + MemoryStream ms = new MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + StringBuilder ret = new StringBuilder(); + return System.Text.Encoding.Default.GetString(ms.ToArray()); + } + + #endregion 解密字符串 + + #region 解密文件 + + /// + /// 解密文件 + /// + /// 输入文件路径 + /// 解密后输出文件路径 + /// 密码,可以为“” + /// + public bool DecryptFile(string filePath, string savePath, string keyStr) + { + DESCryptoServiceProvider des = new DESCryptoServiceProvider(); + if (keyStr == "") + keyStr = key; + FileStream fs = File.OpenRead(filePath); + byte[] inputByteArray = new byte[fs.Length]; + fs.Read(inputByteArray, 0, (int)fs.Length); + fs.Close(); + byte[] keyByteArray = Encoding.Default.GetBytes(keyStr); + SHA1 ha = new SHA1Managed(); + byte[] hb = ha.ComputeHash(keyByteArray); + sKey = new byte[8]; + sIV = new byte[8]; + for (int i = 0; i < 8; i++) + sKey[i] = hb[i]; + for (int i = 8; i < 16; i++) + sIV[i - 8] = hb[i]; + des.Key = sKey; + des.IV = sIV; + MemoryStream ms = new MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + fs = File.OpenWrite(savePath); + foreach (byte b in ms.ToArray()) + { + fs.WriteByte(b); + } + fs.Close(); + cs.Close(); + ms.Close(); + return true; + } + + #endregion 解密文件 + } +} \ No newline at end of file diff --git a/DicomTool/Utils/ObjectData.cs b/DicomTool/Utils/ObjectData.cs new file mode 100644 index 0000000..1cd19b0 --- /dev/null +++ b/DicomTool/Utils/ObjectData.cs @@ -0,0 +1,67 @@ +#region CopyRight + +/**************************************************************** + * Project:健康体检信息管理系统(PEIS) + * Author:张剑峰 + * CLR Version:4.0.30319.42000 + * CreateTime:2023-05-01 14:41:54 + * Version:v2.0 + * + * Description: + * + * History: + * +***************************************************************** + * Copyright @ 云南新八达科技有限公司 2023 All rights reserved +*****************************************************************/ + +#endregion CopyRight + +using System; + +namespace PEIS.Utils +{ + public abstract class ObjectData + { + /// + /// 数据表名 + /// + public abstract string TableName + { + get; + } + } + + public class KeyFlagAttribute : Attribute + { + private bool _bIsKey; + public bool IsKey { get { return _bIsKey; } } + + public KeyFlagAttribute(bool bIsKey) + { + _bIsKey = bIsKey; + } + } + + public class RefFlagAttribute : Attribute + { + private bool _bIsRef; + public bool IsRef { get { return _bIsRef; } } + + public RefFlagAttribute(bool bIsRef) + { + _bIsRef = bIsRef; + } + } + + public class FixFlagAttribute : Attribute + { + private bool _blsFix; + public bool IsFix { get { return _blsFix; } } + + public FixFlagAttribute(bool blsFix) + { + _blsFix = blsFix; + } + } +} \ No newline at end of file diff --git a/DicomTool/Utils/PacsSqlHelper.cs b/DicomTool/Utils/PacsSqlHelper.cs new file mode 100644 index 0000000..895ac73 --- /dev/null +++ b/DicomTool/Utils/PacsSqlHelper.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DicomTool.Utils +{ + public static class PacsSqlHelper + { + public static List GetPacsReportList() + { + var dayBetween = $@"> '{DateTime.Today.AddDays(-7):yyyy-MM-dd}'"; + // var dayBetween = $@"BETWEEN '{DateTime.Today:yyyy-MM-dd}' AND '{DateTime.Today.AddDays(1):yyyy-MM-dd}'"; + var reportList = DAOHelp.GetDataBySQL($@" + SELECT top 2 A.PatientCode, A.ExamFeeitem_Code,A.AccessionNumber + FROM PACS.DICOMSERVER.DBO.PEIS_PacsResult A + where A.ExamDatetime IS NOT NULL and a.ExamDatetime {dayBetween} + AND EXISTS ( SELECT 1 FROM PACS.DICOMSERVER.DBO.ImgForReport WHERE AccessionNumber = A.AccessionNumber ) + AND NOT EXISTS ( SELECT 1 FROM Exam_PacsImage WHERE EID = A.PatientCode AND ReportNo=A.ExamFeeitem_Code) + "); + + Console.WriteLine($"【待同步的PACS报告】{dayBetween}至今,{reportList.Count}"); + return reportList; + } + + public static List GetReportUidList(string reportAccessionNumber) + { + + // 已选图片UID + var selectedList = DAOHelp.GetDataBySQL + ($@"SELECT SopInstanceUID FROM PACS.DICOMSERVER.DBO.ImgForReport WHERE AccessionNumber='{reportAccessionNumber}'") + .Select(s => s.SopInstanceUID).ToList(); + return selectedList; + } + + public static string GetPacsImageFile(string reportPatientCode,string reportExamFeeitemCode) + { + return DAOHelp.GetDataBySQL + ($@"SELECT ImageFile FROM PACS.DICOMSERVER.DBO.PEIS_PacsResult WHERE PatientCode='{reportPatientCode}' and ExamFeeitem_Code='{reportExamFeeitemCode}'") + ?.FirstOrDefault()?.ImageFile; + } + } +} diff --git a/DicomTool/Utils/Test.cs b/DicomTool/Utils/Test.cs new file mode 100644 index 0000000..4a8e253 --- /dev/null +++ b/DicomTool/Utils/Test.cs @@ -0,0 +1,129 @@ +using System; +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Net; +using System.Timers; +using Dicom.Imaging; +using DicomTool.Model; +using DicomTool.Utils; + +namespace DicomTool.Utils +{ + public static class Test + { + private static string basePath = @"C:\Users\15012\Desktop\Tools"; + + public static void TestMethod() + { + var filePath = Path.Combine(basePath,"1.DCM"); + var image = new DicomImage(filePath); + //image.NumberOfFrames 如果有多帧图片需要将每帧都转成jpeg + //DCM转Bitmap + var bitmap = image.RenderImage().AsBitmap(); + using (var streamImg = new MemoryStream()) + { + //Bitmap To byte[] + bitmap.Save(streamImg, System.Drawing.Imaging.ImageFormat.Jpeg); + var imgBytes = streamImg.ToArray(); + // 将byte数组写入到文件 + File.WriteAllBytes(Path.Combine(basePath, "1.jpeg"), imgBytes); + + Console.WriteLine("数据已写入到文件:" + filePath); + } + } + } +} + + +/* + + /// + /// 下载所有图片 + /// + private static void Execute2() + { + Console.WriteLine($"【同步所有图片】{DateTime.Now:yyyy-MM-dd HH:mm}"); + // var dayBetween = $@"BETWEEN '2024-06-16' AND '2024-06-21'"; + var dayBetween = $@"BETWEEN '{DateTime.Today:yyyy-MM-dd}' AND '{DateTime.Today.AddDays(1):yyyy-MM-dd}'"; + Console.WriteLine($@"ExamDatetime {dayBetween}"); + var reportList = DAOHelp.GetDataBySQL($@" +SELECT A.PatientCode, A.ExamFeeitem_Code,A.AccessionNumber +FROM PACS.DICOMSERVER.DBO.PEIS_PacsResult A +where A.ExamDatetime IS NOT NULL and a.ExamDatetime {dayBetween} + AND NOT EXISTS ( SELECT 1 FROM PACS.DICOMSERVER.DBO.ImgForReport WHERE AccessionNumber = A.AccessionNumber ) + AND NOT EXISTS ( SELECT 1 FROM Report_Pacs WHERE EID = A.PatientCode AND ReportNo=A.ExamFeeitem_Code) + "); + Console.WriteLine($"【待下载报告】{reportList.Count}"); + var fileNameList = new List(); + foreach (var report in reportList) + { + try + { + var imageFiles = DAOHelp.GetDataBySQL + ($@"SELECT ImageFile FROM PACS.DICOMSERVER.DBO.PEIS_PacsResult WHERE PatientCode='{report.PatientCode}' and ExamFeeitem_Code='{report.ExamFeeitem_Code}'") + ?.FirstOrDefault()?.ImageFile; + if (string.IsNullOrEmpty(imageFiles)) + { + Console.WriteLine( + $@"[ERROR] EID={report.PatientCode} - FID={report.ExamFeeitem_Code} ImageFile为空"); + continue; + } + + // 得到DCM共享文件地址 + var dcmPaths = imageFiles.Split(';'); + // 路径为空 + if (!(dcmPaths?.Length > 0)) continue; + //获取远程共享文件 + using (var client = new WebClient()) + { + // 配置授权账户密码 + var credentials = new NetworkCredential(UserName, Password); + client.Credentials = credentials; + // 循环路径 + for (var index = 0; index < dcmPaths.Count(); index++) + { + try + { + // 当前路径 + var dcmPath = dcmPaths[index]; + if (string.IsNullOrEmpty(dcmPath)) continue; + var name = $"{report.PatientCode}-{report.ExamFeeitem_Code}-"; + //下载远程文件 + var buffer = client.DownloadData(dcmPath); + // 保存本地 + Bytes2File(buffer, DcmPath, $"{name}.DCM"); + fileNameList.Add($"{name}.DCM"); + Console.WriteLine($"下载:{name}.DCM"); + } + catch (Exception e) + { + Console.WriteLine($"1." + e.Message); + } + } + } + } + catch (Exception e) + { + Console.WriteLine($"2." + e.Message); + } + } + + Console.WriteLine($@"【下载】{fileNameList.Count}"); + if (fileNameList.Count > 0) + // 保存到本地后上传到服务器 + UploadDcmImg(DcmPath, fileNameList, InsertExamPacsImage); + + Console.WriteLine($@"【等待】{intervalInMinutes}min"); + // 删除文件夹下所有文件 + foreach (var filePath in Directory.GetFiles(DcmPath)) + { + File.Delete(filePath); + } + } + + */ diff --git a/DicomTool/packages.config b/DicomTool/packages.config new file mode 100644 index 0000000..f02f338 --- /dev/null +++ b/DicomTool/packages.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Scale/Form1.Designer.cs b/Scale/Form1.Designer.cs new file mode 100644 index 0000000..9947ebf --- /dev/null +++ b/Scale/Form1.Designer.cs @@ -0,0 +1,358 @@ +namespace Scale +{ + partial class Form1 + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.panel1 = new System.Windows.Forms.Panel(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.lblTip = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.btnSend = new System.Windows.Forms.Button(); + this.txtMb = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.txtEID = new System.Windows.Forms.TextBox(); + this.txtSzy = new System.Windows.Forms.TextBox(); + this.txtHeight = new System.Windows.Forms.TextBox(); + this.txtWeight = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.txtSsy = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.btnOpen = new System.Windows.Forms.Button(); + this.txt1 = new System.Windows.Forms.TextBox(); + this.panel2 = new System.Windows.Forms.Panel(); + this.button1 = new System.Windows.Forms.Button(); + this.panel1.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.panel2.SuspendLayout(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.tableLayoutPanel1); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(1184, 611); + this.panel1.TabIndex = 25; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 9; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 170F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 160F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 170F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 160F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 150F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 160F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 180F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.Controls.Add(this.button1, 7, 3); + this.tableLayoutPanel1.Controls.Add(this.label3, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.lblTip, 1, 4); + this.tableLayoutPanel1.Controls.Add(this.label4, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.btnSend, 7, 1); + this.tableLayoutPanel1.Controls.Add(this.txtMb, 6, 3); + this.tableLayoutPanel1.Controls.Add(this.label8, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.label9, 5, 3); + this.tableLayoutPanel1.Controls.Add(this.txtEID, 2, 1); + this.tableLayoutPanel1.Controls.Add(this.txtSzy, 4, 3); + this.tableLayoutPanel1.Controls.Add(this.txtHeight, 2, 2); + this.tableLayoutPanel1.Controls.Add(this.txtWeight, 4, 2); + this.tableLayoutPanel1.Controls.Add(this.label7, 3, 3); + this.tableLayoutPanel1.Controls.Add(this.txtSsy, 2, 3); + this.tableLayoutPanel1.Controls.Add(this.label5, 3, 2); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 6; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 60F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 60F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 60F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 60F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(1184, 611); + this.tableLayoutPanel1.TabIndex = 40; + // + // lblTip + // + this.lblTip.AutoSize = true; + this.tableLayoutPanel1.SetColumnSpan(this.lblTip, 6); + this.lblTip.Dock = System.Windows.Forms.DockStyle.Fill; + this.lblTip.Font = new System.Drawing.Font("宋体", 21.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.lblTip.Location = new System.Drawing.Point(20, 365); + this.lblTip.Name = "lblTip"; + this.lblTip.Size = new System.Drawing.Size(964, 60); + this.lblTip.TabIndex = 39; + this.lblTip.Text = "提示:"; + this.lblTip.TextAlign = System.Drawing.ContentAlignment.BottomCenter; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Dock = System.Windows.Forms.DockStyle.Fill; + this.label3.Font = new System.Drawing.Font("宋体", 18F); + this.label3.Location = new System.Drawing.Point(20, 185); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(164, 60); + this.label3.TabIndex = 28; + this.label3.Text = "体检号:"; + this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Dock = System.Windows.Forms.DockStyle.Fill; + this.label4.Font = new System.Drawing.Font("宋体", 18F); + this.label4.Location = new System.Drawing.Point(20, 245); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(164, 60); + this.label4.TabIndex = 29; + this.label4.Text = "身高:"; + this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // btnSend + // + this.btnSend.Dock = System.Windows.Forms.DockStyle.Fill; + this.btnSend.Font = new System.Drawing.Font("宋体", 15F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.btnSend.Location = new System.Drawing.Point(990, 188); + this.btnSend.Name = "btnSend"; + this.btnSend.Size = new System.Drawing.Size(174, 54); + this.btnSend.TabIndex = 7; + this.btnSend.Text = " 手动上报"; + this.btnSend.UseVisualStyleBackColor = true; + this.btnSend.Click += new System.EventHandler(this.btnSend_Click); + // + // txtMb + // + this.txtMb.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtMb.Font = new System.Drawing.Font("宋体", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.txtMb.Location = new System.Drawing.Point(830, 308); + this.txtMb.MaxLength = 10; + this.txtMb.Name = "txtMb"; + this.txtMb.Size = new System.Drawing.Size(154, 47); + this.txtMb.TabIndex = 6; + this.txtMb.Text = " "; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Dock = System.Windows.Forms.DockStyle.Fill; + this.label8.Font = new System.Drawing.Font("宋体", 18F); + this.label8.Location = new System.Drawing.Point(20, 305); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(164, 60); + this.label8.TabIndex = 34; + this.label8.Text = "收缩压:"; + this.label8.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Dock = System.Windows.Forms.DockStyle.Fill; + this.label9.Font = new System.Drawing.Font("宋体", 18F); + this.label9.Location = new System.Drawing.Point(680, 305); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(144, 60); + this.label9.TabIndex = 37; + this.label9.Text = "脉搏:"; + this.label9.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // txtEID + // + this.txtEID.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtEID.Font = new System.Drawing.Font("宋体", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.txtEID.Location = new System.Drawing.Point(190, 188); + this.txtEID.MaxLength = 10; + this.txtEID.Name = "txtEID"; + this.txtEID.Size = new System.Drawing.Size(154, 47); + this.txtEID.TabIndex = 1; + // + // txtSzy + // + this.txtSzy.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtSzy.Font = new System.Drawing.Font("宋体", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.txtSzy.Location = new System.Drawing.Point(520, 308); + this.txtSzy.MaxLength = 10; + this.txtSzy.Name = "txtSzy"; + this.txtSzy.Size = new System.Drawing.Size(154, 47); + this.txtSzy.TabIndex = 5; + this.txtSzy.Text = " "; + // + // txtHeight + // + this.txtHeight.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtHeight.Font = new System.Drawing.Font("宋体", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.txtHeight.Location = new System.Drawing.Point(190, 248); + this.txtHeight.MaxLength = 10; + this.txtHeight.Name = "txtHeight"; + this.txtHeight.Size = new System.Drawing.Size(154, 47); + this.txtHeight.TabIndex = 2; + // + // txtWeight + // + this.txtWeight.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtWeight.Font = new System.Drawing.Font("宋体", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.txtWeight.Location = new System.Drawing.Point(520, 248); + this.txtWeight.MaxLength = 10; + this.txtWeight.Name = "txtWeight"; + this.txtWeight.Size = new System.Drawing.Size(154, 47); + this.txtWeight.TabIndex = 3; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Dock = System.Windows.Forms.DockStyle.Fill; + this.label7.Font = new System.Drawing.Font("宋体", 18F); + this.label7.Location = new System.Drawing.Point(350, 305); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(164, 60); + this.label7.TabIndex = 35; + this.label7.Text = "舒张压:"; + this.label7.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // txtSsy + // + this.txtSsy.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtSsy.Font = new System.Drawing.Font("宋体", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.txtSsy.Location = new System.Drawing.Point(190, 308); + this.txtSsy.MaxLength = 10; + this.txtSsy.Name = "txtSsy"; + this.txtSsy.Size = new System.Drawing.Size(154, 47); + this.txtSsy.TabIndex = 4; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Dock = System.Windows.Forms.DockStyle.Fill; + this.label5.Font = new System.Drawing.Font("宋体", 18F); + this.label5.Location = new System.Drawing.Point(350, 245); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(164, 60); + this.label5.TabIndex = 30; + this.label5.Text = "体重:"; + this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 21); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(77, 12); + this.label1.TabIndex = 45; + this.label1.Text = "血压仪未连接"; + // + // btnOpen + // + this.btnOpen.Location = new System.Drawing.Point(198, 15); + this.btnOpen.Name = "btnOpen"; + this.btnOpen.Size = new System.Drawing.Size(73, 25); + this.btnOpen.TabIndex = 43; + this.btnOpen.Text = " 打开"; + this.btnOpen.UseVisualStyleBackColor = true; + this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click); + // + // txt1 + // + this.txt1.Location = new System.Drawing.Point(119, 18); + this.txt1.Name = "txt1"; + this.txt1.Size = new System.Drawing.Size(55, 21); + this.txt1.TabIndex = 42; + this.txt1.Text = "COM3"; + // + // panel2 + // + this.panel2.Controls.Add(this.label1); + this.panel2.Controls.Add(this.txt1); + this.panel2.Controls.Add(this.btnOpen); + this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel2.Location = new System.Drawing.Point(0, 560); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(1184, 51); + this.panel2.TabIndex = 26; + // + // button1 + // + this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button1.ForeColor = System.Drawing.Color.Red; + this.button1.Location = new System.Drawing.Point(1088, 321); + this.button1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 10); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(76, 34); + this.button1.TabIndex = 46; + this.button1.Text = "清除"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1184, 611); + this.Controls.Add(this.panel2); + this.Controls.Add(this.panel1); + this.Name = "Form1"; + this.Text = "联机程序"; + this.panel1.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.panel2.ResumeLayout(false); + this.panel2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label lblTip; + private System.Windows.Forms.TextBox txtMb; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox txtSzy; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox txtSsy; + private System.Windows.Forms.TextBox txtWeight; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtEID; + private System.Windows.Forms.TextBox txtHeight; + private System.Windows.Forms.Button btnSend; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btnOpen; + private System.Windows.Forms.TextBox txt1; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Button button1; + } +} + diff --git a/Scale/Form1.cs b/Scale/Form1.cs new file mode 100644 index 0000000..e06d58d --- /dev/null +++ b/Scale/Form1.cs @@ -0,0 +1,350 @@ +using System; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.IO.Ports; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; + +namespace Scale +{ + public partial class Form1 : Form + { + private SerialPort serialPort; + + public Form1() + { + InitializeComponent(); + lblTip.Text = ""; + txtEID.KeyDown += TxtEID_KeyDown; + this.StartPosition = FormStartPosition.CenterScreen; + txtEID.Focus(); + this.Load += Form1_Load; + this.FormClosing += Form_FormClosing; + + SetFont(); + } + + private void SetFont() + { + btnSend.Text = "\ue7a4 手动上报"; + label3.Text = "\ue635 体检号:"; + label4.Text = "\ue7ca 身高:"; + label5.Text = "\ue696 体重:"; + label8.Text = "\ue602 舒张压:"; + label7.Text = "\ue601 收缩压:"; + label9.Text = "\ue89a 脉搏:"; + btnSend.Font = new Font(IconfontHelper.PFCC.Families[0], 18); + btnSend.Font = new Font(IconfontHelper.PFCC.Families[0], 18); + label3.Font = new Font(IconfontHelper.PFCC.Families[0], 18); + label4.Font = new Font(IconfontHelper.PFCC.Families[0], 18); + label5.Font = new Font(IconfontHelper.PFCC.Families[0], 18); + label8.Font = new Font(IconfontHelper.PFCC.Families[0], 18); + label7.Font = new Font(IconfontHelper.PFCC.Families[0], 18); + label9.Font = new Font(IconfontHelper.PFCC.Families[0], 18); + } + private void Form_FormClosing(object sender, FormClosingEventArgs e) + { + // 在窗口即将关闭时触发 + if (MessageBox.Show(@"确定要关闭联机程序吗?", "确认关闭", MessageBoxButtons.YesNo) == DialogResult.No) + { + // 用户取消关闭操作 + e.Cancel = true; + } + else + { + try + { + if (serialPort != null && serialPort.IsOpen) + { + serialPort.Close(); + serialPort.Dispose(); + } + } + catch (Exception ex) + { + // 处理异常,例如记录日志或显示错误消息 + MessageBox.Show($@"关闭串口时发生错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + } + } + + private void Form1_Load(object sender, EventArgs e) + { + DelLog(); + Conn(); + } + + private void TxtEID_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode != Keys.Enter) return; + // 读取身高体重数据 + ReadWeightHeight(); + // Thread.Sleep(1000); + // 上传 + Upload(); + e.SuppressKeyPress = true; // 防止回车键产生额外的换行符 + } + + private void btnOpen_Click(object sender, EventArgs e) + { + Conn(); + } + + private void btnSend_Click(object sender, EventArgs ee) + { + Upload(); + } + + public void TxtEidFocus() + { + Invoke(new Action(() => txtEID.Focus())); + } + + #region 血压仪 + + private void Conn() + { + if (serialPort != null && serialPort.IsOpen) + { + return; + } + var list = System.IO.Ports.SerialPort.GetPortNames(); + if (serialPort != null && serialPort.IsOpen) serialPort.Close(); + var port = txt1.Text?.Trim() ?? "COM1"; + // if (list.Length<=0||!list.Contains(port)) + // { + // MessageBox.Show(@"未找到串口:" + port); + // return; + // } + // 初始化串口 + serialPort = new SerialPort(); + // 设置串口参数 + serialPort.PortName = port; // 根据实际情况设置串口名称 + serialPort.BaudRate = 9600; // 波特率 + serialPort.DataBits = 8; // 数据位 + serialPort.Parity = Parity.None; // 校验位 + serialPort.StopBits = StopBits.One; // 停止位 + // serialPort.RtsEnable = false; + // serialPort.DtrEnable = false; + serialPort.DataReceived += SerialPort_DataReceived; + // 设置数据接收事件处理程序 + // 打开串口 + try + { + serialPort.Open(); + txt1.Enabled = false; + Debug.WriteLine("OPEN"); + label1.Invoke(new Action(() => label1.Text = @"血压仪已连接")); + } + catch (Exception ex) + { + MessageBox.Show(@"无法打开串口:" + ex.Message); + txt1.Enabled = true; + // 关闭串口 + if (serialPort.IsOpen) + { + serialPort.Close(); + } + label1.Invoke(new Action(() => label1.Text = @"血压仪未连接")); + } + } + + /// + /// 血压仪数据接收 + /// + /// + /// + private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) + { + try + { + // 处理接收到的数据 + var buffer = new byte[serialPort.BytesToRead]; + serialPort.Read(buffer, 0, buffer.Length); + var data = Encoding.ASCII.GetString(buffer); + if (!(data.Length >= 51)) + { + MessageBox.Show($@"从仪器接收到错误的数据:{data}"); + return; + } + TxtEidFocus(); + var txtSsyText = data.Substring(40, 3); + Debug.WriteLine(txtSsyText); + txtSsy.Invoke(new Action(() => txtSsy.Text = txtSsyText)); + + var txtSzyText = data.Substring(44, 3); + Debug.WriteLine(txtSzyText); + txtSzy.Invoke(new Action(() => txtSzy.Text = txtSzyText)); + + var txtMbText = data.Substring(48, 3); + Debug.WriteLine(txtMbText); + txtMb.Invoke(new Action(() => txtMb.Text = txtMbText)); + + var weight = txtWeight.Text?.Trim(); + if (string.IsNullOrEmpty(weight)) + { + ReadWeightHeight(); + } + } + catch (Exception exception) + { + MessageBox.Show(@"错误:" + exception.Message); + // 关闭串口 + if (serialPort.IsOpen) serialPort.Close(); + } + } + + #endregion + + #region 身高体重仪 + + public void ReadWeightHeight() + { + try + { + // 获取当前程序路径 + var currentPath = AppDomain.CurrentDomain.BaseDirectory; + // 组合路径,假设 Data 文件夹在当前路径下 + var dataFolderPath = Path.Combine(currentPath, "data"); + // 获取 Data 文件夹下的所有 .log 文件,并按名称排序 + var files = Directory.GetFiles(dataFolderPath, "*.log").OrderBy(f => f).ToArray(); + + if (files.Length <= 0) return; + // 读取第一个文本文件的内容 + var firstFilePath = files[0]; + var content = File.ReadAllText(firstFilePath); + Debug.WriteLine(firstFilePath); + Debug.WriteLine(content); + var match = Regex.Match(content, @"W:(\d+\.\d+)\s+H:(\d+\.\d+)"); + if (match.Success) + { + // 提取身高和体重的值 + var weight = double.Parse(match.Groups[1].Value).ToString("0.##"); + var height = double.Parse(match.Groups[2].Value).ToString("0.##"); + Invoke(new Action(() => txtWeight.Text = weight)); + Invoke(new Action(() => txtHeight.Text = height)); + } + // 删除所有文本文件 + foreach (var filePath in files) + { + File.Delete(filePath); + Debug.WriteLine($"Deleted: {Path.GetFileName(filePath)}"); + } + } + catch (Exception e) + { + MessageBox.Show(e.Message); + } + } + + private void DelLog() + { + + // 获取当前程序路径 + var currentPath = AppDomain.CurrentDomain.BaseDirectory; + // 组合路径,假设 Data 文件夹在当前路径下 + var dataFolderPath = Path.Combine(currentPath, "data"); + // 获取 Data 文件夹下的所有 .log 文件,并按名称排序 + var files = Directory.GetFiles(dataFolderPath, "*.log").OrderBy(f => f).ToArray(); + // 删除所有文本文件 + foreach (var filePath in files) + { + File.Delete(filePath); + } + + } + + #endregion + + + #region 上传数据库 + + public void Upload() + { + var eid = txtEID.Text?.Trim(); + var weight = txtWeight.Text?.Trim(); + var height = txtHeight.Text?.Trim(); + var systolic = txtSsy.Text?.Trim(); + var diastolic = txtSzy.Text?.Trim(); + var pulseRate = txtMb.Text?.Trim(); + if (string.IsNullOrEmpty(eid)) return; + if (string.IsNullOrEmpty(weight) && + string.IsNullOrEmpty(height) && + string.IsNullOrEmpty(systolic) && + string.IsNullOrEmpty(diastolic) && + string.IsNullOrEmpty(pulseRate)) return; + var isEid = Int64.TryParse(eid, out var id); + if (!isEid) + { + MessageBox.Show(@"体检号错误,请重新输入!"); + return; + } + var result = Insert(id, weight, height, systolic, diastolic, pulseRate); + + lblTip.Text = result ? $"提示:体检号 {eid},数据上报成功" : $"提示:体检号 {eid},数据上报失败"; + if (result) + { + Invoke(new Action(() => txtEID.Text = "")); + Invoke(new Action(() => txtWeight.Text = "")); + Invoke(new Action(() => txtHeight.Text = "")); + Invoke(new Action(() => txtSsy.Text = "")); + Invoke(new Action(() => txtSzy.Text = "")); + Invoke(new Action(() => txtMb.Text = "")); + } + TxtEidFocus(); + } + + private const string ConnectionString = @"Data Source=192.168.11.5;Initial Catalog=peisdb;User ID=sa;Password=000626;"; + + public static bool Insert(long eid, string weight, string height, string systolic, string diastolic, string pulseRate) + { + using (var connection = new SqlConnection(ConnectionString)) + { + try + { + connection.Open(); + var insertQuery = $@" +IF NOT EXISTS ( + SELECT 1 FROM Exam_ResultIsm WHERE EID = {eid} AND Weight = '{weight}' AND Height = '{height}' AND Systolic = '{systolic}' AND Diastolic = '{diastolic}' AND PulseRate = '{pulseRate}' +) +BEGIN +INSERT INTO Exam_ResultIsm(EID, Weight, Height, Systolic, Diastolic, PulseRate) +VALUES ({eid}, '{weight}', '{height}', '{systolic}', '{diastolic}', '{pulseRate}') +END"; + using (var command = new SqlCommand(insertQuery, connection)) + { + command.ExecuteNonQuery(); + } + connection.Close(); + return true; + } + catch (Exception e) + { + MessageBox.Show(e.Message); + return false; + } + } + } + + + #endregion + + private void button1_Click(object sender, EventArgs e) + { + Invoke(new Action(() => txtEID.Text = "")); + Invoke(new Action(() => txtWeight.Text = "")); + Invoke(new Action(() => txtHeight.Text = "")); + Invoke(new Action(() => txtSsy.Text = "")); + Invoke(new Action(() => txtSzy.Text = "")); + Invoke(new Action(() => txtMb.Text = "")); + + DelLog(); + txtEID.Focus(); + } + } +} \ No newline at end of file diff --git a/Scale/Form1.resx b/Scale/Form1.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Scale/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Scale/IconfontHelper.cs b/Scale/IconfontHelper.cs new file mode 100644 index 0000000..c1545ad --- /dev/null +++ b/Scale/IconfontHelper.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Scale +{ + public class IconfontHelper + { + private static System.Drawing.Text.PrivateFontCollection pfcc; + + public static System.Drawing.Text.PrivateFontCollection PFCC + { + get { return pfcc ?? LoadFont(); } + set { pfcc = value; } + } + public static bool JzFont { get; private set; } = false; + public static System.Drawing.Text.PrivateFontCollection LoadFont() + { + if (!JzFont) + { + pfcc = new System.Drawing.Text.PrivateFontCollection(); + pfcc.AddFontFile(Environment.CurrentDirectory + "/iconfont.ttf"); + JzFont = true; + } + return pfcc; + } + } +} diff --git a/Scale/Program.cs b/Scale/Program.cs new file mode 100644 index 0000000..02bef83 --- /dev/null +++ b/Scale/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace Scale +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/Scale/Properties/AssemblyInfo.cs b/Scale/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8891c15 --- /dev/null +++ b/Scale/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Scale")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Scale")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("f13021fd-372e-4d3c-8982-6fe5102af45a")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Scale/Properties/Resources.Designer.cs b/Scale/Properties/Resources.Designer.cs new file mode 100644 index 0000000..fbff8fd --- /dev/null +++ b/Scale/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本: 4.0.30319.42000 +// +// 对此文件的更改可能导致不正确的行为,如果 +// 重新生成代码,则所做更改将丢失。 +// +//------------------------------------------------------------------------------ + +namespace Scale.Properties +{ + + + /// + /// 强类型资源类,用于查找本地化字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 返回此类使用的缓存 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Scale.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 覆盖当前线程的 CurrentUICulture 属性 + /// 使用此强类型的资源类的资源查找。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Scale/Properties/Resources.resx b/Scale/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Scale/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Scale/Properties/Settings.Designer.cs b/Scale/Properties/Settings.Designer.cs new file mode 100644 index 0000000..4a535d5 --- /dev/null +++ b/Scale/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Scale.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Scale/Properties/Settings.settings b/Scale/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/Scale/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Scale/Scale.csproj b/Scale/Scale.csproj new file mode 100644 index 0000000..a398d4b --- /dev/null +++ b/Scale/Scale.csproj @@ -0,0 +1,88 @@ + + + + + Debug + AnyCPU + {F13021FD-372E-4D3C-8982-6FE5102AF45A} + WinExe + Scale + Scale + v4.0 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + Always + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + Always + + + + \ No newline at end of file diff --git a/Scale/SgTz.cs b/Scale/SgTz.cs new file mode 100644 index 0000000..5792cd6 --- /dev/null +++ b/Scale/SgTz.cs @@ -0,0 +1,632 @@ + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace TestSerialDLL +{ + public class SerialWrapper : IDisposable + { + #region Enum + public enum StopBits + { + None, + One, + Two, + OnePointFive, + } + + public enum Parity + { + None, + Odd, + Even, + Mark, + Space, + } + #endregion + #region Fields + /// + /// The baud rate at which the communications device operates. + /// + private readonly int iBaudRate; + + /// + /// The number of bits in the bytes to be transmitted and received. + /// + private readonly byte byteSize; + + /// + /// The system handle to the serial port connection ('file' handle). + /// + private IntPtr pHandle = IntPtr.Zero; + + /// + /// The parity scheme to be used. + /// + private readonly Parity parity; + + /// + /// The name of the serial port to connect to. + /// + private readonly string sPortName; + + /// + /// The number of bits in the bytes to be transmitted and received. + /// + private readonly StopBits stopBits; + #endregion + + #region Constructor + /// + /// Creates a new instance of SerialCom. + /// + /// The name of the serial port to connect to + /// The baud rate at which the communications device operates + /// The number of stop bits to be used + /// The parity scheme to be used + /// The number of bits in the bytes to be transmitted and received + public SerialWrapper(string portName, int baudRate, StopBits stopBits, Parity parity, byte byteSize) + { + if (stopBits == StopBits.None) + throw new ArgumentException("stopBits cannot be StopBits.None", "stopBits"); + if (byteSize < 5 || byteSize > 8) + throw new ArgumentOutOfRangeException("The number of data bits must be 5 to 8 bits.", "byteSize"); + if (baudRate < 110 || baudRate > 256000) + throw new ArgumentOutOfRangeException("Invalid baud rate specified.", "baudRate"); + if ((byteSize == 5 && stopBits == StopBits.Two) || (stopBits == StopBits.OnePointFive && byteSize > 5)) + throw new ArgumentException("The use of 5 data bits with 2 stop bits is an invalid combination, " + + "as is 6, 7, or 8 data bits with 1.5 stop bits."); + + this.sPortName = portName; + this.iBaudRate = baudRate; + this.byteSize = byteSize; + this.stopBits = stopBits; + this.parity = parity; + } + + /// + /// Creates a new instance of SerialCom. + /// + /// The name of the serial port to connect to + /// The baud rate at which the communications device operates + /// The number of stop bits to be used + /// The parity scheme to be used + public SerialWrapper(string portName, int baudRate, StopBits stopBits, Parity parity) + : this(portName, baudRate, stopBits, parity, 8) + { + + } + #endregion + + #region Open + /// + /// Opens and initializes the serial connection. + /// + /// Whether or not the operation succeeded + public bool Open() + { + pHandle = CreateFile(this.sPortName, FileAccess.ReadWrite, FileShare.None, + IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero); + if (pHandle == IntPtr.Zero) return false; + + if (ConfigureSerialPort()) return true; + else + { + Dispose(); + return false; + } + } + #endregion + + #region Write + /// + /// Transmits the specified array of bytes. + /// + /// The bytes to write + /// The number of bytes written (-1 if error) + public int Write(byte[] data) + { + FailIfNotConnected(); + if (data == null) return 0; + + int bytesWritten; + if (WriteFile(pHandle, data, data.Length, out bytesWritten, 0)) + return bytesWritten; + return -1; + } + + /// + /// Transmits the specified string. + /// + /// The string to write + /// The number of bytes written (-1 if error) + public int Write(string data) + { + FailIfNotConnected(); + + // convert the string to bytes + byte[] bytes; + if (data == null) + { + bytes = null; + } + else + { + bytes = Encoding.UTF8.GetBytes(data); + } + + return Write(bytes); + } + + /// + /// Transmits the specified string and appends the carriage return to the end + /// if it does not exist. + /// + /// + /// Note that the string must end in '\r\n' before any serial device will interpret the data + /// sent. For ease of programmability, this method should be used instead of Write() when you + /// want to automatically execute the specified command string. + /// + /// The string to write + /// The number of bytes written (-1 if error) + public int WriteLine(string data) + { + if (data != null && !data.EndsWith("\r\n")) + data += "\r\n"; + return Write(data); + } + #endregion + + #region Read + /// + /// Reads any bytes that have been received and writes them to the specified array. + /// + /// The array to write the read data to + /// The number of bytes read (-1 if error) + public int Read(byte[] data) + { + FailIfNotConnected(); + if (data == null) return 0; + + int bytesRead; + if (ReadFile(pHandle, data, data.Length, out bytesRead, 0)) + return bytesRead; + return -1; + } + + /// + /// Reads any data that has been received as a string. + /// + /// The maximum number of bytes to read + /// The data received (null if no data) + public string ReadString(int maxBytesToRead) + { + if (maxBytesToRead < 1) throw new ArgumentOutOfRangeException("maxBytesToRead"); + + byte[] bytes = new byte[maxBytesToRead]; + int numBytes = Read(bytes); + //string data = ASCIIEncoding.ASCII.GetString(bytes, 0, numBytes); + string data = Encoding.UTF8.GetString(bytes, 0, numBytes); + return data; + } + #endregion + + #region Dispose Utils + /// + /// Disconnects and disposes of the SerialCom instance. + /// + public void Dispose() + { + if (pHandle != IntPtr.Zero) + { + CloseHandle(pHandle); + pHandle = IntPtr.Zero; + } + } + + /// + /// Flushes the serial I/O buffers. + /// + /// Whether or not the operation succeeded + public bool Flush() + { + FailIfNotConnected(); + + const int PURGE_RXCLEAR = 0x0008; // input buffer + const int PURGE_TXCLEAR = 0x0004; // output buffer + return PurgeComm(pHandle, PURGE_RXCLEAR | PURGE_TXCLEAR); + } + #endregion + + #region Private Helpers + /// + /// Configures the serial device based on the connection parameters pased in by the user. + /// + /// Whether or not the operation succeeded + private bool ConfigureSerialPort() + { + DCB serialConfig = new DCB(); + if (GetCommState(pHandle, ref serialConfig)) + { + // setup the DCB struct with the serial settings we need + serialConfig.BaudRate = (uint)this.iBaudRate; + serialConfig.ByteSize = this.byteSize; + serialConfig.fBinary = 1; // must be true + serialConfig.fDtrControl = 1; // DTR_CONTROL_ENABLE "Enables the DTR line when the device is opened and leaves it on." + serialConfig.fAbortOnError = 0; // false + serialConfig.fTXContinueOnXoff = 0; // false + + serialConfig.fParity = 1; // true so that the Parity member is looked at + switch (this.parity) + { + case Parity.Even: + serialConfig.Parity = 2; + break; + case Parity.Mark: + serialConfig.Parity = 3; + break; + case Parity.Odd: + serialConfig.Parity = 1; + break; + case Parity.Space: + serialConfig.Parity = 4; + break; + case Parity.None: + default: + serialConfig.Parity = 0; + break; + } + switch (this.stopBits) + { + case StopBits.One: + serialConfig.StopBits = 0; + break; + case StopBits.OnePointFive: + serialConfig.StopBits = 1; + break; + case StopBits.Two: + serialConfig.StopBits = 2; + break; + case StopBits.None: + default: + throw new ArgumentException("stopBits cannot be StopBits.None"); + } + + if (SetCommState(pHandle, ref serialConfig)) + { + // set the serial connection timeouts + COMMTIMEOUTS timeouts = new COMMTIMEOUTS(); + timeouts.ReadIntervalTimeout = 1; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + if (SetCommTimeouts(pHandle, ref timeouts)) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + else + { + return false; + } + } + + /// + /// Helper that throws a InvalidOperationException if we don't have a serial connection. + /// + private void FailIfNotConnected() + { + if (pHandle == IntPtr.Zero) + throw new InvalidOperationException("You must be connected to the serial port before performing this operation."); + } + #endregion + + #region Native Helpers + #region Native structures + /// + /// Contains the time-out parameters for a communications device. + /// + [StructLayout(LayoutKind.Sequential)] + struct COMMTIMEOUTS + { + public uint ReadIntervalTimeout; + public uint ReadTotalTimeoutMultiplier; + public uint ReadTotalTimeoutConstant; + public uint WriteTotalTimeoutMultiplier; + public uint WriteTotalTimeoutConstant; + } + + /// + /// Defines the control setting for a serial communications device. + /// + [StructLayout(LayoutKind.Sequential)] + struct DCB + { + public int DCBlength; + public uint BaudRate; + public uint Flags; + public ushort wReserved; + public ushort XonLim; + public ushort XoffLim; + public byte ByteSize; + public byte Parity; + public byte StopBits; + public sbyte XonChar; + public sbyte XoffChar; + public sbyte ErrorChar; + public sbyte EofChar; + public sbyte EvtChar; + public ushort wReserved1; + public uint fBinary; + public uint fParity; + public uint fOutxCtsFlow; + public uint fOutxDsrFlow; + public uint fDtrControl; + public uint fDsrSensitivity; + public uint fTXContinueOnXoff; + public uint fOutX; + public uint fInX; + public uint fErrorChar; + public uint fNull; + public uint fRtsControl; + public uint fAbortOnError; + } + #endregion + + #region Native Methods + // Used to get a handle to the serial port so that we can read/write to it. + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] + static extern IntPtr CreateFile(string fileName, + [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess, + [MarshalAs(UnmanagedType.U4)] FileShare fileShare, + IntPtr securityAttributes, + [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, + int flags, + IntPtr template); + + // Used to close the handle to the serial port. + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool CloseHandle(IntPtr hObject); + + // Used to get the state of the serial port so that we can configure it. + [DllImport("kernel32.dll")] + static extern bool GetCommState(IntPtr hFile, ref DCB lpDCB); + + // Used to configure the serial port. + [DllImport("kernel32.dll")] + static extern bool SetCommState(IntPtr hFile, [In] ref DCB lpDCB); + + // Used to set the connection timeouts on our serial connection. + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool SetCommTimeouts(IntPtr hFile, ref COMMTIMEOUTS lpCommTimeouts); + + // Used to read bytes from the serial connection. + [DllImport("kernel32.dll")] + static extern bool ReadFile(IntPtr hFile, byte[] lpBuffer, + int nNumberOfBytesToRead, out int lpNumberOfBytesRead, int lpOverlapped); + + // Used to write bytes to the serial connection. + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, + int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, int lpOverlapped); + + // Used to flush the I/O buffers. + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool PurgeComm(IntPtr hFile, int dwFlags); + #endregion + #endregion + } +} +// using System; +// using System.Collections.Generic; +// using System.Linq; +// using System.Runtime.InteropServices; +// using System.Text; +// using System; +// using System.IO.Ports; +// using System.Threading; +// +// namespace Scale +// { +// // Use this code inside a project created with the Visual C# > Windows Desktop > Console Application template. +// // Replace the code in Program.cs with this code. +// +// +// public class PortChat +// { +// static bool _continue; +// static SerialPort _serialPort; +// +// public static void Main() +// { +// string name; +// string message; +// StringComparer stringComparer = StringComparer.OrdinalIgnoreCase; +// Thread readThread = new Thread(Read); +// +// // Create a new SerialPort object with default settings. +// _serialPort = new SerialPort(); +// +// // Allow the user to set the appropriate properties. +// _serialPort.PortName = SetPortName(_serialPort.PortName); +// _serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate); +// _serialPort.Parity = SetPortParity(_serialPort.Parity); +// _serialPort.DataBits = SetPortDataBits(_serialPort.DataBits); +// _serialPort.StopBits = SetPortStopBits(_serialPort.StopBits); +// _serialPort.Handshake = SetPortHandshake(_serialPort.Handshake); +// +// // Set the read/write timeouts +// _serialPort.ReadTimeout = 500; +// _serialPort.WriteTimeout = 500; +// +// _serialPort.Open(); +// _continue = true; +// readThread.Start(); +// +// Console.Write("Name: "); +// name = Console.ReadLine(); +// +// Console.WriteLine("Type QUIT to exit"); +// +// while (_continue) +// { +// message = Console.ReadLine(); +// +// if (stringComparer.Equals("quit", message)) +// { +// _continue = false; +// } +// else +// { +// _serialPort.WriteLine( +// String.Format("<{0}>: {1}", name, message)); +// } +// } +// +// readThread.Join(); +// _serialPort.Close(); +// } +// +// public static void Read() +// { +// while (_continue) +// { +// try +// { +// string message = _serialPort.ReadLine(); +// Console.WriteLine(message); +// } +// catch (TimeoutException) { } +// } +// } +// +// // Display Port values and prompt user to enter a port. +// public static string SetPortName(string defaultPortName) +// { +// string portName; +// +// Console.WriteLine("Available Ports:"); +// foreach (string s in SerialPort.GetPortNames()) +// { +// Console.WriteLine(" {0}", s); +// } +// +// Console.Write("Enter COM port value (Default: {0}): ", defaultPortName); +// portName = Console.ReadLine(); +// +// if (portName == "" || !(portName.ToLower()).StartsWith("com")) +// { +// portName = defaultPortName; +// } +// return portName; +// } +// // Display BaudRate values and prompt user to enter a value. +// public static int SetPortBaudRate(int defaultPortBaudRate) +// { +// string baudRate; +// +// Console.Write("Baud Rate(default:{0}): ", defaultPortBaudRate); +// baudRate = Console.ReadLine(); +// +// if (baudRate == "") +// { +// baudRate = defaultPortBaudRate.ToString(); +// } +// +// return int.Parse(baudRate); +// } +// +// // Display PortParity values and prompt user to enter a value. +// public static Parity SetPortParity(Parity defaultPortParity) +// { +// string parity; +// +// Console.WriteLine("Available Parity options:"); +// foreach (string s in Enum.GetNames(typeof(Parity))) +// { +// Console.WriteLine(" {0}", s); +// } +// +// Console.Write("Enter Parity value (Default: {0}):", defaultPortParity.ToString(), true); +// parity = Console.ReadLine(); +// +// if (parity == "") +// { +// parity = defaultPortParity.ToString(); +// } +// +// return (Parity)Enum.Parse(typeof(Parity), parity, true); +// } +// // Display DataBits values and prompt user to enter a value. +// public static int SetPortDataBits(int defaultPortDataBits) +// { +// string dataBits; +// +// Console.Write("Enter DataBits value (Default: {0}): ", defaultPortDataBits); +// dataBits = Console.ReadLine(); +// +// if (dataBits == "") +// { +// dataBits = defaultPortDataBits.ToString(); +// } +// +// return int.Parse(dataBits.ToUpperInvariant()); +// } +// +// // Display StopBits values and prompt user to enter a value. +// public static StopBits SetPortStopBits(StopBits defaultPortStopBits) +// { +// string stopBits; +// +// Console.WriteLine("Available StopBits options:"); +// foreach (string s in Enum.GetNames(typeof(StopBits))) +// { +// Console.WriteLine(" {0}", s); +// } +// +// Console.Write("Enter StopBits value (None is not supported and \n" + +// "raises an ArgumentOutOfRangeException. \n (Default: {0}):", defaultPortStopBits.ToString()); +// stopBits = Console.ReadLine(); +// +// if (stopBits == "") +// { +// stopBits = defaultPortStopBits.ToString(); +// } +// +// return (StopBits)Enum.Parse(typeof(StopBits), stopBits, true); +// } +// public static Handshake SetPortHandshake(Handshake defaultPortHandshake) +// { +// string handshake; +// +// Console.WriteLine("Available Handshake options:"); +// foreach (string s in Enum.GetNames(typeof(Handshake))) +// { +// Console.WriteLine(" {0}", s); +// } +// +// Console.Write("Enter Handshake value (Default: {0}):", defaultPortHandshake.ToString()); +// handshake = Console.ReadLine(); +// +// if (handshake == "") +// { +// handshake = defaultPortHandshake.ToString(); +// } +// +// return (Handshake)Enum.Parse(typeof(Handshake), handshake, true); +// } +// } +// } +// diff --git a/Scale/commserver.exe b/Scale/commserver.exe new file mode 100644 index 0000000..b0fa81c Binary files /dev/null and b/Scale/commserver.exe differ diff --git a/Scale/iconfont.ttf b/Scale/iconfont.ttf new file mode 100644 index 0000000..236398b Binary files /dev/null and b/Scale/iconfont.ttf differ